kbuild-2695/0000755000000000000000000000000012247157310011433 5ustar rootrootkbuild-2695/Config.kmk0000644000000000000000000003045512247157306013360 0ustar rootroot# $Id: Config.kmk 2668 2012-11-25 19:53:45Z bird $ ## @file # Build Configuration. # # # Copyright (c) 2005-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # # Enable automatic installation of what's built. KBUILD_DO_AUTO_INSTALL := 1 # # The kBuild version. # KBUILD_VERSION_MAJOR = 0 KBUILD_VERSION_MINOR = 1 KBUILD_VERSION_PATCH = 9998 KBUILD_VERSION = 0.1.9998 DEFS += \ KBUILD_VERSION_MAJOR=$(KBUILD_VERSION_MAJOR) \ KBUILD_VERSION_MINOR=$(KBUILD_VERSION_MINOR) \ KBUILD_VERSION_PATCH=$(KBUILD_VERSION_PATCH) # # Get the svn version. # This is shipped with the tarballs in a SvnInfo.kmk in the root. # ifneq ($(wildcard $(PATH_ROOT)/SvnInfo.kmk),) # Shipped KBUILD_SVN_INFO_KMK := $(PATH_ROOT)/SvnInfo.kmk KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK) else ifneq ($(wildcard $(PATH_ROOT)/.svn/entries $(PATH_ROOT)/../.svn/entries),) # Generate from svn info KBUILD_SVN_INFO_KMK := $(PATH_OBJ)/SvnInfo.kmk KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK) $(PATH_OBJ)/SvnInfo.ts +| $(KBUILD_SVN_INFO_KMK): $(wildcard $(PATH_ROOT)/.svn $(PATH_ROOT)/.svn/entries $(PATH_ROOT)/.svn/all-wcprops $(PATH_ROOT)/.svn/format $(PATH_ROOT)/.svn/props $(PATH_ROOT)/.svn/prop-base ) $(call MSG_GENERATE,,$(KBUILD_SVN_INFO_KMK)) @$(RM) -f $@ $@.tmp @$(MKDIR) -p $(@D) @$(REDIRECT) -o $@.tmp -E 'LC_ALL=C' -- svn info $(DEPTH) @$(SED) \ -e 's/URL: */KBUILD_SVN_URL := /' \ -e 's/Revision: */KBUILD_SVN_REV := /' \ -e '/KBUILD_SVN_/!d' \ --append $@ \ $@.tmp @$(RM) -f $@.tmp @$(CP) --changed -fv $@ $(KBUILD_SVN_INFO_KMK) ifeq ($(DEPTH),.) OTHER_CLEAN += $(KBUILD_SVN_INFO_KMK) $(PATH_OBJ)/SvnInfo.ts endif else # Some incomplete source export... KBUILD_SVN_INFO_KMK := $(PATH_OBJ)/SvnInfo.kmk KBUILD_SVN_INFO_DEP := $(KBUILD_SVN_INFO_KMK) $(warning Neither SvnInfo nor .svn/* was found in the root. Will have to cook up something too keep the build happy.) $(KBUILD_SVN_INFO_KMK): $(RM) -f $@ $(MKDIR) -p $(@D) $(APPEND) $@ 'KBUILD_SVN_REV := 0' $(APPEND) $@ 'KBUILD_SVN_URL := /dev/null' ifeq ($(DEPTH),.) OTHER_CLEAN += $(KBUILD_SVN_INFO_KMK) endif endif include $(KBUILD_SVN_INFO_KMK) # # Where to fine the GNU Make stuff (for FreeBSD and Windows). # PATH_GNUMAKE_SRC ?= $(PATH_ROOT)/src/kmk # # Various platform specific hacks. # ifn1of ($(KBUILD_TARGET), haiku openbsd) GCC_Wextra = -Wextra endif if1of ($(KBUILD_TARGET), openbsd) TOOL_FLEX_LEX = gflex endif # # The OS and Architecture indicators. # DEFS.darwin += KBUILD_OS_DARWIN DEFS.freebsd += KBUILD_OS_FREEBSD DEFS.linux += KBUILD_OS_LINUX DEFS.netbsd += KBUILD_OS_NETBSD DEFS.openbsd += KBUILD_OS_OPENBSD DEFS.os2 += KBUILD_OS_OS2 DEFS.solaris += KBUILD_OS_SOLARIS DEFS.win += KBUILD_OS_WINDOWS DEFS.x86 += KBUILD_ARCH_X86 DEFS.amd64 += KBUILD_ARCH_AMD64 # # Check if we're building a *nix installation. # # There are a few optional overrides here for customizing the install location # and how it is installed: # MY_INST_BIN - the bin/ directory (the trailing slash is mandatory). # MY_INST_DATA - the share/kBuild/ directory (the trailing slash is mandatory). # MY_INST_DOC - the share/doc/kBuild-x.y.z/ directory (the trailing slash is mandatory). # MY_INST_UID - the default install UID or user name. # MY_INST_GID - the default install GID or group name. # MY_INST_MODE - the default install mode mask, ",a+x" is added for executables and files. # MY_INST_DATA_UID - data specialization. # MY_INST_DATA_GID - data specialization. # MY_INST_DATA_MODE - data specialization. # MY_INST_DOC_UID - doc specialization. # MY_INST_DOC_GID - doc specialization. # MY_INST_DOC_MODE - doc specialization. # MY_INST_BIN_UID - binary (executable) specialization. # MY_INST_BIN_GID - binary (executable) specialization. # MY_INST_BIN_MODE - binary (executable) specialization. # # When running kmk install, you can use PATH_INS like you use DESTDIR in other makefile # systems. (These things will be improved in 0.2.x btw, so will be possible to enable a # mode where PREFIX and DESTDIR will.) # # ifdef NIX_INSTALL_DIR MY_INST_ROOT := $(patsubst /%,%,$(NIX_INSTALL_DIR))/ ifndef MY_INST_BIN MY_INST_BIN := $(MY_INST_ROOT)bin/ endif ifndef MY_INST_DATA MY_INST_DATA := $(MY_INST_ROOT)share/kBuild/ endif ifndef MY_INST_DOC MY_INST_DOC := $(MY_INST_ROOT)share/doc/kBuild-$(KBUILD_VERSION)/ endif if !defined(MY_INST_BIN_MODE) && defined(MY_INST_MODE) MY_INST_BIN_MODE := $(MY_INST_MODE),a+x endif DEFS += \ KBUILD_PATH=\"/$(patsubst %/,%,$(MY_INST_DATA))\" \ KBUILD_BIN_PATH=\"/$(patsubst %/,%,$(MY_INST_BIN))\" endif # # Templates for installing docs and make scripts. # TEMPLATE_DATA = Data installation template. TEMPLATE_DATA_INST = $(MY_INST_DATA) TEMPLATE_DATA_MODE ?= $(firstword $(MY_INST_DATA_MODE) $(MY_INST_MODE) a+r) TEMPLATE_DATA_UID ?= $(firstword $(MY_INST_DATA_UID) $(MY_INST_UID)) TEMPLATE_DATA_GID ?= $(firstword $(MY_INST_DATA_GID) $(MY_INST_GID)) TEMPLATE_DOC = Documentation installation template. TEMPLATE_DOC_INST = $(MY_INST_DOC) TEMPLATE_DOC_MODE ?= $(firstword $(MY_INST_DOC_MODE) $(MY_INST_MODE) a+r) TEMPLATE_DOC_UID ?= $(firstword $(MY_INST_DOC_UID) $(MY_INST_UID)) TEMPLATE_DOC_GID ?= $(firstword $(MY_INST_DOC_GID) $(MY_INST_GID)) # # Template for building commandline tools. # TEMPLATE_BIN = Command line binary TEMPLATE_BIN_INCS = $(PATH_ROOT)/src/lib TEMPLATE_BIN_DEFS.profile = NDEBUG TEMPLATE_BIN_DEFS.release = NDEBUG if defined(NIX_INSTALL_DIR) && !defined(KBUILD_BOOTSTRAP) TEMPLATE_BIN_INST = $(MY_INST_BIN) TEMPLATE_BIN_MODE ?= $(firstword $(MY_INST_BIN_MODE) a+rx) TEMPLATE_BIN_UID ?= $(firstword $(MY_INST_BIN_UID) $(MY_INST_UID)) TEMPLATE_BIN_GID ?= $(firstword $(MY_INST_BIN_GID) $(MY_INST_GID)) else TEMPLATE_BIN_INST = kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/ endif ifeq ($(KBUILD_TARGET),os2) TEMPLATE_BIN_TOOL = GCC3OMF TEMPLATE_BIN_CFLAGS = -g TEMPLATE_BIN_CFLAGS.profile = -pg TEMPLATE_BIN_CFLAGS.release = -O3 TEMPLATE_BIN_LDFLAGS = -Zhigh-mem -Zstack=1024 -g endif ifeq ($(KBUILD_TARGET),darwin) ifndef KBUILD_MACOSX_VERSION export KBUILD_MACOSX_VERSION := $(expr $(firstword $(subst ., ,$(shell uname -r))) - 4) endif ifndef KBUILD_MACOSX_TARGET_VERSION if $(KBUILD_TARGET_ARCH) == amd64 KBUILD_MACOSX_TARGET_VERSION = 6 else KBUILD_MACOSX_TARGET_VERSION = 4 endif endif if $(KBUILD_MACOSX_TARGET_VERSION) == 4 TOOL_GCC4MACHO_SUFFIX = -4.0 TOOL_GXX4MACHO_SUFFIX = -4.0 else if $(KBUILD_MACOSX_TARGET_VERSION) >= 5 TOOL_GCC4MACHO_SUFFIX = -4.2 TOOL_GXX4MACHO_SUFFIX = -4.2 endif KBUILD_MACOSX_SDK ?= /Developer/SDKs/MacOSX10.$(KBUILD_MACOSX_TARGET_VERSION)$(if-expr $(KBUILD_MACOSX_TARGET_VERSION)==4,u,).sdk TEMPLATE_BIN_TOOL = GCC4MACHO TEMPLATE_BIN_CFLAGS = -g -mmacosx-version-min=10.$(KBUILD_MACOSX_TARGET_VERSION) -isysroot $(KBUILD_MACOSX_SDK) ifeq ($(USER),bird) TEMPLATE_BIN_CFLAGS += -Wall $(GCC_Wextra) -pedantic -Wno-unused-parameter -Wno-long-long TEMPLATE_BIN_DEFS += NO_ENUM_BITFIELDS endif TEMPLATE_BIN_CFLAGS.profile = -O3 -pg TEMPLATE_BIN_CFLAGS.release = -O3 TEMPLATE_BIN_LDFLAGS = -g -mmacosx-version-min=10.$(KBUILD_MACOSX_TARGET_VERSION) -Wl,-syslibroot,$(KBUILD_MACOSX_SDK) if $(KBUILD_MACOSX_TARGET_VERSION) == 4 && $(KBUILD_MACOSX_VERSION) >= 5 TEMPLATE_BIN_LDFLAGS += -classic_ld endif TEMPLATE_BIN_LDFLAGS.profile = -pg endif ifeq ($(filter-out win nt,$(KBUILD_TARGET)),) TEMPLATE_BIN_TOOL = VCC100 TEMPLATE_BIN_TOOL.x86 = VCC100X86 TEMPLATE_BIN_TOOL.amd64 = VCC100AMD64 TEMPLATE_BIN_DEFS = WINDOWS32 _CONSOLE __WIN__ _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS TEMPLATE_BIN_DEFS.x86 = WIN32 __WIN32__ TEMPLATE_BIN_DEFS.amd64 = WIN32 __WIN32__ __WIN64__ WIN64 TEMPLATE_BIN_CFLAGS = -W3 -Zi -Zl TEMPLATE_BIN_CFLAGS.release = -O2 TEMPLATE_BIN_CFLAGS.profile = -O2 -GH -Gh TEMPLATE_BIN_INCS += \ . \ $(PATH_GNUMAKE_SRC)/w32/include \ $(PATH_GNUMAKE_SRC)/glob TEMPLATE_BIN_LDFLAGS = /SUBSYSTEM:console /INCREMENTAL:no /NOD /DEBUG ifeq ($(KBUILD_TYPE),profile) TEMPLATE_BIN_SDKS = WINPSDKINCS TEMPLATE_BIN_CFLAGS += -MT TEMPLATE_BIN_LIBS = \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/lib/kPrf2.lib \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/lib/kPrf2WinApiWrappersImp.lib \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcmt.lib \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcpmt.lib \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/lib/kPrf2WinApiWrappersImp.lib \ $(PATH_SDK_WINPSDKINCS_LIB)/AdvAPI32.lib \ $(PATH_SDK_WINPSDKINCS_LIB)/User32.lib else TEMPLATE_BIN_SDKS = WINPSDK71 ifdef KBUILD_WITH_STATIC_MSVCRT TEMPLATE_BIN_CFLAGS += -MT TEMPLATE_BIN_LIBS = \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcmt.lib \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcpmt.lib else TEMPLATE_BIN_CFLAGS += -MD TEMPLATE_BIN_LIBS = \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \ $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/msvcrt.lib endif endif endif ifndef TEMPLATE_BIN_TOOL # Use GCC3 when we're certain that the system is using GNU ld and ar. ifeq ($(filter-out linux freebsd openbsd netbsd,$(KBUILD_TARGET)),) TEMPLATE_BIN_TOOL = GCC3 else TEMPLATE_BIN_TOOL = GCC3PLAIN endif TEMPLATE_BIN_CFLAGS = -g ifeq ($(USER),bird) TEMPLATE_BIN_CFLAGS += -Wall $(GCC_Wextra) -pedantic -Wno-unused-parameter TEMPLATE_BIN_DEFS += NO_ENUM_BITFIELDS endif TEMPLATE_BIN_LDFLAGS = -g TEMPLATE_BIN_LDFLAGS.profile = -pg -p TEMPLATE_BIN_CFLAGS.release = -O3 TEMPLATE_BIN_CFLAGS.profile = -O3 -pg -p ifeq ($(KBUILD_TARGET),freebsd) TEMPLATE_BIN_INCS += $(PATH_GNUMAKE_SRC)/glob /usr/local/include endif ifeq ($(KBUILD_TARGET),linux) TEMPLATE_BIN_LIBS += rt endif TEMPLATE_BIN_CFLAGS.x86 += -m32 TEMPLATE_BIN_CFLAGS.sparc32 += -m32 TEMPLATE_BIN_CFLAGS.amd64 += -m64 TEMPLATE_BIN_CFLAGS.sparc64 += -m64 TEMPLATE_BIN_CXXFLAGS.x86 += -m32 TEMPLATE_BIN_CXXFLAGS.sparc32+= -m32 TEMPLATE_BIN_CXXFLAGS.amd64 += -m64 TEMPLATE_BIN_CXXFLAGS.sparc64+= -m64 TEMPLATE_BIN_LDFLAGS.x86 += -m32 TEMPLATE_BIN_LDFLAGS.sparc32 += -m32 TEMPLATE_BIN_LDFLAGS.amd64 += -m64 TEMPLATE_BIN_LDFLAGS.sparc64 += -m64 ifeq ($(KBUILD_TARGET),solaris) TEMPLATE_BIN_LIBS += rt dl TEMPLATE_BIN_LDFLAGS += -Wl,-i TEMPLATE_BIN_DEFS.x86 += _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE TEMPLATE_BIN_DEFS.sparc32 += _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE endif endif if1of ($(KBUILD_TARGET), darwin win) TEMPLATE_BIN_LD_DEBUG = split endif # # Template for building threaded binaries. # TEMPLATE_BIN-THREADED = Threaded command line binary TEMPLATE_BIN-THREADED_EXTENDS = BIN TEMPLATE_BIN-THREADED_EXTENDS_BY = appending if1of ($(KBUILD_TARGET), dragonfly freebsd linux openbsd) TEMPLATE_BIN-THREADED_LIBS = pthread endif # # Template for building libraries for the tools. # TEMPLATE_LIB = Library for Commandline binary TEMPLATE_LIB_EXTENDS = BIN TEMPLATE_LIB_INST = lib/ # for LIB_KDEP TEMPLATE_LIB_TOOL = $(TEMPLATE_BIN_TOOL) LIB_KDEP = $(PATH_OBJ)/kDep/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF) LIB_KUTIL = $(PATH_OBJ)/kUtil/$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kUtil$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF) kbuild-2695/bootstrap.gmk0000644000000000000000000002360512247157307014164 0ustar rootroot# $Id: bootstrap.gmk 2421 2010-10-17 21:27:53Z bird $ ## @file # GNU Make Compatible bootstrap Makefile. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # # # ASSUMES: # - KBUILD_TARGET, KBUILD_HOST, KBUILD_HOST_ARCH, and KBUILD_TYPE in the env. # - KBUILD_PATH points to ./kBuild with an absolute path. # - KBUILD_BIN_PATH and PATH_KBUILD_BIN must *NOT* be defined anywhere. # - Current directory == bootstrap.gmk directory. # - mkdir -p works. # - ln -s works # - cp -f works # - cd somedir && command works. # - echo done > some-file works. # - Recent GNU make that implements CURDIR, $(error) and ifdef. # # Tip: kBuild/env.sh --full (g(nu))make -f bootstrap.kmk # # Note to self on bootstrapping solaris.sparc64: # SED_MAKE_DEFS="SED=gsed" AUTOPOINT=true ACLOCAL=aclocal-1.10 AUTOMAKE=automake-1.10 nice ./kBuild/env.sh --full gmake -f bootstrap.gmk # # Note to self on bootstrapping openbsd: # AUTOCONF_VERSION=2.59 AUTOMAKE_VERSION=1.9 ./kBuild/env.sh --full gmake -f bootstrap.gmk # # # OPTIONAL: # Set env.var. NIX_INSTALL_DIR to /usr/local or /usr # (see Config.kmk and wiki for details) # # # Deal with legacy env.vars. - no niceties here. # ifndef KBUILD_HOST KBUILD_HOST := $(BUILD_PLATFORM) endif ifndef KBUILD_HOST_ARCH KBUILD_HOST_ARCH := $(BUILD_PLATFORM_ARCH) endif ifndef KBUILD_HOST_CPU KBUILD_HOST_CPU := $(BUILD_PLATFORM_CPU) endif ifndef KBUILD_TARGET KBUILD_TARGET := $(BUILD_TARGET) endif ifndef KBUILD_TARGET_ARCH KBUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH) endif ifndef KBUILD_TARGET_CPU KBUILD_TARGET_CPU := $(BUILD_TARGET_CPU) endif ifndef KBUILD_TYPE KBUILD_TYPE := $(BUILD_TYPE) endif ifndef KBUILD_PATH KBUILD_PATH := $(PATH_KBUILD) endif # # Check (some of) the assumptions. # ifndef KBUILD_TARGET $(error KBUILD_TARGET not set) endif ifndef KBUILD_HOST $(error KBUILD_HOST not set) endif ifndef KBUILD_HOST_ARCH $(error KBUILD_HOST_ARCH not set) endif ifndef KBUILD_TYPE $(error KBUILD_TYPE not set) endif ifndef KBUILD_TYPE $(error KBUILD_TYPE not set) endif ifndef KBUILD_PATH $(error KBUILD_PATH not set) endif ifdef KBUILD_BIN_PATH $(error KBUILD_BIN_PATH is set) endif ifdef PATH_KBUILD_BIN $(error PATH_KBUILD_BIN is set) endif # # Globals # SRCDIR = $(CURDIR) OUTDIR = $(SRCDIR)/out/$(KBUILD_HOST).$(KBUILD_HOST_ARCH)/$(KBUILD_TYPE)/bootstrap SVN = svn # Override this on the make commandline if you need to (FreeBSD). AUTORECONF = autoreconf all: stage1 stage2 # # Stage 1 - Build bootstrap kmk, kmk_redirect and sed, refresh config.h caches, link # up kmk_ash so $(OUTDIR)/kmk can serve as kBuild bin dir. # stage1: \ $(OUTDIR)/kmk/kmk \ $(OUTDIR)/kmk/kmk_ash \ $(OUTDIR)/kmk/kmk_sed \ $(OUTDIR)/kmk/kmk_echo \ $(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET) \ $(SRCDIR)/src/sed/config.h.$(KBUILD_TARGET) # kmk $(OUTDIR)/kmk/ts-autoreconf: mkdir -p $(@D) cd $(SRCDIR)/src/kmk && $(AUTORECONF) -i -v echo done > $@ $(OUTDIR)/kmk/ts-configured: \ $(OUTDIR)/kmk/ts-autoreconf \ $(OUTDIR)/kmk/fts.h cd $(OUTDIR)/kmk && $(SRCDIR)/src/kmk/configure echo done > $@ ifeq ($(KBUILD_HOST),solaris) $(OUTDIR)/kmk/ts-configured: $(OUTDIR)/kmk/paths.h $(OUTDIR)/kmk/paths.h: echo > $@ endif $(OUTDIR)/kmk/fts.h: ln -s $(SRCDIR)/src/kmk/kmkbuiltin/ftsfake.h $@ $(OUTDIR)/kmk/config.h: $(OUTDIR)/kmk/ts-configured $(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET): $(OUTDIR)/kmk/config.h cp -f $(OUTDIR)/kmk/config.h $(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET) echo "" >> $@ echo '#include "inlined_memchr.h"' >> $@ $(OUTDIR)/kmk/kmk: $(OUTDIR)/kmk/ts-configured $(MAKE) -C $(@D) # sed $(OUTDIR)/sed/ts-autoreconf: mkdir -p $(@D) @cd $(SRCDIR)/src/sed && $(AUTORECONF) -i -v --force echo done > $@ $(OUTDIR)/sed/ts-configured: $(OUTDIR)/sed/ts-autoreconf cd $(OUTDIR)/sed && $(SRCDIR)/src/sed/configure --without-libintl --disable-nls echo done > $@ $(OUTDIR)/sed/config.h: $(OUTDIR)/sed/ts-configured $(SRCDIR)/src/sed/config.h.$(KBUILD_TARGET): $(OUTDIR)/sed/config.h cp -f $< $@ $(OUTDIR)/sed/sed/sed: $(OUTDIR)/sed/ts-configured $(MAKE) $(SED_MAKE_DEFS) -C $(@D)/.. $(OUTDIR)/kmk/kmk_sed: $(OUTDIR)/sed/sed/sed cp -f $< $@ $(OUTDIR)/kmk/kmk_ash: ifeq ($(KBUILD_TARGET),solaris) ln -s /usr/bin/bash $@ else ln -s /bin/sh $@ endif $(OUTDIR)/kmk/kmk_echo: ln -s /bin/echo $@ # # Stage 2 - Build kBuild using the bootstrap tools from the previous step # and install it to kBuild/bin/x.y. # stage2: \ $(OUTDIR)/ts-stage2-build \ $(OUTDIR)/ts-stage2-install $(OUTDIR)/ts-stage2-build: \ $(SRCDIR)/src/kmk/config.h.$(KBUILD_TARGET) \ $(SRCDIR)/src/sed/config.h.$(KBUILD_TARGET) \ $(OUTDIR)/kmk/kmk KBUILD_BIN_PATH=$(OUTDIR)/kmk $(OUTDIR)/kmk/kmk -C $(SRCDIR) KBUILD_BOOTSTRAP=1 echo done > $@ $(OUTDIR)/ts-stage2-install: $(OUTDIR)/ts-stage2-build KBUILD_BIN_PATH=$(OUTDIR)/kmk $(OUTDIR)/kmk/kmk -C $(SRCDIR) KBUILD_BOOTSTRAP=1 PATH_INS=$(SRCDIR) install echo done > $@ # # Clean the output files... Very enjoyable exercise. # clean: rm -Rf $(SRCDIR)/out/ \ $(SRCDIR)/src/kmk/autom4te.cache/ \ $(SRCDIR)/src/sed/autom4te.cache/ rm -f $(SRCDIR)/src/kmk/Makefile.in \ $(SRCDIR)/src/kmk/config.h.in \ $(SRCDIR)/src/kmk/configure \ $(SRCDIR)/src/kmk/aclocal.m4 \ $(SRCDIR)/src/kmk/glob/Makefile.in \ $(SRCDIR)/src/kmk/config/Makefile.in \ $(SRCDIR)/src/kmk/config/depcomp \ $(SRCDIR)/src/kmk/config/compile \ $(SRCDIR)/src/kmk/config/missing \ $(SRCDIR)/src/kmk/config/config.guess \ $(SRCDIR)/src/kmk/config/config.sub \ $(SRCDIR)/src/kmk/config/install-sh \ $(SRCDIR)/src/kmk/w32/Makefile.in \ $(SRCDIR)/src/sed/config_h.in~ \ $(SRCDIR)/src/sed/intl/printf-args.h \ $(SRCDIR)/src/sed/intl/printf.c \ $(SRCDIR)/src/sed/intl/localcharset.h \ $(SRCDIR)/src/sed/intl/libgnuintl.h.in \ $(SRCDIR)/src/sed/intl/vasnwprintf.h \ $(SRCDIR)/src/sed/intl/vasnprintf.c \ $(SRCDIR)/src/sed/intl/vasnprintf.h \ $(SRCDIR)/src/sed/intl/wprintf-parse.h \ $(SRCDIR)/src/sed/intl/relocatable.c \ $(SRCDIR)/src/sed/intl/relocatable.h \ $(SRCDIR)/src/sed/intl/xsize.h \ $(SRCDIR)/src/sed/intl/printf-parse.c \ $(SRCDIR)/src/sed/intl/printf-parse.h \ $(SRCDIR)/src/sed/intl/log.c \ $(SRCDIR)/src/sed/intl/printf-args.c \ $(SRCDIR)/src/sed/po/remove-potcdate.sin \ $(SRCDIR)/src/sed/po/Makevars.template \ $(SRCDIR)/src/sed/config/printf-posix.m4 \ $(SRCDIR)/src/sed/config/uintmax_t.m4 \ $(SRCDIR)/src/sed/config/signed.m4 \ $(SRCDIR)/src/sed/config/longlong.m4 \ $(SRCDIR)/src/sed/config/inttypes.m4 \ $(SRCDIR)/src/sed/config/inttypes_h.m4 \ $(SRCDIR)/src/sed/config/longdouble.m4 \ $(SRCDIR)/src/sed/config/nls.m4 \ $(SRCDIR)/src/sed/config/intmax.m4 \ $(SRCDIR)/src/sed/config/mkinstalldirs \ $(SRCDIR)/src/sed/config/xsize.m4 \ $(SRCDIR)/src/sed/config/ulonglong.m4 \ $(SRCDIR)/src/sed/config/wint_t.m4 \ $(SRCDIR)/src/sed/config/inttypes-pri.m4 \ $(SRCDIR)/src/sed/config/stdint_h.m4 \ $(SRCDIR)/src/sed/config/intdiv0.m4 \ $(SRCDIR)/src/sed/config/isc-posix.m4 \ $(SRCDIR)/src/sed/config/po.m4 \ $(SRCDIR)/src/sed/config/size_max.m4 \ $(SRCDIR)/src/sed/config/wchar_t.m4 \ $(SRCDIR)/src/sed/*~ \ $(SRCDIR)/src/sed/config/*~ \ $(SRCDIR)/src/sed/intl/*~ \ $(SRCDIR)/src/sed/po/*~ \ distclean: clean $(SVN) revert \ src/sed/configure \ src/sed/Makefile.in \ src/sed/doc/Makefile.in \ src/sed/doc/stamp-vti \ src/sed/doc/sed.info \ src/sed/doc/sed.info-1 \ src/sed/doc/sed.info-2 \ src/sed/doc/version.texi \ src/sed/INSTALL \ src/sed/lib/Makefile.in \ src/sed/sed/Makefile.in \ src/sed/config_h.in \ src/sed/testsuite/Makefile.in \ src/sed/config/depcomp \ src/sed/config/config.guess \ src/sed/config/config.sub \ src/sed/config/mdate-sh \ src/sed/config/missing \ src/sed/config/texinfo.tex \ src/sed/config/install-sh \ src/sed/aclocal.m4 \ src/sed/ABOUT-NLS \ src/sed/doc/sed.1 \ src/sed/intl/plural-exp.h \ src/sed/intl/Makefile.in \ src/sed/intl/explodename.c \ src/sed/intl/localcharset.c \ src/sed/intl/VERSION \ src/sed/intl/dcigettext.c \ src/sed/intl/dngettext.c \ src/sed/intl/localealias.c \ src/sed/intl/textdomain.c \ src/sed/intl/bindtextdom.c \ src/sed/intl/ref-del.sin \ src/sed/intl/intl-compat.c \ src/sed/intl/dgettext.c \ src/sed/intl/dcgettext.c \ src/sed/intl/plural.c \ src/sed/intl/loadinfo.h \ src/sed/intl/localename.c \ src/sed/intl/ngettext.c \ src/sed/intl/ChangeLog \ src/sed/intl/locale.alias \ src/sed/intl/os2compat.c \ src/sed/intl/finddomain.c \ src/sed/intl/ref-add.sin \ src/sed/intl/gettextP.h \ src/sed/intl/dcngettext.c \ src/sed/intl/osdep.c \ src/sed/intl/config.charset \ src/sed/intl/l10nflist.c \ src/sed/intl/os2compat.h \ src/sed/intl/loadmsgcat.c \ src/sed/intl/gettext.c \ src/sed/intl/plural.y \ src/sed/intl/gmo.h \ src/sed/intl/plural-exp.c \ src/sed/intl/eval-plural.h \ src/sed/intl/hash-string.h \ src/sed/config.h.darwin \ src/sed/po/Makefile.in.in \ src/sed/po/Rules-quot \ src/sed/config/lib-prefix.m4 \ src/sed/config/lib-link.m4 \ src/sed/config/lib-ld.m4 \ src/sed/config/lcmessage.m4 \ src/sed/config/config.rpath \ src/sed/config/progtest.m4 \ src/sed/config/iconv.m4 \ src/sed/config/gettext.m4 $(SVN) revert \ src/kmk/config.h.solaris \ src/sed/config.h.solaris $(SVN) status --no-ignore # can't hurt... .NOTPARALLEL: kbuild-2695/Makefile.kmk0000644000000000000000000000515212247157310013657 0ustar rootroot# $Id: Makefile.kmk 2674 2013-01-31 13:28:27Z bird $ ## @file # Top-Level Sub-Makefile for kBuild. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = . include $(KBUILD_PATH)/subheader.kmk include $(PATH_SUB_CURRENT)/src/Makefile.kmk ifdef NIX_INSTALL_DIR # # When doing a unix install, install all the kBuild scripts and docs. # TODO: Make this default and make it possible to disable it for in-tree development. # INSTALLS += kBuild-data kBuild-data_TEMPLATE = DATA kBuild-data_SOURCES := \ $(wildcard \ kBuild/*.kmk \ ) \ $(foreach src,\ $(wildcard \ kBuild/tools/*.kmk \ kBuild/sdks/*.kmk \ kBuild/units/*.kmk \ kBuild/msgstyles/*.kmk \ kBuild/templates/*.kmk),\ $(src)=>$(subst kBuild/,,$(src))) INSTALLS += kBuild-doc kBuild-doc_TEMPLATE = DOC kBuild-doc_SOURCES := $(wildcard \ kBuild/doc/*.txt \ kBuild/doc/*.html \ ) endif # # And install any binary only tools and dlls. # TODO: Ship env.sh and envos2.cmd / envwin.cmd where applicable. # INSTALLS += kBuild_bin kBuild_bin_INST = $(TEMPLATE_BIN_INST) kBuild_bin_SOURCES = kBuild_bin_SOURCES.os2 = \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc06.dll=>libc06.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc061.dll=>libc061.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc062.dll=>libc062.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc063.dll=>libc063.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc064.dll=>libc064.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc065.dll=>libc065.dll if1of ($(KBUILD_TARGET), nt win) kBuild_bin_SOURCES.$(KBUILD_TARGET) = \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/msvcr100.dll kBuild_bin_SOURCES.profile = \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2.dll \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2WinApiWrappers.dll endif include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/kBuild/0000755000000000000000000000000012247157310012645 5ustar rootrootkbuild-2695/kBuild/footer-pass1.kmk0000644000000000000000000003521212247157310015677 0ustar rootroot# $Id: footer-pass1.kmk 2551 2011-11-09 13:28:02Z bird $ ## @file # kBuild - Footer - Target lists - Pass 1. # # This pass is for defining variables that might be referenced in # properties of other targets. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # Don't do anything for fetch targets (yet). ## # Link prolog for Pass 1. # # @param $(target) Normalized target name. # @param $(EXT) EXE,DLL,SYS,LIB. # @param $(EXTPRE) HOST or nothing. # @param $(definst) The default _INST value. # @param $(tool_prefix) LD or AR. # @param $(bld_trg_base_var) TARGET or PLATFORM. define def_pass1_link_common local bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE)) local bld_trg := $(firstword $($(target)_BLD_TRG) $(BUILD_$(bld_trg_base_var))) local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(BUILD_$(bld_trg_base_var)_ARCH)) local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(BUILD_$(bld_trg_base_var)_CPU)) local tool := $(call _TARGET_TOOL,$(target),$(tool_prefix)) local name := $(firstword\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch).$(bld_type))\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg).$(bld_type))\ $($(target)_NAME.$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg))\ $($(target)_NAME.$(bld_type))\ $($(target)_NAME)\ $(target)) local outbase := $(call TARGET_BASE,$(name),$(target)) $(target)_0_OUTDIR:= $(patsubst %/,%,$(dir $(outbase))) $(call KB_FN_ASSIGN_DEPRECATED,PATH_$(target),$($(target)_0_OUTDIR), $(target)_0_OUTDIR) ## @todo fix the fun at the last line (AR != LIB => mess). local suff := $(firstword \ $($(target)_$(EXT)SUFF.$(bld_trg).$(bld_trg_arch))\ $($(target)_$(EXT)SUFF.$(bld_trg))\ $($(target)_$(EXT)SUFF)\ $(TOOL_$(tool)_$(tool_prefix)$(EXT)SUFF.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_$(tool_prefix)$(EXT)SUFF.$(bld_trg))\ $(TOOL_$(tool)_$(tool_prefix)$(EXT)SUFF)\ $(if $(eq $(tool_prefix),AR),$(SUFF_LIB),$($(EXTPRE)SUFF_$(EXT))) ) local out := $(outbase)$(suff) # Object directory target variable. $(target)_1_TARGET := $(out) $(call KB_FN_ASSIGN_DEPRECATED,TARGET_$(target),$($(target)_1_TARGET), $(target)_1_TARGET) # Staging and install directory target variables. local insttype := $(firstword \ $($(target)_INSTTYPE.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_INSTTYPE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_INSTTYPE.$(bld_trg).$(bld_type)) \ $($(target)_INSTTYPE.$(bld_trg_arch)) \ $($(target)_INSTTYPE.$(bld_trg_cpu)) \ $($(target)_INSTTYPE.$(bld_trg)) \ $($(target)_INSTTYPE.$(bld_type)) \ $($(target)_INSTTYPE) \ ) ifeq ($(insttype),) ifneq ($(firstword \ $($(target)_NOINST) \ $($(target)_NOINST.$(bld_trg)) \ $($(target)_NOINST.$(bld_trg).$(bld_trg_arch)) \ $($(target)_NOINST.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_NOINST.$(bld_trg_arch)) \ $($(target)_NOINST.$(bld_trg_cpu)) \ $($(target)_NOINST.$(bld_type)) ),) local insttype := none else local insttype := both endif endif ifn1of ($(insttype), none both stage) $(error kBuild: Unknown value '$(insttype)' for '$(target)_INSTTYPE'. Valid values are 'none', 'both' and 'stage'.) endif $(target)_1_INSTTYPE := $(insttype) if1of ($(insttype), stage both) local inst := $(strip $(firstdefined \ $(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_INST.$(bld_trg).$(bld_trg_arch) \ $(target)_INST.$(bld_trg).$(bld_type) \ $(target)_INST.$(bld_trg_arch) \ $(target)_INST.$(bld_trg_cpu) \ $(target)_INST.$(bld_trg) \ $(target)_INST.$(bld_type) \ $(target)_INST \ definst \ ,value)) local stage := $(strip $(firstdefined \ $(target)_STAGE.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_STAGE.$(bld_trg).$(bld_trg_arch) \ $(target)_STAGE.$(bld_trg).$(bld_type) \ $(target)_STAGE.$(bld_trg_arch) \ $(target)_STAGE.$(bld_trg_cpu) \ $(target)_STAGE.$(bld_trg) \ $(target)_STAGE.$(bld_type) \ $(target)_STAGE \ inst \ ,value)) $(target)_1_STAGE := $(stage) if "$(substr $(stage),-1,1)" == "/" # Multicast support requires addprefix/suffix. $(target)_1_STAGE_TARGET := $(addprefix $(PATH_STAGE)/,$(addsuffix $(notdir $(out)),$(stage))) else if "$(stage)" == "" $(target)_1_STAGE_TARGET := $(PATH_STAGE)/$(notdir $(out)) else $(target)_1_STAGE_TARGET := $(addprefix $(PATH_STAGE)/,$(stage)) endif else $(target)_1_STAGE := $(target)_1_STAGE_TARGET := endif INSTARGET_$(target) := $($(target)_1_STAGE_TARGET) if1of ($(insttype), both) $(target)_1_INST := $(inst) if "$(substr $(inst),-1,1)" == "/" # Multicast support requires addprefix/suffix. $(target)_1_INST_TARGET := $(addprefix $(PATH_INS)/,$(addsuffix $(notdir $(out)),$(inst))) else if "$(inst)" == "" $(target)_1_INST_TARGET := $(PATH_INS)/$(notdir $(out)) else $(target)_1_INST_TARGET := $(addprefix $(PATH_INS)/,$(inst)) endif else $(target)_1_INST := $(target)_1_INST_TARGET := endif # Debug info related stuff. local debug_insttype := $(firstword \ $($(target)_DEBUG_INSTTYPE.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_DEBUG_INSTTYPE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_DEBUG_INSTTYPE.$(bld_trg).$(bld_type)) \ $($(target)_DEBUG_INSTTYPE.$(bld_trg_arch)) \ $($(target)_DEBUG_INSTTYPE.$(bld_trg_cpu)) \ $($(target)_DEBUG_INSTTYPE.$(bld_trg)) \ $($(target)_DEBUG_INSTTYPE.$(bld_type)) \ $($(target)_DEBUG_INSTTYPE) \ $(insttype) ) ifn1of ($(debug_insttype), none both stage) $(error kBuild: Unknown value '$(debug_insttype)' for '$(target)_DEBUG_INSTTYPE'. Valid values are 'none', 'both' and 'stage'.) endif $(target)_1_DEBUG_INSTTYPE := $(debug_insttype) if1of ($(debug_insttype), stage both) local debug_stage := $(firstdefined \ $(target)_DEBUG_STAGE.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_DEBUG_STAGE.$(bld_trg).$(bld_trg_arch) \ $(target)_DEBUG_STAGE.$(bld_trg).$(bld_type) \ $(target)_DEBUG_STAGE.$(bld_trg_arch) \ $(target)_DEBUG_STAGE.$(bld_trg_cpu) \ $(target)_DEBUG_STAGE.$(bld_trg) \ $(target)_DEBUG_STAGE.$(bld_type) \ $(target)_DEBUG_STAGE \ $(target)_DEBUG_INST.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_DEBUG_INST.$(bld_trg).$(bld_trg_arch) \ $(target)_DEBUG_INST.$(bld_trg).$(bld_type) \ $(target)_DEBUG_INST.$(bld_trg_arch) \ $(target)_DEBUG_INST.$(bld_trg_cpu) \ $(target)_DEBUG_INST.$(bld_trg) \ $(target)_DEBUG_INST.$(bld_type) \ $(target)_DEBUG_INST) ifneq ($(debug_stage),) $(target)_1_DEBUG_STAGE := $($(debug_stage)) else $(target)_1_DEBUG_STAGE := $(addprefix $(STAGE_DEBUG),$(stage)) endif ifndef $(target)_1_DEBUG_STAGE $(target)_1_DEBUG_STAGE := ./ endif else $(target)_1_DEBUG_STAGE := endif if1of ($(debug_insttype), both) local debug_inst := $(firstdefined \ $(target)_DEBUG_INST.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_DEBUG_INST.$(bld_trg).$(bld_trg_arch) \ $(target)_DEBUG_INST.$(bld_trg).$(bld_type) \ $(target)_DEBUG_INST.$(bld_trg_arch) \ $(target)_DEBUG_INST.$(bld_trg_cpu) \ $(target)_DEBUG_INST.$(bld_trg) \ $(target)_DEBUG_INST.$(bld_type) \ $(target)_DEBUG_INST) ifneq ($(debug_inst),) $(target)_1_DEBUG_INST := $($(debug_inst)) else $(target)_1_DEBUG_INST := $(addprefix $(INST_DEBUG),$(inst)) endif ifndef $(target)_1_DEBUG_INST $(target)_1_DEBUG_INST := ./ endif else $(target)_1_DEBUG_INST := endif #$(warning $(NLTAB)$(target)_1_DEBUG_INST=$($(target)_1_DEBUG_INST)$(NLTAB)$(target)_1_DEBUG_STAGE=$($(target)_1_DEBUG_STAGE)$(NLTAB)insttype=$(insttype)$(NLTAB)debug_insttype=$(debug_insttype)) endef # def_pass1_link_common $(eval-opt-var def_pass1_link_common) # # BLDPROGS (Pass 1) # define def_pass1_bldprog # set NOINST if not forced installation before doing the usual stuff. ifndef $(target)_INST $(target)_INSTTYPE := none endif $(evalval def_pass1_link_common) endef EXT := EXE EXTPRE := HOST definst := $(INST_BIN) tool_prefix := LD bld_trg_base_var := PLATFORM $(foreach target, $(_ALL_BLDPROGS), \ $(evalval def_pass1_bldprog)) # # LIBRARIES (Pass 1) # EXT := LIB EXTPRE := definst := $(INST_LIB) tool_prefix := AR bld_trg_base_var := TARGET $(foreach target, $(_ALL_LIBRARIES), \ $(evalval def_pass1_link_common)) # # DLLS (Pass 1) # EXT := DLL EXTPRE := definst := $(INST_DLL) tool_prefix := LD bld_trg_base_var := TARGET $(foreach target, $(_ALL_DLLS), \ $(evalval def_pass1_link_common)) # # IMPORT LIBRARIES (Pass 1) # # - On OS/2 and windows these are libraries. # - On other platforms they are fake DLLs. # if1of ($(KBUILD_TARGET), nt os2 win win64 win32) EXT := LIB EXTPRE := definst := $(INST_LIB) tool_prefix := AR bld_trg_base_var := TARGET $(foreach target, $(_ALL_IMPORT_LIBS), \ $(evalval def_pass1_link_common)) else EXT := DLL EXTPRE := definst := $(INST_DLL) tool_prefix := LD bld_trg_base_var := TARGET $(foreach target, $(_ALL_IMPORT_LIBS), \ $(evalval def_pass1_link_common)) endif # # PROGRAMS (Pass 1) # EXT := EXE EXTPRE := definst := $(INST_BIN) tool_prefix := LD bld_trg_base_var := TARGET $(foreach target, $(_ALL_PROGRAMS), \ $(evalval def_pass1_link_common)) # # SYSMODS (Pass 1) # EXT := SYS EXTPRE := definst := $(INST_SYS) tool_prefix := LD bld_trg_base_var := TARGET $(foreach target, $(_ALL_SYSMODS), \ $(evalval def_pass1_link_common)) # # MISCBINS (Pass 1) # EXT := BIN EXTPRE := definst := $(INST_BIN) tool_prefix := LD bld_trg_base_var := TARGET $(foreach target, $(_ALL_MISCBINS), \ $(evalval def_pass1_link_common)) # # INSTALLS (Pass 1) # Note! INSTARGET_* for INSTALLS aren't available until later. # define def_pass1_install local bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE)) local bld_trg := $(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET)) local bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(KBUILD_TARGET_ARCH)) local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(KBUILD_TARGET_CPU)) # _1_TARGET $(target)_1_TARGET := $(PATH_TARGET)/$(target).ins $(call KB_FN_ASSIGN_DEPRECATED,TARGET_$(target),$($(target)_1_TARGET), $(target)_1_TARGET) # Determine and set 1_INSTTYPE. local insttype := $(firstword \ $($(target)_INSTTYPE.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_INSTTYPE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_INSTTYPE.$(bld_trg).$(bld_type)) \ $($(target)_INSTTYPE.$(bld_trg_arch)) \ $($(target)_INSTTYPE.$(bld_trg_cpu)) \ $($(target)_INSTTYPE.$(bld_trg)) \ $($(target)_INSTTYPE.$(bld_type)) \ $($(target)_INSTTYPE) \ ) ifeq ($(insttype),) ifneq ($(firstword \ $($(target)_NOINST) \ $($(target)_NOINST.$(bld_trg)) \ $($(target)_NOINST.$(bld_trg).$(bld_trg_arch)) \ $($(target)_NOINST.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_NOINST.$(bld_trg_arch)) \ $($(target)_NOINST.$(bld_trg_cpu)) \ $($(target)_NOINST.$(bld_type)) ),) local insttype := none else local insttype := both endif endif ifn1of ($(insttype), none both stage) $(error kBuild: Unknown value '$(insttype)' for '$(target)_INSTTYPE'. Valid values are 'none', 'both' and 'stage'.) endif $(target)_1_INSTTYPE := $(insttype) # Determine the actual INST and STAGE sub-dirs to use for this target. if1of ($(insttype), stage both) local stage := $(strip $(firstdefined \ $(target)_STAGE.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_STAGE.$(bld_trg).$(bld_trg_arch) \ $(target)_STAGE.$(bld_trg).$(bld_type) \ $(target)_STAGE.$(bld_trg_arch) \ $(target)_STAGE.$(bld_trg_cpu) \ $(target)_STAGE.$(bld_trg) \ $(target)_STAGE.$(bld_type) \ $(target)_STAGE \ $(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_INST.$(bld_trg).$(bld_trg_arch) \ $(target)_INST.$(bld_trg).$(bld_type) \ $(target)_INST.$(bld_trg_arch) \ $(target)_INST.$(bld_trg_cpu) \ $(target)_INST.$(bld_trg) \ $(target)_INST.$(bld_type) \ $(target)_INST \ definst \ ,value)) if $(words $(stage)) > 1 $(warning kBuild: The STAGE/INST property of install '$(target)' specifies multiple location, that is not supported.) local stage := $(word 1, $(stage)) endif $(target)_1_STAGE := $(stage) else $(target)_1_STAGE = $(error _1_STAGE not used) endif if1of ($(insttype), both) local inst := $(strip $(firstdefined \ $(target)_INST.$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_INST.$(bld_trg).$(bld_trg_arch) \ $(target)_INST.$(bld_trg).$(bld_type) \ $(target)_INST.$(bld_trg_arch) \ $(target)_INST.$(bld_trg_cpu) \ $(target)_INST.$(bld_trg) \ $(target)_INST.$(bld_type) \ $(target)_INST \ definst \ ,value)) if $(words $(inst)) > 1 $(warning kBuild: The INST property of install '$(target)' specifies multiple location, that is not supported.) local inst := $(word 1, $(inst)) endif ifneq ($(root $(stage)),) $(error kBuild: The effective INST property of install '$(target)' should not start with a root specification) endif $(target)_1_INST := $(inst) else $(target)_1_INST = $(error _1_INST not used) endif # Block properties that we put off setting until pass 2 for INSTALLS. $(target)_1_STAGE_TARGET = $(error The '_1_STAGE_TARGET' property is not present on install targets. Use '_2_STAGE_TARGETS' instead (set by pass 2!).) $(target)_1_INST_TARGET = $(error The '_1_INST_TARGET' property is not present on install targets. Use '_2_INST_TARGETS' instead (set by pass 2!).) INSTARGET_$(target) = $(error The 'INSTARGET_' is deprecated and besides, it is being accessed to early. Consider '_2_STAGE_TARGETS' or '_2_INST_TARGETS'.) # INSTARGET_ later. # PATH_* local outbase := $(call TARGET_BASE,$(target),$(target)) $(target)_0_OUTDIR := $(patsubst %/,%,$(dir $(outbase))) $(call KB_FN_ASSIGN_DEPRECATED,PATH_$(target),$($(target)_0_OUTDIR), $(target)_0_OUTDIR) endef # def_pass1_install $(eval-opt-var def_pass1_install) $(foreach target, $(_ALL_INSTALLS), \ $(evalval def_pass1_install)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done pass 1) endif kbuild-2695/kBuild/footer-pass2-installs.kmk0000644000000000000000000005224412247157310017533 0ustar rootroot# $Id: footer-pass2-installs.kmk 2537 2011-08-02 19:44:43Z bird $ ## @file # kBuild - Footer - Target lists - Pass 2 - Installs. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # # INSTALLS # ## # Generate the staging rules. # define def_install_src_rule_staging $$(call KB_FN_ASSERT_ABSPATH, stagedst) $$(call KB_FN_ASSERT_ABSPATH, srcsrc) $(stagedst) : $(srcsrc) | $(dir $(stagedst)) %$$(call MSG_INST_FILE,$(srcsrc),$(stagedst)) $(top_pre_file_cmds) $$(QUIET)$(stagecmd) $(top_post_file_cmds) endef $(eval-opt-var def_install_src_rule_staging) define def_install_src_rule_installing $$(call KB_FN_ASSERT_ABSPATH, instdst) $$(call KB_FN_ASSERT_ABSPATH, srcsrc) $(instdst) : $(srcsrc) | $(dir $(instdst)) %$$(call MSG_INST_FILE,$(srcsrc),$(instdst)) $(top_pre_file_cmds) $$(QUIET)$(instcmd) $(top_post_file_cmds) endef $(eval-opt-var def_install_src_rule_installing) ## # Install one file. # define def_install_src # deal with '=>' in the source file name. ifeq ($(src),=>) $(error kBuild: Install target '$(target)' has a bad source specifier containing '=>' without any file names) endif ifeq ($(substr $(src),1,2),=>) $(warning kBuild: Install target '$(target)' has a bad source specifier: $(src)) endif ifeq ($(substr $(src),-2),=>) $(warning kBuild: Install target '$(target)' has a bad source specifier: $(src)) endif local srcdst := $(subst =>, ,$(src)) local srcsrc := $(firstword $(srcdst)) local srcdstdir := $(dir $(word 2,$(srcdst))) ifeq ($(srcdstdir),./) local srcdstdir:= endif local srcdst := $(word $(words $(srcdst)),$(srcdst)) # instfun, mode, uid and gid. ifdef $(srcsrc)_INSTFUN local instfun := $(srcsrc)_INSTFUN else local instfun := $(top_instfun) endif local mode := $(firstword \ $($(target)_$(srcsrc)$(source_type_prefix)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcsrc)$(source_type_prefix)_MODE.$(bld_trg)) \ $($(target)_$(srcsrc)$(source_type_prefix)_MODE) \ $($(target)_$(srcdst)$(source_type_prefix)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcdst)$(source_type_prefix)_MODE.$(bld_trg)) \ $($(target)_$(srcdst)$(source_type_prefix)_MODE) \ $($(srcsrc)$(source_type_prefix)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(srcsrc)$(source_type_prefix)_MODE.$(bld_trg)) \ $($(srcsrc)$(source_type_prefix)_MODE) \ $($(srcdst)$(source_type_prefix)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(srcdst)$(source_type_prefix)_MODE.$(bld_trg)) \ $($(srcdst)$(source_type_prefix)_MODE) \ $(source_type_mode)) local uid := $(firstword \ $($(target)_$(srcsrc)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcsrc)_UID.$(bld_trg)) \ $($(target)_$(srcsrc)_UID) \ $($(target)_$(srcdst)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcdst)_UID.$(bld_trg)) \ $($(target)_$(srcdst)_UID) \ $($(srcsrc)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(srcsrc)_UID.$(bld_trg)) \ $($(srcsrc)_UID) \ $($(srcdst)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(srcdst)_UID.$(bld_trg)) \ $($(srcdst)_UID) \ $(top_uid)) local gid := $(firstword \ $($(target)_$(srcsrc)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcsrc)_GID.$(bld_trg)) \ $($(target)_$(srcsrc)_GID) \ $($(target)_$(srcdst)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcdst)_GID.$(bld_trg)) \ $($(target)_$(srcdst)_GID) \ $($(srcsrc)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(srcsrc)_GID.$(bld_trg)) \ $($(srcsrc)_GID) \ $($(srcdst)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(srcdst)_GID.$(bld_trg)) \ $($(srcdst)_GID) \ $(top_gid)) local flags := \ $(top_ifflags) \ $($(srcdst)$(source_type_prefix)_IFFLAGS) \ $($(srcdst)$(source_type_prefix)_IFFLAGS.$(bld_trg)) \ $($(srcdst)$(source_type_prefix)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) \ $($(srcsrc)$(source_type_prefix)_IFFLAGS) \ $($(srcsrc)$(source_type_prefix)_IFFLAGS.$(bld_trg)) \ $($(srcsrc)$(source_type_prefix)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcdst)$(source_type_prefix)_IFFLAGS) \ $($(target)_$(srcdst)$(source_type_prefix)_IFFLAGS.$(bld_trg)) \ $($(target)_$(srcdst)$(source_type_prefix)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcsrc)$(source_type_prefix)_IFFLAGS) \ $($(target)_$(srcsrc)$(source_type_prefix)_IFFLAGS.$(bld_trg)) \ $($(target)_$(srcsrc)$(source_type_prefix)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) clean_files += \ $($(srcdst)_CLEAN) \ $($(srcdst)_CLEAN.$(bld_trg)) \ $($(srcdst)_CLEAN.$(bld_trg).$(bld_trg_arch)) \ $($(srcsrc)_CLEAN) \ $($(srcsrc)_CLEAN.$(bld_trg)) \ $($(srcsrc)_CLEAN.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcdst)_CLEAN) \ $($(target)_$(srcdst)_CLEAN.$(bld_trg)) \ $($(target)_$(srcdst)_CLEAN.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(srcsrc)_CLEAN) \ $($(target)_$(srcsrc)_CLEAN.$(bld_trg)) \ $($(target)_$(srcsrc)_CLEAN.$(bld_trg).$(bld_trg_arch)) # Adjust the source if we got a default PATH. (This must be done this late!) ifdef $(target)_DEFPATH local defpath := $($(target)_DEFPATH) else ifdef $(target)_PATH local defpath := $($(target)_PATH) else local defpath := endif ifneq ($(defpath),) local srcsrc := $(abspathex $(srcsrc),$(defpath)) endif # Generate the staging rule (requires double evaluation). local stage := $(strip $(firstdefined $(srcsrc)_STAGE $(srcsrc)_INST $(target)_1_STAGE,value)) if "$(substr $(stage),-1)" != "/" && "$(stage)" != "" $(warning kBuild: File $(srcsrc) in install target $(target) has a STAGE/INST property without a trailing slash: '$(stage)') local stage := $(stage)/ endif local stage := $(stage)$(dir $(srcdstdir)) ifeq ($(root $(stage)),) local stagedst := $(call $(instfun),$(srcdst),$(target),$(stage),$(PATH_STAGE)) else local stage := $(abspath $(stage))/ ifeq ($(pos $(PATH_OBJ),$(stage)),1) local stage := $(substr $(stage), $(expr $(length-var PATH_OBJ) + 2)) local stagedst := $(call $(instfun),$(srcdst),$(target),$(stage),$(PATH_OBJ)) else $(error kBuild: File $(srcsrc) in install target $(target) has a STAGE/INST property with an absolute path outside PATH_OBJ: '$(stage)') endif endif ifdef $(srcsrc)_INSTALLER local stagecmd := $(call $(srcsrc)_INSTALLER,$(srcsrc),$(stagedst),$(target),$(flags),stage) else ifdef $(target)_INSTALLER local stagecmd := $(call $(target)_INSTALLER,$(srcsrc),$(stagedst),$(target),$(flags),stage) else local stagecmd := $$(INSTALL_STAGING)\ $(if $(uid),-o $(uid))\ $(if $(gid),-g $(gid))\ $(if $(mode),-m $(mode))\ $(flags) -- \ $(srcsrc) $(stagedst) endif $(eval $(def_install_src_rule_staging)) $(target)_2_STAGE_TARGETS += $(stagedst) # Generate the install rule ifeq ($(insttype),both) local inst := $(strip $(firstdefined $(srcsrc)_INST $(target)_1_INST,value)) if "$(substr $(inst),-1)" != "/" && "$(inst)" != "" $(warning kBuild: File $(srcsrc) in install target $(target) has a INST property without a trailing slash: '$(inst)') local inst := $(inst)/ endif local inst := $(inst)$(dir $(srcdstdir)) ifneq ($(root $(inst)),) $(error kBuild: File $(srcsrc) in install target $(target) has a INST property with an absolute path: '$(inst)') endif local instdst := $(call $(instfun),$(srcdst),$(target),$(inst),$(PATH_INS)) ifdef $(srcsrc)_INSTALLER local instcmd := $(call $(srcsrc)_INSTALLER,$(srcsrc),$(instdst),$(target),$(flags),install) else ifdef $(target)_INSTALLER local instcmd := $(call $(target)_INSTALLER,$(srcsrc),$(instdst),$(target),$(flags),install) else local instcmd := $$(INSTALL)\ $(if $(uid),-o $(uid))\ $(if $(gid),-g $(gid))\ $(if $(mode),-m $(mode))\ $(flags) -- \ $(srcsrc) $(instdst) endif $(eval $(def_install_src_rule_installing)) $(target)_2_INST_TARGETS += $(instdst) endif #$(warning instfun=$(instfun) srcdst=$(srcdst) target=$(target) inst=$(inst) => instdst=$(instdst); stage=$(stage) => stagedst=$(stagedst)) endef # def_install_src $(eval-opt-var def_install_src) ## # Generate the symlink rules. # define def_install_symlink_rule_staging $$(call KB_FN_ASSERT_ABSPATH, stagedst) $(stagedst) : | $(dir $(stagedst)) %$$(call MSG_INST_SYM,$(stagedst),$(symdst)) $$(QUIET)$$(RM) -f -- $$@ $(top_pre_sym_cmds) $$(QUIET)$$(LN_SYMLINK) $(symdst) $(stagedst) $(top_post_sym_cmds) endef $(eval-opt-var def_install_symlink_rule_staging) define def_install_symlink_rule_installing $$(call KB_FN_ASSERT_ABSPATH, instdst) $(instdst) : | $(dir $(instdst)) %$$(call MSG_INST_SYM,$(instdst),$(symdst)) $$(QUIET)$$(RM) -f -- $$@ $(top_pre_sym_cmds) $$(QUIET)$$(LN_SYMLINK) $(symdst) $(instdst) $(top_post_sym_cmds) endef $(eval-opt-var def_install_symlink_rule_installing) ## # Create one symlink. # define def_install_symlink # deal with '=>' in the source file name. local symdst := $(subst =>, ,$(src)) local symlnk := $(firstword $(symdst)) local symdst := $(word $(words $(symdst)),$(symdst)) local symlnkdir := $(dir $(symlnk)) ifeq ($(symlnkdir),./) local symlnkdir := endif # Figure which install function to use below. ifdef $(symlnk)_INSTFUN local instfun := $(symlnk)_INSTFUN else local instfun := $(top_instfun) endif # Calc stage destination and generate the rule (requires double evaluation). local stage := $(strip $(firstdefined $(symlnk)_STAGE $(symlnk)_INST $(target)_1_STAGE,value)) if "$(substr $(stage),-1)" != "/" && "$(stage)" != "" $(warning kBuild: Symlink $(symlnk) in install target $(target) has a STAGE/INST property without a trailing slash: '$(stage)') local stage := $(stage)/ endif local stage := $(stage)$(symlnkdir) ifeq ($(root $(stage)),) local stagedst := $(call $(instfun),$(symlnk),$(target),$(stage),$(PATH_STAGE)) else local stage := $(abspath $(stage))/ ifeq ($(pos $(PATH_OBJ),$(stage)),1) local stage := $(substr $(stage), $(expr $(length-var PATH_OBJ) + 2)) local stagedst := $(call $(instfun),$(symlnk),$(target),$(stage),$(PATH_OBJ)) else $(error kBuild: Symlink $(symlnk) in install target $(target) has a STAGE/INST property with an absolute path outside PATH_OBJ: '$(stage)') endif endif $(eval $(def_install_symlink_rule_staging)) $(target)_2_STAGE_TARGETS += $(stagedst) # Calcuate the install destiation and generate the rule (if necessary). ifeq ($(instmode),both) local inst := $(strip $(firstdefined $(symlnk)_INST $(target)_1_INST,value)) if "$(substr $(inst),-1)" != "/" && "$(inst)" != "" $(warning kBuild: Symlink $(symlnk) in install target $(target) has a INST property without a trailing slash: '$(inst)') local inst := $(inst)/ endif ifneq ($(root $(inst)),) $(error kBuild: Symlink $(symlnk) in install target $(target) has a INST property with an absolute path: '$(inst)') endif local inst := $(inst)$(symlnkdir) local instdst := $(call $(instfun),$(symlnk),$(target),$(inst),$(PATH_INS)) $(eval $(def_install_symlink_rule_installing)) $(target)_2_INST_TARGETS += $(instdst) endif #$(warning symlnk=$(symlnk) symdst=$(symdst) instdst=$(instdst) stagedst=$(stagedst) instfun=$(instfun) inst=$(inst) stage='$(stage)') endef # def_install_symlink $(optmize def_install_symlink) ## # Generate an directory installtion rule. # Note. Used both for staging and real install rules. # define def_install_directory_rule $$(call KB_FN_ASSERT_ABSPATH, insdst) $(insdst): %$$(call MSG_INST_DIR,$(insdst)) $(top_pre_dir_cmds) $$(QUIET)$$(INSTALL) -d \ $(if $(uid),-o $(uid))\ $(if $(gid),-g $(gid))\ $(if $(mode),-m $(mode))\ $(flags) -- \ $(insdst) $(top_post_dir_cmds) .NOTPARALLEL: $(insdst) endef # def_install_directory_rule $(eval-opt-var def_install_directory_rule) ## # Create one directory. # define def_install_directory # gather common properties. local mode := $(firstword \ $($(target)_$(directory)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(directory)_MODE.$(bld_trg)) \ $($(target)_$(directory)_MODE) \ $($(directory)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(directory)_MODE.$(bld_trg)) \ $($(directory)_MODE) \ $(top_mode) ) local uid := $(firstword \ $($(target)_$(directory)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(directory)_UID.$(bld_trg)) \ $($(target)_$(directory)_UID) \ $($(directory)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(directory)_UID.$(bld_trg)) \ $($(directory)_UID) \ $(top_uid) ) local gid := $(firstword \ $($(target)_$(directory)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(directory)_GID.$(bld_trg)) \ $($(target)_$(directory)_GID) \ $($(directory)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(directory)_GID.$(bld_trg)) \ $($(directory)_GID) \ $(top_gid) ) local flags := \ $(top_idflags) \ $($(directory)_IDFLAGS) \ $($(directory)_IDFLAGS.$(bld_trg)) \ $($(directory)_IDFLAGS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(directory)_IDFLAGS) \ $($(target)_$(directory)_IDFLAGS.$(bld_trg)) \ $($(target)_$(directory)_IDFLAGS.$(bld_trg).$(bld_trg_arch)) \ # The staging rule (requires double evaluation). local stage := $(strip $(firstdefined $(directory)_STAGE $(directory)_INST $(target)_1_STAGE,value)) if "$(substr $(stage),-1)" != "/" && "$(stage)" != "" $(warning kBuild: Directory $(directory) in install target $(target) has a STAGE/INST property without a trailing slash: '$(stage)') local stage := $(stage)/ endif ifeq ($(root $(stage)),) local insdst := $(PATH_STAGE)/$(stage)$(directory)/ else local stage := $(abspath $(stage))/ ifeq ($(pos $(PATH_OBJ),$(stage)),1) local insdst := $(stage)$(directory)/ else $(error kBuild: Directory $(directory) in install target $(target) has a STAGE/INST property with an absolute path outside PATH_OBJ: '$(stage)') endif endif $(target)_2_STAGE_DIR_TARGETS += $(insdst) $(eval $(def_install_directory_rule)) # The install rule. ifeq ($(insttype),both) local inst := $(strip $(firstdefined $(directory)_INST $(target)_1_INST,value)) ifneq ($(substr $(inst),-1),/) $(warning kBuild: Directory $(directory) in install target $(target) has a INST property without a trailing slash: '$(inst)') local inst := $(inst)/ endif ifneq ($(root $(stage)),) $(error kBuild: Directory $(directory) in install target $(target) has a INST property with an absolute path: '$(inst)') endif local insdst := $(PATH_INS)/$(inst)$(directory)/ $(target)_2_INST_DIR_TARGETS += $(insdst) $(eval $(def_install_directory_rule)) endif #$(warning directory=$(directory) inst=$(inst) stage=$(stage) mode=$(mode) gid=$(gid) uid=$(uid)) endef # def_install_directory $(eval-opt-var def_install_directory) ## # Process one install target. # define def_install # the basics. local bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE)) local bld_trg := $(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET)) local bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(KBUILD_TARGET_ARCH)) local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(KBUILD_TARGET_CPU)) local insttype := $($(target)_1_INSTTYPE) ifneq ($(insttype),none) $(target)_2_STAGE_TARGETS := $($(target)_GOALS) $($(target)_STAGE_ONLY_GOALS) else $(target)_2_STAGE_TARGETS := endif $(target)_2_STAGE_DIR_TARGETS := ifeq ($(insttype),both) $(target)_2_INST_TARGETS := $($(target)_GOALS) $($(target)_INST_ONLY_GOALS) else $(target)_2_INST_TARGETS := endif $(target)_2_INST_DIR_TARGETS := local outbase := $(call TARGET_BASE,$(target),$(target)) $(target)_0_OUTDIR := $(patsubst %/,%,$(dir $(outbase))) $(call KB_FN_ASSIGN_DEPRECATED,PATH_$(target),$($(target)_0_OUTDIR), $(target)_0_OUTDIR) ifneq ($(insttype),none) # Cache top level target properties. local top_mode := $(firstword \ $($(target)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_MODE.$(bld_trg)) \ $($(target)_MODE) ) local top_exec_mode := $(firstword \ $($(target)_EXEC_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_EXEC_MODE.$(bld_trg)) \ $($(target)_EXEC_MODE) ) local top_uid := $(firstword \ $($(target)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_UID.$(bld_trg)) \ $($(target)_UID) ) local top_gid := $(firstword \ $($(target)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_GID.$(bld_trg)) \ $($(target)_GID) ) local top_ifflags := \ $($(target)_IFFLAGS) \ $($(target)_IFFLAGS.$(bld_trg)) \ $($(target)_IFFLAGS.$(bld_trg).$(bld_trg_arch)) local top_idflags := \ $($(target)_IDFLAGS) \ $($(target)_IDFLAGS.$(bld_trg)) \ $($(target)_IDFLAGS.$(bld_trg).$(bld_trg_arch)) ifdef $(target)_INSTFUN local top_instfun := $(target)_INSTFUN else local top_instfun := _INSTALL_FILE endif # The user have to use double expansion and can only use the above locals. Not 100% optimal... local top_pre_file_cmds := $(evalcall def_fn_prop_get_first_defined,PRE_XFILE_CMDS) local top_post_file_cmds := $(evalcall def_fn_prop_get_first_defined,POST_XFILE_CMDS) local top_pre_sym_cmds := $(evalcall def_fn_prop_get_first_defined,PRE_SYMLINK_CMDS) local top_post_sym_cmds := $(evalcall def_fn_prop_get_first_defined,POST_SYMLINK_CMDS) local top_pre_dir_cmds := $(evalcall def_fn_prop_get_first_defined,PRE_DIRECTORY_CMDS) local top_post_dir_cmds := $(evalcall def_fn_prop_get_first_defined,POST_DIRECTORY_CMDS) $(foreach directory, \ $($(target)_DIRS) \ $($(target)_DIRS.$(bld_trg)) \ $($(target)_DIRS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_DIRS.$(bld_trg_arch)) \ $($(target)_DIRS.$(bld_trg_cpu)) \ $($(target)_DIRS.$(bld_type)), \ $(evalval def_install_directory)) local clean_files := \ $($(target)_CLEAN) \ $($(target)_CLEAN.$(bld_trg)) \ $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) \ $($(target)_CLEAN.$(bld_trg_arch)) \ $($(target)_CLEAN.$(bld_trg_cpu)) \ $($(target)_CLEAN.$(bld_type)) local source_type_prefix := local source_type_mode := $(firstword $(top_mode) a+r,u+w) $(foreach src,\ $($(target)_SOURCES) \ $($(target)_SOURCES.$(bld_trg)) \ $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg_cpu)) \ $($(target)_SOURCES.$(bld_type)), \ $(evalval def_install_src)) local source_type_prefix := EXEC_ local source_type_mode := $(firstword $(top_exec_mode) a+xr,u+w) $(foreach src,\ $($(target)_EXEC_SOURCES) \ $($(target)_EXEC_SOURCES.$(bld_trg)) \ $($(target)_EXEC_SOURCES.$(bld_trg).$(bld_trg_arch)) \ $($(target)_EXEC_SOURCES.$(bld_trg_arch)) \ $($(target)_EXEC_SOURCES.$(bld_trg_cpu)) \ $($(target)_EXEC_SOURCES.$(bld_type)), \ $(evalval def_install_src)) $(foreach src,\ $($(target)_SYMLINKS) \ $($(target)_SYMLINKS.$(bld_trg)) \ $($(target)_SYMLINKS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SYMLINKS.$(bld_trg_arch)) \ $($(target)_SYMLINKS.$(bld_trg_cpu)) \ $($(target)_SYMLINKS.$(bld_type)), \ $(evalval def_install_symlink)) else # none local clean_files := endif # The collection targets (staging only). local clean_files += $($(target)_1_TARGET) $($(target)_1_TARGET): $$($(target)_2_STAGE_TARGETS) | $$($(target)_2_STAGE_DIR_TARGETS) $$(dir $$@) @$(QUIET2)$(APPEND) $@ $(target): $$($(target)_1_TARGET) # Update Global lists. _INSTALLS += $($(target)_1_TARGET) _STAGE_FILES += $($(target)_2_STAGE_TARGETS) _STAGE_DIRS += $($(target)_2_STAGE_DIR_TARGETS) _INSTALLS_FILES += $($(target)_2_INST_TARGETS) _INSTALLS_DIRS += $($(target)_2_INST_DIR_TARGETS) _CLEAN_FILES += $(clean_files) _DIRS += \ $($(target)_0_OUTDIR) \ $($(target)_BLDDIRS) \ $($(target)_BLDDIRS.$(bld_trg)) \ $($(target)_BLDDIRS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_BLDDIRS.$(bld_trg_arch)) \ $($(target)_BLDDIRS.$(bld_trg_cpu)) \ $($(target)_BLDDIRS.$(bld_type)) # Deprecated properties. INSTARGET_$(target) := $($(target)_2_STAGE_TARGETS) INSTARGET_DIRS_$(target) := $($(target)_2_STAGE_DIR_TARGETS) endef # def_install $(eval-opt-var def_install) ## Do pass 1 on the implicit targets and add them to the list. $(foreach target, $(_ALL_INSTALLS_IMPLICIT), \ $(evalval def_pass1_install)) _ALL_INSTALLS += $(_ALL_INSTALLS_IMPLICIT) ## Do pass 2 on all install targets. $(foreach target, $(_ALL_INSTALLS), \ $(evalvalctx def_install)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done install targets) endif # # Some introspection targets that can be useful for package maintainers. # .PHONY: kbuild-show-install-files kbuild-show-install-dirs kbuild-show-install-files:: $(addprefix $(NL)$(TAB)$(QUIET)$(ECHO) , $(subst $(PATH_INS)/,,$(_INSTALLS_FILES))) kbuild-show-install-dirs:: $(addprefix $(NL)$(TAB)$(QUIET)$(ECHO) , $(subst $(PATH_INS)/,,$(_INSTALLS_DIRS))) kbuild-show-stage-files:: $(addprefix $(NL)$(TAB)$(QUIET)$(ECHO) , $(subst $(PATH_STAGE)/,,$(_STAGE_FILES))) kbuild-show-stage-dirs:: $(addprefix $(NL)$(TAB)$(QUIET)$(ECHO) , $(subst $(PATH_STAGE)/,,$(_STAGE_DIRS))) kbuild-2695/kBuild/footer-misc.kmk0000644000000000000000000000654012247157307015613 0ustar rootroot# $Id: footer-misc.kmk 2523 2011-07-31 23:45:20Z bird $ ## @file # kBuild - Footer - Target lists - Pass 2 - Misc. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # # OTHERS # _OTHERS = $(OTHERS) $(OTHERS.$(KBUILD_TARGET)) $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) # # TESTING # _TESTING += $(TESTING) \ $(TESTING.$(KBUILD_TARGET)) \ $(TESTING.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(TESTING.$(KBUILD_TARGET_ARCH)) \ $(TESTING.$(KBUILD_TARGET_CPU)) # # PACKING # _PACKING += $(PACKING) \ $(PACKING.$(KBUILD_TARGET)) \ $(PACKING.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(PACKING.$(KBUILD_TARGET_ARCH)) \ $(PACKING.$(KBUILD_TARGET_CPU)) # # DOCS # # # DIRECTORIES # _DIR_ALL := $(sort \ $(addsuffix /,$(patsubst %/,%,$(_DIRS) )) \ $(dir $(_OUT_FILES) $(_OBJS) $(_INSTALLS_FILES) $(_DEBUG_INSTALL_FILES) $(_STAGE_FILES) $(_DEBUG_STAGE_FILES) ) \ $(foreach path, $(KBUILD_INST_PATHS), $(PATH_INS)/$(INST_$(path)) $(PATH_STAGE)/$(STAGE_$(path)) ) \ $(dir $(patsubst %/,%, $(_INSTALLS_DIRS) $(_STAGE_DIRS) $(_DEBUG_INSTALL_DIRS) $(_DEBUG_STAGE_DIRS)) ) \ ) $(foreach directory, \ $(_INSTALLS_DIRS) \ $(_STAGE_DIRS) \ $(_DEBUG_INSTALL_DIRS) \ $(_DEBUG_STAGE_DIRS) \ , $(eval _DIR_ALL := $(filter-out $(directory),$(_DIR_ALL))) ) define def_mkdir_rule $(directory): %$$(call MSG_MKDIR,$$@) $$(QUIET)$$(MKDIR) -p -- $$@ endef $(foreach directory,$(_DIR_ALL),$(eval $(def_mkdir_rule))) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done directories) endif # # NOTHING # do-nothing: %$(call MSG_NOTHING) ifdef KBUILD_PROFILE_SELF @$(ECHO) 'prof: $(call _KBUILD_FMT_ELAPSED_EX, $(nanots ), $(_KBUILD_TS_HEADER_START)) - $(call _KBUILD_FMT_ELAPSED_EX, $(nanots ), $(_KBUILD_TS_PREV)) - executing $@' ifeq ($(KBUILD_PROFILE_SELF),2) @$(ECHO) 'stat: $(make-stats )' endif endif # # CLEAN UP # do-clean: %$(call MSG_CLEAN) $(QUIET)$(RM) -f -- \ $(_OUT_FILES) \ $(_OBJS) \ $(_DEPFILES) \ $(_DEPFILES_INCLUDED) \ $(_CLEAN_FILES) \ $(OTHER_CLEAN) \ $(_STAGE_FILES) $(QUIET)$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- \ $(rsort $(dir $(_OUT_FILES) \ $(_OBJS) \ $(_DEPFILES) \ $(_DEPFILES_INCLUDED) \ $(_CLEAN_FILES) \ $(OTHER_CLEAN))\ $(_STAGE_DIRS) ) kbuild-2695/kBuild/subheader.kmk0000644000000000000000000001162612247157310015321 0ustar rootroot# $Id: subheader.kmk 2434 2011-01-09 17:45:08Z bird $ ## @file # kBuild - File included at top of a makefile or sub-makefile. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # # Sanity check. # ifdef __footer_kmk__ $(error kBuild: footer.kmk has already been included. Fix your sub-makefiles! $(MAKEFILE_CURRENT)) endif ifndef _SUB_MAKEFILE_NOT_FIRST # # The first time we just take the makefile context set by header.kmk. # _SUB_MAKEFILE_NOT_FIRST := 1 DEPTH ?= $(SUB_DEPTH) include $(PATH_KBUILD)/header.kmk else # # Set the default path and makefile for all new targets. # define def_subfooter ifndef $(target)_PATH ifndef $(target)_DEFPATH $(target)_DEFPATH := $(PATH_SUB_CURRENT) endif $(call KB_FN_ASSIGN_DEPRECATED,$(target)_PATH,$($(target)_DEFPATH), $(target)_DEFPATH) else ifndef $(target)_DEFPATH $(target)_DEFPATH := $($(target)_PATH) endif ifndef $(target)_MAKEFILE $(target)_MAKEFILE := $(MAKEFILE_CURRENT) endif ifndef $(target)_0_OUTDIR $(target)_0_OUTDIR := $(call TARGET_PATH,$(target)) $(call KB_FN_ASSIGN_DEPRECATED,PATH_$(target),$($(target)_0_OUTDIR), $(target)_0_OUTDIR) endif endef $(foreach target,\ $(ALL_TARGETS) \ $(FETCHES) $(FETCHES.$(KBUILD_TARGET)) $(FETCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_CPU)) $(FETCHES.$(KBUILD_TYPE)) \ $(PATCHES) $(PATCHES.$(KBUILD_TARGET)) $(PATCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_CPU)) $(PATCHES.$(KBUILD_TYPE)) \ $(BLDPROGS) $(BLDPROGS.$(KBUILD_HOST)) $(BLDPROGS.$(KBUILD_HOST).$(BUILD_PLATFORM_ARCH)) $(BLDPROGS.$(KBUILD_HOST_ARCH)) $(BLDPROGS.$(KBUILD_HOST_CPU)) $(BLDPROGS.$(KBUILD_TYPE)) \ $(LIBRARIES) $(LIBRARIES.$(KBUILD_TARGET)) $(LIBRARIES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_CPU)) $(LIBRARIES.$(KBUILD_TYPE)) \ $(IMPORT_LIBS) $(IMPORT_LIBS.$(KBUILD_TARGET)) $(IMPORT_LIBS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_CPU)) $(IMPORT_LIBS.$(KBUILD_TYPE)) \ $(DLLS) $(DLLS.$(KBUILD_TARGET)) $(DLLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_CPU)) $(DLLS.$(KBUILD_TYPE)) \ $(PROGRAMS) $(PROGRAMS.$(KBUILD_TARGET)) $(PROGRAMS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_CPU)) $(PROGRAMS.$(KBUILD_TYPE)) \ $(SYSMODS) $(SYSMODS.$(KBUILD_TARGET)) $(SYSMODS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_CPU)) $(SYSMODS.$(KBUILD_TYPE)) \ $(MISCBINS) $(MISCBINS.$(KBUILD_TARGET)) $(MISCBINS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_CPU)) $(MISCBINS.$(KBUILD_TYPE)) \ $(INSTALLS) $(INSTALLS.$(KBUILD_TARGET)) $(INSTALLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_CPU)) $(INSTALLS.$(KBUILD_TYPE)) \ $(OTHERS) $(OTHERS.$(KBUILD_TARGET)) $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_CPU)) $(OTHERS.$(KBUILD_TYPE)) \ ,$(evalval def_subfooter)) # # Switch context. # # push the current old makefile onto the stack. $(stack-push _SUB_MAKEFILE_STACK,$(MAKEFILE_CURRENT)) # the current makefile is the 2nd from the end of the MAKEFILE_LIST (we're the last one). __tmp := $(MAKEFILE_LIST) $(stack-popv __tmp) MAKEFILE_CURRENT := $(stack-top __tmp) PATH_SUB_CURRENT := $(abspath $(dir $(MAKEFILE_CURRENT))) endif kbuild-2695/kBuild/subfooter.kmk0000644000000000000000000001120012247157310015353 0ustar rootroot# $Id: subfooter.kmk 2443 2011-07-06 12:19:50Z bird $ ## @file # kBuild - File included at bottom of a makefile or sub-makefile. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # # Sanity check. # ifdef __footer_kmk__ $(error kBuild: footer.kmk has already been included. Fix your sub-makefiles! $(MAKEFILE_CURRENT)) endif # # Set the default path for all new targets. # define def_subheader ifndef $(target)_PATH ifndef $(target)_DEFPATH $(target)_DEFPATH := $(PATH_SUB_CURRENT) endif $(call KB_FN_ASSIGN_DEPRECATED,$(target)_PATH,$($(target)_DEFPATH),$(target)_DEFPATH) else ifndef $(target)_DEFPATH $(target)_DEFPATH := $($(target)_PATH) endif ifndef $(target)_MAKEFILE $(target)_MAKEFILE := $(MAKEFILE_CURRENT) endif ifndef $(target)_0_OUTDIR $(target)_0_OUTDIR := $(call TARGET_PATH,$(target)) $(call KB_FN_ASSIGN_DEPRECATED,PATH_$(target),$($(target)_0_OUTDIR),$(target)_0_OUTDIR) endif endef $(foreach target,\ $(ALL_TARGETS) \ $(FETCHES) $(FETCHES.$(KBUILD_TARGET)) $(FETCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_CPU)) $(FETCHES.$(KBUILD_TYPE)) \ $(PATCHES) $(PATCHES.$(KBUILD_TARGET)) $(PATCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_CPU)) $(PATCHES.$(KBUILD_TYPE)) \ $(BLDPROGS) $(BLDPROGS.$(KBUILD_HOST)) $(BLDPROGS.$(KBUILD_HOST).$(BUILD_PLATFORM_ARCH)) $(BLDPROGS.$(KBUILD_HOST_ARCH)) $(BLDPROGS.$(KBUILD_HOST_CPU)) $(BLDPROGS.$(KBUILD_TYPE)) \ $(LIBRARIES) $(LIBRARIES.$(KBUILD_TARGET)) $(LIBRARIES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_CPU)) $(LIBRARIES.$(KBUILD_TYPE)) \ $(IMPORT_LIBS) $(IMPORT_LIBS.$(KBUILD_TARGET)) $(IMPORT_LIBS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_CPU)) $(IMPORT_LIBS.$(KBUILD_TYPE)) \ $(DLLS) $(DLLS.$(KBUILD_TARGET)) $(DLLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_CPU)) $(DLLS.$(KBUILD_TYPE)) \ $(PROGRAMS) $(PROGRAMS.$(KBUILD_TARGET)) $(PROGRAMS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_CPU)) $(PROGRAMS.$(KBUILD_TYPE)) \ $(SYSMODS) $(SYSMODS.$(KBUILD_TARGET)) $(SYSMODS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_CPU)) $(SYSMODS.$(KBUILD_TYPE)) \ $(MISCBINS) $(MISCBINS.$(KBUILD_TARGET)) $(MISCBINS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_CPU)) $(MISCBINS.$(KBUILD_TYPE)) \ $(INSTALLS) $(INSTALLS.$(KBUILD_TARGET)) $(INSTALLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_CPU)) $(INSTALLS.$(KBUILD_TYPE)) \ $(OTHERS) $(OTHERS.$(KBUILD_TARGET)) $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_CPU)) $(OTHERS.$(KBUILD_TYPE)) \ ,$(evalval def_subheader)) ifneq ($(_SUB_MAKEFILE_STACK),) # # Switch back to the context of previous makefile on the stack. # MAKEFILE_CURRENT := $(stack-pop _SUB_MAKEFILE_STACK) PATH_SUB_CURRENT := $(abspath $(dir $(MAKEFILE_CURRENT))) else # # We've reached the end of the line, include the real footer. # include $(PATH_KBUILD)/footer.kmk endif kbuild-2695/kBuild/envos2.cmd0000644000000000000000000006434712247157310014564 0ustar rootroot/* echo this is a rexx script! cancel & quit & exit */ /* $Id: envos2.cmd 2413 2010-09-11 17:43:04Z bird $ */ /** @file * Environment setup script for OS/2. */ /* * * Copyright (c) 1999-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * Setup the usual suspects. */ Address CMD '@echo off'; signal on novalue name NoValueHandler if (RxFuncQuery('SysLoadFuncs') = 1) then do call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'; call SysLoadFuncs; end /* * Apply the CMD.EXE workaround. */ call FixCMDEnv; /* * Globals */ skBuildPath = EnvGet("KBUILD_PATH"); skBuildBinPath = EnvGet("KBUILD_BIN_PATH"); skBuildType = EnvGet("KBUILD_TYPE"); skBuildTarget = EnvGet("KBUILD_TARGET"); skBuildTargetArch = EnvGet("KBUILD_TARGET_ARCH"); skBuildTargetCpu = EnvGet("KBUILD_TARGET_CPU"); skBuildHost = EnvGet("KBUILD_HOST"); skBuildHostArch = EnvGet("KBUILD_HOST_ARCH"); skBuildHostCpu = EnvGet("KBUILD_HOST_CPU"); /* * Process arguments. */ fOptFull = 0 fOptLegacy = 0 fOptDbg = 0 fOptQuiet = 0 sOptVars = "" fOptValueOnly = 0 sShowVarPrefix = ""; fOptOverrideAll = 0 fOptOverrideType = 0; fSetType = 0; fOptOverrideTarget = 0; fOptOverrideTargetArch = 0; fOptDefault = 0; parse arg sArgs do while (sArgs <> '') parse value sArgs with sArg sRest say 'sArgs='sArgs';' say ' sArg='sArg';' say 'sRest='sRest';' select when (sArg = "--debug-script") then do fOptDbg = 1; end when (sArg = "--no-debug-script") then do fOptDbg = 0; end when (sArg = "--quiet") then do fOptQuiet = 1; end when (sArg = "--verbose") then do fOptQuiet = 0; end when (sArg = "--full") then do fOptFull = 1; end when (sArg = "--normal") then do fOptFull = 0; end when (sArg = "--legacy") then do fOptLegacy = 1; end when (sArg = "--no-legacy") then do fOptLegacy = 0; end when (sArg = "--eval") then do say "error: --eval is not supported on OS/2." end when (sArg = "--var") then do parse value sRest with sVar sRest2 sRest = sRest2; if (sVar = '') then do say "syntax error: --var is missing the variable name"; call SysSleep 1 exit 1; end if (sVar = "all" | sOptVars = "all") then sOptVars = "all"; else sOptVars = sOptVars || " " || sVar; end when (sArg = "--set") then do sShowVarPrefix = "SET "; end when (sArg = "--no-set") then do sShowVarPrefix = ""; end when (sArg = "--value-only") then do fOptValueOnly = 1; end when (sArg = "--name-and-value") then do fOptValueOnly = 0; end when (sArg = "--release") then do fOptOverrideType = 1; fSetType = 1; skBuildType = 'release'; end when (sArg = "--debug") then do fOptOverrideType = 1; fSetType = 1; skBuildType = 'debug'; end when (sArg = "--profile") then do fOptOverrideType = 1; fSetType = 1; skBuildType = 'profile'; end when (sArg = "--defaults") then do fOptOverrideAll = 1; skBuildType = ""; skBuildTarget = ""; skBuildTargetArch = ""; skBuildTargetCpu = ""; skBuildHost = ""; skBuildHostArch = ""; skBuildHostCpu = ""; skBuildPath = ""; skBuildBinPath = ""; end when (sArg = "--help" | sArg = "-h" | sArg = "-?" | sArg = "/?" | sArg = "/h") then do say "kBuild Environment Setup Script, v0.1.4" say "" say "syntax: envos2.cmd [options] [command [args]]" say " or: envos2.cmd [options] --var " say "" say "The first form will execute the command, or if no command is given" say "modify the current invoking shell." say "The second form will print the specfified variable(s)." say "" say "Options:" say " --debug, --release, --profile" say " Alternative way of specifying KBUILD_TYPE." say " --defaults" say " Enforce defaults for all the KBUILD_* values." say " --debug-script, --no-debug-script" say " Controls debug output. Default: --no-debug-script" say " --quiet, --verbose" say " Controls informational output. Default: --verbose" say " --full, --normal" say " Controls the variable set. Default: --normal" say " --legacy, --no-legacy" say " Include legacy variables in result. Default: --no-legacy" say " --value-only, --name-and-value" say " Controls what the result of a --var query. Default: --name-and-value" say " --set, --no-set" say " Whether to prefix the variable output with 'SET'." say " Default: --no-set" say "" exit 1 end when (sArg = "--") then do sArgs = sRest; leave; end when (left(sArg, 2) = '--') then do say 'syntax error: unknown option: '||sArg call SysSleep 1 exit 1 end otherwise do leave end end sArgs = sRest; end sCommand = strip(sArgs); /* * Deal with legacy environment variables. */ if (\fOptOverrideAll) then do if (EnvGet("PATH_KBUILD") <> '') then do if (skBuildPath <> '' & skBuildPath <> EnvGet("PATH_KBUILD")) then do say "error: KBUILD_PATH ("||skBuildPath||") and PATH_KBUILD ("||EnvGet("PATH_KBUILD")||") disagree." call SysSleep 1; exit 1; end skBuildPath = EnvGet("PATH_KBUILD"); end if (EnvGet("PATH_KBUILD_BIN") <> '') then do if (skBuildPath <> '' & skBuildBinPath <> EnvGet("PATH_KBUILD_BIN")) then do say "error: KBUILD_BIN_PATH ("||skBuildBinPath||") and PATH_KBUILD_BIN ("||EnvGet("PATH_KBUILD_BIN")||") disagree." call SysSleep 1; exit 1; end skBuildBinPath = EnvGet("PATH_KBUILD_BIN"); end if (EnvGet("BUILD_TYPE") <> '') then do if (skBuildType <> '' & skBuildType <> EnvGet("BUILD_TYPE")) then do say "error: KBUILD_TYPE ("||skBuildType||") and BUILD_TYPE ("||EnvGet("BUILD_TYPE")||") disagree." call SysSleep 1; exit 1; end skBuildType = EnvGet("BUILD_TYPE"); end if (EnvGet("BUILD_TARGET") <> '') then do if (skBuildTarget <> '' & skBuildTarget <> EnvGet("BUILD_TARGET")) then do say "error: KBUILD_TARGET ("||skBuildTarget||") and BUILD_TARGET ("||EnvGet("BUILD_TARGET")||") disagree." call SysSleep 1; exit 1; end skBuildTarget = EnvGet("BUILD_TARGET"); end if (EnvGet("BUILD_TARGET_ARCH") <> '') then do if (skBuildTargetArch <> '' & skBuildTargetArch <> EnvGet("BUILD_TARGET_ARCH")) then do say "error: KBUILD_TARGET_ARCH ("||skBuildTargetArch ||") and BUILD_TARGET_ARCH ("||EnvGet("BUILD_TARGET_ARCH")||") disagree." call SysSleep 1; exit 1; end skBuildTargetArch = EnvGet("BUILD_TARGET_ARCH"); end if (EnvGet("BUILD_TARGET_CPU") <> '') then do if (skBuildTargetCpu <> '' & skBuildTargetCpu <> EnvGet("BUILD_TARGET_CPU")) then do say "error: KBUILD_TARGET_CPU ("||skBuildTargetCpu ||") and BUILD_TARGET_CPU ("||EnvGet("BUILD_TARGET_CPU")||") disagree." call SysSleep 1; exit 1; end skBuildTargetCpu = EnvGet("BUILD_TARGET_CPU"); end if (EnvGet("BUILD_PLATFORM") <> '') then do if (skBuildHost <> '' & skBuildHost <> EnvGet("BUILD_PLATFORM")) then do say "error: KBUILD_HOST ("||skBuildHost||") and BUILD_PLATFORM ("||EnvGet("BUILD_PLATFORM")||") disagree." call SysSleep 1; exit 1; end if (skBuildHost = '' & EnvGet("BUILD_PLATFORM") = "OS2") then do say "error: BUILD_PLATFORM=OS2! Please unset it or change it to 'os2'." call SysSleep 1; exit 1; end skBuildHost = EnvGet("BUILD_PLATFORM"); end if (EnvGet("BUILD_PLATFORM_ARCH") <> '') then do if (skBuildHostArch <> '' & skBuildHostArch <> EnvGet("BUILD_PLATFORM_ARCH")) then do say "error: KBUILD_HOST_ARCH ("||skBuildHostArch ||") and BUILD_PLATFORM_ARCH ("||EnvGet("BUILD_PLATFORM_ARCH")||") disagree." call SysSleep 1; exit 1; end skBuildHostArch = EnvGet("BUILD_PLATFORM_ARCH"); end if (EnvGet("BUILD_PLATFORM_CPU") <> '') then do if (skBuildHostCpu <> '' & skBuildHostCpu <> EnvGet("BUILD_PLATFORM_CPU")) then do say "error: KBUILD_HOST_CPU ("||skBuildHostCpu ||") and BUILD_PLATFORM_CPU ("||EnvGet("BUILD_PLATFORM_CPU")||") disagree." call SysSleep 1; exit 1; end skBuildHostCpu = EnvGet("BUILD_PLATFORM_CPU"); end end /* * Set default build type. */ if (skBuildType = '') then skBuildType = 'release'; if (fOptDbg <> 0) then say "dbg: KBUILD_TYPE="||skBuildType /* * Determin the host platform (OS/2) */ if (skBuildHost = '') then skBuildHost = 'os2'; if (fOptDbg <> 0) then say "dbg: KBUILD_HOST="||skBuildHost if (skBuildHostArch = '') then do select when (skBuildHostCpu = 'i386', | skBuildHostCpu = 'i486', | skBuildHostCpu = 'i586', | skBuildHostCpu = 'i686', | skBuildHostCpu = 'i786', | skBuildHostCpu = 'i886', | skBuildHostCpu = 'i986') then do skBuildHostArch = "x86"; end otherwise do skBuildHostArch = "x86"; end end end if (fOptDbg <> 0) then say "dbg: KBUILD_HOST_ARCH="||skBuildHostArch if (skBuildHostCpu = '') then skBuildHostCpu = 'blend'; if (fOptDbg <> 0) then say "dbg: KBUILD_HOST_CPU="||skBuildHostCpu /* * The target platform. * Defaults to the host when not specified. */ if (skBuildTarget = '') then skBuildTarget = skBuildHost; if (fOptDbg <> 0) then say "dbg: KBUILD_TARGET="||skBuildTarget if (skBuildTargetArch = '') then skBuildTargetArch = skBuildHostArch; if (fOptDbg <> 0) then say "dbg: KBUILD_TARGET_ARCH="||skBuildTargetArch if (skBuildTargetCpu = '') then do if (skBuildTargetArch = skBuildHostArch) then skBuildTargetCpu = skBuildHostCpu; else skBuildTargetCpu = "blend"; end if (fOptDbg <> 0) then say "dbg: KBUILD_TARGET_CPU="||skBuildTargetCpu /* * Determin KBUILD_PATH from the script location and calc KBUILD_BIN_PATH from there. */ if (skBuildPath = '') then do skBuildPath = GetScriptDir() end skBuildPath = translate(skBuildPath, '/', '\') if ( FileExists(skBuildPath||"/footer.kmk") = 0, | FileExists(skBuildPath||"/header.kmk") = 0, | FileExists(skBuildPath||"/rules.kmk") = 0) then do say "error: KBUILD_PATH ("skBuildPath||") is not pointing to a popluated kBuild directory." call SysSleep 1 exit 1 end if (fOptDbg <> 0) then say "dbg: KBUILD_PATH="||skBuildPath; if (skBuildBinPath = '') then do skBuildBinPath = skBuildPath||'/bin/'||skBuildHost||'.'||skBuildHostArch; end skBuildBinPath = translate(skBuildBinPath, '/', '\') if (fOptDbg <> 0) then say "dbg: KBUILD_BIN_PATH="||skBuildBinPath; /* * Add the bin/x.y/ directory to the PATH and BEGINLIBPATH. * NOTE! Once bootstrapped this is the only thing that is actually necessary. */ sOldPath = EnvGet("PATH"); call EnvAddFront 0, "PATH", translate(skBuildBinPath, '\', '/'); sNewPath = EnvGet("PATH"); call EnvSet 0, "PATH", sOldPath; if (fOptDbg <> 0) then say "dbg: PATH="||sNewPath; sOldBeginLibPath = EnvGet("BEGINLIBPATH"); call EnvAddFront 0, "BEGINLIBPATH", translate(skBuildBinPath, '\', '/'); sNewBeginLibPath = EnvGet("BEGINLIBPATH"); call EnvSet 0, "BEGINLIBPATH", sOldBeginLibPath; if (fOptDbg <> 0) then say "dbg: BEGINLIBPATH="||sNewBeginLibPath; /* * Sanity check */ if (DirExists(skBuildBinPath) = 0) then say "warning: The bin directory for the build platform doesn't exist. ("||skBuildBinPath||")"; else do sPrograms = "kmk kDepPre kDepIDB kmk_append kmk_ash kmk_cat kmk_cp kmk_echo kmk_install kmk_ln kmk_mkdir kmk_mv kmk_redirect kmk_rm kmk_rmdir kmk_sed"; do i = 1 to words(sPrograms) sProgram = word(sPrograms, i); if (FileExists(skBuildBinPath||"\"||sProgram||".exe") = 0) then say "warning: The "||sProgram||" program doesn't exit for this platform. ("||skBuildBinPath||")"; end end /* * The environment is in place, now take the requested action. */ iRc = 0; if (sOptVars <> '') then do if (sOptVars = "all") then sOptVars = "KBUILD_PATH KBUILD_BIN_PATH KBUILD_TYPE ", || "KBUILD_TARGET KBUILD_TARGET_ARCH KBUILD_TARGET_CPU ", || "KBUILD_HOST KBUILD_HOST_ARCH KBUILD_HOST_CPU "; /* Echo variable values or variable export statements. */ do i = 1 to words(sOptVars) sVar = word(sOptVars, i) sVal = ''; select when (sVar = "PATH") then sVal = sNewPath; when (sVar = "BEGINLIBPATH") then sVal = sNewBeginLibPath; when (sVar = "KBUILD_PATH") then sVal = skBuildPath; when (sVar = "KBUILD_BIN_PATH") then sVal = skBuildBinPath; when (sVar = "KBUILD_TYPE") then sVal = skBuildType; when (sVar = "KBUILD_HOST") then sVal = skBuildHost; when (sVar = "KBUILD_HOST_ARCH") then sVal = skBuildHostArch; when (sVar = "KBUILD_HOST_CPU") then sVal = skBuildHostCpu; when (sVar = "KBUILD_TARGET") then sVal = skBuildTarget; when (sVar = "KBUILD_TARGET_ARCH") then sVal = skBuildTargetArch; when (sVar = "KBUILD_TARGET_CPU") then sVal = skBuildTargetCpu; otherwise do say "error: Unknown variable "||sVar||" specified in --var request." call SysSleep 1 exit 1 end end if (fOptValueOnly <> 0) then say sVal else say sShowVarPrefix||sVar||"="||sVal; end end else do /* Wipe out all variables - legacy included - with --default. */ if (fOptOverrideAll <> 0) then do call EnvSet 0, KBUILD_PATH, '' call EnvSet 0, KBUILD_BIN_PATH, '' call EnvSet 0, KBUILD_HOST, '' call EnvSet 0, KBUILD_HOST_ARCH, '' call EnvSet 0, KBUILD_HOST_CPU, '' call EnvSet 0, KBUILD_TARGET, '' call EnvSet 0, KBUILD_TARGET_ARCH, '' call EnvSet 0, KBUILD_TARGET_CPU, '' call EnvSet 0, PATH_KBUILD, '' call EnvSet 0, PATH_KBUILD_BIN, '' call EnvSet 0, BUILD_PLATFORM, '' call EnvSet 0, BUILD_PLATFORM_ARCH, '' call EnvSet 0, BUILD_PLATFORM_CPU, '' call EnvSet 0, BUILD_TARGET, '' call EnvSet 0, BUILD_TARGET_ARCH, '' call EnvSet 0, BUILD_TARGET_CPU, '' end /* Export the variables. */ call EnvSet 0, "PATH", sNewPath call EnvSet 0, "BEGINLIBPATH", sNewBeginLibPath if (fOptOverrideType <> 0) then call EnvSet 0, "KBUILD_TYPE", skBuildType if (fOptFull <> 0) then do call EnvSet 0, KBUILD_PATH, skBuildPath call EnvSet 0, KBUILD_HOST, skBuildHost call EnvSet 0, KBUILD_HOST_ARCH, skBuildHostArch call EnvSet 0, KBUILD_HOST_CPU, skBuildHostCpu call EnvSet 0, KBUILD_TARGET, skBuildTarget call EnvSet 0, KBUILD_TARGET_ARCH, skBuildTargetArch call EnvSet 0, KBUILD_TARGET_CPU, skBuildTargetCpu if (fOptLegacy <> 0) then do call EnvSet 0, PATH_KBUILD, skBuildPath call EnvSet 0, BUILD_PLATFORM, skBuildHost call EnvSet 0, BUILD_PLATFORM_ARCH, skBuildHostArch call EnvSet 0, BUILD_PLATFORM_CPU, skBuildHostCpu call EnvSet 0, BUILD_TARGET, skBuildTarget call EnvSet 0, BUILD_TARGET_ARCH, skBuildTargetArch call EnvSet 0, BUILD_TARGET_CPU, skBuildTargetCpu end end /* * Execute left over arguments. */ if (strip(sCommand) <> '') then do if (fOptQuiet <> 0) then say "info: Executing command: "|| sCommand address CMD sCommand iRc = rc; if (fOptQuiet <> 0 & iRc <> 0) then say "info: rc="||iRc||": "|| sCommand end end if (fOptDbg <> 0) then say "dbg: finished (rc="||rc||")" exit (iRc); /******************************************************************************* * Procedure Section * *******************************************************************************/ /** * Give the script syntax */ syntax: procedure say 'syntax: envos2.cmd [command to be executed and its arguments]' say '' return 0; /** * No value handler */ NoValueHandler: say 'NoValueHandler: line 'SIGL; exit(16); /** * Add sToAdd in front of sEnvVar. * Note: sToAdd now is allowed to be alist! * * Known features: Don't remove sToAdd from original value if sToAdd * is at the end and don't end with a ';'. */ EnvAddFront: procedure parse arg fRM, sEnvVar, sToAdd, sSeparator /* sets default separator if not specified. */ if (sSeparator = '') then sSeparator = ';'; /* checks that sToAdd ends with an ';'. Adds one if not. */ if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then sToAdd = sToAdd || sSeparator; /* check and evt. remove ';' at start of sToAdd */ if (substr(sToAdd, 1, 1) = ';') then sToAdd = substr(sToAdd, 2); /* loop thru sToAdd */ rc = 0; i = length(sToAdd); do while i > 1 & rc = 0 j = lastpos(sSeparator, sToAdd, i-1); rc = EnvAddFront2(fRM, sEnvVar, substr(sToAdd, j+1, i - j), sSeparator); i = j; end return rc; /** * Add sToAdd in front of sEnvVar. * * Known features: Don't remove sToAdd from original value if sToAdd * is at the end and don't end with a ';'. */ EnvAddFront2: procedure parse arg fRM, sEnvVar, sToAdd, sSeparator /* sets default separator if not specified. */ if (sSeparator = '') then sSeparator = ';'; /* checks that sToAdd ends with a separator. Adds one if not. */ if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then sToAdd = sToAdd || sSeparator; /* check and evt. remove the separator at start of sToAdd */ if (substr(sToAdd, 1, 1) = sSeparator) then sToAdd = substr(sToAdd, 2); /* Get original variable value */ sOrgEnvVar = EnvGet(sEnvVar); /* Remove previously sToAdd if exists. (Changing sOrgEnvVar). */ i = pos(translate(sToAdd), translate(sOrgEnvVar)); if (i > 0) then sOrgEnvVar = substr(sOrgEnvVar, 1, i-1) || substr(sOrgEnvVar, i + length(sToAdd)); /* set environment */ if (fRM) then return EnvSet(0, sEnvVar, sOrgEnvVar); return EnvSet(0, sEnvVar, sToAdd||sOrgEnvVar); /** * Add sToAdd as the end of sEnvVar. * Note: sToAdd now is allowed to be alist! * * Known features: Don't remove sToAdd from original value if sToAdd * is at the end and don't end with a ';'. */ EnvAddEnd: procedure parse arg fRM, sEnvVar, sToAdd, sSeparator /* sets default separator if not specified. */ if (sSeparator = '') then sSeparator = ';'; /* checks that sToAdd ends with a separator. Adds one if not. */ if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then sToAdd = sToAdd || sSeparator; /* check and evt. remove ';' at start of sToAdd */ if (substr(sToAdd, 1, 1) = sSeparator) then sToAdd = substr(sToAdd, 2); /* loop thru sToAdd */ rc = 0; i = length(sToAdd); do while i > 1 & rc = 0 j = lastpos(sSeparator, sToAdd, i-1); rc = EnvAddEnd2(fRM, sEnvVar, substr(sToAdd, j+1, i - j), sSeparator); i = j; end return rc; /** * Add sToAdd as the end of sEnvVar. * * Known features: Don't remove sToAdd from original value if sToAdd * is at the end and don't end with a ';'. */ EnvAddEnd2: procedure parse arg fRM, sEnvVar, sToAdd, sSeparator /* sets default separator if not specified. */ if (sSeparator = '') then sSeparator = ';'; /* checks that sToAdd ends with a separator. Adds one if not. */ if (substr(sToAdd, length(sToAdd), 1) <> sSeparator) then sToAdd = sToAdd || sSeparator; /* check and evt. remove separator at start of sToAdd */ if (substr(sToAdd, 1, 1) = sSeparator) then sToAdd = substr(sToAdd, 2); /* Get original variable value */ sOrgEnvVar = EnvGet(sEnvVar); if (sOrgEnvVar <> '') then do /* Remove previously sToAdd if exists. (Changing sOrgEnvVar). */ i = pos(translate(sToAdd), translate(sOrgEnvVar)); if (i > 0) then sOrgEnvVar = substr(sOrgEnvVar, 1, i-1) || substr(sOrgEnvVar, i + length(sToAdd)); /* checks that sOrgEnvVar ends with a separator. Adds one if not. */ if (sOrgEnvVar = '') then if (right(sOrgEnvVar,1) <> sSeparator) then sOrgEnvVar = sOrgEnvVar || sSeparator; end /* set environment */ if (fRM) then return EnvSet(0, sEnvVar, sOrgEnvVar); return EnvSet(0, sEnvVar, sOrgEnvVar||sToAdd); /** * Sets sEnvVar to sValue. */ EnvSet: procedure parse arg fRM, sEnvVar, sValue /* if we're to remove this, make valuestring empty! */ if (fRM) then sValue = ''; sEnvVar = translate(sEnvVar); /* * Begin/EndLibpath fix: * We'll have to set internal these using both commandline 'SET' * and internal VALUE in order to export it and to be able to * get it (with EnvGet) again. */ if ((sEnvVar = 'BEGINLIBPATH') | (sEnvVar = 'ENDLIBPATH')) then do if (length(sValue) >= 1024) then say 'Warning: 'sEnvVar' is too long,' length(sValue)' char.'; return SysSetExtLibPath(sValue, substr(sEnvVar, 1, 1)); end if (length(sValue) >= 1024) then do say 'Warning: 'sEnvVar' is too long,' length(sValue)' char.'; say ' This may make CMD.EXE unstable after a SET operation to print the environment.'; end sRc = VALUE(sEnvVar, sValue, 'OS2ENVIRONMENT'); return 0; /** * Gets the value of sEnvVar. */ EnvGet: procedure parse arg sEnvVar if ((translate(sEnvVar) = 'BEGINLIBPATH') | (translate(sEnvVar) = 'ENDLIBPATH')) then return SysQueryExtLibPath(substr(sEnvVar, 1, 1)); return value(sEnvVar,, 'OS2ENVIRONMENT'); /** * Checks if a file exists. * @param sFile Name of the file to look for. * @param sComplain Complaint text. Complain if non empty and not found. * @returns TRUE if file exists. * FALSE if file doesn't exists. */ FileExists: procedure parse arg sFile, sComplain rc = stream(sFile, 'c', 'query exist'); if ((rc = '') & (sComplain <> '')) then say sComplain ''''sFile'''.'; return rc <> ''; /** * Checks if a directory exists. * @param sDir Name of the directory to look for. * @param sComplain Complaint text. Complain if non empty and not found. * @returns TRUE if file exists. * FALSE if file doesn't exists. */ DirExists: procedure parse arg sDir, sComplain rc = SysFileTree(sDir, 'sDirs', 'DO'); if (rc = 0 & sDirs.0 = 1) then return 1; if (sComplain <> '') then say sComplain ''''sDir'''.'; return 0; /** * Workaround for bug in CMD.EXE. * It messes up when REXX have expanded the environment. */ FixCMDEnv: procedure /* do this anyway /* check for 4OS2 first */ Address CMD 'set 4os2test_env=%@eval[2 + 2]'; if (value('4os2test_env',, 'OS2ENVIRONMENT') = '4') then return 0; */ /* force environment expansion by setting a lot of variables and freeing them. * ~6600 (bytes) */ do i = 1 to 100 Address CMD '@set dummyenvvar'||i'=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; end do i = 1 to 100 Address CMD '@set dummyenvvar'||i'='; end return 0; /** * Translate a string to lower case. */ ToLower: procedure parse arg sString return translate(sString, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'); /** * Gets the script directory. */ GetScriptDir: procedure /* * Assuming this script is in the root directory, we can determing * the abs path to it by using the 'parse source' feature in rexx. */ parse source . . sScript sScriptDir = filespec('drive', sScript) || strip(filespec('path', sScript), 'T', '\'); return ToLower(sScriptDir); kbuild-2695/kBuild/up.kmk0000644000000000000000000000356312247157310014004 0ustar rootroot# $Id: up.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - File included at top of a up forwarder makefile. # This method is DEPRECATED. Use Makefile.kup files instead. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite typetype0, Boston, MA 0sourcetargettargettarget-targettype07 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # include the header to get the right MAKE and to include config.kmk # files since these may contain global goals. include $(PATH_KBUILD)/header.kmk UP_TO ?= .. # typical kbuild goals. all_recursive \ binaries \ clean \ dlls \ libraries \ needed \ nothing \ objects \ others \ packing \ pass_binaries \ pass_clean \ pass_dlls \ pass_needed \ pass_nothing \ pass_others \ pass_packing \ programs \ rebuild \ sysmods \ target \ : $(MAKE) -C $(UP_TO) $@ # the syntax checkers. %.o %.obj: $(MAKE) -C $(UP_TO) $@ kbuild-2695/kBuild/footer-passes.kmk0000644000000000000000000002437312247157310016154 0ustar rootroot# $Id: footer-passes.kmk 2521 2011-07-26 18:18:19Z bird $ ## @file # kBuild - Footer - Target lists - Pass 2 - Passes. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # # PASSES (including directory and makefile walking) # # # First, check whether we need to order the passes explicitly or not. # This depends on whether we're a leaf makefile or not. A leaf will # know all its dependencies, while a recursive one relies on the # order sub-directories and other makefiles are executed it. # ## Setup a pass and check for optimizations. # @param $(PASS) Uppercase pass name. define def_pass_setup_and_optimize # The setup. ## @todo This is looks a bit weird... ifndef SUBDIRS_$(PASS) SUBDIRS_$(PASS) := $(SUBDIRS) $(SUBDIRS.$(KBUILD_TARGET)) $(SUBDIRS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) endif ifndef SUBDIRS_AFTER_$(PASS) SUBDIRS_AFTER_$(PASS) := $(SUBDIRS_AFTER) $(SUBDIRS_AFTER.$(KBUILD_TARGET)) $(SUBDIRS_AFTER.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) endif ifndef MAKEFILES_BEFORE_$(PASS) MAKEFILES_BEFORE_$(PASS) := $(MAKEFILES_BEFORE) $(MAKEFILES_BEFORE.$(KBUILD_TARGET)) $(MAKEFILES_BEFORE.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) endif ifndef MAKEFILES_AFTER_$(PASS) MAKEFILES_AFTER_$(PASS) := $(MAKEFILES_AFTER) $(MAKEFILES_AFTER.$(KBUILD_TARGET)) $(MAKEFILES_AFTER.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) endif # The check. ifeq ($(_KBUILD_STRICT_PASS_ORDER),nonstrict) ifneq ($(strip \ $(SUBDIRS_$(PASS)) $(SUBDIRS_$(PASS).$(KBUILD_TARGET)) $(SUBDIRS_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(MAKEFILES_BEFORE_$(PASS)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(SUBDIRS_AFTER_$(PASS)) $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET)) $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(MAKEFILES_AFTER_$(PASS)) $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ ),) _KBUILD_STRICT_PASS_ORDER := strict endif endif # _KBUILD_STRICT_PASS_ORDER == nonstrict endef # def_pass_setup_and_optimize $(eval-opt-var def_pass_setup_and_optimize) ## PASS: Setup & optimization. # Check if we can apply the non-strict pass order optimzation (no SUBDIRS_* and MAKEFILES_*), # and set up the pass specific variables as we go along. _KBUILD_STRICT_PASS_ORDER := nonstrict $(foreach PASS, $(PASSES), $(evalval def_pass_setup_and_optimize)) #$ (error _KBUILD_STRICT_PASS_ORDER=$(_KBUILD_STRICT_PASS_ORDER)) ifeq ($(_KBUILD_STRICT_PASS_ORDER),strict) if !defined(KBUILD_SAFE_PARALLEL) || "$(KMK_OPT_JOBS)" == "1" _KBUILD_STRICT_PASS_ORDER := strict_unsafe endif endif ## Subdir # @param $(pass) Lowercase pass name. # @param $(PASS) Uppercase pass name. # @param $(subdir) Subdirectory # @param $(tag) tag to attach to the rule name. define def_pass_subdir pass_$(pass)$(tag):: $(dep) + $$(QUIET)$$(MAKE) -C $(subdir) -f $$(notdir $$(firstword $$(wildcard $$(addprefix $(subdir)/,$$(DEFAULT_MAKEFILE))))) pass_$(pass) endef ## Submakefile # @param $(pass) Lowercase pass name. # @param $(PASS) Uppercase pass name. # @param $(makefile) Makefile. # @param $(tag) tag to attach to the rule name. define def_pass_makefile pass_$(pass)$(tag):: $(dep) + $$(QUIET)$$(MAKE) -C $(patsubst %/,%,$(dir $(makefile))) -f $(notdir $(makefile)) pass_$(pass) endef ## Execute a pass, strict order. # @param $(pass) Lowercase pass name. # @param $(PASS) Uppercase pass name. define def_pass_strict $(eval tag:=_before) $(eval dep:= ) $(foreach subdir, $(SUBDIRS_$(PASS)) $(SUBDIRS_$(PASS).$(KBUILD_TARGET)) $(SUBDIRS_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) ,$(eval $(def_pass_subdir))) $(foreach makefile,$(MAKEFILES_BEFORE_$(PASS)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)),$(eval $(def_pass_makefile))) $(eval tag:=_after) $(eval dep:=pass_$(pass)_doit) $(foreach subdir, $(SUBDIRS_AFTER_$(PASS)) $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET)) $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) ,$(eval $(def_pass_subdir))) $(foreach makefile,$(MAKEFILES_AFTER_$(PASS)) $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) ,$(eval $(def_pass_makefile))) .NOTPARALLEL: pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_this .PHONY: pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_this pass_$(pass)_doit pass_$(pass)_doit: $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$($(var))) pass_$(pass)_this: pass_$(pass)_before + $$(QUIET)$$(MAKE) -f $$(MAKEFILE) pass_$(pass)_doit pass_$(pass)_after:: pass_$(pass)_this pass_$(pass): pass_$(pass)_after #$ (warning pass=$(pass) PASS=$(PASS): $(PASS_$(PASS)_trgs) $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$($(var)))) endef # def_pass_strict $(eval-opt-var def_pass_strict) ## Execute a pass, strict order. # @param $(pass) Lowercase pass name. # @param $(PASS) Uppercase pass name. define def_pass_strict_unsafe $(eval tag:=_before) $(eval dep:= ) $(foreach subdir, $(SUBDIRS_$(PASS)) $(SUBDIRS_$(PASS).$(KBUILD_TARGET)) $(SUBDIRS_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) ,$(eval $(def_pass_subdir))) $(foreach makefile,$(MAKEFILES_BEFORE_$(PASS)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_BEFORE_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)),$(eval $(def_pass_makefile))) $(eval tag:=_after) $(eval dep:=pass_$(pass)_doit) $(foreach subdir, $(SUBDIRS_AFTER_$(PASS)) $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET)) $(SUBDIRS_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) ,$(eval $(def_pass_subdir))) $(foreach makefile,$(MAKEFILES_AFTER_$(PASS)) $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET)) $(MAKEFILES_AFTER_$(PASS).$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) ,$(eval $(def_pass_makefile))) .PHONY: pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_doit .NOTPARALLEL: pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_doit pass_$(pass)_doit: pass_$(pass)_before \ $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$($(var))) pass_$(pass): \ pass_$(pass)_before \ pass_$(pass)_doit \ pass_$(pass)_after #$ (warning pass=$(pass) PASS=$(PASS): $(PASS_$(PASS)_trgs) $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$($(var)))) endef # def_pass_strict_unsafe $(eval-opt-var def_pass_strict_unsafe) ## Execute a pass, non-strict pass ordering. # @param $(pass) Lowercase pass name. # @param $(PASS) Uppercase pass name. define def_pass_nonstrict .PHONY: pass_$(pass) pass_$(pass)_before pass_$(pass)_after pass_$(pass)_doit pass_$(pass)_doit: $(PASS_$(PASS)_trgs) $(foreach var,$(PASS_$(PASS)_vars),$$$$($(var))) pass_$(pass): pass_$(pass)_doit endef # def_pass_nonstrict ## PASS: rules # Generate the rules for the defined passes. $(foreach PASS, $(PASSES), \ $(eval pass := $(PASS_$(PASS)_pass)) \ $(eval $(def_pass_$(_KBUILD_STRICT_PASS_ORDER)))) ## Pass order, strict. # @param $(pass) Current pass name. # @param $(prev_pass) The previous pass name. define def_pass_order_strict .PHONY: pass_$(pass)_order .NOTPARALLEL: pass_$(pass)_order pass_$(pass)_order: $(pass_prev) %$$(call MSG_PASS,$$(if $$(PASS_$(PASS)),$$(PASS_$(PASS)),$(pass))) + $$(QUIET)$$(MAKE) -f $$(MAKEFILE) pass_$(pass) $(eval pass_prev := pass_$(pass)_order) endef # def_pass_order_strict $(eval-opt-var def_pass_order_strict) ## Pass order, strict unsafe. # @param $(pass) Current pass name. # @param $(prev_pass) The previous pass name. define def_pass_order_strict_unsafe .NOTPARALLEL: pass_$(pass)_order pass_$(pass)_banner .PHONY: pass_$(pass)_order pass_$(pass)_banner pass_$(pass)_banner: $(pass_prev) %$$(call MSG_PASS,$$(if $$(PASS_$(PASS)),$$(PASS_$(PASS)),$(pass))) pass_$(pass)_order: $(pass_prev) \ pass_$(pass)_banner \ pass_$(pass) $(eval pass_prev := pass_$(pass)_order) endef # def_pass_order_strict_unsafe $(eval-opt-var def_pass_order_strict_unsafe) ## Pass order, non-strict. # @param $(pass) Current pass name. # @param $(prev_pass) The previous pass name. define def_pass_order_nonstrict .PHONY: pass_$(pass)_order pass_$(pass)_banner pass_$(pass)_banner: %$$(call MSG_PASS,$$(if $$(PASS_$(PASS)),$$(PASS_$(PASS)),$(pass))) pass_$(pass)_order: \ $(pass_prev) \ pass_$(pass)_banner \ pass_$(pass) $(eval pass_prev := pass_$(pass)_order) endef # def_pass_order_nonstrict $(eval-opt-var def_pass_order_nonstrict) ## PASS: order # Use dependencies to ensure correct pass order. pass_prev := $(foreach PASS,$(DEFAULT_PASSES),\ $(eval pass := $(PASS_$(PASS)_pass)) \ $(eval $(def_pass_order_$(_KBUILD_STRICT_PASS_ORDER)))) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done passes) endif # Some common pass aliases ifndef KBUILD_NO_PASS_ALIASES .PHONY: clean clean: pass_clean .PHONY: nothing nothing: pass_nothing .PHONY: staging staging: pass_staging .PHONY: packing packing: pass_packing ifndef KBUILD_NO_TESTING_PASS_ALIASES .PHONY: check check:: pass_testing .PHONY: test test:: pass_testing endif # KBUILD_NO_TESTING_PASS_ALIASES endif # KBUILD_NO_PASS_ALIASES kbuild-2695/kBuild/footer-pass2-patches.kmk0000644000000000000000000000332012247157310017320 0ustar rootroot# $Id: footer-pass2-patches.kmk 2521 2011-07-26 18:18:19Z bird $ ## @file # kBuild - Footer - Target lists - Pass 2 - Patches. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ## ## Patching. ## ## #define def_patch_src # #endef # # ## Deal with one patch target. #define def_patch # #$(foreach source,$($(target)_SOURCES) $($(target)_SOURCES.$(KBUILD_TYPE)) $($(target)_SOURCES.$(KBUILD_TARGET)) $($(target)_SOURCES.$(KBUILD_TARGET_ARCH)) $($(target)_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)),\ # $(evalval def_patch_src)) # #_PATCHES += #endef # #$(foreach target, $(_ALL_PATCHES), \ # $(evalval def_patch)) # kbuild-2695/kBuild/footer-pass2-fetches.kmk0000644000000000000000000003525012247157310017321 0ustar rootroot# $Id: footer-pass2-fetches.kmk 2521 2011-07-26 18:18:19Z bird $ ## @file # kBuild - Footer - Target lists - Pass 2 - Fetches. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ## @page pg_fetches Fetching Tools, Sources and Similar. # # The targets listed in the the FETCHES target list have the following attributes: # SOURCES # INST # FETCHTOOL # FETCHFLAGS # FETCHDIR # UNPACKTOOL # UNPACKFLAGS # # As usual the target name is an alias for 'creating' the target. Other # aliases are: # pass_fetches # fetch # unfetch # download # unpack # # @remark # # This is a little bit complex because we must guarantee that if a source file # changes only sligtly we must refetch it and to a proper unpacking of it. It # is also a desire that fetched archives and unpacked files can be deleted to # save space. # # Thus, we must be able to cleanup what we've unpacked should any of the # sources be removed. We do this by maintaining a file listing the files # and directories that was unpacked. This operation is named 'unfetch'. # # We make use of the SIZE and MD5 attributes for each of the sources to # create a digest that is stored in the primary target file. Subsequent # runswill compare their digest with it to decide if a refetch is required. # When a refetch is found necessary, an 'unfetch' is performed first to # clean out old files and directores. Note even changes in source order # will cause a refetch due to the way the digest is constructed and # evaluated. # # By not depending directly on the archives (nor on any unpacked files) # but on a goal made up from the archive name, size and md5, we allow # the user to delete the archives. Naturally, this means we'll have to # check and fetch missing archives before attempting to unpack them. # # @remark # # This feature will *NOT* work correctly with vanilla GNU make becuase # it makes use of includedep to avoid too many unnecessary files. # # @todo # 0. Move the fetches out into a unit. # 1. Download corruption / continuation. # 2. It's quite possible that there is one too many indirect dependency now... # ## generates the fetch rule define def_fetch_src_fetch_rule # Indirect goal for downloading something. .PRECIOUS: $(out) $(out) + $($(target)_$(srcname)_FETCH_2_OUTPUT) +| $($(target)_$(srcname)_FETCH_2_OUTPUT_MAYBE) : \ | $($(target)_$(srcname)_FETCH_2_DEPORD) %$$(call MSG_FETCH_DL,$(target),$(source),$(out)) @## @todo do fancy stuff like download continuation. $$(QUIET)$$(RM) -f -- $(out) $(cmds) $$(QUIET)$(if $(md5),$$(MD5SUM_EXT) -b -C $(md5) $(out)) # Intermediate goal for making sure the md5 and size matches. it will (re) fetch the archive if necessary. $(out).checked_$(md5)_$(size): $($(target)_$(srcname)_FETCH_2_DEPEND) | $($(target)_$(srcname)_FETCH_2_DEPORD) %$$(call MSG_FETCH_CHK,$(target),$(source),$(out)) $$(QUIET)$$(RM) -f -- $$@ @# (re)fetch the file if it doesn't exist or if it doesn't matches the md5. @## @todo do fancy stuff like download continuation. $$(QUIET)( test -f $(out) && $(if $(md5),$$(MD5SUM_EXT) -b -C $(md5) $(out), true) ) \ || ( $$(RM_EXT) -f $(out) \ && $$(MAKE) $(out) -f $(MAKEFILE) --no-print-directory ) $$(QUIET2)$$(APPEND) $$@ _TARGET_$(target)_FETCHED += $(out) $(out).checked_$(md5)_$(size) # Just a little precaution. .NOTPARALLEL: $(out) $(out).checked_$(md5)_$(size) endef # def_fetch_src_fetch_rule $(eval-opt-var def_fetch_src_fetch_rule) ## generates the unpack rule define def_fetch_src_unpack_rule # This is the unpack rule. it has an order-only dependency on the download check. $(out) + $($(target)_$(srcname)_UNPACK_2_OUTPUT) +| $($(target)_$(srcname)_UNPACK_2_OUTPUT_MAYBE) : \ $($(target)_$(srcname)_UNPACK_2_DEPEND) \ | $($(target)_$(srcname)_UNPACK_2_DEPORD) \ $(archive).checked_$(md5)_$(size) \ $(dir $(out)) %$$(call MSG_FETCH_UP,$(target),$(archive),$(inst)) $$(QUIET)$$(RM) -f -- $(out) $$(QUIET)$$(MKDIR) -p -- $(dir $(out)) @# if the source archive doesn't exist fetch it (may have been deleted to save space). $$(QUIET)test -f $(archive) \ || ( $$(RM_EXT) -f $(archive).checked_$(md5)_$(size) \ && $$(MAKE) $(archive).checked_$(md5)_$(size) -f $(MAKEFILE) --no-print-directory ) $(cmds) $$(QUIET2)$$(APPEND) $(out) $(notdir $(archive).checked_$(md5)_$(size)) $$(QUIET2)$$(APPEND) $(out) $(notdir $(out)) $(eval _TARGET_$(target)_UNPACKED += $(out)) _TARGET_$(target)_DIGEST := $(_TARGET_$(target)_DIGEST)-$(srcname)_$(md5)_$(size) .NOTPARALLEL: $(out) endef # def_fetch_src_unpack_rule $(eval-opt-var def_fetch_src_unpack_rule) ## Processes a fetch source # define def_fetch_src #$ (warning dbg: def_fetch_src: source='$(source)' target='$(target)') # common local srcname := $(notdir $(source)) local inst := $(firstword \ $($(target)_$(source)_INST)\ $($(target)_$(srcname)_INST)\ $($(source)_INST)\ $($(srcname)_INST)\ $($(target)_INST)\ ) ifneq ($(patsubst %/,ok,$(inst)),ok) $(error kBuild: Bad or missing INST property for source '$(source)' in target '$(target)': $(inst)) endif ## @todo Install-revamp: FIXME INSTARGET_$(target)_$(srcname) := $(inst) local fetchdir := $(firstword \ $($(target)_$(source)_FETCHDIR)\ $($(target)_$(srcname)_FETCHDIR)\ $($(source)_FETCHDIR)\ $($(srcname)_FETCHDIR)\ $($(target)_FETCHDIR)\ $(FETCHDIR)\ $(PATH_TARGET)\ ) local deps := \ $($(target)_$(source)_DEPS)\ $($(target)_$(srcname)_DEPS)\ $($(source)_DEPS)\ $($(srcname)_DEPS)\ $($(target)_DEPS) local orderdeps := \ $($(target)_$(source)_ORDERDEPS)\ $($(target)_$(srcname)_ORDERDEPS)\ $($(source)_ORDERDEPS)\ $($(srcname)_ORDERDEPS)\ $($(target)_ORDERDEPS) local md5 := $(firstword \ $($(target)_$(source)_MD5)\ $($(target)_$(srcname)_MD5)\ $($(source)_MD5)\ $($(srcname)_MD5)\ $($(target)_MD5)\ ) local size := $(firstword \ $($(target)_$(source)_SIZE)\ $($(target)_$(srcname)_SIZE)\ $($(source)_SIZE)\ $($(srcname)_SIZE)\ $($(target)_SIZE)\ ) clean_files += \ $($(target)_$(source)_CLEAN)\ $($(target)_$(srcname)_CLEAN)\ $($(source)_CLEAN)\ $($(srcname)_CLEAN) local dep := # not legal for fetch and unpack tools # # The fetching. # local out := $(fetchdir)/$(srcname) local archive := $(out) $(target)_$(srcname)_1_TARGET = $(TARGET_$(target)_$(srcname)) $(call KB_FN_ASSIGN_DEPRECATED,TARGET_$(target)_$(srcname),$(TARGET_$(target)_$(srcname)),TARGET_$(target)_$(srcname)) local dirdep := $(call DIRDEP,$(fetchdir)) local tool := $(firstword \ $($(target)_$(source)_FETCHTOOL)\ $($(target)_$(srcname)_FETCHTOOL)\ $($(target)_$(source)_TOOL)\ $($(target)_$(srcname)_TOOL)\ $($(source)_FETCHTOOL)\ $($(srcname)_FETCHTOOL)\ $($(source)_TOOL)\ $($(srcname)_TOOL)\ $($(target)_FETCHTOOL)\ $($(target)_TOOL)\ ) local flags :=\ $(TOOL_$(tool)_FETCHFLAGS)\ $(FETCHFLAGS)\ $($(target)_FETCHFLAGS)\ $($(srcname)_FETCHFLAGS)\ $($(source)_FETCHFLAGS)\ $($(target)_$(srcname)_FETCHFLAGS)\ $($(target)_$(source)_FETCHFLAGS) #$ (warning dbg: target=$(target) source=$(source) $(srcname)=$(srcname) tool=$(tool) out=$(out) flags=$(flags) dirdep=$(dirdep) fetchdir=$(fetchdir) md5=$(md5) size=$(size)) ifndef TOOL_$(tool)_FETCH_CMDS $(warning kBuild: tools: \ 1 $($(target)_$(source)_FETCHTOOL)\ 2 $($(target)_$(srcname)_FETCHTOOL)\ 3 $($(target)_$(source)_TOOL)\ 4 $($(target)_$(srcname)_TOOL)\ 5 $($(source)_FETCHTOOL)\ 6 $($(srcname)_FETCHTOOL)\ 7 $($(source)_TOOL)\ 8 $($(srcname)_TOOL)\ 9 $($(target)_FETCHTOOL)\ 10 $($(target)_TOOL) ) $(error kBuild: TOOL_$(tool)_FETCH_CMDS is not defined. source=$(source) target=$(target) ) endif # call the tool local cmds := $(TOOL_$(tool)_FETCH_CMDS) $(target)_$(srcname)_FETCH_2_OUTPUT := $(TOOL_$(tool)_FETCH_OUTPUT) $(target)_$(srcname)_FETCH_2_OUTPUT_MAYBE := $(TOOL_$(tool)_FETCH_OUTPUT_MAYBE) $(target)_$(srcname)_FETCH_2_DEPEND := $(TOOL_$(tool)_FETCH_DEPEND) $(deps) $(target)_$(srcname)_FETCH_2_DEPORD := $(TOOL_$(tool)_FETCH_DEPORD) $(dirdep) $(orderdeps) # generate the fetch rule. $(eval $(def_fetch_src_fetch_rule)) # # The unpacking / installing. # local out := $(inst)_kBuild_$(target)_$(srcname)_unpacked.lst local dirdep := $(call DIRDEP,$(inst)) local tool := $(firstword \ $($(target)_$(source)_UNPACKTOOL)\ $($(target)_$(srcname)_UNPACKTOOL)\ $($(target)_$(source)_TOOL)\ $($(target)_$(srcname)_TOOL)\ $($(source)_UNPACKTOOL)\ $($(srcname)_UNPACKTOOL)\ $($(source)_TOOL)\ $($(srcname)_TOOL)\ $($(target)_UNPACKTOOL)\ $($(target)_TOOL) \ ) ifeq ($(tool),) local tool := $(toupper $(subst .,,$(suffix $(subst tar.,TAR,$(srcname))))) $(evalval def_tools_include) endif local flags :=\ $(TOOL_$(tool)_UNPACKFLAGS)\ $(UNPACKFLAGS)\ $($(target)_UNPACKFLAGS)\ $($(srcname)_UNPACKFLAGS)\ $($(source)_UNPACKFLAGS)\ $($(target)_$(srcname)_UNPACKFLAGS)\ $($(target)_$(source)_UNPACKFLAGS) #$ (warning dbg: target=$(target) source=$(source) $(srcname)=$(srcname) tool=$(tool) out=$(out) flags=$(flags) dirdep=$(dirdep) inst=$(inst) md5=$(md5) size=$(size)) ifndef TOOL_$(tool)_UNPACK_CMDS $(warning kBuild: tools: \ 1 $($(target)_$(source)_UNPACKTOOL)\ 2 $($(target)_$(srcname)_UNPACKTOOL)\ 3 $($(target)_$(source)_TOOL)\ 4 $($(target)_$(srcname)_TOOL)\ 5 $($(source)_UNPACKTOOL)\ 6 $($(srcname)_UNPACKTOOL)\ 7 $($(source)_TOOL)\ 8 $($(srcname)_TOOL)\ 9 $($(target)_UNPACKTOOL)\ 10 $($(target)_TOOL) \ 11 $(toupper $(subst tar.,TAR,$(ext $(srcname)))) \ ) $(error kBuild: TOOL_$(tool)_UNPACK_CMDS is not defined. source=$(source) target=$(target) ) endif # call the tool local cmds := $(TOOL_$(tool)_UNPACK_CMDS) $(target)_$(srcname)_UNPACK_2_OUTPUT := $(TOOL_$(tool)_UNPACK_OUTPUT) $(target)_$(srcname)_UNPACK_2_OUTPUT_MAYBE := $(TOOL_$(tool)_UNPACK_OUTPUT_MAYBE) $(target)_$(srcname)_UNPACK_2_DEPEND := $(TOOL_$(tool)_UNPACK_DEPEND) $(deps) $(target)_$(srcname)_UNPACK_2_DEPORD := $(TOOL_$(tool)_UNPACK_DEPORD) $(dirdep) $(orderdeps) # generate the fetch rule. $(eval $(def_fetch_src_unpack_rule)) _DIRS += $(inst) $(fetchdir) endef # def_fetch_src $(eval-opt-var def_fetch_src) ## # Define the target level rules for a fetch. # @param target # @param out # @param inst # @param _TARGET_$(target)_UNPACKED # @param _TARGET_$(target)_DIGEST # @param bld_trg # @param bld_trg_arch define def_fetch_rules $(out).lst: $(_TARGET_$(target)_UNPACKED) | $(call DIRDEP,$(inst)) %$$(call MSG_FETCH_OK,$(target)) $$(QUIET)$$(RM) -f -- $$@ $$@.tmp $$(QUIET2)$$(APPEND) $$@.tmp '$(notdir $(out))' $$(QUIET)$(if $(_TARGET_$(target)_UNPACKED),$$(CAT_EXT) $(_TARGET_$(target)_UNPACKED) >> $$@.tmp) $$(QUIET)$$(MV) -f -- $$@.tmp $$@ $(out)_unfetched: %$$(call MSG_UNFETCH,$(target)) $$(QUIET)$$(RM) -f -- $$(addprefix $(inst),$$(shell $$(CAT_EXT) $(out).lst 2> /dev/null | $$(SED) -e '/\/$$$$/d')) $$(QUIET)$$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- $$(dir $$@) \ $$(addprefix $(inst),$$(sort $$(dir $$(shell $$(CAT_EXT) $(out).lst 2> /dev/null)))) $$(QUIET)$$(RM) -f -- $(out).lst $(out) $$(QUIET)$$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- $$(dir $$@) $(out): $(comp-vars _TARGET_$(target)_DIGEST_PREV,_TARGET_$(target)_DIGEST,FORCE) | $(call DIRDEP,$(inst)) $$(QUIET)$$(RM) -f -- $$@ %$$(if $$(_TARGET_$(target)_DIGEST),$$(if $$(eq $$(file-size $(out).lst),-1)\ ,$$(call MSG_REFETCH,$(target)),$$(call MSG_FETCH,$(target))),$$(call MSG_UNFETCH,$(target))) $$(QUIET)$(TEST_EXT) -f $(out).lst -- $$(MAKE) -f $(MAKEFILE) --no-print-directory $(out)_unfetched $$(QUIET)$$(if $$(_TARGET_$(target)_DIGEST),$$(MAKE) -f $(MAKEFILE) --no-print-directory $(out).lst,$$(RMDIR) -p --ignore-fail-on-non-empty --ignore-fail-on-not-exist -- $$(dir $$@)) $$(QUIET2)$$(if $$(_TARGET_$(target)_DIGEST),$$(APPEND) $$@ "_TARGET_$(target)_DIGEST_PREV := $(_TARGET_$(target)_DIGEST)") .NOTPARALLEL: $(out).lst $(out)_unfetched $(out) endef ## # Deal with one fetch target. # @param target # @param bld_trg # @param bld_trg_arch define def_fetch # common ## @todo Install-revamp: FIXME INSTARGET_$(target) := $($(target)_INST) ifneq ($(patsubst %/,ok,$(INSTARGET_$(target))),ok) $(error kBuild: Bad or missing INST property for target '$(target)'. \ $(target)_INST='$($(target)_INST)' ($(origin $(target)_INST))) endif _TARGET_$(target)_FETCHED := _TARGET_$(target)_UNPACKED := _TARGET_$(target)_DIGEST := local clean_files := $($(target)_CLEAN) $($(target)_CLEAN.$(bld_trg)) $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_arch)) $($(target)_CLEAN.$(KBUILD_TYPE)) # The 'sources'. #$ (warning dbg fetch: target=$(target) sources=$($(target)_SOURCES) $($(target)_SOURCES.$(KBUILD_TYPE)) $($(target)_SOURCES.$(KBUILD_TARGET)) $($(target)_SOURCES.$(bld_trg_arch)) $($(target)_SOURCES.$(KBUILD_TARGET).$(bld_trg_arch))) $(foreach source,$($(target)_SOURCES) $($(target)_SOURCES.$(KBUILD_TYPE)) $($(target)_SOURCES.$(bld_trg)) $($(target)_SOURCES.$(bld_trg_arch)) $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)),\ $(evalval def_fetch_src)) # The target. local inst := $(INSTARGET_$(target)) local out := $(inst)_kBuild_fetch_$(target) $(eval includedep $(out)) $(eval $(def_fetch_rules)) # Define the aliases here (doesn't work if defined in def_fetch_rules, just like includedep). $(target): $(out) $(target)_unfetch: $(out)_unfetched _FETCHES += $(out) _DOWNLOADS += $(_TARGET_$(target)_FETCHED) _UNPACKS += $(_TARGET_$(target)_UNPACKED) _UNFETCHES += $(out)_unfetched _DIRS += $(inst) _CLEAN_FILES += $(clean_files) endef $(eval-opt-var def_fetch) # Walk the FETCH target lists. bld_trg := $(KBUILD_TARGET) bld_trg_arch := $(KBUILD_TARGET_ARCH) $(foreach target, $(_ALL_FETCHES), \ $(evalvalctx def_fetch)) # some aliases. download: $(_DOWNLOADS) unpack: $(_UNPACKS) fetch: $(_FETCHES) unfetch: $(_UNFETCHES) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done fetching targets) endif kbuild-2695/kBuild/footer-inherit-uses-tools.kmk0000644000000000000000000011273112247157310020427 0ustar rootroot# $Id: footer-inherit-uses-tools.kmk 2521 2011-07-26 18:18:19Z bird $ ## @file # kBuild - Footer - Target lists - Pass 2 - Template & Target Inheritance, Uses and Tools. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ## Converts a variable from simple to recursive flavor. # This is used by def_inherit_template_one_accumulate_l and def_inherit_template_one_accumulate_r. # @param $1 The variable name. define def_simple_2_recursive $1_DEFERRED := $$($1) $1 = $$($1_DEFERRED) endef ## Inherit one keyword in a non-accumulative manner. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. define def_inherit_one_keyword ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) = $($(trg)_$(prop).$(src_key)) endif endif endef # EXPAND_BY = overriding ## Inherit one keyword in a non-accumulative manner. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. define def_inherit_one_keyword_overriding_now_l ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key)) endif endif endef ## @copydoc def_inherit_one_overriding_now_l define def_inherit_one_keyword_overriding_now_r ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key)) endif endif endef ## Inherit one keyword in a non-accumulative manner, deferred expansion. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. # @remark This define relies on double evaluation define def_inherit_one_keyword_overriding_deferred ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key)) endif endif endef ## @copydoc def_inherit_one_overriding_deferred define def_inherit_one_keyword_overriding_deferred_l ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key)) endif endif endef ## @copydoc def_inherit_one_overriding_deferred define def_inherit_one_keyword_overriding_deferred_r ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key)) endif endif endef # EXPAND_BY = prepending ## Inherit one keyword in a prepending manner. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. define def_inherit_one_keyword_prepending_now_l ifdef $(trg)_$(prop).$(src_key) $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key)) $($(trg)_$(prop).$(trg_key)) endif endef ## @copydoc def_inherit_one_prepending_now_l define def_inherit_one_keyword_prepending_now_r ifdef $(trg)_$(prop).$(src_key) $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(trg_key)) $($(trg)_$(prop).$(src_key)) endif endef ## Inherit one keyword in a non-accumulative manner, deferred expansion. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. # @remark This define relies on double evaluation define def_inherit_one_keyword_prepending_deferred ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key)) endif endif endef ## Inherit one keyword in a prepending manner, deferred expansion. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. define def_inherit_one_keyword_prepending_deferred_l ifdef $(trg)_$(prop).$(src_key) ifeq ($$(flavor $(trg)_$(prop).$(trg_key)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop).$(trg_key)) endif $(trg)_$(prop).$(trg_key) <= $$($(trg)_$(prop).$(src_key)) endif endef ## @copydoc def_inherit_one_prepending_deferred_l define def_inherit_one_keyword_prepending_deferred_r ifdef $(trg)_$(prop).$(src_key) ifeq ($$(flavor $(trg)_$(prop).$(trg_key)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop).$(trg_key)) endif $(trg)_$(prop).$(trg_key) += $$($(trg)_$(prop).$(src_key)) endif endef # EXPAND_BY = appending ## Inherit one keyword in an appending manner. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. define def_inherit_one_keyword_appending_now_l ifdef $(trg)_$(prop).$(src_key) $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(trg_key)) $($(trg)_$(prop).$(src_key)) endif endef ## @copydoc def_inherit_one_appending_now_l define def_inherit_one_keyword_appending_now_r ifdef $(trg)_$(prop).$(src_key) $(trg)_$(prop).$(trg_key) := $($(trg)_$(prop).$(src_key)) $($(trg)_$(prop).$(trg_key)) endif endef ## Inherit one keyword in a non-accumulative manner, deferred expansion. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. # @remark This define relies on double evaluation define def_inherit_one_keyword_appending_deferred ifdef $(trg)_$(prop).$(src_key) ifndef $(trg)_$(prop).$(trg_key) $(trg)_$(prop).$(trg_key) = $$($(trg)_$(prop).$(src_key)) endif endif endef ## Inherit one keyword in an appending manner, deferred expansion. # @param $(trg) Target object. # @param $(prop) The property. # @param $(src_key) Source keyword. # @param $(trg_key) Target keyword. define def_inherit_one_keyword_appending_deferred_l ifdef $(trg)_$(prop).$(src_key) ifeq ($$(flavor $(trg)_$(prop).$(trg_key)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop).$(trg_key)) endif $(trg)_$(prop).$(trg_key) += $$($(trg)_$(prop).$(src_key)) endif endef ## @copydoc def_inherit_one_appending_deferred_l define def_inherit_one_keyword_appending_deferred_r ifdef $(trg)_$(prop).$(src_key) ifeq ($$(flavor $(trg)_$(prop).$(trg_key)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop).$(trg_key)) endif $(trg)_$(prop).$(trg_key) <= $$($(trg)_$(prop).$(src_key)) endif endef ## Worker for def_inherit that deals with one keyword that makes # use of inheritance. # @param prefix_keyword key_prefix:keyword. The cool join/split game as usual. # @param trg Object to consider for inheriting. # @param properties List of the properties with straight expansion. # @param properties_now_l List of the properties with immediate expansion, accumulating on the left side. # @param properties_now_r List of the properties with immediate expansion, accumulating on the right side. # @param properties_deferred List of the properties with deferred expansion (e.g. function), non-accumulative . # @param properties_deferred_l List of the properties with deferred expansion (e.g. function), accumulating on the left side. # @param properties_deferred_r List of the properties with deferred expansion (e.g. function), accumulating on the right side. define def_inherit_keyword local prefix := $(word 1,$(subst :, ,$(prefix_keyword))) local trg_key := $(word 2,$(subst :, ,$(prefix_keyword))) local src_key := $($(prefix)_$(trg_key)_EXTENDS) local by := $($(prefix)_$(trg_key)_EXTENDS_BY) # Inherit the properties. $(foreach prop, $(properties), $(eval $(def_inherit_one_keyword))) $(foreach prop, $(properties_now_l), $(eval $(def_inherit_one_keyword_$(by)_now_l))) $(foreach prop, $(properties_now_r), $(eval $(def_inherit_one_keyword_$(by)_now_r))) $(foreach prop, $(properties_deferred), $(eval $(def_inherit_one_keyword_$(by)_deferred))) $(foreach prop, $(properties_deferred_l), $(eval $(def_inherit_one_keyword_$(by)_deferred_l))) $(foreach prop, $(properties_deferred_r), $(eval $(def_inherit_one_keyword_$(by)_deferred_r))) endef # def_inherit_keyword ## Inherit one template property in a non-accumulative manner. # @param $(prop) Property name # @param $(src) Source (parent) object. # @param $(trg) Target (child) object. define def_inherit_one ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) = $($(src)_$(prop)) endif endif endef # EXPAND_BY = overriding ## Inherit one template property in a non-accumulative manner. # @param $(prop) Property name # @param $(src) Source (parent) object. # @param $(trg) Target (child) object. define def_inherit_one_overriding_now_l ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) := $($(src)_$(prop)) endif endif endef ## @copydoc def_inherit_one_overriding_now_l define def_inherit_one_overriding_now_r ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) := $($(src)_$(prop)) endif endif endef ## Inherit one template property in a non-accumulative manner, deferred expansion. # @param $(prop) Property name # @param $(src) Source # @param $(trg) Target # @remark This define relies on double evaluation define def_inherit_one_overriding_deferred ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) = $$($(src)_$(prop)) endif endif endef ## @copydoc def_inherit_one_overriding_deferred define def_inherit_one_overriding_deferred_l ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) = $$($(src)_$(prop)) endif endif endef ## @copydoc def_inherit_one_overriding_deferred define def_inherit_one_overriding_deferred_r ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) = $$($(src)_$(prop)) endif endif endef # EXPAND_BY = prepending ## Inherit one template property in a prepending manner. # @param $(prop) Property name # @param $(src) Source (parent) object. # @param $(trg) Target (child) object. define def_inherit_one_prepending_now_l ifdef $(src)_$(prop) $(trg)_$(prop) := $($(src)_$(prop)) $($(trg)_$(prop)) endif endef ## @copydoc def_inherit_one_prepending_now_l define def_inherit_one_prepending_now_r ifdef $(src)_$(prop) $(trg)_$(prop) := $($(trg)_$(prop)) $($(src)_$(prop)) endif endef ## Inherit one template property in a non-accumulative manner, deferred expansion. # @param $(prop) Property name # @param $(src) Source # @param $(trg) Target # @remark This define relies on double evaluation define def_inherit_one_prepending_deferred ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) = $$($(src)_$(prop)) endif endif endef ## Inherit one template property in a prepending manner, deferred expansion. # @param $(prop) Property name # @param $(src) Source (parent) object. # @param $(trg) Target (child) object. define def_inherit_one_prepending_deferred_l ifdef $(src)_$(prop) ifeq ($$(flavor $(trg)_$(prop)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop)) endif $(trg)_$(prop) <= $$($(src)_$(prop)) endif endef ## @copydoc def_inherit_one_prepending_deferred_l define def_inherit_one_prepending_deferred_r ifdef $(src)_$(prop) ifeq ($$(flavor $(trg)_$(prop)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop)) endif $(trg)_$(prop) += $$($(src)_$(prop)) endif endef # EXPAND_BY = appending ## Inherit one template property in an appending manner. # @param $(prop) Property name # @param $(src) Source (parent) object. # @param $(trg) Target (child) object. define def_inherit_one_appending_now_l ifdef $(src)_$(prop) $(trg)_$(prop) := $($(trg)_$(prop)) $($(src)_$(prop)) endif endef ## @copydoc def_inherit_one_appending_now_l define def_inherit_one_appending_now_r ifdef $(src)_$(prop) $(trg)_$(prop) := $($(src)_$(prop)) $($(trg)_$(prop)) endif endef ## Inherit one template property in a non-accumulative manner, deferred expansion. # @param $(prop) Property name # @param $(src) Source # @param $(trg) Target # @remark This define relies on double evaluation define def_inherit_one_appending_deferred ifdef $(src)_$(prop) ifndef $(trg)_$(prop) $(trg)_$(prop) = $$($(src)_$(prop)) endif endif endef ## Inherit one template property in an appending manner, deferred expansion. # @param $(prop) Property name # @param $(src) Source (parent) object. # @param $(trg) Target (child) object. define def_inherit_one_appending_deferred_l ifdef $(src)_$(prop) ifeq ($$(flavor $(trg)_$(prop)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop)) endif $(trg)_$(prop) += $$($(src)_$(prop)) endif endef ## @copydoc def_inherit_one_appending_deferred_l define def_inherit_one_appending_deferred_r ifdef $(src)_$(prop) ifeq ($$(flavor $(trg)_$(prop)),simple) $$(evalcall2 def_simple_2_recursive,$(trg)_$(prop)) endif $(trg)_$(prop) <= $$($(src)_$(prop)) endif endef ## combines the specified properties $(1) with the $(_KEYWORDS) list. _INHERIT_JOIN_KEYWORDS = $(1) $(foreach keyword,$(_KEYWORDS), $(addsuffix .$(keyword), $(1))) ## Generic inheritance for use with targets templates and tools. # @param trg Object to consider for inheriting. # @param src_prefix What to prefix the value found in EXTENDS with to get the object. # @param load_function Load function for stuff that needs # @param properties List of the properties with straight expansion. # @param properties_now_l List of the properties with immediate expansion, accumulating on the left side. # @param properties_now_r List of the properties with immediate expansion, accumulating on the right side. # @param properties_deferred List of the properties with deferred expansion (e.g. function), non-accumulative . # @param properties_deferred_l List of the properties with deferred expansion (e.g. function), accumulating on the left side. # @param properties_deferred_r List of the properties with deferred expansion (e.g. function), accumulating on the right side. define def_inherit # Load it - loading is a mess, fix. ifneq ($(load_function),) local loading := $(patsubst $(src_prefix)%,%,$(trg)) $(evalvalctx $(load_function)) endif local src := $(strip $($(trg)_EXTENDS)) ifneq ($(src),) ifndef $(trg)_EXTENDS_STATUS_ $(trg)_EXTENDS_STATUS_ := 0 # Load the source. ifneq ($(load_function),) local loading := $(src) $(evalvalctx $(load_function)) endif # less typing. local src := $(src_prefix)$(src) # Recursivly process the parent (src) if it's inherting from somebody too. ifdef $(src)_EXTENDS ifneq ($($(src)_EXTENDS_STATUS_),42) # 'foreach' will create 'trg' in a new variable context hiding # out current variable. 'src' OTOH will be overwritten. $(foreach trg, $(src), $(evalval def_inherit)) local src := $(src_prefix)$(strip $($(trg)_EXTENDS)) endif endif # Get & check EXTENDS_BY. local by = $(strip $($(trg)_EXTENDS_BY)) ifeq ($(by),) local by = overriding else ifn1of ($(by), overriding appending prepending) $(error kBuild: Invalid EXTENDS_BY value '$(by)' on '$(trg)'!) endif # Inherit the properties. $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties)), $(eval $(def_inherit_one))) $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_now_l)), $(eval $(def_inherit_one_$(by)_now_l))) $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_now_r)), $(eval $(def_inherit_one_$(by)_now_r))) $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_deferred)), $(eval $(def_inherit_one_$(by)_deferred))) $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_deferred_l)), $(eval $(def_inherit_one_$(by)_deferred_l))) $(foreach prop, $(call _INHERIT_JOIN_KEYWORDS,$(properties_deferred_r)), $(eval $(def_inherit_one_$(by)_deferred_r))) # Mark the target as done. $(trg)_EXTENDS_STATUS_ := 42 else # Check for inheritance loops. ifneq ($($(trg)_EXTENDS_STATUS_),42) $(error kBuild: Target inheritance loop! target=$(trg) $(trg)_EXTENDS_STATUS_=$($(trg)_EXTENDS_STATUS_)) endif endif endif # Keyword inheritance. $(foreach prefix_keyword, $(join $(_KEYWORDS_PREFIX), $(addprefix :,$(_KEYWORDS_EXTENDS))), $(evalval def_inherit_keyword)) endef # def_inherit # # Load global units before doing any inheriting so they can add new properties. # # This only applies to the guys listed in the global USES since there is # no reliable way to deal with things on a target level without first # applying templates. So, to avoid having USES mess up all targets, # we'll make the global and per-target USES property work differently: # The global USES does not apply to targets, just globally. # ## Unit load function. # @param loading The unit name define def_unit_load_function ifndef UNIT_$(loading) UNIT_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_UNIT_PATHS) $(KBUILD_PATH)/units $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk))) ifeq ($(UNIT_$(loading)_KMK_FILE),) $(error kBuild: Cannot find include file for the unit '$(loading)'! Searched: $(KBUILD_UNIT_PATHS) $(KBUILD_PATH)/units $(KBUILD_DEFAULT_PATHS)) endif include $(UNIT_$(loading)_KMK_FILE) ifndef UNIT_$(loading) $(warning kBuild: UNIT_$(loading) was not defined by $(UNIT_$(loading)_KMK_FILE)!) endif endif endef # def_unit_load_function $(foreach loading, \ $(USES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(USES.$(KBUILD_TARGET_CPU)) \ $(USES.$(KBUILD_TARGET_ARCH)) \ $(USES.$(KBUILD_TARGET)) \ $(USES.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \ $(USES.$(KBUILD_HOST_CPU)) \ $(USES.$(KBUILD_HOST_ARCH)) \ $(USES.$(KBUILD_TARGET)) \ $(USES.$(KBUILD_TYPE)) \ $(USES),$(evalval def_unit_load_function)) # # Determin all the templates that is being used and make # sure they are present before we try collect keywords. # _TEMPLATES := $(TEMPLATE) define def_templates ifdef $(target)_TEMPLATE ifneq ("$($(target)_TEMPLATE)","$(strip $($(target)_TEMPLATE))") $$(error kBuild: The template name of target '$(target)' contains tabs ($($(target)_TEMPLATE))). Please remove them) endif _TEMPLATES += $($(target)_TEMPLATE) endif endef # def_templates $(foreach target, $(_ALL_TARGETS), $(eval $(def_templates))) _TEMPLATES := $(sort $(_TEMPLATES)) ## Template load function. # @param loading The template name. This is prefixed. define def_templates_load_function ifndef TEMPLATE_$(loading) TEMPLATE_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_TEMPLATE_PATHS) $(KBUILD_PATH)/templates $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk))) ifeq ($(TEMPLATE_$(loading)_KMK_FILE),) $(error kBuild: Cannot find include file for the template '$(loading)'! Searched: $(KBUILD_TEMPLATE_PATHS) $(KBUILD_PATH)/templates $(KBUILD_DEFAULT_PATHS)) endif include $(TEMPLATE_$(loading)_KMK_FILE) ifndef TEMPLATE_$(loading) $(warning kBuild: TEMPLATE_$(loading) was not defined by $(TEMPLATE_$(loading)_KMK_FILE)!) endif endif endef # def_templates_load_function $(foreach loading, $(_TEMPLATES), $(evalval def_templates_load_function)) # # Determin the keywords required for correct inherting and setup keyword inheritance. # # This means walking all the lists of immediate template and targets and # pick up all the BLD_T* keywords. Since templates that are referenced # indirectly in the inheritance hierarchy, the result from this exercise # might not be 100% accurate... :-/ # _BLD_TYPES := $(KBUILD_TYPE) _BLD_TARGETS := $(KBUILD_TARGET) $(KBUILD_HOSTS) _BLD_ARCHES := $(KBUILD_TARGET_ARCH) $(KBUILD_HOST_ARCH) _BLD_CPUS := $(KBUILD_TARGET_CPU) $(KBUILD_HOST_CPU) define def_collect_bld_xyz ifdef $(src)_BLD_TYPE ifn1of ($($(src)_BLD_TYPE), $(KBUILD_BLD_TYPES)) $(error kBuild: $(src)_BLD_TYPE=$($(src)_BLD_TYPE) not in KBUILD_BLD_TYPES={$(KBUILD_BLD_TYPES)}!) endif _BLD_TYPES += $($(src)_BLD_TYPE) endif ifdef $(src)_BLD_TRG ifn1of ($($(src)_BLD_TRG), $(KBUILD_OSES)) $(error kBuild: $(src)_BLD_TRG=$($(src)_BLD_TRG) not in KBUILD_OSES={$(KBUILD_OSES)}!) endif _BLD_TARGETS += $($(src)_BLD_TRG) endif ifdef $(src)_BLD_TRG_ARCH ifn1of ($($(src)_BLD_TRG_ARCH), $(KBUILD_ARCHES)) $(error kBuild: $(src)_BLD_TRG_ARCH=$($(src)_BLD_TRG_ARCH) not in KBUILD_ARCHES={$(KBUILD_ARCHES)}!) endif _BLD_ARCHES += $($(src)_BLD_TRG_ARCH) endif ifdef $(src)_BLD_TRG_CPU if1of ($($(src)_BLD_CPU), $(KBUILD_ARCHES) $(KBUILD_OSES) $(KBUILD_BLD_TYPES)) $(error kBuild: $(src)_BLD_TRG_CPU=$($(src)_BLD_TRG_CPU) found in KBUILD_ARCHES, KBUILD_OSES or KBUILD_BLD_TYPES!) endif _BLD_CPUS += $($(src)_BLD_TRG_CPU) endif endef # def_collect_bld_xyz $(foreach src, $(addprefix TEMPLATE_, $(_TEMPLATES)) $(_ALL_TARGETS) \ ,$(evalval def_collect_bld_xyz)) # Drop duplicate values. # WARNING! These list might not include keywords only involved in inheritance. _BLD_TYPES := $(sort $(_BLD_TYPES)) _BLD_TARGETS := $(sort $(_BLD_TARGETS)) _BLD_ARCHES := $(sort $(_BLD_ARCHES)) _BLD_CPUS := $(sort $(_BLD_CPUS)) ## Look for keywords which extends others and order them. # @param keyword # @param prefix # @param valid define def_keyword_ordering # Check for EXTENDS, fix and validate it if found. local src := $(strip $($(prefix)_$(keyword)_EXTENDS)) ifneq ($(src),) ifndef $(prefix)_$(keyword)_EXTENDS_STATUS_ ifn1of ($(src), $(valid)) $(error kBuild: $(keyword) tries to extend unknown keyword '$(src)'! (known = $(valid))) endif # Recursivly process the parent (src). ifneq ($($(prefix)_$(src)_EXTENDS_STATUS_),42) $(prefix)_$(keyword)_EXTENDS_STATUS_ := 0 # 'foreach' will create 'keyword' in a new variable context hiding # out current variable. 'src' OTOH will be overwritten. $(foreach keyword, $(src), $(evalval def_keyword_ordering)) local src := $(strip $($(prefix)_$(keyword)_EXTENDS)) endif # Check and strip EXTENDS_BY. local by = $(strip $($(prefix)_$(keyword)_EXTENDS_BY)) ifeq ($(by),) local by = overriding else ifn1of ($(by), overriding appending prepending) $(error kBuild: Invalid EXTENDS_BY value '$(by)' on '$(keyword)'!) endif # Update the attributes with stripped $(prefix)_$(keyword)_EXTENDS_BY := $(by) $(prefix)_$(keyword)_EXTENDS := $(src) # Add it to the list and mark it as done. _KEYWORDS_EXTENDS += $(keyword) _KEYWORDS_PREFIX += $(prefix) $(prefix)_$(keyword)_EXTENDS_STATUS_ := 42 else # Check for inheritance loops. ifneq ($($(trg)_EXTENDS_STATUS_),42) $(error kBuild: Keyword inheritance loop! keyword=$(keyword) $(prefix)_$(keyword)_EXTENDS_STATUS_=$($(prefix)_$(keyword)_EXTENDS_STATUS_)) endif endif else # Add it to the ordered list and mark it as done. _KEYWORDS_ORDERED += $(keyword) $(prefix)_$(src)_EXTENDS_STATUS_ := 42 endif endef # def_keyword_ordering $(eval-opt-var def_keyword_ordering) # Look for keywords which extends others and their parents, and from this # construct two lists. _KEYWORDS_ORDERED := _KEYWORDS_EXTENDS := _KEYWORDS_PREFIX := prefix := BLD_TYPE valid := $(KBUILD_BLD_TYPES) $(foreach keyword, $(_BLD_TYPES) , $(evalval def_keyword_ordering)) prefix := BLD_TRG valid := $(KBUILD_OSES) $(foreach keyword, $(_BLD_TARGETS), $(evalval def_keyword_ordering)) prefix := BLD_ARCH valid := $(KBUILD_ARCHES) $(foreach keyword, $(_BLD_ARCHES) , $(evalval def_keyword_ordering)) prefix := BLD_CPU valid := $(KBUILD_CPUS) $(foreach keyword, $(_BLD_CPUS) , $(evalval def_keyword_ordering)) ## @todo Inherit bld_trg.bld_arch for too? # Construct all the possible keywords. _KEYWORDS := $(_KEYWORDS_ORDERED) $(_KEYWORDS_EXTENDS) \ $(foreach bld_trg,$(_BLD_TARGETS),$(addprefix $(bld_trg).,$(_BLD_ARCHES))) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done keywords) endif # # Target inheritance. # # This has to be done on a per target list basis as to avoid adding # incorrect properties that will wast memory, time, and may confuse # later strictness checks. This also has to be done *before* templates # are applied to the targets. Since we're doing that part rather # early on, the target inheritance feature is a bit restricted at # the moment. However, this will be addressed in a little(?) while. # src_prefix := load_function := properties_deferred_l := properties_deferred_r := # Fetches. properties := $(PROPS_FETCHES_SINGLE) properties_now_l := $(PROPS_FETCHES_ACCUMULATE_L) properties_now_r := $(PROPS_FETCHES_ACCUMULATE_R) properties_deferred := $(PROPS_FETCHES_DEFERRED) $(foreach trg, $(_ALL_FETCHES),$(evalval def_inherit)) ## Patches. - not implemented yet. #properties := $(PROPS_PATCHES_SINGLE) #properties_now_l := $(PROPS_PATCHES_ACCUMULATE_L) #properties_now_r := $(PROPS_PATCHES_ACCUMULATE_R) #properties_deferred := $(PROPS_PATCHES_DEFERRED) #$(foreach trg, $(_ALL_PATCHES),$(evalval def_inherit)) # Programs and build programs. properties := $(PROPS_PROGRAMS_SINGLE) properties_now_l := $(PROPS_PROGRAMS_ACCUMULATE_L) properties_now_r := $(PROPS_PROGRAMS_ACCUMULATE_R) properties_deferred := $(PROPS_PROGRAMS_DEFERRED) $(foreach trg, $(_ALL_BLDPROGS) $(_ALL_PROGRAMS),$(evalval def_inherit)) # Libraries and import libraries. properties := $(PROPS_LIBRARIES_SINGLE) properties_now_l := $(PROPS_LIBRARIES_ACCUMULATE_L) properties_now_r := $(PROPS_LIBRARIES_ACCUMULATE_R) properties_deferred := $(PROPS_LIBRARIES_DEFERRED) if1of ($(KBUILD_TARGET), nt os2 win) $(foreach trg, $(_ALL_LIBRARIES) $(_ALL_IMPORT_LIBS),$(evalval def_inherit)) else $(foreach trg, $(_ALL_LIBRARIES),$(evalval def_inherit)) endif # DLLs. properties := $(PROPS_DLLS_SINGLE) properties_now_l := $(PROPS_DLLS_ACCUMULATE_L) properties_now_r := $(PROPS_DLLS_ACCUMULATE_R) properties_deferred := $(PROPS_DLLS_DEFERRED) if1of ($(KBUILD_TARGET), nt os2 win) $(foreach trg, $(_ALL_DLLS),$(evalval def_inherit)) else $(foreach trg, $(_ALL_DLLS) $(_ALL_IMPORT_LIBS),$(evalval def_inherit)) endif # System modules. properties := $(PROPS_SYSMODS_SINGLE) properties_now_l := $(PROPS_SYSMODS_ACCUMULATE_L) properties_now_r := $(PROPS_SYSMODS_ACCUMULATE_R) properties_deferred := $(PROPS_SYSMODS_DEFERRED) $(foreach trg, $(_ALL_SYSMODS),$(evalval def_inherit)) # Misc binaries. properties := $(PROPS_MISCBINS_SINGLE) properties_now_l := $(PROPS_MISCBINS_ACCUMULATE_L) properties_now_r := $(PROPS_MISCBINS_ACCUMULATE_R) properties_deferred := $(PROPS_MISCBINS_DEFERRED) $(foreach trg, $(_ALL_MISCBINS),$(evalval def_inherit)) # Installs. properties := $(PROPS_INSTALLS_SINGLE) properties_now_l := $(PROPS_INSTALLS_ACCUMULATE_L) properties_now_r := $(PROPS_INSTALLS_ACCUMULATE_R) properties_deferred := $(PROPS_INSTALLS_DEFERRED) $(foreach trg, $(_ALL_INSTALLS),$(evalval def_inherit)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done target inheritance) endif # # Template Inheritance. # # This is much the same as with target inheritance, except we cannot # restrict the properties involved since we haven't got a clue which # target platforms/archs are using them. But, we can drop the instance # expansion we're doing for targets since there won't be any more # changes to either the source nor the target templates beyond this # exercise. # src_prefix := TEMPLATE_ load_function := def_templates_load_function properties := properties_now_l := properties_now_r := properties_deferred := $(PROPS_SINGLE) $(PROPS_DEFERRED) properties_deferred_l := $(PROPS_ACCUMULATE_L) properties_deferred_r := $(PROPS_ACCUMULATE_R) $(foreach trg, $(addprefix TEMPLATE_,$(_TEMPLATES)),$(evalval def_inherit)) # done inheriting. src_prefix := load_function := properties := properties_now_l := properties_now_r := properties_deferred := properties_deferred_l := properties_deferred_r := ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done template inheritance) endif # # Template/Target Expansion. # # Extend all targets with the values from the template. Doing this up front # allows more generic code and less mess down in the pass 2 target handling. # However it does eat a good deal of memory. # define def_inherit_template_workaround_target local _tmpl := $(firstword $($(target)_TEMPLATE) $(TEMPLATE)) local _bld_type := $(firstword $($(target)_BLD_TYPE) $(TEMPLATE_$(_tmpl)_BLD_TYPE) $(KBUILD_TYPE)) local _bld_trg := $(firstword $($(target)_BLD_TRG) $(TEMPLATE_$(_tmpl)_BLD_TRG) $(KBUILD_TARGET)) local _bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(TEMPLATE_$(_tmpl)_BLD_TRG_ARCH) $(KBUILD_TARGET_ARCH)) local _bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(TEMPLATE_$(_tmpl)_BLD_TRG_CPU) $(KBUILD_TARGET_CPU)) $(kb-exp-tmpl 1,$(target),$(_bld_trg),$(_bld_trg_arch),$(_bld_trg_cpu),$(_bld_type)) endef # def_inherit_template_workaround_target #$(kb-exp-tmpl 1,$(_ALL_TARGET_TARGETS),$(KBUILD_TARGET),$(KBUILD_TARGET_ARCH),$(KBUILD_TARGET_CPU),$(KBUILD_TYPE)) $(foreach target,$(_ALL_TARGET_TARGETS),$(evalval def_inherit_template_workaround_target)) define def_inherit_template_workaround_host local _tmpl := $(firstword $($(target)_TEMPLATE) $(TEMPLATE)) local _bld_type := $(firstword $($(target)_BLD_TYPE) $(TEMPLATE_$(_tmpl)_BLD_TYPE) $(KBUILD_TYPE)) local _bld_trg := $(firstword $($(target)_BLD_TRG) $(TEMPLATE_$(_tmpl)_BLD_TRG) $(KBUILD_HOST)) local _bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(TEMPLATE_$(_tmpl)_BLD_TRG_ARCH) $(KBUILD_HOST_ARCH)) local _bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(TEMPLATE_$(_tmpl)_BLD_TRG_CPU) $(KBUILD_HOST_CPU)) $(kb-exp-tmpl 1,$(target),$(_bld_trg),$(_bld_trg_arch),$(_bld_trg_cpu),$(_bld_type)) endef # def_inherit_template_workaround_target #$(kb-exp-tmpl 1,$(_ALL_HOST_TARGETS),$(KBUILD_HOST),$(KBUILD_HOST_ARCH),$(KBUILD_HOST_CPU),$(KBUILD_TYPE)) $(foreach target,$(_ALL_HOST_TARGETS),$(evalval def_inherit_template_workaround_host)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done template/target expansion) endif # # Include tools, sdks and units. # # The first part of this exercise is to figure out which TOOLS and SDKS # that should be included. # _TOOLS := $(TOOL.$(KBUILD_TARGET)) $(TOOL.$(KBUILD_TARGET_ARCH)) $(TOOL.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(TOOL.$(KBUILD_HOST)) $(TOOL.$(KBUILD_HOST_ARCH)) $(TOOL.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \ $(TOOL) _SDKS := $(SDKS.$(KBUILD_TARGET)) $(SDKS.$(KBUILD_TARGET_ARCH)) $(SDKS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(SDKS.$(KBUILD_HOST)) $(SDKS.$(KBUILD_HOST_ARCH)) $(SDKS.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \ $(SDKS.$(KBUILD_TYPE)) \ $(SDKS) _USES := $(USES.$(KBUILD_TARGET)) $(USES.$(KBUILD_TARGET_ARCH)) $(USES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) \ $(USES.$(KBUILD_HOST)) $(USES.$(KBUILD_HOST_ARCH)) $(USES.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) \ $(USES.$(KBUILD_TYPE)) \ $(USES) define def_tools_sdks_target_source $(eval _TOOLS += $(foreach prop, $(PROPS_TOOLS), \ $($(source)_$(prop).$(_bld_trg)) \ $($(target)_$(source)_$(prop).$(_bld_trg)) \ $($(source)_$(prop).$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_$(source)_$(prop).$(_bld_trg).$(_bld_trg_arch)) \ $($(source)_$(prop).$(_bld_trg_arch)) \ $($(target)_$(source)_$(prop).$(_bld_trg_arch)) \ $($(source)_$(prop)) \ $($(target)_$(source)_$(prop)))) $(eval _SDKS += \ $($(source)_SDKS.$(_bld_trg)) \ $($(target)_$(source)_SDKS.$(_bld_trg)) \ $($(source)_SDKS.$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_$(source)_SDKS.$(_bld_trg).$(_bld_trg_arch)) \ $($(source)_SDKS.$(_bld_trg_arch)) \ $($(target)_$(source)_SDKS.$(_bld_trg_arch)) \ $($(source)_SDKS.$(KBUILD_TYPE)) \ $($(target)_$(source)_SDKS.$(KBUILD_TYPE)) \ $($(source)_SDKS) \ $($(target)_$(source)_SDKS)) $(eval _USES += \ $($(source)_USES.$(_bld_trg)) \ $($(target)_$(source)_USES.$(_bld_trg)) \ $($(source)_USES.$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_$(source)_USES.$(_bld_trg).$(_bld_trg_arch)) \ $($(source)_USES.$(_bld_trg_arch)) \ $($(target)_$(source)_USES.$(_bld_trg_arch)) \ $($(source)_USES.$(KBUILD_TYPE)) \ $($(target)_$(source)_USES.$(KBUILD_TYPE)) \ $($(source)_USES) \ $($(target)_$(source)_USES)) endef # def_tools_sdks_target_source $(eval-opt-var def_tools_sdks_target_source) define def_tools_sdks_target local _bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE)) local _bld_trg := $(firstword $($(target)_BLD_TRG) $(bld_trg)) local _bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(bld_trg_arch)) local _bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(bld_trg_cpu)) $(eval _TOOLS += $(foreach prop, $(PROPS_TOOLS), \ $($(target)_$(prop).$(_bld_trg)) \ $($(target)_$(prop).$(_bld_trg_arch)) \ $($(target)_$(prop).$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_$(prop)))) $(eval _SDKS += \ $($(target)_SDKS.$(_bld_trg)) \ $($(target)_SDKS.$(_bld_trg_arch)) \ $($(target)_SDKS.$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_SDKS)) $(eval _USES += \ $($(target)_USES.$(_bld_trg)) \ $($(target)_USES.$(_bld_trg_arch)) \ $($(target)_USES.$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_USES)) $(foreach source, \ $($(target)_SOURCES.$(_bld_trg)) \ $($(target)_SOURCES.$(_bld_trg_arch)) \ $($(target)_SOURCES.$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_SOURCES.$(_bld_trg_cpu)) \ $($(target)_SOURCES.$(_bld_type)) \ $($(target)_SOURCES) \ , $(evalval def_tools_sdks_target_source)) endef # def_tools_sdks_target $(eval-opt-var def_tools_sdks_target) define def_tools_srcname_target local _bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE)) local _bld_trg := $(firstword $($(target)_BLD_TRG) $(bld_trg)) local _bld_trg_arch := $(firstword $($(target)_BLD_TRG_ARCH) $(bld_trg_arch)) local _bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(bld_trg_cpu)) $(foreach source, $(notdir\ $($(target)_SOURCES.$(_bld_trg)) \ $($(target)_SOURCES.$(_bld_trg_arch)) \ $($(target)_SOURCES.$(_bld_trg).$(_bld_trg_arch)) \ $($(target)_SOURCES.$(_bld_trg_cpu)) \ $($(target)_SOURCES.$(_bld_type)) \ $($(target)_SOURCES) \ ), $(evalval def_tools_sdks_target_source)) endef # def_tools_srcname_target $(eval-opt-var def_tools_srcname_target) bld_trg := $(KBUILD_TARGET) bld_trg_arch := $(KBUILD_TARGET_ARCH) bld_trg_cpu := $(KBUILD_TARGET_CPU) $(foreach target, $(_ALL_TARGET_TARGETS), $(evalval def_tools_sdks_target)) $(foreach target, $(_ALL_SRCNAME_TARGETS), $(evalval def_tools_srcname_target)) bld_trg := $(KBUILD_HOST) bld_trg_arch := $(KBUILD_HOST_ARCH) bld_trg_cpu := $(KBUILD_HOST_CPU) $(foreach target, $(_ALL_HOST_TARGETS), $(evalval def_tools_sdks_target)) _TOOLS := $(sort $(_TOOLS)) _SDKS := $(sort $(_SDKS)) ## Tool load function. # @param loading The tool name define def_tools_load_function ifndef TOOL_$(loading) TOOL_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_TOOL_PATHS) $(KBUILD_PATH)/tools $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk))) ifeq ($(TOOL_$(loading)_KMK_FILE),) $(error kBuild: Cannot find include file for the tool '$(loading)'! Searched: $(KBUILD_TOOL_PATHS) $(KBUILD_PATH)/tools $(KBUILD_DEFAULT_PATHS)) endif include $(TOOL_$(loading)_KMK_FILE) ifndef TOOL_$(loading) $(warning kBuild: TOOL_$(loading) was not defined by $(TOOL_$(loading)_KMK_FILE)!) endif endif endef # def_tools_include ## SDK load function. # @param loading The tool name define def_sdk_load_function ifndef SDK_$(loading) SDK_$(loading)_KMK_FILE := $(firstword $(foreach path, $(KBUILD_SDK_PATHS) $(KBUILD_PATH)/sdks $(KBUILD_DEFAULT_PATHS), $(wildcard $(path)/$(loading).kmk))) ifeq ($(SDK_$(loading)_KMK_FILE),) $(error kBuild: Cannot find include file for the SDK '$(loading)'! Searched: $(KBUILD_SDK_PATHS) $(KBUILD_PATH)/sdks $(KBUILD_DEFAULT_PATHS)) endif include $(SDK_$(loading)_KMK_FILE) ifndef SDK_$(loading) $(warning kBuild: SDK_$(loading) was not defined by $(SDK_$(loading)_KMK_FILE)!) endif endif endef # def_sdk_load_function properties := properties_now_l := properties_now_r := properties_deferred := $(PROPS_SINGLE) $(PROPS_DEFERRED) properties_deferred_l := $(PROPS_ACCUMULATE_L) properties_deferred_r := $(PROPS_ACCUMULATE_R) src_prefix := SDK_ load_function := def_sdk_load_function $(foreach trg, $(addprefix SDK_,$(_SDKS)), $(evalval def_inherit)) properties_deferred := $(PROPS_SINGLE) $(PROPS_DEFERRED) $(PROPS_TOOLS_ONLY) src_prefix := TOOL_ load_function := def_tools_load_function $(foreach trg, $(addprefix TOOL_,$(_TOOLS)), $(evalval def_inherit)) # done inheriting. src_prefix := load_function := properties := properties_now_l := properties_now_r := properties_deferred := properties_deferred_l := properties_deferred_r := # No inheriting for the uses, they're just global 'code'. $(foreach loading, $(_USES), $(evalval def_unit_load_function)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done tools + sdks + units) endif kbuild-2695/kBuild/rules.kmk0000644000000000000000000000270312247157310014505 0ustar rootroot# $Id: rules.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - File included at top of makefile. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef PATH_KBUILD # Usual location. include $(PATH_KBUILD)/header.kmk else # Default location. include $(DEPTH)/kBuild/header.kmk endif # PATH_KBUILD is defined now. include $(PATH_KBUILD)/footer.kmk kbuild-2695/kBuild/footer.kmk0000644000000000000000000003501412247157310014652 0ustar rootroot# $Id: footer.kmk 2537 2011-08-02 19:44:43Z bird $ ## @file # kBuild - File included at bottom of a makefile. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifndef __footer_kmk__ # start-of-file-content ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, start of footer.kmk) _KBUILD_TS_FOOTER_START := $(_KBUILD_TS_PREV) endif # # Variables. # (Some of these need initialization before including definitions using them.) # # All targets of each types. _ALL_BLDPROGS := $(BLDPROGS) $(BLDPROGS.$(KBUILD_HOST)) $(BLDPROGS.$(KBUILD_HOST).$(KBUILD_HOST_ARCH)) $(BLDPROGS.$(KBUILD_HOST_ARCH)) $(BLDPROGS.$(KBUILD_HOST_CPU)) $(BLDPROGS.$(KBUILD_TYPE)) _ALL_LIBRARIES := $(LIBRARIES) $(LIBRARIES.$(KBUILD_TARGET)) $(LIBRARIES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_ARCH)) $(LIBRARIES.$(KBUILD_TARGET_CPU)) $(LIBRARIES.$(KBUILD_TYPE)) _ALL_IMPORT_LIBS := $(IMPORT_LIBS) $(IMPORT_LIBS.$(KBUILD_TARGET)) $(IMPORT_LIBS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_ARCH)) $(IMPORT_LIBS.$(KBUILD_TARGET_CPU)) $(IMPORT_LIBS.$(KBUILD_TYPE)) _ALL_DLLS := $(DLLS) $(DLLS.$(KBUILD_TARGET)) $(DLLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_ARCH)) $(DLLS.$(KBUILD_TARGET_CPU)) $(DLLS.$(KBUILD_TYPE)) _ALL_PROGRAMS := $(PROGRAMS) $(PROGRAMS.$(KBUILD_TARGET)) $(PROGRAMS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_ARCH)) $(PROGRAMS.$(KBUILD_TARGET_CPU)) $(PROGRAMS.$(KBUILD_TYPE)) _ALL_SYSMODS := $(SYSMODS) $(SYSMODS.$(KBUILD_TARGET)) $(SYSMODS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_ARCH)) $(SYSMODS.$(KBUILD_TARGET_CPU)) $(SYSMODS.$(KBUILD_TYPE)) _ALL_MISCBINS := $(MISCBINS) $(MISCBINS.$(KBUILD_TARGET)) $(MISCBINS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_ARCH)) $(MISCBINS.$(KBUILD_TARGET_CPU)) $(MISCBINS.$(KBUILD_TYPE)) _ALL_OTHERS := $(OTHERS) $(OTHERS.$(KBUILD_TARGET)) $(OTHERS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_ARCH)) $(OTHERS.$(KBUILD_TARGET_CPU)) $(OTHERS.$(KBUILD_TYPE)) _ALL_INSTALLS := $(INSTALLS) $(INSTALLS.$(KBUILD_TARGET)) $(INSTALLS.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_ARCH)) $(INSTALLS.$(KBUILD_TARGET_CPU)) $(INSTALLS.$(KBUILD_TYPE)) _ALL_FETCHES := $(FETCHES) $(FETCHES.$(KBUILD_TARGET)) $(FETCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_ARCH)) $(FETCHES.$(KBUILD_TARGET_CPU)) $(FETCHES.$(KBUILD_TYPE)) _ALL_PATCHES := $(PATCHES) $(PATCHES.$(KBUILD_TARGET)) $(PATCHES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_ARCH)) $(PATCHES.$(KBUILD_TARGET_CPU)) $(PATCHES.$(KBUILD_TYPE)) # all targets. _ALL_TARGETS = \ $(_ALL_FETCHES) \ $(_ALL_PATCHES) \ $(_ALL_BLDPROGS) \ $(_ALL_LIBRARIES) \ $(_ALL_IMPORT_LIBS) \ $(_ALL_DLLS) \ $(_ALL_PROGRAMS) \ $(_ALL_SYSMODS) \ $(_ALL_MISCBINS) \ $(_ALL_INSTALLS) \ $(_ALL_OTHERS) # all $(KBUILD_TARGET) targets. _ALL_TARGET_TARGETS = \ $(_ALL_FETCHES) \ $(_ALL_PATCHES) \ $(_ALL_LIBRARIES) \ $(_ALL_IMPORT_LIBS) \ $(_ALL_DLLS) \ $(_ALL_PROGRAMS) \ $(_ALL_SYSMODS) \ $(_ALL_MISCBINS) \ $(_ALL_INSTALLS) \ $(_ALL_OTHERS) # all $(KBUILD_HOST) targets. _ALL_HOST_TARGETS = \ $(_ALL_BLDPROGS) # all targets making use of srcname. _ALL_SRCNAME_TARGETS = \ $(_ALL_FETCHES) \ $(_ALL_PATCHES) # Dependency files. (currently not on target level, only this global stuff) _DEPFILES := $(DEPFILES) $(DEPFILES.$(KBUILD_TARGET)) $(DEPFILES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) $(DEPFILES.$(KBUILD_TARGET_ARCH)) $(DEPFILES.$(KBUILD_TARGET_CPU)) $(DEPFILES.$(KBUILD_TYPE)) # included dependency files. _DEPFILES_INCLUDED := # All kind of output files except for _OBJS and _DEPFILES. # Compiling or linking definition outputting other things that $@ and any # required dependency file must add those output files to this variable. _OUT_FILES := # Files which only requires cleaning up. _CLEAN_FILES := # all of a type _OBJS := _FETCHES := _DOWNLOADS:= _UNPACKS := _PATCHES := _UNFETCHES:= _BLDPROGS := _LIBS := _DLLS := _PROGRAMS := _SYSMODS := _MISCBINS := _STAGE_FILES := _STAGE_DIRS := _INSTALLS := _INSTALLS_FILES := _INSTALLS_DIRS := _DEBUG_STAGE_FILES := _DEBUG_STAGE_DIRS := _DEBUG_INSTALL_FILES := _DEBUG_INSTALL_DIRS := _OTHERS := _PACKING := _DIRS := $(PATH_TARGET)/ $(PATH_TARGET) $(BLDDIRS) _IMPORT_LIBS := # Implicit targets added while processing other targets (usually by units). _ALL_INSTALLS_IMPLICIT := # misc pass_prev := # # Footer macros # ## Figure out the tool for a target. # @param $1 normalized target. # @param $2 tooltype. # @param bld_trg build target. # @param bld_trg_arch build target architecture. # @param bld_type build target type. if 0 _TARGET_TOOL = $(strip $(firstword \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_$(2)TOOL.$(bld_trg)) \ $($(1)_$(2)TOOL) \ $($(1)_TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_TOOL.$(bld_trg)) \ $($(1)_TOOL) \ $($(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(2)TOOL.$(bld_trg)) \ $($(2)TOOL) \ $(TOOL.$(bld_trg).$(bld_trg_arch)) \ $(TOOL.$(bld_trg)) \ $(TOOL) \ )) else _TARGET_TOOL = $(strip $(firstword \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_$(2)TOOL.$(bld_trg).$(bld_type)) \ $($(1)_$(2)TOOL.$(bld_trg_arch)) \ $($(1)_$(2)TOOL.$(bld_trg)) \ $($(1)_$(2)TOOL.$(bld_type)) \ $($(1)_$(2)TOOL) \ $($(1)_TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(1)_TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(1)_TOOL.$(bld_trg).$(bld_type)) \ $($(1)_TOOL.$(bld_trg_arch)) \ $($(1)_TOOL.$(bld_trg)) \ $($(1)_TOOL.$(bld_type)) \ $($(1)_TOOL) \ $($(2)TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(2)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(2)TOOL.$(bld_trg).$(bld_type)) \ $($(2)TOOL.$(bld_trg_arch)) \ $($(2)TOOL.$(bld_trg)) \ $($(2)TOOL.$(bld_type)) \ $($(2)TOOL) \ $(TOOL.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $(TOOL.$(bld_trg).$(bld_trg_arch)) \ $(TOOL.$(bld_trg).$(bld_type)) \ $(TOOL.$(bld_trg_arch)) \ $(TOOL.$(bld_trg)) \ $(TOOL.$(bld_type)) \ $(TOOL) \ )) endif ## Figure out the actual name of an installed file. # @param $1 The file to install. # @param $2 The target name. # @param $3 The _INST value (can be empty). # @param $4 The installation root directory. _INSTALL_FILE = $(patsubst %/,%/$(notdir $(1)),$(if $(3),$(4)/$(3),$(4)/)) ## # Function for getting the first defined propert value. # # @param 1 The property name. # @param 2 The default property name, empty if none. # @param 3 What to return if all variables are empty. (optional) # @note Implicit parameters: target, bld_trg, bld_trg_arch, bld_trg_cpu, bld_type. # @returns Expanded property value. # define def_fn_prop_get_first_defined local .RETURN := $(firstdefined \ $(target)_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(target)_$(1).$(bld_trg).$(bld_trg_arch) \ $(target)_$(1).$(bld_trg).$(bld_type) \ $(target)_$(1).$(bld_trg_cpu) \ $(target)_$(1).$(bld_trg_arch) \ $(target)_$(1).$(bld_trg) \ $(target)_$(1).$(bld_type) \ $(target)_$(1) \ ) ifeq ($(.RETURN),) ifneq ($(2),) local .RETURN := $(firstdefined \ $(2).$(bld_trg).$(bld_trg_arch).$(bld_type) \ $(2).$(bld_trg).$(bld_trg_arch) \ $(2).$(bld_trg).$(bld_type) \ $(2).$(bld_trg_cpu) \ $(2).$(bld_trg_arch) \ $(2).$(bld_trg) \ $(2).$(bld_type) \ $(2) \ 3 \ ) else local .RETURN := $(firstdefined \ kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type) \ kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch) \ kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_type) \ kBuildGlobalDefaults_$(1).$(bld_trg_cpu) \ kBuildGlobalDefaults_$(1).$(bld_trg_arch) \ kBuildGlobalDefaults_$(1).$(bld_trg) \ kBuildGlobalDefaults_$(1).$(bld_type) \ kBuildGlobalDefaults_$(1) \ 3 \ ) endif endif local .RETURN := $(strip $($(.RETURN))) endef # def_fn_prop_get_first_defined ## # Function for getting the first property value (ignoring empty defines). # # @param 1 The property name. # @param 2 The default property name, empty if none. # @param 3 What to return if all variables are empty. (optional) # @note Implicit parameters: target, bld_trg, bld_trg_arch, bld_trg_cpu, bld_type. # @returns First word. # define def_fn_prop_get_first_word local .RETURN := $(firstword \ $($(target)_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_$(1).$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(1).$(bld_trg).$(bld_type)) \ $($(target)_$(1).$(bld_trg_cpu)) \ $($(target)_$(1).$(bld_trg_arch)) \ $($(target)_$(1).$(bld_trg)) \ $($(target)_$(1).$(bld_type)) \ $($(target)_$(1)) \ ) ifeq ($(.RETURN),) ifneq ($(2),) local .RETURN := $(firstword \ $($(2).$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(2).$(bld_trg).$(bld_trg_arch)) \ $($(2).$(bld_trg).$(bld_type)) \ $($(2).$(bld_trg_cpu)) \ $($(2).$(bld_trg_arch)) \ $($(2).$(bld_trg)) \ $($(2).$(bld_type)) \ $($(2)) \ $(3) \ ) else local .RETURN := $(firstword \ $(kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_trg_arch)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg).$(bld_type)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg_cpu)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg_arch)) \ $(kBuildGlobalDefaults_$(1).$(bld_trg)) \ $(kBuildGlobalDefaults_$(1).$(bld_type)) \ $(kBuildGlobalDefaults_$(1)) \ $(3) \ ) endif endif endef # def_fn_prop_get_first_word # # The main body. # include $(KBUILD_PATH)/footer-inherit-uses-tools.kmk include $(KBUILD_PATH)/footer-pass1.kmk include $(KBUILD_PATH)/footer-pass2-fetches.kmk include $(KBUILD_PATH)/footer-pass2-patches.kmk include $(KBUILD_PATH)/footer-pass2-compiling-targets.kmk include $(KBUILD_PATH)/footer-pass2-installs.kmk include $(KBUILD_PATH)/footer-misc.kmk include $(KBUILD_PATH)/footer-passes.kmk # # THE MAIN RULES # all_recursive: $(pass_prev) rebuild: clean + $(MAKE) -f $(firstword $(MAKEFILE_LIST)) all_recursive # @todo make this a non-default pass! uninstall:: $(RM) -f -- $(_INSTALLS_FILES) install:: pass_installs # misc shortcuts (use secondary expansion here to save strcache[file] space). targets: bldprogs libraries dlls programs sysmods miscbins others installs objects: $$(_OBJS) bldprogs: $$(_BLDPROGS) libraries: $$(_LIBS) $$(_IMPORT_LIBS) $$(_OTHER_LIBRARIES) dlls: $$(_DLLS) programs: $$(_PROGRAMS) sysmods: $$(_SYSMODS) miscbins: $$(_MISCBINS) others: $$(_OTHERS) stagings: $$(_INSTALLS) $$(_STAGE_DIRS) $$(_STAGE_FILES) installs: $$(_INSTALLS_DIRS) $$(_INSTALLS_FILES) install-debug: $$(_DEBUG_INSTALL_DIRS) $$(_DEBUG_INSTALL_FILES) # # kBuild debugging stuff. # ## @todo this doesn't work. Move to a debug unit and expand it. show_targets: @$(foreach target, $(_ALL_TARGETS),\ @$(ECHO) "target: $(target)" $(NLTAB)\ @$(ECHO) " $(target)_0_OUTDIR=$($(target)_0_OUTDIR)" $(NLTAB)\ @$(ECHO) " $(target)_1_TARGET=$($(target)_1_TARGET)" $(NLTAB)\ @$(ECHO) " INSTARGET_$(target)=$(INSTARGET_$(target))" $(NLTAB)\ $(foreach prop,$(PROPS_SINGLE) $(PROPS_ACCUMULATE_L) $(PROPS_ACCUMULATE_R) 2_OBJS CLEAN, \ $(eval _tmp:=$(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET))) \ $(if $($(target)_$(prop).$(_tmp)),\ @$(ECHO) " $(target)_$(prop).$(_tmp)=$($(target)_$(prop).$(_tmp))" $(NLTAB)) \ $(if $($(target)_$(prop)), $(NLTAB)@$(ECHO) " $(target)_$(prop)=$($(target)_$(prop))" $(NLTAB)) \ )\ $(foreach prop,$(PROPS_DEFERRED), \ $(eval _tmp:=$(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET))) \ $(if $(value $(target)_$(prop).$(_tmp)),\ @$(ECHO) ' $(target)_$(prop).$(_tmp)=$(value $(TARGET)_$(prop).$(_tmp))' $(NLTAB)) \ $(if $(value $(target)_$(prop)), $(NLTAB)@$(ECHO) ' $(target)_$(prop)=$(value $(target)_$(prop))' $(NLTAB)) \ )) # # Include dependency files. # ifdef _DEPFILES # TODO: first works the second doesn't, provided _KB_INCLUDE_DEPS is undefined: # if "$(_KB_INCLUDE_DEPS)" == "1" # if $(_KB_INCLUDE_DEPS) == "1" ifdef KB_HAVE_INCLUDEDEP_QUEUE includedep-queue $(_DEPFILES) else $(foreach dep, $(_DEPFILES), $(eval includedep $(dep))) endif endif ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, end of footer.kmk) _KBUILD_TS_FOOTER_END := $(_KBUILD_TS_PREV) ifneq ($(KBUILD_PROFILE_SELF),0) $(info prof: ALL=$(words $(_ALL_TARGETS)) BLDPROGS=$(words $(_ALL_BLDPROGS)) LIBRARIES=$(words $(_ALL_LIBRARIES)) IMPORT_LIBS=$(words $(IMPORT_LIBS)) DLLS=$(words $(DLLS)) PROGRAMS=$(words $(_ALL_PROGRAMS)) ) $(info prof: SYSMODS=$(words $(_ALL_SYSMODS)) MISCBINS=$(words $(_ALL_MISCBINS)) OTHERS=$(words $(_ALL_OTHERS)) INSTALLS=$(words $(_ALL_INSTALLS)) FETCHES=$(words $(_ALL_FETCHES)) PACKING=$(words $(_PACKING)) TESTING=$(words $(TESTING)) ) $(info prof: DIRS=$(words $(_DIR_ALL)) TOOLS=$(words $(_TOOLS)) SDKS=$(words $(_SDKS)) USES=$(words $(_USES)) OUT_FILES=$(words $(_OUT_FILES)) OBJS=$(words $(_OBJS)) CLEAN_FILES=$(words $(CLEAN_FILES) $(OTHER_CLEAN)) ) $(info prof: DEPFILES_INCLUDED=$(words $(_DEPFILES_INCLUDED)) DEPFILES=$(words $(_DEPFILES)) MAKEFILES=$(words $(MAKEFILE_LIST)) ) endif endif # end-of-file-content __footer_kmk__ := target endif # !defined(__footer_kmk__) kbuild-2695/kBuild/doc/0000755000000000000000000000000012247157310013412 5ustar rootrootkbuild-2695/kBuild/doc/QuickReference-kBuild.txt0000644000000000000000000004006312247157310020261 0ustar rootroot kBuild Quick Reference ====================== This is an attempt at summarizing the magic of kBuild makefiles. The anatomy of a kBuild Makefile -------------------------------- A typical makefile:: # $Id: QuickReference-kBuild.txt 2345 2009-04-19 23:47:42Z bird $ ## @file # Makefile description. # # # Copyright (c) year name # License, disclaimer and other legal text. # SUB_DEPTH = ../.. include $(KBUILD_PATH)/subheader.kmk # # Include sub-makefiles. # include $(PATH_CURRENT)/subdir1/Makefile.kmk include $(PATH_CURRENT)/subdir2/Makefile.kmk # # Global variables. # MYPREFIX_SOMETHING = or another # # Target lists. # DLLS += mydll PROGRAMS += myprogs # # mydll - description. # mydll_TEMPLATE = MYDLL mydll_SOURCES = mydll.c mydll_SOURCES.win = $(mydll_0_OUTDIR)/mydll.def # # myprog - description. # myprog_TEMPLATE = MYPROG myprog_SOURCES = myprog.c # # Custom rules (optional of course). # $$(mydll_0_OUTDIR)/mydll.def: $(APPEND) -t $@ LIBRARY mydll.dll $(APPEND) $@ EXPORTS $(APPEND) $@ ' myfunction' include $(FILE_KBUILD_SUB_FOOTER) Target lists ------------ +-+-------------------+-------------------------------------------------------+ |#| Name | Description | +=+===================+=======================================================+ |1| ``BLDPROGS`` | Build programs, targets the host platform. | +-+-------------------+-------------------------------------------------------+ |2| ``LIBRARIES`` | Libraries (not shared). | +-+-------------------+-------------------------------------------------------+ |3| ``IMPORT_LIBS`` | Import libraries or stub shared libraries. | +-+-------------------+-------------------------------------------------------+ |4| ``DLLS`` | DLLs, Shared Libraries, DYLIBs, etc. | +-+-------------------+-------------------------------------------------------+ |5| ``PROGRAMS`` | Executable programs. | +-+-------------------+-------------------------------------------------------+ |6| ``SYSMODS`` | System modules (kexts, kernel modules, drivers, etc). | +-+-------------------+-------------------------------------------------------+ |7| ``MISCBINS`` | Miscellanceous binaries like BIOS images and such. | +-+-------------------+-------------------------------------------------------+ |8| ``INSTALLS`` | Things to install. [1]_ | +-+-------------------+-------------------------------------------------------+ |9| ``FETCHES`` | Things to fetch. [1]_ | +-+-------------------+-------------------------------------------------------+ |a| ``OTHERS`` | List of targets made during the others pass. | +-+-------------------+-------------------------------------------------------+ Target properties ----------------- The first column indicates the kind of property, S=Single, D=Deferred, Ar=Accumlate-Right and Al=Accumulate-Left. The third column should be cross referenced with the first column in the target list table above. +--+-------------------+-------+----------------------------------------------+ |K | Name | Which | Description | +==+===================+=======+==============================================+ |S | ``ARLIBSUFF`` | 2 | | +--+-------------------+-------+----------------------------------------------+ |S | ``ARTOOL`` | 2 | | +--+-------------------+-------+----------------------------------------------+ |S | ``ASOBJSUFF`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``ASTOOL`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``BINSUFF`` | 7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``BLD_TRG`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``BLD_TRG_ARCH`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``BLD_TRG_CPU`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``BLD_TYPE`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``COBJSUFF`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``CTOOL`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``CXXOBJSUFF`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``CXXTOOL`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``DLLSUFF`` | 34 | | +--+-------------------+-------+----------------------------------------------+ |S | ``EXESUFF`` | 15 | | +--+-------------------+-------+----------------------------------------------+ |S | ``FETCHDIR`` | 9 | | +--+-------------------+-------+----------------------------------------------+ |S | ``FETCHTOOL`` | 9 | | +--+-------------------+-------+----------------------------------------------+ |S | ``GID`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``INST`` | 1-9 | | +--+-------------------+-------+----------------------------------------------+ |S | ``LDTOOL`` | 13-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``LIBSUFF`` | 234 | | +--+-------------------+-------+----------------------------------------------+ |S | ``MODE`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``NOINST`` | 1-8 | | +--+-------------------+-------+----------------------------------------------+ |S | ``OBJCOBJSUFF`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``OBJCTOOL`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``OBJSUFF`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``PATCHTOOL`` | 9 | | +--+-------------------+-------+----------------------------------------------+ |S | ``RCOBJSUFF`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``RCTOOL`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``SYSSUFF`` | 6 | | +--+-------------------+-------+----------------------------------------------+ |S | ``TEMPLATE`` | 1-9 | | +--+-------------------+-------+----------------------------------------------+ |S | ``TOOL`` | 1-9 | | +--+-------------------+-------+----------------------------------------------+ |S | ``UID`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |S | ``UNPACKTOOL`` | 9 | | +--+-------------------+-------+----------------------------------------------+ |D | ``INSTALLER`` | 1-8 | | +--+-------------------+-------+----------------------------------------------+ |D | ``INSTFUN`` | 1-8 | | +--+-------------------+-------+----------------------------------------------+ |D | ``NAME`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |D | ``POST_CMDS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |D | ``PRE_CMDS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |D | ``SONAME`` | 13-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``ARFLAGS`` | 2 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``ASDEFS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``ASFLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``CDEFS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``CFLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``CXXDEFS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``CXXFLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``DEFS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``DEPS`` | 1-8 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``FETCHFLAGS`` | 9 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``IDFLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``IFDLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``ISFLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``LDFLAGS`` | 13-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``LNK_DEPS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``LNK_ORDERDEPS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``OBJCDEFS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``OBJCFLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``ORDERDEPS`` | 1-8 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``PATCHFLAGS`` | 9 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``RCDEFS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``RCFLAGS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Ar| ``UNPACKFLAGS`` | 9 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``ASINCS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``BLDDIRS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``CINCS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``CLEAN`` | 1-9 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``CXXINCS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``DIRS`` | 8 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``INCS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``INTERMEDIATES`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``LIBPATH`` | 13-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``LIBS`` | 13-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``OBJCINCS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``RCINCS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``SDKS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``SOURCES`` | 1-9 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``SRC_HANDLERS`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ |Al| ``USES`` | 1-7 | | +--+-------------------+-------+----------------------------------------------+ ----- .. [1] Normally not one of the default passes. ----- :Status: $Id: QuickReference-kBuild.txt 2345 2009-04-19 23:47:42Z bird $ :Copyright: Copyright (c) 2009 knut st. osmundsen kbuild-2695/kBuild/doc/COPYING-FDL-1.30000644000000000000000000005466212247157310015364 0ustar rootroot GNU Free Documentation License Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. The "publisher" means any person or entity that distributes copies of the Document to the public. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 11. RELICENSING "Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A "Massive Multiauthor Collaboration" (or "MMC") contained in the site means any set of copyrightable works thus published on the MMC site. "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. "Incorporate" means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is "eligible for relicensing" if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. kbuild-2695/kBuild/doc/example1/0000755000000000000000000000000012247157310015126 5ustar rootrootkbuild-2695/kBuild/doc/example1/Config.kmk0000644000000000000000000000132412247157310017037 0ustar rootroot# $Id: Config.kmk 2343 2009-04-19 21:44:50Z bird $ ## @file # kBuild Example no. 1 - Config.kmk - The global configuration file. # # # The author disclaims copyright to this example script and places # it in the public domain. # # include full-legal-disclaimer.kmk # # # Some templates. # TEMPLATE_ExampleNo1Exe = For creating a program or static library for linking into a program. TEMPLATE_ExampleNo1Exe_TOOL = GCC TEMPLATE_ExampleNo1Exe_DEFS = MY_DEFINE=42 MY_OTHER_DEFINE TEMPLATE_ExampleNo1Dll = For creating a DLL/SO/DYLIB or static library for linking into a DLL/SO/DYLIB TEMPLATE_ExampleNo1Dll_EXTENDS = ExampleNo1Exe TEMPLATE_ExampleNo1Dll_EXTENDS_BY = appending TEMPLATE_ExampleNo1Dll_DEFS = MY_DLL_INDICATOR kbuild-2695/kBuild/doc/example1/Makefile.kmk0000644000000000000000000000146412247157310017354 0ustar rootroot# $Id: Makefile.kmk 2343 2009-04-19 21:44:50Z bird $ ## @file # kBuild Example no. 1 - Makefile.kmk - The top-level makefile. # # # The author disclaims copyright to this example script and places # it in the public domain. # # include full-legal-disclaimer.kmk # SUB_DEPTH = . include $(KBUILD_PATH)/subheader.kmk # # Include sub-makefiles. # include $(PATH_CURRENT)/libhello/Makefile.kmk # # The targets. # PROGRAMS += \ hello \ hellolib # # Hello world program. # hello_TEMPLATE = ExampleNo1Exe hello_SOURCES = hello.c # # A hello world variant that has some of the code in the libhello directory, # i.e. linking with a library built by the sub-makefile included above. # hellolib_TEMPLATE = ExampleNo1Exe hellolib_SOURCES = hellolib.c hellolib_LIBS = $(libhello_1_TARGET) include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/kBuild/doc/example1/hellolib.c0000644000000000000000000000055112247157310017065 0ustar rootroot/* $Id: hellolib.c 2343 2009-04-19 21:44:50Z bird $ */ /** @file * Example no. 1 - hellolib.c - Hello world program w/ lib. */ /* * The author disclaims copyright to this example code and places * it in the public domain. * * #include * */ extern int print_hello_world(void); int main() { return print_hello_world(); } kbuild-2695/kBuild/doc/example1/hello.c0000644000000000000000000000052712247157310016401 0ustar rootroot/* $Id: hello.c 2343 2009-04-19 21:44:50Z bird $ */ /** @file * Example no. 1 - hello.c - Hello world program. */ /* * The author disclaims copyright to this example code and places * it in the public domain. * * #include * */ #include int main() { printf("Hello world!\n"); return 0; } kbuild-2695/kBuild/doc/example1/libhello/0000755000000000000000000000000012247157310016720 5ustar rootrootkbuild-2695/kBuild/doc/example1/libhello/libhello.c0000644000000000000000000000063412247157310020661 0ustar rootroot/* $Id: libhello.c 2343 2009-04-19 21:44:50Z bird $ */ /** @file * Example no. 1 - libhello.c - Hello world library. */ /* * The author disclaims copyright to this example code and places * it in the public domain. * * #include * */ #include extern int print_hello_world(void); int print_hello_world(void) { printf("Hello library world!\n"); return 0; } kbuild-2695/kBuild/doc/example1/libhello/Makefile.kmk0000644000000000000000000000103012247157310021133 0ustar rootroot# $Id: Makefile.kmk 2343 2009-04-19 21:44:50Z bird $ ## @file # kBuild Example no. 1 - libhello/Makefile.kmk - The libhello sub-makefile. # # # The author disclaims copyright to this example script and places # it in the public domain. # # include full-legal-disclaimer.kmk # SUB_DEPTH = .. include $(KBUILD_PATH)/subheader.kmk # # The targets. # LIBRARIES += libhello # # The hello world library. # libhello_TEMPLATE = ExampleNo1Exe libhello_SOURCES = libhello.c ## @todo Create a DLL variant. include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/kBuild/doc/QuickReference-kmk.txt0000644000000000000000000013051712247157310017635 0ustar rootroot kmk Quick Reference =================== This is an attempt at summarizing all directives, functions, special variables, special targets, built-in commands, external commands, and ``kmk``-expressions. Since *all* the features are included, the quickness of this reference can be disputed. ;-) Directives ---------- Here is a summary of the directives ``kmk`` recognizes: Define a multi-line, recursively-expanded variable:: define variable endef Conditionally evaluate part of the makefile:: ifdef variable ifndef variable ifeq (a,b) ifeq "a" "b" ifeq 'a' 'b' ifneq (a,b) ifneq "a" "b" ifneq 'a' 'b' if1of (set-a,set-b) [1] ifn1of (set-a,set-b) [1] if expression [1] else endif Include another makefile:: include file -include file sinclude file Include another dependency file [1]_:: includedep file Define a variable, overriding any previous definition, even one from the command line:: override variable = value override variable := value override variable += value override variable <= value [1] override variable ?= value override define variable endef Tell ``kmk`` to export all variables to child processes by default:: export Tell ``kmk`` whether or not to export a particular variable to child processes:: export variable export variable = value export variable := value export variable += value export variable <= value [1] export variable ?= value unexport variable Define a variable in the local context instead of the global one [1]_:: local variable = value local variable := value local variable += value local variable <= value local variable ?= value local define variable endef Specify a search path for files matching a ``%`` pattern:: vpath pattern path Remove all search paths previously specified for pattern:: vpath pattern Remove all search paths previously specified in any vpath directive:: vpath Automatic variables ------------------- Here is a summary of the automatic variables. +-----------+-----------------------------------------------------------------+ | Variable | Description | +===========+=================================================================+ | ``$@`` | The file name of the target. | +-----------+-----------------------------------------------------------------+ | ``$<`` | The name of the first prerequisite. | +-----------+-----------------------------------------------------------------+ | ``$?`` | The names of all the prerequisites that are newer than the | | | target, with spaces between them. | +-----------+-----------------------------------------------------------------+ | ``$^`` | The names of all the prerequisites, duplicates omitted. | +-----------+-----------------------------------------------------------------+ | ``$+`` | The names of all the prerequisites, duplicates and order | | | preserved | +-----------+-----------------------------------------------------------------+ | ``$*`` | The stem with which an implicit rule matches. | +-----------+-----------------------------------------------------------------+ | ``$|`` | The name of all the order only prerequisites. | +-----------+-----------------------------------------------------------------+ | ``$(@D)`` | The directory part of ``$@``. | +-----------+-----------------------------------------------------------------+ | ``$(>`` | | Bitwise right shift. | +---------------+--------+-----------------------------------------------------+ | ``<=`` | Binary | Less or equal than. | +---------------+ +-----------------------------------------------------+ | ``<`` | | Less than. | +---------------+ +-----------------------------------------------------+ | ``>=`` | | Greater or equal than. | +---------------+ +-----------------------------------------------------+ | ``>`` | | Greater than. | +---------------+--------+-----------------------------------------------------+ | ``==`` | Binary | Equal to. | +---------------+ +-----------------------------------------------------+ | ``!=`` | | Not equal to. | +---------------+--------+-----------------------------------------------------+ | ``&`` | Binary | Bitwise AND. | +---------------+--------+-----------------------------------------------------+ | ``^`` | Binary | Bitwise XOR. | +---------------+--------+-----------------------------------------------------+ | ``|`` | Binary | Bitwise OR. | +---------------+--------+-----------------------------------------------------+ | ``&&`` | Binary | Logical AND. | +---------------+--------+-----------------------------------------------------+ | ``||`` | Binary | Logical OR. | +---------------+--------+-----------------------------------------------------+ Built-in functions ------------------ String Manipulation Functions: Replace ``from`` with ``to`` in ``text``:: $(subst from,to,text) Replace words matching ``pattern`` with ``replacement`` in ``text``:: $(patsubst pattern,replacement,text) Remove excess whitespace characters from ``string``:: $(strip string) Locate ``find`` in ``text``, returning ``find`` if found:: $(findstring find,text) Select words in ``text`` that match one of the ``pattern`` words:: $(filter pattern...,text) Select words in ``text`` that do not match any of the ``pattern`` words:: $(filter-out pattern...,text) Sort the words in ``list`` lexicographically, removing duplicates:: $(sort list) Sort the words in ``list`` lexicographically in reserve order, removing duplicates [1]_:: $(rsort list) Count the number of words in ``text``:: $(words text) Extract the ``n``\th word (one-origin) of ``text``:: $(word n,text) Returns the list of words in ``text`` from ``s`` to ``e`` (one-origin):: $(wordlist s,e,text) Extract the first word of ``names``:: $(firstword names...) Extract the last word of ``names``:: $(lastword names...) Join two parallel lists of words:: $(join list1,list2) Extract the first defined variable from ``variables``, returning its name (default) or value:: $(firstdefined variables[, name|value]) Extract the last defined variable from ``variables``, returning its name (default) or value:: $(lastdefined variables[, name|value]) Fold ``text`` to upper case [1]_:: $(toupper text) Fold ``text`` to lower case [1]_:: $(tolower text) String formatting a la the unix ``printf`` command [1]_:: $(printf fmt, arg...) Return the length of a string or a (unexpanded) variable [1]_:: $(length string) $(length-var var) Find the position of ``needle`` in ``haystack``, returns 0 if not found. Negative ``start`` indices are relative to the end of ``haystack``, while positive ones are one based [1]_:: $(pos needle, haystack[, start]) $(lastpos needle, haystack[, start]) Returns the specified substring. The ``start`` works like with ``$(pos )``. If the substring is partially outside the ``string`` the result will be padded with ``pad`` if present [1]_:: $(substr string, start[, length[, pad]]) Insert ``in`` into ``str`` at the specified position. ``n`` works like with ``$(pos )``, except that ``0`` is the end of the string [1]_:: $(insert in, str[, n[, length[, pad]]]) Translate ``string`` exchanging characters in ``from-set`` with ``to-set``, optionally completing ``to-set`` with ``pad-char`` if specified. If no ``pad-char`` characters absent in ``to-set`` will be deleted [1]_:: $(translate string, from-set[, to-set[, pad-char]]) Functions for file names: Extract the directory part of each file ``name``:: $(dir names...) Extract the non-directory part of each file ``name``:: $(notdir names...) Extract the suffix (the last ``.`` and following characters) of each file ``name``:: $(suffix names...) Extract the base name (name without suffix) of each file name:: $(basename names...) Extract the root specification of each file name (a bit complicated on Windows & OS/2) [1]_:: $(root names...) Extract the non-root part of each file name (a bit complicated on Windows & OS/2) [1]_:: $(notroot names...) Append ``suffix`` to each word in ``names``:: $(addsuffix suffix,names...) Prepend ``prefix`` to each word in ``names``:: $(addprefix prefix,names...) Find file names matching a shell file name ``pattern`` (not a ``%`` pattern):: $(wildcard pattern...) For each file name in ``names``, expand to an absolute name that does not contain any ``.``, ``..``, nor symlinks:: $(realpath names...) For each file name in ``names``, expand to an absolute name that does not contain any ``.`` or ``..`` components, but preserves symlinks:: $(abspath names...) Same as ``$(abspath )`` except that the current directory can be specified as ``curdir`` [1]_:: $(abspathex names...[, curdir]) Arithmetic Functions: Returns the sum of the arguments [1]_:: $(int-add addend1, addend2[, addendN]) Returns the difference between the first argument and the sum of the rest [1]_:: $(int-sub minuend, subtrahend[, subtrahendN]) Returns the product of the arguments [1]_:: $(int-mul factor1, factor2[, factorN]) Returns the quotient of first argument and the rest [1]_:: $(int-div dividend, divisor[, divisorN]) Returns the modulus of the two arguments [1]_:: $(int-mod dividend, divisor) Returns the bitwise two-complement of argument [1]_:: $(int-not val) Returns the result of a bitwise AND of the arguments [1]_:: $(int-and val1, val2[, valN]) Returns the result of a bitwise OR of the arguments [1]_:: $(int-or val1, val2[, valN]) Returns the result of a bitwise XOR of the arguments [1]_:: $(int-xor val1, val2[, valN]) Returns the ``kmk`` boolean (true = non-empty, false = empty) result of ``val1 == val2`` [1]_:: $(int-eq val1, val2) Returns the ``kmk`` boolean result of ``val1 != val2`` [1]_:: $(int-ne val1, val2) Returns the ``kmk`` boolean result of ``val1 > val2`` [1]_:: $(int-gt val1, val2) Returns the ``kmk`` boolean result of ``val1 >= val2`` [1]_:: $(int-ge val1, val2) Returns the ``kmk`` boolean result of ``val1 < val2`` [1]_:: $(int-lt val1, val2) Returns the ``kmk`` boolean result of ``val1 <= val2`` [1]_:: $(int-le val1, val2) Boolean and Conditional Functions: Condition is false if the ``condition`` evaluates to an empty string (stripped). Evaluate the ``true-part`` if the condition is true, otherwise the ``false-part``:: $(if condition,true-part[,false-part]) Test if any of the conditions evalues to non-empty string, returning the first one:: $(or condition1[,condition2[,condition3[...]]]) Test if all of the conditions evaluates to non-empty strings, returning the last one:: $(and condition1[,condition2[,condition3[...]]]) Test if the two strings are identical, returning ``kmk`` boolean (true = non-empty, false = empty) [2]_:: $(eq str1, str2) Invert a ``kmk`` boolean value [2]_:: $(not val) Test if ``variable`` is defined, returning a ``kmk`` boolean value [1]_:: $(defined variable) Test if ``set-a`` and ``set-b`` intersects, returning a ``kmk`` boolean value [1]_:: $(intersects set-a, set-b) Same as ``$(if )`` execpt that the condition is a ``kmk``-expression [1]_:: $(if-expr kmk-expression,true-part[,false-part]) Select the first true condition (``kmk``-expression) and expand the following body. Special condition strings ``default`` and ``otherwise`` [1]_:: $(select when1-cond, when1-body[, whenN-cond, whenN-body]) Evalutate the ``kmk-expression`` returning what it evalues as. This is the preferred way of doing arithmentic now [1]_:: $(expr kmk-expression) Stack Fuctions: Push ``item`` onto the ``stack-var``, returning the empty string [1]_:: $(stack-push stack-var, item) Pop the top item off the ``stack-var`` [1]_:: $(stack-pop stack-var) Pop the top item off the ``stack-var``, returning the empty string [1]_:: $(stack-popv stack-var) Get the top item of the ``stack-var``, returning the empty string [1]_:: $(stack-top stack-var) Advanced Functions: Evaluates to the contents of the variable ``var``, with no expansion performed on it:: $(value var) Evaluate ``body`` with ``var`` bound to each word in ``words``, and concatenate the results (spaced):: $(foreach var,words,body) C-style for-loop. Start by evaluating ``init``. Each iteration will first check whether the ``condition`` (``kmk``-expression) is true, then expand ``body`` concatenating the result to the previous iterations (spaced), and finally evaluate ``next`` [1]_:: $(for init,conditions,next,body) C-style while-loop. Each iteration will check whether the ``condition`` (``kmk``-expression) is true, then expand ``body`` concatenating the result to the previous iterations [1]_:: $(while conditions,body) Evaluate the variable ``var`` replacing any references to ``$(1)``, ``$(2)`` with the first, second, etc. ``param`` values:: $(call var,param,...) Evaluate ``text`` then read the results as makefile commands. Expands to the empty string:: $(eval text) Same as ``$(eval text)`` except that the ``text`` is expanded in its own variable context [1]_:: $(evalctx text) Same as ``$(eval $(value var))`` [1]_:: $(evalval var) Same as ``$(evalctx $(value var))`` [1]_:: $(evalvalctx var) A combination of ``$(eval )``, ``$(call )`` and ``$(value )`` [1]_:: $(evalcall var) A combination of ``$(eval )`` and ``$(call )`` [1]_:: $(evalcall2 var) Remove comments and blank lines from the variable ``var``. Expands to the empty string [1]_:: $(eval-opt-var var) Returns accessing ``$<`` of ``target``, either retriving the whole thing or the file at ``pos`` (one-origin) [1]_:: $(deps target[, pos]) Returns accessing ``$+`` (order + duplicates) of ``target``, either retriving the whole thing or the file at ``pos`` (one-origin) [1]_:: $(deps-all target[, pos]) Returns accessing ``$?`` of ``target``, either retriving the whole thing or the file at ``pos`` (one-origin) [1]_:: $(deps-newer target[, pos]) Returns accessing ``$|`` (order only) of ``target``, either retriving the whole thing or the file at ``pos`` (one-origin) [1]_:: $(deps-oo target[, pos]) Command Functions: Create one or more command lines avoiding the max argument length restriction of the host OS [1]_:: $(xargs ar cas mylib.a,$(objects)) $(xargs ar cas mylib.a,ar as mylib.a,$(objects)) Returns the commands for the specified target separated by new-line, space, or a user defined string. Note that this might not produce the 100% correct result if any of the prerequisite automatic variables are used [1]_:: $(commands target) $(commands-sc target) $(commands-usr target,sep) Compares two commands returning the empty string if equal and the 3rd argument if not. This differs from ``$(comp-vars v1,v2,ne)`` in that line by line is stripped of leading spaces, command prefixes and trailing spaces before comparing [1]_:: $(comp-cmds cmds-var1, cmds-var2, ne) $(comp-cmds-ex cmds1, cmd2, ne) Compares the values of the two variables returning the empty string if equal and the 3rd argument if not. Leading and trailing spaces is ignored [1]_:: $(comp-var var1, var2, ne) Utility functions: When this function is evaluated, ``kmk`` generates a fatal error with the message ``text``:: $(error text...) When this function is evaluated, ``kmk`` generates a warning with the message ``text``:: $(warning text...) When this function is evaluated, ``kmk`` generates a info with the message ``text``:: $(info text...) Execute a shell ``command`` and return its output:: $(shell command) Return a string with the location where the ``kmk`` variable ``variable`` was defined:: $(where variable) Return a string describing how the ``kmk`` variable ``variable`` was defined:: $(origin variable) Return a string describing the flavor of the ``kmk`` variable ``variable``:: $(flavor variable) Returns the current local time and date formatted in the ``strftime`` style specifier ``fmt``. ``fmt`` defaults to ``%Y-%m-%dT%H:%M:%S`` when not specified [1]_:: $(date fmt) Returns the current UTC time and date formatted in the ``strftime`` style specifier ``fmt``. ``fmt`` defaults to ``%Y-%m-%dT%H:%M:%SZ`` when not specified [1]_:: $(date-utc fmt) Reformats the ``in`` time and date using ``fmt``. The ``in-fmt`` defaults to ``fmt`` if not specified. While ``fmt`` defaults to ``%Y-%m-%dT%H:%M:%SZ`` if not specified [1]_:: $(date-utc fmt,time,in-fmt) Returns the current nanosecond timestamp (monotonic when possible) [1]_:: $(nanots ) Returns the size of the specified file, or -1 if the size could not be obtained. This can be used to check if a file exist or not [1]_:: $(file-size file) Searches the ``PATH`` ``kmk`` variable for the specified ``files`` [1]_:: $(which files...) OS/2: Returns the specified LIBPATH variable value [1]_:: $(libpath var) OS/2: Sets the specified LIBPATH variable value, returning the empty string [1]_:: $(libpath var,value) Debugging Functions: Returns various make statistics, if no item is specified a default selection is returned [1]_:: $(make-stats item[,itemN]) Raise a debug breakpoint. Used for debugging ``kmk`` makefile parsing [1]_:: $(breakpoint ) Recipes ------- A typical recipe takes one of the two following forms:: targets : normal-prerequisites | order-only-prerequisites command ... targets : normal-prerequisites | order-only-prerequisites ; command command ... Specifying more than one file in the ``targets`` lists is the same as repeating the recipe for each of the files. Use ``+`` and ``+|`` in the list of ``targets`` to tell ``kmk`` that the recipe has more than one output. [1]_ The files after a ``+`` will always be remade, while the files after a ``+|`` don't have to be remade. The latter is frequently employed to update files which prerequisites change wihtout the output files necessarily changing. See also ``kmk_cp --changed``. Double colon recipes Double colon recipes are written with ``::`` instead of ``:`` and are handled differently from ordinary recipes if the target appears in more than one recipe. First, all the recipes must be of the double colon type. Second, the recipes are executed individually and may be omitted depending on the state of their prerequisites. Double colon recipes without any prerequisites will always be executed. Pattern rules A couple of examples:: %.o : %.c gcc -o $@ $< %.tab.c %.tab.h : %.y bison -d $< The latter has two outputs. ----- .. [1] ``kmk`` only feature. .. [2] Experimental GNU ``make`` feature that is not enabled by default. ----- :Status: $Id: QuickReference-kmk.txt 2532 2011-08-02 13:05:37Z bird $ :Copyright: Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Copyright (c) 2008-2009 knut st. osmundsen kbuild-2695/kBuild/doc/Makefile.kmk0000644000000000000000000000366612247157310015646 0ustar rootrootDEPTH = ../.. include ../header.kmk TXTFILES = \ QuickReference-kmk.txt \ QuickReference-kBuild.txt define genrule all: $(name).html clean:: kmk_rm -f $(name).html $(name).html: $(name).txt LC_ALL=C rst2html.py --no-generator $$< $$@ $(name).o: $(name).html .PHONY: $(name).o endef $(foreach name, $(basename $(TXTFILES)), $(eval $(genrule))) # # For generating the basis for the target properties table. # my_tp.1 = BLDPROGS PROGRAMS my_tp.2 = LIBRARIES my_tp.3 = IMPORT_LIBS DLLS my_tp.4 = DLLS my_tp.5 = PROGRAMS my_tp.6 = SYSMODS my_tp.7 = MISCBINS my_tp.8 = INSTALLS my_tp.9 = FETCHES my_tp.a = OTHERS my_tp = 1 2 3 4 5 6 7 8 9 a tpc := $(translate $(my_tp),$(SP)) define def_target_prop_rule target-properties:: @$$(PRINTF) '|%-2s| %-18s| %-6s|%$(expr 79-33)s|\n' "$(kind)" "``$(prop)``" "$(my_tmp_which)" "" @$$(ECHO) '+--+-------------------+-------+----------------------------------------------+' endef define def_target_prop_doit my_tmp_which := $(foreach x,$(my_tp),$(if $(intersects \ $(prop),\ $(foreach nm,$(my_tp.$(x)),$(foreach suff,SINGLE DEFERRED ACCUMULATE_R ACCUMULATE_L,$(PROPS_$(nm)_$(suff)))))\ ,$(x),)) my_tmp_which := $(translate $(my_tmp_which),$(SP)) $(for local i = 1, $i < 10, local i := $(expr $i + 1),$(for local l = $(expr 10 - $i + 1), $l > 3, local l := $(expr $l - 1), \ $(eval my_tmp_which:=$(subst $(substr $(tpc), $i, $l),$i-$(substr $(tpc),$(expr $i + $l - 1),1),$(my_tmp_which)))\ ) ) $(eval $(def_target_prop_rule)) endef kind := S $(foreach prop,$(sort $(PROPS_SINGLE)),$(evalcall def_target_prop_doit)) kind := D $(foreach prop,$(sort $(PROPS_DEFERRED)),$(evalcall def_target_prop_doit)) kind := Ar $(foreach prop,$(sort $(PROPS_ACCUMULATE_R)),$(evalcall def_target_prop_doit)) kind := Al $(foreach prop,$(sort $(PROPS_ACCUMULATE_L)),$(evalcall def_target_prop_doit)) #kind := To #$(foreach prop,$(sort $(PROPS_TOOLS_ONLY)),$(evalcall def_target_prop_doit)) kbuild-2695/kBuild/doc/QuickReference-kmk.html0000644000000000000000000022062212247157310017757 0ustar rootroot kmk Quick Reference

kmk Quick Reference

This is an attempt at summarizing all directives, functions, special variables, special targets, built-in commands, external commands, and kmk-expressions. Since all the features are included, the quickness of this reference can be disputed. ;-)

Directives

Here is a summary of the directives kmk recognizes:

Define a multi-line, recursively-expanded variable:

define variable
endef

Conditionally evaluate part of the makefile:

ifdef variable
ifndef variable
ifeq (a,b)
ifeq "a" "b"
ifeq 'a' 'b'
ifneq (a,b)
ifneq "a" "b"
ifneq 'a' 'b'
if1of (set-a,set-b)             [1]
ifn1of (set-a,set-b)            [1]
if expression                   [1]
else
endif

Include another makefile:

include file
-include file
sinclude file

Include another dependency file [1]:

includedep file

Define a variable, overriding any previous definition, even one from the command line:

override variable = value
override variable := value
override variable += value
override variable <= value      [1]
override variable ?= value
override define variable
endef

Tell kmk to export all variables to child processes by default:

export

Tell kmk whether or not to export a particular variable to child processes:

export variable
export variable = value
export variable := value
export variable += value
export variable <= value        [1]
export variable ?= value
unexport variable

Define a variable in the local context instead of the global one [1]:

local variable = value
local variable := value
local variable += value
local variable <= value
local variable ?= value
local define variable
endef

Specify a search path for files matching a % pattern:

vpath pattern path

Remove all search paths previously specified for pattern:

vpath pattern

Remove all search paths previously specified in any vpath directive:

vpath

Automatic variables

Here is a summary of the automatic variables.

Variable Description
$@ The file name of the target.
$< The name of the first prerequisite.
$? The names of all the prerequisites that are newer than the target, with spaces between them.
$^ The names of all the prerequisites, duplicates omitted.
$+ The names of all the prerequisites, duplicates and order preserved
$* The stem with which an implicit rule matches.
$| The name of all the order only prerequisites.
$(@D) The directory part of $@.
$(<D) The directory part of $<.
$(?D) The directory part of $?.
$(^D) The directory part of %^.
$(+D) The directory part of $+.
$(*D) The directory part of $*.
$(|D) The directory part of $|.
$(@F) The file-within-directory part of $@.
$(<F) The file-within-directory part of $<.
$(?F) The file-within-directory part of $?.
$(^F) The file-within-directory part of $^.
$(+F) The file-within-directory part of $+.
$(*F) The file-within-directory part of $*.
$(|F) The file-within-directory part of $|.

Special variables

All variables starting with a . is reserved by kmk. The following variables are specially used or/and defined by kmk:

Variable Description
.DEFAULT_GOAL The makefile default goal. You can set this in the makefile, if you don't it will default to the first target that is encountered.
.FEATURES List of GNU make features. Do not set this.
.INCLUDE_DIRS List of include directories, -I arguments and defaults. Do not set this.
.RECIPEPREFIX Recipe prefix, defaults to tab.
.VARIABLES Special variable which exands to the list of variable. Do not set this.
CURDIR Set to the pathname of the current working directory (after all -C options are processed, if any). Do not set this.
KBUILD_VERSION, KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_KMK_REVISION The kBuild version string and the break down into individual components. [1]
KBUILD_HOST [1] The host operating system.
KBUILD_HOST_ARCH [1] The host architecture.
KBUILD_HOST_CPU [1] The host CPU kmk is built for, set to blend if not any particular CPU.
KBUILD_PATH [1] Where the kBuild scripts are.
KBUILD_BIN_PATH [1] Where the host specific kBuild binaries are.
KMK [1], MAKE The name with which kmk was invoked. Using this variable in recipes has special meaning.
KMK_BUILTIN [1] List of built-in commands.
KMK_FEATURES [1] List of kmk specific features.
KMK_FLAGS [1]

The flags given to kmk. You can set this in the environment or a makefile to set flags.

It is never appropriate to use KMK_FLAGS directly in a recipe line: its contents may not be quoted correctly for use in the shell. Always allow recursive kmk's to obtain these values through the environment from its parent.

KMK_LEVEL [1] The number of levels of recursion (sub-makes).
KMK_VERSION [1] The GNU make version number.
MAKECMDGOALS The targets given to kmk on the command line. Do not set this.
MAKEFILES Makefiles to be read on every invocation of kmk.
MAKEFILE_LIST List of the makefiles that kmk has opened.
MAKESHELL OS/2 and MS-DOS only, the name of the command interpreter that is to be used by kmk. This value takes precedence over the value of SHELL.
SHELL The name of the default command interpreter, kmk_ash. You can set SHELL in the makefile to change the shell used to run recipes. The SHELL variable is handled specially when importing from and exporting to the environment.
SUFFIXES The default list of suffixes before kmk reads any makefiles (always empty).
VPATH Directory search path for files not found in the current directory.

The following variables reflects kmk options. Do not set these. [1]

Variable Description
KMK_OPTS_JOBS -j slots, 0 if not given.
KMK_OPTS_KEEP_GOING -k indictor (0/1).
KMK_OPTS_JUST_PRINT -n indicator (0/1).
KMK_OPTS_PRORITY --priority level, 0 if not given.
KMK_OPTS_AFFINITY --affinity mask, 0 if not given.
KMK_OPTS_STATISTICS --statistics indicator (0/1).
KMK_OPTS_PRINT_TIME The --print-time value.
KMK_OPTS_PRETTY_COMMAND_PRINTING --pretty-command-printing indicator.

Special Targets

Certain names have special meanings if they appear as targets.

Target Description
.DEFAULT The recipe is used for any target for which no rules are found.
.DELETE_ON_ERROR If mentioned, kmk will delete the targets of a rule if it has changed and its recipe fails or is interrupted.
.EXPORT_ALL_VARIABLES If mentioned, all variables will by default be exported to child processes.
.IGNORE Ignore errors in the execution of the recipe for the targets .IGNORE depends on, if no prequisites all targets are affected.
.INTERMEDIATE The prerequisites are treated as intermediate files (implicite rules).
.LOW_RESOLUTION_TIME kmk will assume prerequisite files are created with low resolution time stamps.
.NOTPARALLEL If mentioned without any prerequisites, kmk will run serially as if -j1 was given. If it has prerequisites kmk [1] will only do this for the targets among them.
.PHONY The prerequisites are considered phony and will be rebuilt unconditionally.
.PRECIOUS The targets which .PRECIOUS depends will to be deleted if kmk is killed or interrupted while their building.
.SECONDARY The prerequisites are treated as intermediate files, except that they are never automatically deleted. If used with no prerequisites all targets gets this treatement.
.SECONDEXPANSION If mentioned, all prerequisite lists after it will be expanded a second time after all makefiles have been read.
.SECONDTARGETEXPANSION [1] If mentioned, all targets after it will be expanded a second time after all makefiles have been read.
.SILENT kmk will not print the recipe for targets listed as prerequisites, if none then it applies to all targets.
.SUFFIXES The prerequisites are the list of suffixes used in checking for suffix rules. If it appears without prerequisites it the suffix will be cleared.

Commands

Builtin commands [1] all start with kmk_builtin_, so in order to save space this prefix has been omitted in the table below. All commands comes in an external edition that can be used by/in the shell, these are prefixed kmk_.

Command Description
append Append text to a file. The builtin version can output the value of a variable or the commands of a target.
cat The BSD cat command.
chmod The BSD chmod command.
cmp The BSD cmp command.
cp The BSD cp command with some twaking.
echo The BSD echo command.
expr The BSD expr command.
install The BSD install command with some tweaking.
kDepIDB Extract dependencies from a Visual C++ .IDB file.
ln The BSD ln command.
md5sum Typical MD5 sum program, custom kBuild version.
mkdir The BSD mkdir command.
mv The BSD mv command with some tweaking.
printf The BSD printf command.
rm The BSD rm command with some tweaking.
rmdir The BSD rmdir command with some tweaking.
sleep Typical sleep program, custom kBuild version.
test The BSD test program with some tweaking.

Some additional external commands are available in the kmk / kBuild environment (kSomething command are not prefixed with kmk_):

Command Description
kDepPre Extract dependencies from the C/C++ preprocessor output.
kObjCache Simple object file cache program.
ash Almquist's shell (NetBSD variant).
gmake Vanilla GNU make from same sources as kmk.
redirect Shell avoidance tool. Sets up file descriptors, environment variables and current directory before kicking of program.
sed GNU sed with some tweaks to avoid involving the shell.
time Stopwatch utility for measuring program execution time(s).

kmk-expression

kmk-expressions [1] are related to the C/C++ preprocessor in some ways as well as nmake and BSD make. There are however some peculiarities because of the way GNU make choose to represent booleans in its function library, so, strings can be turned into boolean by taking any non-empty string as true.

Quoting using single quotes results in hard strings, while double quotes and unquoted string results in soft strings that can be converted to number or boolean to fit the situation.

Here's the operator table in decending precedence order:

Operator Type Description
defined Unary Checks if the following variable exists.
exists Checks if the following file exists.
target Checks if the following target exists.
bool Casts the following value to boolean.
num Casts the following value to a number.
str Casts the following value to a string.
! Unary Logical NOT.
+ Pluss prefix.
- Minus prefix.
~ Bitwise one's complement.
* Binary Multiplication (product).
/ Division (quotient).
% Modulus (remainder).
+ Binary Addition (sum).
- Subtraction (difference).
<< Binary Bitwise left shift.
>> Bitwise right shift.
<= Binary Less or equal than.
< Less than.
>= Greater or equal than.
> Greater than.
== Binary Equal to.
!= Not equal to.
& Binary Bitwise AND.
^ Binary Bitwise XOR.
| Binary Bitwise OR.
&& Binary Logical AND.
|| Binary Logical OR.

Built-in functions

String Manipulation Functions:

Replace from with to in text:

$(subst from,to,text)

Replace words matching pattern with replacement in text:

$(patsubst pattern,replacement,text)

Remove excess whitespace characters from string:

$(strip string)

Locate find in text, returning find if found:

$(findstring find,text)

Select words in text that match one of the pattern words:

$(filter pattern...,text)

Select words in text that do not match any of the pattern words:

$(filter-out pattern...,text)

Sort the words in list lexicographically, removing duplicates:

$(sort list)

Sort the words in list lexicographically in reserve order, removing duplicates [1]:

$(rsort list)

Count the number of words in text:

$(words text)

Extract the nth word (one-origin) of text:

$(word n,text)

Returns the list of words in text from s to e (one-origin):

$(wordlist s,e,text)

Extract the first word of names:

$(firstword names...)

Extract the last word of names:

$(lastword names...)

Join two parallel lists of words:

$(join list1,list2)

Fold text to upper case [1]:

$(toupper text)

Fold text to lower case [1]:

$(tolower text)

String formatting a la the unix printf command [1]:

$(printf fmt, arg...)

Return the length of a string or a (unexpanded) variable [1]:

$(length string)
$(length-var var)

Find the position of needle in haystack, returns 0 if not found. Negative start indices are relative to the end of haystack, while positive ones are one based [1]:

$(pos needle, haystack[, start])
$(lastpos needle, haystack[, start])

Returns the specified substring. The start works like with $(pos ). If the substring is partially outside the string the result will be padded with pad if present [1]:

$(substr string, start[, length[, pad]])

Insert in into str at the specified position. n works like with $(pos ), except that 0 is the end of the string [1]:

$(insert in, str[, n[, length[, pad]]])

Translate string exchanging characters in from-set with to-set, optionally completing to-set with pad-char if specified. If no pad-char characters absent in to-set will be deleted [1]:

$(translate string, from-set[, to-set[, pad-char]])

Functions for file names:

Extract the directory part of each file name:

$(dir names...)

Extract the non-directory part of each file name:

$(notdir names...)

Extract the suffix (the last . and following characters) of each file name:

$(suffix names...)

Extract the base name (name without suffix) of each file name:

$(basename names...)

Extract the root specification of each file name (a bit complicated on Windows & OS/2) [1]:

$(root names...)

Append suffix to each word in names:

$(addsuffix suffix,names...)

Prepend prefix to each word in names:

$(addprefix prefix,names...)

Find file names matching a shell file name pattern (not a % pattern):

$(wildcard pattern...)

For each file name in names, expand to an absolute name that does not contain any ., .., nor symlinks:

$(realpath names...)

For each file name in names, expand to an absolute name that does not contain any . or .. components, but preserves symlinks:

$(abspath names...)

Same as $(abspath ) except that the current directory can be specified as curdir [1]:

$(abspathex names...[, curdir])

Arithmetic Functions:

Returns the sum of the arguments [1]:

$(int-add addend1, addend2[, addendN])

Returns the difference between the first argument and the sum of the rest [1]:

$(int-sub minuend, subtrahend[, subtrahendN])

Returns the product of the arguments [1]:

$(int-mul factor1, factor2[, factorN])

Returns the quotient of first argument and the rest [1]:

$(int-div dividend, divisor[, divisorN])

Returns the modulus of the two arguments [1]:

$(int-mod dividend, divisor)

Returns the bitwise two-complement of argument [1]:

$(int-not val)

Returns the result of a bitwise AND of the arguments [1]:

$(int-and val1, val2[, valN])

Returns the result of a bitwise OR of the arguments [1]:

$(int-or val1, val2[, valN])

Returns the result of a bitwise XOR of the arguments [1]:

$(int-xor val1, val2[, valN])

Returns the kmk boolean (true = non-empty, false = empty) result of val1 == val2 [1]:

$(int-eq val1, val2)

Returns the kmk boolean result of val1 != val2 [1]:

$(int-ne val1, val2)

Returns the kmk boolean result of val1 > val2 [1]:

$(int-gt val1, val2)

Returns the kmk boolean result of val1 >= val2 [1]:

$(int-ge val1, val2)

Returns the kmk boolean result of val1 < val2 [1]:

$(int-lt val1, val2)

Returns the kmk boolean result of val1 <= val2 [1]:

$(int-le val1, val2)

Boolean and Conditional Functions:

Condition is false if the condition evaluates to an empty string (stripped). Evaluate the true-part if the condition is true, otherwise the false-part:

$(if condition,true-part[,false-part])

Test if any of the conditions evalues to non-empty string, returning the first one:

$(or condition1[,condition2[,condition3[...]]])

Test if all of the conditions evaluates to non-empty strings, returning the last one:

$(and condition1[,condition2[,condition3[...]]])

Test if the two strings are identical, returning kmk boolean (true = non-empty, false = empty) [2]:

$(eq str1, str2)

Invert a kmk boolean value [2]:

$(not val)

Test if variable is defined, returning a kmk boolean value [1]:

$(defined variable)

Test if set-a and set-b intersects, returning a kmk boolean value [1]:

$(intersects set-a, set-b)

Same as $(if ) execpt that the condition is a kmk-expression [1]:

$(if-expr kmk-expression,true-part[,false-part])

Select the first true condition (kmk-expression) and expand the following body. Special condition strings default and otherwise [1]:

$(select when1-cond, when1-body[, whenN-cond, whenN-body])

Evalutate the kmk-expression returning what it evalues as. This is the preferred way of doing arithmentic now [1]:

$(expr kmk-expression)

Stack Fuctions:

Push item onto the stack-var, returning the empty string [1]:

$(stack-push stack-var, item)

Pop the top item off the stack-var [1]:

$(stack-pop stack-var)

Pop the top item off the stack-var, returning the empty string [1]:

$(stack-popv stack-var)

Get the top item of the stack-var, returning the empty string [1]:

$(stack-top stack-var)

Advanced Functions:

Evaluates to the contents of the variable var, with no expansion performed on it:

$(value var)

Evaluate body with var bound to each word in words, and concatenate the results (spaced):

$(foreach var,words,body)

C-style for-loop. Start by evaluating init. Each iteration will first check whether the condition (kmk-expression) is true, then expand body concatenating the result to the previous iterations (spaced), and finally evaluate next [1]:

$(for init,conditions,next,body)

C-style while-loop. Each iteration will check whether the condition (kmk-expression) is true, then expand body concatenating the result to the previous iterations [1]:

$(while conditions,body)

Evaluate the variable var replacing any references to $(1), $(2) with the first, second, etc. param values:

$(call var,param,...)

Evaluate text then read the results as makefile commands. Expands to the empty string:

$(eval text)

Same as $(eval text) except that the text is expanded in its own variable context [1]:

$(evalctx text)

Same as $(eval $(value var)) [1]:

$(evalval var)

Same as $(evalctx $(value var)) [1]:

$(evalvalctx var)

A combination of $(eval ), $(call ) and $(value ) [1]:

$(evalcall var)

A combination of $(eval ) and $(call ) [1]:

$(evalcall var)

Remove comments and blank lines from the variable var. Expands to the empty string [1]:

$(eval-opt-var var)

Returns accessing $< of target, either retriving the whole thing or the file at pos (one-origin) [1]:

$(deps target[, pos])

Returns accessing $+ (order + duplicates) of target, either retriving the whole thing or the file at pos (one-origin) [1]:

$(deps-all target[, pos])

Returns accessing $? of target, either retriving the whole thing or the file at pos (one-origin) [1]:

$(deps-newer target[, pos])

Returns accessing $| (order only) of target, either retriving the whole thing or the file at pos (one-origin) [1]:

$(deps-oo target[, pos])

Command Functions:

Create one or more command lines avoiding the max argument length restriction of the host OS [1]:

$(xargs ar cas mylib.a,$(objects))
$(xargs ar cas mylib.a,ar as mylib.a,$(objects))

Returns the commands for the specified target separated by new-line, space, or a user defined string. Note that this might not produce the 100% correct result if any of the prerequisite automatic variables are used [1]:

$(commands target)
$(commands-sc target)
$(commands-usr target,sep)

Compares two commands returning the empty string if equal and the 3rd argument if not. This differs from $(comp-vars v1,v2,ne) in that line by line is stripped of leading spaces, command prefixes and trailing spaces before comparing [1]:

$(comp-cmds cmds-var1, cmds-var2, ne)
$(comp-cmds-ex cmds1, cmd2, ne)

Compares the values of the two variables returning the empty string if equal and the 3rd argument if not. Leading and trailing spaces is ignored [1]:

$(comp-var var1, var2, ne)

Utility functions:

When this function is evaluated, kmk generates a fatal error with the message text:

$(error text...)

When this function is evaluated, kmk generates a warning with the message text:

$(warning text...)

When this function is evaluated, kmk generates a info with the message text:

$(info text...)

Execute a shell command and return its output:

$(shell command)

Return a string describing how the kmk variable variable was defined:

$(origin variable)

Return a string describing the flavor of the kmk variable variable:

$(flavor variable)

Returns the current local time and date formatted in the strftime style specifier fmt. fmt defaults to %Y-%m-%dT%H:%M:%S when not specified [1]:

$(date fmt)

Returns the current UTC time and date formatted in the strftime style specifier fmt. fmt defaults to %Y-%m-%dT%H:%M:%SZ when not specified [1]:

$(date-utc fmt)

Reformats the in time and date using fmt. The in-fmt defaults to fmt if not specified. While fmt defaults to %Y-%m-%dT%H:%M:%SZ if not specified [1]:

$(date-utc fmt,time,in-fmt)

Returns the current nanosecond timestamp (monotonic when possible) [1]:

$(nanots )

Returns the size of the specified file, or -1 if the size could not be obtained. This can be used to check if a file exist or not [1]:

$(file-size file)

Searches the PATH kmk variable for the specified files [1]:

$(which files...)

OS/2: Returns the specified LIBPATH variable value [1]:

$(libpath var)

OS/2: Sets the specified LIBPATH variable value, returning the empty string [1]:

$(libpath var,value)

Debugging Functions:

Returns various make statistics, if no item is specified a default selection is returned [1]:

$(make-stats item[,itemN])

Raise a debug breakpoint. Used for debugging kmk makefile parsing [1]:

$(breakpoint )

Recipes

A typical recipe takes one of the two following forms:

targets : normal-prerequisites | order-only-prerequisites
        command
        ...

targets : normal-prerequisites | order-only-prerequisites ; command
        command
        ...

Specifying more than one file in the targets lists is the same as repeating the recipe for each of the files.

Use + and +| in the list of targets to tell kmk that the recipe has more than one output. [1] The files after a + will always be remade, while the files after a +| don't have to be remade. The latter is frequently employed to update files which prerequisites change wihtout the output files necessarily changing. See also kmk_cp --changed.

Double colon recipes

Double colon recipes are written with :: instead of : and are handled differently from ordinary recipes if the target appears in more than one recipe. First, all the recipes must be of the double colon type. Second, the recipes are executed individually and may be omitted depending on the state of their prerequisites. Double colon recipes without any prerequisites will always be executed.

Pattern rules

A couple of examples:

%.o : %.c
        gcc -o $@ $<
%.tab.c %.tab.h : %.y
        bison -d $<

The latter has two outputs.


[1](1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81) kmk only feature.
[2](1, 2) Experimental GNU make feature that is not enabled by default.

Status:

$Id: QuickReference-kmk.html 2340 2009-04-18 12:05:47Z bird $

Copyright:

Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.

Copyright (c) 2008-2009 knut st. osmundsen

kbuild-2695/kBuild/sdks/0000755000000000000000000000000012247157310013611 5ustar rootrootkbuild-2695/kBuild/sdks/MACOSX105INCS.kmk0000644000000000000000000000332612247157310016216 0ustar rootroot# $Id: MACOSX105INCS.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - Mac OS X v10.5 SDK, includes only. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_MACOSX105INCS := Mac OS X v10.5 SDK # SDK Specific Properties ifndef PATH_SDK_MACOSX105INCS ifdef PATH_SDK_MACOSX105 PATH_SDK_MACOSX105INCS := $(PATH_SDK_MACOSX105) else PATH_SDK_MACOSX105INCS := /Developer/SDKs/MacOSX10.5.sdk endif else # Resolve any fancy stuff once and for all. PATH_SDK_MACOSX105INCS := $(PATH_SDK_MACOSX105INCS) endif # General Properties (used by kBuild) SDK_MACOSX105INCS_INCS = $(PATH_SDK_MACOSX105INCS)/usr/include kbuild-2695/kBuild/sdks/WINPSDK71.kmk0000644000000000000000000001512512247157310015610 0ustar rootroot# $Id: WINPSDK71.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Windows Platform SDK v7.1, targeting (KBUILD_TARGET). # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINPSDK71 := The Windows Platform SDK v7.1, targeting (KBUILD_TARGET). # SDK Specific Properties ifndef PATH_SDK_WINPSDK71 PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/v7.1*) ifeq ($(PATH_SDK_WINPSDK71),) PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/v7.1*) endif ifeq ($(PATH_SDK_WINPSDK71),) PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/v7.1*) endif ifeq ($(PATH_SDK_WINPSDK71),) PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/v7.1*) endif ifneq ($(PATH_SDK_WINPSDK71),) PATH_SDK_WINPSDK71 := $(lastword $(sort $(PATH_SDK_WINPSDK71))) else $(warning kBuild: PATH_SDK_WINPSDK71 couldn't be determined!) PATH_SDK_WINPSDK71 := $(PATH_DEVTOOLS_BLD)/sdk/v7.1-not-found endif else PATH_SDK_WINPSDK71 := $(PATH_SDK_WINPSDK71) endif ifndef PATH_SDK_WINPSDK71_INC PATH_SDK_WINPSDK71_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDK71)/Include) endif ifndef PATH_SDK_WINPSDK71_LIB.x86 PATH_SDK_WINPSDK71_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDK71)/Lib) endif ifndef PATH_SDK_WINPSDK71_LIB.amd64 PATH_SDK_WINPSDK71_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]/[xX]64) $(PATH_SDK_WINPSDK71)/Lib/AMD64) endif ifndef PATH_SDK_WINPSDK71_LIB.ia64 PATH_SDK_WINPSDK71_LIB.ia64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]/[Ii][Aa]64) $(PATH_SDK_WINPSDK71)/Lib/IA64) endif PATH_SDK_WINPSDK71_LIB ?= $(PATH_SDK_WINPSDK71_LIB.$(KBUILD_TARGET_ARCH)) ifndef PATH_SDK_WINPSDK71_BIN PATH_SDK_WINPSDK71_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDK71)/Bin) endif ifndef PATH_SDK_WINPSDK71_BIN_AMD64 PATH_SDK_WINPSDK71_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK71_BIN)/[Ww][Ii][Nn]64/[Xx]86) $(PATH_SDK_WINPSDK71_BIN)/win64/AMD64) endif ifndef PATH_SDK_WINPSDK71_BIN_IA64 PATH_SDK_WINPSDK71_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDK71_BIN)/win64) endif # General Properties used by kBuild SDK_WINPSDK71_INCS ?= $(PATH_SDK_WINPSDK71_INC) SDK_WINPSDK71_LIBPATH.x86 ?= $(PATH_SDK_WINPSDK71_LIB.x86) SDK_WINPSDK71_LIBPATH.amd64 ?= $(PATH_SDK_WINPSDK71_LIB.amd64) SDK_WINPSDK71_LIBPATH.ia64 ?= $(PATH_SDK_WINPSDK71_LIB.ia64) SDK_WINPSDK71_LIBS.x86 ?= \ $(PATH_SDK_WINPSDK71_LIB.x86)/Kernel32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/User32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/Gdi32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/AdvAPI32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/Shell32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/ShLwApi.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/SetupAPI.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/Uuid.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/Version.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/WS2_32.Lib \ \ $(PATH_SDK_WINPSDK71_LIB.x86)/Ole32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/OleAut32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/OleDlg.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/RpcRT4.Lib \ \ $(PATH_SDK_WINPSDK71_LIB.x86)/DbgHelp.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/ImageHlp.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/IPHlpApi.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/ComCtl32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/ComDlg32.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/WinSpool.Lib \ $(PATH_SDK_WINPSDK71_LIB.x86)/WinMM.Lib SDK_WINPSDK71_LIBS.amd64 ?= \ $(PATH_SDK_WINPSDK71_LIB.amd64)/Kernel32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/User32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/Gdi32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/AdvAPI32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/Shell32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/ShLwApi.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/SetupAPI.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/Uuid.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/Version.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/WS2_32.Lib \ \ $(PATH_SDK_WINPSDK71_LIB.amd64)/Ole32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/OleAut32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/OleDlg.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/RpcRT4.Lib \ \ $(PATH_SDK_WINPSDK71_LIB.amd64)/DbgHelp.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/ImageHlp.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/IPHlpApi.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/ComCtl32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/ComDlg32.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/WinSpool.Lib \ $(PATH_SDK_WINPSDK71_LIB.amd64)/WinMM.Lib SDK_WINPSDK71_LIBS.ia64 ?= \ $(PATH_SDK_WINPSDK71_LIB.ia64)/Kernel32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/User32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/Gdi32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/AdvAPI32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/Shell32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/ShLwApi.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/SetupAPI.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/Uuid.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/Version.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/WS2_32.Lib \ \ $(PATH_SDK_WINPSDK71_LIB.ia64)/Ole32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/OleAut32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/OleDlg.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/RpcRT4.Lib \ \ $(PATH_SDK_WINPSDK71_LIB.ia64)/DbgHelp.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/ImageHlp.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/IPHlpApi.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/ComCtl32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/ComDlg32.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/WinSpool.Lib \ $(PATH_SDK_WINPSDK71_LIB.ia64)/WinMM.Lib kbuild-2695/kBuild/sdks/OS2DDKBASE32.kmk0000644000000000000000000000442612247157310016051 0ustar rootroot# $Id: OS2DDKBASE32.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # # kBuild SDK - The OS/2 DDK, 32-bit base headers and libraries. # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_OS2DDKBASE32 := The OS/2 DDK, 32-bit base headers and libraries. # SDK Specific Properties ifndef PATH_SDK_OS2DDKBASE32 PATH_SDK_OS2DDKBASE32 := $(wildcard $(PATH_DEVTOOLS)/os2.x86/ddk/2*/base32) ifeq ($(PATH_SDK_OS2DDKBASE32),) PATH_SDK_OS2DDKBASE32 := $(wildcard $(PATH_DDKBASE)/../base32) endif ifneq ($(PATH_SDK_OS2DDKBASE32),) PATH_SDK_OS2DDKBASE32 := $(lastword $(sort $(PATH_SDK_OS2DDKBASE32))) else $(warning kBuild: PATH_SDK_OS2DDKBASE32 couldn't be determined!) PATH_SDK_OS2DDKBASE32 := $(PATH_DEVTOOLS)/x86.win/ddknt4/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_OS2DDKBASE32 := $(PATH_SDK_OS2DDKBASE32) endif PATH_SDK_OS2DDKBASE32_INC ?= PATH_SDK_OS2DDKBASE32_LIB ?= $(PATH_SDK_OS2DDKBASE32)/lib/i386/free # General Properties used by kBuild SDK_OS2DDKBASE32_INCS ?= $(PATH_SDK_OS2DDKBASE32)/rel/os2c/include/base/os2/16bit SDK_OS2DDKBASE32_ASINCS ?= $(PATH_SDK_OS2DDKBASE32)/rel/os2c/include/base/os2/inc SDK_OS2DDKBASE32_LIBPATH ?= $(PATH_SDK_OS2DDKBASE32_LIB) kbuild-2695/kBuild/sdks/WINDDK71.kmk0000644000000000000000000001117512247157310015452 0ustar rootroot# $Id: WINDDK71.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Microsoft Windows 7 DDK, v7.1. # Defaults to $(KBUILD_TARGET_ARCH). Base SDK. # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDK71 := The Microsoft Windows 7 DDK, v7.1. \ Defaults to $(KBUILD_TARGET_ARCH). Base SDK. # SDK Specific Properties ifndef PATH_SDK_WINDDK71 PATH_SDK_WINDDK71 := $(wildcard $(PATH_DEVTOOLS_TRG)/ddk/7600.16385.1*) ifeq ($(PATH_SDK_WINDDK71),) PATH_SDK_WINDDK71 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddk/7600.16385.1*) endif ifeq ($(PATH_SDK_WINDDK71),) PATH_SDK_WINDDK71 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddk/7600.16385.1*) endif ifeq ($(PATH_SDK_WINDDK71),) ifeq ($(KBUILD_HOST),win) PATH_SDK_WINDDK71 := $(wildcard C:/WinDDK/7600.16385.1*) endif endif ifneq ($(PATH_SDK_WINDDK71),) PATH_SDK_WINDDK71 := $(lastword $(sort $(PATH_SDK_WINDDK71))) else $(warning kBuild: PATH_SDK_WINDDK71 couldn't be determined!) PATH_SDK_WINDDK71 := $(PATH_DEVTOOLS)/win.x86/ddk/7600.16385.1-not-found endif else # Resolve any fancy stuff once and for all. PATH_SDK_WINDDK71 := $(PATH_SDK_WINDDK71) endif PATH_SDK_WINDDK71_INC ?= $(PATH_SDK_WINDDK71)/inc PATH_SDK_WINDDK71_INC_API ?= $(PATH_SDK_WINDDK71_INC)/api PATH_SDK_WINDDK71_INC_CRT ?= $(PATH_SDK_WINDDK71_INC)/crt PATH_SDK_WINDDK71_INC_DDK ?= $(PATH_SDK_WINDDK71_INC)/ddk PATH_SDK_WINDDK71_LIB_ROOT ?= $(PATH_SDK_WINDDK71)/lib PATH_SDK_WINDDK71_LIB_WLH_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/wlh PATH_SDK_WINDDK71_LIB_WNET_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/wnet PATH_SDK_WINDDK71_LIB_WXP_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/wxp PATH_SDK_WINDDK71_LIB_W2K_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/w2k PATH_SDK_WINDDK71_LIB_WDF_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/w2k PATH_SDK_WINDDK71_LIB_WLH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH_ROOT)/amd64 PATH_SDK_WINDDK71_LIB_WLH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH_ROOT)/ia64 PATH_SDK_WINDDK71_LIB_WLH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH_ROOT)/i386 PATH_SDK_WINDDK71_LIB_WLH ?= $(PATH_SDK_WINDDK71_LIB_WLH.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK71_LIB_WNET.amd64?= $(PATH_SDK_WINDDK71_LIB_WNET_ROOT)/amd64 PATH_SDK_WINDDK71_LIB_WNET.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WNET_ROOT)/ia64 PATH_SDK_WINDDK71_LIB_WNET.x86 ?= $(PATH_SDK_WINDDK71_LIB_WNET_ROOT)/i386 PATH_SDK_WINDDK71_LIB_WNET ?= $(PATH_SDK_WINDDK71_LIB_WNET.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK71_LIB_WXP.x86 ?= $(PATH_SDK_WINDDK71_LIB_WXP_ROOT)/i386 PATH_SDK_WINDDK71_LIB_WXP ?= $(PATH_SDK_WINDDK71_LIB_WXP.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK71_LIB_W2K.x86 ?= $(PATH_SDK_WINDDK71_LIB_W2K_ROOT)/i386 PATH_SDK_WINDDK71_LIB_W2K ?= $(PATH_SDK_WINDDK71_LIB_W2K.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK71_LIB.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) PATH_SDK_WINDDK71_LIB.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) PATH_SDK_WINDDK71_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) PATH_SDK_WINDDK71_LIB ?= $(PATH_SDK_WINDDK71_LIB.$(KBUILD_TARGET_ARCH)) # General Properties used by kBuild SDK_WINDDK71_DEFS.amd64 ?= _AMD64_ AMD64 _WIN64 SDK_WINDDK71_DEFS.ia64 ?= _IA64_=1 IA64=1 _WIN64 _MSC_EXTENSIONS SDK_WINDDK71_DEFS.x86 ?= _X86_=1 i386=1 STD_CALL SDK_WINDDK71_INCS ?= \ $(PATH_SDK_WINDDK71_INC_API) \ $(PATH_SDK_WINDDK71_INC_DDK) # The compiler tool(s) will have to select the appropriate crt includes. SDK_WINDDK71_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) SDK_WINDDK71_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) SDK_WINDDK71_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) kbuild-2695/kBuild/sdks/WIN64SDK.kmk0000644000000000000000000000723712247157310015477 0ustar rootroot# $Id: WIN64SDK.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Windows Platform SDK, targeting AMD64. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WIN64SDK := The Windows Platform SDK, targeting AMD64. # SDK Specific Properties ifndef PATH_SDK_WIN64SDK PATH_SDK_WIN64SDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*) ifeq ($(PATH_SDK_WIN64SDK),) PATH_SDK_WIN64SDK := $(PATH_SDK_WINPSDK) endif ifeq ($(PATH_SDK_WIN64SDK),) PATH_SDK_WIN64SDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*) endif ifneq ($(PATH_SDK_WIN64SDK),) PATH_SDK_WIN64SDK := $(lastword $(sort $(PATH_SDK_WIN64SDK))) else $(warning kBuild: PATH_SDK_WIN64SDK couldn't be determined!) PATH_SDK_WIN64SDK := $(PATH_DEVTOOLS)/win.amd64/sdk/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_WIN64SDK := $(PATH_SDK_WIN64SDK) endif ifndef PATH_SDK_WIN64SDK_INC PATH_SDK_WIN64SDK_INC := $(firstword $(wildcard $(PATH_SDK_WIN64SDK)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WIN64SDK)/Include) endif ifndef PATH_SDK_WIN64SDK_LIB PATH_SDK_WIN64SDK_LIB := $(firstword $(wildcard $(PATH_SDK_WIN64SDK)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64 $(PATH_SDK_WIN64SDK)/[Ll][Ii][Bb]/[xX]64) $(PATH_SDK_WIN64SDK)/Lib/AMD64) endif ifndef PATH_SDK_WIN64SDK_BIN PATH_SDK_WIN64SDK_BIN := $(firstword $(wildcard $(PATH_SDK_WIN64SDK)/[Bb][Ii][Nn]) $(PATH_SDK_WIN64SDK)/Bin) endif ifndef PATH_SDK_WIN64SDK_BIN_AMD64 PATH_SDK_WIN64SDK_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WIN64SDK_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64 $(PATH_SDK_WIN64SDK_BIN)/[Ww][Ii][Nn]64/[Xx]86) $(PATH_SDK_WIN64SDK_BIN)/win64/AMD64) endif # General Properties used by kBuild SDK_WIN64SDK_INCS ?= $(PATH_SDK_WIN64SDK_INC) SDK_WIN64SDK_LIBPATH ?= $(PATH_SDK_WIN64SDK_LIB) SDK_WIN64SDK_LIBS ?= \ $(PATH_SDK_WIN64SDK_LIB)/Kernel32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/User32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/Gdi32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/AdvAPI32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/Shell32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/ShLwApi.Lib \ $(PATH_SDK_WIN64SDK_LIB)/SetupAPI.Lib \ $(PATH_SDK_WIN64SDK_LIB)/Uuid.Lib \ $(PATH_SDK_WIN64SDK_LIB)/Version.Lib \ $(PATH_SDK_WIN64SDK_LIB)/WS2_32.Lib \ \ $(PATH_SDK_WIN64SDK_LIB)/Ole32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/OleAut32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/OleDlg.Lib \ $(PATH_SDK_WIN64SDK_LIB)/RpcRT4.Lib \ \ $(PATH_SDK_WIN64SDK_LIB)/DbgHelp.Lib \ $(PATH_SDK_WIN64SDK_LIB)/ImageHlp.Lib \ $(PATH_SDK_WIN64SDK_LIB)/IPHlpApi.Lib \ $(PATH_SDK_WIN64SDK_LIB)/ComCtl32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/ComDlg32.Lib \ $(PATH_SDK_WIN64SDK_LIB)/WinSpool.Lib \ $(PATH_SDK_WIN64SDK_LIB)/WinMM.Lib kbuild-2695/kBuild/sdks/LIBSDL.kmk0000644000000000000000000001357212247157310015276 0ustar rootroot# $Id: LIBSDL.kmk 2566 2012-03-02 12:58:25Z bird $ ## @file # kBuild SDK - Simple DirectMedia Layer, targeting $(KBUILD_TARGET). # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_LIBSDL := Simple DirectMedia Layer, targeting $(KBUILD_TARGET). # SDK Specific Properties _SDK_LIBSDK_IS_FRAMEWORK := no ifndef PATH_SDK_LIBSDL PATH_SDK_LIBSDL := $(wildcard $(PATH_DEVTOOLS_TRG)/libsdl/v*) ifeq ($(PATH_SDK_LIBSDL),) PATH_SDK_LIBSDL := $(wildcard $(PATH_DEVTOOLS_BLD)/libsdl/v*) endif ifneq ($(PATH_SDK_LIBSDL),) PATH_SDK_LIBSDL := $(lastword $(sort $(PATH_SDK_LIBSDL))) else # Darwin might have a framework for it. ifeq ($(KBUILD_TARGET),darwin) PATH_SDK_LIBSDL := $(firstword $(wildcard \ /System/Library/Frameworks/SDL.framework/SDL \ /Library/Frameworks/SDL.framework/SDL \ ) ) ifneq ($(PATH_SDK_LIBSDL),) PATH_SDK_LIBSDL := $(patsubst %/,%,$(dir $(PATH_SDK_LIBSDL))) _SDK_LIBSDK_IS_FRAMEWORK := yes endif endif ifeq ($(PATH_SDK_LIBSDL),) PATH_SDK_LIBSDL := $(firstword $(foreach root,$(KBUILD_LIB_SEARCH_ROOTS) \ ,$(if $(wildcard $(addsuffix libSDL.*,$(addprefix $(root),$(KBUILD_LIB_SEARCH_SUBS)))),$(root),) )) ifeq ($(PATH_SDK_LIBSDL),/) PATH_SDK_LIBSDL := /. else ifneq ($(PATH_SDK_LIBSDL),) PATH_SDK_LIBSDL := $(patsubst %/,%,$(PATH_SDK_LIBSDL)) else $(warning kBuild: PATH_SDK_LIBSDL couldn't be determined!) PATH_SDK_LIBSDL := $(PATH_DEVTOOLS_TRG)/libsdl/not/found endif endif endif else PATH_SDK_LIBSDL := $(PATH_SDK_LIBSDL) ifeq ($(KBUILD_TARGET),darwin) # Check if it's the framework or not. _SDK_LIBSDK_IS_FRAMEWORK := $(if $(wildcard $(PATH_SDK_LIBSDL)/Headers/SDL.h),yes) endif endif # # The way libsdl is distributed on the different platforms # varies quite a bit, thus this kludge. # ifeq ($(KBUILD_TARGET),os2) LIB_SDK_LIBSDL_SDLMAIN ?= DLL_SDK_LIBSDL_SDL ?= $(PATH_SDK_LIBSDL)/SDL/SDL12.dll DLL_SDK_LIBSDL_FSLIB ?= $(PATH_SDK_LIBSDL)/SDL/FSLib.dll LIB_SDK_LIBSDL_SDL ?= $(PATH_SDK_LIBSDL)/SDL/SDL12.lib LIB_SDK_LIBSDL_SDLGFX ?= $(PATH_SDK_LIBSDL)/SDLGfx/SDLGFX.lib LIB_SDK_LIBSDL_SDLIMAGE ?= $(PATH_SDK_LIBSDL)/SDLImage/SDLIMAGE.lib LIB_SDK_LIBSDL_SDLMIXER ?= $(PATH_SDK_LIBSDL)/SDLMixer/SDLMIXER.lib LIB_SDK_LIBSDL_SDLNET ?= $(PATH_SDK_LIBSDL)/SDLNet/SDLNET.lib LIB_SDK_LIBSDL_SDLTTF ?= $(PATH_SDK_LIBSDL)/SDLTTF/SDLTTF.lib # General Properties used by kBuild SDK_LIBSDL_INCS ?= \ $(PATH_SDK_LIBSDL)/SDL/include \ $(PATH_SDK_LIBSDL)/SDLGfx \ $(PATH_SDK_LIBSDL)/SDLImage \ $(PATH_SDK_LIBSDL)/SDLMixer \ $(PATH_SDK_LIBSDL)/SDLNet \ $(PATH_SDK_LIBSDL)/SDLTTF SDK_LIBSDL_LIBS ?= \ $(LIB_SDK_LIBSDL_SDL) SDK_LIBSDL_LIBPATH ?= \ $(PATH_SDK_LIBSDL)/SDL \ $(PATH_SDK_LIBSDL)/SDLGfx \ $(PATH_SDK_LIBSDL)/SDLImage \ $(PATH_SDK_LIBSDL)/SDLMixer \ $(PATH_SDK_LIBSDL)/SDLNet \ $(PATH_SDK_LIBSDL)/SDLTTF else ifeq ($(KBUILD_TARGET),win) # ASSUMES VC++ on windows, sorry. LIB_SDK_LIBSDL_SDLMAIN ?= $(PATH_SDK_LIBSDL)/lib/SDLmain.lib LIB_SDK_LIBSDL_SDL ?= $(PATH_SDK_LIBSDL)/lib/SDL.lib DLL_SDK_LIBSDL_SDL ?= $(PATH_SDK_LIBSDL)/lib/SDL.dll LIB_SDK_LIBSDL_SDLGFX ?= $(PATH_SDK_LIBSDL)/lib/SDL_gfx.lib LIB_SDK_LIBSDL_SDLIMAGE ?= $(PATH_SDK_LIBSDL)/lib/SDL_image.lib LIB_SDK_LIBSDL_SDLMIXER ?= $(PATH_SDK_LIBSDL)/lib/SDL_mixer.lib LIB_SDK_LIBSDL_SDLNET ?= $(PATH_SDK_LIBSDL)/lib/SDL_net.lib LIB_SDK_LIBSDL_SDLTTF ?= $(PATH_SDK_LIBSDL)/lib/SDL_ttf.lib DLL_SDK_LIBSDL_SDLTTF ?= $(PATH_SDK_LIBSDL)/lib/SDL_ttf.dll # General Properties used by kBuild SDK_LIBSDL_INCS ?= \ $(PATH_SDK_LIBSDL)/include/SDL \ $(PATH_SDK_LIBSDL)/include SDK_LIBSDL_LIBS ?= \ $(LIB_SDK_LIBSDL_SDL) SDK_LIBSDL_LIBPATH ?= \ $(PATH_SDK_LIBSDL)/lib else ifeq ($(KBUILD_TARGET).$(_SDK_LIBSDK_IS_FRAMEWORK),darwin.yes) # darwin + framework LIB_SDK_LIBSDL_SDLMAIN ?= $(NO_SUCH_VARIABLE) LIB_SDK_LIBSDL_SDL ?= $(NO_SUCH_VARIABLE) LIB_SDK_LIBSDL_SDLGFX ?= $(NO_SUCH_VARIABLE) LIB_SDK_LIBSDL_SDLIMAGE ?= $(NO_SUCH_VARIABLE) LIB_SDK_LIBSDL_SDLMIXER ?= $(NO_SUCH_VARIABLE) LIB_SDK_LIBSDL_SDLNET ?= $(NO_SUCH_VARIABLE) LIB_SDK_LIBSDL_SDLTTF ?= $(NO_SUCH_VARIABLE) # General Properties used by kBuild SDK_LIBSDL_INCS ?= $(PATH_SDK_LIBSDL)/Headers SDK_LIBSDL_LDFLAGS ?= -framework SDL else # ASSUMES Unix like system LIB_SDK_LIBSDL_SDLMAIN ?= SDLmain LIB_SDK_LIBSDL_SDL ?= SDL LIB_SDK_LIBSDL_SDLGFX ?= SDL_gfx LIB_SDK_LIBSDL_SDLIMAGE ?= SDL_image LIB_SDK_LIBSDL_SDLMIXER ?= SDL_mixer LIB_SDK_LIBSDL_SDLNET ?= SDL_net LIB_SDK_LIBSDL_SDLTTF ?= SDL_ttf # General Properties used by kBuild ifndef SDK_LIBSDL_INCS ifneq ($(wildcard $(PATH_SDK_LIBSDL)/include/SDL/),) SDK_LIBSDL_INCS := $(PATH_SDK_LIBSDL)/include/SDL else SDK_LIBSDL_INCS := $(PATH_SDK_LIBSDL)/include endif endif SDK_LIBSDL_LIBS ?= \ $(LIB_SDK_LIBSDL_SDL) SDK_LIBSDL_LIBPATH ?= \ $(PATH_SDK_LIBSDL)/lib endif kbuild-2695/kBuild/sdks/WINDDKWXP.kmk0000644000000000000000000000350112247157310015673 0ustar rootroot# $Id: WINDDKWXP.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows XP (x86). # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDKWXP := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows XP (x86). SDK_WINDDKWXP_EXTENDS = WINDDK SDK_WINDDKWXP_DEFS ?= WIN32=100 _WIN32_WINNT=0x0501 WINVER=0x0501 _WIN32_IE=0x0603 NTDDI_VERSION=0x05010200 SDK_WINDDKWXP_LIBPATH.x86 ?= $(PATH_SDK_WINDDK_LIB_WXP.x86) # SDK Specific Properties. # Note! extends the WINDDK sdk, so use those variables where ever possible PATH_SDK_WINDDKWXP_LIB.x86 ?= $(PATH_SDK_WINDDK_LIB_WXP.x86) PATH_SDK_WINDDKWXP_LIB ?= $(PATH_SDK_WINDDKWXP_LIB.x86) kbuild-2695/kBuild/sdks/WINDDKWLH.kmk0000644000000000000000000000424412247157310015654 0ustar rootroot# $Id: WINDDKWLH.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Vista and 2008 (KBUILD_TARGET_ARCH). # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDKWLH := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Vista and 2008 (KBUILD_TARGET_ARCH). SDK_WINDDKWLH_EXTENDS = WINDDK SDK_WINDDKWLH_DEFS ?= WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 SDK_WINDDKWLH_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WLH.amd64) SDK_WINDDKWLH_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64) SDK_WINDDKWLH_LIBPATH.x86 ?= $(PATH_SDK_WINDDK_LIB_WLH.x86) # SDK Specific Properties. # Note! extends the WINDDK sdk, so use those variables where ever possible PATH_SDK_WINDDKWLH_LIB.amd64?= $(PATH_SDK_WINDDK_LIB_WLH.amd64) PATH_SDK_WINDDKWLH_LIB.ia64 ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64) PATH_SDK_WINDDKWLH_LIB.x86 ?= $(PATH_SDK_WINDDK_LIB_WLH.x86) PATH_SDK_WINDDKWLH_LIB ?= $(PATH_SDK_WINDDKWLH_LIB.$(KBUILD_TARGET_ARCH)) kbuild-2695/kBuild/sdks/WIN32SDK.kmk0000644000000000000000000000656412247157310015474 0ustar rootroot# $Id: WIN32SDK.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Windows Platform SDK, targeting x86. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WIN32SDK := The Windows Platform SDK, targeting x86. # SDK Specific Properties ifndef PATH_SDK_WIN32SDK PATH_SDK_WIN32SDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*) ifeq ($(PATH_SDK_WIN32SDK),) PATH_SDK_WIN32SDK := $(PATH_SDK_WINPSDK) endif ifeq ($(PATH_SDK_WIN32SDK),) PATH_SDK_WIN32SDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2*) endif ifeq ($(PATH_SDK_WIN32SDK),) PATH_SDK_WIN32SDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*) endif ifneq ($(PATH_SDK_WIN32SDK),) PATH_SDK_WIN32SDK := $(lastword $(sort $(PATH_SDK_WIN32SDK))) else $(warning kBuild: PATH_SDK_WIN32SDK couldn't be determined!) PATH_SDK_WIN32SDK := $(PATH_DEVTOOLS)/win.x86/sdk/not/found endif endif ifndef PATH_SDK_WIN32SDK_INC PATH_SDK_WIN32SDK_INC := $(firstword $(wildcard $(PATH_SDK_WIN32SDK)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WIN32SDK)/Include) endif ifndef PATH_SDK_WIN32SDK_LIB PATH_SDK_WIN32SDK_LIB := $(firstword $(wildcard $(PATH_SDK_WIN32SDK)/[Ll][Ii][Bb]) $(PATH_SDK_WIN32SDK)/Lib) endif ifndef PATH_SDK_WIN32SDK_BIN PATH_SDK_WIN32SDK_BIN := $(firstword $(wildcard $(PATH_SDK_WIN32SDK)/[Bb][Ii][Nn]) $(PATH_SDK_WIN32SDK)/Bin) endif # General Properties used by kBuild SDK_WIN32SDK_INCS ?= $(PATH_SDK_WIN32SDK_INC) SDK_WIN32SDK_LIBPATH ?= $(PATH_SDK_WIN32SDK_LIB) SDK_WIN32SDK_LIBS ?= \ $(PATH_SDK_WIN32SDK_LIB)/Kernel32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/User32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/Gdi32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/AdvAPI32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/Shell32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/ShLwApi.Lib \ $(PATH_SDK_WIN32SDK_LIB)/SetupAPI.Lib \ $(PATH_SDK_WIN32SDK_LIB)/Uuid.Lib \ $(PATH_SDK_WIN32SDK_LIB)/Version.Lib \ $(PATH_SDK_WIN32SDK_LIB)/WS2_32.Lib \ \ $(PATH_SDK_WIN32SDK_LIB)/Ole32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/OleAut32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/OleDlg.Lib \ $(PATH_SDK_WIN32SDK_LIB)/RpcRT4.Lib \ \ $(PATH_SDK_WIN32SDK_LIB)/DbgHelp.Lib \ $(PATH_SDK_WIN32SDK_LIB)/ImageHlp.Lib \ $(PATH_SDK_WIN32SDK_LIB)/IPHlpApi.Lib \ $(PATH_SDK_WIN32SDK_LIB)/ComCtl32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/ComDlg32.Lib \ $(PATH_SDK_WIN32SDK_LIB)/WinSpool.Lib \ $(PATH_SDK_WIN32SDK_LIB)/WinMM.Lib \ kbuild-2695/kBuild/sdks/WINDDK80.kmk0000644000000000000000000001033212247157310015444 0ustar rootroot# $Id: WINDDK80.kmk 2607 2012-07-20 12:12:58Z bird $ ## @file # kBuild SDK - The Microsoft Windows 8 DDK. # Defaults to $(KBUILD_TARGET_ARCH). Base SDK. # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDK80 := The Microsoft Windows 8 DDK. \ Defaults to $(KBUILD_TARGET_ARCH). Base SDK. # SDK Specific Properties ifndef PATH_SDK_WINDDK80 PATH_SDK_WINDDK80 := $(wildcard $(PATH_DEVTOOLS_TRG)/ddk/v8*) ifeq ($(PATH_SDK_WINDDK80),) PATH_SDK_WINDDK80 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddk/v8*) endif ifeq ($(PATH_SDK_WINDDK80),) PATH_SDK_WINDDK80 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddk/v8*) endif ifneq ($(PATH_SDK_WINDDK80),) PATH_SDK_WINDDK80 := $(lastword $(sort $(PATH_SDK_WINDDK80))) else $(warning kBuild: PATH_SDK_WINDDK80 couldn't be determined!) PATH_SDK_WINDDK80 := $(PATH_DEVTOOLS)/win.x86/ddk/v8.0/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_WINDDK80 := $(PATH_SDK_WINDDK80) endif PATH_SDK_WINDDK80_INC ?= $(PATH_SDK_WINDDK80)/Include PATH_SDK_WINDDK80_INC_UM ?= $(PATH_SDK_WINDDK80_INC)/um PATH_SDK_WINDDK80_INC_KM ?= $(PATH_SDK_WINDDK80_INC)/km PATH_SDK_WINDDK80_INC_KM_CRT ?= $(PATH_SDK_WINDDK80_INC_KM)/crt PATH_SDK_WINDDK80_INC_SHARED ?= $(PATH_SDK_WINDDK80_INC)/Shared PATH_SDK_WINDDK80_LIB_ROOT ?= $(PATH_SDK_WINDDK80)/Lib PATH_SDK_WINDDK80_LIB_W8_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/win8 PATH_SDK_WINDDK80_LIB_W7_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/win7 PATH_SDK_WINDDK80_LIB_WLH_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/wlh PATH_SDK_WINDDK80_LIB_WDF_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/wdf PATH_SDK_WINDDK80_LIB_MFC_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/Mfc PATH_SDK_WINDDK80_LIB_ATL_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/Atl PATH_SDK_WINDDK80_LIB_W8.amd64 ?= $(PATH_SDK_WINDDK80_LIB_W8_ROOT)/km/x64 PATH_SDK_WINDDK80_LIB_W8.x86 ?= $(PATH_SDK_WINDDK80_LIB_W8_ROOT)/km/x86 PATH_SDK_WINDDK80_LIB_W8 ?= $(PATH_SDK_WINDDK80_LIB_W8.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK80_LIB_W7.amd64 ?= $(PATH_SDK_WINDDK80_LIB_W7_ROOT)/km/x64 PATH_SDK_WINDDK80_LIB_W7.x86 ?= $(PATH_SDK_WINDDK80_LIB_W7_ROOT)/km/x86 PATH_SDK_WINDDK80_LIB_W7 ?= $(PATH_SDK_WINDDK80_LIB_W7.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK80_LIB_WLH.amd64 ?= $(PATH_SDK_WINDDK80_LIB_WLH_ROOT)/km/x64 PATH_SDK_WINDDK80_LIB_WLH.x86 ?= $(PATH_SDK_WINDDK80_LIB_WLH_ROOT)/km/x86 PATH_SDK_WINDDK80_LIB_WLH ?= $(PATH_SDK_WINDDK80_LIB_WLH.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK80_LIB.amd64 ?= $(PATH_SDK_WINDDK80_LIB_WLH.amd64) PATH_SDK_WINDDK80_LIB.x86 ?= $(PATH_SDK_WINDDK80_LIB_WLH.x86) PATH_SDK_WINDDK80_LIB ?= $(PATH_SDK_WINDDK80_LIB.$(KBUILD_TARGET_ARCH)) # General Properties used by kBuild SDK_WINDDK80_DEFS.amd64 ?= _AMD64_ AMD64 _WIN64 SDK_WINDDK80_DEFS.x86 ?= _X86_=1 i386=1 STD_CALL SDK_WINDDK80_INCS ?= \ $(PATH_SDK_WINDDK80_INC_KM) \ $(PATH_SDK_WINDDK80_INC_UM) \ $(PATH_SDK_WINDDK80_INC_SHARED) \ # The compiler tool(s) will have to select the appropriate crt includes. SDK_WINDDK80_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK80_LIB_WLH.amd64) SDK_WINDDK80_LIBPATH.x86 ?= $(PATH_SDK_WINDDK80_LIB_WLH.x86) kbuild-2695/kBuild/sdks/W2K3DDKAMD64.kmk0000644000000000000000000000513112247157310016022 0ustar rootroot# $Id: W2K3DDKAMD64.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows 2003 DDK, targeting amd64. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_W2K3DDKAMD64 := The Microsoft Windows 2003 DDK, targeting amd64. # SDK Specific Properties ifndef PATH_SDK_W2K3DDKAMD64 PATH_SDK_W2K3DDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/2*) ifeq ($(PATH_SDK_W2K3DDKAMD64),) PATH_SDK_W2K3DDKAMD64 := $(PATH_SDK_W2K3DDK) endif ifeq ($(PATH_SDK_W2K3DDKAMD64),) PATH_SDK_W2K3DDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/2*) endif # legacy: ifeq ($(PATH_SDK_W2K3DDKAMD64),) PATH_SDK_W2K3DDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/2*) endif ifneq ($(PATH_SDK_W2K3DDKAMD64),) PATH_SDK_W2K3DDKAMD64 := $(lastword $(sort $(PATH_SDK_W2K3DDKAMD64))) else $(warning kBuild: PATH_SDK_W2K3DDKAMD64 couldn't be determined!) PATH_SDK_W2K3DDKAMD64 := $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_W2K3DDKAMD64 := $(PATH_SDK_W2K3DDKAMD64) endif PATH_SDK_W2K3DDKAMD64_INC ?= $(PATH_SDK_W2K3DDKAMD64)/inc PATH_SDK_W2K3DDKAMD64_LIB ?= $(PATH_SDK_W2K3DDKAMD64)/lib/wnet/AMD64 # General Properties used by kBuild SDK_W2K3DDKAMD64_DEFS ?= _AMD64_ SDK_W2K3DDKAMD64_INCS ?= \ $(PATH_SDK_W2K3DDKAMD64_INC)/ddk \ $(PATH_SDK_W2K3DDKAMD64_INC)/ddk/wnet \ $(PATH_SDK_W2K3DDKAMD64_INC)/wnet \ $(PATH_SDK_W2K3DDKAMD64_INC)/ddk/wdm/wnet SDK_W2K3DDKAMD64_LIBPATH ?= \ $(PATH_SDK_W2K3DDKAMD64_LIB) kbuild-2695/kBuild/sdks/DXSDK.kmk0000644000000000000000000000474012247157310015177 0ustar rootroot# $Id: DXSDK.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Direct X SDK, targeting $(KBUILD_TARGET). # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_DXSDK := The Microsoft Direct X SDK, targeting $(KBUILD_TARGET) # SDK Specific Properties ifndef PATH_SDK_DXSDK ## @todo which order is logical here, BLD and then TRG or the other way? PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/dxsdk/2*)) ifeq ($(PATH_SDK_DXSDK),) PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS_TRG)/dxsdk/2*)) endif ifeq ($(PATH_SDK_DXSDK),) PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS)/win.x86/dxsdk/2*)) endif ifeq ($(PATH_SDK_DXSDK),) PATH_SDK_DXSDK := $(sort $(wildcard $(PATH_DEVTOOLS)/win.amd64/dxsdk/2*)) endif ifneq ($(PATH_SDK_DXSDK),) PATH_SDK_DXSDK := $(call lastword,$(PATH_SDK_DXSDK)) else $(warning kBuild: PATH_SDK_DXSDK couldn't be determined!) PATH_SDK_DXSDK := $(PATH_DEVTOOLS_TRG)/dxsdk/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_DXSDK := $(PATH_SDK_DXSDK) endif PATH_SDK_DXSDK_INC ?= $(PATH_SDK_DXSDK)/Include PATH_SDK_DXSDK_LIB.x86 ?= $(PATH_SDK_DXSDK)/Lib/x86 PATH_SDK_DXSDK_LIB.amd64 ?= $(PATH_SDK_DXSDK)/Lib/x64 PATH_SDK_DXSDK_LIB ?= $(PATH_SDK_DXSDK_LIB.$(KBUILD_TARGET_ARCH)) # General Properties used by kBuild SDK_DXSDK_INCS ?= $(PATH_SDK_DXSDK_INC) SDK_DXSDK_LIBPATH ?= $(PATH_SDK_DXSDK_LIB) kbuild-2695/kBuild/sdks/WINDDK71WXP.kmk0000644000000000000000000000347312247157310016053 0ustar rootroot# $Id: WINDDK71WXP.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Microsoft Windows 7 DDK, v7.1, Targeting Windows XP (x86). # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDK71WXP := The Microsoft Windows 7 DDK, v7.1, Targeting Windows XP (x86). SDK_WINDDK71WXP_EXTENDS = WINDDK71 SDK_WINDDK71WXP_DEFS ?= WIN32=100 _WIN32_WINNT=0x0501 WINVER=0x0501 _WIN32_IE=0x0603 NTDDI_VERSION=0x05010200 SDK_WINDDK71WXP_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WXP.x86) # SDK Specific Properties. # Note! extends the WINDDK71 sdk, so use those variables where ever possible PATH_SDK_WINDDK71WXP_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WXP.x86) PATH_SDK_WINDDK71WXP_LIB ?= $(PATH_SDK_WINDDK71WXP_LIB.x86) kbuild-2695/kBuild/sdks/WINPSDK.kmk0000644000000000000000000001450412247157310015440 0ustar rootroot# $Id: WINPSDK.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Windows Platform SDK, targeting (KBUILD_TARGET). # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINPSDK := The Windows Platform SDK, targeting (KBUILD_TARGET). # SDK Specific Properties ifndef PATH_SDK_WINPSDK PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/2*) ifeq ($(PATH_SDK_WINPSDK),) PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/2*) endif ifeq ($(PATH_SDK_WINPSDK),) PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*) endif ifeq ($(PATH_SDK_WINPSDK),) PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*) endif ifneq ($(PATH_SDK_WINPSDK),) PATH_SDK_WINPSDK := $(lastword $(sort $(PATH_SDK_WINPSDK))) else $(warning kBuild: PATH_SDK_WINPSDK couldn't be determined!) PATH_SDK_WINPSDK := $(PATH_DEVTOOLS_BLD)/sdk/not/found endif else PATH_SDK_WINPSDK := $(PATH_SDK_WINPSDK) endif ifndef PATH_SDK_WINPSDK_INC PATH_SDK_WINPSDK_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDK)/Include) endif ifndef PATH_SDK_WINPSDK_LIB.x86 PATH_SDK_WINPSDK_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDK)/Lib) endif ifndef PATH_SDK_WINPSDK_LIB.amd64 PATH_SDK_WINPSDK_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK)/[Ll][Ii][Bb]/[xX]64) $(PATH_SDK_WINPSDK)/Lib/AMD64) endif ifndef PATH_SDK_WINPSDK_LIB.ia64 PATH_SDK_WINPSDK_LIB.ia64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Ll][Ii][Bb]/[Ii][Aa]64) $(PATH_SDK_WINPSDK)/Lib/IA64) endif PATH_SDK_WINPSDK_LIB ?= $(PATH_SDK_WINPSDK_LIB.$(KBUILD_TARGET_ARCH)) ifndef PATH_SDK_WINPSDK_BIN PATH_SDK_WINPSDK_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDK)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDK)/Bin) endif ifndef PATH_SDK_WINPSDK_BIN_AMD64 PATH_SDK_WINPSDK_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK_BIN)/[Ww][Ii][Nn]64/[Xx]86) $(PATH_SDK_WINPSDK_BIN)/win64/AMD64) endif ifndef PATH_SDK_WINPSDK_BIN_IA64 PATH_SDK_WINPSDK_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDK_BIN)/win64) endif # General Properties used by kBuild SDK_WINPSDK_INCS ?= $(PATH_SDK_WINPSDK_INC) SDK_WINPSDK_LIBPATH.x86 ?= $(PATH_SDK_WINPSDK_LIB.x86) SDK_WINPSDK_LIBPATH.amd64 ?= $(PATH_SDK_WINPSDK_LIB.amd64) SDK_WINPSDK_LIBPATH.ia64 ?= $(PATH_SDK_WINPSDK_LIB.ia64) SDK_WINPSDK_LIBS.x86 ?= \ $(PATH_SDK_WINPSDK_LIB.x86)/Kernel32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/User32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/Gdi32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/AdvAPI32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/Shell32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/ShLwApi.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/SetupAPI.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/Uuid.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/Version.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/WS2_32.Lib \ \ $(PATH_SDK_WINPSDK_LIB.x86)/Ole32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/OleAut32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/OleDlg.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/RpcRT4.Lib \ \ $(PATH_SDK_WINPSDK_LIB.x86)/DbgHelp.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/ImageHlp.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/IPHlpApi.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/ComCtl32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/ComDlg32.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/WinSpool.Lib \ $(PATH_SDK_WINPSDK_LIB.x86)/WinMM.Lib SDK_WINPSDK_LIBS.amd64 ?= \ $(PATH_SDK_WINPSDK_LIB.amd64)/Kernel32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/User32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/Gdi32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/AdvAPI32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/Shell32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/ShLwApi.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/SetupAPI.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/Uuid.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/Version.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/WS2_32.Lib \ \ $(PATH_SDK_WINPSDK_LIB.amd64)/Ole32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/OleAut32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/OleDlg.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/RpcRT4.Lib \ \ $(PATH_SDK_WINPSDK_LIB.amd64)/DbgHelp.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/ImageHlp.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/IPHlpApi.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/ComCtl32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/ComDlg32.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/WinSpool.Lib \ $(PATH_SDK_WINPSDK_LIB.amd64)/WinMM.Lib SDK_WINPSDK_LIBS.ia64 ?= \ $(PATH_SDK_WINPSDK_LIB.ia64)/Kernel32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/User32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/Gdi32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/AdvAPI32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/Shell32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/ShLwApi.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/SetupAPI.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/Uuid.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/Version.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/WS2_32.Lib \ \ $(PATH_SDK_WINPSDK_LIB.ia64)/Ole32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/OleAut32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/OleDlg.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/RpcRT4.Lib \ \ $(PATH_SDK_WINPSDK_LIB.ia64)/DbgHelp.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/ImageHlp.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/IPHlpApi.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/ComCtl32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/ComDlg32.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/WinSpool.Lib \ $(PATH_SDK_WINPSDK_LIB.ia64)/WinMM.Lib kbuild-2695/kBuild/sdks/ReorderCompilerIncs.kmk0000644000000000000000000000464712247157310020242 0ustar rootroot# $Id: ReorderCompilerIncs.kmk 2603 2012-07-12 20:26:28Z bird $ ## @file # kBuild SDK - Pseudo SDK that inserts the compiler includes a bit earlier. # # Note! This SDK is using a number of internal kBuild variables as well as # making assumptions about expansion order and location. # Please, do NOT attempt anything like this in your own SDKs!! # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_ReorderCompilerIncs := Pseudo SDK that inserts the compiler includes a bit earlier. FN_SDK_ReorderCompilerIncs_GET_INCS = \ $(TOOL_$(tool)_$(1)INCS.$(2).$(3).$(5)) \ $(TOOL_$(tool)_$(1)INCS.$(2).$(3)) \ $(TOOL_$(tool)_$(1)INCS.$(2).$(5)) \ $(TOOL_$(tool)_$(1)INCS.$(4)) \ $(TOOL_$(tool)_$(1)INCS.$(3)) \ $(TOOL_$(tool)_$(1)INCS.$(2)) \ $(TOOL_$(tool)_$(1)INCS.$(5)) \ $(TOOL_$(tool)_$(1)INCS) \ $(TOOL_$(tool)_INCS.$(2).$(3).$(5)) \ $(TOOL_$(tool)_INCS.$(2).$(3)) \ $(TOOL_$(tool)_INCS.$(2).$(5)) \ $(TOOL_$(tool)_INCS.$(4)) \ $(TOOL_$(tool)_INCS.$(3)) \ $(TOOL_$(tool)_INCS.$(2)) \ $(TOOL_$(tool)_INCS.$(5)) \ $(TOOL_$(tool)_INCS) \ $(foreach os,$(KBUILD_OSES),$(foreach arch,$(KBUILD_ARCHES),$(foreach cat,$(KBUILD_COMPILE_CATEGTORIES) \ ,$(eval SDK_ReorderCompilerIncs_$(cat)INCS.$(os).$(arch) = \ $$(call FN_SDK_ReorderCompilerIncs_GET_INCS,CXX,win,amd64,$$(bld_trg_cpu),$$(bld_type))\ )\ ))) kbuild-2695/kBuild/sdks/MACOSX104.kmk0000644000000000000000000000377712247157310015552 0ustar rootroot# $Id: MACOSX104.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - Mac OS X v10.4 SDK. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_MACOSX104 := Mac OS X v10.4 SDK # SDK Specific Properties ifndef PATH_SDK_MACOSX104 PATH_SDK_MACOSX104 := /Developer/SDKs/MacOSX10.4u.sdk else # Resolve any fancy stuff once and for all. PATH_SDK_MACOSX104 := $(PATH_SDK_MACOSX104) endif # General Properties (used by kBuild) # Note: The MAC_OS_X_VERSION_MAX_ALLOWED is left free for the SDK user to define. SDK_MACOSX104_DEFS ?= MAC_OS_X_VERSION_MIN_REQUIRED=1040 SDK_MACOSX104_CFLAGS ?= -mmacosx-version-min=10.4 -isysroot $(PATH_SDK_MACOSX104) SDK_MACOSX104_CXXFLAGS ?= -mmacosx-version-min=10.4 -isysroot $(PATH_SDK_MACOSX104) SDK_MACOSX104_OBJCFLAGS ?= -mmacosx-version-min=10.4 -isysroot $(PATH_SDK_MACOSX104) SDK_MACOSX104_LDFLAGS ?= -mmacosx-version-min=10.4 -Wl,-syslibroot,$(PATH_SDK_MACOSX104) kbuild-2695/kBuild/sdks/WINDDK71WLH.kmk0000644000000000000000000000426012247157310016022 0ustar rootroot# $Id: WINDDK71WLH.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Microsoft Windows 7 DDKs, v7.1, Targeting Vista and 2008 (KBUILD_TARGET_ARCH). # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDK71WLH := The Microsoft Windows 7 DDKs, v7.1, Targeting Vista and 2008 (KBUILD_TARGET_ARCH). SDK_WINDDK71WLH_EXTENDS = WINDDK71 SDK_WINDDK71WLH_DEFS ?= WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 SDK_WINDDK71WLH_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) SDK_WINDDK71WLH_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) SDK_WINDDK71WLH_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) # SDK Specific Properties. # Note! extends the WINDDK71 sdk, so use those variables where ever possible PATH_SDK_WINDDK71WLH_LIB.amd64?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) PATH_SDK_WINDDK71WLH_LIB.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) PATH_SDK_WINDDK71WLH_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) PATH_SDK_WINDDK71WLH_LIB ?= $(PATH_SDK_WINDDK71WLH_LIB.$(KBUILD_TARGET_ARCH)) kbuild-2695/kBuild/sdks/W2K3DDK.kmk0000644000000000000000000000577112247157310015340 0ustar rootroot# $Id: W2K3DDK.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows 2003 DDK, targeting $(KBUILD_TARGET). # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_W2K3DDK := The Microsoft Windows 2003 DDK, targeting $(KBUILD_TARGET). # SDK Specific Properties ifndef PATH_SDK_W2K3DDK PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS_TRG)/ddkwin2k3/2*) ifeq ($(PATH_SDK_W2K3DDK),) PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS_BLD)/ddkwin2k3/2*) endif ifeq ($(PATH_SDK_W2K3DDK),) PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/2*) endif ifeq ($(PATH_SDK_W2K3DDK),) PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/2*) endif ifeq ($(PATH_SDK_W2K3DDK),) PATH_SDK_W2K3DDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/2*) endif ifeq ($(PATH_SDK_W2K3DDK),) ifneq ($(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/lib/wnet/i386/*.lib),) PATH_SDK_W2K3DDK := $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3 endif endif ifneq ($(PATH_SDK_W2K3DDK),) PATH_SDK_W2K3DDK := $(lastword $(sort $(PATH_SDK_W2K3DDK))) else $(warning kBuild: PATH_SDK_W2K3DDK couldn't be determined!) PATH_SDK_W2K3DDK := $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_W2K3DDK := $(PATH_SDK_W2K3DDK) endif PATH_SDK_W2K3DDK_INC ?= $(PATH_SDK_W2K3DDK)/inc PATH_SDK_W2K3DDK_LIB.amd64 ?= $(PATH_SDK_W2K3DDK)/lib/wnet/AMD64 PATH_SDK_W2K3DDK_LIB.x86 ?= $(PATH_SDK_W2K3DDK)/lib/wnet/i386 PATH_SDK_W2K3DDK_LIB ?= $(PATH_SDK_W2K3DDK_LIB.$(KBUILD_TARGET_ARCH)) # General Properties used by kBuild SDK_W2K3DDK_DEFS.amd64 ?= _AMD64_ SDK_W2K3DDK_DEFS.x86 ?= _X86_ SDK_W2K3DDK_INCS ?= \ $(PATH_SDK_W2K3DDK_INC)/ddk \ $(PATH_SDK_W2K3DDK_INC)/ddk/wnet \ $(PATH_SDK_W2K3DDK_INC)/wnet \ $(PATH_SDK_W2K3DDK_INC)/ddk/wdm/wnet SDK_W2K3DDK_LIBPATH.amd64 ?= $(PATH_SDK_W2K3DDK_LIB.amd64) SDK_W2K3DDK_LIBPATH.x86 ?= $(PATH_SDK_W2K3DDK_LIB.x86) kbuild-2695/kBuild/sdks/WINDDK.kmk0000644000000000000000000001741712247157310015307 0ustar rootroot# $Id: WINDDK.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs. # Defaults to $(KBUILD_TARGET_ARCH). Base SDK. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDK := The Microsoft Windows Vista and Server 2008 DDKs. \ Defaults to $(KBUILD_TARGET_ARCH). Base SDK. # SDK Specific Properties ifndef PATH_SDK_WINDDK PATH_SDK_WINDDK := $(wildcard $(PATH_DEVTOOLS_TRG)/ddk/6*) ifeq ($(PATH_SDK_WINDDK),) PATH_SDK_WINDDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddk/6*) endif ifeq ($(PATH_SDK_WINDDK),) PATH_SDK_WINDDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddk/6*) endif ifeq ($(PATH_SDK_WINDDK),) ifeq ($(KBUILD_HOST),win) PATH_SDK_WINDDK := $(wildcard C:/WinDDK/6*) endif endif ifneq ($(PATH_SDK_WINDDK),) PATH_SDK_WINDDK := $(lastword $(sort $(PATH_SDK_WINDDK))) else $(warning kBuild: PATH_SDK_WINDDK couldn't be determined!) PATH_SDK_WINDDK := $(PATH_DEVTOOLS)/win.x86/ddk/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_WINDDK := $(PATH_SDK_WINDDK) endif PATH_SDK_WINDDK_INC ?= $(PATH_SDK_WINDDK)/inc PATH_SDK_WINDDK_INC_API ?= $(PATH_SDK_WINDDK_INC)/api PATH_SDK_WINDDK_INC_CRT ?= $(PATH_SDK_WINDDK_INC)/crt PATH_SDK_WINDDK_INC_DDK ?= $(PATH_SDK_WINDDK_INC)/ddk PATH_SDK_WINDDK_LIB_ROOT ?= $(PATH_SDK_WINDDK)/lib PATH_SDK_WINDDK_LIB_WLH_ROOT ?= $(PATH_SDK_WINDDK_LIB_ROOT)/wlh PATH_SDK_WINDDK_LIB_WNET_ROOT ?= $(PATH_SDK_WINDDK_LIB_ROOT)/wnet PATH_SDK_WINDDK_LIB_WXP_ROOT ?= $(PATH_SDK_WINDDK_LIB_ROOT)/wxp PATH_SDK_WINDDK_LIB_W2K_ROOT ?= $(PATH_SDK_WINDDK_LIB_ROOT)/w2k PATH_SDK_WINDDK_LIB_WDF_ROOT ?= $(PATH_SDK_WINDDK_LIB_ROOT)/w2k PATH_SDK_WINDDK_LIB_WLH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WLH_ROOT)/amd64 PATH_SDK_WINDDK_LIB_WLH.ia64 ?= $(PATH_SDK_WINDDK_LIB_WLH_ROOT)/ia64 PATH_SDK_WINDDK_LIB_WLH.x86 ?= $(PATH_SDK_WINDDK_LIB_WLH_ROOT)/i386 PATH_SDK_WINDDK_LIB_WLH ?= $(PATH_SDK_WINDDK_LIB_WLH.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK_LIB_WNET.amd64?= $(PATH_SDK_WINDDK_LIB_WNET_ROOT)/amd64 PATH_SDK_WINDDK_LIB_WNET.ia64 ?= $(PATH_SDK_WINDDK_LIB_WNET_ROOT)/ia64 PATH_SDK_WINDDK_LIB_WNET.x86 ?= $(PATH_SDK_WINDDK_LIB_WNET_ROOT)/i386 PATH_SDK_WINDDK_LIB_WNET ?= $(PATH_SDK_WINDDK_LIB_WNET.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK_LIB_WXP.x86 ?= $(PATH_SDK_WINDDK_LIB_WXP_ROOT)/i386 PATH_SDK_WINDDK_LIB_WXP ?= $(PATH_SDK_WINDDK_LIB_WXP.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK_LIB_W2K.x86 ?= $(PATH_SDK_WINDDK_LIB_W2K_ROOT)/i386 PATH_SDK_WINDDK_LIB_W2K ?= $(PATH_SDK_WINDDK_LIB_W2K.$(KBUILD_TARGET_ARCH)) PATH_SDK_WINDDK_LIB.amd64 ?= $(PATH_SDK_WINDDK_LIB_WLH.amd64) PATH_SDK_WINDDK_LIB.ia64 ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64) PATH_SDK_WINDDK_LIB.x86 ?= $(PATH_SDK_WINDDK_LIB_WLH.x86) PATH_SDK_WINDDK_LIB ?= $(PATH_SDK_WINDDK_LIB.$(KBUILD_TARGET_ARCH)) # General Properties used by kBuild SDK_WINDDK_DEFS.amd64 ?= _AMD64_ AMD64 _WIN64 SDK_WINDDK_DEFS.ia64 ?= _IA64_=1 IA64=1 _WIN64 _MSC_EXTENSIONS SDK_WINDDK_DEFS.x86 ?= _X86_=1 i386=1 STD_CALL SDK_WINDDK_INCS ?= \ $(PATH_SDK_WINDDK_INC_API) \ $(PATH_SDK_WINDDK_INC_DDK) # The compiler tool(s) will have to select the appropriate crt includes. SDK_WINDDK_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WLH.amd64) SDK_WINDDK_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK_LIB_WLH.ia64) SDK_WINDDK_LIBPATH.x86 ?= $(PATH_SDK_WINDDK_LIB_WLH.x86) # # CDFS defines for the various build environments. Just to give an idea what # you should put in your templates and target DEFS. # # Vista / Server Longhorn x64 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL # Vista / Server Longhorn ia64 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL NO_HW_DETECT _MSC_EXTENSIONS _MERCED_A0_=1 FPO=0 # Vista / Server Longhorn x86 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0 # Windows Server 2003 amd64 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL # Windows Server 2003 ia64 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL NO_HW_DETECT _MSC_EXTENSIONS _MERCED_A0_=1 FPO=0 # Windows Server 2003 x86 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0 # Windows XP Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0501 WINVER=0x0501 _WIN32_IE=0x0603 NTDDI_VERSION=0x05010200 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0 # Windows 2000 Free: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0500 WINVER=0x0500 _WIN32_IE=0x0501 NTDDI_VERSION=0x05000400 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0 # Windows 2000 Checked: NT_INST=0 WIN32=100 _WIN32_WINNT=0x0500 WINVER=0x0500 _WIN32_IE=0x0501 NTDDI_VERSION=0x05000400 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 WIN32_LEAN_AND_MEAN=1 CONDITION_HANDLING=1 DEVL=1 NDEBUG __BUILDMACHINE__=WinDDK _DLL STD_CALL FPO=0 MSC_NOOPT # Some notes about the defines: # NTDDI_VERSION indicates the target NT version, looks kind of important to get right. # _WIN32_WINNT, WINVER and _WIN32_IE are used by a bunch of headers for selecting features. # WIN32_LEAN_AND_MEAN is used by api\WINDOWS.H to drop a bunch of includes. # WIN32 is just used for some ifdef'ing by a handful headers. # __BUILDMACHINE__ is used by api\common.ver (for resources it seems). # STD_CALL is used by ddk\stdcall.inc (masm). # DEVL governs the IF_NTOS_DEBUG() macro in ddk\wdm.h. # NDEBUG is used by crt\assert.h dictated by the standards. # CONDITION_HANDLING, FPO, KMDF_MAJOR_VERSION, KMDF_MINOR_VERSION, MSC_NOOPT and NT_INST are not referenced in any headers. kbuild-2695/kBuild/sdks/DXSDKX86.kmk0000644000000000000000000000426612247157310015510 0ustar rootroot# $Id: DXSDKX86.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Direct X SDK, targeting X86. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_DXSDKX86 := The Microsoft Direct X SDK, targeting X86. # SDK Specific Properties ifndef PATH_SDK_DXSDKX86 PATH_SDK_DXSDKX86 := $(wildcard $(PATH_DEVTOOLS)/win.x86/dxsdk/2*) ifeq ($(PATH_SDK_DXSDKX86),) PATH_SDK_DXSDKX86 := $(PATH_SDK_DXSDK) endif ifeq ($(PATH_SDK_DXSDKX86),) PATH_SDK_DXSDKX86 := $(wildcard $(PATH_DEVTOOLS)/amd64.win/dxsdk/2*) endif ifneq ($(PATH_SDK_DXSDKX86),) PATH_SDK_DXSDKX86 := $(lastword $(sort $(PATH_SDK_DXSDKX86))) else $(warning kBuild: PATH_SDK_DXSDKX86 couldn't be determined!) PATH_SDK_DXSDKX86 := $(PATH_DEVTOOLS)/win.x86/dxsdk/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_DXSDKX86 := $(PATH_SDK_DXSDKX86) endif PATH_SDK_DXSDKX86_INC ?= $(PATH_SDK_DXSDKX86)/Include PATH_SDK_DXSDKX86_LIB ?= $(PATH_SDK_DXSDKX86)/Lib/x86 # General Properties used by kBuild SDK_DXSDKX86_INCS ?= $(PATH_SDK_DXSDKX86_INC) SDK_DXSDKX86_LIBPATH ?= $(PATH_SDK_DXSDKX86_LIB) kbuild-2695/kBuild/sdks/NT4DDK.kmk0000644000000000000000000000420512247157310015246 0ustar rootroot# $Id: NT4DDK.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Windows NT 4 DDK, targeting X86. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_NT4DDK := The MicroSoft NT 4 DDK, targeting X86 (free, not checked). # SDK Specific Properties ifndef PATH_SDK_NT4DDK PATH_SDK_NT4DDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddknt4/1* $(PATH_DEVTOOLS)/win.x86/ddknt4/2*) ifeq ($(PATH_SDK_NT4DDK),) PATH_SDK_NT4DDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddknt4) endif ifneq ($(PATH_SDK_NT4DDK),) PATH_SDK_NT4DDK := $(lastword $(sort $(PATH_SDK_NT4DDK))) else $(warning kBuild: PATH_SDK_NT4DDK couldn't be determined!) PATH_SDK_NT4DDK := $(PATH_DEVTOOLS)/x86.win/ddknt4/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_NT4DDK := $(PATH_SDK_NT4DDK) endif PATH_SDK_NT4DDK_INC ?= $(PATH_SDK_NT4DDK)/inc PATH_SDK_NT4DDK_LIB ?= $(PATH_SDK_NT4DDK)/lib/i386/free # General Properties used by kBuild SDK_NT4DDK_DEFS ?= _X86_ SDK_NT4DDK_INCS ?= $(PATH_SDK_NT4DDK_INC) SDK_NT4DDK_LIBPATH ?= $(PATH_SDK_NT4DDK_LIB) kbuild-2695/kBuild/sdks/MACOSX104INCS.kmk0000644000000000000000000000332712247157310016216 0ustar rootroot# $Id: MACOSX104INCS.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - Mac OS X v10.4 SDK, includes only. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_MACOSX104INCS := Mac OS X v10.4 SDK # SDK Specific Properties ifndef PATH_SDK_MACOSX104INCS ifdef PATH_SDK_MACOSX104 PATH_SDK_MACOSX104INCS := $(PATH_SDK_MACOSX104) else PATH_SDK_MACOSX104INCS := /Developer/SDKs/MacOSX10.4u.sdk endif else # Resolve any fancy stuff once and for all. PATH_SDK_MACOSX104INCS := $(PATH_SDK_MACOSX104INCS) endif # General Properties (used by kBuild) SDK_MACOSX104INCS_INCS = $(PATH_SDK_MACOSX104INCS)/usr/include kbuild-2695/kBuild/sdks/WINDDKWNET.kmk0000644000000000000000000000422312247157310015774 0ustar rootroot# $Id: WINDDKWNET.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH). # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDKWNET := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH). SDK_WINDDKWNET_EXTENDS = WINDDK SDK_WINDDKWNET_DEFS ?= WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 SDK_WINDDKWNET_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK_LIB_WNET.amd64) SDK_WINDDKWNET_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK_LIB_WNET.ia64) SDK_WINDDKWNET_LIBPATH.x86 ?= $(PATH_SDK_WINDDK_LIB_WNET.x86) # SDK Specific Properties. # Note! extends the WINDDK sdk, so use those variables where ever possible PATH_SDK_WINDDKWNET_LIB.amd64?= $(PATH_SDK_WINDDK_LIB_WNET.amd64) PATH_SDK_WINDDKWNET_LIB.ia64 ?= $(PATH_SDK_WINDDK_LIB_WNET.ia64) PATH_SDK_WINDDKWNET_LIB.x86 ?= $(PATH_SDK_WINDDK_LIB_WNET.x86) PATH_SDK_WINDDKWNET_LIB ?= $(PATH_SDK_WINDDKWNET_LIB.$(KBUILD_TARGET_ARCH)) kbuild-2695/kBuild/sdks/MACOSX105.kmk0000644000000000000000000000377612247157310015552 0ustar rootroot# $Id: MACOSX105.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - Mac OS X v10.5 SDK. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_MACOSX105 := Mac OS X v10.5 SDK # SDK Specific Properties ifndef PATH_SDK_MACOSX105 PATH_SDK_MACOSX105 := /Developer/SDKs/MacOSX10.5.sdk else # Resolve any fancy stuff once and for all. PATH_SDK_MACOSX105 := $(PATH_SDK_MACOSX105) endif # General Properties (used by kBuild) # Note: The MAC_OS_X_VERSION_MAX_ALLOWED is left free for the SDK user to define. SDK_MACOSX105_DEFS ?= MAC_OS_X_VERSION_MIN_REQUIRED=1050 SDK_MACOSX105_CFLAGS ?= -mmacosx-version-min=10.5 -isysroot $(PATH_SDK_MACOSX105) SDK_MACOSX105_CXXFLAGS ?= -mmacosx-version-min=10.5 -isysroot $(PATH_SDK_MACOSX105) SDK_MACOSX105_OBJCFLAGS ?= -mmacosx-version-min=10.5 -isysroot $(PATH_SDK_MACOSX105) SDK_MACOSX105_LDFLAGS ?= -mmacosx-version-min=10.5 -Wl,-syslibroot,$(PATH_SDK_MACOSX105) kbuild-2695/kBuild/sdks/WINPSDK71INCS.kmk0000644000000000000000000000737012247157310016270 0ustar rootroot# $Id: WINPSDK71INCS.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Windows Platform SDK v7.1, targeting (KBUILD_TARGET) but # without any libraries or LIBPATH properties. # Basically for finding specstrings.h when using the DDK. # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINPSDK71INCS := The Windows Platform SDK v7.1, targeting (KBUILD_TARGET) but \ without any library or LIBPATH properties. \ Basically for finding specstrings.h when using the DDK. # SDK Specific Properties ifndef PATH_SDK_WINPSDK71INCS ifdef PATH_SDK_WINPSDK71 PATH_SDK_WINPSDK71INCS := $(PATH_SDK_WINPSDK71) else PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/v7.1*) ifeq ($(PATH_SDK_WINPSDK71INCS),) PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/v7.1*) endif ifeq ($(PATH_SDK_WINPSDK71INCS),) PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/v7.1*) endif ifeq ($(PATH_SDK_WINPSDK71INCS),) PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/v7.1*) endif ifneq ($(PATH_SDK_WINPSDK71INCS),) PATH_SDK_WINPSDK71INCS := $(lastword $(sort $(PATH_SDK_WINPSDK71INCS))) else $(warning kBuild: PATH_SDK_WINPSDK71INCS couldn't be determined!) PATH_SDK_WINPSDK71INCS := $(PATH_DEVTOOLS_BLD)/sdk/v7.1-not-found endif endif else PATH_SDK_WINPSDK71INCS := $(PATH_SDK_WINPSDK71INCS) endif ifndef PATH_SDK_WINPSDK71INCS_INC PATH_SDK_WINPSDK71INCS_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDK71INCS)/Include) endif ifndef PATH_SDK_WINPSDK71INCS_LIB.x86 PATH_SDK_WINPSDK71INCS_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDK71INCS)/Lib) endif ifndef PATH_SDK_WINPSDK71INCS_LIB.amd64 PATH_SDK_WINPSDK71INCS_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDK71INCS)/Lib/AMD64) endif PATH_SDK_WINPSDK71INCS_LIB ?= $(PATH_SDK_WINPSDK71INCS_LIB.$(KBUILD_TARGET_ARCH)) ifndef PATH_SDK_WINPSDK71INCS_BIN PATH_SDK_WINPSDK71INCS_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDK71INCS)/Bin) endif ifndef PATH_SDK_WINPSDK71INCS_BIN_AMD64 PATH_SDK_WINPSDK71INCS_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDK71INCS_BIN)/win64/AMD64) endif ifndef PATH_SDK_WINPSDK71INCS_BIN_IA64 PATH_SDK_WINPSDK71INCS_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDK71INCS_BIN)/win64) endif # General Properties used by kBuild SDK_WINPSDK71INCS_INCS ?= $(PATH_SDK_WINPSDK71INCS_INC) kbuild-2695/kBuild/sdks/WINPSDKINCS.kmk0000644000000000000000000000736012247157310016117 0ustar rootroot# $Id: WINPSDKINCS.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Windows Platform SDK, targeting (KBUILD_TARGET) but # without any libraries or LIBPATH properties. # Basically for finding specstrings.h when using the DDK. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINPSDKINCS := The Windows Platform SDK, targeting (KBUILD_TARGET) but \ without any library or LIBPATH properties. \ Basically for finding specstrings.h when using the DDK. # SDK Specific Properties ifndef PATH_SDK_WINPSDKINCS ifdef PATH_SDK_WINPSDK PATH_SDK_WINPSDKINCS := $(PATH_SDK_WINPSDK) else PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/2*) ifeq ($(PATH_SDK_WINPSDKINCS),) PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/2*) endif ifeq ($(PATH_SDK_WINPSDKINCS),) PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*) endif ifeq ($(PATH_SDK_WINPSDKINCS),) PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2*) endif ifeq ($(PATH_SDK_WINPSDKINCS),) PATH_SDK_WINPSDKINCS := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*) endif ifneq ($(PATH_SDK_WINPSDKINCS),) PATH_SDK_WINPSDKINCS := $(lastword $(sort $(PATH_SDK_WINPSDKINCS))) else $(warning kBuild: PATH_SDK_WINPSDKINCS couldn't be determined!) PATH_SDK_WINPSDKINCS := $(PATH_DEVTOOLS_BLD)/sdk/not/found endif endif else PATH_SDK_WINPSDKINCS := $(PATH_SDK_WINPSDKINCS) endif ifndef PATH_SDK_WINPSDKINCS_INC PATH_SDK_WINPSDKINCS_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDKINCS)/Include) endif ifndef PATH_SDK_WINPSDKINCS_LIB.x86 PATH_SDK_WINPSDKINCS_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDKINCS)/Lib) endif ifndef PATH_SDK_WINPSDKINCS_LIB.amd64 PATH_SDK_WINPSDKINCS_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDKINCS)/Lib/AMD64) endif PATH_SDK_WINPSDKINCS_LIB ?= $(PATH_SDK_WINPSDKINCS_LIB.$(KBUILD_TARGET_ARCH)) ifndef PATH_SDK_WINPSDKINCS_BIN PATH_SDK_WINPSDKINCS_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDKINCS)/Bin) endif ifndef PATH_SDK_WINPSDKINCS_BIN_AMD64 PATH_SDK_WINPSDKINCS_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDKINCS_BIN)/win64/AMD64) endif ifndef PATH_SDK_WINPSDKINCS_BIN_IA64 PATH_SDK_WINPSDKINCS_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDKINCS_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDKINCS_BIN)/win64) endif # General Properties used by kBuild SDK_WINPSDKINCS_INCS ?= $(PATH_SDK_WINPSDKINCS_INC) kbuild-2695/kBuild/sdks/WINDDK71WNET.kmk0000644000000000000000000000423712247157310016151 0ustar rootroot# $Id: WINDDK71WNET.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Microsoft Windows 7 DDKs, v7.1, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH). # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDK71WNET := The Microsoft Windows 7 DDKs, v7.1, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH). SDK_WINDDK71WNET_EXTENDS = WINDDK71 SDK_WINDDK71WNET_DEFS ?= WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 SDK_WINDDK71WNET_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WNET.amd64) SDK_WINDDK71WNET_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WNET.ia64) SDK_WINDDK71WNET_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WNET.x86) # SDK Specific Properties. # Note! extends the WINDDK71 sdk, so use those variables where ever possible PATH_SDK_WINDDK71WNET_LIB.amd64?= $(PATH_SDK_WINDDK71_LIB_WNET.amd64) PATH_SDK_WINDDK71WNET_LIB.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WNET.ia64) PATH_SDK_WINDDK71WNET_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WNET.x86) PATH_SDK_WINDDK71WNET_LIB ?= $(PATH_SDK_WINDDK71WNET_LIB.$(KBUILD_TARGET_ARCH)) kbuild-2695/kBuild/sdks/W2K3DDKX86.kmk0000644000000000000000000000520712247157310015640 0ustar rootroot# $Id: W2K3DDKX86.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows 2003 DDK, targeting x86. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_W2K3DDKX86 := The Microsoft Windows 2003 DDK, targeting x86. # SDK Specific Properties ifndef PATH_SDK_W2K3DDKX86 PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddkwin2k3/2*) ifeq ($(PATH_SDK_W2K3DDKX86),) PATH_SDK_W2K3DDKX86 := $(PATH_SDK_W2K3DDK) endif ifeq ($(PATH_SDK_W2K3DDKX86),) PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddkwin2k3/2*) endif # legacy: ifeq ($(PATH_SDK_W2K3DDKX86),) PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3/2*) endif ifeq ($(PATH_SDK_W2K3DDKX86),) PATH_SDK_W2K3DDKX86 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/ddkwin2k3) endif ifneq ($(PATH_SDK_W2K3DDKX86),) PATH_SDK_W2K3DDKX86 := $(lastword $(sort $(PATH_SDK_W2K3DDKX86))) else $(warning kBuild: PATH_SDK_W2K3DDKX86 couldn't be determined!) PATH_SDK_W2K3DDKX86 := $(PATH_DEVTOOLS)/x86.win/ddkwin2k3/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_W2K3DDKX86 := $(PATH_SDK_W2K3DDKX86) endif PATH_SDK_W2K3DDKX86_INC ?= $(PATH_SDK_W2K3DDKX86)/inc PATH_SDK_W2K3DDKX86_LIB ?= $(PATH_SDK_W2K3DDKX86)/lib/wnet/i386 # General Properties used by kBuild SDK_W2K3DDKX86_DEFS ?= _X86_ SDK_W2K3DDKX86_INCS ?= \ $(PATH_SDK_W2K3DDKX86_INC)/ddk \ $(PATH_SDK_W2K3DDKX86_INC)/ddk/wnet \ $(PATH_SDK_W2K3DDKX86_INC)/wnet \ $(PATH_SDK_W2K3DDKX86_INC)/ddk/wdm/wnet SDK_W2K3DDKX86_LIBPATH ?= \ $(PATH_SDK_W2K3DDKX86_LIB) kbuild-2695/kBuild/sdks/WINDDKW2K.kmk0000644000000000000000000000350512247157310015624 0ustar rootroot# $Id: WINDDKW2K.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows 2000 (x86). # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDKW2K := The Microsoft Windows Vista and Server 2008 DDKs, Targeting Windows 2000 (x86). SDK_WINDDKW2K_EXTENDS = WINDDK SDK_WINDDKW2K_DEFS ?= WIN32=100 _WIN32_WINNT=0x0500 WINVER=0x0500 _WIN32_IE=0x0501 NTDDI_VERSION=0x05000400 SDK_WINDDKW2K_LIBPATH.x86 ?= $(PATH_SDK_WINDDK_LIB_W2K.x86) # SDK Specific Properties. # Note! extends the WINDDK sdk, so use those variables where ever possible PATH_SDK_WINDDKW2K_LIB.x86 ?= $(PATH_SDK_WINDDK_LIB_W2K.x86) PATH_SDK_WINDDKW2K_LIB ?= $(PATH_SDK_WINDDKW2K_LIB.x86) kbuild-2695/kBuild/sdks/WINDDK80W8.kmk0000644000000000000000000000401112247157310015660 0ustar rootroot# $Id: WINDDK80W8.kmk 2607 2012-07-20 12:12:58Z bird $ ## @file # kBuild SDK - The Microsoft Windows 8 DDKs, Targeting Windows 8 (KBUILD_TARGET_ARCH). # # # Copyright (c) 2006-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WINDDK80W8 := The Microsoft Windows 8 DDKs, Targeting Windows 8 (KBUILD_TARGET_ARCH). SDK_WINDDK80W8_EXTENDS = WINDDK80 SDK_WINDDK80W8_DEFS ?= WIN32=100 _WIN32_WINNT=0x0602 WINVER=0x0602 _WIN32_IE=0x0A00 NTDDI_VERSION=0x06020000 \ KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 SDK_WINDDK80W8_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK80_LIB_W8.amd64) SDK_WINDDK80W8_LIBPATH.x86 ?= $(PATH_SDK_WINDDK80_LIB_W8.x86) # SDK Specific Properties. # Note! extends the WINDDK80 sdk, so use those variables where ever possible PATH_SDK_WINDDK80W8_LIB.amd64?= $(PATH_SDK_WINDDK80_LIB_W8.amd64) PATH_SDK_WINDDK80W8_LIB.x86 ?= $(PATH_SDK_WINDDK80_LIB_W8.x86) PATH_SDK_WINDDK80W8_LIB ?= $(PATH_SDK_WINDDK80W8_LIB.$(KBUILD_TARGET_ARCH)) kbuild-2695/kBuild/sdks/W32API.kmk0000644000000000000000000000404412247157310015224 0ustar rootroot# $Id: W32API.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - w32api (MinGW), targeting x86. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_W32API := w32api (MinGW), targeting x86. # SDK Specific Properties ifndef PATH_SDK_W32API PATH_SDK_W32API := $(wildcard $(PATH_DEVTOOLS)/win.x86/w32api/v*) ifeq ($(PATH_SDK_W32API),) PATH_SDK_W32API := $(wildcard $(PATH_DEVTOOLS)/x86.win32/w32api/v*) endif ifneq ($(PATH_SDK_W32API),) PATH_SDK_W32API := $(lastword $(sort $(PATH_SDK_W32API))) else $(warning kBuild: PATH_SDK_W32API couldn't be determined!) PATH_SDK_W32API := $(PATH_DEVTOOLS)/x86.win/w32api/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_W32API := $(PATH_SDK_W32API) endif PATH_SDK_W32API_INC ?= $(PATH_SDK_W32API)/include PATH_SDK_W32API_LIB ?= $(PATH_SDK_W32API)/lib # General Properties used by kBuild SDK_W32API_INCS ?= $(PATH_SDK_W32API_INC) SDK_W32API_LIBPATH ?= $(PATH_SDK_W32API_LIB) kbuild-2695/kBuild/sdks/WIN32SDK2002.kmk0000644000000000000000000000667712247157310016005 0ustar rootroot# $Id: WIN32SDK2002.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - Windows Platform SDK (from ~2002), targeting x86. # Differs in that it has ddraw.lib and dxguid.lib. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_WIN32SDK2002 := Windows Platform SDK (from ~2002), targeting x86. \ Differs in that it has ddraw.lib and dxguid.lib. # SDK Specific Properties ifndef PATH_SDK_WIN32SDK2002 PATH_SDK_WIN32SDK2002 := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2002*) ifeq ($(PATH_SDK_WIN32SDK2002),) PATH_SDK_WIN32SDK2002 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2002*) endif ifeq ($(PATH_SDK_WIN32SDK2002),) PATH_SDK_WIN32SDK2002 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk2002*) endif ifneq ($(PATH_SDK_WIN32SDK2002),) PATH_SDK_WIN32SDK2002 := $(lastword $(sort $(PATH_SDK_WIN32SDK2002))) else $(warning kBuild: PATH_SDK_WIN32SDK2002 couldn't be determined!) PATH_SDK_WIN32SDK2002 := $(PATH_DEVTOOLS)/win.x86/sdk/2002/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_WIN32SDK2002 := $(PATH_SDK_WIN32SDK2002) endif PATH_SDK_WIN32SDK2002_INC ?= $(PATH_SDK_WIN32SDK2002)/include PATH_SDK_WIN32SDK2002_LIB ?= $(PATH_SDK_WIN32SDK2002)/lib # General Properties used by kBuild SDK_WIN32SDK2002_INCS ?= $(PATH_SDK_WIN32SDK2002_INC) SDK_WIN32SDK2002_LIBPATH ?= $(PATH_SDK_WIN32SDK2002_LIB) SDK_WIN32SDK2002_LIBS ?= \ $(PATH_SDK_WIN32SDK2002_LIB)/Kernel32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/User32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/Gdi32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/AdvAPI32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/Shell32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/ShLwApi.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/SetupAPI.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/Uuid.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/Version.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/WS2_32.Lib \ \ $(PATH_SDK_WIN32SDK2002_LIB)/Ole32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/OleAut32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/OleDlg.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/RpcRT4.Lib \ \ $(PATH_SDK_WIN32SDK2002_LIB)/DbgHelp.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/ImageHlp.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/IPHlpApi.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/ddraw.lib \ $(PATH_SDK_WIN32SDK2002_LIB)/dxguid.lib \ $(PATH_SDK_WIN32SDK2002_LIB)/ComCtl32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/ComDlg32.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/WinSpool.Lib \ $(PATH_SDK_WIN32SDK2002_LIB)/WinMM.Lib kbuild-2695/kBuild/sdks/DXSDKAMD64.kmk0000644000000000000000000000435112247157310015671 0ustar rootroot# $Id: DXSDKAMD64.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild SDK - The Microsoft Direct X SDK, targeting AMD64. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # SDK_DXSDKAMD64 := The Microsoft Direct X SDK, targeting AMD64. # SDK Specific Properties ifndef PATH_SDK_DXSDKAMD64 PATH_SDK_DXSDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/dxsdk/2*) ifeq ($(PATH_SDK_DXSDKAMD64),) PATH_SDK_DXSDKAMD64 := $(PATH_SDK_DXSDK) endif ifeq ($(PATH_SDK_DXSDKAMD64),) PATH_SDK_DXSDKAMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/dxsdk/2*) endif ifneq ($(PATH_SDK_DXSDKAMD64),) PATH_SDK_DXSDKAMD64 := $(lastword $(sort $(PATH_SDK_DXSDKAMD64))) else $(warning kBuild: PATH_SDK_DXSDKAMD64 couldn't be determined!) PATH_SDK_DXSDKAMD64 := $(PATH_DEVTOOLS)/win.amd64/dxsdk/not/found endif else # Resolve any fancy stuff once and for all. PATH_SDK_DXSDKAMD64 := $(PATH_SDK_DXSDKAMD64) endif PATH_SDK_DXSDKAMD64_INC ?= $(PATH_SDK_DXSDKAMD64)/Include PATH_SDK_DXSDKAMD64_LIB ?= $(PATH_SDK_DXSDKAMD64)/Lib/x64 # General Properties used by kBuild SDK_DXSDKAMD64_INCS ?= $(PATH_SDK_DXSDKAMD64_INC) SDK_DXSDKAMD64_LIBPATH ?= $(PATH_SDK_DXSDKAMD64_LIB) kbuild-2695/kBuild/COPYING0000644000000000000000000004310312247157310013701 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. kbuild-2695/kBuild/footer-pass2-compiling-targets.kmk0000644000000000000000000010656012247157310021333 0ustar rootroot# $Id: footer-pass2-compiling-targets.kmk 2551 2011-11-09 13:28:02Z bird $ ## @file # kBuild - Footer - Target lists - Pass 2 - Compiling Targets. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version source of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # # Object processing. # ## wrapper the compile command dependency check. ifndef NO_COMPILE_CMDS_DEPS if1of ($(KMK_FEATURES),dot-must-make) _DEP_COMPILE_CMDS = # for debugging: $$(warning MUST_MAKE=$$$$(comp-cmds-ex $$$$($(target)_$(subst :,_,$(source))_CMDS_PREV_), $$$$(commands $$@)) -> $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_CMDS_PREV_),$$(commands $$@),FORCE)) else _DEP_COMPILE_CMDS = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_CMDS_PREV_),$$(commands $(obj)),FORCE) endif else _DEP_COMPILE_CMDS = endif ## Generates the rules for building a specific object, and the aliases # for building a source file. # @param $(obj) The object file. define def_target_source_rule ifndef NO_COMPILE_CMDS_DEPS $(obj): .MUST_MAKE = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_CMDS_PREV_),$$(commands $$@),FORCE) endif ifdef TOOL_$(tool)_COMPILE_$(type)_USES_KOBJCACHE _OUT_FILES += $(outbase).koc $(outbase).koc +| $(obj) $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_) : \ $($(target)_$(source)_DEPEND_) \ $(value _DEP_COMPILE_CMDS) \ | \ $($(target)_$(source)_DEPORD_) \ $$$$($(target)_INTERMEDIATES) \ $$$$($(target)_INTERMEDIATES.$(bld_trg)) \ $$$$($(target)_INTERMEDIATES.$(bld_trg).$(bld_trg_arch)) \ $$$$($(target)_INTERMEDIATES.$(bld_trg_arch)) \ $$$$($(target)_INTERMEDIATES.$(bld_trg_cpu)) \ $$$$($(target)_INTERMEDIATES.$(bld_type)) %$$(call MSG_COMPILE,$(target),$(source),$$@,$(type)) else $(obj) + $($(target)_$(source)_OUTPUT_) +| $($(target)_$(source)_OUTPUT_MAYBE_) : \ $($(target)_$(source)_DEPEND_) \ $(value _DEP_COMPILE_CMDS) \ | \ $($(target)_$(source)_DEPORD_) \ $$$$($(target)_INTERMEDIATES) \ $$$$($(target)_INTERMEDIATES.$(bld_trg)) \ $$$$($(target)_INTERMEDIATES.$(bld_trg).$(bld_trg_arch)) \ $$$$($(target)_INTERMEDIATES.$(bld_trg_arch)) \ $$$$($(target)_INTERMEDIATES.$(bld_trg_cpu)) \ $$$$($(target)_INTERMEDIATES.$(bld_type)) %$$(call MSG_COMPILE,$(target),$(source),$$@,$(type)) ifdef TOOL_$(tool)_COMPILE_$(type)_DONT_PURGE_OUTPUT $$(QUIET)$$(RM) -f -- $(dep) $(obj) $($(target)_$(source)_OUTPUT_) $($(target)_OUTPUT_MAYBE_) endif endif $($(target)_$(source)_CMDS_) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(obj)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(basename $(notdir $(obj))).o: $(obj) $(basename $(notdir $(obj))).obj: $(obj) ## @todo make this 'local cmds,output,output_maybe,depend and depord' in 0.2.x or when a new kb-src-one is added. $(target)_$(source)_CMDS_ := $(target)_$(source)_OUTPUT_ := $(target)_$(source)_OUTPUT_MAYBE_ := $(target)_$(source)_DEPEND_ := $(target)_$(source)_DEPORD_ := endef # def_target_source_rule $(eval-opt-var def_target_source_rule) ## wrapper the link command dependency check. ifndef NO_LINK_CMDS_DEPS if1of ($(KMK_FEATURES),dot-must-make) _DEP_LINK_CMDS = else _DEP_LINK_CMDS = $$(comp-cmds-ex $$($(target)_CMDS_PREV_),$$(commands $(out)),FORCE) endif else _DEP_LINK_CMDS = endif ## Generate the link rule for a target. # @param $(target) The normalized target name. # @param $(dirdep) Directories we depend upon begin created before linking. # @param $(dep) The name of the dependency file. # @param $(out) # @param $($(target)_2_OUTPUT) Output files from the link. # @param $($(target)_2_OUTPUT_MAYBE) Output files that the link may perhaps create. # @param $($(target)_2_DEPEND) Dependencies. # @param $($(target)_2_DEPORD) Dependencies which should only affect build order. # @param $(cmds) The link commands. # @param $($(target)_CMDS_PREV_) The link commands from the previous run. define def_link_rule $$(call KB_FN_ASSERT_ABSPATH,out) ifndef NO_LINK_CMDS_DEPS $(out): .MUST_MAKE = $$(comp-cmds-ex $$($(target)_CMDS_PREV_),$$(commands $$@),FORCE) endif $(out) \ + $($(target)_2_OUTPUT) \ + $($(target)_2_OUTPUT_DEBUG_FILES) \ + $($(target)_2_OUTPUT_DEBUG_DIRS) \ +| $($(target)_2_OUTPUT_MAYBE) : \ $$$$($(target)_2_DEPEND) \ $(value _DEP_LINK_CMDS) \ | \ $$$$($(target)_2_DEPORD) %$$(call MSG_LINK,$(target),$$@,$(tool_do)) $$(QUIET)$$(RM) -f -- $(dep) $(out) $($(target)_2_OUTPUT) $($(target)_2_OUTPUT_MAYBE) $($(target)_2_OUTPUT_DEBUG_FILES) ifdef $(target)_2_OUTPUT_DEBUG_DIRS $$(QUIET)$$(RM) -Rf -- $($(target)_2_OUTPUT_DEBUG_DIRS) endif $(cmds) ifndef NO_LINK_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(basename $(notdir $(out))):: $(out) endef # def_link_rule $(eval-opt-var def_link_rule) ## Generate the link & lib install rule # Implicit parameters: target, out, $(target)_1_STAGE_TARGET, mode, # pre_install_cmds, post_install_cmds define def_link_install_rule $$(call KB_FN_ASSERT_ABSPATH,$(target)_1_INST_TARGET) $($(target)_1_INST_TARGET): $(out) | $$$$(dir $$$$@) %$$(call MSG_INST_TRG,$(target),$(out),$$@) $(pre_install_cmds) $$(QUIET)$$(INSTALL) $(if $(mode),-m $(mode)) $(if $(uid),-o $(uid)) $(if $(gid),-g $(gid)) -- $(out) $$@ $(post_install_cmds) endef ## Generate the link & lib stage installation rule # Implicit parameters: target, out, $(target)_1_STAGE_TARGET, mode, # pre_install_cmds, post_install_cmds define def_link_stage_rule $$(call KB_FN_ASSERT_ABSPATH,$(target)_1_STAGE_TARGET) $($(target)_1_STAGE_TARGET): $(out) | $$$$(dir $$$$@) %$$(call MSG_INST_TRG,$(target),$(out),$$@) $(pre_install_cmds) $$(QUIET)$$(INSTALL_STAGING) $(if $(mode),-m $(mode)) $(if $(uid),-o $(uid)) $(if $(gid),-g $(gid)) -- $(out) $$@ $(post_install_cmds) $(basename $(notdir $(out))):: $($(target)_1_STAGE_TARGET) endef ## def_src_handler_* # # @{ define def_src_handler_c local type := C $(kb-src-one 2) endef define def_src_handler_cxx local type := CXX $(kb-src-one 2) endef define def_src_handler_objc local type := OBJC $(kb-src-one 2) endef define def_src_handler_objcxx local type := OBJCXX $(kb-src-one 2) endef define def_src_handler_asm local type := AS $(kb-src-one 2) endef define def_src_handler_rc local type := RC $(kb-src-one 2) endef define def_src_handler_obj ifeq ($(defpath),) $(target)_2_OBJS += $(source) else $(target)_2_OBJS += $(abspathex $(source), $(defpath)) endif endef ## @} ## Handle one source. # . define def_src_handler_one local suff := $(suffix $(source)) local src_handler := $(firstword $(filter $(suff):%, $($(target)_$(source)_SRC_HANDLERS) $($(source)_SRC_HANDLERS) $(target_src_handlers) )) local handler := $(patsubst $(suff):%,%,$(src_handler)) ifneq ($(handler),) $(evalvalctx $(handler)) else othersrc += $(source) endif endef # def_src_handler_one ## Generic macro for processing all target sources. # @param $(target) Normalized target name. # @param $(defpath) # @param much-more... # @returns othersrc, $(target)_2_OBJS, ++ define def_target_sources local target_src_handlers := $($(target)_SRC_HANDLERS) $(KBUILD_SRC_HANDLERS) $(foreach source,\ $($(target)_SOURCES)\ $($(target)_SOURCES.$(bld_trg))\ $($(target)_SOURCES.$(bld_trg).$(bld_type))\ $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch))\ $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch).$(bld_type))\ $($(target)_SOURCES.$(bld_trg_arch))\ $($(target)_SOURCES.$(bld_trg_cpu))\ $($(target)_SOURCES.$(bld_type))\ ,$(evalval def_src_handler_one) ) $(foreach source,\ $($(target)_GEN_SOURCES_)\ $($(target)_GEN_SOURCES_.$(bld_trg))\ $($(target)_GEN_SOURCES_.$(bld_trg).$(bld_type))\ $($(target)_GEN_SOURCES_.$(bld_trg).$(bld_trg_arch))\ $($(target)_GEN_SOURCES_.$(bld_trg).$(bld_trg_arch).$(bld_type))\ $($(target)_GEN_SOURCES_.$(bld_trg_arch))\ $($(target)_GEN_SOURCES_.$(bld_trg_cpu))\ $($(target)_GEN_SOURCES_.$(bld_type))\ ,$(evalval def_src_handler_one) ) endef # def_target_sources $(eval-opt-var def_target_sources) ## # Install a debug directory. # @param debug_dir The directory name. define def_link_install_debug_dir_rule local dir := $(debug_inst_path)/$(debug_inst2)$(debug_dir) $$(call KB_FN_ASSERT_ABSPATH,dir) $$(dir): | $$$$(dir $$$$(patsubst %/,%,$$$$@)) %$$(call MSG_INST_DIR,$$@) $$(QUIET)$$(MKDIR) -p -- $$@ $(target)_2_DEBUG_$(debug_var)_TARGET_DIRS += $$(dir) endef # def_link_install_debug_dir_rule ## # Install a debug file. # @param debug_file Src=>Dst file pair. define def_link_install_debug_file_rule local dst := $(debug_inst_path)/$(debug_inst2)$(word 2, $(subst =>,$(SP),$(debug_file))) $$(call KB_FN_ASSERT_ABSPATH,dst) local src := $(word 1, $(subst =>,$(SP),$(debug_file))) $$(call KB_FN_ASSERT_ABSPATH,src) $$(dst): $$(src) | $$$$(dir $$$$@) %$$(call MSG_INST_FILE,$$<,$$@) $$(QUIET)$(debug_install_cmd) $(if $(mode),-m $(mode)) $(if $(uid),-o $(uid)) $(if $(gid),-g $(gid)) -- $$< $$@ $(target)_2_DEBUG_$(debug_var)_TARGET_FILES += $$(dst) endef # def_link_install_debug_file_rule ## # Install debug info to $(debug_inst), where debug_inst can be a directory or # file (just like $(inst) and $(stage). Used for both staging and installing. define def_target_install_only_debug if "$(substr $(debug_inst),-1,1)" == "/" if "$(debug_inst)" == "./" local debug_inst2 := else local debug_inst2 := $(debug_inst) endif local debug_dirs := $(patsubst $($(target)_0_OUTDIR)/%,%,$($(target)_2_OUTPUT_DEBUG_DIRS)) ifneq ($(strip $(root $(debug_dirs))),) $(error kBuild: Bad tool? debug_dirs='$(debug_dirs)', expected all to be under '$(outbase)') endif local debug_files := $(foreach file, $(patsubst $($(target)_0_OUTDIR)/%,%,$($(target)_2_OUTPUT_DEBUG_FILES)) \ ,$($(target)_0_OUTDIR)/$(file)=>$(file)) else local debug_notdir:= $(notdir $(debug_inst)) local debug_inst2 := $(dir $(debug_inst)) local debug_files := $(call TOOL_$(tool)_$(tool_do)_DEBUG_INSTALL_FN,$(out),$(outbase),$(debug_notdir)) local debug_dirs := $(filter %/,$(debug_files)) local debug_files := $(filter-out %/,$(debug_files)) endif $(foreach debug_dir, $(debug_dirs), $(eval $(def_link_install_debug_dir_rule))) $(foreach debug_file, $(debug_files), $(eval $(def_link_install_debug_file_rule))) endef ## Generic macro for generating the install rule(s) for a target. # # @param $(target) Normalized target name. # @param $(out) The output file. # @param $(typevar) The name of the variable with all the root targets of its type. # @param $(target_type_mode) The default file mode implied by the target type. define def_target_install_only if1of ($($(target)_1_INSTTYPE) $($(target)_1_DEBUG_INSTTYPE), both stage) # Determin common variables. local mode := $(firstword \ $($(target)_MODE.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_MODE.$(bld_trg).$(bld_trg_arch)) \ $($(target)_MODE.$(bld_trg).$(bld_type)) \ $($(target)_MODE.$(bld_trg_arch)) \ $($(target)_MODE.$(bld_trg)) \ $($(target)_MODE.$(bld_type)) \ $($(target)_MODE) \ $(target_type_mode) ) local uid := $(firstword \ $($(target)_UID.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_UID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_UID.$(bld_trg).$(bld_type)) \ $($(target)_UID.$(bld_trg_arch)) \ $($(target)_UID.$(bld_trg)) \ $($(target)_UID.$(bld_type)) \ $($(target)_UID) ) local gid := $(firstword \ $($(target)_GID.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_GID.$(bld_trg).$(bld_trg_arch)) \ $($(target)_GID.$(bld_trg).$(bld_type)) \ $($(target)_GID.$(bld_trg_arch)) \ $($(target)_GID.$(bld_trg)) \ $($(target)_GID.$(bld_type)) \ $($(target)_GID) ) local pre_install_cmds := $(evalcall def_fn_prop_get_first_defined,PRE_INST_CMDS) local post_install_cmds := $(evalcall def_fn_prop_get_first_defined,POST_INST_CMDS) endif ifneq ($($(target)_1_INSTTYPE),none) # Generate the rules ifeq ($($(target)_1_INSTTYPE),both) $(eval $(def_link_install_rule)) _INSTALLS_FILES += $($(target)_1_INST_TARGET) endif $(eval $(def_link_stage_rule)) _STAGE_FILES += $($(target)_1_STAGE_TARGET) $(typevar) += $($(target)_1_STAGE_TARGET) else # INSTTYPE == none $(typevar) += $(out) endif # INSTTYPE == none # Install debug info. $(target)_2_DEBUG_STAGE_TARGET_DIRS := $(target)_2_DEBUG_STAGE_TARGET_FILES := $(target)_2_DEBUG_INSTALL_TARGET_DIRS := $(target)_2_DEBUG_INSTALL_TARGET_FILES := if ( defined($(target)_2_OUTPUT_DEBUG_DIRS) \ || defined($(target)_2_OUTPUT_DEBUG_FILES) ) \ && "$($(target)_1_DEBUG_INSTTYPE)" != "none" local mode := $(if $(mode),$(mode)$(COMMA)a-x,0644) ifeq ($($(target)_1_DEBUG_INSTTYPE),both) local debug_inst_path := $(PATH_INS) local debug_install_cmd := $(INSTALL) local debug_var := INSTALL $(foreach debug_inst, $($(target)_1_DEBUG_INST), $(evalval def_target_install_only_debug)) endif local debug_inst_path := $(PATH_STAGE) local debug_install_cmd := $(INSTALL_STAGING) local debug_var := STAGE if1of ($($(target)_1_DEBUG_INSTTYPE), stage both) $(foreach debug_inst, $($(target)_1_DEBUG_STAGE), $(evalval def_target_install_only_debug)) endif if1of ($($(target)_1_INSTTYPE), stage both) ifndef debug_nostage $(foreach debug_inst,$($(target)_1_STAGE), $(evalval def_target_install_only_debug)) endif endif _DEBUG_STAGE_DIRS += $($(target)_2_DEBUG_STAGE_TARGET_DIRS) _DEBUG_STAGE_FILES += $($(target)_2_DEBUG_STAGE_TARGET_FILES) _DEBUG_INSTALL_DIRS += $($(target)_2_DEBUG_INSTALL_TARGET_DIRS) _DEBUG_INSTALL_FILES += $($(target)_2_DEBUG_INSTALL_TARGET_FILES) $(basename $(notdir $(out))):: $($(target)_2_DEBUG_STAGE_TARGET_DIRS) $($(target)_2_DEBUG_STAGE_TARGET_FILES) endif endef # def_target_install_only # # LIBRARIES # ## Library (one). # @param $(target) Normalized library (target) name. define def_lib # library basics ## @todo prefix local bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE)) local bld_trg := $(firstword $($(target)_BLD_TRG) $(KBUILD_TARGET)) local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(KBUILD_TARGET_ARCH)) local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(KBUILD_TARGET_CPU)) local tool := $(call _TARGET_TOOL,$(target),AR) ifeq ($(tool),) $(error kBuild: Library target $(target) does not have a tool defined!) endif local name := $(firstword\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch).$(bld_type))\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg).$(bld_type))\ $($(target)_NAME.$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg))\ $($(target)_NAME.$(bld_type))\ $($(target)_NAME)\ $(target)) local outbase := $(call TARGET_BASE,$(name),$(target)) $(target)_0_OUTDIR:= $(patsubst %/,%,$(dir $(outbase))) $(call KB_FN_ASSIGN_DEPRECATED,PATH_$(target),$($(target)_0_OUTDIR), $(target)_0_OUTDIR) local suff := $(firstword\ $($(target)_LIBSUFF.$(bld_trg).$(bld_trg_arch))\ $($(target)_LIBSUFF.$(bld_trg))\ $($(target)_LIBSUFF)\ $(TOOL_$(tool)_ARLIBSUFF.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_ARLIBSUFF.$(bld_trg))\ $(TOOL_$(tool)_ARLIBSUFF)\ $(SUFF_LIB)) local out := $(outbase)$(suff) local defpath := $($(target)_DEFPATH) ifeq ($(defpath),) local defpath := $($(target)_PATH) endif $(target)_1_TARGET:= $(out) $(call KB_FN_ASSIGN_DEPRECATED,TARGET_$(target),$($(target)_1_TARGET), $(target)_1_TARGET) # no local here - must be writable across some foreachs. othersrc := $(target)_2_OBJS := # Do units pre source callouts. local units := \ $($(target)_USES.$(bld_trg).$(bld_trg_arch))\ $($(target)_USES.$(bld_trg_arch))\ $($(target)_USES.$(bld_trg))\ $($(target)_USES.$(bld_type))\ $($(target)_USES) $(foreach unit,$(units),$(evalval def_unit_$(unit)_target_pre)) # source -> object $(evalval def_target_sources) # library linking local tool := $(call _TARGET_TOOL,$(target),AR) local name := $(firstword\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch).$(bld_type))\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg).$(bld_type))\ $($(target)_NAME.$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg))\ $($(target)_NAME.$(bld_type))\ $($(target)_NAME)\ $(target)) local outbase := $(call TARGET_BASE,$(name),$(target)) local flags :=\ $(TOOL_$(tool)_ARFLAGS)\ $(TOOL_$(tool)_ARFLAGS.$(bld_type))\ $(ARFLAGS)\ $(ARFLAGS.$(bld_type))\ $($(target)_ARFLAGS)\ $($(target)_ARFLAGS.$(bld_type)) \ $($(target)_ARFLAGS.$(bld_trg)) \ $($(target)_ARFLAGS.$(bld_trg_arch)) \ $($(target)_ARFLAGS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_ARFLAGS.$(bld_trg_cpu)) local dirdep := $(call DIRDEP,$(dir $(out))) local deps := \ $($(target)_DEPS.$(bld_trg_cpu)) \ $($(target)_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_DEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_DEPS.$(bld_trg).$(bld_type)) \ $($(target)_DEPS.$(bld_trg_arch)) \ $($(target)_DEPS.$(bld_trg)) \ $($(target)_DEPS.$(bld_type)) \ $($(target)_DEPS) \ $($(target)_LNK_DEPS.$(bld_trg_cpu)) \ $($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_LNK_DEPS.$(bld_trg).$(bld_type)) \ $($(target)_LNK_DEPS.$(bld_trg_arch)) \ $($(target)_LNK_DEPS.$(bld_trg)) \ $($(target)_LNK_DEPS.$(bld_type)) \ $($(target)_LNK_DEPS) local orderdeps := \ $($(target)_ORDERDEPS.$(bld_trg_cpu)) \ $($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_ORDERDEPS.$(bld_trg).$(bld_type)) \ $($(target)_ORDERDEPS.$(bld_trg_arch)) \ $($(target)_ORDERDEPS.$(bld_trg)) \ $($(target)_ORDERDEPS.$(bld_type)) \ $($(target)_ORDERDEPS) \ $($(target)_LNK_ORDERDEPS.$(bld_trg_cpu)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_type)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg_arch)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg)) \ $($(target)_LNK_ORDERDEPS.$(bld_type)) \ $($(target)_LNK_ORDERDEPS) # Adjust paths if we got a default path. ifneq ($(defpath),) local deps := $(abspathex $(deps),$(defpath)) local orderdeps := $(abspathex $(orderdeps),$(defpath)) othersrc := $(abspathex $(othersrc),$(defpath)) endif # Custom pre-link actions. local pre_cmds := $(evalcall def_fn_prop_get_first_defined,PRE_CMDS) local post_cmds := $(evalcall def_fn_prop_get_first_defined,POST_CMDS) # eliminate this guy? local objs = $($(target)_2_OBJS) # dependency file local dep := $(out)$(SUFF_DEP) ifndef NO_LINK_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) ifdef KB_HAVE_INCLUDEDEP_QUEUE includedep-queue $(dep) else includedep $(dep) endif endif # check that the tool is defined. ifndef TOOL_$(tool)_LINK_LIBRARY_CMDS $(warning kBuild: tools: \ 1 $($(target)_$(source)TOOL.$(bld_trg).$(bld_trg_arch)) \ 2 $($(target)_$(source)TOOL.$(bld_trg)) \ 3 $($(target)_$(source)TOOL) \ 4 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \ 5 $($(target)_TOOL.$(bld_trg)) \ 6 $($(target)_TOOL) \ 7 $($(source)TOOL) \ 8 $($(source)TOOL.$(bld_trg).$(bld_trg_arch)) \ 9 $($(source)TOOL.$(bld_trg)) \ 10 $(TOOL.$(bld_trg).$(bld_trg_arch)) \ 11 $(TOOL.$(bld_trg)) \ 12 $(TOOL) ) $(error kBuild: TOOL_$(tool)_LINK_LIBRARY_CMDS isn't defined! target=$(target) ) endif # call the tool local cmds := $(TOOL_$(tool)_LINK_LIBRARY_CMDS) ifneq ($(pre_cmds),) local cmds := $(TAB)$(pre_cmds)$(NL)$(TAB)$(cmds) endif ifneq ($(post_cmds),) local cmds := $(cmds)$(NL)$(TAB)$(post_cmds) endif $(target)_2_OUTPUT := $(TOOL_$(tool)_LINK_LIBRARY_OUTPUT) $(target)_2_OUTPUT_MAYBE := $(TOOL_$(tool)_LINK_LIBRARY_OUTPUT_MAYBE) $(target)_2_DEPEND := $(TOOL_$(tool)_LINK_LIBRARY_DEPEND) $(deps) $($(target)_2_OBJS) $(target)_2_DEPORD := $(TOOL_$(tool)_LINK_LIBRARY_DEPORD) $(dirdep) $(orderdeps) # generate the link rule. $(eval $(def_link_rule)) # installing and globals. local target_type_mode := a+r,u+w $(evalval def_target_install_only) _OUT_FILES += $($(target)_2_OUTPUT) $($(target)_2_OUTPUT_MAYBE) $(out) _CLEAN_FILES += $($(target)_CLEAN) $($(target)_CLEAN.$(bld_trg)) $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_cpu)) $($(target)_CLEAN.$(bld_type)) _DIRS += $($(target)_BLDDIRS) $($(target)_BLDDIRS.$(bld_trg)) $($(target)_BLDDIRS.$(bld_trg).$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_cpu)) $($(target)_BLDDIRS.$(bld_type)) _OBJS += $($(target)_2_OBJS) endef # def_lib $(eval-opt-var def_lib) # Process libraries typevar := _LIBS tool_do := LINK_LIBRARY mode := 0644 $(foreach target, $(_ALL_LIBRARIES), $(evalval def_lib)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done library targets) endif # # Link operations. # ## # Link prolog # # @param $(target) Normalized target name. # @param $(EXT) EXE,DLL,SYS. # @param $(typevar) The name of the variable with all the root targets of its type. define def_link_common # basics local bld_type := $(firstword $($(target)_BLD_TYPE) $(KBUILD_TYPE)) local bld_trg := $(firstword $($(target)_BLD_TRG) $(BUILD_$(bld_trg_base_var))) local bld_trg_arch:= $(firstword $($(target)_BLD_TRG_ARCH) $(BUILD_$(bld_trg_base_var)_ARCH)) local bld_trg_cpu := $(firstword $($(target)_BLD_TRG_CPU) $(BUILD_$(bld_trg_base_var)_CPU)) local tool := $(call _TARGET_TOOL,$(target),LD) local name := $(firstword\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch).$(bld_type))\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg).$(bld_type))\ $($(target)_NAME.$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg))\ $($(target)_NAME.$(bld_type))\ $($(target)_NAME)\ $(target)) local outbase := $(call TARGET_BASE,$(name),$(target)) $(target)_0_OUTDIR:= $(patsubst %/,%,$(dir $(outbase))) $(call KB_FN_ASSIGN_DEPRECATED,PATH_$(target),$($(target)_0_OUTDIR), $(target)_0_OUTDIR) local suff := $(firstword \ $($(target)_$(EXT)SUFF.$(bld_trg).$(bld_trg_arch))\ $($(target)_$(EXT)SUFF.$(bld_trg))\ $($(target)_$(EXT)SUFF)\ $(TOOL_$(tool)_LD$(EXT)SUFF.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_LD$(EXT)SUFF.$(bld_trg))\ $(TOOL_$(tool)_LD$(EXT)SUFF)\ $($(EXTPRE)SUFF_$(EXT)) ) local out := $(outbase)$(suff) $(target)_1_TARGET:= $(out) $(call KB_FN_ASSIGN_DEPRECATED,TARGET_$(target),$($(target)_1_TARGET), $(target)_1_TARGET) local defpath := $($(target)_DEFPATH) ifeq ($(defpath),) local defpath := $($(target)_PATH) endif # no local here - must be writable across some foreachs. othersrc := $(target)_2_OBJS := # Do units pre source callouts. local units := \ $($(target)_USES.$(bld_trg).$(bld_trg_arch))\ $($(target)_USES.$(bld_trg_arch))\ $($(target)_USES.$(bld_trg))\ $($(target)_USES.$(bld_type))\ $($(target)_USES) $(foreach unit,$(units),$(evalval def_unit_$(unit)_target_pre)) # source -> object $(evalval def_target_sources) # more link stuff. local tool := $(call _TARGET_TOOL,$(target),LD) local name := $(firstword\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch).$(bld_type))\ $($(target)_NAME.$(bld_trg).$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg).$(bld_type))\ $($(target)_NAME.$(bld_trg_arch))\ $($(target)_NAME.$(bld_trg))\ $($(target)_NAME.$(bld_type))\ $($(target)_NAME)\ $(target)) local outbase := $(call TARGET_BASE,$(name),$(target)) local flags :=\ $(TOOL_$(tool)_LDFLAGS)\ $(TOOL_$(tool)_LDFLAGS.$(bld_type))\ $(TOOL_$(tool)_LDFLAGS.$(bld_trg))\ $(TOOL_$(tool)_LDFLAGS.$(bld_trg_arch))\ $(TOOL_$(tool)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_LDFLAGS.$(bld_trg_cpu))\ $(foreach sdk, $(SDKS) \ $(SDKS.$(bld_type)) \ $(SDKS.$(bld_trg)) \ $(SDKS.$(bld_trg_arch)) \ $(SDKS.$(bld_trg).$(bld_trg_arch)),\ $(SDK_$(sdk)_LDFLAGS)\ $(SDK_$(sdk)_LDFLAGS.$(bld_type))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg_arch))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg_cpu)))\ $(LDFLAGS)\ $(LDFLAGS.$(bld_type))\ $(LDFLAGS.$(bld_trg))\ $(LDFLAGS.$(bld_trg_arch))\ $(LDFLAGS.$(bld_trg).$(bld_trg_arch))\ $(LDFLAGS.$(bld_trg_cpu))\ $(foreach sdk, $($(target)_SDKS) \ $($(target)_SDKS.$(bld_type)) \ $($(target)_SDKS.$(bld_trg)) \ $($(target)_SDKS.$(bld_trg_arch)) \ $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)),\ $(SDK_$(sdk)_LDFLAGS)\ $(SDK_$(sdk)_LDFLAGS.$(bld_type))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg_arch))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_LDFLAGS.$(bld_trg_cpu)))\ $($(target)_LDFLAGS)\ $($(target)_LDFLAGS.$(bld_type))\ $($(target)_LDFLAGS.$(bld_trg))\ $($(target)_LDFLAGS.$(bld_trg_arch))\ $($(target)_LDFLAGS.$(bld_trg).$(bld_trg_arch))\ $($(target)_LDFLAGS.$(bld_trg_cpu)) local libs :=\ $($(target)_LIBS.$(bld_trg_cpu))\ $($(target)_LIBS.$(bld_trg).$(bld_trg_arch))\ $($(target)_LIBS.$(bld_trg_arch))\ $($(target)_LIBS.$(bld_trg))\ $($(target)_LIBS.$(bld_type))\ $($(target)_LIBS)\ $(foreach sdk, $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SDKS.$(bld_trg_arch)) \ $($(target)_SDKS.$(bld_trg)) \ $($(target)_SDKS.$(bld_type)) \ $($(target)_SDKS),\ $(SDK_$(sdk)_LIBS.$(bld_trg_cpu))\ $(SDK_$(sdk)_LIBS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_LIBS.$(bld_trg_arch))\ $(SDK_$(sdk)_LIBS.$(bld_trg))\ $(SDK_$(sdk)_LIBS.$(bld_type))\ $(SDK_$(sdk)_LIBS))\ $(LIBS.$(bld_trg_cpu))\ $(LIBS.$(bld_trg).$(bld_trg_arch))\ $(LIBS.$(bld_trg_arch))\ $(LIBS.$(bld_trg))\ $(LIBS.$(bld_type))\ $(LIBS)\ $(foreach sdk, $(SDKS.$(bld_trg).$(bld_trg_arch)) \ $(SDKS.$(bld_trg_arch)) \ $(SDKS.$(bld_trg)) \ $(SDKS.$(bld_type)) \ $(SDKS),\ $(SDK_$(sdk)_LIBS.$(bld_trg_cpu))\ $(SDK_$(sdk)_LIBS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_LIBS.$(bld_trg_arch))\ $(SDK_$(sdk)_LIBS.$(bld_trg))\ $(SDK_$(sdk)_LIBS.$(bld_type))\ $(SDK_$(sdk)_LIBS))\ $(TOOL_$(tool)_LIBS.$(bld_trg_cpu))\ $(TOOL_$(tool)_LIBS.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_LIBS.$(bld_trg_arch))\ $(TOOL_$(tool)_LIBS.$(bld_trg))\ $(TOOL_$(tool)_LIBS.$(bld_type))\ $(TOOL_$(tool)_LIBS) local libpath :=\ $($(target)_LIBPATH.$(bld_trg_cpu))\ $($(target)_LIBPATH.$(bld_trg).$(bld_trg_arch))\ $($(target)_LIBPATH.$(bld_trg_arch))\ $($(target)_LIBPATH.$(bld_trg))\ $($(target)_LIBPATH.$(bld_type))\ $($(target)_LIBPATH)\ $(foreach sdk, $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SDKS.$(bld_trg_arch)) \ $($(target)_SDKS.$(bld_trg)) \ $($(target)_SDKS.$(bld_type)) \ $($(target)_SDKS),\ $(SDK_$(sdk)_LIBPATH.$(bld_trg_cpu))\ $(SDK_$(sdk)_LIBPATH.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_LIBPATH.$(bld_trg_arch))\ $(SDK_$(sdk)_LIBPATH.$(bld_trg))\ $(SDK_$(sdk)_LIBPATH.$(bld_type))\ $(SDK_$(sdk)_LIBPATH))\ $(LIBPATH.$(bld_trg_cpu))\ $(LIBPATH.$(bld_trg).$(bld_trg_arch))\ $(LIBPATH.$(bld_trg_arch))\ $(LIBPATH.$(bld_trg))\ $(LIBPATH.$(bld_type))\ $(LIBPATH)\ $(foreach sdk, $(SDKS.$(bld_trg).$(bld_trg_arch)) \ $(SDKS.$(bld_trg_arch)) \ $(SDKS.$(bld_trg)) \ $(SDKS.$(bld_type)) \ $(SDKS),\ $(SDK_$(sdk)_LIBPATH.$(bld_trg_cpu))\ $(SDK_$(sdk)_LIBPATH.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_LIBPATH.$(bld_trg_arch))\ $(SDK_$(sdk)_LIBPATH.$(bld_trg))\ $(SDK_$(sdk)_LIBPATH.$(bld_type))\ $(SDK_$(sdk)_LIBPATH))\ $(TOOL_$(tool)_LIBPATH.$(bld_trg_cpu))\ $(TOOL_$(tool)_LIBPATH.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_LIBPATH.$(bld_trg_arch))\ $(TOOL_$(tool)_LIBPATH.$(bld_trg))\ $(TOOL_$(tool)_LIBPATH.$(bld_type))\ $(TOOL_$(tool)_LIBPATH) local dirdep := $(call DIRDEP,$(dir $(out))) local deps := \ $($(target)_DEPS.$(bld_trg_cpu)) \ $($(target)_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_DEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_DEPS.$(bld_trg).$(bld_type)) \ $($(target)_DEPS.$(bld_trg_arch)) \ $($(target)_DEPS.$(bld_trg)) \ $($(target)_DEPS.$(bld_type)) \ $($(target)_DEPS) \ $($(target)_LNK_DEPS.$(bld_trg_cpu)) \ $($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_LNK_DEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_LNK_DEPS.$(bld_trg).$(bld_type)) \ $($(target)_LNK_DEPS.$(bld_trg_arch)) \ $($(target)_LNK_DEPS.$(bld_trg)) \ $($(target)_LNK_DEPS.$(bld_type)) \ $($(target)_LNK_DEPS) local orderdeps := \ $($(target)_ORDERDEPS.$(bld_trg_cpu)) \ $($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_ORDERDEPS.$(bld_trg).$(bld_type)) \ $($(target)_ORDERDEPS.$(bld_trg_arch)) \ $($(target)_ORDERDEPS.$(bld_trg)) \ $($(target)_ORDERDEPS.$(bld_type)) \ $($(target)_ORDERDEPS) \ $($(target)_LNK_ORDERDEPS.$(bld_trg_cpu)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch).$(bld_type)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg).$(bld_type)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg_arch)) \ $($(target)_LNK_ORDERDEPS.$(bld_trg)) \ $($(target)_LNK_ORDERDEPS.$(bld_type)) \ $($(target)_LNK_ORDERDEPS) # Adjust paths if we got a default path. ifneq ($(defpath),) local libpath := $(abspathex $(libpath),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) local orderdeps := $(abspathex $(orderdeps),$(defpath)) othersrc := $(abspathex $(othersrc),$(defpath)) # libs are not subject to this because of the the -l stuff. Use $(_DEFPATH)/lib if relative to current dir! endif # Debug info. local ld_debug := $(evalcall def_fn_prop_get_first_defined,LD_DEBUG) local debug_inst := $(evalcall def_fn_prop_get_first_defined,DEBUG_INST) local debug_stage := $(evalcall def_fn_prop_get_first_defined,DEBUG_STAGE) local debug_nostage := $(evalcall def_fn_prop_get_first_word,DEBUG_NOSTAGE) # Custom pre/post-link actions. local pre_cmds := $(evalcall def_fn_prop_get_first_defined,PRE_CMDS) local post_cmds := $(evalcall def_fn_prop_get_first_defined,POST_CMDS) # eliminate this guy? local objs = $($(target)_2_OBJS) # dependency file local dep := $(outbase)$(SUFF_DEP) ifndef NO_LINK_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) ifdef KB_HAVE_INCLUDEDEP_QUEUE includedep-queue $(dep) else includedep $(dep) endif endif # check that the tool is defined. ifndef TOOL_$(tool)_$(tool_do)_CMDS $(warning kBuild: tools: \ 1 $($(target)_$(source)TOOL.$(bld_trg).$(bld_trg_arch)) \ 2 $($(target)_$(source)TOOL.$(bld_trg)) \ 3 $($(target)_$(source)TOOL) \ 4 $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \ 5 $($(target)_TOOL.$(bld_trg)) \ 6 $($(target)_TOOL) \ 7 $($(source)TOOL.$(bld_trg).$(bld_trg_arch)) \ 8 $($(source)TOOL.$(bld_trg)) \ 9 $($(source)TOOL) \ 10 $(TOOL.$(bld_trg).$(bld_trg_arch)) \ 11 $(TOOL.$(bld_trg)) \ 12 $(TOOL) ) $(error kBuild: TOOL_$(tool)_$(tool_do)_CMDS isn't defined! target=$(target) ) endif # call the tool local cmds := $(TOOL_$(tool)_$(tool_do)_CMDS) ifneq ($(pre_cmds),) local cmds := $(TAB)$(pre_cmds)$(NL)$(TAB)$(cmds) endif ifneq ($(post_cmds),) local cmds := $(cmds)$(NL)$(TAB)$(post_cmds) endif $(target)_2_OUTPUT := $(TOOL_$(tool)_$(tool_do)_OUTPUT) $(target)_2_OUTPUT_MAYBE := $(TOOL_$(tool)_$(tool_do)_OUTPUT_MAYBE) if1of ($(ld_debug), split) $(target)_2_OUTPUT_DEBUG_FILES := $(filter-out %/,$(TOOL_$(tool)_$(tool_do)_OUTPUT_DEBUG)) $(target)_2_OUTPUT_DEBUG_DIRS := $(filter %/,$(TOOL_$(tool)_$(tool_do)_OUTPUT_DEBUG)) else $(target)_2_OUTPUT_DEBUG_FILES := $(target)_2_OUTPUT_DEBUG_DIRS := endif $(target)_2_DEPEND := $(TOOL_$(tool)_$(tool_do)_DEPEND) $(deps) $($(target)_2_OBJS) $(target)_2_DEPORD := $(TOOL_$(tool)_$(tool_do)_DEPORD) $(dirdep) $(orderdeps) # generate the link rule. $(eval $(def_link_rule)) # installation targets local target_type_mode := $(evalval def_target_install_only) # Update globals. _OBJS += $($(target)_2_OBJS) _OUT_FILES += $($(target)_2_OUTPUT) $($(target)_2_OUTPUT_MAYBE) $(out) _CLEAN_FILES += $($(target)_CLEAN) $($(target)_CLEAN.$(bld_trg)) $($(target)_CLEAN.$(bld_trg).$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_arch)) $($(target)_CLEAN.$(bld_trg_cpu)) $($(target)_CLEAN.$(bld_type)) _DIRS += $($(target)_BLDDIRS) $($(target)_BLDDIRS.$(bld_trg)) $($(target)_BLDDIRS.$(bld_trg).$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_arch)) $($(target)_BLDDIRS.$(bld_trg_cpu)) $($(target)_BLDDIRS.$(bld_type)) _INSTALLS_FILES += $(INSTARGET_$(target)) endef # def_link_common $(eval-opt-var def_link_common) # # BLDPROGS # # Process build programs. EXT := EXE EXTPRE := HOST tool_do := LINK_PROGRAM typevar := _BLDPROGS mode := 0755 bld_trg_base_var := PLATFORM $(foreach target, $(_ALL_BLDPROGS), $(evalval def_link_common)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done build program targets) endif # # DLLS # # Process dlls EXT := DLL EXTPRE := tool_do := LINK_DLL typevar := _DLLS mode := 0644 bld_trg_base_var := TARGET $(foreach target, $(_ALL_DLLS), $(evalval def_link_common)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done dll targets) endif # # IMPORT LIBRARIES # # - On OS/2 and windows these are libraries. # - On other platforms they are fake DLLs. # EXTPRE := typevar := _IMPORT_LIBS mode := 0644 bld_trg_base_var := TARGET ifeq ($(filter-out nt os2 win win64 win32,$(KBUILD_TARGET)),) EXT := LIB tool_do := LINK_LIBRARY $(foreach target, $(_ALL_IMPORT_LIBS), $(evalval def_lib)) else EXT := DLL tool_do := LINK_DLL $(foreach target, $(_ALL_IMPORT_LIBS), $(evalval def_link_common)) endif ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done import library targets) endif # # PROGRAMS # # Process programs EXT := EXE EXTPRE := tool_do := LINK_PROGRAM typevar := _PROGRAMS mode := 0755 bld_trg_base_var := TARGET $(foreach target, $(_ALL_PROGRAMS), $(evalval def_link_common)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done program targets) endif # # SYSMODS # # Process sysmods EXT := SYS EXTPRE := tool_do := LINK_SYSMOD typevar := _SYSMODS mode := 0644 bld_trg_base_var := TARGET $(foreach target, $(_ALL_SYSMODS), $(evalval def_link_common)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done sysmod targets) endif # # MISCBINS # # Process MISCBINS EXT := BIN EXTPRE := tool_do := LINK_MISCBIN typevar := _MISCBINS mode := 0644 bld_trg_base_var := TARGET $(foreach target, $(_ALL_MISCBINS), $(evalval def_link_common)) ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, done misc binary targets) endif kbuild-2695/kBuild/header.kmk0000644000000000000000000013766712247157310014625 0ustar rootroot# $Id: header.kmk 2689 2013-07-11 21:31:43Z bird $ ## @file # kBuild - File included at top of a makefile. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifndef __header_kmk__ # start-of-file-content ifdef KBUILD_PROFILE_SELF _KBUILD_TS_HEADER_START := $(nanots ) # just a dummy warm up query $(info prof: since start - since previous -- event description) ifeq ($(KBUILD_PROFILE_SELF),2) $(info stat: $(make-stats )) endif _KBUILD_TS_HEADER_START := $(nanots ) _KBUILD_TS_PREV := $(_KBUILD_TS_HEADER_START) _KBUILD_FMT_ELAPSED_EX = $(int-div $(int-add $(int-sub $1, $2),500000),1000000)ms _KBUILD_FMT_ELAPSED = $(call _KBUILD_FMT_ELAPSED_EX,$(_KBUILD_TS_NOW),$1) define def_profile_self _KBUILD_TS_NOW := $(nanots ) $(info prof: $(call _KBUILD_FMT_ELAPSED,$(_KBUILD_TS_HEADER_START)) - $(call _KBUILD_FMT_ELAPSED, $(_KBUILD_TS_PREV)) -- $(strip $1)) ifeq ($(KBUILD_PROFILE_SELF),2) $(info stat: $(make-stats )) endif _KBUILD_TS_PREV := $(_KBUILD_TS_NOW) endef endif # # Check make version before we do anything else. # ifndef KMK_VERSION $(error kBuild: The kmk default variable KMK_VERSION isn't defined! Make sure you are using 'kmk' and not 'make', 'gmake', 'kmk_gmake', 'dmake' or any other make program) endif ifneq ($(KBUILD_VERSION_MAJOR).$(KBUILD_VERSION_MINOR),0.1) ifneq ($(KBUILD_VERSION_MAJOR),0) $(warning kBuild: kmk major version mismatch! Expected '0' but found '$(KBUILD_VERSION_MAJOR)'!) else $(warning kBuild: kmk minor version mismatch! Expected '1' but found '$(KBUILD_VERSION_MINOR)'!) endif else if $(KBUILD_VERSION_PATCH) < 999 $(error kBuild: kmk version mismatch! Expected 0.1.999 or later. Actual version is $(KBUILD_VERSION).) endif endif # # The revision in which this file was last modified. # This can be useful when using development versions of kBuild. # KMK_REVISION := $(patsubst %:,, $Rev: 2689 $ ) # # Define the default goal. # .PHONY: all all_recursive all: all_recursive # # The phony FORCE target. # .PHONY: FORCE FORCE: # # Enable delete on error and second expansion of prerequisites and targets. # .DELETE_ON_ERROR: .SECONDEXPANSION: .SECONDTARGETEXPANSION: # # General purpose macros. # ## # Newline character(s). define NL endef ## # Tab character. TAB := $(subst ., ,.) ## # Newline + tab characters (for generating commands). NLTAB = $(NL)$(TAB) ## # Space character. SP := $(subst ., ,.) ## # Hash character. define HASH # endef ## # Colon character. COLON := : ## # Semicolon character. SEMICOLON := ; ## # Comma character. COMMA := , ## # Dot character. DOT := . ## # Dollar character. DOLLAR := $$ ## # Equal character. EQUAL := = ## # Percent character. PERCENT := % ## # Single quote character. SQUOTE := ' ## # Double quote character. DQUOTE := " # # The list of standard build types in kBuild. # # This list can be extended in Config.kmk and it's possible to extend # (inherit) another build type. # KBUILD_BLD_TYPES := release profile debug # # The OSes, Architectures and CPUs that kBuild recognizes. # # When kBuild is ported to a new OS or architecture a unique keyword needs # to be assigned to it and added here. This strictness is required because # this keyword namespace is shared between OSes, architectures, cpus and # build types. (PORTME) # KBUILD_OSES := darwin dos dragonfly freebsd haiku l4 linux netbsd nt openbsd os2 solaris win os-agnostic KBUILD_ARCHES := x86 amd64 sparc32 sparc64 s390 s390x ppc32 ppc64 mips32 mips64 ia64 hppa32 hppa64 arm alpha KBUILD_ARCHES_64 := amd64 sparc64 s390x ppc64 mips64 ia64 hppa64 alpha KBUILD_ARCHES_32 := x86 sparc32 s390 ppc32 mips32 hppa32 arm # # Set default build type. # ifndef KBUILD_TYPE ifdef BUILD_TYPE KBUILD_TYPE := $(BUILD_TYPE) endif else ifdef BUILD_TYPE ifneq ($(KBUILD_TYPE),$(BUILD_TYPE)) ifeq ($(origin KBUILD_TYPE):$(origin BUILD_TYPE),environment:command line) KBUILD_TYPE := $(BUILD_TYPE) else ifneq ($(origin KBUILD_TYPE):$(origin BUILD_TYPE),command line:environment) $(error kBuild: KBUILD_TYPE and BUILD_TYPE disagree.) endif endif endif override BUILD_TYPE = $(KBUILD_TYPE) ifndef KBUILD_TYPE KBUILD_TYPE := release else if1of ($(KBUILD_TYPE), $(KBUILD_OSES) $(KBUILD_ARCHES)) $(error kBuild: The KBUILD_TYPE value '$(KBUILD_TYPE)' is an OS or architecture!) endif ifneq (.$(words $(KBUILD_TYPE)).$(KBUILD_TYPE).,.1.$(strip $(KBUILD_TYPE)).) $(error kBuild: The KBUILD_TYPE value '$(KBUILD_TYPE)' contains spaces/tabs!) endif endif # # Host platform legacy # kmk deals with this, so this is only temporary until I've rebuilt everything. # ifndef KBUILD_HOST KBUILD_HOST := $(BUILD_PLATFORM) endif ifndef KBUILD_HOST_ARCH KBUILD_HOST_ARCH := $(BUILD_PLATFORM_ARCH) endif ifndef KBUILD_HOST_CPU KBUILD_HOST_CPU := $(BUILD_PLATFORM_CPU) endif # # Assert valid build platform variables. # # All these are set by kmk so they shouldn't be any trouble # unless the user starts messing about with environment variables. # ifneq (.$(words $(KBUILD_HOST)).$(KBUILD_HOST).,.1.$(strip $(KBUILD_HOST)).) $(error kBuild: The KBUILD_HOST value '$(KBUILD_HOST)' contains spaces/tabs!) endif ifneq ($(words $(filter $(KBUILD_HOST),$(KBUILD_OSES))),1) $(error kBuild: KBUILD_HOST value '$(KBUILD_HOST)' is not recognized (valid: $(KBUILD_OSES))) endif ifneq (.$(words $(KBUILD_HOST_ARCH)).$(KBUILD_HOST_ARCH).,.1.$(strip $(KBUILD_HOST_ARCH)).) $(error kBuild: The KBUILD_HOST_ARCH value '$(KBUILD_HOST_ARCH)' contains spaces/tabs!) endif ifneq ($(words $(filter $(KBUILD_HOST_ARCH),$(KBUILD_ARCHES))),1) $(error kBuild: KBUILD_HOST_ARCH value '$(KBUILD_HOST_ARCH)' is not recognized (valid: $(KBUILD_ARCHES))) endif ifeq ($(strip $(KBUILD_HOST_CPU)),) KBUILD_HOST_CPU := blend else ifneq (.$(words $(KBUILD_HOST_CPU)).$(KBUILD_HOST_CPU).,.1.$(strip $(KBUILD_HOST_CPU)).) $(error kBuild: The KBUILD_HOST_CPU value '$(KBUILD_HOST_CPU)' contains spaces/tabs!) endif if1of ($(KBUILD_HOST_CPU), $(KBUILD_OSES) $(KBUILD_ARCHES)) $(error kBuild: The KBUILD_HOST_CPU value '$(KBUILD_HOST_CPU)' was found in the OS or architecture keywords!) endif ifeq ($(KBUILD_HOST_CPU),$(KBUILD_TYPE)) $(error kBuild: The KBUILD_HOST_CPU value '$(KBUILD_HOST_CPU)' is the same as the KBUILD_TYPE!) endif endif # # Deal with target platform legacy. # ifndef KBUILD_TARGET ifdef BUILD_TARGET KBUILD_TARGET := $(BUILD_TARGET) endif else ifdef BUILD_TARGET ifneq ($(KBUILD_TARGET),$(BUILD_TARGET)) ifeq ($(origin KBUILD_TARGET):$(origin BUILD_TARGET),environment:command line) KBUILD_TARGET := $(BUILD_TARGET) else ifneq ($(origin KBUILD_TARGET):$(origin BUILD_TARGET),command line:environment) $(error kBuild: KBUILD_TARGET and BUILD_TARGET disagree) endif endif endif override BUILD_TARGET = $(KBUILD_TARGET) ifndef KBUILD_TARGET_ARCH ifdef BUILD_TARGET_ARCH KBUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH) endif else ifdef BUILD_TARGET_ARCH ifneq ($(KBUILD_TARGET_ARCH),$(BUILD_TARGET_ARCH)) ifeq ($(origin KBUILD_TARGET_ARCH):$(origin BUILD_TARGET_ARCH),environment:command line) KBUILD_TARGET_ARCH := $(BUILD_TARGET_ARCH) else ifneq ($(origin KBUILD_TARGET_ARCH):$(origin BUILD_TARGET_ARCH),command line:environment) $(error kBuild: KBUILD_TARGET_ARCH and BUILD_TARGET_ARCH disagree) endif endif endif override BUILD_TARGET_ARCH = $(KBUILD_TARGET_ARCH) ifndef KBUILD_TARGET_CPU ifdef BUILD_TARGET_CPU KBUILD_TARGET_CPU := $(BUILD_TARGET_CPU) endif else ifdef BUILD_TARGET_CPU ifneq ($(KBUILD_TARGET_CPU),$(BUILD_TARGET_CPU)) ifeq ($(origin KBUILD_TARGET_CPU):$(origin BUILD_TARGET_CPU),environment:command line) KBUILD_TARGET_CPU := $(BUILD_TARGET_CPU) else ifneq ($(origin KBUILD_TARGET_CPU):$(origin BUILD_TARGET_CPU),command line:environment) $(error kBuild: KBUILD_TARGET_CPU and BUILD_TARGET_CPU disagree) endif endif endif override BUILD_TARGET_CPU = $(KBUILD_TARGET_CPU) # # Assert or set default target platform. # When not defined use the corresponding KBUILD_HOST value. # ifndef KBUILD_TARGET KBUILD_TARGET := $(KBUILD_HOST) else ifneq (.$(words $(KBUILD_TARGET)).$(KBUILD_TARGET).,.1.$(strip $(KBUILD_TARGET)).) $(error kBuild: The KBUILD_TARGET value '$(KBUILD_TARGET)' contains spaces/tabs!) endif ifneq ($(words $(filter $(KBUILD_TARGET),$(KBUILD_OSES))),1) $(error kBuild: KBUILD_TARGET value '$(KBUILD_TARGET)' is not recognized (valid: $(KBUILD_OSES))) endif endif ifndef KBUILD_TARGET_ARCH KBUILD_TARGET_ARCH := $(KBUILD_HOST_ARCH) else ifneq (.$(words $(KBUILD_TARGET_ARCH)).$(KBUILD_TARGET_ARCH).,.1.$(strip $(KBUILD_TARGET_ARCH)).) $(error kBuild: The KBUILD_TARGET_ARCH value '$(KBUILD_TARGET_ARCH)' contains spaces/tabs!) endif ifneq ($(words $(filter $(KBUILD_TARGET_ARCH),$(KBUILD_ARCHES))),1) $(error kBuild: KBUILD_TARGET_ARCH value '$(KBUILD_TARGET_ARCH)' is not recognized (valid: $(KBUILD_ARCHES))) endif endif ifndef KBUILD_TARGET_CPU KBUILD_TARGET_CPU := $(KBUILD_HOST_CPU) else ifeq ($(strip $(KBUILD_TARGET_CPU)),) ifeq ($(KBUILD_TARGET_ARCH),$(KBUILD_HOST_ARCH)) KBUILD_TARGET_CPU := $(KBUILD_HOST_CPU) else KBUILD_TARGET_CPU := blend endif else ifneq (.$(words $(KBUILD_TARGET_CPU)).$(KBUILD_TARGET_CPU).,.1.$(strip $(KBUILD_TARGET_CPU)).) $(error kBuild: The KBUILD_TARGET_CPU value '$(KBUILD_TARGET_CPU)' contains spaces/tabs!) endif if1of ($(KBUILD_TARGET_CPU), $(KBUILD_OSES) $(KBUILD_ARCHES)) $(error kBuild: The KBUILD_TARGET_CPU value was found in the OS or architecture keywords!) endif ifeq ($(KBUILD_TARGET_CPU),$(KBUILD_TYPE)) $(error kBuild: The KBUILD_TARGET_CPU value '$(KBUILD_TARGET_CPU)' is the same as the KBUILD_TYPE!) endif endif # # Paths and stuff. # # Adjust DEPTH first. DEPTH := $(strip $(DEPTH)) ifeq ($(DEPTH),) DEPTH := . endif ## PATH_CURRENT is the current directory (getcwd). PATH_CURRENT := $(abspath $(CURDIR)) ## PATH_SUB_CURRENT points to current directory of the current makefile. # Meaning that it will change value as we enter and exit sub-makefiles. PATH_SUB_CURRENT := $(PATH_CURRENT) ## PATH_ROOT points to the project root directory. PATH_ROOT := $(abspath $(PATH_CURRENT)/$(DEPTH)) ## PATH_SUB_ROOT points to the directory of the top-level makefile. ifneq ($(strip $(SUB_DEPTH)),) SUB_DEPTH := $(strip $(SUB_DEPTH)) PATH_SUB_ROOT := $(abspath $(PATH_CURRENT)/$(SUB_DEPTH)) else PATH_SUB_ROOT := $(PATH_CURRENT) endif ## CURSUBDIR is PATH_SUB_ROOT described relative to PATH_ROOT. # This variable is used to determin where the object files and other output goes. ifneq ($(PATH_ROOT),$(PATH_SUB_ROOT)) CURSUBDIR := $(patsubst $(PATH_ROOT)/%,%,$(PATH_SUB_ROOT)) else CURSUBDIR := . endif # Install directory layout. Relative to PATH_INS. KBUILD_INST_PATHS := BIN DLL SYS LIB DOC DEBUG SBIN LIBEXEC SHARE INST_BIN = bin/ if1of ($(KBUILD_TARGET), win) INST_DLL = bin/ else INST_DLL = lib/ endif if1of ($(KBUILD_TARGET), os2 win) INST_SYS = drivers/ else INST_SYS = kernel/ endif INST_LIB = lib/ INST_DOC = share/doc/ INST_DEBUG = debug/ INST_SBIN = sbin/ INST_LIBEXEC = libexec/ INST_SHARE = share/ # Staging directory layout. Relative to PATH_STAGE. STAGE_BIN = $(INST_BIN) STAGE_DLL = $(INST_DLL) STAGE_SYS = $(INST_SYS) STAGE_LIB = $(INST_LIB) STAGE_DOC = $(INST_DOC) STAGE_DEBUG = $(INST_DEBUG) STAGE_SBIN = $(INST_SBIN) STAGE_LIBEXEC = $(INST_LIBEXEC) STAGE_SHARE = $(INST_SHARE) # Install and staging directory paths. $(foreach path, $(KBUILD_INST_PATHS), \ $(eval PATH_STAGE_$(path) = $$(patsubst %/,%,$$(PATH_STAGE)/$$(STAGE_$(path)))) \ $(eval PATH_INST_$(path) = $$(patsubst %/,%,$$(PATH_INS)/$$(INST_$(path)))) \ ) # Output directories. ifndef PATH_OUT_BASE PATH_OUT_BASE := $(PATH_ROOT)/out endif ifndef PATH_OUT ifdef BUILD_TARGET_SUB # (BUILD_TARGET_SUB is not currently recognized by kBuild in any other places - obsolete) PATH_OUT = $(PATH_OUT_BASE)/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH).$(BUILD_TARGET_SUB)/$(KBUILD_TYPE) else PATH_OUT = $(PATH_OUT_BASE)/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/$(KBUILD_TYPE) endif endif # !define PATH_OUT PATH_OBJCACHE = $(PATH_OUT_BASE)/kObjCache PATH_OBJ = $(PATH_OUT)/obj PATH_TARGET = $(PATH_OBJ)/$(CURSUBDIR) PATH_STAGE = $(PATH_OUT)/stage ifndef PATH_INS ifdef DESTROOT PATH_INS = $(DESTROOT) else PATH_INS = $(PATH_OUT)/dist endif endif # Tripwire obsolete PATH defines. PATH_BIN = $(error kBuild: PATH_BIN is obsoleted in kBuild 0.1.2. Use PATH_STAGE_BIN or PATH_INST_BIN instead) PATH_DLL = $(error kBuild: PATH_LIB is obsoleted in kBuild 0.1.2. Use PATH_STAGE_DLL or PATH_INST_DLL instead) PATH_LIB = $(error kBuild: PATH_LIB is obsoleted in kBuild 0.1.2. Use PATH_STAGE_LIB or PATH_INST_LIB instead) PATH_SYS = $(error kBuild: PATH_SYS is obsoleted in kBuild 0.1.2. Use PATH_STAGE_SYS or PATH_INST_SYS instead) PATH_DOC = $(error kBuild: PATH_DOC is obsoleted in kBuild 0.1.2. Use PATH_STAGE_DOC or PATH_INST_DOC instead) # Development tool tree. KBUILD_DEVTOOLS = $(if $(PATH_DEVTOOLS),$(PATH_DEVTOOLS),$(PATH_ROOT)/tools) KBUILD_DEVTOOLS_TRG = $(KBUILD_DEVTOOLS)/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH) KBUILD_DEVTOOLS_HST = $(KBUILD_DEVTOOLS)/$(KBUILD_HOST).$(KBUILD_HOST_ARCH) if1of ($(KBUILD_TARGET_ARCH), amd64 hppa64 mips64 ppc64 s390x sparc64) ifeq ($(KBUILD_TARGET_ARCH),amd64) KBUILD_DEVTOOLS_TRG_ALT = $(PATH_DEVTOOLS)/$(KBUILD_TARGET).x86 else ifeq ($(KBUILD_TARGET_ARCH),hppa64) KBUILD_DEVTOOLS_TRG_ALT = $(PATH_DEVTOOLS)/$(KBUILD_TARGET).hppa32 else ifeq ($(KBUILD_TARGET_ARCH),mips64) KBUILD_DEVTOOLS_TRG_ALT = $(PATH_DEVTOOLS)/$(KBUILD_TARGET).mips32 else ifeq ($(KBUILD_TARGET_ARCH),ppc64) KBUILD_DEVTOOLS_TRG_ALT = $(PATH_DEVTOOLS)/$(KBUILD_TARGET).ppc32 else ifeq ($(KBUILD_TARGET_ARCH),s390x) KBUILD_DEVTOOLS_TRG_ALT = $(PATH_DEVTOOLS)/$(KBUILD_TARGET).s390 else ifeq ($(KBUILD_TARGET_ARCH),sparc64) KBUILD_DEVTOOLS_TRG_ALT = $(PATH_DEVTOOLS)/$(KBUILD_TARGET).sparc32 endif endif if1of ($(KBUILD_HOST_ARCH), amd64 hppa64 mips64 ppc64 s390x sparc64) ifeq ($(KBUILD_HOST_ARCH),amd64) KBUILD_DEVTOOLS_HST_ALT = $(PATH_DEVTOOLS)/$(KBUILD_HOST).x86 else ifeq ($(KBUILD_HOST_ARCH),hppa64) KBUILD_DEVTOOLS_HST_ALT = $(PATH_DEVTOOLS)/$(KBUILD_HOST).hppa32 else ifeq ($(KBUILD_HOST_ARCH),mips64) KBUILD_DEVTOOLS_HST_ALT = $(PATH_DEVTOOLS)/$(KBUILD_HOST).mips32 else ifeq ($(KBUILD_HOST_ARCH),ppc64) KBUILD_DEVTOOLS_HST_ALT = $(PATH_DEVTOOLS)/$(KBUILD_HOST).ppc32 else ifeq ($(KBUILD_HOST_ARCH),s390x) KBUILD_DEVTOOLS_HST_ALT = $(PATH_DEVTOOLS)/$(KBUILD_HOST).s390 else ifeq ($(KBUILD_HOST_ARCH),sparc64) KBUILD_DEVTOOLS_HST_ALT = $(PATH_DEVTOOLS)/$(KBUILD_HOST).sparc32 endif endif # KBUILD_PATH / PATH_KBUILD is determined by kmk. ifndef KBUILD_PATH KBUILD_PATH := $(PATH_KBUILD) endif ifeq ($(strip $(KBUILD_PATH)),) $(error kBuild: KBUILD_PATH is missing or empty! kmk is supposed to set it.) endif # KBUILD_BIN_PATH / PATH_KBUILD_BIN is determined by kmk. ifndef KBUILD_BIN_PATH KBUILD_BIN_PATH := $(PATH_KBUILD_BIN) endif ifeq ($(strip $(KBUILD_BIN_PATH)),) $(error kBuild: KBUILD_BIN_PATH is missing or empty! kmk is supposed to set it.) endif # kBuild files which might be of interest. FILE_KBUILD_HEADER := $(KBUILD_PATH)/header.kmk #FILE_KBUILD_CONFIG := $(KBUILD_PATH)/config.kmk FILE_KBUILD_FOOTER := $(KBUILD_PATH)/footer.kmk FILE_KBUILD_SUB_HEADER := $(KBUILD_PATH)/subheader.kmk FILE_KBUILD_SUB_FOOTER := $(KBUILD_PATH)/subfooter.kmk ## MAKEFILE is the name of the main makefile. MAKEFILE := $(firstword $(MAKEFILE_LIST)) ## MAKEFILE_CURRENT is the name of the current makefile. # This is updated everything a sub-makefile is included. MAKEFILE_CURRENT := $(MAKEFILE) ## @todo this should be done via SUFF_XYZ.target/host... # # Build platform setup. # (PORTME) # if1of ($(KBUILD_HOST), win nt) # Win, Win32, Win64, NT. EXEC_X86_WIN32 := HOSTSUFF_EXE := .exe # OS/2. else ifeq ($(KBUILD_HOST),os2) EXEC_X86_WIN32 := innopec.exe HOSTSUFF_EXE := .exe else if1of ($(KBUILD_HOST), freebsd dragonfly linux openbsd netbsd) # Unix (like) systems with wine. EXEC_X86_WIN32 := wine HOSTSUFF_EXE := else # Unix (like) systems without wine. EXEC_X86_WIN32 := false HOSTSUFF_EXE := endif # # Build target setup. # (PORTME) # SUFF_DEP := .dep SUFF_BIN := if1of ($(KBUILD_TARGET), win nt os2) SUFF_OBJ := .obj SUFF_LIB := .lib SUFF_DLL := .dll SUFF_EXE := .exe SUFF_SYS := .sys SUFF_RES := .res else ifeq ($(KBUILD_TARGET),l4) SUFF_OBJ := .o SUFF_LIB := .a SUFF_DLL := .s.so SUFF_EXE := SUFF_SYS := .a SUFF_RES := else ifeq ($(KBUILD_TARGET),darwin) SUFF_OBJ := .o SUFF_LIB := .a SUFF_DLL := .dylib SUFF_EXE := SUFF_SYS := SUFF_RES := else SUFF_OBJ := .o SUFF_LIB := .a SUFF_DLL := .so SUFF_EXE := if1of ($(KBUILD_TARGET), dragonfly freebsd linux netbsd openbsd) ## @todo check netbsd and openbsd. SUFF_SYS := .ko else SUFF_SYS := endif SUFF_RES := endif # # Standard kBuild tools. # ifeq ($(KMK),kmk) KMK := $(KBUILD_BIN_PATH)/kmk$(HOSTSUFF_EXE) endif MAKE := $(KMK) GMAKE := $(KBUILD_BIN_PATH)/kmk_gmake$(HOSTSUFF_EXE) #DEP_EXT := $(KBUILD_BIN_PATH)/kDep$(HOSTSUFF_EXE) #DEP_INT := $(KBUILD_BIN_PATH)/kDep$(HOSTSUFF_EXE) #DEP := $(DEP_INT) DEP_IDB_EXT := $(KBUILD_BIN_PATH)/kDepIDB$(HOSTSUFF_EXE) DEP_IDB_INT := kmk_builtin_kDepIDB DEP_IDB := $(DEP_IDB_INT) DEP_PRE := $(KBUILD_BIN_PATH)/kDepPre$(HOSTSUFF_EXE) KOBJCACHE_EXT := $(KBUILD_BIN_PATH)/kObjCache$(HOSTSUFF_EXE) KOBJCACHE := $(KOBJCACHE_EXT) APPEND_EXT := $(KBUILD_BIN_PATH)/kmk_append$(HOSTSUFF_EXE) APPEND_INT := kmk_builtin_append APPEND := $(APPEND_INT) CAT_EXT := $(KBUILD_BIN_PATH)/kmk_cat$(HOSTSUFF_EXE) CAT_INT := kmk_builtin_cat CAT := $(CAT_INT) CHMOD_EXT := $(KBUILD_BIN_PATH)/kmk_chmod$(HOSTSUFF_EXE) CHMOD_INT := kmk_builtin_chmod CHMOD := $(CHMOD_INT) CMP_EXT := $(KBUILD_BIN_PATH)/kmk_cmp$(HOSTSUFF_EXE) CMP_INT := kmk_builtin_cmp CMP := $(CMP_INT) CP_EXT := $(KBUILD_BIN_PATH)/kmk_cp$(HOSTSUFF_EXE) CP_INT := kmk_builtin_cp CP := $(CP_INT) ECHO_EXT := $(KBUILD_BIN_PATH)/kmk_echo$(HOSTSUFF_EXE) ECHO_INT := kmk_builtin_echo ECHO := $(ECHO_INT) EXPR_EXT := $(KBUILD_BIN_PATH)/kmk_expr$(HOSTSUFF_EXE) EXPR_INT := kmk_builtin_expr EXPR := $(EXPR_INT) INSTALL_EXT := $(KBUILD_BIN_PATH)/kmk_install$(HOSTSUFF_EXE) INSTALL_INT := kmk_builtin_install INSTALL := $(INSTALL_INT) LN_EXT := $(KBUILD_BIN_PATH)/kmk_ln$(HOSTSUFF_EXE) LN_INT := kmk_builtin_ln LN := $(LN_INT) MD5SUM_EXT := $(KBUILD_BIN_PATH)/kmk_md5sum$(HOSTSUFF_EXE) MD5SUM_INT := kmk_builtin_md5sum MD5SUM := $(MD5SUM_INT) MKDIR_EXT := $(KBUILD_BIN_PATH)/kmk_mkdir$(HOSTSUFF_EXE) MKDIR_INT := kmk_builtin_mkdir MKDIR := $(MKDIR_INT) MV_EXT := $(KBUILD_BIN_PATH)/kmk_mv$(HOSTSUFF_EXE) MV_INT := kmk_builtin_mv MV := $(MV_INT) PRINTF_EXT := $(KBUILD_BIN_PATH)/kmk_printf$(HOSTSUFF_EXE) PRINTF_INT := kmk_builtin_printf PRINTF := $(PRINTF_INT) REDIRECT_EXT:= $(KBUILD_BIN_PATH)/kmk_redirect$(HOSTSUFF_EXE) REDIRECT_INT:= $(REDIRECT_EXT) REDIRECT := $(REDIRECT_INT) RM_EXT := $(KBUILD_BIN_PATH)/kmk_rm$(HOSTSUFF_EXE) RM_INT := kmk_builtin_rm RM := $(RM_INT) RMDIR_EXT := $(KBUILD_BIN_PATH)/kmk_rmdir$(HOSTSUFF_EXE) RMDIR_INT := kmk_builtin_rmdir RMDIR := $(RMDIR_INT) SED_EXT := $(KBUILD_BIN_PATH)/kmk_sed$(HOSTSUFF_EXE) SED_INT := $(SED_EXT) SED := $(SED_EXT) SLEEP_INT := kmk_builtin_sleep SLEEP_EXT := $(KBUILD_BIN_PATH)/kmk_sleep$(HOSTSUFF_EXE) SLEEP := $(SLEEP_EXT) TEST_EXT := $(KBUILD_BIN_PATH)/kmk_test$(HOSTSUFF_EXE) TEST_INT := kmk_builtin_test TEST := $(TEST_INT) TIME_EXT := $(KBUILD_BIN_PATH)/kmk_time$(HOSTSUFF_EXE) TIME_INT := $(TIME_EXT) TIME := $(TIME_INT) # Our default shell is the Almquist shell from *BSD. ASH := $(KBUILD_BIN_PATH)/kmk_ash$(HOSTSUFF_EXE) MAKESHELL := $(ASH) SHELL := $(ASH) export SHELL MAKESHELL # Symlinking is problematic on some platforms... LN_SYMLINK := $(LN) -s # When copying to the staging area, use hard links to save time and space. ifndef KBUILD_NO_HARD_LINKING INSTALL_STAGING := $(INSTALL) --hard-link-files-when-possible else INSTALL_STAGING := $(INSTALL) endif # # Some Functions. # The lower cased ones are either fallbacks or candidates for functions.c. # ## ABSPATH - make paths absolute. # This implementation is clumsy and doesn't resolve '..' and '.' components. # # @param $1 The paths to make absolute. # @obsolete Use the GNU make function $(abspath) directly now. ABSPATH = $(abspath $(1))$(warning ABSPATH is deprecated, use abspath directly!) ## DIRDEP - make create directory dependencies. # # @param $1 The paths to the directories which must be created. DIRDEP = $(foreach path,$(patsubst %/,%,$(1)),$(path)/) ## Cygwin kludge. # This converts /cygdrive/x/% to x:%. # # @param $1 The paths to make native. # @remark This macro is pretty much obsolete since we don't use cygwin base make. ifneq ($(patsubst /cygdrive/%,%,$(CURDIR)),$(CURDIR)) CYGPATHMIXED = $(foreach path,$(1)\ ,$(if $(patsubst /cygdrive/%,,$(path)),$(path),$(patsubst $(strip $(firstword $(subst /, ,$(patsubst /cygdrive/%,%,$(path)))))/%,$(strip $(firstword $(subst /, ,$(patsubst /cygdrive/%,%,$(path))))):/%,$(patsubst /cygdrive/%,%,$(path))))) else CYGPATHMIXED = $(1) endif ## Removes the drive letter from a path (if it has one) # @param $1 the path no-drive = $(word $(words $(subst :, ,$(1))),$(subst :, ,$(1))) ## Removes the root slash from a path (if it has one) # @param $1 the path no-root-slash = $(patsubst /%,%,$(1)) ## # Similar to firstword, except it returns the value of first defined variable. # @param $1 list of variables to probe. define FIRST-DEFINED-VAR local .RETURN := $(strip $(firstdefined $1, value)) endef ## Figure out where to put object files. # @param $1 real target name. # @param $2 normalized main target TARGET_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(1))) ## Figure out where to put object files. # @param $1 normalized main target TARGET_PATH = $(PATH_TARGET)/$(1) ## # Checks if the specified short option ($1) is found in the flags ($2), # assuming getopt style options. # # @returns $3 if present, $4 not. # # @param $1 The option (single char!). # @param $2 The option arguments. # @param $3 Eval and return if present. # @param $4 Eval and return if not present. # # @todo May confuse option values starting with '-' for options. # @remarks Invoke like this: $(evalcall KB_FN_OPT_TEST_SHORT,d,$(flags),present,not-present) # define KB_FN_OPT_TEST_SHORT local options := $(translate $(strip $(filter -%,$(filter-out --%,$2))),$(SP)-,) local .RETURN := $(if-expr $(pos $1,$(options)) != 0,$3,$4) endef ## # Checks if the specified long option ($1) is found in the flags ($2), # assuming getopt style options. # # @returns $3 if present, $4 not. # # @param $1 The long option, dashes included. No % chars. # @param $2 The option arguments. # @param $3 Eval and return if present. # @param $4 Eval and return if not present. # # @todo May confuse option values starting with '--' for options. # @remarks Invoke like this: $(evalcall KBFN_OPT_TEST_SHORT,--defined,$(flags),present,not-present) # define KB_FN_OPT_TEST_LONG local options := $(filter-out =delete=%,$(subst :, =delete=,$(subst =, =delete=,$2))) local .RETURN := $(if-expr "$(filter $1,$(options))" != "",$3,$4) endef ## # Checks if the specified short ($1) or long ($2) option is found in the flags ($2), # assuming getopt style options. # # @returns $4 if present, $5 not. # # @param $1 The short option (single char!). # @param $2 The long option, dashes included. No % chars. # @param $3 The option arguments. # @param $4 Eval and return if present. # @param $5 Eval and return if not present. # # @todo May confuse option values starting with '--' for options. # @remarks Invoke like this: $(evalcall KB_FN_OPT_TEST_SHORT_LONG,d,--defined,$(flags),present,not-present) # define KB_FN_OPT_TEST_SHORT_LONG local short_options := $(translate $(strip $(filter -%,$(filter-out --%,$3))),$(SP)-,) local long_options := $(filter-out =delete=%,$(subst :, =delete=,$(subst =, =delete=,$3))) local .RETURN := $(if-expr $(pos $1,$(short_options)) != 0 || "$(filter $2,$(long_options))" != "",$4,$5) endef ## # Make an assignment to a deprecated variable. # # @param $1 The variable name. # @param $2 The value. # @param $3 The variable to use instead. # ifdef KBUILD_WITH_DEPREATED_AS_ERROR KB_FN_ASSIGN_DEPRECATED = $(eval $(subst :,$$(COLON),$1) = $2$$(error $1 is deprecated, use $3 instead)) else KB_FN_ASSIGN_DEPRECATED = $(eval $(subst :,$$(COLON),$1) = $2$$(warning $1 is deprecated, use $3 instead)) endif ## # Show an assertion message. # # @param $1 The assertion name. # @param $2 The details. # define KB_FN_ASSERT_MSG $(info !! kBuild $1 Assertion Failed !!) ifdef target $(info !! target: $(target)) local varloc := $(where $(target)) if "$(varloc)" == "undefined" local varloc := $(where $(target)_TEMPLATE) endif if "$(varloc)" == "undefined" local varloc := $(where $(target)_SOURCES) endif if "$(varloc)" == "undefined" local varloc := $(where $(target)_EXTENDS) endif if "$(varloc)" == "undefined" local varloc := $(where target) endif ifneq ($(varloc),) $(info !! location: $(varloc)) else $(info !! probable location: $($(target)_DEFPATH)/Makefile.kmk) endif endif $(info !! $2) $(error fixme) endef ## # Throw an error if the given path $1 isn't absolute and assertions are enabled. # # @param $1 The name of the path variable to check. # ifdef KBUILD_INTERNAL_STRICT KB_FN_ASSERT_ABSPATH = $(if-expr "$(abspath $($(strip $1)))" != "$(strip $($(strip $1)))",\ $(evalcall KB_FN_ASSERT_MSG,abspath,$1 is:$(NLTAB)'$($(strip $1))'$(NLTAB)expected:$(NLTAB)'$(abspath $($(strip $1)))')) else KB_FN_ASSERT_ABSPATH := endif # # Initialize some of the globals which the Config.kmk and # others can add stuff to if they like for processing in the footer. # ## KBUILD_TEMPLATE_PATHS # List a paths (separated by space) where templates can be found. KBUILD_TEMPLATE_PATHS := ## KBUILD_TOOL_PATHS # List of paths (separated by space) where tools can be found. KBUILD_TOOL_PATHS := ## KBUILD_SDK_PATHS # List of paths (separated by space) where SDKs can be found. KBUILD_SDK_PATHS := ## KBUILD_UNIT_PATHS # List of paths (separated by space) where units (USES) can be found. KBUILD_UNIT_PATHS := ## KBUILD_DEFAULT_PATHS # List of paths (separated by space) to search for stuff as a last resort. KBUILD_DEFAULT_PATHS := ## Proritized list of the default makefile when walking subdirectories. # The user can overload this list. DEFAULT_MAKEFILE := Makefile.kmk makefile.kmk Makefile makefile ## KBUILD_SRC_HANDLERS # The list of source handlers, pair of extension and handler. # The user can overload this list to provide additional or custom # handlers. On a per-target/template see SRC_HANDLERS. KBUILD_SRC_HANDLERS := \ .c:def_src_handler_c \ .C:def_src_handler_c \ .cxx:def_src_handler_cxx \ .CXX:def_src_handler_cxx \ .cpp:def_src_handler_cxx \ .CPP:def_src_handler_cxx \ .cc:def_src_handler_cxx \ .CC:def_src_handler_cxx \ .m:def_src_handler_objc \ .M:def_src_handler_objcxx \ .mm:def_src_handler_objcxx \ .asm:def_src_handler_asm \ .ASM:def_src_handler_asm \ .s:def_src_handler_asm \ .S:def_src_handler_asm \ .rc:def_src_handler_rc \ .obj:def_src_handler_obj \ .o:def_src_handler_obj \ .res:def_src_handler_obj ## PROPS_TOOLS # This is a subset of PROPS_SINGLE. PROPS_TOOLS := TOOL CTOOL CXXTOOL OBJCTOOL OBJCXXTOOL ASTOOL RCTOOL ARTOOL LDTOOL FETCHTOOL UNPACKTOOL PATCHTOOL ## PROPS_SINGLE # The list of non-accumulative target properties. # A Config.kmk file can add it's own properties to this list and kBuild # will do the necessary inheritance for templates, sdks, tools and targets. PROPS_SINGLE := $(PROPS_TOOLS) TEMPLATE INSTTYPE INST STAGE NOINST BLD_TYPE BLD_TRG BLD_TRG_ARCH BLD_TRG_CPU FETCHDIR \ OBJSUFF COBJSUFF CXXOBJSUFF OBJCOBJSUFF OBJCXXOBJSUFF ASOBJSUFF RCOBJSUFF SYSSUFF BINSUFF EXESUFF DLLSUFF LIBSUFF ARLIBSUFF \ MODE UID GID LD_DEBUG DEBUG_INSTTYPE DEBUG_INST DEBUG_STAGE ## PROPS_SINGLE_LNK # Subset of PROPS_SINGLE which applies to all linkable targets. PROPS_SINGLE_LNK := $(filter-out FETCHTOOL UNPACKTOOL PATCHTOOL FETCHDIR, $(PROPS_SINGLE)) ## PROPS_DEFERRED # This list of non-accumulative target properties which are or may be # functions, and thus should not be expanded until the very last moment. PROPS_DEFERRED := INSTFUN INSTALLER PRE_CMDS POST_CMDS PRE_INST_CMDS POST_INST_CMDS \ PRE_FILE_CMDS POST_FILE_CMDS PRE_SYMLINK_CMDS POST_SYMLINK_CMDS PRE_DIRECTORY_CMDS POST_DIRECTORY_CMDS \ NAME SONAME ## PROPS_ACCUMULATE_R # The list of accumulative target properties where the right most value/flag # is the 'most significant'. # A Config.kmk file can add it's own properties to this list and kBuild # will do the necessary inheritance from templates to targets. PROPS_ACCUMULATE_R := \ DEPS LNK_DEPS ORDERDEPS LNK_ORDERDEPS DEFS \ ARFLAGS \ CFLAGS CDEFS \ CXXFLAGS CXXDEFS \ OBJCFLAGS OBJCDEFS \ OBJCXXFLAGS OBJCXXDEFS \ ASFLAGS ASDEFS \ RCFLAGS RCDEFS \ LDFLAGS \ IDFLAGS IFFLAGS EXEC_IFFLAGS ISFLAGS \ FETCHFLAGS UNPACKFLAGS PATCHFLAGS ## PROPS_ACCUMULATE_R_LNK # Subset of PROPS_ACCUMULATE_R which applies to all linkable targets. PROPS_ACCUMULATE_R_LNK := $(filter-out ARFLAGS LDFLAGS EXEC_IFFLAGS FETCHFLAGS UNPACKFLAGS PATCHFLAGS, $(PROPS_ACCUMULATE_R)) ## PROPS_ACCUMULATE # The list of accumulative target properties where the left most value/flag # is the 'most significant'. # A Config.kmk file can add it's own properties to this list and kBuild # will do the necessary inheritance from templates to targets. PROPS_ACCUMULATE_L := \ SDKS USES SOURCES EXEC_SOURCES SRC_HANDLERS INTERMEDIATES \ INCS CINCS CXXINCS OBJCINCS OBJCXXINCS ASINCS RCINCS \ LIBS LIBPATH \ DIRS BLDDIRS CLEAN ## PROPS_ACCUMULATE_L_LNK # Subset of PROPS_ACCUMULATE_L which applies to all linkable targets. PROPS_ACCUMULATE_L_LNK := $(filter-out LIBS LIBPATH EXEC_SOURCES DIRS, $(PROPS_ACCUMULATE_L)) ## PROPS_ALL # List of all the properties. PROPS_ALL = $(PROPS_SINGLE) $(PROPS_DEFERRED) $(PROPS_ACCUMULATE_L) $(PROPS_ACCUMULATE_R) ## @name Properties valid on programs (BLDPROGS and PROGRAMS) ## @{ PROPS_PROGRAMS_SINGLE := $(PROPS_SINGLE_LNK) LDTOOL EXESUFF PROPS_PROGRAMS_DEFERRED := $(PROPS_DEFERRED) PROPS_PROGRAMS_ACCUMULATE_R := $(PROPS_ACCUMULATE_R_LNK) LDFLAGS PROPS_PROGRAMS_ACCUMULATE_L := $(PROPS_ACCUMULATE_L_LNK) LIBS LIBPATH ## @} ## @name Properties valid on libraries (LIBRARIES and IMPORT_LIBS) ## @{ PROPS_LIBRARIES_SINGLE := $(PROPS_SINGLE_LNK) ARTOOL LIBSUFF ARLIBSUFF LIBSUFF PROPS_LIBRARIES_DEFERRED := $(filter-out SONAME,$(PROPS_DEFERRED)) PROPS_LIBRARIES_ACCUMULATE_R := $(PROPS_ACCUMULATE_R_LNK) ARFLAGS PROPS_LIBRARIES_ACCUMULATE_L := $(PROPS_ACCUMULATE_L_LNK) ## @} ## @name Properties valid on dlls (DLLS) ## @{ PROPS_DLLS_SINGLE := $(PROPS_SINGLE_LNK) LDTOOL DLLSUFF LIBSUFF PROPS_DLLS_DEFERRED := $(PROPS_DEFERRED) PROPS_DLLS_ACCUMULATE_R := $(PROPS_ACCUMULATE_R_LNK) LDFLAGS PROPS_DLLS_ACCUMULATE_L := $(PROPS_ACCUMULATE_L_LNK) LIBS LIBPATH ## @} ## @name Properties valid on system modules (SYSMODS) ## @{ PROPS_SYSMODS_SINGLE := $(PROPS_SINGLE_LNK) LDTOOL SYSSUFF PROPS_SYSMODS_DEFERRED := $(PROPS_DEFERRED) PROPS_SYSMODS_ACCUMULATE_R := $(PROPS_ACCUMULATE_R_LNK) LDFLAGS PROPS_SYSMODS_ACCUMULATE_L := $(PROPS_ACCUMULATE_L_LNK) LIBS LIBPATH ## @} ## @name Properties valid on misc binaries (MISCBINS) ## @{ PROPS_MISCBINS_SINGLE := $(PROPS_SINGLE_LNK) LDTOOL BINSUFF PROPS_MISCBINS_DEFERRED := $(PROPS_DEFERRED) PROPS_MISCBINS_ACCUMULATE_R := $(PROPS_ACCUMULATE_R_LNK) LDFLAGS PROPS_MISCBINS_ACCUMULATE_L := $(PROPS_ACCUMULATE_L_LNK) LIBS LIBPATH ## @} ## @name Properties valid on installs (INSTALLS) ## @{ PROPS_INSTALLS_SINGLE := TOOL TEMPLATE INSTTYPE INST STAGE NOINST BLD_TYPE BLD_TRG BLD_TRG_ARCH BLD_TRG_CPU MODE UID GID PROPS_INSTALLS_DEFERRED := INSTFUN INSTALLER PRE_FILE_CMDS POST_FILE_CMDS PRE_SYMLINK_CMDS POST_SYMLINK_CMDS \ PRE_DIRECTORY_CMDS POST_DIRECTORY_CMDS PROPS_INSTALLS_ACCUMULATE_R := DEPS ORDERDEPS GOALS INST_ONLY_GOALS STAGE_ONLY_GOALS IFFLAGS EXEC_IFFLAGS PROPS_INSTALLS_ACCUMULATE_L := SOURCES EXEC_SOURCES DIRS CLEAN ## @} ## @name Properties valid on fetches (FETCHES) ## @{ PROPS_FETCHES_SINGLE := TOOL TEMPLATE FETCHTOOL UNPACKTOOL PATCHTOOL INST FETCHDIR PROPS_FETCHES_DEFERRED := PROPS_FETCHES_ACCUMULATE_R := FETCHFLAGS UNPACKFLAGS PATCHFLAGS PROPS_FETCHES_ACCUMULATE_L := SOURCES CLEAN ## @} ## KBUILD_COMPILE_CATEGTORIES # Tools categories for compiling. KBUILD_COMPILE_CATEGTORIES := AS C CXX OBJC OBJCXX RC ## KBUILD_GENERIC_CATEGORIES # Generic tool categories. KBUILD_GENERIC_CATEGORIES := FETCH UNPACK PATCH $(addprefix LINK_,LIBRARY PROGRAM DLL SYSMOD MISCBIN) ## PROPS_TOOLS_ONLY # Properties found only on tools. # This is expanded in a deferred manner, so it will pick up changes made to # KBUILD_COMPILE_CATEGTORIES and KBUILD_GENERIC_CATEGORIES made by units. PROPS_TOOLS_ONLY = \ $(foreach cat, $(KBUILD_COMPILE_CATEGTORIES), \ COMPILE_$(cat)_CMDS \ COMPILE_$(cat)_OUTPUT \ COMPILE_$(cat)_OUTPUT_MAYBE \ COMPILE_$(cat)_DEPEND \ COMPILE_$(cat)_DEPORD \ COMPILE_$(cat)_USES_KOBJCACHE ) \ $(foreach cat, $(KBUILD_GENERIC_CATEGORIES), \ $(cat)_CMDS \ $(cat)_OUTPUT \ $(cat)_OUTPUT_MAYBE \ $(cat)_DEPEND \ $(cat)_DEPORD )) # # Here is a special 'hack' to prevent innocent environment variables being # picked up and treated as properties. (The most annoying example of why # this is necessary is the Visual C++ commandline with it's LIBPATH.) # # Define KBUILD_DONT_KILL_ENV_PROPS in the env. or on the commandline to # disable this 'hack'. # ifndef KBUILD_DONT_KILL_ENV_PROPS define def_nuke_environment_prop ifeq ($(origin $(prop)),environment) $(prop) = endif endef $(foreach prop, $(PROPS_ALL) \ FETCHES PATCHES BLDPROGS LIBRARIES IMPORT_LIBS DLLS PROGRAMS SYSMODS MISCBINS INSTALLS OTHERS \ SUBDIRS MAKEFILES BLDDIRS \ ,$(eval $(value def_nuke_environment_prop))) endif # KBUILD_DONT_KILL_ENV_PROPS # # Pass configuration. # # The PASS__trgs variable is listing the targets. # The PASS__vars variable is listing the target variables. # The PASS__pass variable is the lowercased passname. # ## PASS: fetches # This pass fetches and unpacks things needed to complete the build. PASS_FETCHES := Fetches PASS_FETCHES_trgs := PASS_FETCHES_vars := _FETCHES PASS_FETCHES_pass := fetches ## PASS: patches # This pass applies patches. PASS_PATCHES := Patches PASS_PATCHES_trgs := PASS_PATCHES_vars := _PATCHES PASS_PATCHES_pass := patches ## PASS: bldprogs # This pass builds targets which are required for building the rest. PASS_BLDPROGS := Build Programs PASS_BLDPROGS_trgs := PASS_BLDPROGS_vars := _BLDPROGS PASS_BLDPROGS_pass := bldprogs ## PASS: libraries # This pass builds library targets. PASS_LIBRARIES := Libraries PASS_LIBRARIES_trgs := PASS_LIBRARIES_vars := _LIBS _IMPORT_LIBS _OTHER_LIBRARIES PASS_LIBRARIES_pass := libraries ## PASS: binaries # This pass builds dll targets. PASS_DLLS := DLLs PASS_DLLS_trgs := PASS_DLLS_vars := _DLLS _OTHER_DLLS PASS_DLLS_pass := dlls ## PASS: binaries # This pass builds binary targets, i.e. programs, system modules and stuff. PASS_BINARIES := Programs PASS_BINARIES_trgs := PASS_BINARIES_vars := _PROGRAMS _SYSMODS _MISC_BINS _OTHER_BINARIES PASS_BINARIES_pass := binaries ## PASS: others # This pass builds other targets. PASS_OTHERS := Other Stuff PASS_OTHERS_trgs := PASS_OTHERS_vars := _OTHERS PASS_OTHERS_pass := others ## PASS: staging # This pass installs the built entities to a sandbox area. ## @todo split this up into build install (to sandbox) and real installation. PASS_STAGING := Staging PASS_STAGING_trgs := PASS_STAGING_vars := _STAGE_DIRS _INSTALLS _STAGE_FILES _DEBUG_STAGE_DIRS _DEBUG_STAGE_FILES PASS_STAGING_pass := staging ## PASS: install # This pass installs the built entities to where they will be used (using # DESTROOT or PATH_INS to indicate where this is). PASS_INSTALLS := Install PASS_INSTALLS_trgs := PASS_INSTALLS_vars := _INSTALLS_DIRS _INSTALLS_FILES _DEBUG_INSTALL_DIRS _DEBUG_INSTALL_FILES PASS_INSTALLS_pass := installs ## PASS: testing # This pass processes custom rules for executing tests. PASS_TESTING := Tests PASS_TESTING_trgs := PASS_TESTING_vars := _TESTING PASS_TESTING_pass := testing ## PASS: packing # This pass processes custom packing rules. PASS_PACKING := Packing PASS_PACKING_trgs := PASS_PACKING_vars := _PACKING PASS_PACKING_pass := packing ## PASS: clean # This pass removes all generated files. PASS_CLEAN := Clean PASS_CLEAN_trgs := do-clean PASS_CLEAN_vars := PASS_CLEAN_pass := clean ## PASS: nothing # This pass just walks the tree. PASS_NOTHING := Nothing PASS_NOTHING_trgs := do-nothing PASS_NOTHING_vars := PASS_NOTHING_pass := nothing ## DEFAULT_PASSES # The default passes and their order. DEFAULT_PASSES := BLDPROGS LIBRARIES DLLS BINARIES OTHERS STAGING ## PASSES # The passes that should be defined. This must include # all passes mentioned by DEFAULT_PASSES. PASSES := FETCHES PATCHES $(DEFAULT_PASSES) INSTALLS TESTING PACKING CLEAN NOTHING # # Check for --pretty-command-printing before including the Config.kmk # so that anyone overriding the message macros can take the implied # verbosity level change into account. # ifndef KBUILD_VERBOSE ifndef KBUILD_QUIET ifeq ($(KMK_OPTS_PRETTY_COMMAND_PRINTING),1) export KBUILD_VERBOSE := 2 endif endif endif # # Legacy variable translation. # These will be eliminated when switching to the next version. # ifdef USE_KOBJCACHE ifndef KBUILD_USE_KOBJCACHE export KBUILD_USE_KOBJCACHE := $(USE_KOBJCACHE) endif endif # # Library path searching hints (target OS + arch). # # KBUILD_LIB_SEARCH_SUBS - Subdirs typically containing the right libraries. # KBUILD_LIB_SEARCH_ROOTS - Roots to search for library subdirs. # KBUILD_LIB_SEARCH_PATHS - ROOTS + SUBS. # ifeq ($(KBUILD_TARGET),darwin) KBUILD_LIB_SEARCH_ROOTS := \ /usr/ \ /Developer/usr/ KBUILD_LIB_SEARCH_SUBS := lib/ else if1of ($(KBUILD_TARGET), freebsd netbsd openbsd dragonfly) KBUILD_LIB_SEARCH_ROOTS := \ / \ /usr/ \ /usr/local/ KBUILD_LIB_SEARCH_SUBS := lib/ else ifeq ($(KBUILD_TARGET),linux) ifeq ($(realpath /bin),/usr/bin) KBUILD_LIB_SEARCH_ROOTS := \ /usr/ \ / \ /usr/local/ else KBUILD_LIB_SEARCH_ROOTS := \ / \ /usr/ \ /usr/local/ endif ifeq ($(KBUILD_TARGET_ARCH),amd64) KBUILD_LIB_SEARCH_SUBS := \ lib/x86_64-linux-gnu/ \ lib64/ \ lib/ else ifeq ($(KBUILD_TARGET_ARCH),x86) KBUILD_LIB_SEARCH_SUBS := \ lib/i686-linux-gnu/ \ lib/i386-linux-gnu/ \ lib32/ \ lib/ else KBUILD_LIB_SEARCH_SUBS := lib/ endif else ifeq ($(KBUILD_TARGET),solaris) KBUILD_LIB_SEARCH_ROOTS := \ / \ /usr/ \ /usr/sfw/ \ /usr/local/ \ /sw/ ifeq ($(KBUILD_TARGET_ARCH),amd64) KBUILD_LIB_SEARCH_SUBS := lib/amd64/ lib/ else ifeq ($(KBUILD_TARGET_ARCH),sparc64) KBUILD_LIB_SEARCH_SUBS := lib/sparcv9/ lib/ else KBUILD_LIB_SEARCH_SUBS := lib/ endif else KBUILD_LIB_SEARCH_SUBS := KBUILD_LIB_SEARCH_ROOTS := endif KBUILD_LIB_SEARCH_PATHS := $(foreach root, $(KBUILD_LIB_SEARCH_ROOTS), $(addprefix $(root),$(KBUILD_LIB_SEARCH_SUBS))) # # This is how we find the closest config.kmk. # It's a little hacky but I think it works fine. # _CFGDIR := . _CFGFILES := ./Config.kmk ./config.kmk define def_include_config $(eval _CFGDIR := $(_CFGDIR)/$(dir)) _CFGFILES += $(_CFGDIR)/Config.kmk $(_CFGDIR)/config.kmk endef # walk down the _RELATIVE_ path specified by DEPTH. $(foreach dir,$(subst /, ,$(DEPTH)), $(eval $(def_include_config)) ) # add the default config file. _CFGFILE := $(firstword $(wildcard $(_CFGFILES) $(FILE_KBUILD_CONFIG))) _CFGFILES := _CFGDIR := ifeq ($(_CFGFILE),) $(error kBuild: no Config.kmk file found! Check the DEPTH: DEPTH='$(DEPTH)' PATH_CURRENT='$(PATH_CURRENT)') endif # Include the config.kmk we found file (or the default one). ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, including $(_CFGFILE)) include $(_CFGFILE) $(evalcall def_profile_self, included $(_CFGFILE)) else include $(_CFGFILE) endif # # Finalize a the central path variables now that we've included the Config.kmk file. # # This prevents some trouble when users override the defaults for these # variables and uses relative paths or paths with incorrect case. # PATH_OUT_BASE := $(abspath $(PATH_OUT_BASE)) PATH_OUT := $(abspath $(PATH_OUT)) PATH_OBJ := $(abspath $(PATH_OBJ)) PATH_TARGET := $(abspath $(PATH_TARGET)) PATH_INS := $(abspath $(PATH_INS)) PATH_STAGE := $(abspath $(PATH_STAGE)) # Finalize the install and staging directory layouts. define def_kbuild_finalize_inst local val := $(strip $($(y)_$(x))) ifeq ($(val),) $(error kBuild: '$(y)_$(x)' is set to an empty value.) endif ifneq ($(words $(val)),1) $(error kBuild: The '$(y)_$(x)' value '$(val)' should not contain spaces.) endif ifneq ($(pos \,$(val)), 0) $(error kBuild: The '$(y)_$(x)' value '$(val)' contains DOS slashes: not allowed.) endif ifneq ($(pos $(COLON),$(val)), 0) $(error kBuild: The '$(y)_$(x)' value '$(val)' contains colon: not allowed.) endif ifneq ($(substr $(val),-1), /) $(error kBuild: The '$(y)_$(x)' value '$(val)' has no trailing slash.) endif if $(pos /../,$(val)) != 0 || "$(substr $(val), 3)" == "../" $(error kBuild: The '$(y)_$(x)' value '$(val)' contains dot-dot escape.) endif $($(y)_$(x) := $(val) local val := $(strip $(PATH_$(y)_$(x))) ifeq ($(val),) $(error kBuild: 'PATH_$(y)_$(x)' is set to an empty value.) endif PATH_$(y)_$(x) := $(val) endef $(foreach y, INST STAGE, $(foreach x, $(KBUILD_INST_PATHS), $(evalcall def_kbuild_finalize_inst))) # # Setup the message style. The default one is inlined. # # See kBuild/msgstyles for more styles or use KBUILD_MSG_STYLE_PATHS # to create your own message style. # KBUILD_MSG_STYLE ?= default ifeq ($(KBUILD_MSG_STYLE),default) # # The 'default' style. # ## Fetch starting. # @param 1 Target name. MSG_FETCH ?= $(call MSG_L1,Fetching $1...) ## Re-fetch starting. # @param 1 Target name. MSG_REFETCH ?= $(call MSG_L1,Re-fetching $1...) ## Downloading a fetch component. # @param 1 Target name. # @param 2 The source URL. # @param 3 The destination file name. MSG_FETCH_DL ?= $(call MSG_L1,Downloading $1 - $2,=> $3) ## Checking a fetch component. # @param 1 Target name. # @param 2 The source URL. # @param 3 The destination file name. MSG_FETCH_CHK?= $(call MSG_L1,Checking $1 - $3, ($2)) ## Unpacking a fetch component. # @param 1 Target name. # @param 2 The archive file name. # @param 3 The target directory. MSG_FETCH_UP ?= $(call MSG_L1,Unpacking $1 - $2 => $3) ## Fetch completed. # @param 1 Target name. MSG_FETCH_OK ?= $(call MSG_L1,Successfully fetched $1) ## Unfetch a fetch target. # @param 1 Target name. MSG_UNFETCH ?= $(call MSG_L1,Unfetching $1...) ## Compiling a source file. # @param 1 Target name. # @param 2 The source filename. # @param 3 The primary link output file name. # @param 4 The source type (C,CXX,OBJC,AS,RC,++). MSG_COMPILE ?= $(call MSG_L1,Compiling $1 - $2,=> $3) ## Tool # @param 1 The tool name (bin2c,...) # @param 2 Target name. # @param 3 The source filename. # @param 4 The primary output file name. MSG_TOOL ?= $(call MSG_L1,$1 $2 - $3,=> $4) ## Generate a file, typically a source file. # @param 1 Target name if applicable. # @param 2 Output file name. # @param 3 What it's generated from MSG_GENERATE ?= $(call MSG_L1,Generating $(if $1,$1 - )$2,$(if $3,from $3)) ## Linking a bldprog/dll/program/sysmod target. # @param 1 Target name. # @param 2 The primary link output file name. # @param 3 The link tool operation (LINK_LIBRARY,LINK_PROGRAM,LINK_DLL,LINK_SYSMOD,++). MSG_LINK ?= $(call MSG_L1,Linking $1,=> $2) ## Merging a library into the target (during library linking). # @param 1 Target name. # @param 2 The output library name. # @param 3 The input library name. MSG_AR_MERGE ?= $(call MSG_L1,Merging $3 into $1, ($2)) ## Creating a directory (build). # @param 1 Directory name. MSG_MKDIR ?= $(call MSG_L2,Creating directory $1) ## Cleaning. MSG_CLEAN ?= $(call MSG_L1,Cleaning...) ## Nothing. MSG_NOTHING ?= $(call MSG_L1,Did nothing in $(CURDIR)) ## Pass # @param 1 The pass name. MSG_PASS ?= $(call MSG_L1,Pass - $1) ## Installing a bldprog/lib/dll/program/sysmod target. # @param 1 Target name. # @param 2 The source filename. # @param 3 The destination file name. MSG_INST_TRG ?= $(call MSG_L1,Installing $1 => $3) ## Installing a file (install target). # @param 1 The source filename. # @param 2 The destination filename. MSG_INST_FILE?= $(call MSG_L1,Installing $2,(<= $1)) ## Installing a symlink. # @param 1 Symlink # @param 2 Link target MSG_INST_SYM ?= $(call MSG_L1,Installing symlink $1,=> $2) ## Installing a directory. # @param 1 Directory name. MSG_INST_DIR ?= $(call MSG_L1,Installing directory $1) else _KBUILD_MSG_STYLE_FILE := $(firstword $(foreach path, $(KBUILD_MSG_STYLE_PATHS) $(KBUILD_PATH)/msgstyles, $(wildcard $(path)/$(KBUILD_MSG_STYLE).kmk))) ifneq ($(_KBUILD_MSG_STYLE_FILE),) include $(_KBUILD_MSG_STYLE_FILE) else $(error kBuild: Can't find the style setup file for KBUILD_MSG_STYLE '$(KBUILD_MSG_STYLE)') endif endif # # Message macros. # # This is done after including Config.kmk as to allow for # KBUILD_QUIET and KBUILD_VERBOSE to be configurable. # ifdef KBUILD_QUIET # No output QUIET := @ QUIET2:= @ MSG_L1 = MSG_L2 = else ifndef KBUILD_VERBOSE # Default output level. QUIET := @ QUIET2 := @ MSG_L1 ?= %@$(ECHO) "kBuild: $1" MSG_L2 = else ifeq ($(KBUILD_VERBOSE),1) # A bit more output QUIET := @ QUIET2 := @ MSG_L1 ?= %@$(ECHO) "kBuild: $1 $2" MSG_L2 = else ifeq ($(KBUILD_VERBOSE),2) # Lot more output QUIET := QUIET2 := @ MSG_L1 ?= %@$(ECHO) "kBuild: $1 $2" MSG_L2 ?= %@$(ECHO) "kBuild: $1" else # maximal output. QUIET := QUIET2 := MSG_L1 ?= %@$(ECHO) "kBuild: $1 $2" MSG_L2 ?= %@$(ECHO) "kBuild: $1" endif endif # # Validate any KBUILD_BLD_TYPES additions and finally the KBUILD_TYPE. # if1of ($(KBUILD_BLD_TYPES), $(KBUILD_OSES)) $(error kBuild: found KBUILD_BLD_TYPES in KBUILD_OSES!) endif if1of ($(KBUILD_BLD_TYPES), $(KBUILD_ARCHES)) $(error kBuild: found KBUILD_BLD_TYPES in KBUILD_ARCHES!) endif if1of ($(KBUILD_OSES), $(KBUILD_ARCHES)) $(error kBuild: found KBUILD_OSES in KBUILD_ARCHES!) endif ifn1of ($(KBUILD_TYPE), $(KBUILD_BLD_TYPES)) $(error kBuild: KBUILD_TYPE(=$(KBUILD_TYPE)) is not found in KBUILD_BLD_TYPES(=$(KBUILD_BLD_TYPES))!) endif ifdef KBUILD_PROFILE_SELF $(evalcall def_profile_self, end of header.kmk) _KBUILD_TS_HEADER_END := $(_KBUILD_TS_PREV) endif # end-of-file-content __header_kmk__ := 1 endif # !__header_kmk__ kbuild-2695/kBuild/envwin.cmd0000644000000000000000000006270612247157307014661 0ustar rootroot@echo off REM $Id: envwin.cmd 2413 2010-09-11 17:43:04Z bird $ REM REM @file REM Environment setup script. REM REM REM Copyright (c) 2005-2010 knut st. osmundsen REM REM This file is part of kBuild. REM REM kBuild is free software; you can redistribute it and/or modify REM it under the terms of the GNU General Public License as published by REM the Free Software Foundation; either version 2 of the License, or REM (at your option) any later version. REM REM kBuild is distributed in the hope that it will be useful, REM but WITHOUT ANY WARRANTY; without even the implied warranty of REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the REM GNU General Public License for more details. REM REM You should have received a copy of the GNU General Public License REM along with kBuild; if not, write to the Free Software REM Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA REM REM REM Globals REM set _KBUILD_CURDIR=%CD% for /f "tokens=*" %%d in ('cd') do set _KBUILD_CURDIR=%%d set _KBUILD_PATH=%KBUILD_PATH% set _KBUILD_BIN_PATH=%KBUILD_BIN_PATH% set _KBUILD_TYPE=%KBUILD_TYPE% set _KBUILD_TARGET=%KBUILD_TARGET% set _KBUILD_TARGET_ARCH=%KBUILD_TARGET_ARCH% set _KBUILD_TARGET_CPU=%KBUILD_TARGET_CPU% set _KBUILD_HOST=%KBUILD_HOST% set _KBUILD_HOST_ARCH=%KBUILD_HOST_ARCH% set _KBUILD_HOST_CPU=%KBUILD_HOST_CPU% set _KBUILD_OVERRIDE_TYPE=0 set _KBUILD_OVERRIDE_TARGET=0 set _KBUILD_OVERRIDE_TARGET_ARCH=0 REM REM Parse the arguments. REM REM Note: The 0 argument must be safed as it is also shifted. REM set _KBUILD_SELF=%0 set _KBUILD_OPT_FULL=0 set _KBUILD_OPT_LEGACY=0 set _KBUILD_OPT_VAR= set _KBUILD_OPT_VALUE_ONLY=0 set _KBUILD_SHOW_VAR_PREFIX= set _KBUILD_OPT_DBG=1 set _KBUILD_OPT_OVERRIDE_ALL=0 :argument_loop if ".%1" == ".-h" goto do_help if ".%1" == "./h" goto do_help if ".%1" == "./H" goto do_help if ".%1" == ".-h" goto do_help if ".%1" == ".-help" goto do_help if ".%1" == ".--help" goto do_help if ".%1" == ".--win" goto want_win if ".%1" == ".-win" goto want_win if ".%1" == ".--win32" goto want_win32_bit if ".%1" == ".-win32" goto want_win32_bit if ".%1" == ".-win64" goto want_win64_bit if ".%1" == ".--win64" goto want_win64_bit if ".%1" == ".--nt" goto want_nt if ".%1" == ".-nt" goto want_nt if ".%1" == ".--nt32" goto want_nt32_bit if ".%1" == ".-nt32" goto want_nt32_bit if ".%1" == ".--nt64" goto want_nt64_bit if ".%1" == ".-nt64" goto want_nt64_bit if ".%1" == ".--release" goto want_release if ".%1" == ".--profile" goto want_profile if ".%1" == ".--debug" goto want_debug if ".%1" == ".--full" goto opt_full if ".%1" == ".--normal" goto opt_normal if ".%1" == ".--legacy" goto opt_legacy if ".%1" == ".--no-legacy" goto opt_no_legacy if ".%1" == ".--debug-script" goto opt_debug_script if ".%1" == ".--no-debug-script" goto opt_no_debug_script if ".%1" == ".--var" goto opt_var if ".%1" == ".--value-only" goto opt_value_only if ".%1" == ".--name-and-value" goto opt_name_and_value if ".%1" == ".--set" goto opt_set if ".%1" == ".--no-set" goto opt_no_set goto done_arguments :want_win shift set _KBUILD_TARGET=win set _KBUILD_OVERRIDE_TARGET=1 goto argument_loop :want_win32_bit shift set _KBUILD_TARGET=win set _KBUILD_TARGET_ARCH=x86 set _KBUILD_OVERRIDE_TARGET=1 set _KBUILD_OVERRIDE_TARGET_ARCH=1 goto argument_loop :want_win64_bit shift set _KBUILD_TARGET=win set _KBUILD_TARGET_ARCH=amd64 set _KBUILD_OVERRIDE_TARGET=1 set _KBUILD_OVERRIDE_TARGET_ARCH=1 goto argument_loop :want_nt shift set _KBUILD_TARGET=nt set _KBUILD_OVERRIDE_TARGET=1 goto argument_loop :want_nt32_bit shift set _KBUILD_TARGET=nt set _KBUILD_TARGET_ARCH=x86 set _KBUILD_OVERRIDE_TARGET=1 set _KBUILD_OVERRIDE_TARGET_ARCH=1 goto argument_loop :want_nt64_bit shift set _KBUILD_TARGET=nt set _KBUILD_TARGET_ARCH=amd64 set _KBUILD_OVERRIDE_TARGET=1 set _KBUILD_OVERRIDE_TARGET_ARCH=1 goto argument_loop :want_release shift set _KBUILD_TYPE=release set _KBUILD_OVERRIDE_TYPE=1 goto argument_loop :want_profile shift set _KBUILD_TYPE=profile set _KBUILD_OVERRIDE_TYPE=1 goto argument_loop :want_debug shift set _KBUILD_TYPE=debug set _KBUILD_OVERRIDE_TYPE=1 goto argument_loop :opt_full shift set _KBUILD_OPT_FULL=1 goto argument_loop :opt_normal shift set _KBUILD_OPT_FULL=0 goto argument_loop :opt_legacy shift set _KBUILD_OPT_LEGACY=1 goto argument_loop :opt_no_legacy shift set _KBUILD_OPT_LEGACY=0 goto argument_loop :opt_debug_script shift set _KBUILD_OPT_DBG=1 goto argument_loop :opt_no_debug_script shift set _KBUILD_OPT_DBG=0 goto argument_loop :opt_var shift if ".%1" == "." echo syntax error: --var is missing it's variable name. if ".%1" == "." goto failure set _KBUILD_OPT_VAR=%_KBUILD_OPT_VAR% %1 shift goto argument_loop :opt_value_only shift set _KBUILD_OPT_VALUE_ONLY=1 goto argument_loop :opt_name_and_value shift set _KBUILD_OPT_VALUE_ONLY=0 goto argument_loop :opt_set shift set _KBUILD_SHOW_VAR_PREFIX=SET %_KBUILD_NON_EXISTING_VAR% goto argument_loop :opt_no_set shift set _KBUILD_SHOW_VAR_PREFIX= goto argument_loop REM # REM # Syntax REM # :do_help echo kBuild environment setup script for Windows NT. echo Syntax: envwin.cmd [options] [command to be executed] echo or: envwin.cmd [options] --var varname echo . echo Options: echo --win echo Force windows target and host platform. echo --win32 echo Force x86 32-bit windows target platform. echo --win64 echo Force AMD64 64-bit windows target platform. echo --nt echo Force NT target and host platform. echo --nt32 echo Force x86 32-bit NT target platform. echo --nt64 echo Force AMD64 64-bit NT target platform. echo --debug, --release, --profile echo Alternative way of specifying KBUILD_TYPE. echo --full, --normal echo Controls the variable set. Default: --normal echo --legacy, --no-legacy echo Include legacy variables in result. Default: --legacy echo --value-only, --name-and-value echo Controls what the result of a --var query. Default: --name-and-value echo --set, --no-set echo Whether to prefix the variable output with 'SET' or not. echo Default: --no-set goto end :done_arguments REM REM Convert legacy variable names. REM if ".%_KBUILD_OPT_OVERRIDE_ALL%" == ".1" goto legacy_convertion_done set _KBUILD_VARS=KBUILD_HOST (%_KBUILD_HOST%) and BUILD_PLATFORM (%BUILD_PLATFORM%) if not ".%BUILD_PLATFORM%" == "." if not ".%_KBUILD_HOST%" == "." if ".%_KBUILD_HOST%" == ".%BUILD_PLATFORM%" goto legacy_mismatch if not ".%BUILD_PLATFORM%" == "." set _KBUILD_HOST=%BUILD_PLATFORM% set _KBUILD_VARS=KBUILD_HOST_ARCH (%_KBUILD_HOST_ARCH%) and BUILD_PLATFORM_ARCH (%BUILD_PLATFORM_ARCH%) if not ".%BUILD_PLATFORM_ARCH%" == "." if not ".%_KBUILD_HOST_ARCH%" == "." if ".%_KBUILD_HOST_ARCH%" == ".%BUILD_PLATFORM_ARCH%" goto legacy_mismatch if not ".%BUILD_PLATFORM_ARCH%" == "." set _KBUILD_HOST_ARCH=%BUILD_PLATFORM_ARCH% set _KBUILD_VARS=KBUILD_HOST_CPU (%_KBUILD_HOST_CPU%) and BUILD_PLATFORM_CPU (%BUILD_PLATFORM_CPU%) if not ".%BUILD_PLATFORM_CPU%" == "." if not ".%_KBUILD_HOST_CPU%" == "." if ".%_KBUILD_HOST_CPU%" == ".%BUILD_PLATFORM_CPU%" goto legacy_mismatch if not ".%BUILD_PLATFORM_CPU%" == "." set _KBUILD_HOST_CPU=%BUILD_PLATFORM_CPU% if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_target set _KBUILD_VARS=KBUILD_TARGET (%_KBUILD_TARGET%) and BUILD_TARGET (%BUILD_TARGET%) if not ".%BUILD_TARGET%" == "." if not ".%_KBUILD_TARGET%" == "." if ".%_KBUILD_TARGET%" == ".%BUILD_TARGET%" goto legacy_mismatch if not ".%BUILD_TARGET%" == "." set _KBUILD_TARGET=%BUILD_TARGET% :legacy_skip_target if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_target_arch set _KBUILD_VARS=KBUILD_TARGET_ARCH (%_KBUILD_TARGET_ARCH%) and BUILD_TARGET_ARCH (%BUILD_TARGET_ARCH%) if not ".%BUILD_TARGET_ARCH%" == "." if not ".%_KBUILD_TARGET_ARCH%" == "." if ".%_KBUILD_TARGET_ARCH%" == ".%BUILD_TARGET_ARCH%" goto legacy_mismatch if not ".%BUILD_TARGET_ARCH%" == "." set _KBUILD_TARGET_ARCH=%BUILD_TARGET_ARCH% :legacy_skip_target_arch if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_target_cpu set _KBUILD_VARS=KBUILD_TARGET_CPU (%_KBUILD_TARGET_CPU%) and BUILD_TARGET_CPU (%BUILD_TARGET_CPU%) if not ".%BUILD_TARGET_CPU%" == "." if not ".%_KBUILD_TARGET_CPU%" == "." if ".%_KBUILD_TARGET_CPU%" == ".%BUILD_TARGET_CPU%" goto legacy_mismatch if not ".%BUILD_TARGET_CPU%" == "." set _KBUILD_TARGET_CPU=%BUILD_TARGET_CPU% :legacy_skip_target_cpu if ".%_KBUILD_OVERRIDE_TARGET%" == ".1" goto legacy_skip_type set _KBUILD_VARS=KBUILD_TYPE (%_KBUILD_TYPE%) and BUILD_TYPE (%BUILD_TYPE%) if not ".%BUILD_TYPE%" == "." if not ".%_KBUILD_TYPE%" == "." if ".%_KBUILD_TYPE%" == ".%BUILD_TYPE%" goto legacy_mismatch if not ".%BUILD_TYPE%" == "." set _KBUILD_TYPE=%BUILD_TYPE% :legacy_skip_type set _KBUILD_VARS=KBUILD_PATH (%_KBUILD_PATH%) and PATH_KBUILD (%PATH_KBUILD%) if not ".%PATH_KBUILD%" == "." if not ".%_KBUILD_PATH%" == "." if ".%_KBUILD_PATH%" == ".%PATH_KBUILD%" goto legacy_mismatch if not ".%PATH_KBUILD%" == "." set _KBUILD_PATH=%PATH_KBUILD% goto legacy_convertion_done :legacy_mismatch echo error: %_KBUILD_VARS% disagree. goto failed :legacy_convertion_done REM REM Check for illegal target/platforms. REM :target_and_platform if "%_KBUILD_TARGET" == "win32" goto illegal_target if "%_KBUILD_TARGET" == "win64" goto illegal_target if "%_KBUILD_HOST" == "win32" goto illegal_host if "%_KBUILD_HOST" == "win64" goto illegal_host goto target_and_platform_ok :illegal_target echo error: KBUILD_TARGET=%KBUILD_TARGET% is no longer valid. echo Only 'win' and 'nt' are permitted for targeting microsoft windows. goto failed :illegal_host echo error: KBUILD_HOST=%KBUILD_HOST is no longer valid. echo Only 'win' and 'nt' are permitted for building on microsoft windows. goto failed :target_and_platform_ok REM REM Find kBuild. REM REM We'll try determin the location of this script first and use that REM as a starting point for guessing the kBuild directory. REM REM Check if set via KBUILD_PATH. if not ".%_KBUILD_PATH%" == "." if exist %_KBUILD_PATH%\footer.kmk goto found_kbuild REM Determin a correct self - by %0 if exist "%_KBUILD_SELF%" goto found_self set _KBUILD_SELF=%_KBUILD_SELF%.cmd if exist "%_KBUILD_SELF%" goto found_self REM Determin a correct self - by the PATH REM This is very verbose because nested for loops didn't work out. for /f "tokens=1 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=2 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=3 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=4 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=5 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=6 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=7 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=8 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=9 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=10 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=11 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=12 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=13 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=14 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=15 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=16 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=17 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=18 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=19 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self for /f "tokens=20 delims=;" %%d in ("%PATH%") do set _KBUILD_SELF=%%d\envwin.cmd if exist "%_KBUILD_SELF%" goto found_self goto try_by_pwd :found_self cd "%_KBUILD_SELF%\.." for /f "tokens=*" %%d in ('cd') do set _KBUILD_PATH=%%d cd "%_KBUILD_CURDIR%" if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild REM Try relative to the current directory. :try_by_pwd if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild set _KBUILD_PATH=%_KBUILD_CURDIR% if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild set _KBUILD_PATH=%_KBUILD_CURDIR%\kBuild if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild set _KBUILD_PATH=%_KBUILD_CURDIR%\..\kBuild if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild set _KBUILD_PATH=%_KBUILD_CURDIR%\..\..\kBuild if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild set _KBUILD_PATH=%_KBUILD_CURDIR%\..\..\..\kBuild if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild set _KBUILD_PATH=%_KBUILD_CURDIR%\..\..\..\..\kBuild if exist "%_KBUILD_PATH%\footer.kmk" goto found_kbuild echo kBuild: Can't find the kBuild directory! set CURDIR= goto failed :found_kbuild cd "%_KBUILD_PATH%" for /f "tokens=*" %%d in ('cd') do set _KBUILD_PATH=%%d cd "%_KBUILD_CURDIR%" if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_PATH=%_KBUILD_PATH% REM REM Type - release is the default. REM if not ".%_KBUILD_TYPE%" == "." goto have_type set _KBUILD_TYPE=release :have_type if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_TYPE=%_KBUILD_TYPE% REM REM Host platform - windows REM if not ".%_KBUILD_HOST%" == "." goto have_host set _KBUILD_HOST=win if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_HOST=%_KBUILD_HOST% :have_host if not ".%_KBUILD_HOST_ARCH%" == "." goto have_host_arch REM try guess from _KBUILD_HOST_CPU if ".%KBUILD_HOST_CPU%" == ".i386" set _KBUILD_HOST_ARCH=x86 if ".%KBUILD_HOST_CPU%" == ".i486" set _KBUILD_HOST_ARCH=x86 if ".%KBUILD_HOST_CPU%" == ".i586" set _KBUILD_HOST_ARCH=x86 if ".%KBUILD_HOST_CPU%" == ".i686" set _KBUILD_HOST_ARCH=x86 if ".%KBUILD_HOST_CPU%" == ".i786" set _KBUILD_HOST_ARCH=x86 if ".%KBUILD_HOST_CPU%" == ".i886" set _KBUILD_HOST_ARCH=x86 if ".%KBUILD_HOST_CPU%" == ".i986" set _KBUILD_HOST_ARCH=x86 if ".%KBUILD_HOST_CPU%" == ".k8" set _KBUILD_HOST_ARCH=amd64 if ".%KBUILD_HOST_CPU%" == ".k9" set _KBUILD_HOST_ARCH=amd64 if ".%KBUILD_HOST_CPU%" == ".k10" set _KBUILD_HOST_ARCH=amd64 if not ".%_KBUILD_HOST_ARCH%" == "." goto have_host_arch REM try guess from PROCESSOR_ARCHITEW6432 and PROCESSOR_ARCHITECTURE set _KBUILD_TMP=%PROCESSOR_ARCHITECTURE% if not ".%PROCESSOR_ARCHITEW6432%" == "." set _KBUILD_TMP=%PROCESSOR_ARCHITEW6432% if "%_KBUILD_TMP%" == "x86" set _KBUILD_HOST_ARCH=x86 if "%_KBUILD_TMP%" == "X86" set _KBUILD_HOST_ARCH=x86 if "%_KBUILD_TMP%" == "amd64" set _KBUILD_HOST_ARCH=amd64 if "%_KBUILD_TMP%" == "Amd64" set _KBUILD_HOST_ARCH=amd64 if "%_KBUILD_TMP%" == "AMD64" set _KBUILD_HOST_ARCH=amd64 if "%_KBUILD_TMP%" == "x64" set _KBUILD_HOST_ARCH=amd64 if "%_KBUILD_TMP%" == "X64" set _KBUILD_HOST_ARCH=amd64 if not ".%_KBUILD_HOST_ARCH%" == "." goto have_host_arch echo error: Cannot figure KBUILD_HOST_ARCH! goto failed :have_host_arch if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_HOST_ARCH=%_KBUILD_HOST_ARCH% if not ".%_KBUILD_HOST_CPU%" == "." goto have_host_cpu set _KBUILD_HOST_CPU=blend :have_host_cpu if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_HOST_CPU=%_KBUILD_HOST_CPU% REM REM The target platform. REM Defaults to the host when not specified. REM if not ".%_KBUILD_TARGET%" == "." goto have_target set _KBUILD_TARGET=%_KBUILD_HOST% :have_target if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_TARGET=%_KBUILD_TARGET% if not ".%_KBUILD_TARGET_ARCH%" == "." goto have_target_arch set _KBUILD_TARGET_ARCH=%_KBUILD_HOST_ARCH% :have_target_arch if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH% if not ".%_KBUILD_TARGET_CPU%" == "." goto have_target_cpu if ".%_KBUILD_TARGET_ARCH%" == ".%_KBUILD_HOST_ARCH%" set _KBUILD_TARGET_CPU=%_KBUILD_HOST_CPU% if not ".%_KBUILD_TARGET_CPU%" == "." goto have_target_cpu set _KBUILD_TARGET_CPU=%_KBUILD_HOST_CPU% :have_target_cpu if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_TARGET_CPU=%_KBUILD_TARGET_CPU% REM REM Calc KBUILD_BIN_PATH and the new PATH value. REM if not ".%_KBUILD_BIN_PATH%" == "." goto have_kbuild_bin_path set _KBUILD_BIN_PATH=%_KBUILD_PATH%\bin\win.%_KBUILD_HOST_ARCH% :have_kbuild_bin_path if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_BIN_PATH=%_KBUILD_BIN_PATH% set _KBUILD_NEW_PATH=%_KBUILD_BIN_PATH%;%PATH% if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: _KBUILD_NEW_PATH=%_KBUILD_NEW_PATH% REM REM Sanity check. REM if not exist "%_KBUILD_BIN_PATH%" goto missing_bin_path if not exist "%_KBUILD_BIN_PATH%" goto done_chekcing_for_tools set _KBUILD_TMP=kmk kDepPre kDepIDB kmk_append kmk_ash kmk_cat kmk_cp kmk_echo kmk_install kmk_ln kmk_mkdir kmk_mv kmk_rm kmk_rmdir kmk_sed for %%i in ( %_KBUILD_TMP% ) do if not exist "%_KBUILD_BIN_PATH%\%%i.exe" echo warning: The %%i program doesn't exist for this platform. (%_KBUILD_BIN_PATH%\%%i.exe)" goto done_chekcing_for_tools :missing_bin_path echo warning: The bin directory for this platform doesn't exist. (%_KBUILD_BIN_PATH%) :done_chekcing_for_tools REM REM The environment is in place, now take the requested action. REM if ".%_KBUILD_OPT_VAR%" == "." goto exec_or_setup_env goto show_variable REM REM Show a set of variables. REM REM Note: 4nt doesn't grok the setlocal delayed expansion option. REM So, we'll have to identify which shell we're running. REM :show_variable for %%i in ( %_KBUILD_OPT_VAR% ) do if "%%i" == "all" goto show_all_variables if not ".%_4VER%" == "." goto 4nt setlocal ENABLEDELAYEDEXPANSION if errorlevel 1 goto no_delay_expansion for %%i in ( %_KBUILD_OPT_VAR% ) do ( set _KBUILD_VAR=%%i set _KBUILD_TMP= if "%%i" == "KBUILD_PATH" set _KBUILD_TMP=%_KBUILD_PATH% if "%%i" == "KBUILD_BIN_PATH" set _KBUILD_TMP=%_KBUILD_BIN_PATH% if "%%i" == "KBUILD_TYPE" set _KBUILD_TMP=%_KBUILD_TYPE% if "%%i" == "KBUILD_HOST" set _KBUILD_TMP=%_KBUILD_HOST% if "%%i" == "KBUILD_HOST_ARCH" set _KBUILD_TMP=%_KBUILD_HOST_ARCH% if "%%i" == "KBUILD_HOST_CPU" set _KBUILD_TMP=%_KBUILD_HOST_CPU% if "%%i" == "KBUILD_TARGET" set _KBUILD_TMP=%_KBUILD_TARGET% if "%%i" == "KBUILD_TARGET_ARCH" set _KBUILD_TMP=%_KBUILD_TARGET_ARCH% if "%%i" == "KBUILD_TARGET_CPU" set _KBUILD_TMP=%_KBUILD_TARGET_CPU% if ".!_KBUILD_TMP!" == "." goto varible_not_found if not ".%_KBUILD_OPT_VALUE_ONLY%" == ".1" echo %_KBUILD_SHOW_VAR_PREFIX%%%i=!_KBUILD_TMP! if ".%_KBUILD_OPT_VALUE_ONLY%" == ".1" echo !_KBUILD_TMP! ) endlocal goto end :no_delay_expansion echo error: Unable to enable delayed expansion in the shell. :4nt for %%i in ( %_KBUILD_OPT_VAR% ) do ( set _KBUILD_VAR=%%i set _KBUILD_TMP= if "%%i" == "KBUILD_PATH" set _KBUILD_TMP=%_KBUILD_PATH% if "%%i" == "KBUILD_BIN_PATH" set _KBUILD_TMP=%_KBUILD_BIN_PATH% if "%%i" == "KBUILD_TYPE" set _KBUILD_TMP=%_KBUILD_TYPE% if "%%i" == "KBUILD_HOST" set _KBUILD_TMP=%_KBUILD_HOST% if "%%i" == "KBUILD_HOST_ARCH" set _KBUILD_TMP=%_KBUILD_HOST_ARCH% if "%%i" == "KBUILD_HOST_CPU" set _KBUILD_TMP=%_KBUILD_HOST_CPU% if "%%i" == "KBUILD_TARGET" set _KBUILD_TMP=%_KBUILD_TARGET% if "%%i" == "KBUILD_TARGET_ARCH" set _KBUILD_TMP=%_KBUILD_TARGET_ARCH% if "%%i" == "KBUILD_TARGET_CPU" set _KBUILD_TMP=%_KBUILD_TARGET_CPU% if ".%_KBUILD_TMP%" == "." goto varible_not_found if not ".%_KBUILD_OPT_VALUE_ONLY%" == ".1" echo %_KBUILD_SHOW_VAR_PREFIX%%i=%_KBUILD_TMP% if ".%_KBUILD_OPT_VALUE_ONLY%" == ".1" echo %_KBUILD_TMP% ) goto end :varible_not_found echo error: Unknown variable %_KBUILD_VAR% specified in --var request. goto failed :show_all_variables echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_PATH=%_KBUILD_PATH% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_BIN_PATH=%_KBUILD_BIN_PATH% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TYPE=%_KBUILD_TYPE% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_HOST=%_KBUILD_HOST% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_HOST_ARCH=%_KBUILD_HOST_ARCH% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_HOST_CPU=%_KBUILD_HOST_CPU% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TARGET=%_KBUILD_TARGET% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH% echo %_KBUILD_SHOW_VAR_PREFIX%KBUILD_TARGET_CPU=%_KBUILD_TARGET_CPU% goto end REM REM Setup environment for the current shell or execute a command. REM REM Note: We use setlocal if we're going to execute a command as we REM don't want the environment of the invoking shell to be changed. REM :exec_or_setup_env if not ".%1" == "." setlocal REM The PATH is always set. set PATH=%_KBUILD_NEW_PATH% REM Clear up anything that should be overridden. if not "%_KBUILD_OPT_OVERRIDE_ALL%" == "1" goto skip_override_all set KBUILD_TYPE= set KBUILD_HOST= set KBUILD_HOST_ARCH= set KBUILD_HOST_CPU= set KBUILD_TARGET= set KBUILD_TARGET_ARCH= set KBUILD_TARGET_CPU= set KBUILD_PATH= set KBUILD_BIN_PATH= if not "%_KBUILD_OPT_LEGACY%" == "1" goto skip_override_all set BUILD_TYPE= set BUILD_PLATFORM= set BUILD_PLATFORM_ARCH= set BUILD_PLATFORM_CPU= set BUILD_TARGET= set BUILD_TARGET_ARCH= set BUILD_TARGET_CPU= set PATH_KBUILD= set PATH_KBUILD_BIN= :skip_override_all REM Specific overrides, these implicitly deletes the legacy variable. if "%_KBUILD_OVERRIDE_TARGET%" == "1" set KBUILD_TARGET=%_KBUILD_TARGET% if "%_KBUILD_OVERRIDE_TARGET%" == "1" set BUILD_TARGET= if "%_KBUILD_OVERRIDE_TARGET_ARCH%" == "1" set KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH% if "%_KBUILD_OVERRIDE_TARGET_ARCH%" == "1" set BUILD_TARGET_ARCH= if "%_KBUILD_OVERRIDE_TYPE%" == "1" set KBUILD_TYPE=%_KBUILD_TYPE% if "%_KBUILD_OVERRIDE_TYPE%" == "1" set BUILD_TYPE= if not "%_KBUILD_OPT_FULL%" == "1" goto env_setup_done set KBUILD_PATH=%_KBUILD_PATH% set KBUILD_BIN_PATH=%_KBUILD_BIN_PATH% set KBUILD_TYPE=%_KBUILD_TYPE% set KBUILD_HOST=%_KBUILD_HOST% set KBUILD_HOST_ARCH=%_KBUILD_HOST_ARCH% set KBUILD_HOST_CPU=%_KBUILD_HOST_CPU% set KBUILD_TARGET=%_KBUILD_TARGET% set KBUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH% set KBUILD_TARGET_CPU=%_KBUILD_TARGET_CPU% if not "%_KBUILD_OPT_LEGACY%" == "1" goto env_setup_done set PATH_KBUILD=%_KBUILD_PATH% set PATH_KBUILD_BIN=%_KBUILD_BIN_PATH% set BUILD_TYPE=%_KBUILD_TYPE% set BUILD_PLATFORM=%_KBUILD_HOST% set BUILD_PLATFORM_ARCH=%_KBUILD_HOST_ARCH% set BUILD_PLATFORM_CPU=%_KBUILD_HOST_CPU% set BUILD_TARGET=%_KBUILD_TARGET% set BUILD_TARGET_ARCH=%_KBUILD_TARGET_ARCH% set BUILD_TARGET_CPU=%_KBUILD_TARGET_CPU% :env_setup_done if ".%1" == "." goto end REM Execute the specified command if ".%_KBUILD_OPT_DBG%" == ".1" echo dbg: Executing: %1 %2 %3 %4 %5 %6 %7 %8 %9 set _KBUILD_CLEAN_GOTO=exec_command & goto cleanup :exec_command SET _KBUILD_CLEAN_GOTO= %1 %2 %3 %4 %5 %6 %7 %8 %9 endlocal goto end_no_exit REM REM All exit paths leads to 'end' or 'failed' depending on REM which exit code is desire. This is required as we're manually REM performing environment cleanup (setlocal/endlocal is crap). REM :cleanup set _KBUILD_CURDIR= set _KBUILD_PATH= set _KBUILD_BIN_PATH= set _KBUILD_NEW_PATH= set _KBUILD_TYPE= set _KBUILD_TARGET= set _KBUILD_TARGET_ARCH= set _KBUILD_TARGET_CPU= set _KBUILD_HOST= set _KBUILD_HOST_ARCH= set _KBUILD_HOST_CPU= set _KBUILD_OPT_OVERRIDE_ALL= set _KBUILD_OVERRIDE_TYPE= set _KBUILD_OVERRIDE_TARGET= set _KBUILD_OVERRIDE_TARGET_ARCH= set _KBUILD_SELF= set _KBUILD_OPT_FULL= set _KBUILD_OPT_LEGACY= set _KBUILD_OPT_VAR= set _KBUILD_OPT_VALUE_ONLY= set _KBUILD_SHOW_VAR_PREFIX= set _KBUILD_OPT_DBG= set _KBUILD_OPT_OVERRIDE_ALL= set _KBUILD_TMP= set _KBUILD_VAR= set _KBUILD_VARS= goto %_KBUILD_CLEAN_GOTO% :failed set _KBUILD_CLEAN_GOTO=failed_done & goto cleanup :failed_done set _KBUILD_CLEAN_GOTO= exit /b 1 :end set _KBUILD_CLEAN_GOTO=end_done & goto cleanup :end_done set _KBUILD_CLEAN_GOTO= exit /b 0 :end_no_exit kbuild-2695/kBuild/units/0000755000000000000000000000000012247157310014007 5ustar rootrootkbuild-2695/kBuild/units/qt-Q_OBJECT.sed0000644000000000000000000000222112247157310016351 0ustar rootroot# $Id: qt-Q_OBJECT.sed 2413 2010-09-11 17:43:04Z bird $ ## @file # Qt unit - sed script for checking for Q_OBJECT in a file. # # This is not very sophisticated, but it helps avoid generating # files we don't need. It outputs '1' when Q_OBJECT is found # and then quits, allowing us to do $(if $(shell ...),moc_...). # is # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # /Q_OBJECT/!b skip s/^.*$/1/ q 0 :skip d kbuild-2695/kBuild/units/yacc.kmk0000644000000000000000000001361112247157310015434 0ustar rootroot# $Id: yacc.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # yacc/bison unit. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef UNIT_yacc $(error kBuild: The yacc unit was included twice!) endif UNIT_yacc = yacc # Add our target properties. PROPS_TOOLS += YACCTOOL PROPS_SINGLE += YACCTOOL PROPS_ACCUMULATE_R += YACCFLAGS # Add ourselves to the default source handlers. KBUILD_SRC_HANDLERS += \ .y:def_src_handler_yacc_y \ .ypp:def_src_handler_yacc_ypp \ .y++:def_src_handler_yacc_ypp ## wrapper the compile command dependency check. ifndef NO_COMPILE_CMDS_DEPS _DEP_YACC_CMDS = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_YACC_CMDS_PREV_),$$(commands $(out)),FORCE) else _DEP_YACC_CMDS = endif ## # Generates the rules for running flex on a specific source file. # # @param $(obj) The object file. # @param lots more define def_yacc_rule $(out) + $(output_extra) +| $(output_maybe) : \ $(deps) \ $(value _DEP_YACC_CMDS) \ | \ $(orderdeps) %$$(call MSG_COMPILE,$(target),$(source),$$@,$(type)) $$(QUIET)$$(RM) -f -- $(dep) $(out) $(output_extra) $(output_maybe) $(cmds) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_YACC_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif # update globals and target properties. _OUT_FILES += $(out) $(output_extra) $(output_maybe) $(target)_GEN_SOURCES_ += $(out) $(target)_INTERMEDIATES += $(intermediates) endef # def_yacc_rule ## # Handler for .y files listed in the SOURCES properties. # # .y files are transformed into .c (and maybe .h) files that then gets # compiled by the C compiler. # # @param target The target file. # @param source The source file. # @param lots more # @returns quite a bit. # define def_src_handler_yacc_y # Figure out all the props. local type := YACC local tmp := $(kb-src-tool tool) ifeq ($(tool),) $(error kBuild: $(target) / $(sources) does not a (yacc) tool defined!) endif ifndef TOOL_$(tool)_YACC_CMDS $(error kBuild: TOOL_$(tool)_YACC_CMDS isn't defined! target=$(target) source=$(source) ) endif local out := $(kb-obj-base outbase).c local tmp := $(kb-src-prop YACCFLAGS,flags,left-to-right,) local tmp := $(kb-src-prop DEPS,deps,left-to-right,$(defpath)) local tmp := $(kb-src-prop ORDERDEPS,orderdeps,left-to-right,$(defpath)) local dirdep := $(call DIRDEP,$(dir $(out))) # Adjust paths if we got a default path. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) endif # dependency file. local dep := $(out)$(SUFF_DEP) ifndef NO_COMPILE_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) $(eval includedep $(dep)) endif # Call the tool. local cmds := $(TOOL_$(tool)_YACC_CMDS) local output_extra := $(TOOL_$(tool)_YACC_OUTPUT) local output_maybe := $(TOOL_$(tool)_YACC_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_YACC_DEPEND) $(source) local orderdeps += $(TOOL_$(tool)_YACC_DEPORD) $(dirdep) # Whether it generates a header file depends on flags. local intermediates := $(filter %.h %.hpp %.h++ %.H,$(output_extra)) # Generate the rule. $(eval $(def_yacc_rule)) endef # def_src_handler_yacc_y ## # Handler for .ypp/.y++ files listed in the SOURCES properties. # # .ypp/++ files are transformed into .cpp/++ (and maybe .hpp/++) files that then gets # compiled by the C++ compiler. # # @param target The target file. # @param source The source file. # @param lots more # @returns quite a bit. # define def_src_handler_yacc_ypp # Figure out all the props. local type := YACC local tmp := $(kb-src-tool tool) ifeq ($(tool),) $(error kBuild: $(target) / $(sources) does not a (yacc) tool defined!) endif ifndef TOOL_$(tool)_YACC_CMDS $(error kBuild: TOOL_$(tool)_YACC_CMDS isn't defined! target=$(target) source=$(source) ) endif local out := $(kb-obj-base outbase).c$(substr $(suffix $(source),3)) local tmp := $(kb-src-prop YACCFLAGS,flags,left-to-right,) local tmp := $(kb-src-prop DEPS,deps,left-to-right,$(defpath)) local tmp := $(kb-src-prop ORDERDEPS,orderdeps,left-to-right,$(defpath)) local dirdep := $(call DIRDEP,$(dir $(out))) # Adjust paths if we got a default path. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) endif # dependency file. local dep := $(out)$(SUFF_DEP) ifndef NO_COMPILE_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) $(eval includedep $(dep)) endif # Call the tool. local cmds := $(TOOL_$(tool)_YACC_CMDS) local output_extra := $(TOOL_$(tool)_YACC_OUTPUT) local output_maybe := $(TOOL_$(tool)_YACC_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_YACC_DEPEND) $(source) local orderdeps += $(TOOL_$(tool)_YACC_DEPORD) $(dirdep) # Whether it generates a header file depends on flags. local intermediates := $(filter %.h %.hpp %.h++ %.H,$(output_extra)) # Generate the rule. $(eval $(def_yacc_rule)) endef # def_src_handler_yacc_ypp kbuild-2695/kBuild/units/lex.kmk0000644000000000000000000001040612247157310015304 0ustar rootroot# $Id: lex.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # lex unit. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef UNIT_lex $(error kBuild: The lex unit was included twice!) endif UNIT_lex = lex # Add our target properties. PROPS_TOOLS += LEXTOOL PROPS_SINGLE += LEXTOOL PROPS_ACCUMULATE_R += LEXFLAGS # Add ourselves to the default source handlers. KBUILD_SRC_HANDLERS += \ .l:def_src_handler_lex ## wrapper the compile command dependency check. ifndef NO_COMPILE_CMDS_DEPS _DEP_LEX_CMDS = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_LEX_CMDS_PREV_),$$(commands $(out)),FORCE) else _DEP_LEX_CMDS = endif ## # Generates the rules for running flex on a specific source file. # # @param $(obj) The object file. # @param lots more define def_lex_rule $(out) + $(output_extra) +| $(output_maybe) : \ $(deps) \ $(value _DEP_LEX_CMDS) \ | \ $(orderdeps) %$$(call MSG_COMPILE,$(target),$(source),$$@,$(type)) $$(QUIET)$$(RM) -f -- $(dep) $(out) $(output_extra) $(output_maybe) $(cmds) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_LEX_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif # update globals _OUT_FILES += $(out) $(output_extra) $(output_maybe) $(target)_GEN_SOURCES_ += $(out) $(target)_INTERMEDIATES += $(intermediates) endef # def_lex_rule ## # Handler for .l files listed in the SOURCES properties. # # .l files are transformed into .c files that then gets compiled by # the C compiler. # # @param target The target file. # @param source The source file. # @param lots more # @returns quite a bit. define def_src_handler_lex # Figure out all the props. local type := LEX local tmp := $(kb-src-tool tool) ifeq ($(tool),) $(error kBuild: $(target) / $(sources) does not a (lex) tool defined!) endif ifndef TOOL_$(tool)_LEX_CMDS $(error kBuild: TOOL_$(tool)_LEX_CMDS isn't defined! target=$(target) source=$(source) ) endif local out := $(kb-obj-base outbase).c local tmp := $(kb-src-prop LEXFLAGS,flags,left-to-right,) local tmp := $(kb-src-prop DEPS,deps,left-to-right,$(defpath)) local tmp := $(kb-src-prop ORDERDEPS,orderdeps,left-to-right,$(defpath)) ifdef TOOL_$(tool)_LEX_OUT_FILE # .c/.cpp output depends on flags. local out := $(strip $(TOOL_$(tool)_LEX_OUT_FILE)) ifeq ($(out),) local out := $(outbase).c endif endif local dirdep := $(call DIRDEP,$(dir $(out))) # Adjust paths if we got a default path. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) endif # dependency file. local dep := $(out)$(SUFF_DEP) ifndef NO_COMPILE_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) $(eval includedep $(dep)) endif # call the tool local cmds := $(TOOL_$(tool)_LEX_CMDS) local output_extra := $(TOOL_$(tool)_LEX_OUTPUT) local output_maybe := $(TOOL_$(tool)_LEX_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_LEX_DEPEND) $(source) local orderdeps += $(TOOL_$(tool)_LEX_DEPORD) $(dirdep) # Whether it generates a header file depends on the tool / flags. local intermediates := $(filter %.h %.hpp %.h++ %.H,$(output_extra)) # generate the rule. $(eval $(def_lex_rule)) endef # def_src_handler_lex kbuild-2695/kBuild/units/dtrace.kmk0000644000000000000000000001575312247157310015770 0ustar rootroot# $Id: dtrace.kmk 2571 2012-04-15 11:12:31Z bird $ ## @file # DTrace unit. # # # Copyright (c) 2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef UNIT_dtrace $(error kBuild: The lex unit was included twice!) endif UNIT_dtrace = dtrace # Add our target properties. PROPS_TOOLS += DTRACETOOL PROPS_SINGLE += DTRACETOOL PROPS_ACCUMULATE_R += DTRACE_HDR_FLAGS DTRACE_OBJ_FLAGS # Add ourselves to the default source handlers. KBUILD_SRC_HANDLERS += \ .d:def_src_handler_dtrace ## wrapper the compile command dependency check. ifndef NO_COMPILE_CMDS_DEPS _DEP_DTRACE_HDR_CMDS = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_DTRACE_HDR_CMDS_PREV_),$$(commands $(out)),FORCE) _DEP_DTRACE_OBJ_CMDS = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_DTRACE_OBJ_CMDS_PREV_),$$(commands $(out)),FORCE) else _DEP_DTRACE_HDR_CMDS = _DEP_DTRACE_OBJ_CMDS = endif ## # Generates the rule for creating a DTrace header from a D source file. # # @param out The output file. # @param cmds The dtrace command(s). # @param lots more # define def_dtrace_hdr_rule $(out): \ $(deps) \ $(value _DEP_DTRACE_HDR_CMDS) \ | \ $(orderdeps) %$$(call MSG_GENERATE,$(target),$$@,$(source)) $$(QUIET)$$(RM) -f -- $(dep) $(out) $(cmds) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_DTRACE_HDR_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif # update globals _OUT_FILES += $(out) $(target)_INTERMEDIATES += $(out) endef # def_dtrace_hdr_rule ## # Generates the rule for creating a DTrace object file from a D source file # and a bunch of object files. # # @param out The output file. # @param cmds The dtrace command(s). # @param lots more # define def_dtrace_obj_rule $(out): \ $(deps) \ $$$$(filter-out %-dtrace-object-format.o, $$$$($(target)_2_OBJS)) \ $(value _DEP_DTRACE_OBJ_CMDS) \ | \ $(orderdeps) %$$(call MSG_GENERATE,$(target),$$@,$(source) ++) $$(QUIET)$$(RM) -f -- $(dep) $(out) $(cmds) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_DTRACE_OBJ_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif # update globals _OUT_FILES += $(out) $(target)_2_OBJS <= $(out) endef # def_dtrace_hdr_rule ## # Handler for .d files listed in the SOURCES properties. # # .d files are transformed into .h that is used when compiling, thus needing # to be generated before anything is compiled, and into object files that needs # to go into the linking. Mac does not create object files. # # The step producing the object file requires all the object files with dtrace # probes in them as input/output as well, because it adjusts the dtrace symbols # from UNDEF to IGNORE. This is really ugly and cannot be expressed in make # syntax (prerequisite object files being modified). Fortunately, it works # fine because the object files won't be used by anyone else before the dtrace # object file exists. # # @param target The target file. # @param source The source file. # @param lots more # @returns quite a bit. define def_src_handler_dtrace local type := DTRACE local tmp := $(kb-src-tool tool) ifeq ($(tool),) $ (error kBuild: $(target) / $(sources) does not have a (DTRACE) tool defined!) endif local dtracedir := $($(target)_0_OUTDIR)/dtrace # # The header file first. # # Figure out all the props. ifndef TOOL_$(tool)_DTRACE_HDR_CMDS $(error kBuild: TOOL_$(tool)_DTRACE_HDR_CMDS isn't defined! target=$(target) source=$(source) ) endif ## @todo put the header in a subdir and add this to INCS? Do we have a early per-target hook for this?? local outbase := $(dtracedir)/dtrace/$(basename $(notdir $(source))) local out := $(outbase).h local tmp := $(kb-src-prop DTRACE_HDR_FLAGS,flags,left-to-right,) local tmp := $(kb-src-prop DEPS,deps,left-to-right,$(defpath)) local tmp := $(kb-src-prop ORDERDEPS,orderdeps,left-to-right,$(defpath)) local dirdep := $(call DIRDEP,$(dir $(out))) # Adjust paths if we got a default path. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) endif # dependency file. local dep := $(out)$(SUFF_DEP) ifndef NO_COMPILE_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) $(eval includedep $(dep)) endif # call the tool local cmds := $(TOOL_$(tool)_DTRACE_HDR_CMDS) local deps += $(TOOL_$(tool)_DTRACE_DEPEND) $(source) local orderdeps += $(TOOL_$(tool)_DTRACE_DEPORD) $(dirdep) # generate the rule. $(eval $(def_dtrace_hdr_rule)) # # Adjust the object files and generate one from the D source, if needed. # ifn1of ($(bld_trg), $(TOOL_$(tool)_DTRACE_OBJ_NOT_NEEDED)) # Figure out all the props. ifndef TOOL_$(tool)_DTRACE_OBJ_CMDS $(error kBuild: TOOL_$(tool)_DTRACE_OBJ_CMDS isn't defined! target=$(target) source=$(source) ) endif local outbase := $(dtracedir)/$(basename $(notdir $(source))) local out := $(outbase)-dtrace-object-format.o local tmp := $(kb-src-prop DTRACE_OBJ_FLAGS,flags,left-to-right,) local tmp := $(kb-src-prop DEPS,deps,left-to-right,$(defpath)) local tmp := $(kb-src-prop ORDERDEPS,orderdeps,left-to-right,$(defpath)) local dirdep := $(call DIRDEP,$(dir $(out))) # Adjust paths if we got a default path. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) endif # dependency file. local dep := $(out)$(SUFF_DEP) ifndef NO_COMPILE_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) $(eval includedep $(dep)) endif # call the tool local cmds := $(TOOL_$(tool)_DTRACE_OBJ_CMDS) local deps += $(TOOL_$(tool)_DTRACE_DEPEND) $(source) local orderdeps += $(TOOL_$(tool)_DTRACE_DEPORD) $(dirdep) # generate the rule. $(eval $(def_dtrace_obj_rule)) endif endef # def_src_handler_dtrace # # The pre-target hook. # define def_unit_dtrace_target_pre local dtracedir := $($(target)_0_OUTDIR)/dtrace $(eval $(target)_INCS += $(dtracedir)) endef #def_unit_dtrace_target_pre kbuild-2695/kBuild/units/qt3.kmk0000644000000000000000000010213712247157310015226 0ustar rootroot# $Id: qt3.kmk 2544 2011-09-13 19:00:25Z bird $ ## @file # Qt 3.3.x unit. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef UNIT_qt3 $(error kBuild: The qt3 unit was included twice!) endif UNIT_qt3 = qt3 ifndef UNIT_qt4 # Add our target properties (same as qt4). PROPS_SINGLE += QTTOOL MOCTOOL UICTOOL LRCTOOL QT_TRANSLATIONS_INST QT_TRANSLATIONS_TEMPLATE QT_PREFIX PROPS_ACCUMULATE_R += MOCDEFS MOCFLAGS UICFLAGS LRCFLAGS QT_TRANSLATIONS QT_MOCSRCS QT_MOCHDRS endif PROPS_SINGLE += PROPS_ACCUMULATE_R += QT_IMAGES # # The QT3 SDK. # # This is implemented here rather than in sdks/QT3.kmk to enforce the global USES. # It also makes things easier to develop, with fewer files I mean. # ## @todo the SDK might actually not be necessary as it turns out... For now it servers # a purpose if the host differs from the target, in theory at least. SDK_QT3 = Qt3 # SDK Specific Properties # PATH_SDK_QT3 - the general location of the Qt3 SDK stuff. # PATH_SDK_QT3_INC - the Qt3 include directory. # PATH_SDK_QT3_LIB - the Qt3 library directory for KBUILD_TARGET. # PATH_SDK_QT3_LIB.amd64 - the Qt3 library directory for AMD64. # PATH_SDK_QT3_LIB.x86 - the Qt3 library directory for X86. ifndef PATH_SDK_QT3 PATH_SDK_QT3 := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/qt/v3*))) ifeq ($(PATH_SDK_QT3),) # If target == host, try look for Qt in the various platform specific places. ifeq ($(KBUILD_TARGET),$(KBUILD_HOST)) ifeq ($(KBUILD_TARGET),darwin) # No idea here yet... else ifeq ($(KBUILD_TARGET),os2) # No idea here yet... Check QTDIR perhaps, but for now users have toset PATH_SDK_QT3. else ifeq ($(KBUILD_TARGET),win) # No idea here yet... Check QTDIR perhaps, but for now users have toset PATH_SDK_QT3. else # The Unices. Includes and esp. libs are tricky, so override the PATH_SDK_QT3_LIB* stuff if it doesn't work. # Try find the general location of the thing by looking for the qm2ts program, then try looking for # the moc program in likely and unlikely places save /usr[/local]/bin to avoid mistaking it with Qt4. PATH_SDK_QT3 := $(patsubst %/bin/qm2ts,%,$(firstword $(wildcard \ /usr/lib/qt-3.3/bin/qm2ts \ /usr/lib64/qt-3.3/bin/qm2ts \ /usr/qt/3/bin/qm2ts \ $(if $(QTDIR),$(QTDIR)/bin/qm2ts) \ /usr/bin/qm2ts \ /usr/local/bin/qm2ts \ /usr/share/qt3/bin/qm2ts \ ))) ifeq ($(PATH_SDK_QT3),) # Try with moc, but not in /usr/bin and /usr/local/bin. PATH_SDK_QT3 := $(patsubst %/bin/moc,%,$(firstword $(wildcard \ /usr/lib/qt-3.3/bin/moc \ /usr/lib64/qt-3.3/bin/moc \ /usr/qt/3/bin/moc \ /usr/share/qt3/bin/moc \ $(if $(QTDIR),$(QTDIR)/bin/moc) \ ))) endif ifneq ($(PATH_SDK_QT3),) # Found something! Export the variable for the benefit of recursive make instances. export PATH_SDK_QT3 # Determin the include directory. ifeq ($(PATH_SDK_QT3_INC),) PATH_SDK_QT3_INC := $(patsubst %/private/qfiledefs_p.h,%,$(firstword $(wildcard \ $(PATH_SDK_QT3)/include/private/qfiledefs_p.h \ $(PATH_SDK_QT3)/include/qt3/private/qfiledefs_p.h \ /usr/include/qt3/private/qfiledefs_p.h))) ifneq ($(PATH_SDK_QT3_INC),) export PATH_SDK_QT3_INC endif endif # Determin the most likely x86 and AMD64 lib directories (only used for making PATH_SDK_QT3_LIB). ifeq ($(PATH_SDK_QT3_LIB.x86),) PATH_SDK_QT3_LIB.x86 := $(patsubst %/libqt-mt$(SUFF_DLL),%,$(firstword $(wildcard \ $(PATH_SDK_QT3)/lib32/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib32/qt3/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib32/qt3-3/lib/libqt-mt$(SUFF_DLL) \ /usr/lib32/libqt-mt$(SUFF_DLL) \ /usr/lib32/qt3/libqt-mt$(SUFF_DLL) \ /usr/lib/i386-linux-gnu/libqt-mt$(SUFF_DLL) \ /usr/local/lib32/libqt-mt$(SUFF_DLL) \ /usr/local/lib32/qt3/libqt-mt$(SUFF_DLL) \ /usr/local/lib32/qt3-3/lib/libqt-mt$(SUFF_DLL) \ /usr/local/lib/i386-linux-gnu/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/qt3/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/i386-linux-gnu/libqt-mt$(SUFF_DLL) \ ))) ifneq ($(PATH_SDK_QT3_LIB.x86),) export PATH_SDK_QT3_LIB.x86 endif endif ifeq ($(PATH_SDK_QT3_LIB.amd64),) PATH_SDK_QT3_LIB.amd64 := $(patsubst %/libqt-mt$(SUFF_DLL),%,$(firstword $(wildcard \ $(PATH_SDK_QT3)/lib64/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib64/qt3/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib64/qt3-3/lib/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/amd64/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/64/libqt-mt$(SUFF_DLL) \ /usr/lib64/libqt-mt$(SUFF_DLL) \ /usr/lib64/qt3/libqt-mt$(SUFF_DLL) \ /usr/lib64/qt3-3/lib/libqt-mt$(SUFF_DLL) \ /usr/lib/amd64/libqt-mt$(SUFF_DLL) \ /usr/lib/64/libqt-mt$(SUFF_DLL) \ /usr/lib/x86_64-linux-gnu/libqt-mt$(SUFF_DLL) \ /usr/local/lib64/libqt-mt$(SUFF_DLL) \ /usr/local/lib64/qt3/libqt-mt$(SUFF_DLL) \ /usr/local/lib64/qt3-3/lib/libqt-mt$(SUFF_DLL) \ /usr/local/lib/amd64/libqt-mt$(SUFF_DLL) \ /usr/local/lib/64/libqt-mt$(SUFF_DLL) \ /usr/local/lib/x86_64-linux-gnu/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/qt3/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/x86_64-linux-gnu/libqt-mt$(SUFF_DLL) \ ))) ifneq ($(PATH_SDK_QT3_LIB.amd64),) export PATH_SDK_QT3_LIB.amd64 endif endif # Determin the KBUILD_TARGET lib directory. ifeq ($(PATH_SDK_QT3_LIB),) PATH_SDK_QT3_LIB := $(PATH_SDK_QT3_LIB.$(KBUILD_TARGET_ARCH)) ifeq ($(PATH_SDK_QT3_LIB),) PATH_SDK_QT3_LIB := $(patsubst %/libqt-mt$(SUFF_DLL),%,$(firstword $(wildcard \ $(PATH_SDK_QT3)/lib/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/qt3/libqt-mt$(SUFF_DLL) \ $(PATH_SDK_QT3)/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \ /usr/lib/libqt-mt$(SUFF_DLL) \ /usr/lib/qt3/libqt-mt$(SUFF_DLL) \ /usr/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \ /usr/local/lib/libqt-mt$(SUFF_DLL) \ /usr/local/lib/qt3/libqt-mt$(SUFF_DLL) \ /usr/local/lib/qt3-3/lib/libqt-mt$(SUFF_DLL) \ ))) ifneq ($(PATH_SDK_QT3_LIB),) export PATH_SDK_QT3_LIB endif endif endif endif endif # Unices endif # Found it? ifeq ($(PATH_SDK_QT3),) $(warning kBuild: Couldn't find the Qt3 headers and libaries...) PATH_SDK_QT3 := $(PATH_DEVTOOLS_TRG)/qt/not-found endif endif else # Resolve any fancy stuff once and for all. PATH_SDK_QT3 := $(PATH_SDK_QT3) endif # Libraries can be in either Frameworks or lib depending on how you # build it on the mac. The .dmg installs into Frameworks but builds into lib. PATH_SDK_QT3_LIB ?= $(PATH_SDK_QT3)/lib PATH_SDK_QT3_INC ?= $(PATH_SDK_QT3)/include # The bits that kBuild picks up. # (nothing here) # # The QT3 tool. # # This is implemented here rather than in tools/QT3.kmk to enforce the global USES. # It also makes things easier to develop, with fewer files I mean. # TOOL_QT3 = Qt3 # Tool Specific Properties (PATH_TOOL_QT3_BIN and TOOL_QT3_BIN_SUFF) # TOOL_QT3_BIN_SUFF - the '-qt3' bit found on debian. # PATH_TOOL_QT3_BIN - the directory containing moc, uic, lrelease, lupdate and qm2ts. ifndef PATH_TOOL_QT3_BIN PATH_TOOL_QT3_BIN := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/qt/v3*/bin))) ifeq ($(PATH_TOOL_QT3_BIN),) if1of ($(KBUILD_HOST), win os2) # Sorry, no joy here. Check QTDIR perhaps, but for now users have to set PATH_TOOL_QT3_BIN. else ifdef TOOL_QT3_BIN_SUFF TOOL_QT3_BIN_SUFF := $(TOOL_QT3_BIN_SUFF) endif PATH_TOOL_QT3_BIN := $(patsubst %/qm2ts$(TOOL_QT3_BIN_SUFF),%,$(firstword $(wildcard \ /usr/lib/qt-3.3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \ /usr/lib64/qt-3.3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \ /usr/qt/3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \ $(if $(QTDIR),$(QTDIR)/bin/qm2ts$(TOOL_QT3_BIN_SUFF)) \ /usr/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \ /usr/local/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \ /usr/share/qt3/bin/qm2ts$(TOOL_QT3_BIN_SUFF) \ ))) ifeq ($(PATH_TOOL_QT3_BIN),) # If we couldn't find the qt3 specific tool qm2ts, debian and other skip # this (thanks a bundle). Try with look for 'moc' with a '-qt3' extension, # then for just moc. In the latter case don't search /usr[/local]/bin to # void finding the qt4 tools and messing up. ifeq ($(TOOL_QT3_BIN_SUFF),) PATH_TOOL_QT3_BIN := $(patsubst %/moc-qt3,%,$(firstword $(wildcard \ /usr/bin/moc-qt3 \ /usr/local/bin/moc-qt3 \ /usr/lib/qt-3.3/bin/moc-qt3 \ /usr/lib64/qt-3.3/bin/moc-qt3 \ /usr/qt/3/bin/moc-qt3 \ /usr/share/qt3/bin/moc-qt3 \ $(if $(QTDIR),$(QTDIR)/bin/moc-qt3) \ ))) endif ifneq ($(PATH_TOOL_QT3_BIN),) export TOOL_QT3_BIN_SUFF := -qt3 else PATH_TOOL_QT3_BIN := $(patsubst %/moc$(TOOL_QT3_BIN_SUFF),%,$(firstword $(wildcard \ /usr/lib/qt-3.3/bin/moc$(TOOL_QT3_BIN_SUFF) \ /usr/lib64/qt-3.3/bin/moc$(TOOL_QT3_BIN_SUFF) \ /usr/qt/3/bin/moc$(TOOL_QT3_BIN_SUFF) \ /usr/share/qt3/bin/moc$(TOOL_QT3_BIN_SUFF) \ $(if $(QTDIR),$(QTDIR)/bin/moc$(TOOL_QT3_BIN_SUFF)) \ ))) endif endif ifneq ($(PATH_TOOL_QT3_BIN),) export PATH_TOOL_QT3_BIN endif endif endif # If not found, we'll enter the 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_QT3_BIN := $(PATH_TOOL_QT3_BIN) TOOL_QT3_BIN_SUFF := $(TOOL_QT3_BIN_SUFF) endif ifneq ($(PATH_TOOL_QT3_BIN),) ifeq ($(KBUILD_HOST),os2) TOOL_QT3_ENV_SETUP ?= $(REDIRECT) -E 'BEGINLIBPATH=$(PATH_TOOL_QT3_BIN);$(libpath BEGINLIBPATH)' -- endif TOOL_QT3_MOC ?= $(TOOL_QT3_ENV_SETUP) $(PATH_TOOL_QT3_BIN)/moc$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT3_UIC ?= $(TOOL_QT3_ENV_SETUP) $(PATH_TOOL_QT3_BIN)/uic$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT3_LRC ?= $(TOOL_QT3_ENV_SETUP) $(PATH_TOOL_QT3_BIN)/lrelease$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT3_LUPDATE ?= $(TOOL_QT3_ENV_SETUP) $(PATH_TOOL_QT3_BIN)/lupdate$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) else # Pathless, relies on the environment. TOOL_QT3_MOC ?= moc$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT3_UIC ?= uic$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT3_LRC ?= lrelease$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT3_LUPDATE ?= lupdate$(TOOL_QT3_BIN_SUFF)$(HOST_SUFF_EXE) endif # General Properties used by kBuild and/or units/qt.kmk TOOL_QT3_MOCFLAGS ?= TOOL_QT3_UICFLAGS ?= TOOL_QT3_LRCFLAGS ?= ## MOC a C++ source file. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT3_MOC_CPP_DEPEND = TOOL_QT3_MOC_CPP_DEPORD = TOOL_QT3_MOC_CPP_OUTPUT = TOOL_QT3_MOC_CPP_OUTPUT_MAYBE = define TOOL_QT3_MOC_CPP_CMDS $(QUIET)$(TOOL_QT3_MOC)\ $(flags)\ -o $(out)\ -i \ $(source) endef ## MOC a C++ header file. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT3_MOC_HPP_DEPEND = TOOL_QT3_MOC_HPP_DEPORD = TOOL_QT3_MOC_HPP_OUTPUT = TOOL_QT3_MOC_HPP_OUTPUT_MAYBE = define TOOL_QT3_MOC_HPP_CMDS $(QUIET)$(TOOL_QT3_MOC)\ $(flags)\ -o $(out)\ $(source) endef ## Compile a Qt user interface file (.ui). # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out.cpp) The C++ source file to be generated. # @param $(out.h) The C++ header file to be generated. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT3_UIC_UI_DEPEND = TOOL_QT3_UIC_UI_DEPORD = TOOL_QT3_UIC_UI_OUTPUT = TOOL_QT3_UIC_UI_OUTPUT_MAYBE = define TOOL_QT3_UIC_UI_CMDS $(QUIET)$(TOOL_QT3_UIC)\ $(flags)\ -o $(out.h)\ $(source) $(QUIET)$(TOOL_QT3_UIC)\ $(flags)\ -i $(out.h) \ -o $(out.cpp)\ $(source) endef ## Compile a Qt translation file (.ts). # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. # @param $(incs) Includes. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT3_LRC_TS_DEPEND = TOOL_QT3_LRC_TS_DEPORD = TOOL_QT3_LRC_TS_OUTPUT = TOOL_QT3_LRC_TS_OUTPUT_MAYBE = define TOOL_QT3_LRC_TS_CMDS $(QUIET)$(TOOL_QT3_LRC)\ $(flags)\ $(source)\ -qm $(out) endef # # # Back to the Qt3 unit. # # ## wrapper for the lrelease (LRC) command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT3_LRC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_LRC_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT3_LRC_CMDS_DEP = endif ## # def_unit_qt3_target_pre_handle_translation helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt3_target_pre_handle_translation_dx $(out) + $(more_output) +| $(maybe_output): \ $(deps) \ $(value _UNIT_QT3_LRC_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,lrelease,$(target),$(source),$$@) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_LRC_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_CLEAN += $(out) $(more_output) $(maybe_output) $(dep) $(target)-inst-nls_SOURCES += $(out) endef # def_unit_qt3_target_pre_handle_translation_dx ## # Handle a source file listed in QT_TRANSLATIONS. # # The files listed in QT_TRANSLATIONS are translation files (.ts) which needs # to be translated into .qm files that are loadble by Qt. # # @remarks Invoked via $(evalvalctx ). define def_unit_qt3_target_pre_handle_translation local type := LRC # fetch the properties. local tool := $(kb-src-tool dummy_var) local qtnlsdir := $($(target)_0_OUTDIR)/qtnls local outbase := $(qtnlsdir)/$(notdir $(basename $(source))) local out := $(outbase).qm local dep := $(out).dep local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_LRC_TS_CMDS $(error kBuild: qt lrelease tool not found: TOOL_$(tool)_LRC_TS_CMDS) endif local cmds := $(TOOL_$(tool)_LRC_TS_CMDS) local more_output := $(TOOL_$(tool)_LRC_TS_OUTPUT) local maybe_output := $(TOOL_$(tool)_LRC_TS_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_LRC_TS_DEPEND) local orderdeps += $(TOOL_$(tool)_LRC_TS_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt3_target_pre_handle_translation_dx)) endef # def_unit_qt3_target_pre_handle_translation ## wrapper for the UIC command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT3_UIC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_UIC_CMDS_PREV_),$$(commands $(out.h)),FORCE) else _UNIT_QT3_UIC_CMDS_DEP = endif ## # def_unit_qt3_src_handler_ui helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt3_target_pre_handle_ui_dx $(out.h) + $(out.cpp) +| $(realout.h) $(realout.cpp) $(more_output) $(maybe_output): \ $(deps) \ $(value _UNIT_QT3_UIC_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,uic,$(target),$(source),$(out.h) $(out.cpp)) $(QUIET2)$(RM) -f $(out.h) $(out.cpp) $(more_output) $(maybe_output) $(dep) $(cmds) $(QUIET)$(CP) --changed -f $(out.h) $(realout.h) $(QUIET)$(CP) --changed -f $(out.cpp) $(realout.cpp) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_UIC_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out.h)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_INTERMEDIATES += $(realout.h) $(target)_GEN_SOURCES_ += $(realout.cpp) $(target)_CLEAN += $(out.h) $(out.cpp) $(realout.h) $(realout.cpp) $(more_output) $(maybe_output) $(dep) endef # def_unit_qt3_target_pre_handle_ui_dx ## # Source handler for .ui sources. # # @remarks $(evalvalctx me). define def_unit_qt3_src_handler_ui local type := UIC # fetch the properties. local tool := $(kb-src-tool dummy_var) local qtuicdir := $($(target)_0_OUTDIR)/qtuic local outbase := $(qtuicdir)/$(notdir $(basename $(source))) local out.h := $(outbase).tmp.h local out.cpp := $(outbase).tmp.cpp local realout.h := $(outbase).h local realout.cpp:=$(outbase).cpp local dep := $(realout.h).dep local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_UIC_UI_CMDS $(error kBuild: qt uic tool not found: TOOL_$(tool)_UIC_UI_CMDS) endif local cmds := $(TOOL_$(tool)_UIC_UI_CMDS) local more_output := $(TOOL_$(tool)_UIC_UI_OUTPUT) local maybe_output := $(TOOL_$(tool)_UIC_UI_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_UIC_UI_DEPEND) local orderdeps += $(TOOL_$(tool)_UIC_UI_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt3_target_pre_handle_ui_dx)) endef # def_unit_qt3_src_handler_ui ## wrapper for the MOC command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT3_MOC_HPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_MOC_HPP_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT3_MOC_HPP_CMDS_DEP = endif ## # def_unit_qt3_target_pre_handle_moc_hdr helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt3_target_pre_handle_moc_hdr_dx $(out) +| $(realout) $(more_output) $(maybe_output): \ $(deps) \ $(value _UNIT_QT3_MOC_HPP_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,moc,$(target),$(source),$(realout)) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) $(QUIET)$(CP) --changed -f $(out) $(realout) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_MOC_HPP_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_INTERMEDIATES += $(realout) $(target)_GEN_SOURCES_ += $(realout) $(target)_CLEAN += $(out) $(realout) $(more_output) $(maybe_output) $(dep) endef ## # Handle a source file listed in QT_MOCHDRS. # # The files listed in QT_MOCHDRS uses the Q_OBJECT macro and we will # generate a .cpp file for each of them and add it to the generated # sources so that it's compiled and linked. (There is an alternative # way to do this where the .cpp file is included, this isn't currently # supported by this unit.) # # @remarks Invoked via $(evalvalctx ). define def_unit_qt3_target_pre_handle_moc_hdr local type := MOC # fetch the properties. local tool := $(kb-src-tool dummy_var) local outbase := $(qtmocdir)/$(notdir $(basename $(source))) local out := $(outbase).tmp.cpp local realout := $(outbase).cpp local dep := $(realout).dep local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_MOC_HPP_CMDS $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_HPP_CMDS) endif local cmds := $(TOOL_$(tool)_MOC_HPP_CMDS) local more_output := $(TOOL_$(tool)_MOC_HPP_OUTPUT) local maybe_output := $(TOOL_$(tool)_MOC_HPP_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_MOC_HPP_DEPEND) local orderdeps += $(TOOL_$(tool)_MOC_HPP_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt3_target_pre_handle_moc_hdr_dx)) endef # def_unit_qt3_target_pre_handle_moc_hdr ## wrapper for the MOC command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT3_MOC_CPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT3_MOC_CPP_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT3_MOC_CPP_CMDS_DEP = endif ## # def_unit_qt3_target_pre_handle_moc_src helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt3_target_pre_handle_moc_src_dx $(out) +| $(realout) $(more_output) $(maybe_output): \ $(deps) \ $(value _UNIT_QT3_MOC_CPP_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,moc,$(target),$(source),$(realout)) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) $(QUIET)$(CP) --changed -f $(out) $(realout) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT3_MOC_CPP_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_INTERMEDIATES += $(realout) $(target)_CLEAN += $(out) $(realout) $(more_output) $(maybe_output) $(dep) endef ## # Handle a source file listed in QT_MOCSRCS. # # The files listed in QT_MOCSRCS uses the Q_OBJECT macro and will include # a .moc file that we're expected to generate here. # # @remarks Invoked via $(evalvalctx ). define def_unit_qt3_target_pre_handle_moc_src local type := MOC # fetch the properties. local tool := $(kb-src-tool dummy_var) local outbase := $(qtmocdir)/$(notdir $(basename $(source))) local out := $(outbase).tmp.moc local realout := $(outbase).moc local dep := $(realout).dep local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_MOC_CPP_CMDS $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_CPP_CMDS) endif local cmds := $(TOOL_$(tool)_MOC_CPP_CMDS) local more_output := $(TOOL_$(tool)_MOC_CPP_OUTPUT) local maybe_output := $(TOOL_$(tool)_MOC_CPP_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_MOC_CPP_DEPEND) local orderdeps += $(TOOL_$(tool)_MOC_CPP_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt3_target_pre_handle_moc_src_dx)) endef # def_unit_qt3_target_pre_handle_moc_src ## # Adds sources containing Q_OBJECT to QT_MOCSRCS. define def_unit_qt3_target_pre_cpp_source ifneq ($(file-size $(source)),-1) ifneq ($(strip $(shell $(SED) -f $(KBUILD_PATH)/units/qt-Q_OBJECT.sed $(source))),) $(eval $(target)_QT_MOCSRCS += $(source)) endif endif endef # def_unit_qt3_target_pre_cpp_source ## # Invoked early in the processing of a target that uses the Qt unit. # # It will append the qt source handlers to the target (.h, .ui, .ts, # .png, .bmp, .gif). # # It will then check all the C++ sources and check which needs # a .moc files and generate rules and dependencies fofor these # define def_unit_qt3_target_pre # Make QTTOOL the default for the specific Qt tools instead of TOOL. ifneq ($($(target)_QTTOOL),) ifeq ($($(target)_MOCTOOL),) $(target)_MOCTOOL := $($(target)_QTTOOL) endif ifeq ($($(target)_UICTOOL),) $(target)_UICTOOL := $($(target)_QTTOOL) endif ifeq ($($(target)_LRCTOOL),) $(target)_LRCTOOL := $($(target)_QTTOOL) endif endif # Deal with QT_MODULES and QT_PREFIX. local qt_prefix := $(firstword \ $($(target)_QT_PREFIX.$(bld_trg)) \ $($(target)_QT_PREFIX.$(bld_trg_arch)) \ $($(target)_QT_PREFIX.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_PREFIX.$(bld_trg_cpu)) \ $($(target)_QT_PREFIX.$(bld_type)) \ $($(target)_QT_PREFIX)) ifeq ($(bld_trg),win) local qt_lib := $(firstword $(wildcard \ $(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)qt-mt3*$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/$(qt_prefix)qt-mt3*$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)qt-mt$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/$(qt_prefix)qt-mt$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)Qt3*$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/$(qt_prefix)Qt3*$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/dynamic/$(qt_prefix)Qt*$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/$(qt_prefix)Qt*$(SUFF_LIB) \ ) $(PATH_SDK_QT3_LIB)/$(qt_prefix)qt-mt$(SUFF_LIB) ) $(eval $(target)_LIBS += $(qt_lib) ) ifeq ($(tool_do),LINK_PROGRAM) local qt_main_lib := $(firstword $(wildcard \ $(PATH_SDK_QT3_LIB)/$(qt_prefix)qtmain$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/qtmain$(SUFF_LIB) \ ) $(PATH_SDK_QT3_LIB)/$(qt_prefix)qtmain$(SUFF_LIB) ) $(eval $(target)_LIBS += $(qt_main_lib) ) endif else ifeq ($(bld_trg),os2) # This is a real PITA since the dll/lib can be called (almost) anything. :-( local qt_lib := $(firstword $(wildcard \ $(PATH_SDK_QT3_LIB)/$(qt_prefix)*qt3*$(SUFF_LIB) \ $(PATH_SDK_QT3_LIB)/$(qt_prefix)*qt*$(SUFF_LIB) \ )) ifeq ($(qt_lib),) local qt_prls := $(basename $(wildcard $(PATH_SDK_QT3_LIB)/$(qt_prefix)*.prl)) local qt_defs := $(basename $(wildcard $(PATH_SDK_QT3_LIB)/$(qt_prefix)*.def)) local qt_dlls := $(basename $(wildcard $(PATH_SDK_QT3_LIB)/$(qt_prefix)*.dll)) local qt_libs := $(basename $(wildcard $(PATH_SDK_QT3_LIB)/$(qt_prefix)*.lib)) local qt_lib := $(firstword \ $(addsuffix .lib,$(filter $(qt_prls), $(filter $(qt_defs), $(filter $(qt_dlls), $(qt_libs))))) \ $(PATH_SDK_QT3_LIB)/myqt.lib ) endif $(eval $(target)_LIBS += $(qt_lib) ) else local qt_lib := $(PATH_SDK_QT3_LIB)/lib$(qt_prefix)qt-mt$(SUFF_DLL) $(eval $(target)_LIBS += $(qt_lib) ) endif $(eval $(target)_INCS += $(PATH_SDK_QT3_INC) ) # On Qt3 we will try pickup the QMAKE_PRL_DEFINES listed in the .prl file (in libs). local qt_prl := $(firstword $(wildcard \ $(patsubst %$(SUFF_DLL),%,$(patsubst %$(SUFF_LIB),%,$(qt_lib))).prl \ $(dir $(qt_lib))/$(qt_prefix)qt-mt.prl \ $(dir $(qt_lib))/*qt-mt*.prl \ $(dir $(qt_lib))/*qt*.prl \ )) ifneq ($(qt_prl),) include $(qt_prl) $(eval $(target)_DEFS += $(QMAKE_PRL_DEFINES)) endif # Autodetect source files with Q_OBJECT references if QT_MOCSRCS is undefined. (slow) # Tip: Use target_QT_MOCSRCS = $(NO_SUCH_VARIABLE) to avoid this. ifndef $(target)_QT_MOCSRCS $(foreach source, $(filter %.cxx %.CXX %.cpp %.CPP %.cc %.CC,\ $($(target)_SOURCES.$(bld_trg)) \ $($(target)_SOURCES.$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg_cpu)) \ $($(target)_SOURCES.$(bld_type)) \ $($(target)_SOURCES) \ ), $(evalval def_unit_qt3_target_pre_cpp_source)) endif # Install source handlers for .ui files. $(target)_SRC_HANDLERS += \ .ui:def_unit_qt3_src_handler_ui \ .UI:def_unit_qt3_src_handler_ui # Calc the MOC and UI output directories and add them to BLDDIRS and INCS. local qtmocdir := $($(target)_0_OUTDIR)/qtmoc local qtuicdir := $($(target)_0_OUTDIR)/qtuic local qtnlsdir := $($(target)_0_OUTDIR)/qtnls $(eval $(target)_BLDDIRS += $(qtmocdir) $(qtuicdir) $(qtnlsdir) ) $(eval $(target)_INCS += $(qtmocdir) $(qtuicdir) ) # Calc .ui sources so we can add them to the QT_MOCSRCS and QT_MOCHDRS. local ui_sources := $(notdir $(basename $(filter %.ui %.UI, \ $($(target)_SOURCES.$(bld_trg)) \ $($(target)_SOURCES.$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg_cpu)) \ $($(target)_SOURCES.$(bld_type)) \ $($(target)_SOURCES) \ ))) #$(error ui_sources:=$(ui_sources)) # Deal with QT_MOCSRCS. $(foreach source, \ $($(target)_QT_MOCSRCS.$(bld_trg)) \ $($(target)_QT_MOCSRCS.$(bld_trg_arch)) \ $($(target)_QT_MOCSRCS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_MOCSRCS.$(bld_trg_cpu)) \ $($(target)_QT_MOCSRCS.$(bld_type)) \ $($(target)_QT_MOCSRCS) \ $(addsuffix .h,$(addprefix $(qtuicdir)/,$(notdir $(basename $(ui_sources))))) \ , $(evalvalctx def_unit_qt3_target_pre_handle_moc_src)) # Deal with QT_MOCHDRS. $(foreach source, \ $($(target)_QT_MOCHDRS.$(bld_trg)) \ $($(target)_QT_MOCHDRS.$(bld_trg_arch)) \ $($(target)_QT_MOCHDRS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_MOCHDRS.$(bld_trg_cpu)) \ $($(target)_QT_MOCHDRS.$(bld_type)) \ $($(target)_QT_MOCHDRS) \ $(addsuffix .h,$(addprefix $(qtuicdir)/,$(notdir $(basename $(ui_sources))))) \ , $(evalvalctx def_unit_qt3_target_pre_handle_moc_hdr)) # Deal with QT_TRANSLATIONS. # ASSUMES (_ALL_)INSTALLS is processed after the targets using this unit. local translations := \ $($(target)_QT_TRANSLATIONS.$(bld_trg)) \ $($(target)_QT_TRANSLATIONS.$(bld_trg_arch)) \ $($(target)_QT_TRANSLATIONS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_TRANSLATIONS.$(bld_trg_cpu)) \ $($(target)_QT_TRANSLATIONS.$(bld_type)) \ $($(target)_QT_TRANSLATIONS) ifneq ($(strip $(translations)),) local expr := _ALL_INSTALLS_IMPLICIT += $(target)-inst-nls $(eval $(expr)) ifdef $(target)_QT_TRANSLATIONS_TEMPLATE $(target)-inst-nls_TEMPLATE := $($(target)_QT_TRANSLATIONS_TEMPLATE) else $(target)-inst-nls_MODE := 0644 endif ifdef $(target)_QT_TRANSLATIONS_INST $(target)-inst-nls_INST := $($(target)_QT_TRANSLATIONS_INST) endif $(target)-inst-nls_SOURCES := $(foreach source, $(translations)\ , $(evalvalctx def_unit_qt3_target_pre_handle_translation)) endif endef # def_unit_qt3_target_pre # # Rule for debugging. # unit-qt3-show-vars: @$(ECHO) 'The Qt3 SDK variables:' @$(ECHO) ' PATH_SDK_QT3 = "$(PATH_SDK_QT3)"' @$(ECHO) ' PATH_SDK_QT3_INC = "$(PATH_SDK_QT3_INC)"' @$(ECHO) ' PATH_SDK_QT3_LIB = "$(PATH_SDK_QT3_LIB)"' @$(ECHO) ' PATH_SDK_QT3_LIB.amd64 = "$(PATH_SDK_QT3_LIB.amd64)"' @$(ECHO) ' PATH_SDK_QT3_LIB.x86 = "$(PATH_SDK_QT3_LIB.x86)"' @$(ECHO) 'The Qt3 TOOL variables:' @$(ECHO) ' PATH_TOOL_QT3_BIN = "$(PATH_TOOL_QT3_BIN)"' @$(ECHO) ' TOOL_QT3_BIN_SUFF = "$(TOOL_QT3_BIN_SUFF)"' @$(ECHO) ' TOOL_QT3_MOC = "$(TOOL_QT3_MOC)"' @$(ECHO) ' TOOL_QT3_UIC = "$(TOOL_QT3_UIC)"' @$(ECHO) ' TOOL_QT3_LRC = "$(TOOL_QT3_LRC)"' @$(ECHO) ' TOOL_QT3_LUPDATE = "$(TOOL_QT3_LUPDATE)"' kbuild-2695/kBuild/units/qt4.kmk0000644000000000000000000011064412247157310015231 0ustar rootroot# $Id: qt4.kmk 2544 2011-09-13 19:00:25Z bird $ ## @file # Qt 4 unit. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef UNIT_qt4 $(error kBuild: The qt4 unit was included twice!) endif UNIT_qt4 = qt4 ifndef UNIT_qt3 # Add our target properties (same as qt3). PROPS_SINGLE += QTTOOL MOCTOOL UICTOOL LRCTOOL QT_TRANSLATIONS_INST QT_TRANSLATIONS_TEMPLATE QT_PREFIX PROPS_ACCUMULATE_R += MOCDEFS MOCFLAGS UICFLAGS LRCFLAGS QT_TRANSLATIONS QT_MOCSRCS QT_MOCHDRS endif PROPS_SINGLE += RCCTOOL QT_INFIX PROPS_ACCUMULATE_R += RCCFLAGS QT_MODULES ## @todo use pkg-config? # # The QT4 SDK. # # This is implemented here rather than in sdks/QT4.kmk to enforce the global USES. # It also makes things easier to develop, with fewer files I mean. # ## @todo the SDK might actually not be necessary as it turns out... For now it servers # a purpose if the host differs from the target, in theory at least. SDK_QT4 = Qt4 # SDK Specific Properties # PATH_SDK_QT4 - The general Qt4 root directory. # PATH_SDK_QT4_INC - The include directory. # PATH_SDK_QT4_LIB.amd64 - The lib directory for AMD64. # PATH_SDK_QT4_LIB.x86 - The lib directory for X86. # PATH_SDK_QT4_LIB - The lib directory for KBUILD_TARGET. ifndef PATH_SDK_QT4 PATH_SDK_QT4 := $(firstword $(rsort $(wildcard $(KBUILD_DEVTOOLS_TRG)/qt/v4*))) ifeq ($(PATH_SDK_QT4),) # If target == host, try look for Qt in the various platform specific places. ifeq ($(KBUILD_TARGET),$(KBUILD_HOST)) ifeq ($(KBUILD_TARGET),darwin) PATH_SDK_QT4 := $(patsubst %/Frameworks/QtCore.framework/Versions/4,%,$(firstword $(wildcard /Library/Frameworks/QtCore.framework/Versions/4))) else ifeq ($(KBUILD_TARGET),win) # No idea here yet... else ifeq ($(KBUILD_TARGET),ose) # No port... else # The Unices. Includes and esp. libs are tricky, so override the PATH_SDK_QT4_LIB* stuff if it doesn't work. # Try find the general root of thing by looking for the qt3to4 program, if not found, then look for rcc. PATH_SDK_QT4 := $(patsubst %/bin/qt3to4,%,$(firstword $(wildcard \ /usr/bin/qt3to4 \ /usr/local/bin/qt3to4 \ /usr/qt/4/bin/qt3to4 \ /usr/share/qt4/bin/qt3to4 \ ))) ifeq ($(PATH_SDK_QT4),) PATH_SDK_QT4 := $(patsubst %/bin/rcc,%,$(firstword $(wildcard \ /usr/bin/rcc \ /usr/local/bin/rcc \ /usr/qt/4/bin/rcc \ /usr/share/qt4/bin/rcc \ ))) endif ifneq ($(PATH_SDK_QT4),) export PATH_SDK_QT4 # Locate the include files. ifeq ($(PATH_SDK_QT4_INC),) PATH_SDK_QT4_INC := $(patsubst %/QtCore/qglobal.h,%,$(firstword $(wildcard \ $(PATH_SDK_QT4)/include/QtCore/qglobal.h \ $(PATH_SDK_QT4)/include/qt4/QtCore/qglobal.h \ /usr/include/qt4/QtCore/qtglobal.h \ /usr/local/include/qt4/QtCore/qtglobal.h \ ))) ifneq ($(PATH_SDK_QT4_INC),) export PATH_SDK_QT4_INC endif endif # Now for the libraries (mostly for helping out finding the KBUILD_TARGET libs). ifeq ($(PATH_SDK_QT4_LIB.x86),) PATH_SDK_QT4_LIB.x86 := $(patsubst %/libQtCore$(SUFF_DLL),%,$(firstword $(wildcard \ $(PATH_SDK_QT4)/lib32/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib32/qt4/libQtCore$(SUFF_DLL) \ /usr/lib32/libQtCore$(SUFF_DLL) \ /usr/lib32/qt4/libQtCore$(SUFF_DLL) \ /usr/lib/i386-linux-gnu/libQtCore$(SUFF_DLL) \ /usr/local/lib32/libQtCore$(SUFF_DLL) \ /usr/local/lib32/qt4/libQtCore$(SUFF_DLL) \ /usr/local/lib/i386-linux-gnu/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/qt4/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/i386-linux-gnu/libQtCore$(SUFF_DLL) \ ))) ifneq ($(PATH_SDK_QT4_LIB.x86),) export PATH_SDK_QT4_LIB.x86 endif endif ifeq ($(PATH_SDK_QT4_LIB.amd64),) PATH_SDK_QT4_LIB.amd64 := $(patsubst %/libQtCore$(SUFF_DLL),%,$(firstword $(wildcard \ $(PATH_SDK_QT4)/lib64/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib64/qt4/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/amd64/libQtCore$(SUFF_DLL) \ /usr/lib64/libQtCore$(SUFF_DLL) \ /usr/lib64/qt4/libQtCore$(SUFF_DLL) \ /usr/lib/amd64/libQtCore$(SUFF_DLL) \ /usr/lib/x86_64-linux-gnu/libQtCore$(SUFF_DLL) \ /usr/local/lib64/libQtCore$(SUFF_DLL) \ /usr/local/lib64/qt4/libQtCore$(SUFF_DLL) \ /usr/local/lib/amd64/libQtCore$(SUFF_DLL) \ /usr/local/lib/x86_64-linux-gnu/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/qt4/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/x86_64-linux-gnu/libQtCore$(SUFF_DLL) \ ))) ifneq ($(PATH_SDK_QT4_LIB.amd64),) export PATH_SDK_QT4_LIB.amd64 endif endif # And finally, the library path for KBUILD_TARGET. ifeq ($(PATH_SDK_QT4_LIB),) PATH_SDK_QT4_LIB := $(PATH_SDK_QT4_LIB.$(KBUILD_TARGET_ARCH)) ifeq ($(PATH_SDK_QT4_LIB),) PATH_SDK_QT4_LIB := $(patsubst %/libQtCore$(SUFF_DLL),%,$(firstword $(wildcard \ $(PATH_SDK_QT4)/lib/libQtCore$(SUFF_DLL) \ $(PATH_SDK_QT4)/lib/qt4/libQtCore$(SUFF_DLL) \ /usr/lib/libQtCore$(SUFF_DLL) \ /usr/lib/qt4/libQtCore$(SUFF_DLL) \ /usr/local/lib/libQtCore$(SUFF_DLL) \ /usr/local/lib/qt4/libQtCore$(SUFF_DLL) \ ))) endif ifneq ($(PATH_SDK_QT4_LIB),) export PATH_SDK_QT4_LIB endif endif endif endif # Unices endif # Found it? ifeq ($(PATH_SDK_QT4),) $(warning kBuild: Couldn't find the Qt4 headers and libaries...) PATH_SDK_QT4 := $(KBUILD_DEVTOOLS_TRG)/qt/not-found endif endif else # Resolve any fancy stuff once and for all. PATH_SDK_QT4 := $(PATH_SDK_QT4) endif # Libraries can be in either Frameworks or lib depending on how you # build it on the mac. The .dmg installs into Frameworks but builds into lib. ifeq ($(KBUILD_TARGET),darwin) ifndef PATH_SDK_QT4_LIB ifneq ($(wildcard $(PATH_SDK_QT4)/Frameworks),) PATH_SDK_QT4_LIB ?= $(PATH_SDK_QT4)/Frameworks else PATH_SDK_QT4_LIB ?= $(PATH_SDK_QT4)/lib endif endif else PATH_SDK_QT4_LIB ?= $(PATH_SDK_QT4)/lib PATH_SDK_QT4_INC ?= $(PATH_SDK_QT4)/include endif # The bits that kBuild picks up. # (nothing here) # # The QT4 tool. # # This is implemented here rather than in tools/QT4.kmk to enforce the global USES. # It also makes things easier to develop, with fewer files I mean. # TOOL_QT4 = Qt4 # Tool Specific Properties # PATH_TOOL_QT4 - Obsolete. # PATH_TOOL_QT4_BIN - The # TOOL_QT4_BIN_SUFF - if !defined(PATH_TOOL_QT4_BIN) && defined(PATH_TOOL_QT4) PATH_TOOL_QT4_BIN := $(PATH_TOOL_QT4)/bin endif ifndef PATH_TOOL_QT4_BIN PATH_TOOL_QT4_BIN := $(firstword $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/qt/v4*/bin))) if "$(PATH_TOOL_QT4_BIN)" == "" && "$(KBUILD_DEVTOOLS_HST_ALT)" != "" PATH_TOOL_QT4_BIN := $(firstword $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/qt/v4*/bin))) endif ifeq ($(PATH_TOOL_QT4_BIN),) ifdef TOOL_QT4_BIN_SUFF TOOL_QT4_BIN_SUFF := $(TOOL_QT4_BIN_SUFF) endif # Try looking for moc-qt4 / moc-$(suffix) first. ifneq ($(TOOL_QT4_BIN_SUFF),) PATH_TOOL_QT4_BIN := $(patsubst %/moc$(TOOL_QT4_BIN_SUFF),%,$(firstword $(wildcard \ /usr/lib/qt4/bin/moc$(TOOL_QT4_BIN_SUFF) \ /usr/qt/4/bin/moc$(TOOL_QT4_BIN_SUFF) \ /usr/share/qt4/bin/moc$(TOOL_QT4_BIN_SUFF) \ /usr/local/bin/moc$(TOOL_QT4_BIN_SUFF) \ /usr/bin/moc$(TOOL_QT4_BIN_SUFF) \ ))) else PATH_TOOL_QT4_BIN := $(patsubst %/moc-qt4,%,$(firstword $(wildcard \ /usr/lib/qt4/bin/moc-qt4 \ /usr/qt/4/bin/moc-qt4 \ /usr/share/qt4/bin/moc-qt4 \ /usr/local/bin/moc-qt4 \ /usr/bin/moc-qt4 \ ))) ifneq ($(PATH_TOOL_QT4_BIN),) TOOL_QT4_BIN_SUFF := -qt4 else # If no luck, try looking for moc in the qt4 specific locations. PATH_TOOL_QT4_BIN := $(patsubst %/moc,%,$(firstword $(wildcard \ /usr/lib/qt4/bin/moc \ /usr/qt/4/bin/moc \ /usr/share/qt4/bin/moc \ ))) endif endif # If still no go, try looking for qt3to4 and rcc. ifeq ($(PATH_TOOL_QT4_BIN),) PATH_TOOL_QT4_BIN := $(patsubst %/qt3to4,%,$(firstword $(wildcard \ /usr/lib/qt4/bin/qt3to4 \ /usr/qt/4/bin/qt3to4 \ /usr/share/qt4/bin/qt3to4 \ /usr/local/bin/qt3to4 \ /usr/bin/qt3to4 \ ))) endif ifeq ($(PATH_TOOL_QT4_BIN),) PATH_TOOL_QT4_BIN := $(patsubst %/rcc$(TOOL_QT4_BIN_SUFF),%,$(firstword $(wildcard \ /usr/lib/qt4/bin/rcc$(TOOL_QT4_BIN_SUFF) \ /usr/qt/4/bin/rcc$(TOOL_QT4_BIN_SUFF) \ /usr/share/qt4/bin/rcc$(TOOL_QT4_BIN_SUFF) \ /usr/local/bin/rcc$(TOOL_QT4_BIN_SUFF) \ /usr/bin/rcc$(TOOL_QT4_BIN_SUFF) \ ))) endif if "$(PATH_TOOL_QT4_BIN)" == "" && "$(TOOL_QT4_BIN_SUFF)" != "" PATH_TOOL_QT4_BIN := $(patsubst %/rcc,%,$(firstword $(wildcard \ /usr/lib/qt4/bin/rcc \ /usr/qt/4/bin/rcc \ /usr/share/qt4/bin/rcc \ /usr/local/bin/rcc \ /usr/bin/rcc \ ))) endif ifneq ($(PATH_TOOL_QT4_BIN),) export PATH_TOOL_QT4_BIN endif endif # If not found, we'll enter the 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_QT4_BIN := $(PATH_TOOL_QT4_BIN) endif ifneq ($(PATH_TOOL_QT4_BIN),) TOOL_QT4_MOC ?= $(PATH_TOOL_QT4_BIN)/moc$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT4_UIC ?= $(PATH_TOOL_QT4_BIN)/uic$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) ifndef TOOL_QT4_RCC TOOL_QT4_RCC := $(PATH_TOOL_QT4_BIN)/rcc$(HOST_SUFF_EXE) ifeq ($(wildcard $(TOOL_QT4_RCC)),) TOOL_QT4_RCC := $(PATH_TOOL_QT4_BIN)/rcc$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) endif endif TOOL_QT4_LRC ?= $(PATH_TOOL_QT4_BIN)/lrelease$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT4_LUPDATE ?= $(PATH_TOOL_QT4_BIN)/lupdate$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) else # Pathless, relies on the environment. TOOL_QT4_MOC ?= moc$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT4_UIC ?= uic$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT4_RCC ?= rcc$(HOST_SUFF_EXE) TOOL_QT4_LRC ?= lrelease$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) TOOL_QT4_LUPDATE ?= lupdate$(TOOL_QT4_BIN_SUFF)$(HOST_SUFF_EXE) endif # General Properties used by kBuild and/or units/qt.kmk TOOL_QT4_MOCFLAGS ?= TOOL_QT4_MOCINCS ?= TOOL_QT4_MOCDEFS ?= TOOL_QT4_MOCDEFS.darwin ?= __APPLE__ __GNUC__ TOOL_QT4_MOCDEFS.solaris ?= __sun TOOL_QT4_MOCDEFS.win.amd64 ?= WIN64 TOOL_QT4_MOCDEFS.win.x86 ?= WIN32 ## MOC a C++ source file. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. # @param $(incs) Includes. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT4_MOC_CPP_DEPEND = TOOL_QT4_MOC_CPP_DEPORD = TOOL_QT4_MOC_CPP_OUTPUT = TOOL_QT4_MOC_CPP_OUTPUT_MAYBE = define TOOL_QT4_MOC_CPP_CMDS $(QUIET)$(TOOL_QT4_MOC)\ $(flags)\ $(addprefix -I, $(incs))\ $(addprefix -D, $(defs))\ -o $(out)\ $(source) endef ## MOC a C++ header file. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. # @param $(incs) Includes. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT4_MOC_HPP_DEPEND = TOOL_QT4_MOC_HPP_DEPORD = TOOL_QT4_MOC_HPP_OUTPUT = TOOL_QT4_MOC_HPP_OUTPUT_MAYBE = define TOOL_QT4_MOC_HPP_CMDS $(QUIET)$(TOOL_QT4_MOC)\ $(flags)\ $(addprefix -I, $(incs))\ $(addprefix -D, $(defs))\ -o $(out)\ $(source) endef ## Compile a Qt user interface file (.ui). # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. # @param $(incs) Includes. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT4_UIC_UI_DEPEND = TOOL_QT4_UIC_UI_DEPORD = TOOL_QT4_UIC_UI_OUTPUT = TOOL_QT4_UIC_UI_OUTPUT_MAYBE = define TOOL_QT4_UIC_UI_CMDS $(QUIET)$(TOOL_QT4_UIC)\ $(flags)\ -o $(out)\ $(source) endef ## Compile a Qt resource file (.qrc). # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. # @param $(incs) Includes. # @param $(outbase) Output basename (full). Use this for list files and such. # # @remarks The sed script generating the dependency file is a bit naive. TOOL_QT4_RCC_QRC_DEPEND = TOOL_QT4_RCC_QRC_DEPORD = TOOL_QT4_RCC_QRC_OUTPUT = TOOL_QT4_RCC_QRC_OUTPUT_MAYBE = define TOOL_QT4_RCC_QRC_CMDS $(QUIET)$(TOOL_QT4_RCC)\ $(flags)\ -o $(out)\ $(source) $(QUIET2)$(APPEND) $(dep) '\' $(QUIET2)$(APPEND) $(dep) '$(out): \' $(QUIET2)$(APPEND) $(dep) '$(source) \' $(QUIET2)$(SED) \ -e '/^[[:blank:]]*]*>/!d' \ -e 's/^.*]*>\([^<]*\)<\/file>.*$$$$/\1/' \ -e 's|^[^/][^:]|$(abspathex $(dir $(source)),$(defpath))/&|' \ -e 's|$$$$| \\|' \ --append $(dep) \ $(source) $(QUIET2)$(APPEND) $(dep) $(QUIET2)$(SED) \ -e '/^[[:blank:]]*]*>/!d' \ -e 's/^.*]*>\([^<]*\)<\/file>.*$$$$/\1/' \ -e 's|^[^/][^:]|$(abspathex $(dir $(source)),$(defpath))/&|' \ -e 's|$$$$|:\n|' \ --append $(dep) \ $(source) $(QUIET2)$(APPEND) $(dep) endef ## Compile a Qt translation file (.ts). # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(out) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This may be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. # @param $(incs) Includes. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_QT4_LRC_TS_DEPEND = TOOL_QT4_LRC_TS_DEPORD = TOOL_QT4_LRC_TS_OUTPUT = TOOL_QT4_LRC_TS_OUTPUT_MAYBE = define TOOL_QT4_LRC_TS_CMDS $(QUIET)$(TOOL_QT4_LRC)\ $(flags)\ $(source)\ -qm $(out) endef # # # Back to the Qt4 unit. # # ## wrapper for the lrelease (LRC) command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT4_LRC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_LRC_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT4_LRC_CMDS_DEP = endif ## # def_unit_qt4_target_pre_handle_translation helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt4_target_pre_handle_translation_dx $(out) + $(more_output) +| $(maybe_output): \ $(deps) \ $(value _UNIT_QT4_LRC_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,lrelease,$(target),$(source),$$@) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_LRC_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_CLEAN += $(out) $(more_output) $(maybe_output) $(dep) $(target)-inst-nls_SOURCES += $(out) endef # def_unit_qt4_target_pre_handle_translation_dx ## # Handle a source file listed in QT_TRANSLATIONS. # # The files listed in QT_TRANSLATIONS are translation files (.ts) which needs # to be translated into .qm files that are loadble by Qt. # # @remarks Invoked via $(evalvalctx ). define def_unit_qt4_target_pre_handle_translation local type := LRC # fetch the properties. local tool := $(kb-src-tool dummy_var) local qtnlsdir := $($(target)_0_OUTDIR)/qtnls local outbase := $(qtnlsdir)/$(notdir $(basename $(source))) local out := $(outbase).qm local dep := $(out).dep local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_LRC_TS_CMDS $(error kBuild: qt lrelease tool not found: TOOL_$(tool)_LRC_TS_CMDS) endif local cmds := $(TOOL_$(tool)_LRC_TS_CMDS) local more_output := $(TOOL_$(tool)_LRC_TS_OUTPUT) local maybe_output := $(TOOL_$(tool)_LRC_TS_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_LRC_TS_DEPEND) local orderdeps += $(TOOL_$(tool)_LRC_TS_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt4_target_pre_handle_translation_dx)) endef # def_unit_qt4_target_pre_handle_translation ## wrapper for the UIC command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT4_RCC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_RCC_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT4_RCC_CMDS_DEP = endif ## # def_unit_qt4_target_pre_handle_qrc helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt4_target_pre_handle_rcc_dx $(out) +| $(realout) $(more_output) $(maybe_output): \ $(deps) \ $(value _UNIT_QT4_RCC_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,rcc,$(target),$(source),$$@) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) $(QUIET)$(CP) --changed -f $(out) $(realout) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_RCC_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_INTERMEDIATES += $(realout) $(target)_GEN_SOURCES_ += $(realout) $(target)_CLEAN += $(out) $(realout) $(more_output) $(maybe_output) $(dep) endef # def_unit_qt4_target_pre_handle_rcc_dx ## # Source handler for .qrc sources (Qt resource files). # # @remarks $(evalvalctx me). define def_unit_qt4_src_handler_qrc local type := RCC # fetch the properties. local tool := $(kb-src-tool dummy_var) local qtrccdir := $($(target)_0_OUTDIR)/qtrcc local outbase := $(qtrccdir)/$(notdir $(basename $(source))) local out := $(outbase).tmp.gen.cpp local realout := $(outbase).gen.cpp local dep := $(realout).dep local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_RCC_QRC_CMDS $(error kBuild: qt rcc tool not found: TOOL_$(tool)_RCC_QRC_CMDS) endif local cmds := $(TOOL_$(tool)_RCC_QRC_CMDS) local more_output := $(TOOL_$(tool)_RCC_QRC_OUTPUT) local maybe_output := $(TOOL_$(tool)_RCC_QRC_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_RCC_QRC_DEPEND) local orderdeps += $(TOOL_$(tool)_RCC_QRC_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt4_target_pre_handle_rcc_dx)) endef # def_unit_qt4_src_handler_qrc ## wrapper for the UIC command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT4_UIC_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_UIC_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT4_UIC_CMDS_DEP = endif ## # def_unit_qt4_src_handler_ui helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt4_target_pre_handle_ui_dx $(out) +| $(realout) $(more_output) $(maybe_output): \ $(deps) \ $(value _UNIT_QT4_UIC_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,uic,$(target),$(source),$$@) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) $(QUIET)$(CP) --changed -f $(out) $(realout) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_UIC_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_INTERMEDIATES += $(realout) $(target)_CLEAN += $(out) $(realout) $(more_output) $(maybe_output) $(dep) endef # def_unit_qt4_target_pre_handle_ui_dx ## # Source handler for .ui sources. # # @remarks $(evalvalctx me). define def_unit_qt4_src_handler_ui local type := UIC # fetch the properties. local tool := $(kb-src-tool dummy_var) local qtuicdir := $($(target)_0_OUTDIR)/qtuic local outbase := $(qtuicdir)/$(notdir $(basename $(source))) local out := $(outbase).tmp.gen.h local realout := $(outbase).gen.h local dep := $(realout).dep local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_UIC_UI_CMDS $(error kBuild: qt uic tool not found: TOOL_$(tool)_UIC_UI_CMDS) endif local cmds := $(TOOL_$(tool)_UIC_UI_CMDS) local more_output := $(TOOL_$(tool)_UIC_UI_OUTPUT) local maybe_output := $(TOOL_$(tool)_UIC_UI_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_UIC_UI_DEPEND) local orderdeps += $(TOOL_$(tool)_UIC_UI_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt4_target_pre_handle_ui_dx)) endef # def_unit_qt4_src_handler_ui ## wrapper for the MOC command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT4_MOC_HPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_MOC_HPP_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT4_MOC_HPP_CMDS_DEP = endif ## # def_unit_qt4_target_pre_handle_moc_hdr helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt4_target_pre_handle_moc_hdr_dx $(out) +| $(realout) $(more_output) $(maybe_output): \ $(deps) \ $(value _UNIT_QT4_MOC_HPP_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,moc,$(target),$(source),$$@) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) $(QUIET)$(CP) --changed -f $(out) $(realout) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_MOC_HPP_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_INTERMEDIATES += $(realout) $(target)_GEN_SOURCES_ += $(realout) $(target)_CLEAN += $(out) $(realout) $(more_output) $(maybe_output) $(dep) endef ## # Handle a source file listed in QT_MOCHDRS. # # The files listed in QT_MOCHDRS uses the Q_OBJECT macro and we will # generate a .cpp file for each of them and add it to the generated # sources so that it's compiled and linked. (There is an alternative # way to do this where the .cpp file is included, this isn't currently # supported by this unit.) # # @remarks Invoked via $(evalvalctx ). define def_unit_qt4_target_pre_handle_moc_hdr local type := MOC # fetch the properties. local tool := $(kb-src-tool dummy_var) local outbase := $(qtmocdir)/$(notdir $(basename $(source))) local out := $(outbase).tmp.cpp local realout := $(outbase).cpp local dep := $(realout).dep local defs := $(kb-src-prop DEFS,dummy_var,left-to-right) local incs := $(kb-src-prop INCS,dummy_var,right-to-left) local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_MOC_HPP_CMDS $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_HPP_CMDS) endif local cmds := $(TOOL_$(tool)_MOC_HPP_CMDS) local more_output := $(TOOL_$(tool)_MOC_HPP_OUTPUT) local maybe_output := $(TOOL_$(tool)_MOC_HPP_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_MOC_HPP_DEPEND) local orderdeps += $(TOOL_$(tool)_MOC_HPP_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt4_target_pre_handle_moc_hdr_dx)) endef # def_unit_qt4_target_pre_handle_moc_hdr ## wrapper for the MOC command dependencies. ifndef NO_COMPILE_CMDS_DEPS _UNIT_QT4_MOC_CPP_CMDS_DEP = $$(comp-cmds-ex $$($(target)_$(subst :,_,$(source))_QT4_MOC_CPP_CMDS_PREV_),$$(commands $(out)),FORCE) else _UNIT_QT4_MOC_CPP_CMDS_DEP = endif ## # def_unit_qt4_target_pre_handle_moc_src helper that is expanded before evaluation. # # This is necessary to resolve reference to local variables before doing # assignments and setting up commands. They would otherwise be resolved # later in a different context and the result would be completely wrong. # define def_unit_qt4_target_pre_handle_moc_src_dx $(out) +| $(realout) $(more_output) $(maybe_output): \ $(deps) \ $(value _UNIT_QT4_MOC_CPP_CMDS_DEP) \ | \ $(orderdeps) %$$(call MSG_TOOL,moc,$(target),$(source),$$@) $(QUIET2)$(RM) -f $(out) $(more_output) $(maybe_output) $(dep) $(cmds) $(QUIET)$(CP) --changed -f $(out) $(realout) ifndef NO_COMPILE_CMDS_DEPS %$$(QUIET2)$$(APPEND) '$(dep)' %$$(QUIET2)$$(APPEND) '$(dep)' 'define $(target)_$(subst :,_,$(source))_QT4_MOC_CPP_CMDS_PREV_' %$$(QUIET2)$$(APPEND) -c '$(dep)' '$(out)' %$$(QUIET2)$$(APPEND) '$(dep)' 'endef' endif $(target)_INTERMEDIATES += $(realout) $(target)_CLEAN += $(out) $(realout) $(more_output) $(maybe_output) $(dep) endef ## # Handle a source file listed in QT_MOCSRCS. # # The files listed in QT_MOCSRCS uses the Q_OBJECT macro and will include # a .moc file that we're expected to generate here. # # @remarks Invoked via $(evalvalctx ). define def_unit_qt4_target_pre_handle_moc_src local type := MOC # fetch the properties. local tool := $(kb-src-tool dummy_var) local outbase := $(qtmocdir)/$(notdir $(basename $(source))) local out := $(outbase).tmp.moc local realout := $(outbase).moc local dep := $(realout).dep local defs := $(kb-src-prop DEFS,dummy_var,left-to-right) local incs := $(kb-src-prop INCS,dummy_var,right-to-left) local flags := $(kb-src-prop FLAGS,dummy_var,right-to-left) local deps := $(kb-src-prop DEPS,dummy_var,left-to-right) local orderdeps := $(call DIRDEP,$(dir $(outbase))) $(kb-src-prop ORDERDEPS,dummy_var,left-to-right) # default path + source dep. ifneq ($(defpath),) local source := $(abspathex $(source),$(defpath)) local deps := $(abspathex $(deps),$(defpath)) $(source) local incs := $(abspathex $(incs),$(defpath)) else local deps += $(source) endif # call the tool ifndef TOOL_$(tool)_MOC_CPP_CMDS $(error kBuild: qt moc tool not found: TOOL_$(tool)_MOC_CPP_CMDS) endif local cmds := $(TOOL_$(tool)_MOC_CPP_CMDS) local more_output := $(TOOL_$(tool)_MOC_CPP_OUTPUT) local maybe_output := $(TOOL_$(tool)_MOC_CPP_OUTPUT_MAYBE) local deps += $(TOOL_$(tool)_MOC_CPP_DEPEND) local orderdeps += $(TOOL_$(tool)_MOC_CPP_DEPORD) # generate the link rule and update some source and target variables. ifndef NO_COMPILE_CMDS_DEPS $(eval includedep $(dep)) endif $(eval $(def_unit_qt4_target_pre_handle_moc_src_dx)) endef # def_unit_qt4_target_pre_handle_moc_src ## # Adds sources containing Q_OBJECT to QT_MOCSRCS. define def_unit_qt4_target_pre_cpp_source ifneq ($(file-size $(source)),-1) ifneq ($(strip $(shell $(SED) -f $(KBUILD_PATH)/units/qt-Q_OBJECT.sed $(source))),) $(eval $(target)_QT_MOCSRCS += $(source)) endif endif endef # def_unit_qt4_target_pre_cpp_source ## # Invoked early in the processing of a target that uses the Qt unit. # # It will append the qt source handlers to the target (.h, .ui, .ts, # .png, .bmp, .gif). # # It will then check all the C++ sources and check which needs # a .moc files and generate rules and dependencies fofor these # define def_unit_qt4_target_pre # Make QTTOOL the default for the specific Qt tools instead of TOOL. ifneq ($($(target)_QTTOOL),) ifeq ($($(target)_MOCTOOL),) $(target)_MOCTOOL := $($(target)_QTTOOL) endif ifeq ($($(target)_UICTOOL),) $(target)_UICTOOL := $($(target)_QTTOOL) endif ifeq ($($(target)_RCCTOOL),) $(target)_RCCTOOL := $($(target)_QTTOOL) endif ifeq ($($(target)_LRCTOOL),) $(target)_LRCTOOL := $($(target)_QTTOOL) endif endif # Deal with QT_MODULES, QT_PREFIX and QT_INFIX. local qt_modules := \ $($(target)_QT_MODULES.$(bld_trg)) \ $($(target)_QT_MODULES.$(bld_trg_arch)) \ $($(target)_QT_MODULES.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_MODULES.$(bld_trg_cpu)) \ $($(target)_QT_MODULES.$(bld_type)) \ $($(target)_QT_MODULES) local qt_prefix := $(firstword \ $($(target)_QT_PREFIX.$(bld_trg)) \ $($(target)_QT_PREFIX.$(bld_trg_arch)) \ $($(target)_QT_PREFIX.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_PREFIX.$(bld_trg_cpu)) \ $($(target)_QT_PREFIX.$(bld_type)) \ $($(target)_QT_PREFIX)) local qt_infix := $(firstword \ $($(target)_QT_INFIX.$(bld_trg)) \ $($(target)_QT_INFIX.$(bld_trg_arch)) \ $($(target)_QT_INFIX.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_INFIX.$(bld_trg_cpu)) \ $($(target)_QT_INFIX.$(bld_type)) \ $($(target)_QT_INFIX)) ifeq ($(bld_trg),darwin) # Adding -F to CXXFLAGS is necessary to make #include stuff work... $(eval $(target)_CXXFLAGS += -F$(PATH_SDK_QT4_LIB) ) $(eval $(target)_OBJCXXFLAGS += -F$(PATH_SDK_QT4_LIB) ) $(eval $(target)_LDFLAGS += -F$(PATH_SDK_QT4_LIB) $(foreach module,$(qt_modules), -framework $(qt_prefix)Qt$(module)$(qt_infix)) ) $(eval $(target)_INCS += $(foreach module,$(qt_modules), $(PATH_SDK_QT4_LIB)/$(qt_prefix)Qt$(module)$(qt_infix).framework/Versions/4/Headers) ) else ifeq ($(bld_trg),win) $(eval $(target)_LIBS += $(foreach module,$(qt_modules), $(PATH_SDK_QT4_LIB)/$(qt_prefix)Qt$(module)$(qt_infix)4$(SUFF_LIB)) ) ifeq ($(tool_do),LINK_PROGRAM) $(eval $(target)_LIBS += $(PATH_SDK_QT4_LIB)/$(qt_prefix)qtmain$(qt_infix)$(SUFF_LIB) ) endif else $(eval $(target)_LIBS += $(foreach module,$(qt_modules), $(PATH_SDK_QT4_LIB)/lib$(qt_prefix)Qt$(module)$(qt_infix)$(SUFF_DLL)) ) endif $(eval $(target)_INCS += $(addprefix $(PATH_SDK_QT4_INC)/Qt,$(qt_modules)) $(PATH_SDK_QT4_INC) ) endif $(eval $(target)_DEFS += $(foreach module,$(toupper $(qt_modules)), QT_$(module)_LIB) ) # Autodetect source files with Q_OBJECT references if QT_MOCSRCS is undefined. (slow) # Tip: Use target_QT_MOCSRCS = $(NO_SUCH_VARIABLE) to avoid this. ifndef $(target)_QT_MOCSRCS $(foreach source, $(filter %.cxx %.CXX %.cpp %.CPP %.cc %.CC,\ $($(target)_SOURCES.$(bld_trg)) \ $($(target)_SOURCES.$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SOURCES.$(bld_trg_cpu)) \ $($(target)_SOURCES.$(bld_type)) \ $($(target)_SOURCES) \ ), $(evalval def_unit_qt4_target_pre_cpp_source)) endif # Install source handlers for .ui files. $(target)_SRC_HANDLERS += \ .ui:def_unit_qt4_src_handler_ui \ .UI:def_unit_qt4_src_handler_ui \ .qrc:def_unit_qt4_src_handler_qrc \ .qrc:def_unit_qt4_src_handler_qrc # Calc the MOC and UI output directories and add them to BLDDIRS and INCS. local qtmocdir := $($(target)_0_OUTDIR)/qtmoc local qtuicdir := $($(target)_0_OUTDIR)/qtuic local qtrccdir := $($(target)_0_OUTDIR)/qtrcc local qtnlsdir := $($(target)_0_OUTDIR)/qtnls $(eval $(target)_BLDDIRS += $(qtmocdir) $(qtuicdir) $(qtrccdir) $(qtnlsdir)) $(eval $(target)_INCS += $(qtmocdir) $(qtuicdir)) # Deal with QT_MOCSRCS. $(foreach source, \ $($(target)_QT_MOCSRCS.$(bld_trg)) \ $($(target)_QT_MOCSRCS.$(bld_trg_arch)) \ $($(target)_QT_MOCSRCS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_MOCSRCS.$(bld_trg_cpu)) \ $($(target)_QT_MOCSRCS.$(bld_type)) \ $($(target)_QT_MOCSRCS) \ , $(evalvalctx def_unit_qt4_target_pre_handle_moc_src)) # Deal with QT_MOCHDRS. $(foreach source, \ $($(target)_QT_MOCHDRS.$(bld_trg)) \ $($(target)_QT_MOCHDRS.$(bld_trg_arch)) \ $($(target)_QT_MOCHDRS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_MOCHDRS.$(bld_trg_cpu)) \ $($(target)_QT_MOCHDRS.$(bld_type)) \ $($(target)_QT_MOCHDRS) \ , $(evalvalctx def_unit_qt4_target_pre_handle_moc_hdr)) # Deal with QT_TRANSLATIONS. # ASSUMES (_ALL_)INSTALLS is processed after the targets using this unit. local translations := \ $($(target)_QT_TRANSLATIONS.$(bld_trg)) \ $($(target)_QT_TRANSLATIONS.$(bld_trg_arch)) \ $($(target)_QT_TRANSLATIONS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_QT_TRANSLATIONS.$(bld_trg_cpu)) \ $($(target)_QT_TRANSLATIONS.$(bld_type)) \ $($(target)_QT_TRANSLATIONS) ifneq ($(strip $(translations)),) local expr := _ALL_INSTALLS_IMPLICIT += $(target)-inst-nls $(eval $(expr)) ifdef $(target)_QT_TRANSLATIONS_TEMPLATE $(target)-inst-nls_TEMPLATE := $($(target)_QT_TRANSLATIONS_TEMPLATE) else $(target)-inst-nls_MODE := 0644 endif ifdef $(target)_QT_TRANSLATIONS_INST $(target)-inst-nls_INST := $($(target)_QT_TRANSLATIONS_INST) endif $(target)-inst-nls_SOURCES := $(foreach source, $(translations)\ , $(evalvalctx def_unit_qt4_target_pre_handle_translation)) endif endef # def_unit_qt4_target_pre # # Rule for debugging. # unit-qt4-show-vars: @$(ECHO) 'The Qt4 SDK variables:' @$(ECHO) ' PATH_SDK_QT4 = "$(PATH_SDK_QT4)"' @$(ECHO) ' PATH_SDK_QT4_INC = "$(PATH_SDK_QT4_INC)"' @$(ECHO) ' PATH_SDK_QT4_LIB = "$(PATH_SDK_QT4_LIB)"' @$(ECHO) ' PATH_SDK_QT4_LIB.amd64 = "$(PATH_SDK_QT4_LIB.amd64)"' @$(ECHO) ' PATH_SDK_QT4_LIB.x86 = "$(PATH_SDK_QT4_LIB.x86)"' @$(ECHO) 'The Qt4 TOOL variables:' @$(ECHO) ' PATH_TOOL_QT4_BIN = "$(PATH_TOOL_QT4_BIN)"' @$(ECHO) ' TOOL_QT4_BIN_SUFF = "$(TOOL_QT4_BIN_SUFF)"' @$(ECHO) ' TOOL_QT4_MOC = "$(TOOL_QT4_MOC)"' @$(ECHO) ' TOOL_QT4_UIC = "$(TOOL_QT4_UIC)"' @$(ECHO) ' TOOL_QT4_RCC = "$(TOOL_QT4_RCC)"' @$(ECHO) ' TOOL_QT4_LRC = "$(TOOL_QT4_LRC)"' @$(ECHO) ' TOOL_QT4_LUPDATE = "$(TOOL_QT4_LUPDATE)"' kbuild-2695/kBuild/templates/0000755000000000000000000000000012247157310014643 5ustar rootrootkbuild-2695/kBuild/templates/DUMMY.kmk0000644000000000000000000000244412247157310016246 0ustar rootroot# $Id: DUMMY.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Template Config - Empty dummy template. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TEMPLATE_DUMMY = Empty dummy template kbuild-2695/kBuild/msgstyles/0000755000000000000000000000000012247157310014677 5ustar rootrootkbuild-2695/kBuild/msgstyles/brief.kmk0000644000000000000000000001126412247157310016476 0ustar rootroot# $Id: brief.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Message Style - 'brief' # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # Indent the messages, drop the kBuild: prefix, and shorten paths. ifndef KBUILD_VERBOSE ifndef MSG_L1 MSG_L1 = @$(PRINTF) " %-7s %s\n" \ "$(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1))))" \ "$(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$2))))" endif else MSG_L1 ?= @$(ECHO) " $(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1 $2))))" MSG_L2 ?= @$(ECHO) " $(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1))))" endif ## Fetch starting. # @param 1 Target name. MSG_FETCH ?= $(call MSG_L1,FTCH,$1...) ## Re-fetch starting. # @param 1 Target name. MSG_REFETCH ?= $(call MSG_L1,RFTCH,$1...) ## Downloading a fetch component. # @param 1 Target name. # @param 2 The source URL. # @param 3 The destination file name. MSG_FETCH_DL ?= $(call MSG_L1,GET,$1 - $2,=> $3) ## Checking a fetch component. # @param 1 Target name. # @param 2 The source URL. # @param 3 The destination file name. MSG_FETCH_CHK?= $(call MSG_L1,CHK,$1 - $3, ($2)) ## Unpacking a fetch component. # @param 1 Target name. # @param 2 The archive file name. # @param 3 The target directory. MSG_FETCH_UP ?= $(call MSG_L1,UNPK,$1 - $2,=> $3) ## Fetch completed. # @param 1 Target name. MSG_FETCH_OK ?= $(call MSG_L1,DONE,$1) ## Unfetch a fetch target. # @param 1 Target name. MSG_UNFETCH ?= $(call MSG_L1,RM,$1...) ## Compiling a source file. # @param 1 Target name. # @param 2 The source filename. # @param 3 The primary link output file name. # @param 4 The source type (CXX,C,AS,RC,++). MSG_COMPILE ?= $(call MSG_L1,$4,$1 - $2,=> $3) ## Tool # @param 1 The tool name (bin2c,...) # @param 2 Target name. # @param 3 The source filename. # @param 4 The primary output file name. MSG_TOOL ?= $(call MSG_L1,$1,$2 - $3,=> $4) ## Generate a file, typically a source file. # @param 1 Target name if applicable. # @param 2 Output file name. # @param 3 What it's generated from MSG_GENERATE ?= $(call MSG_L1,GEN,$2) ## Linking a bldprog/dll/program/sysmod target. # @param 1 Target name. # @param 2 The primary link output file name. # @param 3 The link tool operation (LINK_LIBRARY,LINK_PROGRAM,LINK_DLL,LINK_SYSMOD,++). MSG_LINK ?= $(call MSG_L1,$(if $(eq $3,LINK_LIBRARY),AR,LD),$1,=> $2) ## Merging a library into the target (during library linking). # @param 1 Target name. # @param 2 The output library name. # @param 3 The input library name. MSG_AR_MERGE ?= $(NO_SUCH_VARIABLE) ## Creating a directory (build). # @param 1 Directory name. MSG_MKDIR ?= $(call MSG_L2,DIR,$1) ## Cleaning. MSG_CLEAN ?= $(call MSG_L1,CLEAN) ## Nothing. MSG_NOTHING ?= $(call MSG_L1,NOTHING $(CURDIR)) ## Installing a bldprog/lib/dll/program/sysmod target. # @param 1 Target name. # @param 2 The source filename. # @param 3 The destination file name. MSG_INST_TRG ?= $(call MSG_L1,INST,$1 => $3) ## Installing a file (install target). # @param 1 The source filename. # @param 2 The destination filename. MSG_INST_FILE?= $(call MSG_L1,IFIL,$2,(<= $1)) ## Installing a symlink. # @param 1 Symlink # @param 2 Link target MSG_INST_SYM ?= $(call MSG_L1,ISYM,$1,=> $2) ## Installing a directory. # @param 1 Directory name. MSG_INST_DIR ?= $(call MSG_L1,IDIR,$1) kbuild-2695/kBuild/msgstyles/brief2.kmk0000644000000000000000000001143712247157310016562 0ustar rootroot# $Id: brief2.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Message Style - 'brief' # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # # Indent the messages, drop the kBuild: prefix, and shorten paths. ifndef KBUILD_VERBOSE ifndef MSG_L1 MSG_L1 = @$(PRINTF) " %-7s %s\n" \ "$(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1))))" \ "$(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$2))))" endif ifndef MSG_L1I MSG_L1I = @$(PRINTF) " %-7s %s\n" "$1" "$2" endif else MSG_L1 ?= @$(ECHO) " $(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1 $2))))" MSG_L1I?= @$(ECHO) " $1 $2" MSG_L2 ?= @$(ECHO) " $(subst $(PATH_ROOT)/,{R}/,$(subst $(PATH_OUT)/,{O}/,$(subst $(CURDIR)/,{C}/,$(subst $(PATH_TARGET)/,{T}/,$1))))" endif ## Fetch starting. # @param 1 Target name. MSG_FETCH ?= $(call MSG_L1,FTCH,$1...) ## Re-fetch starting. # @param 1 Target name. MSG_REFETCH ?= $(call MSG_L1,RFTCH,$1...) ## Downloading a fetch component. # @param 1 Target name. # @param 2 The source URL. # @param 3 The destination file name. MSG_FETCH_DL ?= $(call MSG_L1,GET,$1 - $2,=> $3) ## Checking a fetch component. # @param 1 Target name. # @param 2 The source URL. # @param 3 The destination file name. MSG_FETCH_CHK?= $(call MSG_L1,CHK,$1 - $3, ($2)) ## Unpacking a fetch component. # @param 1 Target name. # @param 2 The archive file name. # @param 3 The target directory. MSG_FETCH_UP ?= $(call MSG_L1,UNPK,$1 - $2,=> $3) ## Fetch completed. # @param 1 Target name. MSG_FETCH_OK ?= $(call MSG_L1,DONE,$1) ## Unfetch a fetch target. # @param 1 Target name. MSG_UNFETCH ?= $(call MSG_L1,RM,$1...) ## Compiling a source file. # @param 1 Target name. # @param 2 The source filename. # @param 3 The primary link output file name. # @param 4 The source type (CXX,C,AS,RC,++). MSG_COMPILE ?= $(call MSG_L1,$4,$1 - $2,=> $3) ## Tool # @param 1 The tool name (bin2c,...) # @param 2 Target name. # @param 3 The source filename. # @param 4 The primary output file name. MSG_TOOL ?= $(call MSG_L1,$1,$2 - $3,=> $4) ## Generate a file, typically a source file. # @param 1 Target name if applicable. # @param 2 Output file name. # @param 3 What it's generated from MSG_GENERATE ?= $(call MSG_L1,GEN,$2) ## Linking a bldprog/dll/program/sysmod target. # @param 1 Target name. # @param 2 The primary link output file name. # @param 3 The link tool operation (LINK_LIBRARY,LINK_PROGRAM,LINK_DLL,LINK_SYSMOD,++). MSG_LINK ?= $(call MSG_L1I,$(if $(eq $3,LINK_LIBRARY),AR,LD),$1 => $2,) ## Merging a library into the target (during library linking). # @param 1 Target name. # @param 2 The output library name. # @param 3 The input library name. MSG_AR_MERGE ?= $(NO_SUCH_VARIABLE) ## Creating a directory (build). # @param 1 Directory name. MSG_MKDIR ?= $(call MSG_L2,DIR,$1) ## Cleaning. MSG_CLEAN ?= $(call MSG_L1,CLEAN) ## Nothing. MSG_NOTHING ?= $(call MSG_L1,NOTHING $(CURDIR)) ## Installing a bldprog/lib/dll/program/sysmod target. # @param 1 Target name. # @param 2 The source filename. # @param 3 The destination file name. MSG_INST_TRG ?= $(call MSG_L1I,INST,$1 => $3) ## Installing a file (install target). # @param 1 The source filename. # @param 2 The destination filename. MSG_INST_FILE?= $(call MSG_L1I,IFIL,$2,(<= $1)) ## Installing a symlink. # @param 1 Symlink # @param 2 Link target MSG_INST_SYM ?= $(call MSG_L1I,ISYM,$1,=> $2) ## Installing a directory. # @param 1 Directory name. MSG_INST_DIR ?= $(call MSG_L1I,IDIR,$1) kbuild-2695/kBuild/env.sh0000755000000000000000000004455112247157310014005 0ustar rootroot#!/bin/sh # $Id: env.sh 2546 2011-10-01 19:49:54Z bird $ ## @file # Environment setup script. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # #set -x # # Check if we're in eval mode or not. # ERR_REDIR=1 DBG_REDIR=1 EVAL_OPT= EVAL_EXPORT="export " DBG_OPT= QUIET_OPT= FULL_OPT= FULL_WITH_BIN_OPT= LEGACY_OPT= VAR_OPT= VALUE_ONLY_OPT= EXP_TYPE_OPT= while test $# -gt 0; do case "$1" in "--debug-script") DBG_OPT="true" ;; "--no-debug-script") DBG_OPT= ;; "--quiet") QUIET_OPT="true" ;; "--verbose") QUIET_OPT= ;; "--full") FULL_OPT="true" ;; "--full-with-bin") FULL_OPT="true" FULL_WITH_BIN_OPT="true" ;; "--normal") FULL_OPT= ;; "--legacy") LEGACY_OPT="true" ;; "--no-legacy") LEGACY_OPT= ;; "--eval") EVAL_OPT="true" ERR_REDIR=2 DBG_REDIR=2 ;; "--set") EVAL_OPT="true" EVAL_EXPORT="" ERR_REDIR=2 DBG_REDIR=2 ;; "--var") shift VAR_OPT="${VAR_OPT} $1" ERR_REDIR=2 DBG_REDIR=2 ;; "--value-only") VALUE_ONLY_OPT="true" ;; "--name-and-value") VALUE_ONLY_OPT= ;; "--release") EXP_TYPE_OPT=1 KBUILD_TYPE=release BUILD_TYPE= ;; "--debug") EXP_TYPE_OPT=1 KBUILD_TYPE=debug BUILD_TYPE= ;; "--profile") EXP_TYPE_OPT=1 KBUILD_TYPE=profile BUILD_TYPE= ;; "--help") echo "kBuild Environment Setup Script, v0.2.0-pre" echo "" echo "syntax: $0 [options] [command [args]]" echo " or: $0 [options] --var " echo " or: $0 [options] --eval" echo " or: $0 [options] --eval --var " echo "" echo "The first form will execute the command, or if no command is given start" echo "an interactive shell." echo "The second form will print the specfified variable(s)." echo "The third form will print all exported variables suitable for bourne shell" echo "evaluation." echo "The forth form will only print the specified variable(s)." echo "" echo "Options:" echo " --debug, --release, --profile" echo " Alternative way of specifying KBUILD_TYPE." echo " --debug-script, --no-debug-script" echo " Controls debug output. Default: --no-debug-script" echo " --quiet, --verbose" echo " Controls informational output. Default: --verbose" echo " --full, --full-with-bin, --normal" echo " Controls the variable set. Default: --normal" echo " --legacy, --no-legacy" echo " Include legacy variables in result. Default: --no-legacy" echo " --value-only, --name-and-value" echo " Controls what the result of a --var query. Default: --name-and-value" echo " --set, --export" echo " Whether --eval explicitly export the variables. --set is useful for" echo " getting a list of environment vars for a commandline, while --eval" echo ' is useful for eval `env.sh`. Default: --export' echo "" exit 1 ;; *) break ;; esac shift done # # Deal with legacy environment variables. # if test -n "$PATH_KBUILD"; then if test -n "$KBUILD_PATH" -a "$KBUILD_PATH" != "$PATH_KBUILD"; then echo "$0: error: KBUILD_PATH ($KBUILD_PATH) and PATH_KBUILD ($PATH_KBUILD) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_PATH=$PATH_KBUILD fi if test -n "$PATH_KBUILD_BIN"; then if test -n "$KBUILD_BIN_PATH" -a "$KBUILD_BIN_PATH" != "$PATH_KBUILD_BIN"; then echo "$0: error: KBUILD_BIN_PATH ($KBUILD_BIN_PATH) and PATH_KBUILD_BIN ($PATH_KBUILD_BIN) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_BIN_PATH=$PATH_KBUILD_BIN fi if test -n "$BUILD_TYPE"; then if test -n "$KBUILD_TYPE" -a "$KBUILD_TYPE" != "$BUILD_TYPE"; then echo "$0: error: KBUILD_TYPE ($KBUILD_TYPE) and BUILD_TYPE ($BUILD_TYPE) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_TYPE=$BUILD_TYPE fi if test -n "$BUILD_PLATFORM"; then if test -n "$KBUILD_HOST" -a "$KBUILD_HOST" != "$BUILD_PLATFORM"; then echo "$0: error: KBUILD_HOST ($KBUILD_HOST) and BUILD_PLATFORM ($BUILD_PLATFORM) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_HOST=$BUILD_PLATFORM fi if test -n "$BUILD_PLATFORM_ARCH"; then if test -n "$KBUILD_HOST_ARCH" -a "$KBUILD_HOST_ARCH" != "$BUILD_PLATFORM_ARCH"; then echo "$0: error: KBUILD_HOST_ARCH ($KBUILD_HOST_ARCH) and BUILD_PLATFORM_ARCH ($BUILD_PLATFORM_ARCH) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_HOST_ARCH=$BUILD_PLATFORM_ARCH fi if test -n "$BUILD_PLATFORM_CPU"; then if test -n "$KBUILD_HOST_CPU" -a "$KBUILD_HOST_CPU" != "$BUILD_PLATFORM_CPU"; then echo "$0: error: KBUILD_HOST_CPU ($KBUILD_HOST_CPU) and BUILD_PLATFORM_CPU ($BUILD_PLATFORM_CPU) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_HOST_CPU=$BUILD_PLATFORM_CPU fi if test -n "$BUILD_TARGET"; then if test -n "$KBUILD_TARGET" -a "$KBUILD_TARGET" != "$BUILD_TARGET"; then echo "$0: error: KBUILD_TARGET ($KBUILD_TARGET) and BUILD_TARGET ($BUILD_TARGET) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_TARGET=$BUILD_TARGET fi if test -n "$BUILD_TARGET_ARCH"; then if test -n "$KBUILD_TARGET_ARCH" -a "$KBUILD_TARGET_ARCH" != "$BUILD_TARGET_ARCH"; then echo "$0: error: KBUILD_TARGET_ARCH ($KBUILD_TARGET_ARCH) and BUILD_TARGET_ARCH ($BUILD_TARGET_ARCH) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_TARGET_ARCH=$BUILD_TARGET_ARCH fi if test -n "$BUILD_TARGET_CPU"; then if test -n "$KBUILD_TARGET_CPU" -a "$KBUILD_TARGET_CPU" != "$BUILD_TARGET_CPU"; then echo "$0: error: KBUILD_TARGET_CPU ($KBUILD_TARGET_CPU) and BUILD_TARGET_CPU ($BUILD_TARGET_CPU) disagree." 1>&${ERR_REDIR} sleep 1 exit 1 fi KBUILD_TARGET_CPU=$BUILD_TARGET_CPU fi # # Set default build type. # if test -z "$KBUILD_TYPE"; then KBUILD_TYPE=release fi test -n "$DBG_OPT" && echo "dbg: KBUILD_TYPE=$KBUILD_TYPE" 1>&${DBG_REDIR} # # Determin the host platform. # # The CPU isn't important, only the other two are. But, since the cpu, # arch and platform (and build type) share a common key space, try make # sure any new additions are unique. (See header.kmk, KBUILD_OSES/ARCHES.) # if test -z "$KBUILD_HOST"; then KBUILD_HOST=`uname` case "$KBUILD_HOST" in Darwin|darwin) KBUILD_HOST=darwin ;; DragonFly) KBUILD_HOST=dragonfly ;; freebsd|FreeBSD|FREEBSD) KBUILD_HOST=freebsd ;; Haiku) KBUILD_HOST=haiku ;; linux|Linux|GNU/Linux|LINUX) KBUILD_HOST=linux ;; netbsd|NetBSD|NETBSD) KBUILD_HOST=netbsd ;; openbsd|OpenBSD|OPENBSD) KBUILD_HOST=openbsd ;; os2|OS/2|OS2) KBUILD_HOST=os2 ;; SunOS) KBUILD_HOST=solaris ;; WindowsNT|CYGWIN_NT-*) KBUILD_HOST=win ;; *) echo "$0: unknown os $KBUILD_HOST" 1>&${ERR_REDIR} sleep 1 exit 1 ;; esac fi test -n "$DBG_OPT" && echo "dbg: KBUILD_HOST=$KBUILD_HOST" 1>&${DBG_REDIR} if test -z "$KBUILD_HOST_ARCH"; then # Try deduce it from the cpu if given. if test -n "$KBUILD_HOST_CPU"; then case "$KBUILD_HOST_CPU" in i[3456789]86) KBUILD_HOST_ARCH='x86' ;; k8|k8l|k9|k10) KBUILD_HOST_ARCH='amd64' ;; esac fi fi if test -z "$KBUILD_HOST_ARCH"; then # Use uname -m or isainfo (lots of guesses here, please help clean this up...) if test "$KBUILD_HOST" = "solaris"; then KBUILD_HOST_ARCH=`isainfo | cut -f 1 -d ' '` else KBUILD_HOST_ARCH=`uname -m` fi case "$KBUILD_HOST_ARCH" in x86_64|AMD64|amd64|k8|k8l|k9|k10) KBUILD_HOST_ARCH='amd64' ;; x86|i86pc|ia32|i[3456789]86|BePC) KBUILD_HOST_ARCH='x86' ;; sparc32|sparc|sparcv8|sparcv7|sparcv8e) KBUILD_HOST_ARCH='sparc32' ;; sparc64|sparcv9) KBUILD_HOST_ARCH='sparc64' ;; s390) KBUILD_HOST_ARCH='s390' ;; s390x) KBUILD_HOST_ARCH='s390x' ;; ppc32|ppc|powerpc) KBUILD_HOST_ARCH='ppc32' ;; ppc64|powerpc64) KBUILD_HOST_ARCH='ppc64' ;; mips32|mips) KBUILD_HOST_ARCH='mips32' ;; mips64) KBUILD_HOST_ARCH='mips64' ;; ia64) KBUILD_HOST_ARCH='ia64' ;; hppa32|parisc32|parisc) KBUILD_HOST_ARCH='hppa32' ;; hppa64|parisc64) KBUILD_HOST_ARCH='hppa64' ;; arm|armv4l|armv5tel|armv5tejl) KBUILD_HOST_ARCH='arm' ;; alpha) KBUILD_HOST_ARCH='alpha' ;; *) echo "$0: unknown cpu/arch - $KBUILD_HOST_ARCH" 1>&${ERR_REDIR} sleep 1 exit 1 ;; esac fi test -n "$DBG_OPT" && echo "dbg: KBUILD_HOST_ARCH=$KBUILD_HOST_ARCH" 1>&${DBG_REDIR} if test -z "$KBUILD_HOST_CPU"; then KBUILD_HOST_CPU="blend" fi test -n "$DBG_OPT" && echo "dbg: KBUILD_HOST_CPU=$KBUILD_HOST_CPU" 1>&${DBG_REDIR} # # The target platform. # Defaults to the host when not specified. # if test -z "$KBUILD_TARGET"; then KBUILD_TARGET="$KBUILD_HOST" fi test -n "$DBG_OPT" && echo "dbg: KBUILD_TARGET=$KBUILD_TARGET" 1>&${DBG_REDIR} if test -z "$KBUILD_TARGET_ARCH"; then KBUILD_TARGET_ARCH="$KBUILD_HOST_ARCH" fi test -n "$DBG_OPT" && echo "dbg: KBUILD_TARGET_ARCH=$KBUILD_TARGET_ARCH" 1>&${DBG_REDIR} if test -z "$KBUILD_TARGET_CPU"; then if test "$KBUILD_TARGET_ARCH" = "$KBUILD_HOST_ARCH"; then KBUILD_TARGET_CPU="$KBUILD_HOST_CPU" else KBUILD_TARGET_CPU="blend" fi fi test -n "$DBG_OPT" && echo "dbg: KBUILD_TARGET_CPU=$KBUILD_TARGET_CPU" 1>&${DBG_REDIR} # # Determin executable extension and path separator. # _SUFF_EXE= _PATH_SEP=":" case "$KBUILD_HOST" in os2|win|nt) _SUFF_EXE=".exe" _PATH_SEP=";" ;; esac # # Determin KBUILD_PATH from the script location and calc KBUILD_BIN_PATH from there. # if test -z "$KBUILD_PATH"; then KBUILD_PATH=`dirname "$0"` KBUILD_PATH=`cd "$KBUILD_PATH" ; /bin/pwd` fi if test ! -f "$KBUILD_PATH/footer.kmk" -o ! -f "$KBUILD_PATH/header.kmk" -o ! -f "$KBUILD_PATH/rules.kmk"; then echo "$0: error: KBUILD_PATH ($KBUILD_PATH) is not pointing to a popluated kBuild directory." 1>&${ERR_REDIR} sleep 1 exit 1 fi test -n "$DBG_OPT" && echo "dbg: KBUILD_PATH=$KBUILD_PATH" 1>&${DBG_REDIR} if test -z "$KBUILD_BIN_PATH"; then KBUILD_BIN_PATH="${KBUILD_PATH}/bin/${KBUILD_HOST}.${KBUILD_HOST_ARCH}" fi test -n "$DBG_OPT" && echo "dbg: KBUILD_BIN_PATH=${KBUILD_BIN_PATH}" 1>&${DBG_REDIR} # # Add the bin/x.y/ directory to the PATH. # NOTE! Once bootstrapped this is the only thing that is actually necessary. # PATH="${KBUILD_BIN_PATH}${_PATH_SEP}$PATH" test -n "$DBG_OPT" && echo "dbg: PATH=$PATH" 1>&${DBG_REDIR} # # Sanity and x bits. # if test ! -d "${KBUILD_BIN_PATH}/"; then echo "$0: warning: The bin directory for this platform doesn't exist. (${KBUILD_BIN_PATH}/)" 1>&${ERR_REDIR} else for prog in kmk kDepPre kDepIDB kmk_append kmk_ash kmk_cat kmk_cp kmk_echo kmk_install kmk_ln kmk_mkdir kmk_mv kmk_rm kmk_rmdir kmk_sed; do chmod a+x ${KBUILD_BIN_PATH}/${prog} > /dev/null 2>&1 if test ! -f "${KBUILD_BIN_PATH}/${prog}${_SUFF_EXE}"; then echo "$0: warning: The ${prog} program doesn't exist for this platform. (${KBUILD_BIN_PATH}/${prog}${_SUFF_EXE})" 1>&${ERR_REDIR} fi done fi # # The environment is in place, now take the requested action. # MY_RC=0 if test -n "${VAR_OPT}"; then # Echo variable values or variable export statements. for var in ${VAR_OPT}; do val= case "$var" in PATH) val=$PATH ;; KBUILD_PATH) val=$KBUILD_PATH ;; KBUILD_BIN_PATH) val=$KBUILD_BIN_PATH ;; KBUILD_HOST) val=$KBUILD_HOST ;; KBUILD_HOST_ARCH) val=$KBUILD_HOST_ARCH ;; KBUILD_HOST_CPU) val=$KBUILD_HOST_CPU ;; KBUILD_TARGET) val=$KBUILD_TARGET ;; KBUILD_TARGET_ARCH) val=$KBUILD_TARGET_ARCH ;; KBUILD_TARGET_CPU) val=$KBUILD_TARGET_CPU ;; KBUILD_TYPE) val=$KBUILD_TYPE ;; *) echo "$0: error: Unknown variable $var specified in --var request." 1>&${ERR_REDIR} sleep 1 exit 1 ;; esac if test -n "$EVAL_OPT"; then echo "${EVAL_EXPORT} $var=$val" else if test -n "$VALUE_ONLY_OPT"; then echo "$val" else echo "$var=$val" fi fi done else if test -n "$EVAL_OPT"; then # Echo statements for the shell to evaluate. test -n "$DBG_OPT" && echo "dbg: echoing exported variables" 1>&${DBG_REDIR} echo "${EVAL_EXPORT} PATH=${PATH}" test -n "${FULL_OPT}" -o "${EXP_TYPE_OPT}" && echo "${EVAL_EXPORT} KBUILD_TYPE=${KBUILD_TYPE}" if test -n "${FULL_OPT}"; then echo "${EVAL_EXPORT} KBUILD_PATH=${KBUILD_PATH}" if test -n "{FULL_WITH_BIN_OPT}"; then echo "${EVAL_EXPORT} KBUILD_BIN_PATH=${KBUILD_BIN_PATH}" fi echo "${EVAL_EXPORT} KBUILD_HOST=${KBUILD_HOST}" echo "${EVAL_EXPORT} KBUILD_HOST_ARCH=${KBUILD_HOST_ARCH}" echo "${EVAL_EXPORT} KBUILD_HOST_CPU=${KBUILD_HOST_CPU}" echo "${EVAL_EXPORT} KBUILD_TARGET=${KBUILD_TARGET}" echo "${EVAL_EXPORT} KBUILD_TARGET_ARCH=${KBUILD_TARGET_ARCH}" echo "${EVAL_EXPORT} KBUILD_TARGET_CPU=${KBUILD_TARGET_CPU}" if test -n "${LEGACY_OPT}"; then echo "${EVAL_EXPORT} PATH_KBUILD=${KBUILD_PATH}" if test -n "${FULL_WITH_BIN_OPT}"; then echo "${EVAL_EXPORT} PATH_KBUILD_BIN=${KBUILD_PATH_BIN}" fi echo "${EVAL_EXPORT} BUILD_TYPE=${KBUILD_TYPE}" echo "${EVAL_EXPORT} BUILD_PLATFORM=${KBUILD_HOST}" echo "${EVAL_EXPORT} BUILD_PLATFORM_ARCH=${KBUILD_HOST_ARCH}" echo "${EVAL_EXPORT} BUILD_PLATFORM_CPU=${KBUILD_HOST_CPU}" echo "${EVAL_EXPORT} BUILD_TARGET=${KBUILD_TARGET}" echo "${EVAL_EXPORT} BUILD_TARGET_ARCH=${KBUILD_TARGET_ARCH}" echo "${EVAL_EXPORT} BUILD_TARGET_CPU=${KBUILD_TARGET_CPU}" fi fi else # Export variables. export PATH test -n "${FULL_OPT}" -o "${EXP_TYPE_OPT}" && export KBUILD_TYPE if test -n "${FULL_OPT}"; then export KBUILD_PATH if test -n "${FULL_WITH_BIN_OPT}"; then export KBUILD_BIN_PATH fi export KBUILD_HOST export KBUILD_HOST_ARCH export KBUILD_HOST_CPU export KBUILD_TARGET export KBUILD_TARGET_ARCH export KBUILD_TARGET_CPU if test -n "${LEGACY_OPT}"; then export PATH_KBUILD=$KBUILD_PATH if test -n "${FULL_WITH_BIN_OPT}"; then export PATH_KBUILD_BIN=$KBUILD_BIN_PATH fi export BUILD_TYPE=$KBUILD_TYPE export BUILD_PLATFORM=$KBUILD_HOST export BUILD_PLATFORM_ARCH=$KBUILD_HOST_ARCH export BUILD_PLATFORM_CPU=$KBUILD_HOST_CPU export BUILD_TARGET=$KBUILD_TARGET export BUILD_TARGET_ARCH=$KBUILD_TARGET_ARCH export BUILD_TARGET_CPU=$KBUILD_TARGET_CPU fi fi # Execute command or spawn shell. if test $# -eq 0; then test -z "${QUIET_OPT}" && echo "$0: info: Spawning work shell..." 1>&${ERR_REDIR} if test "$TERM" != 'dumb' -a -n "$BASH"; then export PS1='\[\033[01;32m\]\u@\h \[\033[01;34m\]\W \$ \[\033[00m\]' fi $SHELL -i MY_RC=$? else test -z "${QUIET_OPT}" && echo "$0: info: Executing command: $*" 1>&${ERR_REDIR} $* MY_RC=$? test -z "${QUIET_OPT}" -a "$MY_RC" -ne 0 && echo "$0: info: rc=$MY_RC: $*" 1>&${ERR_REDIR} fi fi fi test -n "$DBG_OPT" && echo "dbg: finished (rc=$MY_RC)" 1>&${DBG_REDIR} exit $MY_RC kbuild-2695/kBuild/tools/0000755000000000000000000000000012247157310014005 5ustar rootrootkbuild-2695/kBuild/tools/GCC64.kmk0000644000000000000000000003211512247157310015261 0ustar rootroot# $Id: GCC64.kmk 2541 2011-08-03 09:51:30Z bird $ ## @file # kBuild Tool Config - Generic 64-bit GCC v3.2.x or later Using The System GCC. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC64 := Generic 64-bit GCC v3.2.x or later Using The System GCC. \ More or less Linux/ELF specfic. # Tool Specific Properties TOOL_GCC64_CC ?= gcc$(HOSTSUFF_EXE) -m64 TOOL_GCC64_CXX ?= g++$(HOSTSUFF_EXE) -m64 TOOL_GCC64_AS ?= gcc$(HOSTSUFF_EXE) -m64 TOOL_GCC64_AR ?= ar$(HOSTSUFF_EXE) TOOL_GCC64_LD ?= gcc$(HOSTSUFF_EXE) -m64 TOOL_GCC64_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) ifndef TOOL_GCC64_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC64_LDFLAGS.dll ?= -shared else TOOL_GCC64_LDFLAGS.dll ?= $(TOOL_GCC64_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GCC64_LDFLAGS.sysmod ?= -r -m elf_x86_64$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,) TOOL_GCC64_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) ifeq ($(KBUILD_TARGET),os2) TOOL_GCC64_LD_MAP ?= -Zmap=$(1) else TOOL_GCC64_LD_MAP ?= endif ifeq ($(KBUILD_TARGET),os2) TOOL_GCC64_LD_SYSMOD_MAP ?= -Zmap=$(1) else TOOL_GCC64_LD_SYSMOD_MAP ?= endif if1of ($(KBUILD_HOST), solaris) TOOL_GCC64_OBJCOPY ?= gobjcopy$(HOSTSUFF_EXE) else TOOL_GCC64_OBJCOPY ?= objcopy$(HOSTSUFF_EXE) endif ifdef SLKRUNS TOOL_GCC64_CC += -fmessage-length=0 TOOL_GCC64_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GCC64_COBJSUFF ?= .o TOOL_GCC64_CFLAGS ?= TOOL_GCC64_CFLAGS.debug ?= -g TOOL_GCC64_CFLAGS.profile ?= -O2 #-g -pg TOOL_GCC64_CFLAGS.release ?= -O2 TOOL_GCC64_CINCS ?= TOOL_GCC64_CDEFS ?= TOOL_GCC64_CXXOBJSUFF ?= .o TOOL_GCC64_CXXOBJSUFF ?= .o TOOL_GCC64_CXXFLAGS ?= TOOL_GCC64_CXXFLAGS.debug ?= -g TOOL_GCC64_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GCC64_CXXFLAGS.release ?= -O2 TOOL_GCC64_CXXINCS ?= TOOL_GCC64_CXXDEFS ?= TOOL_GCC64_ASFLAGS ?= -x assembler-with-cpp TOOL_GCC64_ASFLAGS.debug ?= -g TOOL_GCC64_ASFLAGS.profile ?= -g TOOL_GCC64_ASOBJSUFF ?= .o TOOL_GCC64_ARFLAGS ?= cr TOOL_GCC64_ARLIBSUFF ?= .a TOOL_GCC64_LDFLAGS ?= TOOL_GCC64_LDFLAGS.debug ?= -g TOOL_GCC64_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC64_COMPILE_C_DEPEND = TOOL_GCC64_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC64_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GCC64_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GCC64_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GCC64_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC64_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC64_COMPILE_C_OUTPUT = define TOOL_GCC64_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC64_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC64_COMPILE_CXX_DEPEND = TOOL_GCC64_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC64_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GCC64_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GCC64_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC64_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC64_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC64_COMPILE_CXX_OUTPUT = define TOOL_GCC64_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC64_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC64_COMPILE_AS_OUTPUT = TOOL_GCC64_COMPILE_AS_DEPEND = TOOL_GCC64_COMPILE_AS_DEPORD = define TOOL_GCC64_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC64_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC64_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_GCC64_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GCC64_LINK_LIBRARY_DEPORD = define TOOL_GCC64_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(othersrc), 'ADDLIB $(o)') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GCC64_AR) -M endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC64_LINK_PROGRAM_OUTPUT = TOOL_GCC64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GCC64_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC64_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC64_LINK_PROGRAM_DEPORD = define TOOL_GCC64_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GCC64_LD) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC64_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC64_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC64_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC64_LINK_DLL_OUTPUT = TOOL_GCC64_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GCC64_LINK_DLL_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC64_LINK_DLL_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC64_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC64_LINK_DLL_DEPORD = define TOOL_GCC64_LINK_DLL_CMDS $(QUIET)$(TOOL_GCC64_LD) $(TOOL_GCC64_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GCC64_LD_SONAME,$(target),$(out)))\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC64_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC64_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC64_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC64_LINK_SYSMOD_OUTPUT = TOOL_GCC64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GCC64_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC64_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC64_LINK_SYSMOD_DEPORD = define TOOL_GCC64_LINK_SYSMOD_CMDS $(QUIET)$(TOOL_GCC64_LD_SYSMOD) $(TOOL_GCC64_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC64_LD_SYSMOD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC64_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC64_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef kbuild-2695/kBuild/tools/MASM6PLUS.kmk0000644000000000000000000000472512247157310016050 0ustar rootroot# $Id: MASM6PLUS.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - MASM v6 and later. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_MASM6PLUS := Microsoft Macro Assembler v6 and later. # Tool Specific Properties ifndef TOOL_MASM6PLUS_AS TOOL_MASM6PLUS_AS := $(firstword $(rsort $(wildcard \ $(PATH_DEVTOOLS_BLD)/masm/*/bin$(if $(eq $(KBUILD_HOST),os2),p,)/ml$(HOSTSUFF_EXE)\ ))) ifeq ($(TOOL_MASM6PLUS_AS),) TOOL_MASM6PLUS_AS := $(firstword $(rsort $(wildcard \ $(PATH_DEVTOOLS_BLD)/vcc/*/bin/ml$(HOSTSUFF_EXE) \ ))) endif ifeq ($(TOOL_MASM6PLUS_AS),) TOOL_MASM6PLUS_AS := $(firstword $(rsort $(wildcard \ $(PATH_DEVTOOLS)/win.x86/vcc/*/bin/ml$(HOSTSUFF_EXE) \ ))) endif endif ifeq ($(TOOL_MASM6PLUS_AS),) TOOL_MASM6PLUS_AS := $(firstword $(which ml$(HOSTSUFF_EXE)) path/notfound/ml$(HOSTSUFF_EXE)) endif # General Properties used by kBuild TOOL_MASM6PLUS_ASFLAGS ?= /nologo TOOL_MASM6PLUS_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_MASM6PLUS_COMPILE_AS_DEPEND = TOOL_MASM6PLUS_COMPILE_AS_DEPORD = define TOOL_MASM6PLUS_COMPILE_AS_CMDS $(QUIET)$(REDIRECT) \ -E 'INCLUDE=$(subst $(SP),,$(addsuffix ;,$(subst /,\,$(incs))))' \ -E 'MASM=' -E 'ML=' \ -- \ $(subst /,\\,$(TOOL_MASM6PLUS_AS)) -c \ $(strip $(flags)) \ $(addprefix -D,$(defs)) \ -Fo$(subst /,\\,$(obj)) \ -Fl$(subst /,\\,$(outbase).lst) \ $(subst /,\\,$(source)) endef kbuild-2695/kBuild/tools/GCC.kmk0000644000000000000000000002113212247157310015104 0ustar rootroot# $Id: GCC.kmk 2545 2011-09-13 19:09:05Z bird $ ## @file # kBuild Tool Config - Generic GCC Using The System GCC. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC := Generic GCC Using The System GCC. # Tool Specific Properties TOOL_GCC_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GCC_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GCC_AS ?= gcc$(HOSTSUFF_EXE) TOOL_GCC_AR ?= ar$(HOSTSUFF_EXE) TOOL_GCC_RANLIB ?= ranlib$(HOSTSUFF_EXE) TOOL_GCC_LD ?= gcc$(HOSTSUFF_EXE) TOOL_GCC_LDFLAGS.dll.os2 ?= -Zdll TOOL_GCC_LDFLAGS.dll.darwin ?= -dynamiclib ifndef TOOL_GCC_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC_LDFLAGS.dll ?= -shared else TOOL_GCC_LDFLAGS.dll ?= $(TOOL_GCC_LDFLAGS.$(KBUILD_TARGET)) endif # General Properties used by kBuild TOOL_GCC_COBJSUFF ?= .o TOOL_GCC_CFLAGS ?= TOOL_GCC_CFLAGS.debug ?= -g TOOL_GCC_CFLAGS.profile ?= -g -O2 #-pg TOOL_GCC_CFLAGS.release ?= -O2 TOOL_GCC_CINCS ?= TOOL_GCC_CDEFS ?= TOOL_GCC_CXXOBJSUFF ?= .o TOOL_GCC_CXXOBJSUFF ?= .o TOOL_GCC_CXXFLAGS ?= TOOL_GCC_CXXFLAGS.debug ?= -g -O0 TOOL_GCC_CXXFLAGS.profile ?= -g -O2 #-pg TOOL_GCC_CXXFLAGS.release ?= -O2 TOOL_GCC_CXXINCS ?= TOOL_GCC_CXXDEFS ?= TOOL_GCC_ASFLAGS ?= -x assembler-with-cpp TOOL_GCC_ASFLAGS.debug ?= -g TOOL_GCC_ASFLAGS.profile ?= -g TOOL_GCC_ASOBJSUFF ?= .o TOOL_GCC_ARFLAGS ?= cr TOOL_GCC_ARLIBSUFF ?= .a TOOL_GCC_LDFLAGS ?= TOOL_GCC_LDFLAGS.debug ?= -g TOOL_GCC_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC_COMPILE_C_OUTPUT = TOOL_GCC_COMPILE_C_DEPEND = TOOL_GCC_COMPILE_C_DEPORD = define TOOL_GCC_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC_COMPILE_CXX_OUTPUT = TOOL_GCC_COMPILE_CXX_DEPEND = TOOL_GCC_COMPILE_CXX_DEPORD = define TOOL_GCC_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC_COMPILE_AS_OUTPUT = TOOL_GCC_COMPILE_AS_DEPEND = TOOL_GCC_COMPILE_AS_DEPORD = define TOOL_GCC_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC_LINK_LIBRARY_OUTPUT = TOOL_GCC_LINK_LIBRARY_DEPEND = TOOL_GCC_LINK_LIBRARY_DEPORD = define TOOL_GCC_LINK_LIBRARY_CMDS $(QUIET)$(TOOL_GCC_AR) $(flags) $(out) $(objs) $(call xargs,$(QUIET)$(TOOL_GCC_AR) $(flags) $(out),$(objs)) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GCC_AR) x $(abspath $(lib)) \ && $(TOOL_GCC_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) $(QUIET)$(TOOL_GCC_RANLIB) $(out) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC_LINK_PROGRAM_OUTPUT = TOOL_GCC_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC_LINK_PROGRAM_DEPORD = define TOOL_GCC_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GCC_LD) $(flags) -o $(out) $(objs) \ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC_LINK_DLL_OUTPUT = TOOL_GCC_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC_LINK_DLL_DEPORD = define TOOL_GCC_LINK_DLL_CMDS $(QUIET)$(TOOL_GCC_LD) $(TOOL_GCC_LDFLAGS.dll) $(flags) -o $(out) $(objs) \ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef kbuild-2695/kBuild/tools/OPENWATCOM-WL.kmk0000644000000000000000000001026612247157310016512 0ustar rootroot# $Id: OPENWATCOM-WL.kmk 2663 2012-10-15 13:13:45Z bird $ ## @file # kBuild Tool Config - Open Watcom v1.4 and later, using wlink. # # @remarks wrc is untested, so are DLLs, and programs. # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_OPENWATCOM-WL = Open Watcom v1.4 and later, using wlink. TOOL_OPENWATCOM-WL_EXTENDS = OPENWATCOM TOOL_OPENWATCOM-WL_LDFLAGS ?= Option Quiet TOOL_OPENWATCOM-WL_LDFLAGS.dos ?= $(NO_SUCH_VARIABLE) TOOL_OPENWATCOM-WL_LDFLAGS.linux ?= $(NO_SUCH_VARIABLE) TOOL_OPENWATCOM-WL_LDFLAGS.nt ?= $(NO_SUCH_VARIABLE) TOOL_OPENWATCOM-WL_LDFLAGS.os2 ?= $(NO_SUCH_VARIABLE) TOOL_OPENWATCOM-WL_LDFLAGS.win ?= $(NO_SUCH_VARIABLE) TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).sym TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPORD = define TOOL_OPENWATCOM-WL_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(if $(flags),'$(flags)',) \ 'Name $(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(out)$(if $(suffix $(out)),,.))' \ 'Option Map=$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(outbase)).map' \ $(foreach p,$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(libpath)),'LIBPath $p') \ $(foreach o,$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(filter-out %.res,$(objs)) $(othersrc)),'$(if $(filter %.lib %.a,$l),LIB,)File $o') \ $(foreach l,$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(libs)),'Library $l') $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_WLINK) @$(outbase).rsp $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter %.res,$(objs)))) endef TOOL_OPENWATCOM-WL_LINK_DLL_OUTPUT = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT) TOOL_OPENWATCOM-WL_LINK_DLL_OUTPUT_MAYBE = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT_MAYBE) TOOL_OPENWATCOM-WL_LINK_DLL_DEPEND = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPEND) TOOL_OPENWATCOM-WL_LINK_DLL_DEPORD = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPORD) TOOL_OPENWATCOM-WL_LINK_DLL_CMDS = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_CMDS) TOOL_OPENWATCOM-WL_LINK_SYSMOD_OUTPUT = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT) TOOL_OPENWATCOM-WL_LINK_SYSMOD_OUTPUT_MAYBE = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT_MAYBE) TOOL_OPENWATCOM-WL_LINK_SYSMOD_DEPEND = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPEND) TOOL_OPENWATCOM-WL_LINK_SYSMOD_DEPORD = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPORD) TOOL_OPENWATCOM-WL_LINK_SYSMOD_CMDS = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_CMDS) TOOL_OPENWATCOM-WL_LINK_MISCBIN_OUTPUT = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT) TOOL_OPENWATCOM-WL_LINK_MISCBIN_OUTPUT_MAYBE = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_OUTPUT_MAYBE) TOOL_OPENWATCOM-WL_LINK_MISCBIN_DEPEND = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPEND) TOOL_OPENWATCOM-WL_LINK_MISCBIN_DEPORD = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPORD) TOOL_OPENWATCOM-WL_LINK_MISCBIN_CMDS = $(TOOL_OPENWATCOM-WL_LINK_PROGRAM_CMDS) kbuild-2695/kBuild/tools/MASM610.kmk0000644000000000000000000000435612247157310015505 0ustar rootroot# $Id: MASM610.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - MASM v6.10 # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_MASM610 := Microsoft Macro Assembler v6.10 # Tool Specific Properties ifndef TOOL_MASM610_AS TOOL_MASM610_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/masm/v6.10*/binp/ml$(HOSTSUFF_EXE)))) ifeq ($(TOOL_MASM610_AS),) TOOL_MASM610_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/masm/v6.10*/binp/ml$(HOSTSUFF_EXE)))) endif endif ifeq ($(TOOL_MASM610_AS),) TOOL_MASM610_AS := $(firstword $(which ml$(HOSTSUFF_EXE)) path/notfound/ml$(HOSTSUFF_EXE)) endif # General Properties used by kBuild TOOL_MASM610_ASFLAGS ?= /nologo TOOL_MASM610_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_MASM610_COMPILE_AS_DEPEND = TOOL_MASM610_COMPILE_AS_DEPORD = define TOOL_MASM610_COMPILE_AS_CMDS $(QUIET)$(REDIRECT) \ -E 'INCLUDE=$(subst $(SP),,$(addsuffix ;,$(subst /,\,$(incs))))' \ -E 'MASM=' -E 'ML=' \ -- \ $(subst /,\\,$(TOOL_MASM610_AS)) -c \ $(strip $(flags)) \ $(addprefix -D,$(defs)) \ -Fo$(subst /,\\,$(obj)) \ -Fl$(subst /,\\,$(outbase).lst) \ $(subst /,\\,$(source)) endef kbuild-2695/kBuild/tools/VAC308.kmk0000644000000000000000000001703012247157310015356 0ustar rootroot# $Id: VAC308.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - VisualAge for C++ v3.08. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VAC308 := VisualAge for C++ v3.08 # Determin VAC308 location. ifndef PATH_TOOL_VAC308 PATH_TOOL_VAC308 := $(wildcard $(PATH_DEVTOOLS_BLD)/vac/v3.0.8*) ifeq ($(PATH_TOOL_VAC308),) PATH_TOOL_VAC308 := $(wildcard $(PATH_DEVTOOLS_BLD)/vac/v308*) endif ifeq ($(PATH_TOOL_VAC308),) PATH_TOOL_VAC308 := $(wildcard $(PATH_DEVTOOLS_TRG)/vac/v3.0.8*) ifeq ($(PATH_TOOL_VAC308),) PATH_TOOL_VAC308 := $(wildcard $(PATH_DEVTOOLS_TRG)/vac/v308*) endif endif ifeq ($(PATH_TOOL_VAC308),) PATH_TOOL_VAC308 := $(firstword $(rsort $(PATH_TOOL_VAC308))) endif # if not found, we'll enter 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_VAC308 := $(PATH_TOOL_VAC308) endif ifneq ($(PATH_TOOL_VAC308),) TOOL_VAC308_PATHLESS := PATH_TOOL_VAC308_BIN ?= $(PATH_TOOL_VAC308)/bin PATH_TOOL_VAC308_LIB ?= $(PATH_TOOL_VAC308)/lib PATH_TOOL_VAC308_INC ?= $(PATH_TOOL_VAC308)/include PATH_TOOL_VAC308_DLL ?= $(PATH_TOOL_VAC308)/dll PATH_TOOL_VAC308_HELP ?= $(PATH_TOOL_VAC308)/help PATH_TOOL_VAC308_LOCALE ?= $(PATH_TOOL_VAC308)/locale TOOL_VAC308_ENV_SETUP ?= $(REDIRECT) \ -E 'BEGINLIBPATH=$(PATH_TOOL_VAC308_DLL);$(BEGINLIBPATH)' \ -E 'DPATH=$(PATH_TOOL_VAC308_LOCALE);$(PATH_TOOL_VAC308_HELP);$(DPATH)' \ -E 'LIB=' \ -E 'INCLUDE=' \ -- TOOL_VAC308_CC ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE) TOOL_VAC308_CXX ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE) TOOL_VAC308_AR ?= $(PATH_TOOL_VAC308_BIN)/ilib$(HOSTSUFF_EXE) TOOL_VAC308_LD ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE) TOOL_VAC308_RC ?= $(PATH_TOOL_VAC308_BIN)/rc$(HOSTSUFF_EXE) else # Pathless, relies on the environment. TOOL_VAC308_PATHLESS := yes TOOL_VAC308_ENV_SETUP ?= $(REDIRECT) \ -E 'LIB=' \ -E 'INCLUDE=' \ -- TOOL_VAC308_CC ?= icc$(HOSTSUFF_EXE) TOOL_VAC308_CXX ?= icc$(HOSTSUFF_EXE) TOOL_VAC308_AR ?= ilib$(HOSTSUFF_EXE) TOOL_VAC308_LD ?= icc$(HOSTSUFF_EXE) TOOL_VAC308_RC ?= rc$(HOSTSUFF_EXE) endif # More tool specific properties. # Note: implib isn't really a part of VAC308. TOOL_VAC308_IMP ?= implib$(HOSTSUFF_EXE) TOOL_VAC308_IMPFLAGS ?= /nologo /noignorecase # General Properties used by kBuild TOOL_VAC308_COBJSUFF ?= .obj TOOL_VAC308_CFLAGS ?= -Q+ TOOL_VAC308_CFLAGS.debug ?= -Ti+ TOOL_VAC308_CFLAGS.release ?= -O TOOL_VAC308_CINCS ?= $(PATH_TOOL_VAC308_INC) TOOL_VAC308_CDEFS ?= TOOL_VAC308_CXXOBJSUFF ?= .obj TOOL_VAC308_CXXFLAGS ?= -Q+ TOOL_VAC308_CXXFLAGS.debug ?= -Ti TOOL_VAC308_CXXFLAGS.release ?= -O TOOL_VAC308_CXXINCS ?= $(PATH_TOOL_VAC308_INC) TOOL_VAC308_CXXDEFS ?= TOOL_VAC308_RCOBJSUFF ?= .res TOOL_VAC308_RCFLAGS ?= -n TOOL_VAC308_RCINCS ?= TOOL_VAC308_RCDEFS ?= TOOL_VAC308_ARFLAGS ?= /nologo /noignorecase TOOL_VAC308_ARLIBSUFF ?= .lib TOOL_VAC308_LDFLAGS ?= -Q+ TOOL_VAC308_LDFLAGS.debug ?= -Ti+ TOOL_VAC308_COMPILE_C_DEPEND = TOOL_VAC308_COMPILE_C_DEPORD = TOOL_VAC308_COMPILE_C_OUTPUT = define TOOL_VAC308_COMPILE_C_CMDS $(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fo$(obj)\ $(abspath $(source)) $(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CC) -P+ -Pd+ \ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(abspath $(source)) \ | $(DEP_PRE) -f -s -o $(dep) -t $(obj) - endef TOOL_VAC308_COMPILE_CXX_DEPEND = TOOL_VAC308_COMPILE_CXX_DEPORD = TOOL_VAC308_COMPILE_CXX_OUTPUT = define TOOL_VAC308_COMPILE_CXX_CMDS $(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fo$(obj)\ $(abspath $(source)) $(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CXX) -P+ -Pd+ \ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(abspath $(source)) \ | $(DEP_PRE) -f -s -o $(dep) -t $(obj) - endef TOOL_VAC308_COMPILE_RC_OUTPUT = TOOL_VAC308_COMPILE_RC_DEPEND = TOOL_VAC308_COMPILE_RC_DEPORD = define TOOL_VAC308_COMPILE_RC_CMDS $(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_RC) -r\ $(flags) $(addprefix -i, $(subst /,\\,$(incs))) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ $(obj) endef TOOL_VAC308_LINK_LIBRARY_OUTPUT = ## @todo $(outbase).rsp TOOL_VAC308_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VAC308_LINK_LIBRARY_DEPORD = define TOOL_VAC308_LINK_LIBRARY_CMDS $(if $(strip $(othersrc)),\ $(QUIET)$(call TOOL_VAC308_ENV_SETUP) \ $(TOOL_VAC308_IMP) $(TOOL_VAC308_IMPFLAGS) $(subst /,\\,$(out)) $(subst /,\\,$(othersrc)) ) $(if $(strip $(objs)),$(QUIET)$(call TOOL_VAC308_ENV_SETUP) \ $(TOOL_VAC308_AR) $(flags) $(subst /,\\,$(out)) $(foreach obj,$(subst /,\\,$(objs)),+"$(obj)") ";" ) endef TOOL_VAC308_LINK_PROGRAM_OUTPUT = $(outbase).map TOOL_VAC308_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VAC308_LINK_PROGRAM_DEPORD = define TOOL_VAC308_LINK_PROGRAM_CMDS $(QUIET)$(call TOOL_VAC308_ENV_SETUP,$(subst $(SP),;,$(libpath))) \ $(TOOL_VAC308_LD) $(flags) -Fe$(out) -Fm$(outbase).map $(filter-out %.res,$(objs)) $(libs) $(othersrc) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_VAC308_ENV_SETUP) \ $(TOOL_VAC308_RC) $(filter %.res,$(objs)) $(out)) endef TOOL_VAC308_LINK_DLL_OUTPUT = $(outbase).map TOOL_VAC308_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VAC308_LINK_DLL_DEPORD = define TOOL_VAC308_LINK_DLL_CMDS $(QUIET)$(call TOOL_VAC308_ENV_SETUP,$(subst $(SP),;,$(libpath))) \ $(TOOL_VAC308_LD) /B"/DLL" $(flags) -Fe$(out) -Fm$(outbase).map $(filter-out %.res,$(objs)) $(libs) $(othersrc) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_VAC308_ENV_SETUP) \ $(TOOL_VAC308_RC) $(filter %.res,$(objs)) $(out)) endef TOOL_VAC308_LINK_SYSMOD_OUTPUT = $(outbase).map TOOL_VAC308_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VAC308_LINK_SYSMOD_DEPORD = define TOOL_VAC308_LINK_SYSMOD_CMDS $(QUIET)$(call TOOL_VAC308_ENV_SETUP,$(subst $(SP),;,$(libpath))) \ $(TOOL_VAC308_LD) $(flags) -Fe$(out) -Fm$(outbase).map $(filter-out %.res,$(objs)) $(libs) $(othersrc) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_VAC308_ENV_SETUP) \ $(TOOL_VAC308_RC) $(filter %.res,$(objs)) $(out)) endef kbuild-2695/kBuild/tools/BISON.kmk0000644000000000000000000000320712247157310015365 0ustar rootroot# $Id: BISON.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # GNU bison tool # # # Copyright (c) 2009-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_BISON = GNU bison ifndef TOOL_BISON_YACC TOOL_BISON_YACC := bison$(HOSTSUFF_EXE) endif #TOOL_BISON_YACCFLAGS ?= TOOL_BISON_YACC_OUTPUT = $(evalcall KB_FN_OPT_TEST_SHORT_LONG,d,--defines,$(flags),$(outbase).h$(substr $(suffix $(source)),3),) TOOL_BISON_YACC_OUTPUT_MAYBE = TOOL_BISON_YACC_DEPEND = TOOL_BISON_YACC_DEPORD = define TOOL_BISON_YACC_CMDS $(QUIET)$(TOOL_BISON_YACC) $(flags) -o $(out) $(source) endef kbuild-2695/kBuild/tools/GXX4MACHO.kmk0000644000000000000000000004544112247157310016023 0ustar rootroot# $Id: GXX4MACHO.kmk 2547 2011-11-04 21:58:53Z bird $ ## @file # kBuild Tool Config - GCC v4 targeting Darwin (Mac OS X) Mach-O, for building C++ code. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX4MACHO := GCC v4 targeting Darwin (Mac OS X) Mach-O, for building C++ code. # Tool Specific Properties TOOL_GXX4MACHO_PREFIX ?= TOOL_GXX4MACHO_SUFFIX ?= $(HOSTSUFF_EXE) TOOL_GXX4MACHO_CC ?= $(TOOL_GXX4MACHO_PREFIX)gcc$(TOOL_GXX4MACHO_SUFFIX) TOOL_GXX4MACHO_CXX ?= $(TOOL_GXX4MACHO_PREFIX)g++$(TOOL_GXX4MACHO_SUFFIX) TOOL_GXX4MACHO_OBJC ?= $(TOOL_GXX4MACHO_PREFIX)gcc$(TOOL_GXX4MACHO_SUFFIX) TOOL_GXX4MACHO_OBJCXX ?= $(TOOL_GXX4MACHO_PREFIX)gcc$(TOOL_GXX4MACHO_SUFFIX) TOOL_GXX4MACHO_AS ?= $(TOOL_GXX4MACHO_PREFIX)gcc$(TOOL_GXX4MACHO_SUFFIX) TOOL_GXX4MACHO_LD ?= $(TOOL_GXX4MACHO_PREFIX)g++$(TOOL_GXX4MACHO_SUFFIX) TOOL_GXX4MACHO_LD_SYSMOD ?= $(TOOL_GXX4MACHO_PREFIX)g++$(TOOL_GXX4MACHO_SUFFIX) ifndef TOOL_GXX4MACHO_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX4MACHO_LDFLAGS.dll ?= -dynamiclib else TOOL_GXX4MACHO_LDFLAGS.dll ?= $(TOOL_GXX4MACHO_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GXX4MACHO_LDFLAGS.sysmod ?= -r #TOOL_GXX4MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_GXX4MACHO_DSYMUTIL ?= dsymutil ifdef SLKRUNS TOOL_GXX4MACHO_CC += -fmessage-length=0 TOOL_GXX4MACHO_CXX += -fmessage-length=0 TOOL_GXX4MACHO_OBJC += -fmessage-length=0 TOOL_GXX4MACHO_OBJCXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GXX4MACHO_COBJSUFF ?= .o TOOL_GXX4MACHO_CFLAGS ?= TOOL_GXX4MACHO_CFLAGS.debug ?= -g TOOL_GXX4MACHO_CFLAGS.profile ?= -O2 #-g -pg TOOL_GXX4MACHO_CFLAGS.release ?= -O2 TOOL_GXX4MACHO_CINCS ?= TOOL_GXX4MACHO_CDEFS ?= TOOL_GXX4MACHO_CXXOBJSUFF ?= .o TOOL_GXX4MACHO_CXXFLAGS ?= TOOL_GXX4MACHO_CXXFLAGS.debug ?= -g TOOL_GXX4MACHO_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX4MACHO_CXXFLAGS.release ?= -O2 TOOL_GXX4MACHO_CXXINCS ?= TOOL_GXX4MACHO_CXXDEFS ?= TOOL_GXX4MACHO_OBJCOBJSUFF ?= .o TOOL_GXX4MACHO_OBJCFLAGS ?= TOOL_GXX4MACHO_OBJCFLAGS.debug ?= -g TOOL_GXX4MACHO_OBJCFLAGS.profile?= -O2 #-g -pg TOOL_GXX4MACHO_OBJCFLAGS.release?= -O2 TOOL_GXX4MACHO_OBJCINCS ?= TOOL_GXX4MACHO_OBJCDEFS ?= TOOL_GXX4MACHO_OBJCXXOBJSUFF ?= .o TOOL_GXX4MACHO_OBJCXXFLAGS ?= TOOL_GXX4MACHO_OBJCXXFLAGS.debug ?= -g TOOL_GXX4MACHO_OBJCXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX4MACHO_OBJCXXFLAGS.release ?= -O2 TOOL_GXX4MACHO_OBJCXXINCS ?= TOOL_GXX4MACHO_OBJCXXDEFS ?= TOOL_GXX4MACHO_ASFLAGS ?= -x assembler-with-cpp TOOL_GXX4MACHO_ASFLAGS.debug ?= -g TOOL_GXX4MACHO_ASFLAGS.profile ?= -g TOOL_GXX4MACHO_ASOBJSUFF ?= .o TOOL_GXX4MACHO_AR ?= ar$(HOSTSUFF_EXE) TOOL_GXX4MACHO_ARFLAGS ?= -c -rs TOOL_GXX4MACHO_ARLIBSUFF ?= .a TOOL_GXX4MACHO_LDFLAGS ?= TOOL_GXX4MACHO_LDFLAGS.debug ?= -g TOOL_GXX4MACHO_LDFLAGS.profile ?= -g TOOL_GXX4MACHO_STRIP_PROGRAM ?= strip -SXxru TOOL_GXX4MACHO_STRIP_DLL ?= strip -Sxru TOOL_GXX4MACHO_STRIP_SYSMOD ?= strip -Sru ## # Calculate the files in the debug bundle. # @param 1 The whole output filename. # @param 2 The output filename sans suffix. TOOL_GXX4MACHO_DEBUG_BUNDLE_FN = \ $(1).dSYM/ \ $(1).dSYM/Contents/ \ $(1).dSYM/Contents/Resources/ \ $(1).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1)) ## # Calculate the files in the debug bundle. # @param 1 The whole linker output filename. # @param 2 The linker output filename sans suffix. # @param 3 The desired install name (no dir slash). # @remarks The Info.plist has some reference to the original name, but gdb # does not care and only check for a symbol file in the DWARF # directory with the same name as the debugged module. TOOL_GXX4MACHO_DEBUG_INSTALL_FN= \ $(3).dSYM/ \ $(3).dSYM/Contents/ \ $(3).dSYM/Contents/Resources/ \ $(3).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist=>$(3).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1))=>$(3).dSYM/Contents/Resources/DWARF/$(notdir $(3)) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX4MACHO_COMPILE_C_DEPEND = TOOL_GXX4MACHO_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GXX4MACHO_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GXX4MACHO_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GXX4MACHO_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX4MACHO_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_C_OUTPUT = define TOOL_GXX4MACHO_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX4MACHO_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KUSE_OBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX4MACHO_COMPILE_CXX_DEPEND = TOOL_GXX4MACHO_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GXX4MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GXX4MACHO_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX4MACHO_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX4MACHO_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_CXX_OUTPUT = define TOOL_GXX4MACHO_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX4MACHO_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX4MACHO_COMPILE_OBJC_DEPEND = TOOL_GXX4MACHO_COMPILE_OBJC_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1 TOOL_GXX4MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi define TOOL_GXX4MACHO_COMPILE_OBJC_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX4MACHO_OBJC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX4MACHO_OBJC) -c\ $(flags) -fpreprocessed -x objective-c \ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_OBJC_OUTPUT = define TOOL_GXX4MACHO_COMPILE_OBJC_CMDS $(QUIET)$(TOOL_GXX4MACHO_OBJC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX4MACHO_COMPILE_OBJCXX_DEPEND = TOOL_GXX4MACHO_COMPILE_OBJCXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_OBJCXX_USES_KOBJCACHE = 1 TOOL_GXX4MACHO_COMPILE_OBJCXX_OUTPUT = $(outbase).mii define TOOL_GXX4MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).mii\ $(TOOL_GXX4MACHO_OBJCXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX4MACHO_OBJCXX) -c\ $(flags) -fpreprocessed -x objective-c++ \ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX4MACHO_COMPILE_OBJCXX_OUTPUT = define TOOL_GXX4MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(TOOL_GXX4MACHO_OBJCXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX4MACHO_COMPILE_AS_OUTPUT = TOOL_GXX4MACHO_COMPILE_AS_DEPEND = TOOL_GXX4MACHO_COMPILE_AS_DEPORD = define TOOL_GXX4MACHO_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX4MACHO_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX4MACHO_LINK_LIBRARY_OUTPUT = TOOL_GXX4MACHO_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GXX4MACHO_LINK_LIBRARY_DEPORD = define TOOL_GXX4MACHO_LINK_LIBRARY_CMDS $(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_GXX4MACHO_AR) $(flags) $(out),$(objs))) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GXX4MACHO_AR) -x $(abspath $(lib)) \ && $(RM_EXT) -f ./__.SYMDEF* \ && $(TOOL_GXX4MACHO_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX4MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp TOOL_GXX4MACHO_LINK_PROGRAM_OUTPUT_DEBUG = $(call TOOL_GXX4MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GXX4MACHO_LINK_PROGRAM_DEBUG_INSTALL_FN = $(TOOL_GXX4MACHO_DEBUG_INSTALL_FN) TOOL_GXX4MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX4MACHO_LINK_PROGRAM_DEPORD = define TOOL_GXX4MACHO_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GXX4MACHO_LD) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GXX4MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GXX4MACHO_STRIP_PROGRAM) $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX4MACHO_LINK_DLL_OUTPUT = $(outbase).rsp TOOL_GXX4MACHO_LINK_DLL_OUTPUT_DEBUG = $(call TOOL_GXX4MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GXX4MACHO_LINK_DLL_DEBUG_INSTALL_FN = $(TOOL_GXX4MACHO_DEBUG_INSTALL_FN) TOOL_GXX4MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX4MACHO_LINK_DLL_DEPORD = define TOOL_GXX4MACHO_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GXX4MACHO_LD) $(TOOL_GXX4MACHO_LDFLAGS.dll) $(flags) -o $(out)\ $(call TOOL_GXX4MACHO_LD_SONAME,$(target),$(out))\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GXX4MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GXX4MACHO_STRIP_DLL) $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX4MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp TOOL_GXX4MACHO_LINK_SYSMOD_OUTPUT_DEBUG = $(call TOOL_GXX4MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GXX4MACHO_LINK_SYSMOD_DEBUG_INSTALL_FN = $(TOOL_GXX4MACHO_DEBUG_INSTALL_FN) TOOL_GXX4MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX4MACHO_LINK_SYSMOD_DEPORD = define TOOL_GXX4MACHO_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GXX4MACHO_LD_SYSMOD) $(TOOL_GXX4MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GXX4MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GXX4MACHO_STRIP_SYSMOD) $(out) endif endef kbuild-2695/kBuild/tools/MASM600.kmk0000644000000000000000000000535112247157310015500 0ustar rootroot# $Id: MASM600.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - MASM v6.00 # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_MASM600 := Microsoft Macro Assembler v6.00 # Tool Specific Properties ifndef TOOL_MASM600_AS TOOL_MASM600_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/masm/v6.00*/binp/ml$(HOSTSUFF_EXE)))) ifeq ($(TOOL_MASM600_AS),) TOOL_MASM600_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/masm/v6.00*/binp/ml$(HOSTSUFF_EXE)))) endif ifeq ($(TOOL_MASM600_AS),) TOOL_MASM600_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS)/os2.x86/ddk/*/toolkits/masm60/binp/ml$(HOSTSUFF_EXE)))) endif ifeq ($(TOOL_MASM600_AS),) if1of ($(USER) $(USERNAME) $(LOGNAME), bird) TOOL_MASM600_AS := $(wildcard D:/dev/DDK/*/toolkits/masm60/binp/ML.EXE) endif endif endif ifeq ($(TOOL_MASM600_AS),) TOOL_MASM600_AS := $(firstword $(which ml$(HOSTSUFF_EXE)) path/notfound/ml$(HOSTSUFF_EXE)) endif # General Properties used by kBuild TOOL_MASM600_ASFLAGS ?= /nologo ## # @remarks MASM v5.10 has serious trouble, so play safe with v6.00 as well. # See MASM510.kmk for details. TOOL_MASM600_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_MASM600_COMPILE_AS_DEPEND = TOOL_MASM600_COMPILE_AS_DEPORD = define TOOL_MASM600_COMPILE_AS_CMDS $(QUIET)$(REDIRECT) \ -c3 -c4 -c5 -c6 -c7 -c8 -c9 -c10 -c11 -c12 -c13 -c14 -c15 -c16 -c17 -c18 -c19 -Z \ -E 'INCLUDE=$(subst $(SP),,$(addsuffix ;,$(subst /,\,$(incs))))' \ -- \ $(subst /,\\,$(TOOL_MASM600_AS)) -c \ $(strip $(flags)) \ $(addprefix -D,$(defs)) \ -Fo$(subst /,\\,$(obj)) \ -Fl$(subst /,\\,$(outbase).lst) \ $(subst /,\\,$(source)) endef kbuild-2695/kBuild/tools/StandardDTrace.kmk0000644000000000000000000000354412247157310017342 0ustar rootroot# $Id: StandardDTrace.kmk 2567 2012-03-17 19:27:32Z bird $ ## @file # Standard DTrace tool. # # # Copyright (c) 2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_StandardDTrace := Standard DTrace or similar. TOOL_StandardDTrace_DTRACE := dtrace TOOL_StandardDTrace_DTRACE_HDR_FLAGS := -h define TOOL_StandardDTrace_DTRACE_HDR_CMDS $(QUIET)$(TOOL_StandardDTrace_DTRACE) $(flags) \ -o "$(out)" -s "$(source)" endef TOOL_StandardDTrace_DTRACE_OBJ_NOT_NEEDED := darwin TOOL_StandardDTrace_DTRACE_OBJ_FLAGS := -G define TOOL_StandardDTrace_DTRACE_OBJ_CMDS $(QUIET)$(TOOL_StandardDTrace_DTRACE) \ $(if-expr $(intersects $(bld_trg_arch),$(KBUILD_ARCHES_64)),-64,-32) \ $(flags) \ -o "$(out)" -s "$(source)" \ $$(filter-out %-dtrace-object-format.o, $$($(target)_2_OBJS)) endef kbuild-2695/kBuild/tools/OPENWATCOM-16.kmk0000644000000000000000000001624312247157310016417 0ustar rootroot# $Id: OPENWATCOM-16.kmk 2572 2012-04-27 13:19:55Z bird $ ## @file # kBuild Tool Config - Open Watcom v1.4 and later, 16-bit targets. # # @remarks wrc is untested, so are DLLs, and programs. # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_OPENWATCOM-16 = Open Watcom v1.4 and later - 16-bit targets. TOOL_OPENWATCOM-16_EXTENDS = OPENWATCOM TOOL_OPENWATCOM-16_ASFLAGS.win ?= -bt=windows TOOL_OPENWATCOM-16_CFLAGS.win ?= -bt=windows TOOL_OPENWATCOM-16_CXXFLAGS.win ?= -bt=windows TOOL_OPENWATCOM-16_RCFLAGS.win ?= -bt=windows TOOL_OPENWATCOM-16_LDFLAGS.win ?= -bt=windows TOOL_OPENWATCOM-16_COMPILE_AS_DEPEND = TOOL_OPENWATCOM-16_COMPILE_AS_DEPORD = TOOL_OPENWATCOM-16_COMPILE_AS_OUTPUT = $(obj).err define TOOL_OPENWATCOM-16_COMPILE_AS_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_AS) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ -fr=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)).err \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_OPENWATCOM-16_COMPILE_C_DEPEND = TOOL_OPENWATCOM-16_COMPILE_C_DEPORD = TOOL_OPENWATCOM-16_COMPILE_C_OUTPUT = $(obj).err define TOOL_OPENWATCOM-16_COMPILE_C_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_CC16) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ -fr=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)).err \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_OPENWATCOM-16_COMPILE_CXX_DEPEND = TOOL_OPENWATCOM-16_COMPILE_CXX_DEPORD = TOOL_OPENWATCOM-16_COMPILE_CXX_OUTPUT = $(obj).err define TOOL_OPENWATCOM-16_COMPILE_CXX_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_CXX16) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ -fr=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)).err \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_OPENWATCOM-16_COMPILE_RC_OUTPUT = TOOL_OPENWATCOM-16_COMPILE_RC_DEPEND = TOOL_OPENWATCOM-16_COMPILE_RC_DEPORD = define TOOL_OPENWATCOM-16_COMPILE_RC_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) -r\ $(flags) \ $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs))) \ $(addprefix -d, $(defs))\ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) endef TOOL_OPENWATCOM-16_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_OPENWATCOM-16_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_OPENWATCOM-16_LINK_LIBRARY_DEPORD = define TOOL_OPENWATCOM-16_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp $(foreach obj,$(call TOOL_OPENWATCOM_FIX_SLASHES,$(objs) $(othersrc)),'+"$(obj)"') $(QUIET)$(TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_AR) $(flags) $(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) @$(outbase).rsp endef TOOL_OPENWATCOM-16_LINK_PROGRAM_OUTPUT = $(outbase).map TOOL_OPENWATCOM-16_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).sym TOOL_OPENWATCOM-16_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_OPENWATCOM-16_LINK_PROGRAM_DEPORD = define TOOL_OPENWATCOM-16_LINK_PROGRAM_CMDS $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_OPENWATCOM_LD16) \ $(flags) \ -fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ -fm=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(outbase).map) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter-out %.res,$(objs))) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(libs)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter %.res,$(objs)))) endef TOOL_OPENWATCOM-16_LINK_DLL_OUTPUT = $(outbase).map TOOL_OPENWATCOM-16_LINK_DLL_OUTPUT_MAYBE = $(outbase).sym TOOL_OPENWATCOM-16_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_OPENWATCOM-16_LINK_DLL_DEPORD = define TOOL_OPENWATCOM-16_LINK_DLL_CMDS $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_OPENWATCOM_LD16) \ $(flags) \ -fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ -fm=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(outbase).map) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter-out %.res,$(objs))) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(libs)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter %.res,$(objs)))) endef TOOL_OPENWATCOM-16_LINK_SYSMOD_OUTPUT = $(outbase).map TOOL_OPENWATCOM-16_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).sym TOOL_OPENWATCOM-16_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_OPENWATCOM-16_LINK_SYSMOD_DEPORD = define TOOL_OPENWATCOM-16_LINK_SYSMOD_CMDS $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_OPENWATCOM_LD16) \ $(flags) \ -fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ -fm=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(outbase).map) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter-out %.res,$(objs))) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(libs)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter %.res,$(objs)))) endef kbuild-2695/kBuild/tools/JWASM.kmk0000644000000000000000000000406412247157310015376 0ustar rootroot# $Id: JWASM.kmk 2578 2012-06-07 00:08:22Z bird $ ## @file # kBuild Tool Config - JWasm # # # Copyright (c) 2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_JWASM := JWasm - MASM clone based on the Open Watcom assembler. # Tool Specific Properties ifndef TOOL_JWASM_AS TOOL_JWASM_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/jwasm/*/jwasm$(HOSTSUFF_EXE)))) ifeq ($(TOOL_JWASM_AS),) TOOL_JWASM_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/jwasm/*/jwasm$(HOSTSUFF_EXE)))) endif endif ifeq ($(TOOL_JWASM_AS),) TOOL_JWASM_AS := $(firstword $(which ml$(HOSTSUFF_EXE)) jwasm$(HOSTSUFF_EXE)) endif # General Properties used by kBuild TOOL_JWASM_ASFLAGS ?= -X -nologo TOOL_JWASM_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_JWASM_COMPILE_AS_DEPEND = TOOL_JWASM_COMPILE_AS_DEPORD = define TOOL_JWASM_COMPILE_AS_CMDS $(TOOL_JWASM_AS) -c \ $(strip $(flags)) \ $(addprefix -D,$(defs)) \ $(addprefix -I,$(incs)) \ -Fo$(obj) \ -Fl$(outbase).lst \ $(source) endef kbuild-2695/kBuild/tools/FLEX.kmk0000644000000000000000000000311712247157310015251 0ustar rootroot# $Id: FLEX.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # flex tool # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_FLEX = flex TOOL_FLEX_LEX ?= flex$(HOSTSUFF_EXE) #TOOL_FLEX_LEXFLAGS ?= TOOL_FLEX_LEX_OUT_FILE = $(evalcall KB_FN_OPT_TEST_SHORT_LONG,+,--c++,$(flags),$(outbase).cpp,$(outbase).c) TOOL_FLEX_LEX_OUTPUT = TOOL_FLEX_LEX_OUTPUT_MAYBE = TOOL_FLEX_LEX_DEPEND = TOOL_FLEX_LEX_DEPORD = define TOOL_FLEX_LEX_CMDS $(QUIET)$(TOOL_FLEX_LEX) $(flags) -o$(out) $(source) endef kbuild-2695/kBuild/tools/YASM.kmk0000644000000000000000000000703412247157310015266 0ustar rootroot# $Id: YASM.kmk 2694 2013-07-22 13:39:36Z bird $ ## @file # kBuild Tool Config - YASM 0.4.0 or later. # # # Copyright (c) 2006-2013 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_YASM := YASM v0.4.0+ # Tool Specific Properties ifndef PATH_TOOL_YASM PATH_TOOL_YASM := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/yasm/v*.*)) ifneq ($(PATH_TOOL_YASM),) PATH_TOOL_YASM := $(call lastword,$(PATH_TOOL_YASM)) endif else # Resolve any fancy stuff once and for all. PATH_TOOL_YASM := $(PATH_TOOL_YASM) endif ifneq ($(PATH_TOOL_YASM),) TOOL_YASM_AS ?= $(PATH_TOOL_YASM)/yasm$(HOSTSUFF_EXE) else TOOL_YASM_AS ?= yasm$(HOSTSUFF_EXE) endif # General Properties used by kBuild TOOL_YASM_ASFLAGS ?= ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_YASM_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_YASM_COMPILE_AS_OUTPUT_MAYBE = $(obj).map TOOL_YASM_COMPILE_AS_DEPEND = TOOL_YASM_COMPILE_AS_DEPORD = define TOOL_YASM_COMPILE_AS_CMDS $(QUIET)$(TOOL_YASM_AS)\ $(patsubst --mapfile%,--mapfile=$(obj).map,$(flags))\ $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\ -l $(outbase).lst\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(REDIRECT) -wo $(dep) -- $(TOOL_YASM_AS) -DKBUILD_GENERATING_MAKEFILE_DEPENDENCIES\ $(patsubst --mapfile%,--mapfile=$(obj).map,$(flags))\ $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\ -o $(obj) \ $(abspath $(source)) \ -M if1of ($(KBUILD_HOST), win nt os2) $(QUIET)$(SED) -e 's/\\\(.\)/\/\1/g' --output "$(dep).tmp" "$(dep)" else $(QUIET)$(CP) -f -- "$(dep)" "$(dep).tmp" endif $(QUIET)$(APPEND) -n "$(dep).tmp" "" "" $(QUIET)$(SED) $(if $(intersects $(KBUILD_HOST), win nt os2), -e 's/\\\(.\)/\/\1/g',)\ -e 's/^[^ ]*: / /'\ -e 's/ *\\$$(DOLLAR)//'\ -e 's/^ *//'\ -e 's/ */\n/g'\ -e 's/ *\([^ \n][^ \n]*\)/\1:\n/g'\ --append "$(dep).tmp"\ "$(dep)" $(QUIET)$(MV) -f -- "$(dep).tmp" "$(dep)" endef kbuild-2695/kBuild/tools/WATCOMC11C-WL.kmk0000644000000000000000000000724312247157310016401 0ustar rootroot# $Id: WATCOMC11C-WL.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - Watcom C/C++ v11.0c, using wlink. # # @remarks wrc is untested, so are DLLs, and programs. # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_WATCOMC11C-WL = Watcom C/C++ v11.0c, using wlink. TOOL_WATCOMC11C-WL_EXTENDS = WATCOMC11C TOOL_WATCOMC11C-WL_LDFLAGS ?= Option Quiet TOOL_WATCOMC11C-WL_LDFLAGS.dos ?= $(NO_SUCH_VARIABLE) TOOL_WATCOMC11C-WL_LDFLAGS.linux ?= $(NO_SUCH_VARIABLE) TOOL_WATCOMC11C-WL_LDFLAGS.nt ?= $(NO_SUCH_VARIABLE) TOOL_WATCOMC11C-WL_LDFLAGS.os2 ?= $(NO_SUCH_VARIABLE) TOOL_WATCOMC11C-WL_LDFLAGS.win ?= $(NO_SUCH_VARIABLE) TOOL_WATCOMC11C-WL_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPORD = define TOOL_WATCOMC11C-WL_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(if $(flags),'$(flags)',) \ 'Name $(subst /,\,$(out)$(if $(suffix $(out)),,.))' \ 'Option Map=$(subst /,\,$(outbase)).map' \ $(foreach p,$(subst /,\,$(libpath)),'LIBPath $p') \ $(foreach o,$(subst /,\,$(filter-out %.res,$(objs)) $(othersrc)),'$(if $(filter %.lib %.a,$l),LIB,)File $o') \ $(foreach l,$(subst /,\,$(libs)),'Library $l') $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_WLINK) @$(outbase).rsp $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(subst /,\\,$(out)) \ $(subst /,\\,$(filter %.res,$(objs)))) endef TOOL_WATCOMC11C-WL_LINK_DLL_OUTPUT = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_OUTPUT) TOOL_WATCOMC11C-WL_LINK_DLL_DEPEND = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPEND) TOOL_WATCOMC11C-WL_LINK_DLL_DEPORD = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPORD) TOOL_WATCOMC11C-WL_LINK_DLL_CMDS = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_CMDS) TOOL_WATCOMC11C-WL_LINK_SYSMOD_OUTPUT = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_OUTPUT) TOOL_WATCOMC11C-WL_LINK_SYSMOD_DEPEND = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPEND) TOOL_WATCOMC11C-WL_LINK_SYSMOD_DEPORD = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPORD) TOOL_WATCOMC11C-WL_LINK_SYSMOD_CMDS = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_CMDS) TOOL_WATCOMC11C-WL_LINK_MISCBIN_OUTPUT = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_OUTPUT) TOOL_WATCOMC11C-WL_LINK_MISCBIN_DEPEND = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPEND) TOOL_WATCOMC11C-WL_LINK_MISCBIN_DEPORD = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_DEPORD) TOOL_WATCOMC11C-WL_LINK_MISCBIN_CMDS = $(TOOL_WATCOMC11C-WL_LINK_PROGRAM_CMDS) kbuild-2695/kBuild/tools/TARBZ2.kmk0000644000000000000000000000252012247157310015454 0ustar rootroot# $Id: TARBZ2.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - tar.bz2 unpacker. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_TARBZ2 := tar.bz2 unpacker. TOOL_TARBZ2_EXTENDS = TAR TOOL_TARBZ2_UNPACKFLAGS ?= -j kbuild-2695/kBuild/tools/GXX3PLAIN.kmk0000644000000000000000000003216212247157310016032 0ustar rootroot# $Id: GXX3PLAIN.kmk 2545 2011-09-13 19:09:05Z bird $ ## @file # kBuild Tool Config - Generic GCC v3.2.x or later using the system GCC, any Unix linker and Unix archiver to build C++ code. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX3PLAIN := Generic GCC v3.2.x or later using the system GCC, any Unix linker and Unix archiver to build C++ code. # Tool Specific Properties TOOL_GXX3PLAIN_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_AS ?= gcc$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_AR ?= ar$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_RANLIB ?= ranlib$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_LD ?= g++$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_LD_SYSMOD.os2 ?= g++$(HOSTSUFF_EXE) TOOL_GXX3PLAIN_LDFLAGS.dll.os2 ?= -Zdll TOOL_GXX3PLAIN_LDFLAGS.dll.darwin ?= -dynamiclib ifndef TOOL_GXX3PLAIN_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX3PLAIN_LDFLAGS.dll ?= -shared else TOOL_GXX3PLAIN_LDFLAGS.dll ?= $(TOOL_GXX3PLAIN_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GXX3PLAIN_LD_SONAME.darwin ?= $(NO_SUCH_VARIABLE) TOOL_GXX3PLAIN_LD_SONAME.os2 ?= $(NO_SUCH_VARIABLE) TOOL_GXX3PLAIN_LD_SONAME.solaris ?= -Wl,-h,$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_GXX3PLAIN_LD_SONAME.win ?= $(NO_SUCH_VARIABLE) ifndef TOOL_GXX3PLAIN_LD_SONAME.$(KBUILD_TARGET) TOOL_GXX3PLAIN_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) else TOOL_GXX3PLAIN_LD_SONAME ?= $(TOOL_GXX3PLAIN_LD_SONAME.$(KBUILD_TARGET)) endif ifdef SLKRUNS TOOL_GXX3PLAIN_CC += -fmessage-length=0 TOOL_GXX3PLAIN_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GXX3PLAIN_COBJSUFF ?= .o TOOL_GXX3PLAIN_CFLAGS ?= TOOL_GXX3PLAIN_CFLAGS.debug ?= -g TOOL_GXX3PLAIN_CFLAGS.profile ?= -O2 #-g -pg TOOL_GXX3PLAIN_CFLAGS.release ?= -O2 TOOL_GXX3PLAIN_CINCS ?= TOOL_GXX3PLAIN_CDEFS ?= TOOL_GXX3PLAIN_CXXOBJSUFF ?= .o TOOL_GXX3PLAIN_CXXOBJSUFF ?= .o TOOL_GXX3PLAIN_CXXFLAGS ?= TOOL_GXX3PLAIN_CXXFLAGS.debug ?= -g TOOL_GXX3PLAIN_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX3PLAIN_CXXFLAGS.release ?= -O2 TOOL_GXX3PLAIN_CXXINCS ?= TOOL_GXX3PLAIN_CXXDEFS ?= TOOL_GXX3PLAIN_ASFLAGS ?= -x assembler-with-cpp TOOL_GXX3PLAIN_ASFLAGS.debug ?= -g TOOL_GXX3PLAIN_ASFLAGS.profile ?= -g TOOL_GXX3PLAIN_ASOBJSUFF ?= .o TOOL_GXX3PLAIN_ARFLAGS ?= cr TOOL_GXX3PLAIN_ARLIBSUFF ?= .a TOOL_GXX3PLAIN_LDFLAGS ?= ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX3PLAIN_COMPILE_C_DEPEND = TOOL_GXX3PLAIN_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX3PLAIN_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GXX3PLAIN_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GXX3PLAIN_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GXX3PLAIN_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX3PLAIN_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX3PLAIN_COMPILE_C_OUTPUT = define TOOL_GXX3PLAIN_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX3PLAIN_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX3PLAIN_COMPILE_CXX_DEPEND = TOOL_GXX3PLAIN_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX3PLAIN_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GXX3PLAIN_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GXX3PLAIN_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX3PLAIN_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX3PLAIN_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX3PLAIN_COMPILE_CXX_OUTPUT = define TOOL_GXX3PLAIN_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX3PLAIN_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX3PLAIN_COMPILE_AS_OUTPUT = TOOL_GXX3PLAIN_COMPILE_AS_DEPEND = TOOL_GXX3PLAIN_COMPILE_AS_DEPORD = define TOOL_GXX3PLAIN_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX3PLAIN_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3PLAIN_LINK_LIBRARY_OUTPUT = TOOL_GXX3PLAIN_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GXX3PLAIN_LINK_LIBRARY_DEPORD = define TOOL_GXX3PLAIN_LINK_LIBRARY_CMDS $(call xargs,$(QUIET)$(TOOL_GXX3PLAIN_AR) $(flags) $(out),$(objs)) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GXX3PLAIN_AR) x $(abspath $(lib)) \ && $(TOOL_GXX3PLAIN_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) $(QUIET)$(TOOL_GXX3PLAIN_RANLIB) $(out) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3PLAIN_LINK_PROGRAM_OUTPUT = TOOL_GXX3PLAIN_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GXX3PLAIN_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX3PLAIN_LINK_PROGRAM_DEPORD = define TOOL_GXX3PLAIN_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GXX3PLAIN_LD) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3PLAIN_LINK_DLL_OUTPUT = TOOL_GXX3PLAIN_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GXX3PLAIN_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX3PLAIN_LINK_DLL_DEPORD = define TOOL_GXX3PLAIN_LINK_DLL_CMDS $(QUIET)$(TOOL_GXX3PLAIN_LD) $(TOOL_GXX3PLAIN_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_GXX3PLAIN_LD_SONAME,$(target),$(out)))\ $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef ## Link system module (windows aka driver, linux aka kernel module) # This tool target might not work everywhere, but is provided for the # platforms where it works (Solaris, etc). # # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3PLAIN_LINK_SYSMOD_OUTPUT = TOOL_GXX3PLAIN_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GXX3PLAIN_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX3PLAIN_LINK_SYSMOD_DEPORD = define TOOL_GXX3PLAIN_LINK_SYSMOD_CMDS $(QUIET)$(if $(TOOL_GXX3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GXX3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GXX3PLAIN_LD_SYSMOD))\ $(TOOL_GXX3PLAIN_LDFLAGS_SYSMOD.$(bld_trg)) $(flags) -o $(out) \ $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef kbuild-2695/kBuild/tools/MASM710.kmk0000644000000000000000000000457712247157310015513 0ustar rootroot# $Id: MASM710.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - MASM v7.10 # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_MASM710 := Microsoft Macro Assembler v7.10 # Tool Specific Properties ifndef TOOL_MASM710_AS TOOL_MASM710_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/masm/v7.10*/binp/ml$(HOSTSUFF_EXE)))) ifeq ($(TOOL_MASM710_AS),) TOOL_MASM710_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/masm/v7.10*/binp/ml$(HOSTSUFF_EXE)))) endif ifeq ($(TOOL_MASM710_AS),) TOOL_MASM710_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v7*/bin/ml$(HOSTSUFF_EXE)))) endif endif ifeq ($(TOOL_MASM710_AS),) TOOL_MASM710_AS := $(firstword $(which ml$(HOSTSUFF_EXE)) path/notfound/ml$(HOSTSUFF_EXE)) endif # General Properties used by kBuild TOOL_MASM710_ASFLAGS ?= /nologo TOOL_MASM710_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_MASM710_COMPILE_AS_DEPEND = TOOL_MASM710_COMPILE_AS_DEPORD = define TOOL_MASM710_COMPILE_AS_CMDS $(QUIET)$(REDIRECT) \ -E 'INCLUDE=$(subst $(SP),,$(addsuffix ;,$(subst /,\,$(incs))))' \ -E 'MASM=' -E 'ML=' \ -- \ $(subst /,\\,$(TOOL_MASM710_AS)) -c \ $(strip $(flags)) \ $(addprefix -D,$(defs)) \ -Fo$(subst /,\\,$(obj)) \ -Fl$(subst /,\\,$(outbase).lst) \ $(subst /,\\,$(source)) endef kbuild-2695/kBuild/tools/VCC100AMD64.kmk0000644000000000000000000004160512247157310016047 0ustar rootroot# $Id: VCC100AMD64.kmk 2625 2012-08-07 20:26:48Z bird $ ## @file # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting AMD64. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VCC100AMD64 := Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting AMD64 # Tool Specific Properties ifndef PATH_TOOL_VCC100AMD64 PATH_TOOL_VCC100AMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v10*) ifeq ($(PATH_TOOL_VCC100AMD64),) PATH_TOOL_VCC100AMD64 := $(PATH_TOOL_VCC100) endif ifeq ($(PATH_TOOL_VCC100AMD64),) PATH_TOOL_VCC100AMD64 := $(PATH_TOOL_VCC100X86) endif ifeq ($(PATH_TOOL_VCC100AMD64),) PATH_TOOL_VCC100AMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v10*) endif ifneq ($(PATH_TOOL_VCC100AMD64),) PATH_TOOL_VCC100AMD64 := $(lastword $(sort $(PATH_TOOL_VCC100AMD64))) else $(warning kBuild: PATH_TOOL_VCC100AMD64 cannot be determined!) PATH_TOOL_VCC100AMD64 := $(PATH_DEVTOOLS)/win.x86/vcc/v10 endif else # Resolve any fancy stuff once and for all. PATH_TOOL_VCC100AMD64 := $(PATH_TOOL_VCC100AMD64) endif ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),win.amd64) PATH_TOOL_VCC100AMD64_BIN ?= $(PATH_TOOL_VCC100AMD64)/bin/amd64 else PATH_TOOL_VCC100AMD64_BIN ?= $(PATH_TOOL_VCC100AMD64)/bin/x86_amd64 endif PATH_TOOL_VCC100AMD64_LIB ?= $(PATH_TOOL_VCC100AMD64)/lib/amd64 PATH_TOOL_VCC100AMD64_INC ?= $(PATH_TOOL_VCC100AMD64)/include PATH_TOOL_VCC100AMD64_ATLMFC ?= $(PATH_TOOL_VCC100AMD64)/atlmfc PATH_TOOL_VCC100AMD64_ATLMFC_INC ?= $(PATH_TOOL_VCC100AMD64_ATLMFC)/include PATH_TOOL_VCC100AMD64_ATLMFC_LIB ?= $(PATH_TOOL_VCC100AMD64_ATLMFC)/lib/amd64 TOOL_VCC100AMD64_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/cl.exe TOOL_VCC100AMD64_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/cl.exe TOOL_VCC100AMD64_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/ml64.exe TOOL_VCC100AMD64_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/lib.exe TOOL_VCC100AMD64_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/link.exe TOOL_VCC100AMD64_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/dumpbin.exe TOOL_VCC100AMD64_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/editbin.exe TOOL_VCC100AMD64_RC ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED) TOOL_VCC100AMD64_MT ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED) # The following in duplicated in VCC100.kmk and VCC100X86.kmk. TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword \ $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \ $(if-expr defined(PATH_SDK_WINPSDK_BIN) , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \ $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \ $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \ $1)) TOOL_VCC100_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC100_FN_FIND_SDK_TOOL_SUB),)$($3) ## Disabled fast DEP_IDB based dependencies. #VCC100AMD64_OLD_DEPS = 1 ## Constructs the correct .pdb name (the name is lowercased). # @param $(1) Base name, no extention. # @param $(2) The extension. TOOL_VCC100AMD64_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) TOOL_VCC100AMD64_COBJSUFF ?= .obj TOOL_VCC100AMD64_CFLAGS ?= -TC -nologo TOOL_VCC100AMD64_CFLAGS.debug ?= -Zi TOOL_VCC100AMD64_CFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100AMD64_CFLAGS.release ?= -O2 TOOL_VCC100AMD64_CFLAGS.profile ?= -O2 TOOL_VCC100AMD64_CINCS ?= $(PATH_TOOL_VCC100AMD64_INC) TOOL_VCC100AMD64_CDEFS ?= TOOL_VCC100AMD64_CXXOBJSUFF ?= .obj TOOL_VCC100AMD64_CXXFLAGS ?= -TP -nologo TOOL_VCC100AMD64_CXXFLAGS.debug ?= -Zi TOOL_VCC100AMD64_CXXFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100AMD64_CXXFLAGS.release ?= -O2 TOOL_VCC100AMD64_CXXFLAGS.profile ?= -O2 TOOL_VCC100AMD64_CXXINCS ?= $(PATH_TOOL_VCC100AMD64_INC) $(PATH_TOOL_VCC100AMD64_ATLMFC_INC) TOOL_VCC100AMD64_CXXDEFS ?= TOOL_VCC100AMD64_ASOBJSUFF ?= .obj TOOL_VCC100AMD64_RCOBJSUFF ?= .res TOOL_VCC100AMD64_RCINCS ?= $(PATH_TOOL_VCC100AMD64_INC) $(PATH_TOOL_VCC100AMD64_ATLMFC_INC) TOOL_VCC100AMD64_ARFLAGS ?= -nologo -machine:amd64 TOOL_VCC100AMD64_ARLIBSUFF ?= .lib TOOL_VCC100AMD64_LDFLAGS ?= -nologo -machine:amd64 TOOL_VCC100AMD64_LDFLAGS.debug ?= -debug TOOL_VCC100AMD64_LDFLAGS.dbgopt ?= -debug TOOL_VCC100AMD64_LDFLAGS.profile ?= -debug TOOL_VCC100AMD64_LDFLAGS.release ?= ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100AMD64_COMPILE_C_DEPEND = TOOL_VCC100AMD64_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_VCC100AMD64_COMPILE_C_USES_KOBJCACHE = 1 TOOL_VCC100AMD64_COMPILE_C_OUTPUT = $(outbase).i TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE = define TOOL_VCC100AMD64_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ --kObjCache-cpp $(outbase).i\ $(TOOL_VCC100AMD64_CC) -E\ $(subst -Zi,-Z7,$(flags))\ $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ --kObjCache-cc $(obj)\ $(TOOL_VCC100AMD64_CC) -c\ $(subst -Zi,-Z7,$(flags))\ -Fo$(obj)\ $(outbase).i endef else # !KBUILD_USE_KOBJCACHE TOOL_VCC100AMD64_COMPILE_C_OUTPUT = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,idb) TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,pdb) define TOOL_VCC100AMD64_COMPILE_C_CMDS $(QUIET)$(TOOL_VCC100AMD64_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100AMD64_PDB,$(outbase)-obj,idb) endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100AMD64_COMPILE_CXX_DEPEND = TOOL_VCC100AMD64_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_VCC100AMD64_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT = $(outbase).ii TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = define TOOL_VCC100AMD64_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ --kObjCache-cpp $(outbase).ii\ $(TOOL_VCC100AMD64_CXX) -E\ $(subst -Zi,-Z7,$(flags))\ $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ --kObjCache-cc $(obj)\ $(TOOL_VCC100AMD64_CXX) -c\ $(subst -Zi,-Z7,$(flags))\ -Fo$(obj)\ $(outbase).ii endef else # !KBUILD_USE_KOBJCACHE TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,idb) TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,pdb) define TOOL_VCC100AMD64_COMPILE_CXX_CMDS $(QUIET)$(TOOL_VCC100AMD64_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100AMD64_PDB,$(outbase)-obj,idb) endef endif # !KBUILD_USE_KOBJCACHE ## @todo configure the assembler template. ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100AMD64_COMPILE_RC_DEPEND = TOOL_VCC100AMD64_COMPILE_RC_DEPORD = TOOL_VCC100AMD64_COMPILE_RC_OUTPUT = define TOOL_VCC100AMD64_COMPILE_RC_CMDS $(QUIET)$(TOOL_VCC100AMD64_RC) \ $(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\ /fo$(obj)\ $(subst /,\\,$(abspath $(source))) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC100AMD64_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VCC100AMD64_LINK_LIBRARY_DEPORD = TOOL_VCC100AMD64_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_VCC100AMD64_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb define TOOL_VCC100AMD64_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs) \ $(filter-out %.def,$(othersrc))) \ $(addprefix /DEF:,$(filter %.def,$(othersrc))) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100AMD64_AR) $(flags) /OUT:$(out) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC100AMD64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100AMD64_LINK_PROGRAM_DEPORD = TOOL_VCC100AMD64_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC100AMD64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC100AMD64_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100AMD64_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100AMD64_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100AMD64_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100AMD64_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out)) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC100AMD64_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100AMD64_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) TOOL_VCC100AMD64_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp TOOL_VCC100AMD64_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp TOOL_VCC100AMD64_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100AMD64_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100AMD64_LINK_DLL_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100AMD64_LD) $(flags) \ /OUT:$(out) \ /IMPLIB:$(outbase).lib \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ /DLL \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' $(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/ $(eval _DIRS += $(PATH_STAGE_LIB)) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC100AMD64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100AMD64_LINK_SYSMOD_DEPORD = TOOL_VCC100AMD64_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC100AMD64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC100AMD64_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100AMD64_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100AMD64_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100AMD64_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' endef kbuild-2695/kBuild/tools/VCC80.kmk0000644000000000000000000003552412247157310015305 0ustar rootroot# $Id: VCC80.kmk 2557 2011-12-13 12:48:32Z bird $ ## @file # kBuild Tool Config - Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting $(KBUILD_TARGET). # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VCC80 := Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting $(KBUILD_TARGET). # Tool Specific Properties ifndef PATH_TOOL_VCC80 PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS_TRG)/vcc/v8*) ifeq ($(PATH_TOOL_VCC80),) PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*) endif ifeq ($(PATH_TOOL_VCC80),) PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/vcc/v8*) endif ifeq ($(PATH_TOOL_VCC80),) PATH_TOOL_VCC80 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/vcc/v8*) endif ifeq ($(PATH_TOOL_VCC80),) PATH_TOOL_VCC80 := $(lastword $(sort $(PATH_TOOL_VCC80))) endif # if not found, we'll enter 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_VCC80 := $(PATH_TOOL_VCC80) endif ifneq ($(PATH_TOOL_VCC80),) ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),win.amd64) PATH_TOOL_VCC80_BIN.amd64 ?= $(PATH_TOOL_VCC80)/bin/amd64 else PATH_TOOL_VCC80_BIN.amd64 ?= $(PATH_TOOL_VCC80)/bin/x86_amd64 endif PATH_TOOL_VCC80_BIN.x86 ?= $(PATH_TOOL_VCC80)/bin PATH_TOOL_VCC80_BIN ?= $(PATH_TOOL_VCC80_BIN.$(KBUILD_TARGET_ARCH)) PATH_TOOL_VCC80_LIB.amd64 ?= $(PATH_TOOL_VCC80)/lib/amd64 PATH_TOOL_VCC80_LIB.x86 ?= $(PATH_TOOL_VCC80)/lib PATH_TOOL_VCC80_LIB ?= $(PATH_TOOL_VCC80_LIB.$(KBUILD_TARGET_ARCH)) PATH_TOOL_VCC80_INC ?= $(PATH_TOOL_VCC80)/include PATH_TOOL_VCC80_ATLMFC ?= $(PATH_TOOL_VCC80X86)/atlmfc PATH_TOOL_VCC80_ATLMFC_INC ?= $(PATH_TOOL_VCC80_ATLMFC)/include PATH_TOOL_VCC80_ATLMFC_LIB.amd64 ?= $(PATH_TOOL_VCC80_ATLMFC)/lib PATH_TOOL_VCC80_ATLMFC_LIB.x86 ?= $(PATH_TOOL_VCC80_ATLMFC)/lib/amd64 PATH_TOOL_VCC80_ATLMFC_LIB ?= $(PATH_TOOL_VCC80_ATLMFC_LIB.$(KBUILD_TARGET_ARCH)) TOOL_VCC80_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/cl.exe TOOL_VCC80_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/cl.exe TOOL_VCC80_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/ml64.exe TOOL_VCC80_RC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN.x86)/rc.exe TOOL_VCC80_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/lib.exe TOOL_VCC80_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN)/link.exe TOOL_VCC80_MT ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80_BIN.x86)/mt.exe else # Pathless, relies on the environment. TOOL_VCC80_CC ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC80_CXX ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC80_AS ?= $(EXEC_X86_WIN32) ml64.exe TOOL_VCC80_RC ?= $(EXEC_X86_WIN32) rc.exe TOOL_VCC80_AR ?= $(EXEC_X86_WIN32) lib.exe TOOL_VCC80_LD ?= $(EXEC_X86_WIN32) link.exe TOOL_VCC80_MT ?= $(EXEC_X86_WIN32) mt.exe endif ## Disabled fast DEP_IDB based dependencies. #VCC80_OLD_DEPS = 1 ## Constructs the correct .pdb name (the name is lowercased). # @param $(1) Base name, no extention. # @param $(2) The extension. TOOL_VCC80_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) TOOL_VCC80_COBJSUFF ?= .obj TOOL_VCC80_CFLAGS ?= -TC -c -nologo TOOL_VCC80_CFLAGS.debug ?= -Od -Zi TOOL_VCC80_CFLAGS.release ?= -O2 TOOL_VCC80_CFLAGS.profile ?= -O2 TOOL_VCC80_CINCS ?= $(PATH_TOOL_VCC80_INC) TOOL_VCC80_CDEFS ?= TOOL_VCC80_CXXOBJSUFF ?= .obj TOOL_VCC80_CXXFLAGS ?= -TP -c -nologo TOOL_VCC80_CXXFLAGS.debug ?= -Od -Zi TOOL_VCC80_CXXFLAGS.release ?= -O2 TOOL_VCC80_CXXFLAGS.profile ?= -O2 TOOL_VCC80_CXXINCS ?= $(PATH_TOOL_VCC80_INC) $(PATH_TOOL_VCC80_ATLMFC_INC) TOOL_VCC80_CXXDEFS ?= TOOL_VCC80_ASOBJSUFF ?= .obj TOOL_VCC80_RCOBJSUFF ?= .res TOOL_VCC80_RCINCS ?= $(PATH_TOOL_VCC80_INC) $(PATH_TOOL_VCC80_ATLMFC_INC) TOOL_VCC80_ARFLAGS.amd64 ?= -machine:amd64 TOOL_VCC80_ARFLAGS.x86 ?= -machine:x86 TOOL_VCC80_ARFLAGS ?= -nologo TOOL_VCC80_ARLIBSUFF ?= .lib TOOL_VCC80_LDFLAGS.amd64 ?= -machine:amd64 TOOL_VCC80_LDFLAGS.x86 ?= -machine:x86 TOOL_VCC80_LDFLAGS ?= -nologo TOOL_VCC80_LDFLAGS.debug ?= -debug TOOL_VCC80_LDFLAGS.release ?= TOOL_VCC80_LIBPATH.amd64 ?= $(PATH_TOOL_VCC80_LIB.amd64) $(PATH_TOOL_VCC80_ATLMFC_LIB.amd64) TOOL_VCC80_LIBPATH.x86 ?= $(PATH_TOOL_VCC80_LIB.x86) $(PATH_TOOL_VCC80_ATLMFC_LIB.x86) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80_COMPILE_C_DEPEND = TOOL_VCC80_COMPILE_C_DEPORD = TOOL_VCC80_COMPILE_C_OUTPUT = $(call TOOL_VCC80_PDB, $(outbase)-obj,idb) TOOL_VCC80_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC80_PDB, $(outbase)-obj,pdb) define TOOL_VCC80_COMPILE_C_CMDS $(QUIET)$(TOOL_VCC80_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC80_PDB,$(outbase)-obj,idb) endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80_COMPILE_CXX_DEPEND = TOOL_VCC80_COMPILE_CXX_DEPORD = TOOL_VCC80_COMPILE_CXX_OUTPUT = $(call TOOL_VCC80_PDB, $(outbase)-obj,idb) TOOL_VCC80_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC80_PDB, $(outbase)-obj,pdb) define TOOL_VCC80_COMPILE_CXX_CMDS $(QUIET)$(TOOL_VCC80_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC80_PDB,$(outbase)-obj,idb) endef ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80_COMPILE_RC_OUTPUT = TOOL_VCC80_COMPILE_RC_DEPEND = TOOL_VCC80_COMPILE_RC_DEPORD = define TOOL_VCC80_COMPILE_RC_CMDS $(QUIET)$(TOOL_VCC80_RC) \ $(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\ /fo$(obj)\ $(subst /,\\,$(abspath $(source))) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC80_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VCC80_LINK_LIBRARY_DEPORD = TOOL_VCC80_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_VCC80_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb define TOOL_VCC80_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs) \ $(filter-out %.def,$(othersrc))) \ $(addprefix /DEF:,$(filter %.def,$(othersrc))) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80_AR) $(flags) /OUT:$(out) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC80_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80_LINK_PROGRAM_DEPORD = TOOL_VCC80_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC80_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC80_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out)) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC80_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) TOOL_VCC80_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp TOOL_VCC80_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp TOOL_VCC80_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80_LINK_DLL_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80_LD) $(flags) \ /OUT:$(out) \ /IMPLIB:$(outbase).lib \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ /DLL \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' $(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/ $(eval _DIRS += $(PATH_STAGE_LIB)) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC80_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80_LINK_SYSMOD_DEPORD = TOOL_VCC80_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC80_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC80_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' endef kbuild-2695/kBuild/tools/WATCOMC11C-16.kmk0000644000000000000000000001325312247157310016303 0ustar rootroot# $Id: WATCOMC11C-16.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - Watcom C v11.0c, 16-bit targets. # # @remarks wrc is untested, so are DLLs, and programs. # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_WATCOMC11C-16 = Watcom C/C++ v11.0c - 16-bit targets. TOOL_WATCOMC11C-16_EXTENDS = WATCOMC11C TOOL_WATCOMC11C-16_ASFLAGS.win ?= -bt=windows TOOL_WATCOMC11C-16_CFLAGS.win ?= -bt=windows TOOL_WATCOMC11C-16_CXXFLAGS.win ?= -bt=windows TOOL_WATCOMC11C-16_RCFLAGS.win ?= -bt=windows TOOL_WATCOMC11C-16_LDFLAGS.win ?= -bt=windows TOOL_WATCOMC11C-16_COMPILE_C_DEPEND = TOOL_WATCOMC11C-16_COMPILE_C_DEPORD = TOOL_WATCOMC11C-16_COMPILE_C_OUTPUT = $(obj).err define TOOL_WATCOMC11C-16_COMPILE_C_CMDS $(QUIET) $(call TOOL_WATCOMC11C_ENV_SETUP) $(TOOL_WATCOMC11C_CC16) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(subst /,\\,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(subst /,\\,$(obj)) \ -fr=$(subst /,\\,$(obj)).err \ $(subst /,\\,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_WATCOMC11C-16_COMPILE_CXX_DEPEND = TOOL_WATCOMC11C-16_COMPILE_CXX_DEPORD = TOOL_WATCOMC11C-16_COMPILE_CXX_OUTPUT = $(obj).err define TOOL_WATCOMC11C-16_COMPILE_CXX_CMDS $(QUIET) $(call TOOL_WATCOMC11C_ENV_SETUP) $(TOOL_WATCOMC11C_CXX16) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(subst /,\\,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(subst /,\\,$(obj)) \ -fr=$(subst /,\\,$(obj)).err \ $(subst /,\\,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_WATCOMC11C-16_COMPILE_RC_OUTPUT = TOOL_WATCOMC11C-16_COMPILE_RC_DEPEND = TOOL_WATCOMC11C-16_COMPILE_RC_DEPORD = define TOOL_WATCOMC11C-16_COMPILE_RC_CMDS $(QUIET) $(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) -r\ $(flags) \ $(addprefix -i=, $(subst /,\\,$(incs))) \ $(addprefix -d, $(defs))\ -fo=$(subst /,\\,$(obj)) \ $(subst /,\\,$(abspath $(source))) endef TOOL_WATCOMC11C-16_LINK_LIBRARY_OUTPUT = ## @todo $(outbase).rsp TOOL_WATCOMC11C-16_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_WATCOMC11C-16_LINK_LIBRARY_DEPORD = define TOOL_WATCOMC11C-16_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp $(foreach obj,$(subst /,\,$(objs) $(othersrc)),'+"$(obj)"') $(QUIET)$(TOOL_WATCOMC11C_ENV_SETUP) $(TOOL_WATCOMC11C_AR) $(flags) $(subst /,\\,$(out)) @$(outbase).rsp endef TOOL_WATCOMC11C-16_LINK_PROGRAM_OUTPUT = $(outbase).map TOOL_WATCOMC11C-16_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_WATCOMC11C-16_LINK_PROGRAM_DEPORD = define TOOL_WATCOMC11C-16_LINK_PROGRAM_CMDS $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_WATCOMC11C_LD16) \ $(flags) \ -fe=$(subst /,\\,$(out)) \ -fm=$(subst /,\\,$(outbase).map) \ $(subst /,\\,$(filter-out %.res,$(objs))) \ $(subst /,\\,$(libs)) \ $(subst /,\\,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(subst /,\\,$(out)) \ $(subst /,\\,$(filter %.res,$(objs)))) endef TOOL_WATCOMC11C-16_LINK_DLL_OUTPUT = $(outbase).map TOOL_WATCOMC11C-16_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_WATCOMC11C-16_LINK_DLL_DEPORD = define TOOL_WATCOMC11C-16_LINK_DLL_CMDS $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_WATCOMC11C_LD16) \ $(flags) \ -fe=$(subst /,\\,$(out)) \ -fm=$(subst /,\\,$(outbase).map) \ $(subst /,\\,$(filter-out %.res,$(objs))) \ $(subst /,\\,$(libs)) \ $(subst /,\\,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(subst /,\\,$(out)) \ $(subst /,\\,$(filter %.res,$(objs)))) endef TOOL_WATCOMC11C-16_LINK_SYSMOD_OUTPUT = $(outbase).map TOOL_WATCOMC11C-16_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_WATCOMC11C-16_LINK_SYSMOD_DEPORD = define TOOL_WATCOMC11C-16_LINK_SYSMOD_CMDS $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_WATCOMC11C_LD16) \ $(flags) \ -fe=$(subst /,\\,$(out)) \ -fm=$(subst /,\\,$(outbase).map) \ $(subst /,\\,$(filter-out %.res,$(objs))) \ $(subst /,\\,$(libs)) \ $(subst /,\\,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(subst /,\\,$(out)) \ $(subst /,\\,$(filter %.res,$(objs)))) endef kbuild-2695/kBuild/tools/MINGW32.kmk0000644000000000000000000002513112247157310015541 0ustar rootroot# $Id: MINGW32.kmk 2487 2011-07-21 20:01:27Z bird $ ## @file # kBuild Tool Config - MinGW32 GCC v3.3+. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef TOOL_MINGW32 $(error Already included (TOOL_MINGW32=$(TOOL_MINGW32))) endif TOOL_MINGW32 := MinGW32 GCC v3.3+. # Tool Specific Properties ifndef PATH_TOOL_MINGW32 PATH_TOOL_MINGW32 := $(wildcard $(PATH_DEVTOOLS_BLD)/mingw32/v*.*) ifeq ($(PATH_TOOL_MINGW32),) PATH_TOOL_MINGW32 := $(wildcard $(PATH_DEVTOOLS)/win.x86/mingw32/v*.*) endif ifeq ($(PATH_TOOL_MINGW32),) PATH_TOOL_MINGW32 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/mingw32/v*.*) endif ifneq ($(PATH_TOOL_MINGW32),) PATH_TOOL_MINGW32 := $(lastword $(sort $(PATH_TOOL_MINGW32))) endif else # Resolve any fancy stuff once and for all. PATH_TOOL_MINGW32 := $(PATH_TOOL_MINGW32) endif # figure out if it's native or needs a win32 launcher TOOL_MINGW32_HOSTSUFF_EXE ?= $(HOSTSUFF_EXE) ifndef TOOL_MINGW32_PREFIX ifneq ($(PATH_TOOL_MINGW32),) TOOL_MINGW32_PREFIX := $(PATH_TOOL_MINGW32)/bin/ else TOOL_MINGW32_PREFIX := endif ifneq ($(KBUILD_HOST),win) # we're cross compiling either using an emulator (wine/odin) or a cross compiler. ifneq ($(PATH_TOOL_MINGW32),$(subst /win.x86,,$(subst /x86.win,,$(PATH_TOOL_MINGW32)))) TOOL_MINGW32_PREFIX := $(EXEC_X86_WIN32) $(TOOL_MINGW32_PREFIX) TOOL_MINGW32_HOSTSUFF_EXE := .exe else TOOL_MINGW32_PREFIX := $(TOOL_MINGW32_PREFIX)i386-mingw32msvc- TOOL_MINGW32_HOSTSUFF_EXE := TOOL_MINGW32_XCOMPILE := 1 endif endif else # Resolve any fancy stuff once and for all. TOOL_MINGW32_PREFIX := $(TOOL_MINGW32_PREFIX) endif TOOL_MINGW32_CC ?= $(TOOL_MINGW32_PREFIX)gcc$(TOOL_MINGW32_HOSTSUFF_EXE) TOOL_MINGW32_CXX ?= $(TOOL_MINGW32_PREFIX)g++$(TOOL_MINGW32_HOSTSUFF_EXE) TOOL_MINGW32_AS ?= $(TOOL_MINGW32_PREFIX)gcc$(TOOL_MINGW32_HOSTSUFF_EXE) TOOL_MINGW32_AR ?= $(TOOL_MINGW32_PREFIX)ar$(TOOL_MINGW32_HOSTSUFF_EXE) ifndef TOOL_MINGW32_XCOMPILE# The gentoo package doesn't have g++. TOOL_MINGW32_LD ?= $(TOOL_MINGW32_PREFIX)g++$(TOOL_MINGW32_HOSTSUFF_EXE) else TOOL_MINGW32_LD ?= $(TOOL_MINGW32_PREFIX)gcc$(TOOL_MINGW32_HOSTSUFF_EXE) endif TOOL_MINGW32_DLLWRAP ?= $(TOOL_MINGW32_PREFIX)dllwrap$(TOOL_MINGW32_HOSTSUFF_EXE) TOOL_MINGW32_DLLTOOL ?= $(TOOL_MINGW32_PREFIX)dlltool$(TOOL_MINGW32_HOSTSUFF_EXE) # General Properties used by kBuild TOOL_MINGW32_COBJSUFF ?= .o TOOL_MINGW32_CFLAGS ?= -g TOOL_MINGW32_CFLAGS.debug ?= -O0 TOOL_MINGW32_CFLAGS.release ?= -O2 TOOL_MINGW32_CFLAGS.profile ?= -O2 #-pg TOOL_MINGW32_CINCS ?= TOOL_MINGW32_CDEFS ?= TOOL_MINGW32_CXXOBJSUFF ?= .o TOOL_MINGW32_CXXOBJSUFF ?= .o TOOL_MINGW32_CXXFLAGS ?= -g TOOL_MINGW32_CXXFLAGS.debug ?= -O0 TOOL_MINGW32_CXXFLAGS.release ?= -O2 TOOL_MINGW32_CXXFLAGS.profile ?= -O2 #-pg TOOL_MINGW32_CXXINCS ?= TOOL_MINGW32_CXXDEFS ?= TOOL_MINGW32_ASFLAGS ?= -g -x assembler-with-cpp TOOL_MINGW32_ASOBJSUFF ?= .o TOOL_MINGW32_ARFLAGS ?= cr TOOL_MINGW32_ARLIBSUFF ?= .a TOOL_MINGW32_LDFLAGS ?= TOOL_MINGW32_LDFLAGS.debug ?= -g TOOL_MINGW32_LDFLAGS.release ?= -s ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_MINGW32_COMPILE_C_OUTPUT = TOOL_MINGW32_COMPILE_C_DEPEND = TOOL_MINGW32_COMPILE_C_DEPORD = define TOOL_MINGW32_COMPILE_C_CMDS $(QUIET)$(TOOL_MINGW32_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_MINGW32_COMPILE_CXX_OUTPUT = TOOL_MINGW32_COMPILE_CXX_DEPEND = TOOL_MINGW32_COMPILE_CXX_DEPORD = define TOOL_MINGW32_COMPILE_CXX_CMDS $(QUIET)$(TOOL_MINGW32_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_MINGW32_COMPILE_AS_OUTPUT = TOOL_MINGW32_COMPILE_AS_DEPEND = TOOL_MINGW32_COMPILE_AS_DEPORD = define TOOL_MINGW32_COMPILE_AS_CMDS $(QUIET)$(TOOL_MINGW32_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_MINGW32_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_MINGW32_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_MINGW32_LINK_LIBRARY_DEPORD = define TOOL_MINGW32_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(othersrc), 'ADDLIB $(o)') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(TOOL_MINGW32_AR) -M < $(out).ar-script endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_MINGW32_LINK_PROGRAM_OUTPUT = TOOL_MINGW32_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_MINGW32_LINK_PROGRAM_DEPORD = define TOOL_MINGW32_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_MINGW32_LD) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib))) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_MINGW32_LINK_DLL_OUTPUT = TOOL_MINGW32_LINK_DLL_OUTPUT_MAYBE = $(outbase).a $(outbase).exp $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp $(PATH_STAGE_LIB)/$(notdir $(outbase)).a ## @todo Find a better solution for installing the extra files (.a, .exp, .pdb, etc). TOOL_MINGW32_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def %.res,$(othersrc)) TOOL_MINGW32_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) define TOOL_MINGW32_LINK_DLL_CMDS $(QUIET)$(TOOL_MINGW32_DLLWRAP) $(flags)\ --dllname=$(out)\ --output-exp=$(outbase).exp\ --output-lib=$(outbase).a\ $(foreach def,$(filter %.def,$(othersrc)), --def $(def))\ $(filter %.res,$(othersrc))\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib))) $(QUIET)$(CP) $(outbase).exp $(outbase).a $(PATH_STAGE_LIB)/ endef ## @todo separate install stuff! kbuild-2695/kBuild/tools/WGET.kmk0000644000000000000000000000425712247157310015267 0ustar rootroot# $Id: WGET.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - wget fetchers. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_WGET := wget fetcher. # Tool Specific Properties ifndef TOOL_WGET_FETCH TOOL_WGET_FETCH := $(wildcard $(PATH_DEVTOOLS_BLD)/wget/v*/wget$(HOSTSUFF_EXE)) ifneq ($(TOOL_WGET_FETCH),) TOOL_WGET_FETCH := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/wget$(HOSTSUFF_EXE)) endif ifneq ($(TOOL_WGET_FETCH),) TOOL_WGET_FETCH := $(lastword $(sort $(TOOL_WGET_FETCH))) else TOOL_WGET_FETCH := wget$(HOSTSUFF_EXE) endif else # Resolve any fancy stuff once and for all. TOOL_WGET_FETCH := $(TOOL_WGET_FETCH) endif # General Properties used by kBuild TOOL_WGET_FETCHFLAGS ?= --passive-ftp -t 5 -T 60 ## Fetch one file. # @param $(target) Normalized main target name. # @param $(source) The URI of the file. # @param $(flags) Flags. # @param $(out) The output file TOOL_WGET_FETCH_OUTPUT = TOOL_WGET_FETCH_DEPEND = TOOL_WGET_FETCH_DEPORD = define TOOL_WGET_FETCH_CMDS $(QUIET)$(TOOL_WGET_FETCH) $(flags) -P $(dir $(out)) $(source) endef kbuild-2695/kBuild/tools/LLVMGXX42MACHO.kmk0000644000000000000000000004720012247157310016573 0ustar rootroot# $Id: LLVMGXX42MACHO.kmk 2547 2011-11-04 21:58:53Z bird $ ## @file # kBuild Tool Config - LLVM GCC v4.2.x targeting Darwin (Mac OS X) Mach-O, for building C++ code. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_LLVMGXX42MACHO := LLVM GCC v4.2.x targeting Darwin (Mac OS X) Mach-O, for building C++ code. # Tool Specific Properties TOOL_LLVMGXX42MACHO_PREFIX ?= llvm- TOOL_LLVMGXX42MACHO_SUFFIX ?= -4.2$(HOSTSUFF_EXE) TOOL_LLVMGXX42MACHO_CC ?= $(TOOL_LLVMGXX42MACHO_PREFIX)gcc$(TOOL_LLVMGXX42MACHO_SUFFIX) TOOL_LLVMGXX42MACHO_CXX ?= $(TOOL_LLVMGXX42MACHO_PREFIX)g++$(TOOL_LLVMGXX42MACHO_SUFFIX) TOOL_LLVMGXX42MACHO_OBJC ?= $(TOOL_LLVMGXX42MACHO_PREFIX)gcc$(TOOL_LLVMGXX42MACHO_SUFFIX) TOOL_LLVMGXX42MACHO_OBJCXX ?= $(TOOL_LLVMGXX42MACHO_PREFIX)gcc$(TOOL_LLVMGXX42MACHO_SUFFIX) TOOL_LLVMGXX42MACHO_AS ?= $(TOOL_LLVMGXX42MACHO_PREFIX)gcc$(TOOL_LLVMGXX42MACHO_SUFFIX) TOOL_LLVMGXX42MACHO_LD ?= $(TOOL_LLVMGXX42MACHO_PREFIX)g++$(TOOL_LLVMGXX42MACHO_SUFFIX) TOOL_LLVMGXX42MACHO_LD_SYSMOD ?= $(TOOL_LLVMGXX42MACHO_PREFIX)g++$(TOOL_LLVMGXX42MACHO_SUFFIX) ifndef TOOL_LLVMGXX42MACHO_LDFLAGS.$(KBUILD_TARGET) TOOL_LLVMGXX42MACHO_LDFLAGS.dll ?= -dynamiclib else TOOL_LLVMGXX42MACHO_LDFLAGS.dll ?= $(TOOL_LLVMGXX42MACHO_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_LLVMGXX42MACHO_LDFLAGS.sysmod ?= -r #TOOL_LLVMGXX42MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_LLVMGXX42MACHO_DSYMUTIL ?= dsymutil ifdef SLKRUNS TOOL_LLVMGXX42MACHO_CC += -fmessage-length=0 TOOL_LLVMGXX42MACHO_CXX += -fmessage-length=0 TOOL_LLVMGXX42MACHO_OBJC += -fmessage-length=0 TOOL_LLVMGXX42MACHO_OBJCXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_LLVMGXX42MACHO_COBJSUFF ?= .o TOOL_LLVMGXX42MACHO_CFLAGS ?= TOOL_LLVMGXX42MACHO_CFLAGS.debug ?= -g TOOL_LLVMGXX42MACHO_CFLAGS.profile ?= -O2 #-g -pg TOOL_LLVMGXX42MACHO_CFLAGS.release ?= -O2 TOOL_LLVMGXX42MACHO_CINCS ?= TOOL_LLVMGXX42MACHO_CDEFS ?= TOOL_LLVMGXX42MACHO_CXXOBJSUFF ?= .o TOOL_LLVMGXX42MACHO_CXXFLAGS ?= TOOL_LLVMGXX42MACHO_CXXFLAGS.debug ?= -g TOOL_LLVMGXX42MACHO_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_LLVMGXX42MACHO_CXXFLAGS.release ?= -O2 TOOL_LLVMGXX42MACHO_CXXINCS ?= TOOL_LLVMGXX42MACHO_CXXDEFS ?= TOOL_LLVMGXX42MACHO_OBJCOBJSUFF ?= .o TOOL_LLVMGXX42MACHO_OBJCFLAGS ?= TOOL_LLVMGXX42MACHO_OBJCFLAGS.debug ?= -g TOOL_LLVMGXX42MACHO_OBJCFLAGS.profile?= -O2 #-g -pg TOOL_LLVMGXX42MACHO_OBJCFLAGS.release?= -O2 TOOL_LLVMGXX42MACHO_OBJCINCS ?= TOOL_LLVMGXX42MACHO_OBJCDEFS ?= TOOL_LLVMGXX42MACHO_OBJCXXOBJSUFF ?= .o TOOL_LLVMGXX42MACHO_OBJCXXFLAGS ?= TOOL_LLVMGXX42MACHO_OBJCXXFLAGS.debug ?= -g TOOL_LLVMGXX42MACHO_OBJCXXFLAGS.profile ?= -O2 #-g -pg TOOL_LLVMGXX42MACHO_OBJCXXFLAGS.release ?= -O2 TOOL_LLVMGXX42MACHO_OBJCXXINCS ?= TOOL_LLVMGXX42MACHO_OBJCXXDEFS ?= TOOL_LLVMGXX42MACHO_ASFLAGS ?= -x assembler-with-cpp TOOL_LLVMGXX42MACHO_ASFLAGS.debug ?= -g TOOL_LLVMGXX42MACHO_ASFLAGS.profile ?= -g TOOL_LLVMGXX42MACHO_ASOBJSUFF ?= .o TOOL_LLVMGXX42MACHO_AR ?= ar$(HOSTSUFF_EXE) TOOL_LLVMGXX42MACHO_ARFLAGS ?= -c -rs TOOL_LLVMGXX42MACHO_ARLIBSUFF ?= .a TOOL_LLVMGXX42MACHO_LDFLAGS ?= TOOL_LLVMGXX42MACHO_LDFLAGS.debug ?= -g TOOL_LLVMGXX42MACHO_LDFLAGS.profile ?= -g TOOL_LLVMGXX42MACHO_STRIP_PROGRAM ?= strip -SXxru TOOL_LLVMGXX42MACHO_STRIP_DLL ?= strip -Sxru TOOL_LLVMGXX42MACHO_STRIP_SYSMOD ?= strip -Sru ## # Calculate the files in the debug bundle. # @param 1 The whole output filename. # @param 2 The output filename sans suffix. TOOL_LLVMGXX42MACHO_DEBUG_BUNDLE_FN = \ $(1).dSYM/ \ $(1).dSYM/Contents/ \ $(1).dSYM/Contents/Resources/ \ $(1).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1)) ## # Calculate the files in the debug bundle. # @param 1 The whole linker output filename. # @param 2 The linker output filename sans suffix. # @param 3 The desired install name (no dir slash). # @remarks The Info.plist has some reference to the original name, but gdb # does not care and only check for a symbol file in the DWARF # directory with the same name as the debugged module. TOOL_LLVMGXX42MACHO_DEBUG_INSTALL_FN= \ $(3).dSYM/ \ $(3).dSYM/Contents/ \ $(3).dSYM/Contents/Resources/ \ $(3).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist=>$(3).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1))=>$(3).dSYM/Contents/Resources/DWARF/$(notdir $(3)) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGXX42MACHO_COMPILE_C_DEPEND = TOOL_LLVMGXX42MACHO_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_C_USES_KOBJCACHE = 1 TOOL_LLVMGXX42MACHO_COMPILE_C_OUTPUT = $(outbase).i define TOOL_LLVMGXX42MACHO_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_LLVMGXX42MACHO_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGXX42MACHO_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_C_OUTPUT = define TOOL_LLVMGXX42MACHO_COMPILE_C_CMDS $(QUIET)$(TOOL_LLVMGXX42MACHO_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KUSE_OBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGXX42MACHO_COMPILE_CXX_DEPEND = TOOL_LLVMGXX42MACHO_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_LLVMGXX42MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_LLVMGXX42MACHO_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_LLVMGXX42MACHO_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGXX42MACHO_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_CXX_OUTPUT = define TOOL_LLVMGXX42MACHO_COMPILE_CXX_CMDS $(QUIET)$(TOOL_LLVMGXX42MACHO_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGXX42MACHO_COMPILE_OBJC_DEPEND = TOOL_LLVMGXX42MACHO_COMPILE_OBJC_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1 TOOL_LLVMGXX42MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi define TOOL_LLVMGXX42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_LLVMGXX42MACHO_OBJC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGXX42MACHO_OBJC) -c\ $(flags) -fpreprocessed -x objective-c \ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_OBJC_OUTPUT = define TOOL_LLVMGXX42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(TOOL_LLVMGXX42MACHO_OBJC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGXX42MACHO_COMPILE_OBJCXX_DEPEND = TOOL_LLVMGXX42MACHO_COMPILE_OBJCXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_OBJCXX_USES_KOBJCACHE = 1 TOOL_LLVMGXX42MACHO_COMPILE_OBJCXX_OUTPUT = $(outbase).mii define TOOL_LLVMGXX42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).mii\ $(TOOL_LLVMGXX42MACHO_OBJCXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGXX42MACHO_OBJCXX) -c\ $(flags) -fpreprocessed -x objective-c++ \ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGXX42MACHO_COMPILE_OBJCXX_OUTPUT = define TOOL_LLVMGXX42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(TOOL_LLVMGXX42MACHO_OBJCXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_LLVMGXX42MACHO_COMPILE_AS_OUTPUT = TOOL_LLVMGXX42MACHO_COMPILE_AS_DEPEND = TOOL_LLVMGXX42MACHO_COMPILE_AS_DEPORD = define TOOL_LLVMGXX42MACHO_COMPILE_AS_CMDS $(QUIET)$(TOOL_LLVMGXX42MACHO_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGXX42MACHO_LINK_LIBRARY_OUTPUT = TOOL_LLVMGXX42MACHO_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_LLVMGXX42MACHO_LINK_LIBRARY_DEPORD = define TOOL_LLVMGXX42MACHO_LINK_LIBRARY_CMDS $(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_LLVMGXX42MACHO_AR) $(flags) $(out),$(objs))) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_LLVMGXX42MACHO_AR) -x $(abspath $(lib)) \ && $(RM_EXT) -f ./__.SYMDEF* \ && $(TOOL_LLVMGXX42MACHO_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGXX42MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp TOOL_LLVMGXX42MACHO_LINK_PROGRAM_OUTPUT_DEBUG = $(call TOOL_LLVMGXX42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_LLVMGXX42MACHO_LINK_PROGRAM_DEBUG_INSTALL_FN = $(TOOL_LLVMGXX42MACHO_DEBUG_INSTALL_FN) TOOL_LLVMGXX42MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_LLVMGXX42MACHO_LINK_PROGRAM_DEPORD = define TOOL_LLVMGXX42MACHO_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_LLVMGXX42MACHO_LD) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_LLVMGXX42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_LLVMGXX42MACHO_STRIP_PROGRAM) $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGXX42MACHO_LINK_DLL_OUTPUT = $(outbase).rsp TOOL_LLVMGXX42MACHO_LINK_DLL_OUTPUT_DEBUG = $(call TOOL_LLVMGXX42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_LLVMGXX42MACHO_LINK_DLL_DEBUG_INSTALL_FN = $(TOOL_LLVMGXX42MACHO_DEBUG_INSTALL_FN) TOOL_LLVMGXX42MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_LLVMGXX42MACHO_LINK_DLL_DEPORD = define TOOL_LLVMGXX42MACHO_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_LLVMGXX42MACHO_LD) $(TOOL_LLVMGXX42MACHO_LDFLAGS.dll) $(flags) -o $(out)\ $(call TOOL_LLVMGXX42MACHO_LD_SONAME,$(target),$(out))\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_LLVMGXX42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_LLVMGXX42MACHO_STRIP_DLL) $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGXX42MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp TOOL_LLVMGXX42MACHO_LINK_SYSMOD_OUTPUT_DEBUG = $(call TOOL_LLVMGXX42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_LLVMGXX42MACHO_LINK_SYSMOD_DEBUG_INSTALL_FN = $(TOOL_LLVMGXX42MACHO_DEBUG_INSTALL_FN) TOOL_LLVMGXX42MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_LLVMGXX42MACHO_LINK_SYSMOD_DEPORD = define TOOL_LLVMGXX42MACHO_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_LLVMGXX42MACHO_LD_SYSMOD) $(TOOL_LLVMGXX42MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_LLVMGXX42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_LLVMGXX42MACHO_STRIP_SYSMOD) $(out) endif endef kbuild-2695/kBuild/tools/VCC70.kmk0000644000000000000000000003511412247157310015277 0ustar rootroot# $Id: VCC70.kmk 2557 2011-12-13 12:48:32Z bird $ ## @file # kBuild Tool Config - Visual C++ 7.0 (aka Visual Studio .NET), targeting x86. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VCC70 := Visual C++ 7.0 (aka Visual Studio .NET), targeting x86. # Tool Specific Properties ifndef PATH_TOOL_VCC70 PATH_TOOL_VCC70 := $(firstword $(wildcard \ $(PATH_DEVTOOLS)/win.x86/vcc/v7 \ $(PATH_DEVTOOLS)/x86.win32/vcc/v7 \ $(PATH_DEVTOOLS)/x86.win32/vcc70) ) # if not found, we'll enter 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_VCC70 := $(PATH_TOOL_VCC70) endif ifneq ($(PATH_TOOL_VCC70),) PATH_TOOL_VCC70_BIN ?= $(PATH_TOOL_VCC70)/bin PATH_TOOL_VCC70_LIB ?= $(PATH_TOOL_VCC70)/lib PATH_TOOL_VCC70_INC ?= $(PATH_TOOL_VCC70)/include PATH_TOOL_VCC70_ATLMFC ?= $(PATH_TOOL_VCC70)/atlmfc PATH_TOOL_VCC70_ATLMFC_INC ?= $(PATH_TOOL_VCC70_ATLMFC)/include PATH_TOOL_VCC70_ATLMFC_LIB ?= $(PATH_TOOL_VCC70_ATLMFC)/lib TOOL_VCC70_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/cl.exe TOOL_VCC70_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/cl.exe TOOL_VCC70_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/ml.exe TOOL_VCC70_RC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/rc.exe TOOL_VCC70_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/lib.exe TOOL_VCC70_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC70_BIN)/link.exe else # Pathless, relies on the environment. TOOL_VCC70_CC ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC70_CXX ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC70_AS ?= $(EXEC_X86_WIN32) ml.exe TOOL_VCC70_RC ?= $(EXEC_X86_WIN32) rc.exe TOOL_VCC70_AR ?= $(EXEC_X86_WIN32) lib.exe TOOL_VCC70_LD ?= $(EXEC_X86_WIN32) link.exe endif ## Disabled fast DEP_IDB based dependencies. #VCC70_OLD_DEPS = 1 ## Constructs the correct .pdb name (the name is lowercased). # @param $(1) Base name, no extention. # @param $(2) The extension. TOOL_VCC70_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) # General Properties used by kBuild TOOL_VCC70_COBJSUFF ?= .obj TOOL_VCC70_CFLAGS ?= -TC -c -nologo TOOL_VCC70_CFLAGS.debug ?= -Od -Zi TOOL_VCC70_CFLAGS.release ?= -O2 TOOL_VCC70_CFLAGS.profile ?= -O2 TOOL_VCC70_CINCS ?= $(PATH_TOOL_VCC70_INC) TOOL_VCC70_CDEFS ?= TOOL_VCC70_CXXOBJSUFF ?= .obj TOOL_VCC70_CXXFLAGS ?= -TP -c -nologo TOOL_VCC70_CXXFLAGS.debug ?= -Od -Zi TOOL_VCC70_CXXFLAGS.release ?= -O2 TOOL_VCC70_CXXFLAGS.profile ?= -O2 TOOL_VCC70_CXXINCS ?= $(PATH_TOOL_VCC70_INC) $(PATH_TOOL_VCC70_ATLMFC_INC) TOOL_VCC70_CXXDEFS ?= TOOL_VCC70_ASOBJSUFF ?= .obj TOOL_VCC70_RCOBJSUFF ?= .res TOOL_VCC70_RCINCS ?= $(PATH_TOOL_VCC70_INC) $(PATH_TOOL_VCC70_ATLMFC_INC) TOOL_VCC70_ARFLAGS ?= -nologo TOOL_VCC70_ARLIBSUFF ?= .lib TOOL_VCC70_LDFLAGS ?= -nologo TOOL_VCC70_LDFLAGS.debug ?= -debug TOOL_VCC70_LDFLAGS.release ?= ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC70_COMPILE_C_DONT_PURGE_OUTPUT = TOOL_VCC70_COMPILE_C_DEPEND = TOOL_VCC70_COMPILE_C_DEPORD = #ifdef KBUILD_USE_KOBJCACHE #TOOL_VCC70_COMPILE_C_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC70_PDB, $(outbase)-obj,idb) $(outbase).i #TOOL_VCC70_COMPILE_C_USESES_KOBJCACHE = 1 #define TOOL_VCC70_COMPILE_C_CMDS # $(QUIET)$(KOBJCACHE) -f $(outbase).koc -r --kObjCache-cpp $(outbase).i \ # $(TOOL_VCC70_CC) -E \ # $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ # $(subst /,\\,$(abspath $(source))) \ # --kObjCache-cc $(obj) \ # $(TOOL_VCC70_CC) -c -TC\ # $(flags) \ # -Fd$(outbase)-obj.pdb \ # -FD\ # -Fo$(obj)\ # $(subst /,\\,$(outbase).i) # $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb) #endef #else # !KBUILD_USE_KOBJCACHE TOOL_VCC70_COMPILE_C_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,idb) TOOL_VCC70_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb) define TOOL_VCC70_COMPILE_C_CMDS $(QUIET)$(TOOL_VCC70_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb) endef #endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC70_COMPILE_CXX_DONT_PURGE_OUTPUT = TOOL_VCC70_COMPILE_CXX_DEPEND = TOOL_VCC70_COMPILE_CXX_DEPORD = #ifdef KBUILD_USE_KOBJCACHE #TOOL_VCC70_COMPILE_CXX_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC70_PDB, $(outbase)-obj,idb) $(outbase).ii #TOOL_VCC70_COMPILE_CXX_USES_KOBJCACHE = 1 #define TOOL_VCC70_COMPILE_CXX_CMDS # $(QUIET)$(KOBJCACHE) -f $(outbase).koc -r --kObjCache-cpp $(outbase).ii \ # $(TOOL_VCC70_CC) -E \ # $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ # $(subst /,\\,$(abspath $(source))) \ # --kObjCache-cc $(obj) \ # $(TOOL_VCC70_CC) -c -TP\ # $(flags) \ # -Fd$(outbase)-obj.pdb \ # -FD\ # -Fo$(obj)\ # $(subst /,\\,$(outbase).ii) # $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb) #endef #else # !KBUILD_USE_KOBJCACHE TOOL_VCC70_COMPILE_CXX_OUTPUT = $(call TOOL_VCC70_PDB, $(outbase)-obj,idb) TOOL_VCC70_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC70_PDB, $(outbase)-obj,pdb) define TOOL_VCC70_COMPILE_CXX_CMDS $(QUIET)$(TOOL_VCC70_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC70_PDB,$(outbase)-obj,idb) endef #endif # !KBUILD_USE_KOBJCACHE ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC70_COMPILE_RC_OUTPUT = TOOL_VCC70_COMPILE_RC_DEPEND = TOOL_VCC70_COMPILE_RC_DEPORD = define TOOL_VCC70_COMPILE_RC_CMDS $(QUIET)$(TOOL_VCC70_RC) \ $(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\ /fo$(obj)\ $(subst /,\\,$(abspath $(source))) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC70_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VCC70_LINK_LIBRARY_DEPORD = TOOL_VCC70_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_VCC70_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb define TOOL_VCC70_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs) \ $(filter-out %.def,$(othersrc))) \ $(addprefix /DEF:,$(filter %.def,$(othersrc))) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC70_AR) $(flags) /OUT:$(out) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC70_LINK_PROGRAM_OUTPUT = $(outbase).rsp TOOL_VCC70_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).ilk TOOL_VCC70_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC70_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb TOOL_VCC70_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC70_LINK_PROGRAM_DEPORD = define TOOL_VCC70_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC70_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO /MAPINFO:LINES \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC70_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp TOOL_VCC70_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp TOOL_VCC70_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC70_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb TOOL_VCC70_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC70_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) define TOOL_VCC70_LINK_DLL_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC70_LD) $(flags) \ /OUT:$(out) \ /IMPLIB:$(outbase).lib \ /MAPINFO:EXPORTS /INCREMENTAL:NO /MAPINFO:LINES \ /MAP:$(outbase).map \ /DLL \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/ $(eval _DIRS += $(PATH_STAGE_LIB)) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC70_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC70_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk TOOL_VCC70_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC70_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb TOOL_VCC70_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC70_LINK_SYSMOD_DEPORD = define TOOL_VCC70_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC70_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO /MAPINFO:LINES \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp endef kbuild-2695/kBuild/tools/GXX64.kmk0000644000000000000000000003217312247157310015337 0ustar rootroot# $Id: GXX64.kmk 2541 2011-08-03 09:51:30Z bird $ ## @file # kBuild Tool Config - Generic 64-bit GCC v3.2.x or later using the system GCC, for building C++ code. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX64 := Generic 64-bit GCC v3.2.x or later using the system GCC, for building C++ code. \ More or less Linux/ELF specfic. # Tool Specific Properties TOOL_GXX64_CC ?= gcc$(HOSTSUFF_EXE) -m64 TOOL_GXX64_CXX ?= g++$(HOSTSUFF_EXE) -m64 TOOL_GXX64_AS ?= gcc$(HOSTSUFF_EXE) -m64 TOOL_GXX64_AR ?= ar$(HOSTSUFF_EXE) TOOL_GXX64_LD ?= g++$(HOSTSUFF_EXE) -m64 TOOL_GXX64_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) ifndef TOOL_GXX64_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX64_LDFLAGS.dll ?= -shared else TOOL_GXX64_LDFLAGS.dll ?= $(TOOL_GXX64_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GXX64_LDFLAGS.sysmod ?= -r -m elf_x86_64$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,) TOOL_GXX64_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) ifeq ($(KBUILD_TARGET),os2) TOOL_GXX64_LD_MAP ?= -Zmap=$(1) else TOOL_GXX64_LD_MAP ?= endif ifeq ($(KBUILD_TARGET),os2) TOOL_GXX64_LD_SYSMOD_MAP ?= -Zmap=$(1) else TOOL_GXX64_LD_SYSMOD_MAP ?= endif if1of ($(KBUILD_HOST), solaris) TOOL_GXX64_OBJCOPY ?= gobjcopy$(HOSTSUFF_EXE) else TOOL_GXX64_OBJCOPY ?= objcopy$(HOSTSUFF_EXE) endif ifdef SLKRUNS TOOL_GXX64_CC += -fmessage-length=0 TOOL_GXX64_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GXX64_COBJSUFF ?= .o TOOL_GXX64_CFLAGS ?= TOOL_GXX64_CFLAGS.debug ?= -g TOOL_GXX64_CFLAGS.profile ?= -O2 #-g -pg TOOL_GXX64_CFLAGS.release ?= -O2 TOOL_GXX64_CINCS ?= TOOL_GXX64_CDEFS ?= TOOL_GXX64_CXXOBJSUFF ?= .o TOOL_GXX64_CXXOBJSUFF ?= .o TOOL_GXX64_CXXFLAGS ?= TOOL_GXX64_CXXFLAGS.debug ?= -g TOOL_GXX64_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX64_CXXFLAGS.release ?= -O2 TOOL_GXX64_CXXINCS ?= TOOL_GXX64_CXXDEFS ?= TOOL_GXX64_ASFLAGS ?= -x assembler-with-cpp TOOL_GXX64_ASFLAGS.debug ?= -g TOOL_GXX64_ASFLAGS.profile ?= -g TOOL_GXX64_ASOBJSUFF ?= .o TOOL_GXX64_ARFLAGS ?= cr TOOL_GXX64_ARLIBSUFF ?= .a TOOL_GXX64_LDFLAGS ?= TOOL_GXX64_LDFLAGS.debug ?= -g TOOL_GXX64_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX64_COMPILE_C_DEPEND = TOOL_GXX64_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX64_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GXX64_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GXX64_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GXX64_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX64_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX64_COMPILE_C_OUTPUT = define TOOL_GXX64_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX64_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX64_COMPILE_CXX_DEPEND = TOOL_GXX64_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX64_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GXX64_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GXX64_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX64_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX64_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX64_COMPILE_CXX_OUTPUT = define TOOL_GXX64_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX64_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX64_COMPILE_AS_OUTPUT = TOOL_GXX64_COMPILE_AS_DEPEND = TOOL_GXX64_COMPILE_AS_DEPORD = define TOOL_GXX64_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX64_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX64_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_GXX64_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GXX64_LINK_LIBRARY_DEPORD = define TOOL_GXX64_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(othersrc), 'ADDLIB $(o)') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GXX64_AR) -M endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX64_LINK_PROGRAM_OUTPUT = TOOL_GXX64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GXX64_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX64_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX64_LINK_PROGRAM_DEPORD = define TOOL_GXX64_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GXX64_LD) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX64_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX64_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX64_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX64_LINK_DLL_OUTPUT = TOOL_GXX64_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GXX64_LINK_DLL_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX64_LINK_DLL_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX64_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX64_LINK_DLL_DEPORD = define TOOL_GXX64_LINK_DLL_CMDS $(QUIET)$(TOOL_GXX64_LD) $(TOOL_GXX64_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GXX64_LD_SONAME,$(target),$(out)))\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX64_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX64_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX64_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX64_LINK_SYSMOD_OUTPUT = TOOL_GXX64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GXX64_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX64_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX64_LINK_SYSMOD_DEPORD = define TOOL_GXX64_LINK_SYSMOD_CMDS $(QUIET)$(TOOL_GXX64_LD_SYSMOD) $(TOOL_GXX64_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX64_LD_SYSMOD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX64_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX64_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef kbuild-2695/kBuild/tools/MASM510.kmk0000644000000000000000000001024112247157310015472 0ustar rootroot# $Id: MASM510.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - MASM v5.10 # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_MASM510 := Microsoft Macro Assembler v5.10 # Tool Specific Properties ifndef TOOL_MASM510_AS TOOL_MASM510_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/masm/v5.10*/masm$(HOSTSUFF_EXE)))) ifeq ($(TOOL_MASM510_AS),) TOOL_MASM510_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/masm/v5.10*/masm$(HOSTSUFF_EXE)))) endif ifeq ($(TOOL_MASM510_AS),) TOOL_MASM510_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS)/os2.x86/ddk/*/base/tools/masm$(HOSTSUFF_EXE)))) endif ifeq ($(TOOL_MASM510_AS),) TOOL_MASM510_AS := $(firstword $(rsort $(wildcard \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/video/tools/os2.386/lx.386/bin/masm$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/base32/tools/os2.386/bin/masm$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/base32/tools/os2.386/lx.386/bin/masm$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/print/tools/os2.386/lx.386/bin/masm$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/wpshell/tools/os2.386/lx.386/bin/masm$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/mme/tools/os2.386/lx.386/bin/masm$(HOSTSUFF_EXE) \ ))) endif ifneq ($(TOOL_MASM510_AS),) TOOL_MASM510_AS := $(TOOL_MASM510_AS) endif endif ifeq ($(TOOL_MASM510_AS),) TOOL_MASM510_AS := $(firstword $(which masm$(HOSTSUFF_EXE)) path/notfound/masm$(HOSTSUFF_EXE)) endif # General Properties used by kBuild TOOL_MASM510_ASFLAGS ?= -t -z -Zd -Zi -t ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # # @remarks MASM v5.10 has severe length limitations in several places and will respond with # crashing when these are exceeded. Thus, we use MASM and INCLUDE to avoid exceeding # the command line length (and the MASM length). # The closing of file handles and zapping of environment is to make sure it doesn't # mess up due handles left behind by some device init or because the env is too big. TOOL_MASM510_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_MASM510_COMPILE_AS_DEPEND = TOOL_MASM510_COMPILE_AS_DEPORD = define TOOL_MASM510_COMPILE_AS_CMDS $(QUIET)$(REDIRECT) \ -c3 -c4 -c5 -c6 -c7 -c8 -c9 -c10 -c11 -c12 -c13 -c14 -c15 -c16 -c17 -c18 -c19 -Z \ -E 'MASM=$(addprefix -D, $(subst /,\,$(defs)))' \ -E 'INCLUDE=$(subst $(SP),,$(addsuffix ;,$(subst /,\,$(incs))))' \ -- \ $(subst /,\\,$(TOOL_MASM510_AS)) $(strip $(flags)) '$(subst /,\,$(source),$(obj),$(outbase).lst);' endef kbuild-2695/kBuild/tools/LLVMGCC42MACHO.kmk0000644000000000000000000004713512247157310016530 0ustar rootroot# $Id: LLVMGCC42MACHO.kmk 2547 2011-11-04 21:58:53Z bird $ ## @file # kBuild Tool Config - LLVM GCC v4.2.x targeting Darwin (Mac OS X) Mach-O. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_LLVMGCC42MACHO := LLVM GCC v4.2.x targeting Darwin (Mac OS X) Mach-O. # Tool Specific Properties TOOL_LLVMGCC42MACHO_PREFIX ?= llvm- TOOL_LLVMGCC42MACHO_SUFFIX ?= -4.2$(HOSTSUFF_EXE) TOOL_LLVMGCC42MACHO_CC ?= $(TOOL_LLVMGCC42MACHO_PREFIX)gcc$(TOOL_LLVMGCC42MACHO_SUFFIX) TOOL_LLVMGCC42MACHO_CXX ?= $(TOOL_LLVMGCC42MACHO_PREFIX)g++$(TOOL_LLVMGCC42MACHO_SUFFIX) TOOL_LLVMGCC42MACHO_OBJC ?= $(TOOL_LLVMGCC42MACHO_PREFIX)gcc$(TOOL_LLVMGCC42MACHO_SUFFIX) TOOL_LLVMGCC42MACHO_OBJCXX ?= $(TOOL_LLVMGCC42MACHO_PREFIX)gcc$(TOOL_LLVMGCC42MACHO_SUFFIX) TOOL_LLVMGCC42MACHO_AS ?= $(TOOL_LLVMGCC42MACHO_PREFIX)gcc$(TOOL_LLVMGCC42MACHO_SUFFIX) TOOL_LLVMGCC42MACHO_LD ?= $(TOOL_LLVMGCC42MACHO_PREFIX)gcc$(TOOL_LLVMGCC42MACHO_SUFFIX) TOOL_LLVMGCC42MACHO_LD_SYSMOD ?= $(TOOL_LLVMGCC42MACHO_PREFIX)gcc$(TOOL_LLVMGCC42MACHO_SUFFIX) ifndef TOOL_LLVMGCC42MACHO_LDFLAGS.$(KBUILD_TARGET) TOOL_LLVMGCC42MACHO_LDFLAGS.dll ?= -dynamiclib else TOOL_LLVMGCC42MACHO_LDFLAGS.dll ?= $(TOOL_LLVMGCC42MACHO_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_LLVMGCC42MACHO_LDFLAGS.sysmod ?= -r #TOOL_LLVMGCC42MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_LLVMGCC42MACHO_DSYMUTIL ?= dsymutil ifdef SLKRUNS TOOL_LLVMGCC42MACHO_CC += -fmessage-length=0 TOOL_LLVMGCC42MACHO_CXX += -fmessage-length=0 TOOL_LLVMGCC42MACHO_OBJC += -fmessage-length=0 TOOL_LLVMGCC42MACHO_OBJCXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_LLVMGCC42MACHO_COBJSUFF ?= .o TOOL_LLVMGCC42MACHO_CFLAGS ?= TOOL_LLVMGCC42MACHO_CFLAGS.debug ?= -g TOOL_LLVMGCC42MACHO_CFLAGS.profile ?= -g -O2 #-pg TOOL_LLVMGCC42MACHO_CFLAGS.release ?= -O2 TOOL_LLVMGCC42MACHO_CINCS ?= TOOL_LLVMGCC42MACHO_CDEFS ?= TOOL_LLVMGCC42MACHO_CXXOBJSUFF ?= .o TOOL_LLVMGCC42MACHO_CXXFLAGS ?= TOOL_LLVMGCC42MACHO_CXXFLAGS.debug ?= -g TOOL_LLVMGCC42MACHO_CXXFLAGS.profile ?= -g -O2 #-pg TOOL_LLVMGCC42MACHO_CXXFLAGS.release ?= -O2 TOOL_LLVMGCC42MACHO_CXXINCS ?= TOOL_LLVMGCC42MACHO_CXXDEFS ?= TOOL_LLVMGCC42MACHO_OBJCOBJSUFF ?= .o TOOL_LLVMGCC42MACHO_OBJCFLAGS ?= TOOL_LLVMGCC42MACHO_OBJCFLAGS.debug ?= -g TOOL_LLVMGCC42MACHO_OBJCFLAGS.profile?= -O2 #-g -pg TOOL_LLVMGCC42MACHO_OBJCFLAGS.release?= -O2 TOOL_LLVMGCC42MACHO_OBJCINCS ?= TOOL_LLVMGCC42MACHO_OBJCDEFS ?= TOOL_LLVMGCC42MACHO_OBJCXXOBJSUFF ?= .o TOOL_LLVMGCC42MACHO_OBJCXXFLAGS ?= TOOL_LLVMGCC42MACHO_OBJCXXFLAGS.debug ?= -g TOOL_LLVMGCC42MACHO_OBJCXXFLAGS.profile ?= -O2 #-g -pg TOOL_LLVMGCC42MACHO_OBJCXXFLAGS.release ?= -O2 TOOL_LLVMGCC42MACHO_OBJCXXINCS ?= TOOL_LLVMGCC42MACHO_OBJCXXDEFS ?= TOOL_LLVMGCC42MACHO_ASFLAGS ?= -x assembler-with-cpp TOOL_LLVMGCC42MACHO_ASFLAGS.debug ?= -g TOOL_LLVMGCC42MACHO_ASFLAGS.profile ?= -g TOOL_LLVMGCC42MACHO_ASOBJSUFF ?= .o TOOL_LLVMGCC42MACHO_AR ?= ar$(HOSTSUFF_EXE) TOOL_LLVMGCC42MACHO_ARFLAGS ?= -c -rs TOOL_LLVMGCC42MACHO_ARLIBSUFF ?= .a TOOL_LLVMGCC42MACHO_LDFLAGS ?= TOOL_LLVMGCC42MACHO_LDFLAGS.debug ?= -g TOOL_LLVMGCC42MACHO_LDFLAGS.profile ?= -g TOOL_LLVMGCC42MACHO_STRIP_PROGRAM ?= strip -SXxru TOOL_LLVMGCC42MACHO_STRIP_DLL ?= strip -Sxru TOOL_LLVMGCC42MACHO_STRIP_SYSMOD ?= strip -Sru ## # Calculate the files in the debug bundle. # @param 1 The whole output filename. # @param 2 The output filename sans suffix. TOOL_LLVMGCC42MACHO_DEBUG_BUNDLE_FN = \ $(1).dSYM/ \ $(1).dSYM/Contents/ \ $(1).dSYM/Contents/Resources/ \ $(1).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1)) ## # Calculate the files in the debug bundle. # @param 1 The whole linker output filename. # @param 2 The linker output filename sans suffix. # @param 3 The desired install name (no dir slash). # @remarks The Info.plist has some reference to the original name, but gdb # does not care and only check for a symbol file in the DWARF # directory with the same name as the debugged module. TOOL_LLVMGCC42MACHO_DEBUG_INSTALL_FN= \ $(3).dSYM/ \ $(3).dSYM/Contents/ \ $(3).dSYM/Contents/Resources/ \ $(3).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist=>$(3).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1))=>$(3).dSYM/Contents/Resources/DWARF/$(notdir $(3)) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGCC42MACHO_COMPILE_C_DEPEND = TOOL_LLVMGCC42MACHO_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_C_USES_KOBJCACHE = 1 TOOL_LLVMGCC42MACHO_COMPILE_C_OUTPUT = $(outbase).i define TOOL_LLVMGCC42MACHO_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_LLVMGCC42MACHO_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGCC42MACHO_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_C_OUTPUT = define TOOL_LLVMGCC42MACHO_COMPILE_C_CMDS $(QUIET)$(TOOL_LLVMGCC42MACHO_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KUSE_OBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGCC42MACHO_COMPILE_CXX_DEPEND = TOOL_LLVMGCC42MACHO_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_LLVMGCC42MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_LLVMGCC42MACHO_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_LLVMGCC42MACHO_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGCC42MACHO_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_CXX_OUTPUT = define TOOL_LLVMGCC42MACHO_COMPILE_CXX_CMDS $(QUIET)$(TOOL_LLVMGCC42MACHO_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGCC42MACHO_COMPILE_OBJC_DEPEND = TOOL_LLVMGCC42MACHO_COMPILE_OBJC_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1 TOOL_LLVMGCC42MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi define TOOL_LLVMGCC42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_LLVMGCC42MACHO_OBJC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGCC42MACHO_OBJC) -c\ $(flags) -fpreprocessed -x cbjective-c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_OBJC_OUTPUT = define TOOL_LLVMGCC42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(TOOL_LLVMGCC42MACHO_OBJC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_LLVMGCC42MACHO_COMPILE_OBJCXX_DEPEND = TOOL_LLVMGCC42MACHO_COMPILE_OBJCXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_OBJCXX_USES_KOBJCACHE = 1 TOOL_LLVMGCC42MACHO_COMPILE_OBJCXX_OUTPUT = $(outbase).mii define TOOL_LLVMGCC42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).mii\ $(TOOL_LLVMGCC42MACHO_OBJCXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_LLVMGCC42MACHO_OBJCXX) -c\ $(flags) -fpreprocessed -x objective-c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_LLVMGCC42MACHO_COMPILE_OBJCXX_OUTPUT = define TOOL_LLVMGCC42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(TOOL_LLVMGCC42MACHO_OBJCXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_LLVMGCC42MACHO_COMPILE_AS_OUTPUT = TOOL_LLVMGCC42MACHO_COMPILE_AS_DEPEND = TOOL_LLVMGCC42MACHO_COMPILE_AS_DEPORD = define TOOL_LLVMGCC42MACHO_COMPILE_AS_CMDS $(QUIET)$(TOOL_LLVMGCC42MACHO_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGCC42MACHO_LINK_LIBRARY_OUTPUT = TOOL_LLVMGCC42MACHO_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_LLVMGCC42MACHO_LINK_LIBRARY_DEPORD = define TOOL_LLVMGCC42MACHO_LINK_LIBRARY_CMDS $(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_LLVMGCC42MACHO_AR) $(flags) $(out),$(objs))) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_LLVMGCC42MACHO_AR) -x $(abspath $(lib)) \ && $(RM_EXT) -f ./__.SYMDEF* \ && $(TOOL_LLVMGCC42MACHO_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGCC42MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp TOOL_LLVMGCC42MACHO_LINK_PROGRAM_OUTPUT_DEBUG = $(call TOOL_LLVMGCC42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_LLVMGCC42MACHO_LINK_PROGRAM_DEBUG_INSTALL_FN = $(TOOL_LLVMGCC42MACHO_DEBUG_INSTALL_FN) TOOL_LLVMGCC42MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_LLVMGCC42MACHO_LINK_PROGRAM_DEPORD = define TOOL_LLVMGCC42MACHO_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_LLVMGCC42MACHO_LD) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_LLVMGCC42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_LLVMGCC42MACHO_STRIP_PROGRAM) $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGCC42MACHO_LINK_DLL_OUTPUT = $(outbase).rsp TOOL_LLVMGCC42MACHO_LINK_DLL_OUTPUT_DEBUG = $(call TOOL_LLVMGCC42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_LLVMGCC42MACHO_LINK_DLL_DEBUG_INSTALL_FN = $(TOOL_LLVMGCC42MACHO_DEBUG_INSTALL_FN) TOOL_LLVMGCC42MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_LLVMGCC42MACHO_LINK_DLL_DEPORD = define TOOL_LLVMGCC42MACHO_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_LLVMGCC42MACHO_LD) $(TOOL_LLVMGCC42MACHO_LDFLAGS.dll) $(flags) -o $(out)\ $(call TOOL_LLVMGCC42MACHO_LD_SONAME,$(target),$(out))\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_LLVMGCC42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_LLVMGCC42MACHO_STRIP_DLL) $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_LLVMGCC42MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp TOOL_LLVMGCC42MACHO_LINK_SYSMOD_OUTPUT_DEBUG = $(call TOOL_LLVMGCC42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_LLVMGCC42MACHO_LINK_SYSMOD_DEBUG_INSTALL_FN = $(TOOL_LLVMGCC42MACHO_DEBUG_INSTALL_FN) TOOL_LLVMGCC42MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_LLVMGCC42MACHO_LINK_SYSMOD_DEPORD = define TOOL_LLVMGCC42MACHO_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_LLVMGCC42MACHO_LD_SYSMOD) $(TOOL_LLVMGCC42MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_LLVMGCC42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_LLVMGCC42MACHO_STRIP_SYSMOD) $(out) endif endef kbuild-2695/kBuild/tools/WATCOMC11C.kmk0000644000000000000000000002243012247157310016054 0ustar rootroot# $Id: WATCOMC11C.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - Watcom C v11.0c # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_WATCOMC11C = Watcom C/C++ v11.0c (generic) ifeq ($(PATH_TOOL_WATCOMC11C),) ifeq ($(PATH_TOOL_WATCOMC11C),) PATH_TOOL_WATCOMC11C := $(wildcard $(PATH_DEVTOOLS_BLD)/watcom/v11.0c*) endif ifeq ($(PATH_TOOL_WATCOMC11C),) PATH_TOOL_WATCOMC11C := $(wildcard $(PATH_DEVTOOLS_TRG)/watcom/v11.0c*) endif ifeq ($(PATH_TOOL_WATCOMC11C),) PATH_TOOL_WATCOMC11C := $(wildcard $(PATH_DEVTOOLS)/common/watcom/v11.0c*) endif ifeq ($(PATH_TOOL_WATCOMC11C)$(KBUILD_HOST),os2) if1of ($(USER) $(USERNAME) $(LOGNAME), bird) PATH_TOOL_WATCOMC11C := $(wildcard d:/dev/Watcom/v11.0c*) endif endif PATH_TOOL_WATCOMC11C := $(firstword $(sort $(PATH_TOOL_WATCOMC11C))) # if not found, we'll enter 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_WATCOMC11C := $(PATH_TOOL_WATCOMC11C) endif ifneq ($(PATH_TOOL_WATCOMC11C),) TOOL_WATCOMC11C_PATHLESS := no ifeq ($(KBUILD_HOST),os2) PATH_TOOL_WATCOMC11C_BIN = $(PATH_TOOL_WATCOMC11C)/binp PATH_TOOL_WATCOMC11C_BIN2 = $(PATH_TOOL_WATCOMC11C)/binw TOOL_WATCOMC11C_ENV_SETUP ?= $(REDIRECT) \ -E 'BEGINLIBPATH=$(PATH_TOOL_WATCOMC11C)/binp/dll;$(BEGINLIBPATH)' \ -E 'LIBPATHSTRICT=T' \ -E 'PATH=$(PATH_TOOL_WATCOMC11C_BIN);$(PATH_TOOL_WATCOMC11C_BIN2)' \ -E 'WATCOM=$(PATH_TOOL_WATCOMC11C)' \ -E 'EDPATH=$(PATH_TOOL_WATCOMC11C)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- else PATH_TOOL_WATCOMC11C_BIN = $(PATH_TOOL_WATCOMC11C)/binnt PATH_TOOL_WATCOMC11C_BIN2 = $(PATH_TOOL_WATCOMC11C_BIN) TOOL_WATCOMC11C_ENV_SETUP ?= $(REDIRECT) \ -E 'PATH=$(PATH_TOOL_WATCOMC11C_BIN);$(PATH_TOOL_WATCOMC11C)/binw' \ -E 'WATCOM=$(PATH_TOOL_WATCOMC11C)' \ -E 'EDPATH=$(PATH_TOOL_WATCOMC11C)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- endif TOOL_WATCOMC11C_CC ?= $(PATH_TOOL_WATCOMC11C_BIN)/wcc386$(HOSTSUFF_EXE) TOOL_WATCOMC11C_CC16 ?= $(PATH_TOOL_WATCOMC11C_BIN)/wcc$(HOSTSUFF_EXE) TOOL_WATCOMC11C_CXX ?= $(PATH_TOOL_WATCOMC11C_BIN)/wpp386$(HOSTSUFF_EXE) TOOL_WATCOMC11C_CXX16 ?= $(PATH_TOOL_WATCOMC11C_BIN)/wpp$(HOSTSUFF_EXE) TOOL_WATCOMC11C_AS ?= $(PATH_TOOL_WATCOMC11C_BIN)/wasm$(HOSTSUFF_EXE) TOOL_WATCOMC11C_AR ?= $(PATH_TOOL_WATCOMC11C_BIN)/wlib$(HOSTSUFF_EXE) TOOL_WATCOMC11C_RC ?= $(PATH_TOOL_WATCOMC11C_BIN2)/wrc$(HOSTSUFF_EXE) TOOL_WATCOMC11C_LD ?= $(PATH_TOOL_WATCOMC11C_BIN2)/wcl386$(HOSTSUFF_EXE) TOOL_WATCOMC11C_LD16 ?= $(PATH_TOOL_WATCOMC11C_BIN2)/wcl$(HOSTSUFF_EXE) TOOL_WATCOMC11C_WLINK ?= $(PATH_TOOL_WATCOMC11C_BIN2)/wlink$(HOSTSUFF_EXE) else # Pathless, relies on the environment. TOOL_WATCOMC11C_PATHLESS := TOOL_WATCOMC11C_ENV_SETUP ?= $(REDIRECT) \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- TOOL_WATCOMC11C_CC ?= wcc386$(HOSTSUFF_EXE) TOOL_WATCOMC11C_CC16 ?= wcc$(HOSTSUFF_EXE) TOOL_WATCOMC11C_CXX ?= wpp386$(HOSTSUFF_EXE) TOOL_WATCOMC11C_CXX16 ?= wpp$(HOSTSUFF_EXE) TOOL_WATCOMC11C_AS ?= wasm$(HOSTSUFF_EXE) TOOL_WATCOMC11C_AR ?= wlib$(HOSTSUFF_EXE) TOOL_WATCOMC11C_RC ?= wrc$(HOSTSUFF_EXE) TOOL_WATCOMC11C_LD ?= wcl386$(HOSTSUFF_EXE) TOOL_WATCOMC11C_LD16 ?= wcl$(HOSTSUFF_EXE) TOOL_WATCOMC11C_WLINK ?= wcl$(HOSTSUFF_EXE) endif # General Properties used by kBuild TOOL_WATCOMC11C_COBJSUFF ?= .obj TOOL_WATCOMC11C_CFLAGS ?= -zq TOOL_WATCOMC11C_CFLAGS.dos ?= -bt=dos TOOL_WATCOMC11C_CFLAGS.os2 ?= -bt=os2 TOOL_WATCOMC11C_CFLAGS.win ?= -bt=nt ifdef PATH_TOOL_WATCOMC11C TOOL_WATCOMC11C_CINCS ?= $(PATH_TOOL_WATCOMC11C)/h endif TOOL_WATCOMC11C_CXXOBJSUFF ?= .obj TOOL_WATCOMC11C_CXXFLAGS ?= -zq TOOL_WATCOMC11C_CXXFLAGS.dos ?= -bt=dos TOOL_WATCOMC11C_CXXFLAGS.os2 ?= -bt=os2 TOOL_WATCOMC11C_CXXFLAGS.win ?= -bt=nt ifdef PATH_TOOL_WATCOMC11C TOOL_WATCOMC11C_CXXINCS ?= $(PATH_TOOL_WATCOMC11C)/h endif TOOL_WATCOMC11C_RCOBJSUFF ?= .res TOOL_WATCOMC11C_RCFLAGS ?= -r ifdef PATH_TOOL_WATCOMC11C TOOL_WATCOMC11C_RCINCS ?= $(PATH_TOOL_WATCOMC11C)/h endif TOOL_WATCOMC11C_ARFLAGS ?= -q TOOL_WATCOMC11C_ARLIBSUFF ?= .lib TOOL_WATCOMC11C_LDFLAGS ?= -zq -y TOOL_WATCOMC11C_LDFLAGS.dos ?= -bt=dos TOOL_WATCOMC11C_LDFLAGS.os2 ?= -bt=os2 TOOL_WATCOMC11C_LDFLAGS.win ?= -bt=nt TOOL_WATCOMC11C_COMPILE_C_DEPEND = TOOL_WATCOMC11C_COMPILE_C_DEPORD = TOOL_WATCOMC11C_COMPILE_C_OUTPUT = $(obj).err define TOOL_WATCOMC11C_COMPILE_C_CMDS $(QUIET) $(call TOOL_WATCOMC11C_ENV_SETUP) $(TOOL_WATCOMC11C_CC) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(subst /,\\,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(subst /,\\,$(obj)) \ -fr=$(subst /,\\,$(obj)).err \ $(subst /,\\,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_WATCOMC11C_COMPILE_CXX_DEPEND = TOOL_WATCOMC11C_COMPILE_CXX_DEPORD = TOOL_WATCOMC11C_COMPILE_CXX_OUTPUT = $(obj).err define TOOL_WATCOMC11C_COMPILE_CXX_CMDS $(QUIET) $(call TOOL_WATCOMC11C_ENV_SETUP) $(TOOL_WATCOMC11C_CXX) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(subst /,\\,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(subst /,\\,$(obj)) \ -fr=$(subst /,\\,$(obj)).err \ $(subst /,\\,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_WATCOMC11C_COMPILE_RC_OUTPUT = TOOL_WATCOMC11C_COMPILE_RC_DEPEND = TOOL_WATCOMC11C_COMPILE_RC_DEPORD = define TOOL_WATCOMC11C_COMPILE_RC_CMDS $(QUIET) $(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) -r\ $(flags) \ $(addprefix -i=, $(subst /,\\,$(incs))) \ $(addprefix -d, $(defs))\ -fo=$(subst /,\\,$(obj)) \ $(subst /,\\,$(abspath $(source))) endef TOOL_WATCOMC11C_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_WATCOMC11C_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_WATCOMC11C_LINK_LIBRARY_DEPORD = define TOOL_WATCOMC11C_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp $(foreach obj,$(subst /,\,$(objs) $(othersrc)),'+"$(obj)"') $(QUIET)$(TOOL_WATCOMC11C_ENV_SETUP) $(TOOL_WATCOMC11C_AR) $(flags) $(subst /,\\,$(out)) @$(outbase).rsp endef TOOL_WATCOMC11C_LINK_PROGRAM_OUTPUT = $(outbase).map TOOL_WATCOMC11C_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_WATCOMC11C_LINK_PROGRAM_DEPORD = define TOOL_WATCOMC11C_LINK_PROGRAM_CMDS $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_WATCOMC11C_LD) \ $(flags) \ -fe=$(subst /,\\,$(out)) \ -fm=$(subst /,\\,$(outbase).map) \ $(subst /,\\,$(filter-out %.res,$(objs))) \ $(subst /,\\,$(libs)) \ $(subst /,\\,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(subst /,\\,$(out)) \ $(subst /,\\,$(filter %.res,$(objs)))) endef TOOL_WATCOMC11C_LINK_DLL_OUTPUT = $(outbase).map TOOL_WATCOMC11C_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_WATCOMC11C_LINK_DLL_DEPORD = define TOOL_WATCOMC11C_LINK_DLL_CMDS $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_WATCOMC11C_LD) \ $(flags) \ -fe=$(subst /,\\,$(out)) \ -fm=$(subst /,\\,$(outbase).map) \ $(subst /,\\,$(filter-out %.res,$(objs))) \ $(subst /,\\,$(libs)) \ $(subst /,\\,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(subst /,\\,$(out)) \ $(subst /,\\,$(filter %.res,$(objs)))) endef TOOL_WATCOMC11C_LINK_SYSMOD_OUTPUT = $(outbase).map TOOL_WATCOMC11C_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_WATCOMC11C_LINK_SYSMOD_DEPORD = define TOOL_WATCOMC11C_LINK_SYSMOD_CMDS $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_WATCOMC11C_LD) \ $(flags) \ -fe=$(subst /,\\,$(out)) \ -fm=$(subst /,\\,$(outbase).map) \ $(subst /,\\,$(filter-out %.res,$(objs))) \ $(subst /,\\,$(libs)) \ $(subst /,\\,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_WATCOMC11C_ENV_SETUP) \ $(TOOL_WATCOMC11C_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(subst /,\\,$(out)) \ $(subst /,\\,$(filter %.res,$(objs)))) endef kbuild-2695/kBuild/tools/YACC.kmk0000644000000000000000000000377012247157310015237 0ustar rootroot# $Id: YACC.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # yacc tool # # # Copyright (c) 2009-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_YACC = yacc ifndef TOOL_YACC_YACC TOOL_YACC_YACC := $(firstword $(which byacc$(HOSTSUFF_EXE)) $(which yacc$(HOSTSUFF_EXE)) yacc$(HOSTSUFF_EXE)) endif #TOOL_YACC_YACCFLAGS ?= TOOL_YACC_YACC_OUTPUT = $(evalcall KB_FN_OPT_TEST_SHORT,d,$(flags),$(outbase).h$(substr $(suffix $(source)),3),) TOOL_YACC_YACC_OUTPUT_MAYBE = $(outbase).tab.c$(substr $(suffix $(source)),3) $(outbase).tab.h$(substr $(suffix $(source)),3) TOOL_YACC_YACC_DEPEND = TOOL_YACC_YACC_DEPORD = define TOOL_YACC_YACC_CMDS $(QUIET)$(TOOL_YACC_YACC) $(flags) -b $(outbase) $(source) $(QUIET)$(evalcall KB_FN_OPT_TEST_SHORT,d,$(flags),$(MV) -f -- $(outbase).tab.h$(substr $(suffix $(source)),3) $(outbase).h$(substr $(suffix $(source)),3),) $(QUIET)$(MV) -f -- $(outbase).tab.c$(substr $(suffix $(source)),3) $(out) endef kbuild-2695/kBuild/tools/GCC4MACHO.kmk0000644000000000000000000004537612247157310015760 0ustar rootroot# $Id: GCC4MACHO.kmk 2547 2011-11-04 21:58:53Z bird $ ## @file # kBuild Tool Config - GCC v4 targeting Darwin (Mac OS X) Mach-O. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC4MACHO := GCC v4 targeting Darwin (Mac OS X) Mach-O. # Tool Specific Properties TOOL_GCC4MACHO_PREFIX ?= TOOL_GCC4MACHO_SUFFIX ?= $(HOSTSUFF_EXE) TOOL_GCC4MACHO_CC ?= $(TOOL_GCC4MACHO_PREFIX)gcc$(TOOL_GCC4MACHO_SUFFIX) TOOL_GCC4MACHO_CXX ?= $(TOOL_GCC4MACHO_PREFIX)g++$(TOOL_GCC4MACHO_SUFFIX) TOOL_GCC4MACHO_OBJC ?= $(TOOL_GCC4MACHO_PREFIX)gcc$(TOOL_GCC4MACHO_SUFFIX) TOOL_GCC4MACHO_OBJCXX ?= $(TOOL_GCC4MACHO_PREFIX)gcc$(TOOL_GCC4MACHO_SUFFIX) TOOL_GCC4MACHO_AS ?= $(TOOL_GCC4MACHO_PREFIX)gcc$(TOOL_GCC4MACHO_SUFFIX) TOOL_GCC4MACHO_LD ?= $(TOOL_GCC4MACHO_PREFIX)gcc$(TOOL_GCC4MACHO_SUFFIX) TOOL_GCC4MACHO_LD_SYSMOD ?= $(TOOL_GCC4MACHO_PREFIX)gcc$(TOOL_GCC4MACHO_SUFFIX) ifndef TOOL_GCC4MACHO_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC4MACHO_LDFLAGS.dll ?= -dynamiclib else TOOL_GCC4MACHO_LDFLAGS.dll ?= $(TOOL_GCC4MACHO_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GCC4MACHO_LDFLAGS.sysmod ?= -r #TOOL_GCC4MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_GCC4MACHO_DSYMUTIL ?= dsymutil ifdef SLKRUNS TOOL_GCC4MACHO_CC += -fmessage-length=0 TOOL_GCC4MACHO_CXX += -fmessage-length=0 TOOL_GCC4MACHO_OBJC += -fmessage-length=0 TOOL_GCC4MACHO_OBJCXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GCC4MACHO_COBJSUFF ?= .o TOOL_GCC4MACHO_CFLAGS ?= TOOL_GCC4MACHO_CFLAGS.debug ?= -g TOOL_GCC4MACHO_CFLAGS.profile ?= -g -O2 #-pg TOOL_GCC4MACHO_CFLAGS.release ?= -O2 TOOL_GCC4MACHO_CINCS ?= TOOL_GCC4MACHO_CDEFS ?= TOOL_GCC4MACHO_CXXOBJSUFF ?= .o TOOL_GCC4MACHO_CXXFLAGS ?= TOOL_GCC4MACHO_CXXFLAGS.debug ?= -g TOOL_GCC4MACHO_CXXFLAGS.profile ?= -g -O2 #-pg TOOL_GCC4MACHO_CXXFLAGS.release ?= -O2 TOOL_GCC4MACHO_CXXINCS ?= TOOL_GCC4MACHO_CXXDEFS ?= TOOL_GCC4MACHO_OBJCOBJSUFF ?= .o TOOL_GCC4MACHO_OBJCFLAGS ?= TOOL_GCC4MACHO_OBJCFLAGS.debug ?= -g TOOL_GCC4MACHO_OBJCFLAGS.profile?= -O2 #-g -pg TOOL_GCC4MACHO_OBJCFLAGS.release?= -O2 TOOL_GCC4MACHO_OBJCINCS ?= TOOL_GCC4MACHO_OBJCDEFS ?= TOOL_GCC4MACHO_OBJCXXOBJSUFF ?= .o TOOL_GCC4MACHO_OBJCXXFLAGS ?= TOOL_GCC4MACHO_OBJCXXFLAGS.debug ?= -g TOOL_GCC4MACHO_OBJCXXFLAGS.profile ?= -O2 #-g -pg TOOL_GCC4MACHO_OBJCXXFLAGS.release ?= -O2 TOOL_GCC4MACHO_OBJCXXINCS ?= TOOL_GCC4MACHO_OBJCXXDEFS ?= TOOL_GCC4MACHO_ASFLAGS ?= -x assembler-with-cpp TOOL_GCC4MACHO_ASFLAGS.debug ?= -g TOOL_GCC4MACHO_ASFLAGS.profile ?= -g TOOL_GCC4MACHO_ASOBJSUFF ?= .o TOOL_GCC4MACHO_AR ?= ar$(HOSTSUFF_EXE) TOOL_GCC4MACHO_ARFLAGS ?= -c -rs TOOL_GCC4MACHO_ARLIBSUFF ?= .a TOOL_GCC4MACHO_LDFLAGS ?= TOOL_GCC4MACHO_LDFLAGS.debug ?= -g TOOL_GCC4MACHO_LDFLAGS.profile ?= -g TOOL_GCC4MACHO_STRIP_PROGRAM ?= strip -SXxru TOOL_GCC4MACHO_STRIP_DLL ?= strip -Sxru TOOL_GCC4MACHO_STRIP_SYSMOD ?= strip -Sru ## # Calculate the files in the debug bundle. # @param 1 The whole output filename. # @param 2 The output filename sans suffix. TOOL_GCC4MACHO_DEBUG_BUNDLE_FN = \ $(1).dSYM/ \ $(1).dSYM/Contents/ \ $(1).dSYM/Contents/Resources/ \ $(1).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1)) ## # Calculate the files in the debug bundle. # @param 1 The whole linker output filename. # @param 2 The linker output filename sans suffix. # @param 3 The desired install name (no dir slash). # @remarks The Info.plist has some reference to the original name, but gdb # does not care and only check for a symbol file in the DWARF # directory with the same name as the debugged module. TOOL_GCC4MACHO_DEBUG_INSTALL_FN= \ $(3).dSYM/ \ $(3).dSYM/Contents/ \ $(3).dSYM/Contents/Resources/ \ $(3).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist=>$(3).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1))=>$(3).dSYM/Contents/Resources/DWARF/$(notdir $(3)) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC4MACHO_COMPILE_C_DEPEND = TOOL_GCC4MACHO_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GCC4MACHO_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GCC4MACHO_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GCC4MACHO_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC4MACHO_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_C_OUTPUT = define TOOL_GCC4MACHO_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC4MACHO_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KUSE_OBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC4MACHO_COMPILE_CXX_DEPEND = TOOL_GCC4MACHO_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GCC4MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GCC4MACHO_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC4MACHO_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC4MACHO_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_CXX_OUTPUT = define TOOL_GCC4MACHO_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC4MACHO_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC4MACHO_COMPILE_OBJC_DEPEND = TOOL_GCC4MACHO_COMPILE_OBJC_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1 TOOL_GCC4MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi define TOOL_GCC4MACHO_COMPILE_OBJC_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC4MACHO_OBJC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC4MACHO_OBJC) -c\ $(flags) -fpreprocessed -x cbjective-c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_OBJC_OUTPUT = define TOOL_GCC4MACHO_COMPILE_OBJC_CMDS $(QUIET)$(TOOL_GCC4MACHO_OBJC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC4MACHO_COMPILE_OBJCXX_DEPEND = TOOL_GCC4MACHO_COMPILE_OBJCXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_OBJCXX_USES_KOBJCACHE = 1 TOOL_GCC4MACHO_COMPILE_OBJCXX_OUTPUT = $(outbase).mii define TOOL_GCC4MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).mii\ $(TOOL_GCC4MACHO_OBJCXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC4MACHO_OBJCXX) -c\ $(flags) -fpreprocessed -x objective-c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC4MACHO_COMPILE_OBJCXX_OUTPUT = define TOOL_GCC4MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(TOOL_GCC4MACHO_OBJCXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC4MACHO_COMPILE_AS_OUTPUT = TOOL_GCC4MACHO_COMPILE_AS_DEPEND = TOOL_GCC4MACHO_COMPILE_AS_DEPORD = define TOOL_GCC4MACHO_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC4MACHO_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC4MACHO_LINK_LIBRARY_OUTPUT = TOOL_GCC4MACHO_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GCC4MACHO_LINK_LIBRARY_DEPORD = define TOOL_GCC4MACHO_LINK_LIBRARY_CMDS $(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_GCC4MACHO_AR) $(flags) $(out),$(objs))) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GCC4MACHO_AR) -x $(abspath $(lib)) \ && $(RM_EXT) -f ./__.SYMDEF* \ && $(TOOL_GCC4MACHO_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC4MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp TOOL_GCC4MACHO_LINK_PROGRAM_OUTPUT_DEBUG = $(call TOOL_GCC4MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GCC4MACHO_LINK_PROGRAM_DEBUG_INSTALL_FN = $(TOOL_GCC4MACHO_DEBUG_INSTALL_FN) TOOL_GCC4MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC4MACHO_LINK_PROGRAM_DEPORD = define TOOL_GCC4MACHO_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GCC4MACHO_LD) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GCC4MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GCC4MACHO_STRIP_PROGRAM) $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC4MACHO_LINK_DLL_OUTPUT = $(outbase).rsp TOOL_GCC4MACHO_LINK_DLL_OUTPUT_DEBUG = $(call TOOL_GCC4MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GCC4MACHO_LINK_DLL_DEBUG_INSTALL_FN = $(TOOL_GCC4MACHO_DEBUG_INSTALL_FN) TOOL_GCC4MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC4MACHO_LINK_DLL_DEPORD = define TOOL_GCC4MACHO_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GCC4MACHO_LD) $(TOOL_GCC4MACHO_LDFLAGS.dll) $(flags) -o $(out)\ $(call TOOL_GCC4MACHO_LD_SONAME,$(target),$(out))\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GCC4MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GCC4MACHO_STRIP_DLL) $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC4MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp TOOL_GCC4MACHO_LINK_SYSMOD_OUTPUT_DEBUG = $(call TOOL_GCC4MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GCC4MACHO_LINK_SYSMOD_DEBUG_INSTALL_FN = $(TOOL_GCC4MACHO_DEBUG_INSTALL_FN) TOOL_GCC4MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC4MACHO_LINK_SYSMOD_DEPORD = define TOOL_GCC4MACHO_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GCC4MACHO_LD_SYSMOD) $(TOOL_GCC4MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GCC4MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GCC4MACHO_STRIP_SYSMOD) $(out) endif endef kbuild-2695/kBuild/tools/MSLINK510.kmk0000644000000000000000000001175212247157310015742 0ustar rootroot# $Id: MSLINK510.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - Microsoft Link v5.10 # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_MSLINK510 := Microsoft Segmented-Executable Linker Version 5.10 # Tool Specific Properties ifndef TOOL_MSLINK510_LD TOOL_MSLINK510_LD := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS)/os2.x86/ddk/*/base/tools/link$(HOSTSUFF_EXE)))) ifeq ($(TOOL_MSLINK510_LD),) TOOL_MSLINK510_LD := $(firstword $(rsort $(wildcard \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/video/tools/os2.386/lx.386/bin/link$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/base32/tools/os2.386/bin/link$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/base32/tools/os2.386/lx.386/bin/link$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/print/tools/os2.386/lx.386/bin/link$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/wpshell/tools/os2.386/lx.386/bin/link$(HOSTSUFF_EXE) \ $(PATH_DEVTOOLS)/os2.x86/ddk/*/mme/tools/os2.386/lx.386/bin/link$(HOSTSUFF_EXE) \ ))) endif ifneq ($(TOOL_MSLINK510_LD),) TOOL_MSLINK510_LD := $(TOOL_MSLINK510_LD) endif endif ifeq ($(TOOL_MSLINK510_LD),) TOOL_MSLINK510_LD := $(firstword $(which link$(HOSTSUFF_EXE)) path/notfound/link$(HOSTSUFF_EXE)) endif TOOL_MSLINK510_ENV_SETUP = $(REDIRECT) \ -Z -E 'LIB=$1' \ -- # General Properties used by kBuild TOOL_MSLINK510_LDFLAGS ?= /nologo /map:full /linenumbers TOOL_MSLINK510_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_MSLINK510_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_MSLINK510_LINK_PROGRAM_DEPORD = define TOOL_MSLINK510_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp '$(subst $(SP),+' ',$(strip $(subst /,\,$(objs)))),' $(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(out)),' $(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(outbase)).map,' $(QUIET)$(APPEND) -n $(outbase).rsp '$(subst $(SP),+' ',$(strip $(subst /,\,$(libs))))$(if $(filter %.def,$(othersrc)),$(COMMA),;)' $(if $(filter %.def,$(othersrc)),$(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(filter %.def,$(othersrc)));',) $(QUIET)$(call TOOL_MSLINK510_ENV_SETUP,$(subst $(SP),;,$(libpath))) \ $(TOOL_MSLINK510_LD) $(flags) '@$(subst /,\,$(outbase).rsp)' endef TOOL_MSLINK510_LINK_DLL_OUTPUT = $(outbase).map $(outbase).rsp TOOL_MSLINK510_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_MSLINK510_LINK_DLL_DEPORD = define TOOL_MSLINK510_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp '$(subst $(SP),+' ',$(strip $(subst /,\,$(objs)))),' $(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(out)),' $(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(outbase)).map,' $(QUIET)$(APPEND) -n $(outbase).rsp '$(subst $(SP),+' ',$(strip $(subst /,\,$(libs))))$(if $(filter %.def,$(othersrc)),$(COMMA),;)' $(if $(filter %.def,$(othersrc)),$(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(filter %.def,$(othersrc)));',) $(QUIET)$(call TOOL_MSLINK510_ENV_SETUP,$(subst $(SP),;,$(libpath))) \ $(TOOL_MSLINK510_LD) $(flags) '@$(subst /,\,$(outbase).rsp)' endef TOOL_MSLINK510_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_MSLINK510_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_MSLINK510_LINK_SYSMOD_DEPORD = define TOOL_MSLINK510_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp '$(subst $(SP),+' ',$(strip $(subst /,\,$(objs)))),' $(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(out)),' $(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(outbase)).map,' $(QUIET)$(APPEND) -n $(outbase).rsp '$(subst $(SP),+' ',$(strip $(subst /,\,$(libs))))$(if $(filter %.def,$(othersrc)),$(COMMA),;)' $(if $(filter %.def,$(othersrc)),$(QUIET)$(APPEND) $(outbase).rsp '$(subst /,\,$(filter %.def,$(othersrc)));',) $(QUIET)$(call TOOL_MSLINK510_ENV_SETUP,$(subst $(SP),;,$(libpath))) \ $(TOOL_MSLINK510_LD) $(flags) '@$(subst /,\,$(outbase).rsp)' endef kbuild-2695/kBuild/tools/NASM.kmk0000644000000000000000000000564012247157310015254 0ustar rootroot# $Id: NASM.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - Netwide Assembler v0.98+. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_NASM := Netwide Assembler v0.98+ # Tool Specific Properties ifndef PATH_TOOL_NASM PATH_TOOL_NASM := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/nasm/v*.*)) ifneq ($(PATH_TOOL_NASM),) PATH_TOOL_NASM := $(call lastword,$(PATH_TOOL_NASM)) endif else # Resolve any fancy stuff once and for all. PATH_TOOL_NASM := $(PATH_TOOL_NASM) endif ifneq ($(PATH_TOOL_NASM),) TOOL_NASM_AS ?= $(PATH_TOOL_NASM)/nasm$(HOSTSUFF_EXE) else TOOL_NASM_AS ?= nasm$(HOSTSUFF_EXE) endif # General Properties used by kBuild TOOL_NASM_ASFLAGS ?= ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_NASM_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_NASM_COMPILE_AS_DEPEND = TOOL_NASM_COMPILE_AS_DEPORD = define TOOL_NASM_COMPILE_AS_CMDS $(QUIET)$(TOOL_NASM_AS)\ $(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\ -l $(outbase).lst\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(REDIRECT) -wo $(dep) -- $(TOOL_NASM_AS)\ $(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\ -l $(outbase).lst\ -o $(obj)\ $(abspath $(source)) \ -M endef kbuild-2695/kBuild/tools/MINGWW64.kmk0000644000000000000000000002543512247157310015704 0ustar rootroot# $Id: MINGWW64.kmk 2695 2013-07-26 12:42:25Z bird $ ## @file # kBuild Tool Config - MinGW-W64. # # # Copyright (c) 2004-2012 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # ifdef TOOL_MINGWW64 $(error Already included (TOOL_MINGWW64=$(TOOL_MINGWW64))) endif TOOL_MINGWW64 := MinGW-W64 - The incomprehensible 64-bit GCC port to Windows. # Tool Specific Properties ifndef PATH_TOOL_MINGWW64 PATH_TOOL_MINGWW64 := $(wildcard $(PATH_DEVTOOLS_BLD)/mingw-w64/r*) ifeq ($(PATH_TOOL_MINGWW64),) PATH_TOOL_MINGWW64 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/mingw-w64/r*) endif ifeq ($(PATH_TOOL_MINGWW64),) PATH_TOOL_MINGWW64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/mingw-w64/r*) endif ifneq ($(PATH_TOOL_MINGWW64),) PATH_TOOL_MINGWW64 := $(lastword $(sort $(PATH_TOOL_MINGWW64))) endif else # Resolve any fancy stuff once and for all. PATH_TOOL_MINGWW64 := $(PATH_TOOL_MINGWW64) endif # figure out if it's native or needs a win32 launcher TOOL_MINGWW64_HOSTSUFF_EXE ?= $(HOSTSUFF_EXE) ifndef TOOL_MINGWW64_PREFIX ifneq ($(PATH_TOOL_MINGWW64),) TOOL_MINGWW64_PREFIX := $(PATH_TOOL_MINGWW64)/bin/ else TOOL_MINGWW64_PREFIX := endif ifneq ($(KBUILD_HOST),win) # # we're cross compiling either using an emulator (wine/odin) or a cross compiler. # ifneq ($(PATH_TOOL_MINGWW64),$(subst /win.x86,,$(subst /x86.win,,$(PATH_TOOL_MINGWW64)))) TOOL_MINGWW64_PREFIX := $(EXEC_X86_WIN32) $(TOOL_MINGWW64_PREFIX) TOOL_MINGWW64_HOSTSUFF_EXE := .exe # else # TOOL_MINGWW64_PREFIX := $(TOOL_MINGWW64_PREFIX)i386-mingw32msvc- # TOOL_MINGWW64_HOSTSUFF_EXE := # TOOL_MINGWW64_XCOMPILE := 1 # endif endif else # Resolve any fancy stuff once and for all. TOOL_MINGWW64_PREFIX := $(TOOL_MINGWW64_PREFIX) endif TOOL_MINGWW64_CC ?= $(TOOL_MINGWW64_PREFIX)gcc$(TOOL_MINGWW64_HOSTSUFF_EXE) TOOL_MINGWW64_CXX ?= $(TOOL_MINGWW64_PREFIX)g++$(TOOL_MINGWW64_HOSTSUFF_EXE) TOOL_MINGWW64_AS ?= $(TOOL_MINGWW64_PREFIX)gcc$(TOOL_MINGWW64_HOSTSUFF_EXE) TOOL_MINGWW64_AR ?= $(TOOL_MINGWW64_PREFIX)ar$(TOOL_MINGWW64_HOSTSUFF_EXE) ifndef TOOL_MINGWW64_XCOMPILE# The gentoo package doesn't have g++. TOOL_MINGWW64_LD ?= $(TOOL_MINGWW64_PREFIX)g++$(TOOL_MINGWW64_HOSTSUFF_EXE) else TOOL_MINGWW64_LD ?= $(TOOL_MINGWW64_PREFIX)gcc$(TOOL_MINGWW64_HOSTSUFF_EXE) endif TOOL_MINGWW64_DLLWRAP ?= $(TOOL_MINGWW64_PREFIX)dllwrap$(TOOL_MINGWW64_HOSTSUFF_EXE) TOOL_MINGWW64_DLLTOOL ?= $(TOOL_MINGWW64_PREFIX)dlltool$(TOOL_MINGWW64_HOSTSUFF_EXE) # General Properties used by kBuild TOOL_MINGWW64_COBJSUFF ?= .o TOOL_MINGWW64_CFLAGS ?= -g TOOL_MINGWW64_CFLAGS.debug ?= -O0 TOOL_MINGWW64_CFLAGS.release ?= -O2 TOOL_MINGWW64_CFLAGS.profile ?= -O2 #-pg TOOL_MINGWW64_CINCS ?= TOOL_MINGWW64_CDEFS ?= TOOL_MINGWW64_CXXOBJSUFF ?= .o TOOL_MINGWW64_CXXOBJSUFF ?= .o TOOL_MINGWW64_CXXFLAGS ?= -g TOOL_MINGWW64_CXXFLAGS.debug ?= -O0 TOOL_MINGWW64_CXXFLAGS.release ?= -O2 TOOL_MINGWW64_CXXFLAGS.profile ?= -O2 #-pg TOOL_MINGWW64_CXXINCS ?= TOOL_MINGWW64_CXXDEFS ?= TOOL_MINGWW64_ASFLAGS ?= -g -x assembler-with-cpp TOOL_MINGWW64_ASOBJSUFF ?= .o TOOL_MINGWW64_ARFLAGS ?= cr TOOL_MINGWW64_ARLIBSUFF ?= .a TOOL_MINGWW64_LDFLAGS ?= TOOL_MINGWW64_LDFLAGS.debug ?= -g TOOL_MINGWW64_LDFLAGS.release ?= -s ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_MINGWW64_COMPILE_C_OUTPUT = TOOL_MINGWW64_COMPILE_C_DEPEND = TOOL_MINGWW64_COMPILE_C_DEPORD = define TOOL_MINGWW64_COMPILE_C_CMDS $(QUIET)$(TOOL_MINGWW64_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_MINGWW64_COMPILE_CXX_OUTPUT = TOOL_MINGWW64_COMPILE_CXX_DEPEND = TOOL_MINGWW64_COMPILE_CXX_DEPORD = define TOOL_MINGWW64_COMPILE_CXX_CMDS $(QUIET)$(TOOL_MINGWW64_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_MINGWW64_COMPILE_AS_OUTPUT = TOOL_MINGWW64_COMPILE_AS_DEPEND = TOOL_MINGWW64_COMPILE_AS_DEPORD = define TOOL_MINGWW64_COMPILE_AS_CMDS $(QUIET)$(TOOL_MINGWW64_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_MINGWW64_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_MINGWW64_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_MINGWW64_LINK_LIBRARY_DEPORD = define TOOL_MINGWW64_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(othersrc), 'ADDLIB $(o)') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(TOOL_MINGWW64_AR) -M < $(out).ar-script endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_MINGWW64_LINK_PROGRAM_OUTPUT = TOOL_MINGWW64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_MINGWW64_LINK_PROGRAM_DEPORD = define TOOL_MINGWW64_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_MINGWW64_LD) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib))) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_MINGWW64_LINK_DLL_OUTPUT = TOOL_MINGWW64_LINK_DLL_OUTPUT_MAYBE = $(outbase).a $(outbase).exp $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp $(PATH_STAGE_LIB)/$(notdir $(outbase)).a ## @todo Find a better solution for installing the extra files (.a, .exp, .pdb, etc). TOOL_MINGWW64_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def %.res,$(othersrc)) TOOL_MINGWW64_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) define TOOL_MINGWW64_LINK_DLL_CMDS $(QUIET)$(REDIRECT) -C "$(dir $(out))" -- $(TOOL_MINGWW64_DLLWRAP) $(flags)\ --dllname=$(notdir $(out))\ --output-exp=$(outbase).exp\ --output-lib=$(outbase).a\ $(foreach def,$(filter %.def,$(othersrc)), --def $(def))\ $(filter %.res,$(othersrc))\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib))) $(QUIET)$(CP) $(outbase).exp $(outbase).a $(PATH_STAGE_LIB)/ endef ## @todo separate install stuff! kbuild-2695/kBuild/tools/GXX3.kmk0000644000000000000000000003303012247157310015241 0ustar rootroot# $Id: GXX3.kmk 2541 2011-08-03 09:51:30Z bird $ ## @file # kBuild Tool Config - Generic GCC v3.2.x using the system GCC and Binutils, for building C++ code. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX3 := Generic GCC v3.2.x or later using the system GCC and Binutils, for building C++ code. # Tool Specific Properties TOOL_GXX3_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GXX3_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GXX3_AS ?= gcc$(HOSTSUFF_EXE) ifeq ($(KBUILD_TARGET),solaris) TOOL_GXX3_AR ?= gar$(HOSTSUFF_EXE) else TOOL_GXX3_AR ?= ar$(HOSTSUFF_EXE) endif ifeq ($(KBUILD_TARGET),os2) TOOL_GXX3_AR_IMP ?= emximp$(HOSTSTUFF_EXE) else TOOL_GXX3_AR_IMP ?= $(ECHO) not supported! endif TOOL_GXX3_LD ?= g++$(HOSTSUFF_EXE) TOOL_GXX3_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) ifndef TOOL_GXX3_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX3_LDFLAGS.dll ?= -shared else TOOL_GXX3_LDFLAGS.dll ?= $(TOOL_GXX3_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GXX3_LDFLAGS.sysmod ?= -r TOOL_GXX3_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) ifeq ($(KBUILD_TARGET),os2) TOOL_GXX3_LD_MAP ?= -Zmap=$(1) TOOL_GXX3_LD_SYSMOD_MAP ?= -Zmap=$(1) else TOOL_GXX3_LD_MAP ?= TOOL_GXX3_LD_SYSMOD_MAP ?= endif if1of ($(KBUILD_HOST), solaris) TOOL_GXX3_OBJCOPY ?= gobjcopy$(HOSTSUFF_EXE) else TOOL_GXX3_OBJCOPY ?= objcopy$(HOSTSUFF_EXE) endif ifdef SLKRUNS TOOL_GXX3_CC += -fmessage-length=0 TOOL_GXX3_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GXX3_COBJSUFF ?= .o TOOL_GXX3_CFLAGS ?= TOOL_GXX3_CFLAGS.debug ?= -g TOOL_GXX3_CFLAGS.profile ?= -O2 #-g -pg TOOL_GXX3_CFLAGS.release ?= -O2 TOOL_GXX3_CINCS ?= TOOL_GXX3_CDEFS ?= TOOL_GXX3_CXXOBJSUFF ?= .o TOOL_GXX3_CXXOBJSUFF ?= .o TOOL_GXX3_CXXFLAGS ?= TOOL_GXX3_CXXFLAGS.debug ?= -g TOOL_GXX3_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX3_CXXFLAGS.release ?= -O2 TOOL_GXX3_CXXINCS ?= TOOL_GXX3_CXXDEFS ?= TOOL_GXX3_ASFLAGS ?= -x assembler-with-cpp TOOL_GXX3_ASFLAGS.debug ?= -g TOOL_GXX3_ASFLAGS.profile ?= -g TOOL_GXX3_ASOBJSUFF ?= .o TOOL_GXX3_ARFLAGS ?= cr TOOL_GXX3_ARLIBSUFF ?= .a TOOL_GXX3_LDFLAGS ?= TOOL_GXX3_LDFLAGS.debug ?= -g TOOL_GXX3_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX3_COMPILE_C_DEPEND = TOOL_GXX3_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX3_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GXX3_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GXX3_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GXX3_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX3_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX3_COMPILE_C_OUTPUT = define TOOL_GXX3_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX3_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX3_COMPILE_CXX_DEPEND = TOOL_GXX3_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX3_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GXX3_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GXX3_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX3_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX3_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX3_COMPILE_CXX_OUTPUT = define TOOL_GXX3_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX3_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX3_COMPILE_AS_OUTPUT = TOOL_GXX3_COMPILE_AS_DEPEND = TOOL_GXX3_COMPILE_AS_DEPORD = define TOOL_GXX3_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX3_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_GXX3_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).imp.a TOOL_GXX3_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GXX3_LINK_LIBRARY_DEPORD = define TOOL_GXX3_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(filter-out %.def %.imp,$(othersrc)), 'ADDLIB $(o)') $(if $(filter %.def %.imp,$(othersrc))\ ,$(TOOL_GXX3_AR_IMP) -o $(outbase).imp.a $(filter %.def %.imp,$(othersrc))\ $(NL)$(TAB)$(QUIET)$(APPEND) $(out).ar-script 'ADDLIB $(outbase).imp.a') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GXX3_AR) -M endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3_LINK_PROGRAM_OUTPUT = TOOL_GXX3_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GXX3_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX3_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX3_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX3_LINK_PROGRAM_DEPORD = define TOOL_GXX3_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GXX3_LD) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX3_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX3_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX3_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3_LINK_DLL_OUTPUT = TOOL_GXX3_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GXX3_LINK_DLL_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX3_LINK_DLL_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX3_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX3_LINK_DLL_DEPORD = define TOOL_GXX3_LINK_DLL_CMDS $(QUIET)$(TOOL_GXX3_LD) $(TOOL_GXX3_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GXX3_LD_SONAME,$(target),$(out)))\ $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX3_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX3_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX3_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3_LINK_SYSMOD_OUTPUT = TOOL_GXX3_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GXX3_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX3_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX3_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX3_LINK_SYSMOD_DEPORD = define TOOL_GXX3_LINK_SYSMOD_CMDS $(QUIET)$(TOOL_GXX3_LD_SYSMOD) $(TOOL_GXX3_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX3_LD_SYSMOD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX3_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX3_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef kbuild-2695/kBuild/tools/GCC3.kmk0000644000000000000000000003302112247157310015167 0ustar rootroot# $Id: GCC3.kmk 2541 2011-08-03 09:51:30Z bird $ ## @file # kBuild Tool Config - Generic GCC v3.2.x or later Using The System GCC and Binutils. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC3 := Generic GCC v3.2.x or later Using The System GCC and Binutils. # Tool Specific Properties TOOL_GCC3_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GCC3_AS ?= gcc$(HOSTSUFF_EXE) ifeq ($(KBUILD_TARGET),solaris) ## @todo drop the MRI script! TOOL_GCC3_AR ?= gar$(HOSTSUFF_EXE) else TOOL_GCC3_AR ?= ar$(HOSTSUFF_EXE) endif ifeq ($(KBUILD_TARGET),os2) TOOL_GCC3_AR_IMP ?= emximp$(HOSTSTUFF_EXE) else TOOL_GCC3_AR_IMP ?= $(ECHO) not supported! endif TOOL_GCC3_LD ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) ifndef TOOL_GCC3_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC3_LDFLAGS.dll ?= -shared else TOOL_GCC3_LDFLAGS.dll ?= $(TOOL_GCC3_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GCC3_LDFLAGS.sysmod ?= -r TOOL_GCC3_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) ifeq ($(KBUILD_TARGET),os2) TOOL_GCC3_LD_MAP ?= -Zmap=$(1) TOOL_GCC3_LD_SYSMOD_MAP ?= -Zmap=$(1) else TOOL_GCC3_LD_MAP ?= TOOL_GCC3_LD_SYSMOD_MAP ?= endif if1of ($(KBUILD_HOST), solaris) TOOL_GCC3_OBJCOPY ?= gobjcopy$(HOSTSUFF_EXE) else TOOL_GCC3_OBJCOPY ?= objcopy$(HOSTSUFF_EXE) endif ifdef SLKRUNS TOOL_GCC3_CC += -fmessage-length=0 TOOL_GCC3_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GCC3_COBJSUFF ?= .o TOOL_GCC3_CFLAGS ?= TOOL_GCC3_CFLAGS.debug ?= -g TOOL_GCC3_CFLAGS.profile ?= -O2 #-g -pg TOOL_GCC3_CFLAGS.release ?= -O2 TOOL_GCC3_CINCS ?= TOOL_GCC3_CDEFS ?= TOOL_GCC3_CXXOBJSUFF ?= .o TOOL_GCC3_CXXOBJSUFF ?= .o TOOL_GCC3_CXXFLAGS ?= TOOL_GCC3_CXXFLAGS.debug ?= -g TOOL_GCC3_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GCC3_CXXFLAGS.release ?= -O2 TOOL_GCC3_CXXINCS ?= TOOL_GCC3_CXXDEFS ?= TOOL_GCC3_ASFLAGS ?= -x assembler-with-cpp TOOL_GCC3_ASFLAGS.debug ?= -g TOOL_GCC3_ASFLAGS.profile ?= -g TOOL_GCC3_ASOBJSUFF ?= .o TOOL_GCC3_ARFLAGS ?= cr TOOL_GCC3_ARLIBSUFF ?= .a TOOL_GCC3_LDFLAGS ?= TOOL_GCC3_LDFLAGS.debug ?= -g TOOL_GCC3_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC3_COMPILE_C_DEPEND = TOOL_GCC3_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC3_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GCC3_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GCC3_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GCC3_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC3_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC3_COMPILE_C_OUTPUT = define TOOL_GCC3_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC3_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC3_COMPILE_CXX_DEPEND = TOOL_GCC3_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC3_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GCC3_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GCC3_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC3_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC3_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC3_COMPILE_CXX_OUTPUT = define TOOL_GCC3_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC3_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC3_COMPILE_AS_OUTPUT = TOOL_GCC3_COMPILE_AS_DEPEND = TOOL_GCC3_COMPILE_AS_DEPORD = define TOOL_GCC3_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC3_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_GCC3_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).imp.a TOOL_GCC3_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GCC3_LINK_LIBRARY_DEPORD = define TOOL_GCC3_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(filter-out %.def %.imp,$(othersrc)), 'ADDLIB $(o)') $(if $(filter %.def %.imp,$(othersrc))\ ,$(TOOL_GCC3_AR_IMP) -o $(outbase).imp.a $(filter %.def %.imp,$(othersrc))\ $(NL)$(TAB)$(QUIET)$(APPEND) $(out).ar-script 'ADDLIB $(outbase).imp.a') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GCC3_AR) -M endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3_LINK_PROGRAM_OUTPUT = TOOL_GCC3_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GCC3_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC3_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC3_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC3_LINK_PROGRAM_DEPORD = define TOOL_GCC3_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GCC3_LD) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC3_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC3_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC3_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3_LINK_DLL_OUTPUT = TOOL_GCC3_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GCC3_LINK_DLL_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC3_LINK_DLL_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC3_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC3_LINK_DLL_DEPORD = define TOOL_GCC3_LINK_DLL_CMDS $(QUIET)$(TOOL_GCC3_LD) $(TOOL_GCC3_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GCC3_LD_SONAME,$(target),$(out)))\ $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC3_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC3_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC3_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3_LINK_SYSMOD_OUTPUT = TOOL_GCC3_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GCC3_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC3_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC3_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC3_LINK_SYSMOD_DEPORD = define TOOL_GCC3_LINK_SYSMOD_CMDS $(QUIET)$(TOOL_GCC3_LD_SYSMOD) $(TOOL_GCC3_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC3_LD_SYSMOD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC3_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC3_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef kbuild-2695/kBuild/tools/TAR.kmk0000644000000000000000000000505112247157310015140 0ustar rootroot# $Id: TAR.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - tar unpacker. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_TAR := tar unpacker. # Tool Specific Properties ifndef TOOL_TAR_TAR TOOL_TAR_TAR := $(wildcard $(PATH_DEVTOOLS_BLD)/tar/v*/tar$(HOSTSUFF_EXE)) ifeq ($(TOOL_TAR_TAR),) TOOL_TAR_TAR := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/tar$(HOSTSUFF_EXE)) endif ifneq ($(TOOL_TAR_TAR),) TOOL_TAR_TAR := $(lastword $(sort $(TOOL_TAR_TAR))) else TOOL_TAR_TAR := tar$(HOSTSUFF_EXE) endif else TOOL_TAR_TAR := $(TOOL_TAR_TAR) endif TOOL_TAR_UNPACK ?= $(TOOL_TAR_TAR) # General Properties used by kBuild TOOL_TAR_UNPACKFLAGS ?= ## UNPACK one file. # @param $(target) Normalized main target name. # @param $(archive) The file to unpack. # @param $(flags) Flags. # @param $(inst) Where to unpack it. # @param $(out) Where to write the file list. TOOL_TAR_UNPACK_OUTPUT = TOOL_TAR_UNPACK_DEPEND = TOOL_TAR_UNPACK_DEPORD = ifeq ($(KBUILD_HOST),win) # hacking with buggy unxutils on windows. it doesn't like driver letters. define TOOL_TAR_UNPACK_CMDS $(QUIET)$(TOOL_TAR_UNPACK) -x $(flags) -C $(subst G:,,$(inst)) -f $(archive) $(QUIET)$(TOOL_TAR_UNPACK) -t $(filter-out -v --verbose,$(flags)) -f $(archive) > $(out) endef else define TOOL_TAR_UNPACK_CMDS $(QUIET)$(TOOL_TAR_UNPACK) -x $(flags) -C $(inst) -f $(archive) $(QUIET)$(TOOL_TAR_UNPACK) -t $(filter-out -v --verbose,$(flags)) -f $(archive) > $(out) endef endif kbuild-2695/kBuild/tools/ZIP.kmk0000644000000000000000000000567312247157310015166 0ustar rootroot# $Id: ZIP.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - The zip/unzip packer/unpacker. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_ZIP := The zip/unzip packer/unpacker. # Tool Specific Properties ifndef TOOL_ZIP_UNPACK TOOL_ZIP_UNPACK := $(wildcard $(PATH_DEVTOOLS_BLD)/unzip/v*/unzip$(HOSTSUFF_EXE)) ifeq ($(TOOL_ZIP_UNPACK),) TOOL_ZIP_UNPACK := $(wildcard $(PATH_DEVTOOLS_BLD)/zip/v*/unzip$(HOSTSUFF_EXE)) endif ifeq ($(TOOL_ZIP_UNPACK),) TOOL_ZIP_UNPACK := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/unzip$(HOSTSUFF_EXE)) endif ifneq ($(TOOL_ZIP_UNPACK),) TOOL_ZIP_UNPACK := $(lastword $(sort $(TOOL_ZIP_UNPACK))) else TOOL_ZIP_UNPACK := unzip$(HOSTSUFF_EXE) endif else TOOL_ZIP_UNPACK := $(TOOL_ZIP_UNPACK) endif #ifndef TOOL_ZIP_PACK # TOOL_ZIP_PACK := $(wildcard $(PATH_DEVTOOLS_BLD)/zip/v*/zip$(HOSTSUFF_EXE)) # ifeq ($(TOOL_ZIP_PACK),) # TOOL_ZIP_PACK := $(wildcard $(PATH_DEVTOOLS_BLD)/unzip/v*/zip$(HOSTSUFF_EXE)) # endif # ifeq ($(TOOL_ZIP_PACK),) # TOOL_ZIP_PACK := $(wildcard $(PATH_DEVTOOLS_BLD)/bin/zip$(HOSTSUFF_EXE)) # endif # ifneq ($(TOOL_ZIP_PACK),) # TOOL_ZIP_PACK := $(lastword $(sort $(TOOL_ZIP_PACK))) # else # TOOL_ZIP_PACK := zip$(HOSTSUFF_EXE) # endif #else # TOOL_ZIP_PACK := $(TOOL_ZIP_PACK) #endif # General Properties used by kBuild TOOL_ZIP_UNPACKFLAGS ?= ## UNPACK one file. # @param $(zipget) Normalized main zipget name. # @param $(archive) The file to unpack. # @param $(flags) Flags. # @param $(inst) Where to unpack it. # @param $(out) Where to write the file list. TOOL_ZIP_UNPACK_OUTPUT = TOOL_ZIP_UNPACK_DEPEND = TOOL_ZIP_UNPACK_DEPORD = define TOOL_ZIP_UNPACK_CMDS $(QUIET)$(TOOL_ZIP_UNPACK) $(flags) $(archive) -d "$(inst)" $(QUIET)$(TOOL_ZIP_UNPACK) -l $(archive) | $(SED) \ -e '/ [0-2][0-9]:[0-6][0-9]/!d' \ -e 's/^.* [0-2][0-9]:[0-6][0-9] //' \ > $(out) endef kbuild-2695/kBuild/tools/GCC3PLAIN.kmk0000644000000000000000000003211612247157310015757 0ustar rootroot# $Id: GCC3PLAIN.kmk 2545 2011-09-13 19:09:05Z bird $ ## @file # kBuild Tool Config - Generic GCC v3.2.x or later Using The System GCC, any Unix Linker and Unix Archiver. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC3PLAIN := Generic GCC v3.2.x or later Using The System GCC, any Unix Linker and Unix Archiver. # Tool Specific Properties TOOL_GCC3PLAIN_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_AS ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_AR ?= ar$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_RANLIB ?= ranlib$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_LD ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_LD_SYSMOD.os2 ?= g++$(HOSTSUFF_EXE) TOOL_GCC3PLAIN_LDFLAGS.dll.os2 ?= -Zdll TOOL_GCC3PLAIN_LDFLAGS.dll.darwin ?= -dynamiclib ifndef TOOL_GCC3PLAIN_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC3PLAIN_LDFLAGS.dll ?= -shared else TOOL_GCC3PLAIN_LDFLAGS.dll ?= $(TOOL_GCC3PLAIN_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GCC3PLAIN_LD_SONAME.darwin ?= $(NO_SUCH_VARIABLE) TOOL_GCC3PLAIN_LD_SONAME.os2 ?= $(NO_SUCH_VARIABLE) TOOL_GCC3PLAIN_LD_SONAME.solaris ?= -Wl,-h,$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_GCC3PLAIN_LD_SONAME.win ?= $(NO_SUCH_VARIABLE) ifndef TOOL_GCC3PLAIN_LD_SONAME.$(KBUILD_TARGET) TOOL_GCC3PLAIN_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) else TOOL_GCC3PLAIN_LD_SONAME ?= $(TOOL_GCC3PLAIN_LD_SONAME.$(KBUILD_TARGET)) endif ifdef SLKRUNS TOOL_GCC3PLAIN_CC += -fmessage-length=0 TOOL_GCC3PLAIN_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GCC3PLAIN_COBJSUFF ?= .o TOOL_GCC3PLAIN_CFLAGS ?= TOOL_GCC3PLAIN_CFLAGS.debug ?= -g TOOL_GCC3PLAIN_CFLAGS.profile ?= -O2 #-g -pg TOOL_GCC3PLAIN_CFLAGS.release ?= -O2 TOOL_GCC3PLAIN_CINCS ?= TOOL_GCC3PLAIN_CDEFS ?= TOOL_GCC3PLAIN_CXXOBJSUFF ?= .o TOOL_GCC3PLAIN_CXXOBJSUFF ?= .o TOOL_GCC3PLAIN_CXXFLAGS ?= TOOL_GCC3PLAIN_CXXFLAGS.debug ?= -g TOOL_GCC3PLAIN_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GCC3PLAIN_CXXFLAGS.release ?= -O2 TOOL_GCC3PLAIN_CXXINCS ?= TOOL_GCC3PLAIN_CXXDEFS ?= TOOL_GCC3PLAIN_ASFLAGS ?= -x assembler-with-cpp TOOL_GCC3PLAIN_ASFLAGS.debug ?= -g TOOL_GCC3PLAIN_ASFLAGS.profile ?= -g TOOL_GCC3PLAIN_ASOBJSUFF ?= .o TOOL_GCC3PLAIN_ARFLAGS ?= cr TOOL_GCC3PLAIN_ARLIBSUFF ?= .a TOOL_GCC3PLAIN_LDFLAGS ?= ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC3PLAIN_COMPILE_C_DEPEND = TOOL_GCC3PLAIN_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC3PLAIN_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GCC3PLAIN_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GCC3PLAIN_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GCC3PLAIN_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC3PLAIN_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC3PLAIN_COMPILE_C_OUTPUT = define TOOL_GCC3PLAIN_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC3PLAIN_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC3PLAIN_COMPILE_CXX_DEPEND = TOOL_GCC3PLAIN_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC3PLAIN_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GCC3PLAIN_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GCC3PLAIN_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC3PLAIN_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC3PLAIN_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC3PLAIN_COMPILE_CXX_OUTPUT = define TOOL_GCC3PLAIN_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC3PLAIN_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC3PLAIN_COMPILE_AS_OUTPUT = TOOL_GCC3PLAIN_COMPILE_AS_DEPEND = TOOL_GCC3PLAIN_COMPILE_AS_DEPORD = define TOOL_GCC3PLAIN_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC3PLAIN_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3PLAIN_LINK_LIBRARY_OUTPUT = TOOL_GCC3PLAIN_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GCC3PLAIN_LINK_LIBRARY_DEPORD = define TOOL_GCC3PLAIN_LINK_LIBRARY_CMDS $(call xargs,$(QUIET)$(TOOL_GCC3PLAIN_AR) $(flags) $(out),$(objs)) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GCC3PLAIN_AR) x $(abspath $(lib)) \ && $(TOOL_GCC3PLAIN_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) $(QUIET)$(TOOL_GCC3PLAIN_RANLIB) $(out) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3PLAIN_LINK_PROGRAM_OUTPUT = TOOL_GCC3PLAIN_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GCC3PLAIN_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC3PLAIN_LINK_PROGRAM_DEPORD = define TOOL_GCC3PLAIN_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GCC3PLAIN_LD) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3PLAIN_LINK_DLL_OUTPUT = TOOL_GCC3PLAIN_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GCC3PLAIN_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC3PLAIN_LINK_DLL_DEPORD = define TOOL_GCC3PLAIN_LINK_DLL_CMDS $(QUIET)$(TOOL_GCC3PLAIN_LD) $(TOOL_GCC3PLAIN_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_GCC3PLAIN_LD_SONAME,$(target),$(out)))\ $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef ## Link system module (windows aka driver, linux aka kernel module) # This tool target might not work everywhere, but is provided for the # platforms where it works (Solaris, etc). # # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3PLAIN_LINK_SYSMOD_OUTPUT = TOOL_GCC3PLAIN_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GCC3PLAIN_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC3PLAIN_LINK_SYSMOD_DEPORD = define TOOL_GCC3PLAIN_LINK_SYSMOD_CMDS $(QUIET)$(if $(TOOL_GCC3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GCC3PLAIN_LD_SYSMOD.$(bld_trg)),$(TOOL_GCC3PLAIN_LD_SYSMOD))\ $(TOOL_GCC3PLAIN_LDFLAGS_SYSMOD.$(bld_trg)) $(flags) -o $(out)\ $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef kbuild-2695/kBuild/tools/VCC100X86.kmk0000644000000000000000000004113412247157310015656 0ustar rootroot# $Id: VCC100X86.kmk 2625 2012-08-07 20:26:48Z bird $ ## @file # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting x86. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VCC100X86 := Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting x86. # Tool Specific Properties ifndef PATH_TOOL_VCC100X86 PATH_TOOL_VCC100X86 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v10*) ifeq ($(PATH_TOOL_VCC100X86),) PATH_TOOL_VCC100X86 := $(PATH_TOOL_VCC100) endif ifeq ($(PATH_TOOL_VCC100X86),) PATH_TOOL_VCC100X86 := $(PATH_TOOL_VCC100AMD64) endif ifeq ($(PATH_TOOL_VCC100X86),) PATH_TOOL_VCC100X86 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/vcc/v10*) endif ifeq ($(PATH_TOOL_VCC100X86),) PATH_TOOL_VCC100X86 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/vcc/v10*) endif ifneq ($(PATH_TOOL_VCC100X86),) PATH_TOOL_VCC100X86 := $(lastword $(sort $(PATH_TOOL_VCC100X86))) else $(warning kBuild: PATH_TOOL_VCC100X86 cannot be determined!) PATH_TOOL_VCC100X86 := $(PATH_DEVTOOLS)/x86.win/vcc/v10 endif else # Resolve any fancy stuff once and for all. PATH_TOOL_VCC100X86 := $(PATH_TOOL_VCC100X86) endif PATH_TOOL_VCC100X86_BIN ?= $(PATH_TOOL_VCC100X86)/bin PATH_TOOL_VCC100X86_LIB ?= $(PATH_TOOL_VCC100X86)/lib PATH_TOOL_VCC100X86_INC ?= $(PATH_TOOL_VCC100X86)/include PATH_TOOL_VCC100X86_ATLMFC ?= $(PATH_TOOL_VCC100X86)/atlmfc PATH_TOOL_VCC100X86_ATLMFC_INC ?= $(PATH_TOOL_VCC100X86_ATLMFC)/include PATH_TOOL_VCC100X86_ATLMFC_LIB ?= $(PATH_TOOL_VCC100X86_ATLMFC)/lib TOOL_VCC100X86_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/cl.exe TOOL_VCC100X86_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/cl.exe TOOL_VCC100X86_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/ml.exe TOOL_VCC100X86_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/lib.exe TOOL_VCC100X86_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/link.exe TOOL_VCC100X86_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/dumpbin.exe TOOL_VCC100X86_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/editbin.exe TOOL_VCC100X86_RC ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED) TOOL_VCC100X86_MT ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED) # The following in duplicated in VCC100.kmk and VCC100X86.kmk. TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword \ $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \ $(if-expr defined(PATH_SDK_WINPSDK_BIN) , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \ $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \ $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \ $1)) TOOL_VCC100_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC100_FN_FIND_SDK_TOOL_SUB),)$($3) ## Disabled fast DEP_IDB based dependencies. #VCC100X86_OLD_DEPS = 1 ## Constructs the correct .pdb name (the name is lowercased). # @param $(1) Base name, no extention. # @param $(2) The extension. TOOL_VCC100X86_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) # General Properties used by kBuild TOOL_VCC100X86_COBJSUFF ?= .obj TOOL_VCC100X86_CFLAGS ?= -TC -nologo TOOL_VCC100X86_CFLAGS.debug ?= -Zi TOOL_VCC100X86_CFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100X86_CFLAGS.release ?= -O2 TOOL_VCC100X86_CFLAGS.profile ?= -O2 TOOL_VCC100X86_CINCS ?= $(PATH_TOOL_VCC100X86_INC) TOOL_VCC100X86_CDEFS ?= TOOL_VCC100X86_CXXOBJSUFF ?= .obj TOOL_VCC100X86_CXXFLAGS ?= -TP -nologo TOOL_VCC100X86_CXXFLAGS.debug ?= -Zi TOOL_VCC100X86_CXXFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100X86_CXXFLAGS.release ?= -O2 TOOL_VCC100X86_CXXFLAGS.profile ?= -O2 TOOL_VCC100X86_CXXINCS ?= $(PATH_TOOL_VCC100X86_INC) $(PATH_TOOL_VCC100X86_ATLMFC_INC) TOOL_VCC100X86_CXXDEFS ?= TOOL_VCC100X86_ASOBJSUFF ?= .obj TOOL_VCC100X86_RCOBJSUFF ?= .res TOOL_VCC100X86_RCINCS ?= $(PATH_TOOL_VCC100X86_INC) $(PATH_TOOL_VCC100X86_ATLMFC_INC) TOOL_VCC100X86_ARFLAGS ?= -nologo TOOL_VCC100X86_ARLIBSUFF ?= .lib TOOL_VCC100X86_LDFLAGS ?= -nologo -machine:x86 TOOL_VCC100X86_LDFLAGS.debug ?= -debug TOOL_VCC100X86_LDFLAGS.dbgopt ?= -debug TOOL_VCC100X86_LDFLAGS.profile ?= -debug TOOL_VCC100X86_LDFLAGS.release ?= ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100X86_COMPILE_C_DEPEND = TOOL_VCC100X86_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_VCC100X86_COMPILE_C_USES_KOBJCACHE = 1 TOOL_VCC100X86_COMPILE_C_OUTPUT = $(outbase).i TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE = define TOOL_VCC100X86_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ --kObjCache-cpp $(outbase).i\ $(TOOL_VCC100X86_CC) -E\ $(subst -Zi,-Z7,$(flags))\ $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ --kObjCache-cc $(obj)\ $(TOOL_VCC100X86_CC) -c\ $(subst -Zi,-Z7,$(flags))\ -Fo$(obj)\ $(outbase).i endef else # !KBUILD_USE_KOBJCACHE TOOL_VCC100X86_COMPILE_C_OUTPUT = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,idb) TOOL_VCC100X86_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,pdb) define TOOL_VCC100X86_COMPILE_C_CMDS $(QUIET)$(TOOL_VCC100X86_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100X86_PDB,$(outbase)-obj,idb) endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100X86_COMPILE_CXX_DEPEND = TOOL_VCC100X86_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_VCC100X86_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_VCC100X86_COMPILE_CXX_OUTPUT = $(outbase).ii TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = define TOOL_VCC100X86_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ --kObjCache-cpp $(outbase).ii\ $(TOOL_VCC100X86_CXX) -E\ $(subst -Zi,-Z7,$(flags))\ $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ --kObjCache-cc $(obj)\ $(TOOL_VCC100X86_CXX) -c\ $(subst -Zi,-Z7,$(flags))\ -Fo$(obj)\ $(outbase).ii endef else # !KBUILD_USE_KOBJCACHE TOOL_VCC100X86_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,idb) TOOL_VCC100X86_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,pdb) define TOOL_VCC100X86_COMPILE_CXX_CMDS $(QUIET)$(TOOL_VCC100X86_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100X86_PDB,$(outbase)-obj,idb) endef endif # !KBUILD_USE_KOBJCACHE ## @todo configure the assembler template. ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100X86_COMPILE_RC_DEPEND = TOOL_VCC100X86_COMPILE_RC_DEPORD = TOOL_VCC100X86_COMPILE_RC_OUTPUT = define TOOL_VCC100X86_COMPILE_RC_CMDS $(QUIET)$(TOOL_VCC100X86_RC) \ $(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\ /fo$(obj)\ $(subst /,\\,$(abspath $(source))) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC100X86_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VCC100X86_LINK_LIBRARY_DEPORD = TOOL_VCC100X86_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_VCC100X86_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb define TOOL_VCC100X86_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs) \ $(filter-out %.def,$(othersrc))) \ $(addprefix /DEF:,$(filter %.def,$(othersrc))) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100X86_AR) $(flags) /OUT:$(out) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC100X86_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100X86_LINK_PROGRAM_DEPORD = TOOL_VCC100X86_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC100X86_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC100X86_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100X86_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100X86_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100X86_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100X86_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out)) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC100X86_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100X86_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) TOOL_VCC100X86_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp TOOL_VCC100X86_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp TOOL_VCC100X86_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100X86_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100X86_LINK_DLL_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100X86_LD) $(flags) \ /OUT:$(out) \ /IMPLIB:$(outbase).lib \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ /DLL \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' $(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/ $(eval _DIRS += $(PATH_STAGE_LIB)) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC100X86_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100X86_LINK_SYSMOD_DEPORD = TOOL_VCC100X86_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC100X86_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC100X86_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100X86_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100X86_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100X86_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' endef kbuild-2695/kBuild/tools/GCC32.kmk0000644000000000000000000003265212247157310015262 0ustar rootroot# $Id: GCC32.kmk 2541 2011-08-03 09:51:30Z bird $ ## @file # kBuild Tool Config - Generic 32-bit GCC v3.2.x or later Using The System GCC. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC32 := Generic 32-bit GCC v3.2.x or later Using The System GCC. \ More or less Linux/ELF specfic. # Tool Specific Properties TOOL_GCC32_CC ?= gcc$(HOSTSUFF_EXE) -m32 TOOL_GCC32_CXX ?= g++$(HOSTSUFF_EXE) -m32 TOOL_GCC32_AS ?= gcc$(HOSTSUFF_EXE) -m32 TOOL_GCC32_AR ?= ar$(HOSTSUFF_EXE) TOOL_GCC32_LD ?= gcc$(HOSTSUFF_EXE) -m32 TOOL_GCC32_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) ifndef TOOL_GCC32_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC32_LDFLAGS.dll ?= -shared else TOOL_GCC32_LDFLAGS.dll ?= $(TOOL_GCC32_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GCC32_LDFLAGS.sysmod ?= -r -m elf_i386$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,) TOOL_GCC32_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) ifeq ($(KBUILD_TARGET),os2) TOOL_GCC32_LD_MAP ?= -Zmap=$(1) else TOOL_GCC32_LD_MAP ?= endif ifeq ($(KBUILD_TARGET),os2) TOOL_GCC32_LD_SYSMOD_MAP ?= -Zmap=$(1) else TOOL_GCC32_LD_SYSMOD_MAP ?= endif if1of ($(KBUILD_HOST), solaris) TOOL_GCC32_OBJCOPY ?= gobjcopy$(HOSTSUFF_EXE) else TOOL_GCC32_OBJCOPY ?= objcopy$(HOSTSUFF_EXE) endif ifdef SLKRUNS TOOL_GCC32_CC += -fmessage-length=0 TOOL_GCC32_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GCC32_COBJSUFF ?= .o TOOL_GCC32_CFLAGS ?= TOOL_GCC32_CFLAGS.debug ?= -g TOOL_GCC32_CFLAGS.profile ?= -O2 #-g -pg TOOL_GCC32_CFLAGS.release ?= -O2 TOOL_GCC32_CINCS ?= TOOL_GCC32_CDEFS ?= TOOL_GCC32_CXXOBJSUFF ?= .o TOOL_GCC32_CXXOBJSUFF ?= .o TOOL_GCC32_CXXFLAGS ?= TOOL_GCC32_CXXFLAGS.debug ?= -g TOOL_GCC32_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GCC32_CXXFLAGS.release ?= -O2 TOOL_GCC32_CXXINCS ?= TOOL_GCC32_CXXDEFS ?= TOOL_GCC32_ASFLAGS ?= -x assembler-with-cpp TOOL_GCC32_ASFLAGS.debug ?= -g TOOL_GCC32_ASFLAGS.profile ?= -g TOOL_GCC32_ASOBJSUFF ?= .o TOOL_GCC32_ARFLAGS ?= cr TOOL_GCC32_ARLIBSUFF ?= .a TOOL_GCC32_LDFLAGS ?= TOOL_GCC32_LDFLAGS.debug ?= -g TOOL_GCC32_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC32_COMPILE_C_DEPEND = TOOL_GCC32_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC32_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GCC32_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GCC32_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GCC32_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC32_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC32_COMPILE_C_OUTPUT = define TOOL_GCC32_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC32_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC32_COMPILE_CXX_DEPEND = TOOL_GCC32_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC32_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GCC32_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GCC32_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC32_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC32_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC32_COMPILE_CXX_OUTPUT = define TOOL_GCC32_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC32_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC32_COMPILE_AS_OUTPUT = TOOL_GCC32_COMPILE_AS_DEPEND = TOOL_GCC32_COMPILE_AS_DEPORD = define TOOL_GCC32_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC32_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC32_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_GCC32_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GCC32_LINK_LIBRARY_DEPORD = define TOOL_GCC32_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(filter-out %.def %.imp,$(othersrc)), 'ADDLIB $(o)') $(if $(filter %.def %.imp,$(othersrc))\ ,$(TOOL_GCC32_AR_IMP) -o $(outbase).imp.a $(filter %.def %.imp,$(othersrc))\ $(NL)$(TAB)$(QUIET)$(APPEND) $(out).ar-script 'ADDLIB $(outbase).imp.a') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GCC32_AR) -M endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC32_LINK_PROGRAM_OUTPUT = TOOL_GCC32_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GCC32_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC32_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC32_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC32_LINK_PROGRAM_DEPORD = define TOOL_GCC32_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GCC32_LD) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC32_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC32_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC32_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC32_LINK_DLL_OUTPUT = TOOL_GCC32_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GCC32_LINK_DLL_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC32_LINK_DLL_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC32_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC32_LINK_DLL_DEPORD = define TOOL_GCC32_LINK_DLL_CMDS $(QUIET)$(TOOL_GCC32_LD) $(TOOL_GCC32_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GCC32_LD_SONAME,$(target),$(out)))\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC32_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC32_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC32_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC32_LINK_SYSMOD_OUTPUT = TOOL_GCC32_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GCC32_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).debug TOOL_GCC32_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GCC32_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GCC32_LINK_SYSMOD_DEPORD = define TOOL_GCC32_LINK_SYSMOD_CMDS $(QUIET)$(TOOL_GCC32_LD_SYSMOD) $(TOOL_GCC32_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GCC32_LD_SYSMOD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GCC32_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GCC32_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef kbuild-2695/kBuild/tools/GXX.kmk0000644000000000000000000002121012247157310015153 0ustar rootroot# $Id: GXX.kmk 2545 2011-09-13 19:09:05Z bird $ ## @file # kBuild Tool Config - Generic GCC using the system GCC, for building C++ code. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX := Generic GCC using the system GCC, for building C++ code. # Tool Specific Properties TOOL_GXX_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GXX_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GXX_AS ?= gcc$(HOSTSUFF_EXE) TOOL_GXX_AR ?= ar$(HOSTSUFF_EXE) TOOL_GXX_RANLIB ?= ranlib$(HOSTSUFF_EXE) TOOL_GXX_LD ?= g++$(HOSTSUFF_EXE) TOOL_GXX_LDFLAGS.dll.os2 ?= -Zdll TOOL_GXX_LDFLAGS.dll.darwin ?= -dynamiclib ifndef TOOL_GXX_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX_LDFLAGS.dll ?= -shared else TOOL_GXX_LDFLAGS.dll ?= $(TOOL_GXX_LDFLAGS.$(KBUILD_TARGET)) endif # General Properties used by kBuild TOOL_GXX_COBJSUFF ?= .o TOOL_GXX_CFLAGS ?= TOOL_GXX_CFLAGS.debug ?= -g TOOL_GXX_CFLAGS.profile ?= -g -O2 #-pg TOOL_GXX_CFLAGS.release ?= -O2 TOOL_GXX_CINCS ?= TOOL_GXX_CDEFS ?= TOOL_GXX_CXXOBJSUFF ?= .o TOOL_GXX_CXXOBJSUFF ?= .o TOOL_GXX_CXXFLAGS ?= TOOL_GXX_CXXFLAGS.debug ?= -g -O0 TOOL_GXX_CXXFLAGS.profile ?= -g -O2 #-pg TOOL_GXX_CXXFLAGS.release ?= -O2 TOOL_GXX_CXXINCS ?= TOOL_GXX_CXXDEFS ?= TOOL_GXX_ASFLAGS ?= -x assembler-with-cpp TOOL_GXX_ASFLAGS.debug ?= -g TOOL_GXX_ASFLAGS.profile ?= -g TOOL_GXX_ASOBJSUFF ?= .o TOOL_GXX_ARFLAGS ?= cr TOOL_GXX_ARLIBSUFF ?= .a TOOL_GXX_LDFLAGS ?= TOOL_GXX_LDFLAGS.debug ?= -g TOOL_GXX_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX_COMPILE_C_OUTPUT = TOOL_GXX_COMPILE_C_DEPEND = TOOL_GXX_COMPILE_C_DEPORD = define TOOL_GXX_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX_COMPILE_CXX_OUTPUT = TOOL_GXX_COMPILE_CXX_DEPEND = TOOL_GXX_COMPILE_CXX_DEPORD = define TOOL_GXX_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX_COMPILE_AS_OUTPUT = TOOL_GXX_COMPILE_AS_DEPEND = TOOL_GXX_COMPILE_AS_DEPORD = define TOOL_GXX_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX_LINK_LIBRARY_OUTPUT = TOOL_GXX_LINK_LIBRARY_DEPEND = TOOL_GXX_LINK_LIBRARY_DEPORD = define TOOL_GXX_LINK_LIBRARY_CMDS $(QUIET)$(TOOL_GXX_AR) $(flags) $(out) $(objs) $(call xargs,$(QUIET)$(TOOL_GXX_AR) $(flags) $(out),$(objs)) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GXX_AR) x $(abspath $(lib)) \ && $(TOOL_GXX_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) $(QUIET)$(TOOL_GXX_RANLIB) $(out) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX_LINK_PROGRAM_OUTPUT = TOOL_GXX_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX_LINK_PROGRAM_DEPORD = define TOOL_GXX_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GXX_LD) $(flags) -o $(out) $(objs) \ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX_LINK_DLL_OUTPUT = TOOL_GXX_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX_LINK_DLL_DEPORD = define TOOL_GXX_LINK_DLL_CMDS $(QUIET)$(TOOL_GXX_LD) $(TOOL_GXX_LDFLAGS.dll) $(flags) -o $(out) $(objs) \ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) endef kbuild-2695/kBuild/tools/VCC80X86.kmk0000644000000000000000000003405612247157310015612 0ustar rootroot# $Id: VCC80X86.kmk 2557 2011-12-13 12:48:32Z bird $ ## @file # kBuild Tool Config - Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting x86. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VCC80X86 := Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting x86. # Tool Specific Properties ifndef PATH_TOOL_VCC80X86 PATH_TOOL_VCC80X86 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*) ifeq ($(PATH_TOOL_VCC80X86),) PATH_TOOL_VCC80X86 := $(PATH_TOOL_VCC80) endif ifeq ($(PATH_TOOL_VCC80X86),) PATH_TOOL_VCC80X86 := $(PATH_TOOL_VCC80AMD64) endif ifeq ($(PATH_TOOL_VCC80X86),) PATH_TOOL_VCC80X86 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/vcc/v8*) endif ifeq ($(PATH_TOOL_VCC80X86),) PATH_TOOL_VCC80X86 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/vcc/v8*) endif ifneq ($(PATH_TOOL_VCC80X86),) PATH_TOOL_VCC80X86 := $(lastword $(sort $(PATH_TOOL_VCC80X86))) else $(warning kBuild: PATH_TOOL_VCC80X86 cannot be determined!) PATH_TOOL_VCC80X86 := $(PATH_DEVTOOLS)/x86.win/vcc/v8 endif else # Resolve any fancy stuff once and for all. PATH_TOOL_VCC80X86 := $(PATH_TOOL_VCC80X86) endif PATH_TOOL_VCC80X86_BIN ?= $(PATH_TOOL_VCC80X86)/bin PATH_TOOL_VCC80X86_LIB ?= $(PATH_TOOL_VCC80X86)/lib PATH_TOOL_VCC80X86_INC ?= $(PATH_TOOL_VCC80X86)/include PATH_TOOL_VCC80X86_ATLMFC ?= $(PATH_TOOL_VCC80X86)/atlmfc PATH_TOOL_VCC80X86_ATLMFC_INC ?= $(PATH_TOOL_VCC80X86_ATLMFC)/include PATH_TOOL_VCC80X86_ATLMFC_LIB ?= $(PATH_TOOL_VCC80X86_ATLMFC)/lib TOOL_VCC80X86_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/cl.exe TOOL_VCC80X86_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/cl.exe TOOL_VCC80X86_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/ml.exe TOOL_VCC80X86_RC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/rc.exe TOOL_VCC80X86_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/lib.exe TOOL_VCC80X86_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/link.exe TOOL_VCC80X86_MT ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80X86_BIN)/mt.exe ## Disabled fast DEP_IDB based dependencies. #VCC80X86_OLD_DEPS = 1 ## Constructs the correct .pdb name (the name is lowercased). # @param $(1) Base name, no extention. # @param $(2) The extension. TOOL_VCC80X86_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) # General Properties used by kBuild TOOL_VCC80X86_COBJSUFF ?= .obj TOOL_VCC80X86_CFLAGS ?= -TC -c -nologo TOOL_VCC80X86_CFLAGS.debug ?= -Zi TOOL_VCC80X86_CFLAGS.release ?= -O2 TOOL_VCC80X86_CFLAGS.profile ?= -O2 TOOL_VCC80X86_CINCS ?= $(PATH_TOOL_VCC80X86_INC) TOOL_VCC80X86_CDEFS ?= TOOL_VCC80X86_CXXOBJSUFF ?= .obj TOOL_VCC80X86_CXXFLAGS ?= -TP -c -nologo TOOL_VCC80X86_CXXFLAGS.debug ?= -Zi TOOL_VCC80X86_CXXFLAGS.release ?= -O2 TOOL_VCC80X86_CXXFLAGS.profile ?= -O2 TOOL_VCC80X86_CXXINCS ?= $(PATH_TOOL_VCC80X86_INC) $(PATH_TOOL_VCC80X86_ATLMFC_INC) TOOL_VCC80X86_CXXDEFS ?= TOOL_VCC80X86_ASOBJSUFF ?= .obj TOOL_VCC80X86_RCOBJSUFF ?= .res TOOL_VCC80X86_RCINCS ?= $(PATH_TOOL_VCC80X86_INC) $(PATH_TOOL_VCC80X86_ATLMFC_INC) TOOL_VCC80X86_ARFLAGS ?= -nologo TOOL_VCC80X86_ARLIBSUFF ?= .lib TOOL_VCC80X86_LDFLAGS ?= -nologo -machine:x86 TOOL_VCC80X86_LDFLAGS.debug ?= -debug TOOL_VCC80X86_LDFLAGS.release ?= ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80X86_COMPILE_C_DEPEND = TOOL_VCC80X86_COMPILE_C_DEPORD = TOOL_VCC80X86_COMPILE_C_OUTPUT = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,idb) TOOL_VCC80X86_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,pdb) define TOOL_VCC80X86_COMPILE_C_CMDS $(QUIET)$(TOOL_VCC80X86_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC80X86_PDB,$(outbase)-obj,idb) endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80X86_COMPILE_CXX_DEPEND = TOOL_VCC80X86_COMPILE_CXX_DEPORD = TOOL_VCC80X86_COMPILE_CXX_OUTPUT = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,idb) TOOL_VCC80X86_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC80X86_PDB, $(outbase)-obj,pdb) define TOOL_VCC80X86_COMPILE_CXX_CMDS $(QUIET)$(TOOL_VCC80X86_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC80X86_PDB,$(outbase)-obj,idb) endef ## @todo configure the assembler template. ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80X86_COMPILE_RC_DEPEND = TOOL_VCC80X86_COMPILE_RC_DEPORD = TOOL_VCC80X86_COMPILE_RC_OUTPUT = define TOOL_VCC80X86_COMPILE_RC_CMDS $(QUIET)$(TOOL_VCC80X86_RC) \ $(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\ /fo$(obj)\ $(subst /,\\,$(abspath $(source))) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC80X86_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VCC80X86_LINK_LIBRARY_DEPORD = TOOL_VCC80X86_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_VCC80X86_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb define TOOL_VCC80X86_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs) \ $(filter-out %.def,$(othersrc))) \ $(addprefix /DEF:,$(filter %.def,$(othersrc))) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80X86_AR) $(flags) /OUT:$(out) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC80X86_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80X86_LINK_PROGRAM_DEPORD = TOOL_VCC80X86_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC80X86_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC80X86_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80X86_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80X86_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80X86_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80X86_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out)) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC80X86_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80X86_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) TOOL_VCC80X86_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp TOOL_VCC80X86_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp TOOL_VCC80X86_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80X86_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80X86_LINK_DLL_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80X86_LD) $(flags) \ /OUT:$(out) \ /IMPLIB:$(outbase).lib \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ /DLL \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' $(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/ $(eval _DIRS += $(PATH_STAGE_LIB)) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC80X86_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80X86_LINK_SYSMOD_DEPORD = TOOL_VCC80X86_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC80X86_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC80X86_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80X86_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80X86_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80X86_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' endef kbuild-2695/kBuild/tools/GXX32.kmk0000644000000000000000000003272612247157310015336 0ustar rootroot# $Id: GXX32.kmk 2541 2011-08-03 09:51:30Z bird $ ## @file # kBuild Tool Config - Generic 32-bit GCC v3.2.x or later using the system GCC, for building C++ code. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX32 := Generic 32-bit GCC v3.2.x or later using the system GCC, for building C++ code. \ More or less Linux/ELF specfic. # Tool Specific Properties TOOL_GXX32_CC ?= gcc$(HOSTSUFF_EXE) -m32 TOOL_GXX32_CXX ?= g++$(HOSTSUFF_EXE) -m32 TOOL_GXX32_AS ?= gcc$(HOSTSUFF_EXE) -m32 TOOL_GXX32_AR ?= ar$(HOSTSUFF_EXE) TOOL_GXX32_LD ?= g++$(HOSTSUFF_EXE) -m32 TOOL_GXX32_LD_SYSMOD ?= ld$(HOSTSUFF_EXE) ifndef TOOL_GXX32_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX32_LDFLAGS.dll ?= -shared else TOOL_GXX32_LDFLAGS.dll ?= $(TOOL_GXX32_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GXX32_LDFLAGS.sysmod ?= -r -m elf_i386$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,) TOOL_GXX32_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) ifeq ($(KBUILD_TARGET),os2) TOOL_GXX32_LD_MAP ?= -Zmap=$(1) else TOOL_GXX32_LD_MAP ?= endif ifeq ($(KBUILD_TARGET),os2) TOOL_GXX32_LD_SYSMOD_MAP ?= -Zmap=$(1) else TOOL_GXX32_LD_SYSMOD_MAP ?= endif if1of ($(KBUILD_HOST), solaris) TOOL_GXX32_OBJCOPY ?= gobjcopy$(HOSTSUFF_EXE) else TOOL_GXX32_OBJCOPY ?= objcopy$(HOSTSUFF_EXE) endif ifdef SLKRUNS TOOL_GXX32_CC += -fmessage-length=0 TOOL_GXX32_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GXX32_COBJSUFF ?= .o TOOL_GXX32_CFLAGS ?= TOOL_GXX32_CFLAGS.debug ?= -g TOOL_GXX32_CFLAGS.profile ?= -O2 #-g -pg TOOL_GXX32_CFLAGS.release ?= -O2 TOOL_GXX32_CINCS ?= TOOL_GXX32_CDEFS ?= TOOL_GXX32_CXXOBJSUFF ?= .o TOOL_GXX32_CXXOBJSUFF ?= .o TOOL_GXX32_CXXFLAGS ?= TOOL_GXX32_CXXFLAGS.debug ?= -g TOOL_GXX32_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX32_CXXFLAGS.release ?= -O2 TOOL_GXX32_CXXINCS ?= TOOL_GXX32_CXXDEFS ?= TOOL_GXX32_ASFLAGS ?= -x assembler-with-cpp TOOL_GXX32_ASFLAGS.debug ?= -g TOOL_GXX32_ASFLAGS.profile ?= -g TOOL_GXX32_ASOBJSUFF ?= .o TOOL_GXX32_ARFLAGS ?= cr TOOL_GXX32_ARLIBSUFF ?= .a TOOL_GXX32_LDFLAGS ?= TOOL_GXX32_LDFLAGS.debug ?= -g TOOL_GXX32_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX32_COMPILE_C_DEPEND = TOOL_GXX32_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX32_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GXX32_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GXX32_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GXX32_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX32_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX32_COMPILE_C_OUTPUT = define TOOL_GXX32_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX32_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX32_COMPILE_CXX_DEPEND = TOOL_GXX32_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX32_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GXX32_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GXX32_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX32_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX32_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX32_COMPILE_CXX_OUTPUT = define TOOL_GXX32_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX32_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX32_COMPILE_AS_OUTPUT = TOOL_GXX32_COMPILE_AS_DEPEND = TOOL_GXX32_COMPILE_AS_DEPORD = define TOOL_GXX32_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX32_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX32_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_GXX32_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GXX32_LINK_LIBRARY_DEPORD = define TOOL_GXX32_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(filter-out %.def %.imp,$(othersrc)), 'ADDLIB $(o)') $(if $(filter %.def %.imp,$(othersrc))\ ,$(TOOL_GXX3_AR_IMP) -o $(outbase).imp.a $(filter %.def %.imp,$(othersrc))\ $(NL)$(TAB)$(QUIET)$(APPEND) $(out).ar-script 'ADDLIB $(outbase).imp.a') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_GXX32_AR) -M endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX32_LINK_PROGRAM_OUTPUT = TOOL_GXX32_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map TOOL_GXX32_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX32_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX32_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX32_LINK_PROGRAM_DEPORD = define TOOL_GXX32_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_GXX32_LD) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX32_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX32_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX32_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX32_LINK_DLL_OUTPUT = TOOL_GXX32_LINK_DLL_OUTPUT_MAYBE = $(outbase).map TOOL_GXX32_LINK_DLL_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX32_LINK_DLL_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX32_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX32_LINK_DLL_DEPORD = define TOOL_GXX32_LINK_DLL_CMDS $(QUIET)$(TOOL_GXX32_LD) $(TOOL_GXX32_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win os2, $(KBUILD_TARGET)),$(call TOOL_GXX32_LD_SONAME,$(target),$(out)))\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX32_LD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX32_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX32_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX32_LINK_SYSMOD_OUTPUT = TOOL_GXX32_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).map TOOL_GXX32_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).debug TOOL_GXX32_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).debug=>$(basename $(3)).debug TOOL_GXX32_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ $(filter %.def, $(othersrc)) TOOL_GXX32_LINK_SYSMOD_DEPORD = define TOOL_GXX32_LINK_SYSMOD_CMDS $(QUIET)$(TOOL_GXX32_LD_SYSMOD) $(TOOL_GXX32_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\ $(filter %.def, $(othersrc))\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ $(call TOOL_GXX32_LD_SYSMOD_MAP,$(outbase).map) ifeq ($(ld_debug),split) $(TOOL_GXX32_OBJCOPY) --only-keep-debug $(out) $(outbase).debug $(CHMOD) a-x $(outbase).debug $(TOOL_GXX32_OBJCOPY) --strip-debug --strip-unneeded --add-gnu-debuglink=$(outbase).debug $(out) endif endef kbuild-2695/kBuild/tools/GXX42MACHO.kmk0000644000000000000000000004572412247157310016111 0ustar rootroot# $Id: GXX42MACHO.kmk 2547 2011-11-04 21:58:53Z bird $ ## @file # kBuild Tool Config - GCC v4.2.x targeting Darwin (Mac OS X) Mach-O, for building C++ code. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX42MACHO := GCC v4.2.x targeting Darwin (Mac OS X) Mach-O, for building C++ code. # Tool Specific Properties TOOL_GXX42MACHO_PREFIX ?= TOOL_GXX42MACHO_SUFFIX ?= -4.2$(HOSTSUFF_EXE) TOOL_GXX42MACHO_CC ?= $(TOOL_GXX42MACHO_PREFIX)gcc$(TOOL_GXX42MACHO_SUFFIX) TOOL_GXX42MACHO_CXX ?= $(TOOL_GXX42MACHO_PREFIX)g++$(TOOL_GXX42MACHO_SUFFIX) TOOL_GXX42MACHO_OBJC ?= $(TOOL_GXX42MACHO_PREFIX)gcc$(TOOL_GXX42MACHO_SUFFIX) TOOL_GXX42MACHO_OBJCXX ?= $(TOOL_GXX42MACHO_PREFIX)gcc$(TOOL_GXX42MACHO_SUFFIX) TOOL_GXX42MACHO_AS ?= $(TOOL_GXX42MACHO_PREFIX)gcc$(TOOL_GXX42MACHO_SUFFIX) TOOL_GXX42MACHO_LD ?= $(TOOL_GXX42MACHO_PREFIX)g++$(TOOL_GXX42MACHO_SUFFIX) TOOL_GXX42MACHO_LD_SYSMOD ?= $(TOOL_GXX42MACHO_PREFIX)g++$(TOOL_GXX42MACHO_SUFFIX) ifndef TOOL_GXX42MACHO_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX42MACHO_LDFLAGS.dll ?= -dynamiclib else TOOL_GXX42MACHO_LDFLAGS.dll ?= $(TOOL_GXX42MACHO_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GXX42MACHO_LDFLAGS.sysmod ?= -r #TOOL_GXX42MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_GXX42MACHO_DSYMUTIL ?= dsymutil ifdef SLKRUNS TOOL_GXX42MACHO_CC += -fmessage-length=0 TOOL_GXX42MACHO_CXX += -fmessage-length=0 TOOL_GXX42MACHO_OBJC += -fmessage-length=0 TOOL_GXX42MACHO_OBJCXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GXX42MACHO_COBJSUFF ?= .o TOOL_GXX42MACHO_CFLAGS ?= TOOL_GXX42MACHO_CFLAGS.debug ?= -g TOOL_GXX42MACHO_CFLAGS.profile ?= -O2 #-g -pg TOOL_GXX42MACHO_CFLAGS.release ?= -O2 TOOL_GXX42MACHO_CINCS ?= TOOL_GXX42MACHO_CDEFS ?= TOOL_GXX42MACHO_CXXOBJSUFF ?= .o TOOL_GXX42MACHO_CXXFLAGS ?= TOOL_GXX42MACHO_CXXFLAGS.debug ?= -g TOOL_GXX42MACHO_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX42MACHO_CXXFLAGS.release ?= -O2 TOOL_GXX42MACHO_CXXINCS ?= TOOL_GXX42MACHO_CXXDEFS ?= TOOL_GXX42MACHO_OBJCOBJSUFF ?= .o TOOL_GXX42MACHO_OBJCFLAGS ?= TOOL_GXX42MACHO_OBJCFLAGS.debug ?= -g TOOL_GXX42MACHO_OBJCFLAGS.profile?= -O2 #-g -pg TOOL_GXX42MACHO_OBJCFLAGS.release?= -O2 TOOL_GXX42MACHO_OBJCINCS ?= TOOL_GXX42MACHO_OBJCDEFS ?= TOOL_GXX42MACHO_OBJCXXOBJSUFF ?= .o TOOL_GXX42MACHO_OBJCXXFLAGS ?= TOOL_GXX42MACHO_OBJCXXFLAGS.debug ?= -g TOOL_GXX42MACHO_OBJCXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX42MACHO_OBJCXXFLAGS.release ?= -O2 TOOL_GXX42MACHO_OBJCXXINCS ?= TOOL_GXX42MACHO_OBJCXXDEFS ?= TOOL_GXX42MACHO_ASFLAGS ?= -x assembler-with-cpp TOOL_GXX42MACHO_ASFLAGS.debug ?= -g TOOL_GXX42MACHO_ASFLAGS.profile ?= -g TOOL_GXX42MACHO_ASOBJSUFF ?= .o TOOL_GXX42MACHO_AR ?= ar$(HOSTSUFF_EXE) TOOL_GXX42MACHO_ARFLAGS ?= -c -rs TOOL_GXX42MACHO_ARLIBSUFF ?= .a TOOL_GXX42MACHO_LDFLAGS ?= TOOL_GXX42MACHO_LDFLAGS.debug ?= -g TOOL_GXX42MACHO_LDFLAGS.profile ?= -g TOOL_GXX42MACHO_STRIP_PROGRAM ?= strip -SXxru TOOL_GXX42MACHO_STRIP_DLL ?= strip -Sxru TOOL_GXX42MACHO_STRIP_SYSMOD ?= strip -Sru ## # Calculate the files in the debug bundle. # @param 1 The whole output filename. # @param 2 The output filename sans suffix. TOOL_GXX42MACHO_DEBUG_BUNDLE_FN = \ $(1).dSYM/ \ $(1).dSYM/Contents/ \ $(1).dSYM/Contents/Resources/ \ $(1).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1)) ## # Calculate the files in the debug bundle. # @param 1 The whole linker output filename. # @param 2 The linker output filename sans suffix. # @param 3 The desired install name (no dir slash). # @remarks The Info.plist has some reference to the original name, but gdb # does not care and only check for a symbol file in the DWARF # directory with the same name as the debugged module. TOOL_GXX42MACHO_DEBUG_INSTALL_FN= \ $(3).dSYM/ \ $(3).dSYM/Contents/ \ $(3).dSYM/Contents/Resources/ \ $(3).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist=>$(3).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1))=>$(3).dSYM/Contents/Resources/DWARF/$(notdir $(3)) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX42MACHO_COMPILE_C_DEPEND = TOOL_GXX42MACHO_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GXX42MACHO_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GXX42MACHO_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GXX42MACHO_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX42MACHO_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_C_OUTPUT = define TOOL_GXX42MACHO_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX42MACHO_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KUSE_OBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX42MACHO_COMPILE_CXX_DEPEND = TOOL_GXX42MACHO_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GXX42MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GXX42MACHO_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX42MACHO_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX42MACHO_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_CXX_OUTPUT = define TOOL_GXX42MACHO_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX42MACHO_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX42MACHO_COMPILE_OBJC_DEPEND = TOOL_GXX42MACHO_COMPILE_OBJC_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1 TOOL_GXX42MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi define TOOL_GXX42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX42MACHO_OBJC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX42MACHO_OBJC) -c\ $(flags) -fpreprocessed -x objective-c \ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_OBJC_OUTPUT = define TOOL_GXX42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(TOOL_GXX42MACHO_OBJC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX42MACHO_COMPILE_OBJCXX_DEPEND = TOOL_GXX42MACHO_COMPILE_OBJCXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_OBJCXX_USES_KOBJCACHE = 1 TOOL_GXX42MACHO_COMPILE_OBJCXX_OUTPUT = $(outbase).mii define TOOL_GXX42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).mii\ $(TOOL_GXX42MACHO_OBJCXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX42MACHO_OBJCXX) -c\ $(flags) -fpreprocessed -x objective-c++ \ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX42MACHO_COMPILE_OBJCXX_OUTPUT = define TOOL_GXX42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(TOOL_GXX42MACHO_OBJCXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX42MACHO_COMPILE_AS_OUTPUT = TOOL_GXX42MACHO_COMPILE_AS_DEPEND = TOOL_GXX42MACHO_COMPILE_AS_DEPORD = define TOOL_GXX42MACHO_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX42MACHO_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX42MACHO_LINK_LIBRARY_OUTPUT = TOOL_GXX42MACHO_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GXX42MACHO_LINK_LIBRARY_DEPORD = define TOOL_GXX42MACHO_LINK_LIBRARY_CMDS $(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_GXX42MACHO_AR) $(flags) $(out),$(objs))) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GXX42MACHO_AR) -x $(abspath $(lib)) \ && $(RM_EXT) -f ./__.SYMDEF* \ && $(TOOL_GXX42MACHO_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX42MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp TOOL_GXX42MACHO_LINK_PROGRAM_OUTPUT_DEBUG = $(call TOOL_GXX42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GXX42MACHO_LINK_PROGRAM_DEBUG_INSTALL_FN = $(TOOL_GXX42MACHO_DEBUG_INSTALL_FN) TOOL_GXX42MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX42MACHO_LINK_PROGRAM_DEPORD = define TOOL_GXX42MACHO_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GXX42MACHO_LD) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GXX42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GXX42MACHO_STRIP_PROGRAM) $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX42MACHO_LINK_DLL_OUTPUT = $(outbase).rsp TOOL_GXX42MACHO_LINK_DLL_OUTPUT_DEBUG = $(call TOOL_GXX42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GXX42MACHO_LINK_DLL_DEBUG_INSTALL_FN = $(TOOL_GXX42MACHO_DEBUG_INSTALL_FN) TOOL_GXX42MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX42MACHO_LINK_DLL_DEPORD = define TOOL_GXX42MACHO_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GXX42MACHO_LD) $(TOOL_GXX42MACHO_LDFLAGS.dll) $(flags) -o $(out)\ $(call TOOL_GXX42MACHO_LD_SONAME,$(target),$(out))\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GXX42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GXX42MACHO_STRIP_DLL) $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX42MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp TOOL_GXX42MACHO_LINK_SYSMOD_OUTPUT_DEBUG = $(call TOOL_GXX42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GXX42MACHO_LINK_SYSMOD_DEBUG_INSTALL_FN = $(TOOL_GXX42MACHO_DEBUG_INSTALL_FN) TOOL_GXX42MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GXX42MACHO_LINK_SYSMOD_DEPORD = define TOOL_GXX42MACHO_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GXX42MACHO_LD_SYSMOD) $(TOOL_GXX42MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GXX42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GXX42MACHO_STRIP_SYSMOD) $(out) endif endef kbuild-2695/kBuild/tools/GXX3OMF.kmk0000644000000000000000000002747312247157310015621 0ustar rootroot# $Id: GXX3OMF.kmk 2545 2011-09-13 19:09:05Z bird $ ## @file # kBuild Tool Config - GCC v3 targeting OS/2 OMF, for building C++ code. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GXX3OMF := GCC v3 targeting OS/2 OMF, for building C++ code. # Tool Specific Properties TOOL_GXX3OMF_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GXX3OMF_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GXX3OMF_AS ?= gcc$(HOSTSUFF_EXE) TOOL_GXX3OMF_AR ?= emxomfar$(HOSTSUFF_EXE) TOOL_GXX3OMF_AR_IMP ?= emximp$(HOSTSUFF_EXE) TOOL_GXX3OMF_LD ?= g++$(HOSTSUFF_EXE) TOOL_GXX3OMF_LD_SYSMOD ?= g++$(HOSTSUFF_EXE) ifndef TOOL_GXX3OMF_LDFLAGS.$(KBUILD_TARGET) TOOL_GXX3OMF_LDFLAGS.dll ?= -shared -Zdll else TOOL_GXX3OMF_LDFLAGS.dll ?= $(TOOL_GXX3OMF_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GXX3OMF_LDFLAGS.sysmod ?= -nostdlib TOOL_GXX3OMF_LD_MAP ?= -Zmap=$(1) TOOL_GXX3OMF_LD_SYSMOD_MAP ?= -Zmap=$(1) ifdef SLKRUNS TOOL_GXX3OMF_CC += -fmessage-length=0 TOOL_GXX3OMF_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GXX3OMF_COBJSUFF ?= .o TOOL_GXX3OMF_CFLAGS ?= -Zomf TOOL_GXX3OMF_CFLAGS.debug ?= -g TOOL_GXX3OMF_CFLAGS.profile ?= -O2 #-g -pg TOOL_GXX3OMF_CFLAGS.release ?= -O2 TOOL_GXX3OMF_CINCS ?= TOOL_GXX3OMF_CDEFS ?= TOOL_GXX3OMF_CXXOBJSUFF ?= .o TOOL_GXX3OMF_CXXOBJSUFF ?= .o TOOL_GXX3OMF_CXXFLAGS ?= -Zomf TOOL_GXX3OMF_CXXFLAGS.debug ?= -g TOOL_GXX3OMF_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GXX3OMF_CXXFLAGS.release ?= -O2 TOOL_GXX3OMF_CXXINCS ?= TOOL_GXX3OMF_CXXDEFS ?= TOOL_GXX3OMF_ASFLAGS ?= -x assembler-with-cpp -Zomf TOOL_GXX3OMF_ASFLAGS.debug ?= -g TOOL_GXX3OMF_ASFLAGS.profile ?= -g TOOL_GXX3OMF_ASOBJSUFF ?= .obj TOOL_GXX3OMF_ARFLAGS ?= cr TOOL_GXX3OMF_ARLIBSUFF ?= .lib TOOL_GXX3OMF_LDFLAGS ?= -Zomf TOOL_GXX3OMF_LDFLAGS.debug ?= -g TOOL_GXX3OMF_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX3OMF_COMPILE_C_DEPEND = TOOL_GXX3OMF_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX3OMF_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GXX3OMF_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GXX3OMF_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GXX3OMF_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX3OMF_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX3OMF_COMPILE_C_OUTPUT = define TOOL_GXX3OMF_COMPILE_C_CMDS $(QUIET)$(TOOL_GXX3OMF_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GXX3OMF_COMPILE_CXX_DEPEND = TOOL_GXX3OMF_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GXX3OMF_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GXX3OMF_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GXX3OMF_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GXX3OMF_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GXX3OMF_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GXX3OMF_COMPILE_CXX_OUTPUT = define TOOL_GXX3OMF_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GXX3OMF_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GXX3OMF_COMPILE_AS_OUTPUT = TOOL_GXX3OMF_COMPILE_AS_DEPEND = TOOL_GXX3OMF_COMPILE_AS_DEPORD = define TOOL_GXX3OMF_COMPILE_AS_CMDS $(QUIET)$(TOOL_GXX3OMF_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3OMF_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_GXX3OMF_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GXX3OMF_LINK_LIBRARY_DEPORD = define TOOL_GXX3OMF_LINK_LIBRARY_CMDS $(if $(filter %.def %.imp,$(othersrc))\ ,$(QUIET)$(APPEND) -n $(outbase).rsp $(filter %.def %.imp,$(othersrc))\ $(NL)$(TAB)$(QUIET)$(QUIET)$(TOOL_GXX3OMF_AR_IMP) -o $(out) @$(outbase).rsp\ $(NL)$(TAB)$(QUIET)$(RM) -f $(outbase).rsp) $(QUIET)$(APPEND) -n $(outbase).rsp $(flags) $(out) $(objs) $(filter-out %.def %.imp,$(othersrc)) $(TOOL_GXX3OMF_AR) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3OMF_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_GXX3OMF_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_GXX3OMF_LINK_PROGRAM_DEPORD = define TOOL_GXX3OMF_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp\ $(flags)\ -o $(out)\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(othersrc)\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ -Zmap=$(outbase).map $(QUIET)$(TOOL_GXX3OMF_LD) @$(outbase).rsp endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3OMF_LINK_DLL_OUTPUT = $(outbase).map $(outbase).rsp TOOL_GXX3OMF_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_GXX3OMF_LINK_DLL_DEPORD = define TOOL_GXX3OMF_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp\ $(TOOL_GXX3OMF_LDFLAGS.dll)\ $(flags)\ -o $(out)\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(othersrc)\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ -Zmap=$(outbase).map $(TOOL_GXX3OMF_LD) @$(outbase).rsp endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GXX3OMF_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_GXX3OMF_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_GXX3OMF_LINK_SYSMOD_DEPORD = define TOOL_GXX3OMF_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp\ $(TOOL_GXX3OMF_LDFLAGS.sysmod)\ $(flags)\ -o $(out)\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(othersrc)\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ -Zmap=$(outbase).map $(QUIET)$(TOOL_GXX3OMF_LD_SYSMOD) @$(outbase).rsp endef kbuild-2695/kBuild/tools/ALP.kmk0000644000000000000000000000517512247157310015135 0ustar rootroot# $Id: ALP.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - ALP or later. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_ALP := The IBM Assembly Language Processor # Tool Specific Properties ifndef PATH_TOOL_ALP PATH_TOOL_ALP := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/alp/v*.*)) ifneq ($(PATH_TOOL_ALP),) PATH_TOOL_ALP := $(call lastword,$(PATH_TOOL_ALP)) endif endif ifneq ($(PATH_TOOL_ALP),) TOOL_ALP_AS ?= $(PATH_TOOL_ALP)/alp$(HOSTSUFF_EXE) else TOOL_ALP_AS ?= alp$(HOSTSUFF_EXE) endif # General Properties used by kBuild TOOL_ALP_ASFLAGS ?= -Mb ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_ALP_COMPILE_AS_OUTPUT = $(outbase).lst TOOL_ALP_COMPILE_AS_DEPEND = TOOL_ALP_COMPILE_AS_DEPORD = define TOOL_ALP_COMPILE_AS_CMDS $(QUIET)$(TOOL_ALP_AS)\ $(flags) $(addsuffix /,$(addprefix -I:, $(incs))) $(addprefix -D:, $(defs))\ $(source)\ -Fl:$(outbase).lst\ -Fd:$(dep)\ -Fo:$(obj) endef kbuild-2695/kBuild/tools/GCC3OMF.kmk0000644000000000000000000002741512247157310015543 0ustar rootroot# $Id: GCC3OMF.kmk 2545 2011-09-13 19:09:05Z bird $ ## @file # kBuild Tool Config - GCC v3 targeting OS/2 OMF. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC3OMF := GCC v3 targeting OS/2 OMF. # Tool Specific Properties TOOL_GCC3OMF_CC ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3OMF_CXX ?= g++$(HOSTSUFF_EXE) TOOL_GCC3OMF_AS ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3OMF_AR ?= emxomfar$(HOSTSUFF_EXE) TOOL_GCC3OMF_AR_IMP ?= emximp$(HOSTSUFF_EXE) TOOL_GCC3OMF_LD ?= gcc$(HOSTSUFF_EXE) TOOL_GCC3OMF_LD_SYSMOD ?= gcc$(HOSTSUFF_EXE) ifndef TOOL_GCC3OMF_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC3OMF_LDFLAGS.dll ?= -shared -Zdll else TOOL_GCC3OMF_LDFLAGS.dll ?= $(TOOL_GCC3OMF_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GCC3OMF_LDFLAGS.sysmod ?= -nostdlib TOOL_GCC3OMF_LD_MAP ?= -Zmap=$(1) TOOL_GCC3OMF_LD_SYSMOD_MAP ?= -Zmap=$(1) ifdef SLKRUNS TOOL_GCC3OMF_CC += -fmessage-length=0 TOOL_GCC3OMF_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GCC3OMF_COBJSUFF ?= .o TOOL_GCC3OMF_CFLAGS ?= -Zomf TOOL_GCC3OMF_CFLAGS.debug ?= -g TOOL_GCC3OMF_CFLAGS.profile ?= -O2 #-g -pg TOOL_GCC3OMF_CFLAGS.release ?= -O2 TOOL_GCC3OMF_CINCS ?= TOOL_GCC3OMF_CDEFS ?= TOOL_GCC3OMF_CXXOBJSUFF ?= .o TOOL_GCC3OMF_CXXOBJSUFF ?= .o TOOL_GCC3OMF_CXXFLAGS ?= -Zomf TOOL_GCC3OMF_CXXFLAGS.debug ?= -g TOOL_GCC3OMF_CXXFLAGS.profile ?= -O2 #-g -pg TOOL_GCC3OMF_CXXFLAGS.release ?= -O2 TOOL_GCC3OMF_CXXINCS ?= TOOL_GCC3OMF_CXXDEFS ?= TOOL_GCC3OMF_ASFLAGS ?= -x assembler-with-cpp -Zomf TOOL_GCC3OMF_ASFLAGS.debug ?= -g TOOL_GCC3OMF_ASFLAGS.profile ?= -g TOOL_GCC3OMF_ASOBJSUFF ?= .obj TOOL_GCC3OMF_ARFLAGS ?= cr TOOL_GCC3OMF_ARLIBSUFF ?= .lib TOOL_GCC3OMF_LDFLAGS ?= -Zomf TOOL_GCC3OMF_LDFLAGS.debug ?= -g TOOL_GCC3OMF_LDFLAGS.profile ?= -g ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC3OMF_COMPILE_C_DEPEND = TOOL_GCC3OMF_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC3OMF_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GCC3OMF_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GCC3OMF_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GCC3OMF_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC3OMF_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC3OMF_COMPILE_C_OUTPUT = define TOOL_GCC3OMF_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC3OMF_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC3OMF_COMPILE_CXX_DEPEND = TOOL_GCC3OMF_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC3OMF_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GCC3OMF_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GCC3OMF_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC3OMF_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC3OMF_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC3OMF_COMPILE_CXX_OUTPUT = define TOOL_GCC3OMF_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC3OMF_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP \ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC3OMF_COMPILE_AS_OUTPUT = TOOL_GCC3OMF_COMPILE_AS_DEPEND = TOOL_GCC3OMF_COMPILE_AS_DEPORD = define TOOL_GCC3OMF_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC3OMF_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3OMF_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_GCC3OMF_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GCC3OMF_LINK_LIBRARY_DEPORD = define TOOL_GCC3OMF_LINK_LIBRARY_CMDS $(if $(filter %.def %.imp,$(othersrc))\ ,$(QUIET)$(APPEND) -n $(outbase).rsp $(filter %.def %.imp,$(othersrc))\ $(NL)$(TAB)$(QUIET)$(QUIET)$(TOOL_GCC3OMF_AR_IMP) -o $(out) @$(outbase).rsp\ $(NL)$(TAB)$(QUIET)$(RM) -f $(outbase).rsp) $(QUIET)$(APPEND) -n $(outbase).rsp $(flags) $(out) $(objs) $(filter-out %.def %.imp,$(othersrc)) $(TOOL_GCC3OMF_AR) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3OMF_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_GCC3OMF_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_GCC3OMF_LINK_PROGRAM_DEPORD = define TOOL_GCC3OMF_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp\ $(flags)\ -o $(out)\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(othersrc)\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ -Zmap=$(outbase).map $(QUIET)$(TOOL_GCC3OMF_LD) @$(outbase).rsp endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3OMF_LINK_DLL_OUTPUT = $(outbase).map $(outbase).rsp TOOL_GCC3OMF_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_GCC3OMF_LINK_DLL_DEPORD = define TOOL_GCC3OMF_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp\ $(TOOL_GCC3OMF_LDFLAGS.dll)\ $(flags)\ -o $(out)\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(othersrc)\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ -Zmap=$(outbase).map $(TOOL_GCC3OMF_LD) @$(outbase).rsp endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC3OMF_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_GCC3OMF_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_GCC3OMF_LINK_SYSMOD_DEPORD = define TOOL_GCC3OMF_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp\ $(TOOL_GCC3OMF_LDFLAGS.sysmod)\ $(flags)\ -o $(out)\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(othersrc)\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib)))\ -Zmap=$(outbase).map $(QUIET)$(TOOL_GCC3OMF_LD_SYSMOD) @$(outbase).rsp endef kbuild-2695/kBuild/tools/XGCCAMD64LINUX.kmk0000644000000000000000000003063712247157310016562 0ustar rootroot# $Id: XGCCAMD64LINUX.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - GCC Cross compiler for AMD64+Linux. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_XGCCAMD64LINUX := GCC Cross compiler for AMD64+Linux. # Tool Specific Properties TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE ?= $(HOSTSUFF_EXE) ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),linux.amd64) # not x-compile, use the default gcc. TOOL_XGCCAMD64LINUX_PREFIX := $(TOOL_XGCCAMD64LINUX_PREFIX) else # x-compile: # find the latest xgcc build. ifndef TOOL_XGCCAMD64LINUX_PREFIX TOOL_XGCCAMD64LINUX_PREFIX := x86_64-unknown-linux-gnu- ifndef PATH_TOOL_XGCCAMD64LINUX PATH_TOOL_XGCCAMD64LINUX := $(sort $(wildcard $(PATH_DEVTOOLS_BLD)/x86_64-unknown-linux-gnu/*)) ifeq ($(PATH_TOOL_XGCCAMD64LINUX),) ifeq ($(filter-out win.amd64,$(KBUILD_HOST).$(KBUILD_HOST_ARCH)),) # these can use the windows build. TOOL_XGCCAMD64LINUX_EXEC_PREFIX ?= $(EXEC_X86_WIN32) TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE := .exe PATH_TOOL_XGCCAMD64LINUX := $(sort $(wildcard $(PATH_DEVTOOLS)/win.x86/x86_64-unknown-linux-gnu/*)) ifeq ($(PATH_TOOL_XGCCAMD64LINUX),) PATH_TOOL_XGCCAMD64LINUX := $(sort $(wildcard $(PATH_DEVTOOLS)/x86.win32/x86_64-unknown-linux-gnu/*)) endif endif endif ifneq ($(PATH_TOOL_XGCCAMD64LINUX),) PATH_TOOL_XGCCAMD64LINUX := $(call lastword,$(PATH_TOOL_XGCCAMD64LINUX)) endif endif # !PATH_TOOL_XGCCAMD64LINUX ifneq ($(PATH_TOOL_XGCCAMD64LINUX),) TOOL_XGCCAMD64LINUX_PREFIX := $(TOOL_XGCCAMD64LINUX_EXEC_PREFIX) $(PATH_TOOL_XGCCAMD64LINUX)/bin/$(TOOL_XGCCAMD64LINUX_PREFIX) endif else # Resolve any fancy stuff once and for all. TOOL_XGCCAMD64LINUX_PREFIX := $(TOOL_XGCCAMD64LINUX_PREFIX) endif endif TOOL_XGCCAMD64LINUX_CC ?= $(TOOL_XGCCAMD64LINUX_PREFIX)gcc$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE) TOOL_XGCCAMD64LINUX_CXX ?= $(TOOL_XGCCAMD64LINUX_PREFIX)g++$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE) TOOL_XGCCAMD64LINUX_AS ?= $(TOOL_XGCCAMD64LINUX_PREFIX)gcc$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE) TOOL_XGCCAMD64LINUX_AR ?= $(TOOL_XGCCAMD64LINUX_PREFIX)ar$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE) TOOL_XGCCAMD64LINUX_LD ?= $(TOOL_XGCCAMD64LINUX_PREFIX)g++$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE) TOOL_XGCCAMD64LINUX_LD_SYSMOD ?= $(TOOL_XGCCAMD64LINUX_PREFIX)ld$(TOOL_XGCCAMD64LINUX_HOSTSUFF_EXE) TOOL_XGCCAMD64LINUX_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_XGCCAMD64LINUX_LD_MAP ?= -Wl,-Map -Wl,$(1) -Wl,--cref TOOL_XGCCAMD64LINUX_LD_SYSMOD_MAP ?= -Map $(1) --cref TOOL_XGCCAMD64LINUX_LDFLAGS.dll ?= -shared TOOL_XGCCAMD64LINUX_LDFLAGS.sysmod ?= -r ifdef SLKRUNS TOOL_XGCCAMD64LINUX_CC += -fmessage-length=0 TOOL_XGCCAMD64LINUX_CXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_XGCCAMD64LINUX_COBJSUFF ?= .o TOOL_XGCCAMD64LINUX_CFLAGS ?= -g TOOL_XGCCAMD64LINUX_CFLAGS.debug ?= -O0 TOOL_XGCCAMD64LINUX_CFLAGS.release ?= -O2 TOOL_XGCCAMD64LINUX_CFLAGS.profile ?= -O2 #-pg TOOL_XGCCAMD64LINUX_CINCS ?= TOOL_XGCCAMD64LINUX_CDEFS ?= TOOL_XGCCAMD64LINUX_CXXOBJSUFF ?= .o TOOL_XGCCAMD64LINUX_CXXOBJSUFF ?= .o TOOL_XGCCAMD64LINUX_CXXFLAGS ?= -g TOOL_XGCCAMD64LINUX_CXXFLAGS.debug ?= -O0 TOOL_XGCCAMD64LINUX_CXXFLAGS.release ?= -O2 TOOL_XGCCAMD64LINUX_CXXFLAGS.profile ?= -O2 #-pg TOOL_XGCCAMD64LINUX_CXXINCS ?= TOOL_XGCCAMD64LINUX_CXXDEFS ?= TOOL_XGCCAMD64LINUX_ASFLAGS ?= -g -x assembler-with-cpp TOOL_XGCCAMD64LINUX_ASOBJSUFF ?= .o TOOL_XGCCAMD64LINUX_ARFLAGS ?= cr TOOL_XGCCAMD64LINUX_ARLIBSUFF ?= .a TOOL_XGCCAMD64LINUX_LDFLAGS ?= TOOL_XGCCAMD64LINUX_LDFLAGS.debug ?= -g TOOL_XGCCAMD64LINUX_LDFLAGS.release ?= -s ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_XGCCAMD64LINUX_COMPILE_C_OUTPUT = TOOL_XGCCAMD64LINUX_COMPILE_C_DEPEND = TOOL_XGCCAMD64LINUX_COMPILE_C_DEPORD = define TOOL_XGCCAMD64LINUX_COMPILE_C_CMDS $(QUIET)$(TOOL_XGCCAMD64LINUX_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_XGCCAMD64LINUX_COMPILE_CXX_OUTPUT = TOOL_XGCCAMD64LINUX_COMPILE_CXX_DEPEND = TOOL_XGCCAMD64LINUX_COMPILE_CXX_DEPORD = define TOOL_XGCCAMD64LINUX_COMPILE_CXX_CMDS $(QUIET)$(TOOL_XGCCAMD64LINUX_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_XGCCAMD64LINUX_COMPILE_AS_OUTPUT = TOOL_XGCCAMD64LINUX_COMPILE_AS_DEPEND = TOOL_XGCCAMD64LINUX_COMPILE_AS_DEPORD = define TOOL_XGCCAMD64LINUX_COMPILE_AS_CMDS $(QUIET)$(TOOL_XGCCAMD64LINUX_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_XGCCAMD64LINUX_LINK_LIBRARY_OUTPUT = $(out).ar-script TOOL_XGCCAMD64LINUX_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_XGCCAMD64LINUX_LINK_LIBRARY_DEPORD = define TOOL_XGCCAMD64LINUX_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' $(QUIET)$(APPEND) -n $(out).ar-script \ $(foreach o,$(objs), 'ADDMOD $(o)') \ $(foreach o,$(othersrc), 'ADDLIB $(o)') $(QUIET)$(APPEND) $(out).ar-script 'SAVE' $(QUIET)$(APPEND) $(out).ar-script 'END' $(QUIET)$(REDIRECT) -rti $(out).ar-script -- $(TOOL_XGCCAMD64LINUX_AR) -M endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_XGCCAMD64LINUX_LINK_PROGRAM_OUTPUT = $(outbase).map TOOL_XGCCAMD64LINUX_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_XGCCAMD64LINUX_LINK_PROGRAM_DEPORD = define TOOL_XGCCAMD64LINUX_LINK_PROGRAM_CMDS $(QUIET)$(TOOL_XGCCAMD64LINUX_LD) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))\ $(call TOOL_XGCCAMD64LINUX_LD_MAP,$(outbase).map) endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_XGCCAMD64LINUX_LINK_DLL_OUTPUT = $(outbase).map TOOL_XGCCAMD64LINUX_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_XGCCAMD64LINUX_LINK_DLL_DEPORD = define TOOL_XGCCAMD64LINUX_LINK_DLL_CMDS $(QUIET)$(TOOL_XGCCAMD64LINUX_LD) $(TOOL_XGCCAMD64LINUX_LDFLAGS.dll) $(flags) -o $(out)\ $(if $(filter-out win32 os2, $(KBUILD_TARGET)),$(call TOOL_XGCCAMD64LINUX_LD_SONAME,$(target),$(out)))\ $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))\ $(call TOOL_XGCCAMD64LINUX_LD_MAP,$(outbase).map) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_XGCCAMD64LINUX_LINK_SYSMOD_OUTPUT = $(outbase).map TOOL_XGCCAMD64LINUX_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_XGCCAMD64LINUX_LINK_SYSMOD_DEPORD = define TOOL_XGCCAMD64LINUX_LINK_SYSMOD_CMDS $(QUIET)$(TOOL_XGCCAMD64LINUX_LD_SYSMOD) $(TOOL_XGCCAMD64LINUX_LDFLAGS.sysmod) $(flags) -o $(out) $(objs)\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib)))\ $(call TOOL_XGCCAMD64LINUX_LD_SYSMOD_MAP,$(outbase).map) endef kbuild-2695/kBuild/tools/TARGZ.kmk0000644000000000000000000000251212247157310015400 0ustar rootroot# $Id: TARGZ.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild Tool Config - tar.gz unpacker. # # # Copyright (c) 2006-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_TARGZ := tar.gz unpacker. TOOL_TARGZ_EXTENDS = TAR TOOL_TARGZ_UNPACKFLAGS ?= -z kbuild-2695/kBuild/tools/VCC80AMD64.kmk0000644000000000000000000003445612247157310016004 0ustar rootroot# $Id: VCC80AMD64.kmk 2557 2011-12-13 12:48:32Z bird $ ## @file # kBuild Tool Config - Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting AMD64. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VCC80AMD64 := Visual C++ 8.0 (aka Visual .NET 2005, or MSC v14), targeting AMD64. # Tool Specific Properties ifndef PATH_TOOL_VCC80AMD64 PATH_TOOL_VCC80AMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*) ifeq ($(PATH_TOOL_VCC80AMD64),) PATH_TOOL_VCC80AMD64 := $(PATH_TOOL_VCC80) endif ifeq ($(PATH_TOOL_VCC80AMD64),) PATH_TOOL_VCC80AMD64 := $(PATH_TOOL_VCC80X86) endif ifeq ($(PATH_TOOL_VCC80AMD64),) PATH_TOOL_VCC80AMD64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v8*) endif ifneq ($(PATH_TOOL_VCC80AMD64),) PATH_TOOL_VCC80AMD64 := $(lastword $(sort $(PATH_TOOL_VCC80AMD64))) else $(warning kBuild: PATH_TOOL_VCC80AMD64 cannot be determined!) PATH_TOOL_VCC80AMD64 := $(PATH_DEVTOOLS)/win.x86/vcc/v8 endif else # Resolve any fancy stuff once and for all. PATH_TOOL_VCC80AMD64 := $(PATH_TOOL_VCC80AMD64) endif ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),win.amd64) PATH_TOOL_VCC80AMD64_BIN ?= $(PATH_TOOL_VCC80AMD64)/bin/amd64 else PATH_TOOL_VCC80AMD64_BIN ?= $(PATH_TOOL_VCC80AMD64)/bin/x86_amd64 endif PATH_TOOL_VCC80AMD64_LIB ?= $(PATH_TOOL_VCC80AMD64)/lib/amd64 PATH_TOOL_VCC80AMD64_INC ?= $(PATH_TOOL_VCC80AMD64)/include PATH_TOOL_VCC80AMD64_ATLMFC ?= $(PATH_TOOL_VCC80AMD64)/atlmfc PATH_TOOL_VCC80AMD64_ATLMFC_INC ?= $(PATH_TOOL_VCC80AMD64_ATLMFC)/include PATH_TOOL_VCC80AMD64_ATLMFC_LIB ?= $(PATH_TOOL_VCC80AMD64_ATLMFC)/lib/amd64 TOOL_VCC80AMD64_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/cl.exe TOOL_VCC80AMD64_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/cl.exe TOOL_VCC80AMD64_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/ml64.exe TOOL_VCC80AMD64_RC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/../rc.exe TOOL_VCC80AMD64_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/lib.exe TOOL_VCC80AMD64_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/link.exe TOOL_VCC80AMD64_MT ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC80AMD64_BIN)/../mt.exe ## Disabled fast DEP_IDB based dependencies. #VCC80AMD64_OLD_DEPS = 1 ## Constructs the correct .pdb name (the name is lowercased). # @param $(1) Base name, no extention. # @param $(2) The extension. TOOL_VCC80AMD64_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) TOOL_VCC80AMD64_COBJSUFF ?= .obj TOOL_VCC80AMD64_CFLAGS ?= -TC -c -nologo TOOL_VCC80AMD64_CFLAGS.debug ?= -Od -Zi TOOL_VCC80AMD64_CFLAGS.release ?= -O2 TOOL_VCC80AMD64_CFLAGS.profile ?= -O2 TOOL_VCC80AMD64_CINCS ?= $(PATH_TOOL_VCC80AMD64_INC) TOOL_VCC80AMD64_CDEFS ?= TOOL_VCC80AMD64_CXXOBJSUFF ?= .obj TOOL_VCC80AMD64_CXXFLAGS ?= -TP -c -nologo TOOL_VCC80AMD64_CXXFLAGS.debug ?= -Od -Zi TOOL_VCC80AMD64_CXXFLAGS.release ?= -O2 TOOL_VCC80AMD64_CXXFLAGS.profile ?= -O2 TOOL_VCC80AMD64_CXXINCS ?= $(PATH_TOOL_VCC80AMD64_INC) $(PATH_TOOL_VCC80AMD64_ATLMFC_INC) TOOL_VCC80AMD64_CXXDEFS ?= TOOL_VCC80AMD64_ASOBJSUFF ?= .obj TOOL_VCC80AMD64_RCOBJSUFF ?= .res TOOL_VCC80AMD64_RCINCS ?= $(PATH_TOOL_VCC80AMD64_INC) $(PATH_TOOL_VCC80AMD64_ATLMFC_INC) TOOL_VCC80AMD64_ARFLAGS ?= -nologo -machine:amd64 TOOL_VCC80AMD64_ARLIBSUFF ?= .lib TOOL_VCC80AMD64_LDFLAGS ?= -nologo -machine:amd64 TOOL_VCC80AMD64_LDFLAGS.debug ?= -debug TOOL_VCC80AMD64_LDFLAGS.release ?= ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80AMD64_COMPILE_C_DEPEND = TOOL_VCC80AMD64_COMPILE_C_DEPORD = TOOL_VCC80AMD64_COMPILE_C_OUTPUT = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,idb) TOOL_VCC80AMD64_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,pdb) define TOOL_VCC80AMD64_COMPILE_C_CMDS $(QUIET)$(TOOL_VCC80AMD64_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC80AMD64_PDB,$(outbase)-obj,idb) endef ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80AMD64_COMPILE_CXX_DEPEND = TOOL_VCC80AMD64_COMPILE_CXX_DEPORD = TOOL_VCC80AMD64_COMPILE_CXX_OUTPUT = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,idb) TOOL_VCC80AMD64_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC80AMD64_PDB, $(outbase)-obj,pdb) define TOOL_VCC80AMD64_COMPILE_CXX_CMDS $(QUIET)$(TOOL_VCC80AMD64_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC80AMD64_PDB,$(outbase)-obj,idb) endef ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC80AMD64_COMPILE_RC_DEPEND = TOOL_VCC80AMD64_COMPILE_RC_DEPORD = TOOL_VCC80AMD64_COMPILE_RC_OUTPUT = define TOOL_VCC80AMD64_COMPILE_RC_CMDS $(QUIET)$(TOOL_VCC80AMD64_RC) \ $(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\ /fo$(obj)\ $(subst /,\\,$(abspath $(source))) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC80AMD64_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VCC80AMD64_LINK_LIBRARY_DEPORD = TOOL_VCC80AMD64_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_VCC80AMD64_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb define TOOL_VCC80AMD64_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs) \ $(filter-out %.def,$(othersrc))) \ $(addprefix /DEF:,$(filter %.def,$(othersrc))) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80AMD64_AR) $(flags) /OUT:$(out) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC80AMD64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80AMD64_LINK_PROGRAM_DEPORD = TOOL_VCC80AMD64_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC80AMD64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC80AMD64_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80AMD64_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80AMD64_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80AMD64_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80AMD64_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out)) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC80AMD64_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80AMD64_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) TOOL_VCC80AMD64_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp TOOL_VCC80AMD64_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp TOOL_VCC80AMD64_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80AMD64_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80AMD64_LINK_DLL_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80AMD64_LD) $(flags) \ /OUT:$(out) \ /IMPLIB:$(outbase).lib \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ /DLL \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' $(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/ $(eval _DIRS += $(PATH_STAGE_LIB)) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC80AMD64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC80AMD64_LINK_SYSMOD_DEPORD = TOOL_VCC80AMD64_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC80AMD64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC80AMD64_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC80AMD64_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC80AMD64_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC80AMD64_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC80AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' endef kbuild-2695/kBuild/tools/OPENWATCOM.kmk0000644000000000000000000003075112247157310016173 0ustar rootroot# $Id: OPENWATCOM.kmk 2663 2012-10-15 13:13:45Z bird $ ## @file # kBuild Tool Config - Open Watcom v1.4 and later. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_OPENWATCOM = Open Watcom v1.4 and later (generic) ifeq ($(PATH_TOOL_OPENWATCOM),) ifeq ($(PATH_TOOL_OPENWATCOM),) PATH_TOOL_OPENWATCOM := $(wildcard $(PATH_DEVTOOLS_BLD)/openwatcom/v*) endif ifeq ($(PATH_TOOL_OPENWATCOM),) PATH_TOOL_OPENWATCOM := $(wildcard $(PATH_DEVTOOLS_TRG)/openwatcom/v*) endif ifeq ($(PATH_TOOL_OPENWATCOM),) PATH_TOOL_OPENWATCOM := $(wildcard $(PATH_DEVTOOLS)/common/openwatcom/v*) endif ifeq ($(PATH_TOOL_OPENWATCOM)$(KBUILD_HOST),os2) if1of ($(USER) $(USERNAME) $(LOGNAME), bird) PATH_TOOL_OPENWATCOM := $(wildcard d:/dev/Watcom/v1.*) endif endif PATH_TOOL_OPENWATCOM := $(firstword $(sort $(PATH_TOOL_OPENWATCOM))) # if not found, we'll enter 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_OPENWATCOM := $(PATH_TOOL_OPENWATCOM) endif ifneq ($(PATH_TOOL_OPENWATCOM),) TOOL_OPENWATCOM_PATHLESS := no ifeq ($(KBUILD_HOST),darwin) PATH_TOOL_OPENWATCOM_BIN = $(PATH_TOOL_OPENWATCOM)/binosx TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \ -E 'PATH=$(PATH_TOOL_OPENWATCOM_BIN):$(PATH_TOOL_OPENWATCOM)/binl:$(PATH_TOOL_OPENWATCOM)/binw:$(PATH)' \ -E 'WATCOM=$(PATH_TOOL_OPENWATCOM)' \ -E 'EDPATH=$(PATH_TOOL_OPENWATCOM)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- else ifeq ($(KBUILD_HOST),freebsd) PATH_TOOL_OPENWATCOM_BIN = $(PATH_TOOL_OPENWATCOM)/binfbsd TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \ -E 'PATH=$(PATH_TOOL_OPENWATCOM_BIN):$(PATH_TOOL_OPENWATCOM)/binl:$(PATH_TOOL_OPENWATCOM)/binw:$(PATH)' \ -E 'WATCOM=$(PATH_TOOL_OPENWATCOM)' \ -E 'EDPATH=$(PATH_TOOL_OPENWATCOM)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- else ifeq ($(KBUILD_HOST),linux) PATH_TOOL_OPENWATCOM_BIN = $(PATH_TOOL_OPENWATCOM)/binl TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \ -E 'PATH=$(PATH_TOOL_OPENWATCOM_BIN):$(PATH_TOOL_OPENWATCOM)/binw:$(PATH)' \ -E 'WATCOM=$(PATH_TOOL_OPENWATCOM)' \ -E 'EDPATH=$(PATH_TOOL_OPENWATCOM)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- else ifeq ($(KBUILD_HOST),os2) PATH_TOOL_OPENWATCOM_BIN = $(PATH_TOOL_OPENWATCOM)/binp TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \ -E 'BEGINLIBPATH=$(PATH_TOOL_OPENWATCOM)/binp/dll;$(BEGINLIBPATH)' \ -E 'LIBPATHSTRICT=T' \ -E 'PATH=$(PATH_TOOL_OPENWATCOM_BIN);$(PATH_TOOL_OPENWATCOM)/binw;$(PATH)' \ -E 'WATCOM=$(PATH_TOOL_OPENWATCOM)' \ -E 'EDPATH=$(PATH_TOOL_OPENWATCOM)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- else ifeq ($(KBUILD_HOST),solaris) PATH_TOOL_OPENWATCOM_BIN = $(PATH_TOOL_OPENWATCOM)/binsol TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \ -E 'PATH=$(PATH_TOOL_OPENWATCOM_BIN):$(PATH_TOOL_OPENWATCOM)/binl:$(PATH_TOOL_OPENWATCOM)/binw:$(PATH)' \ -E 'WATCOM=$(PATH_TOOL_OPENWATCOM)' \ -E 'EDPATH=$(PATH_TOOL_OPENWATCOM)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- else PATH_TOOL_OPENWATCOM_BIN = $(PATH_TOOL_OPENWATCOM)/binnt TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \ -E 'PATH=$(PATH_TOOL_OPENWATCOM_BIN);$(PATH_TOOL_OPENWATCOM)/binw;$(PATH)' \ -E 'WATCOM=$(PATH_TOOL_OPENWATCOM)' \ -E 'EDPATH=$(PATH_TOOL_OPENWATCOM)/EDDAT' \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- endif TOOL_OPENWATCOM_CC ?= $(PATH_TOOL_OPENWATCOM_BIN)/wcc386$(HOSTSUFF_EXE) TOOL_OPENWATCOM_CC16 ?= $(PATH_TOOL_OPENWATCOM_BIN)/wcc$(HOSTSUFF_EXE) TOOL_OPENWATCOM_CXX ?= $(PATH_TOOL_OPENWATCOM_BIN)/wpp386$(HOSTSUFF_EXE) TOOL_OPENWATCOM_CXX16 ?= $(PATH_TOOL_OPENWATCOM_BIN)/wpp$(HOSTSUFF_EXE) TOOL_OPENWATCOM_AS ?= $(PATH_TOOL_OPENWATCOM_BIN)/wasm$(HOSTSUFF_EXE) TOOL_OPENWATCOM_AR ?= $(PATH_TOOL_OPENWATCOM_BIN)/wlib$(HOSTSUFF_EXE) TOOL_OPENWATCOM_RC ?= $(PATH_TOOL_OPENWATCOM_BIN)/wrc$(HOSTSUFF_EXE) TOOL_OPENWATCOM_LD ?= $(PATH_TOOL_OPENWATCOM_BIN)/wcl386$(HOSTSUFF_EXE) TOOL_OPENWATCOM_LD16 ?= $(PATH_TOOL_OPENWATCOM_BIN)/wcl$(HOSTSUFF_EXE) TOOL_OPENWATCOM_WLINK ?= $(PATH_TOOL_OPENWATCOM_BIN)/wlink$(HOSTSUFF_EXE) else # Pathless, relies on the environment. TOOL_OPENWATCOM_PATHLESS := TOOL_OPENWATCOM_ENV_SETUP ?= $(REDIRECT) \ -E 'LIB=$1' \ -E 'INCLUDE=' \ -- TOOL_OPENWATCOM_CC ?= wcc386$(HOSTSUFF_EXE) TOOL_OPENWATCOM_CC16 ?= wcc$(HOSTSUFF_EXE) TOOL_OPENWATCOM_CXX ?= wpp386$(HOSTSUFF_EXE) TOOL_OPENWATCOM_CXX16 ?= wpp$(HOSTSUFF_EXE) TOOL_OPENWATCOM_AS ?= wasm$(HOSTSUFF_EXE) TOOL_OPENWATCOM_AR ?= wlib$(HOSTSUFF_EXE) TOOL_OPENWATCOM_RC ?= wrc$(HOSTSUFF_EXE) TOOL_OPENWATCOM_LD ?= wcl386$(HOSTSUFF_EXE) TOOL_OPENWATCOM_LD16 ?= wcl$(HOSTSUFF_EXE) TOOL_OPENWATCOM_WLINK ?= wlink$(HOSTSUFF_EXE) endif # Functions for changing slashes (SQ = single quoted). if1of ($(KBUILD_HOST), os2 win) TOOL_OPENWATCOM_FIX_SLASHES = $(subst /,\\,$1) TOOL_OPENWATCOM_FIX_SLASHES_SQ = $(subst /,\,$1) else TOOL_OPENWATCOM_FIX_SLASHES = $1 TOOL_OPENWATCOM_FIX_SLASHES_SQ = $1 endif # General Properties used by kBuild TOOL_OPENWATCOM_ASOBJSUFF ?= .obj TOOL_OPENWATCOM_ASFLAGS ?= -zq TOOL_OPENWATCOM_ASFLAGS.dos ?= -bt=dos TOOL_OPENWATCOM_ASFLAGS.os2 ?= -bt=os2 TOOL_OPENWATCOM_ASFLAGS.win ?= -bt=nt TOOL_OPENWATCOM_COBJSUFF ?= .obj TOOL_OPENWATCOM_CFLAGS ?= -zq TOOL_OPENWATCOM_CFLAGS.dos ?= -bt=dos TOOL_OPENWATCOM_CFLAGS.os2 ?= -bt=os2 TOOL_OPENWATCOM_CFLAGS.win ?= -bt=nt ifdef PATH_TOOL_OPENWATCOM TOOL_OPENWATCOM_CINCS ?= $(PATH_TOOL_OPENWATCOM)/h endif TOOL_OPENWATCOM_CXXOBJSUFF ?= .obj TOOL_OPENWATCOM_CXXFLAGS ?= -zq TOOL_OPENWATCOM_CXXFLAGS.dos ?= -bt=dos TOOL_OPENWATCOM_CXXFLAGS.os2 ?= -bt=os2 TOOL_OPENWATCOM_CXXFLAGS.win ?= -bt=nt ifdef PATH_TOOL_OPENWATCOM TOOL_OPENWATCOM_CXXINCS ?= $(PATH_TOOL_OPENWATCOM)/h endif TOOL_OPENWATCOM_RCOBJSUFF ?= .res TOOL_OPENWATCOM_RCFLAGS ?= -r TOOL_OPENWATCOM_RCFLAGS.os2 ?= -bt=os2 TOOL_OPENWATCOM_RCFLAGS.win ?= -bt=nt ifdef PATH_TOOL_OPENWATCOM TOOL_OPENWATCOM_RCINCS ?= $(PATH_TOOL_OPENWATCOM)/h endif TOOL_OPENWATCOM_ARFLAGS ?= -q TOOL_OPENWATCOM_ARLIBSUFF ?= .lib TOOL_OPENWATCOM_LDFLAGS ?= -zq -y TOOL_OPENWATCOM_LDFLAGS.dos ?= -bt=dos TOOL_OPENWATCOM_LDFLAGS.os2 ?= -bt=os2 TOOL_OPENWATCOM_LDFLAGS.win ?= -bt=nt TOOL_OPENWATCOM_COMPILE_AS_DEPEND = TOOL_OPENWATCOM_COMPILE_AS_DEPORD = TOOL_OPENWATCOM_COMPILE_AS_OUTPUT = $(obj).err define TOOL_OPENWATCOM_COMPILE_AS_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_AS) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ -fr=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)).err \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_OPENWATCOM_COMPILE_C_DEPEND = TOOL_OPENWATCOM_COMPILE_C_DEPORD = TOOL_OPENWATCOM_COMPILE_C_OUTPUT = $(obj).err define TOOL_OPENWATCOM_COMPILE_C_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_CC) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ -fr=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)).err \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_OPENWATCOM_COMPILE_CXX_DEPEND = TOOL_OPENWATCOM_COMPILE_CXX_DEPORD = TOOL_OPENWATCOM_COMPILE_CXX_OUTPUT = $(obj).err define TOOL_OPENWATCOM_COMPILE_CXX_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_CXX) \ $(flags) \ $(addsuffix , $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs)))) \ $(addprefix -d, $(defs)) \ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ -fr=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)).err \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) $(QUIET)$(APPEND) -n $(obj).err ## @todo dependencies endef TOOL_OPENWATCOM_COMPILE_RC_OUTPUT = TOOL_OPENWATCOM_COMPILE_RC_DEPEND = TOOL_OPENWATCOM_COMPILE_RC_DEPORD = define TOOL_OPENWATCOM_COMPILE_RC_CMDS $(QUIET) $(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) -r\ $(flags) \ $(addprefix -i=, $(call TOOL_OPENWATCOM_FIX_SLASHES,$(incs))) \ $(addprefix -d, $(defs))\ -fo=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(obj)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(abspath $(source))) endef TOOL_OPENWATCOM_LINK_LIBRARY_OUTPUT = ## @todo $(outbase).rsp TOOL_OPENWATCOM_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_OPENWATCOM_LINK_LIBRARY_DEPORD = define TOOL_OPENWATCOM_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp $(foreach obj,$(call TOOL_OPENWATCOM_FIX_SLASHES,$(objs) $(othersrc)),'+"$(obj)"') $(QUIET)$(TOOL_OPENWATCOM_ENV_SETUP) $(TOOL_OPENWATCOM_AR) $(flags) $(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) @$(outbase).rsp endef TOOL_OPENWATCOM_LINK_PROGRAM_OUTPUT = $(outbase).map TOOL_OPENWATCOM_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_OPENWATCOM_LINK_PROGRAM_DEPORD = define TOOL_OPENWATCOM_LINK_PROGRAM_CMDS $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_OPENWATCOM_LD) \ $(flags) \ -fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ -fm=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(outbase).map) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter-out %.res,$(objs))) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(libs)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter %.res,$(objs)))) endef TOOL_OPENWATCOM_LINK_DLL_OUTPUT = $(outbase).map TOOL_OPENWATCOM_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_OPENWATCOM_LINK_DLL_DEPORD = define TOOL_OPENWATCOM_LINK_DLL_CMDS $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_OPENWATCOM_LD) \ $(flags) \ -fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ -fm=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(outbase).map) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter-out %.res,$(objs))) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(libs)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter %.res,$(objs)))) endef TOOL_OPENWATCOM_LINK_SYSMOD_OUTPUT = $(outbase).map TOOL_OPENWATCOM_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_OPENWATCOM_LINK_SYSMOD_DEPORD = define TOOL_OPENWATCOM_LINK_SYSMOD_CMDS $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP,$(subst $(SP),,$(addsuffix ;,$(libpath)))) \ $(TOOL_OPENWATCOM_LD) \ $(flags) \ -fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ -fm=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(outbase).map) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter-out %.res,$(objs))) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(libs)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(othersrc)) $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_RC) \ $(filter -bt=%,$(flags)) \ /fe=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)) \ $(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter %.res,$(objs)))) endef kbuild-2695/kBuild/tools/VCC100.kmk0000644000000000000000000004260212247157310015351 0ustar rootroot# $Id: VCC100.kmk 2677 2013-02-01 15:04:53Z bird $ ## @file # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting $(KBUILD_TARGET). # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_VCC100 := Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting $(KBUILD_TARGET). # Tool Specific Properties ifndef PATH_TOOL_VCC100 PATH_TOOL_VCC100 := $(wildcard $(PATH_DEVTOOLS_TRG)/vcc/v10*) ifeq ($(PATH_TOOL_VCC100),) PATH_TOOL_VCC100 := $(wildcard $(PATH_DEVTOOLS)/win.x86/vcc/v10*) endif ifeq ($(PATH_TOOL_VCC100),) PATH_TOOL_VCC100 := $(wildcard $(PATH_DEVTOOLS)/x86.win32/vcc/v10*) endif ifeq ($(PATH_TOOL_VCC100),) PATH_TOOL_VCC100 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/vcc/v10*) endif ifeq ($(PATH_TOOL_VCC100),) PATH_TOOL_VCC100 := $(lastword $(sort $(PATH_TOOL_VCC100))) endif # if not found, we'll enter 'pathless' mode. else # Resolve any fancy stuff once and for all. PATH_TOOL_VCC100 := $(PATH_TOOL_VCC100) endif ifneq ($(PATH_TOOL_VCC100),) ifeq ($(KBUILD_HOST).$(KBUILD_HOST_ARCH),win.amd64) PATH_TOOL_VCC100_BIN.amd64 ?= $(PATH_TOOL_VCC100)/bin/amd64 else PATH_TOOL_VCC100_BIN.amd64 ?= $(PATH_TOOL_VCC100)/bin/x86_amd64 endif PATH_TOOL_VCC100_BIN.x86 ?= $(PATH_TOOL_VCC100)/bin PATH_TOOL_VCC100_BIN ?= $(PATH_TOOL_VCC100_BIN.$(KBUILD_TARGET_ARCH)) PATH_TOOL_VCC100_LIB.amd64 ?= $(PATH_TOOL_VCC100)/lib/amd64 PATH_TOOL_VCC100_LIB.x86 ?= $(PATH_TOOL_VCC100)/lib PATH_TOOL_VCC100_LIB ?= $(PATH_TOOL_VCC100_LIB.$(KBUILD_TARGET_ARCH)) PATH_TOOL_VCC100_INC ?= $(PATH_TOOL_VCC100)/include PATH_TOOL_VCC100_ATLMFC ?= $(PATH_TOOL_VCC100X86)/atlmfc PATH_TOOL_VCC100_ATLMFC_INC ?= $(PATH_TOOL_VCC100_ATLMFC)/include PATH_TOOL_VCC100_ATLMFC_LIB.amd64 ?= $(PATH_TOOL_VCC100_ATLMFC)/lib PATH_TOOL_VCC100_ATLMFC_LIB.x86 ?= $(PATH_TOOL_VCC100_ATLMFC)/lib/amd64 PATH_TOOL_VCC100_ATLMFC_LIB ?= $(PATH_TOOL_VCC100_ATLMFC_LIB.$(KBUILD_TARGET_ARCH)) TOOL_VCC100_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/cl.exe TOOL_VCC100_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/cl.exe TOOL_VCC100_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/ml64.exe TOOL_VCC100_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/lib.exe TOOL_VCC100_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/link.exe TOOL_VCC100_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/dumpbin.exe TOOL_VCC100_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/editbin.exe else # Pathless, relies on the environment. TOOL_VCC100_CC ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC100_CXX ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC100_AS ?= $(EXEC_X86_WIN32) ml64.exe TOOL_VCC100_AR ?= $(EXEC_X86_WIN32) lib.exe TOOL_VCC100_LD ?= $(EXEC_X86_WIN32) link.exe TOOL_VCC100_DUMPBIN ?= $(EXEC_X86_WIN32) dumpbin.exe TOOL_VCC100_EDITBIN ?= $(EXEC_X86_WIN32) editbin.exe endif TOOL_VCC100_RC ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED) TOOL_VCC100_MT ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED) # The following in duplicated in VCC100.kmk and VCC100X86.kmk. TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword \ $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \ $(if-expr defined(PATH_SDK_WINPSDK_BIN) , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \ $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \ $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \ $1)) TOOL_VCC100_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC100_FN_FIND_SDK_TOOL_SUB),)$($3) ## Disabled fast DEP_IDB based dependencies. #VCC100_OLD_DEPS = 1 ## Constructs the correct .pdb name (the name is lowercased). # @param $(1) Base name, no extention. # @param $(2) The extension. TOOL_VCC100_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) TOOL_VCC100_COBJSUFF ?= .obj TOOL_VCC100_CFLAGS ?= -TC -nologo TOOL_VCC100_CFLAGS.debug ?= -Zi TOOL_VCC100_CFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100_CFLAGS.release ?= -O2 TOOL_VCC100_CFLAGS.profile ?= -O2 TOOL_VCC100_CINCS ?= $(PATH_TOOL_VCC100_INC) TOOL_VCC100_CDEFS ?= TOOL_VCC100_CXXOBJSUFF ?= .obj TOOL_VCC100_CXXFLAGS ?= -TP -nologo TOOL_VCC100_CXXFLAGS.debug ?= -Zi TOOL_VCC100_CXXFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100_CXXFLAGS.release ?= -O2 TOOL_VCC100_CXXFLAGS.profile ?= -O2 TOOL_VCC100_CXXINCS ?= $(PATH_TOOL_VCC100_INC) $(PATH_TOOL_VCC100_ATLMFC_INC) TOOL_VCC100_CXXDEFS ?= TOOL_VCC100_ASOBJSUFF ?= .obj TOOL_VCC100_RCOBJSUFF ?= .res TOOL_VCC100_RCINCS ?= $(PATH_TOOL_VCC100_INC) $(PATH_TOOL_VCC100_ATLMFC_INC) TOOL_VCC100_ARFLAGS.amd64 ?= -machine:amd64 TOOL_VCC100_ARFLAGS.x86 ?= -machine:x86 TOOL_VCC100_ARFLAGS ?= -nologo TOOL_VCC100_ARLIBSUFF ?= .lib TOOL_VCC100_LDFLAGS.amd64 ?= -machine:amd64 TOOL_VCC100_LDFLAGS.x86 ?= -machine:x86 TOOL_VCC100_LDFLAGS ?= -nologo TOOL_VCC100_LDFLAGS.debug ?= -debug TOOL_VCC100_LDFLAGS.dbgopt ?= -debug TOOL_VCC100_LDFLAGS.profile ?= -debug TOOL_VCC100_LDFLAGS.release ?= TOOL_VCC100_LIBPATH.amd64 ?= $(PATH_TOOL_VCC100_LIB.amd64) $(PATH_TOOL_VCC100_ATLMFC_LIB.amd64) TOOL_VCC100_LIBPATH.x86 ?= $(PATH_TOOL_VCC100_LIB.x86) $(PATH_TOOL_VCC100_ATLMFC_LIB.x86) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100_COMPILE_C_DEPEND = TOOL_VCC100_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_VCC100_COMPILE_C_USES_KOBJCACHE = 1 TOOL_VCC100_COMPILE_C_OUTPUT = $(outbase).i TOOL_VCC100_COMPILE_C_OUTPUT_MAYBE = define TOOL_VCC100_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ --kObjCache-cpp $(outbase).i\ $(TOOL_VCC100_CC) -E\ $(subst -Zi,-Z7,$(flags))\ $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ --kObjCache-cc $(obj)\ $(TOOL_VCC100_CC) -c\ $(subst -Zi,-Z7,$(flags))\ -Fo$(obj)\ $(outbase).i endef else # !KBUILD_USE_KOBJCACHE TOOL_VCC100_COMPILE_C_OUTPUT = $(call TOOL_VCC100_PDB, $(outbase)-obj,idb) TOOL_VCC100_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100_PDB, $(outbase)-obj,pdb) define TOOL_VCC100_COMPILE_C_CMDS $(QUIET)$(TOOL_VCC100_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100_PDB,$(outbase)-obj,idb) endef endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100_COMPILE_CXX_DEPEND = TOOL_VCC100_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_VCC100_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_VCC100_COMPILE_CXX_OUTPUT = $(outbase).ii TOOL_VCC100_COMPILE_CXX_OUTPUT_MAYBE = define TOOL_VCC100_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ --kObjCache-cpp $(outbase).ii\ $(TOOL_VCC100_CXX) -E\ $(subst -Zi,-Z7,$(flags))\ $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ --kObjCache-cc $(obj)\ $(TOOL_VCC100_CXX) -c\ $(subst -Zi,-Z7,$(flags))\ -Fo$(obj)\ $(outbase).ii endef else # !KBUILD_USE_KOBJCACHE TOOL_VCC100_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100_PDB, $(outbase)-obj,idb) TOOL_VCC100_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100_PDB, $(outbase)-obj,pdb) define TOOL_VCC100_COMPILE_CXX_CMDS $(QUIET)$(TOOL_VCC100_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Fd$(outbase)-obj.pdb \ -FD\ -Fo$(obj)\ $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100_PDB,$(outbase)-obj,idb) endef endif # !KBUILD_USE_KOBJCACHE ## @todo configure the assembler template. ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_VCC100_COMPILE_RC_OUTPUT = TOOL_VCC100_COMPILE_RC_DEPEND = TOOL_VCC100_COMPILE_RC_DEPORD = define TOOL_VCC100_COMPILE_RC_CMDS $(QUIET)$(TOOL_VCC100_RC) \ $(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\ /fo$(obj)\ $(subst /,\\,$(abspath $(source))) endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC100_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_VCC100_LINK_LIBRARY_DEPORD = TOOL_VCC100_LINK_LIBRARY_OUTPUT = $(outbase).rsp TOOL_VCC100_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb define TOOL_VCC100_LINK_LIBRARY_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs) \ $(filter-out %.def,$(othersrc))) \ $(addprefix /DEF:,$(filter %.def,$(othersrc))) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100_AR) $(flags) /OUT:$(out) @$(outbase).rsp endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. # TOOL_VCC100_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100_LINK_PROGRAM_DEPORD = TOOL_VCC100_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC100_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC100_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out)) endef ## Link DLL. # @param $(target) Normalized main target name. # @param $(out) DLL name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC100_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) TOOL_VCC100_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp TOOL_VCC100_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp TOOL_VCC100_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100_LINK_DLL_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100_LD) $(flags) \ /OUT:$(out) \ /IMPLIB:$(outbase).lib \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ /DLL \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' $(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/ $(eval _DIRS += $(PATH_STAGE_LIB)) endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_VCC100_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100_LINK_SYSMOD_DEPORD = TOOL_VCC100_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp TOOL_VCC100_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC100_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(foreach arg,\ $(subst /,\\,$(objs)) \ $(subst /,\\,$(libs)) \ ,\"$(arg)\") $(QUIET)$(TOOL_VCC100_LD) $(flags) \ /OUT:$(out) \ /MAPINFO:EXPORTS /INCREMENTAL:NO \ /MAP:$(outbase).map \ $(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \ $(subst /,\\,$(filter %.exp %.res,$(othersrc))) \ $(foreach p,$(libpath), /LIBPATH:$(p)) \ @$(outbase).rsp $(QUIET)$(TEST) -f $(out).manifest -- \ $(TOOL_VCC100_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2' endef kbuild-2695/kBuild/tools/GCC42MACHO.kmk0000644000000000000000000004566112247157310016037 0ustar rootroot# $Id: GCC42MACHO.kmk 2547 2011-11-04 21:58:53Z bird $ ## @file # kBuild Tool Config - GCC v4.2.x targeting Darwin (Mac OS X) Mach-O. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # As a special exception you are granted permission to include this file, via # the kmk include directive, as you wish without this in itself causing the # resulting makefile, program or whatever to be covered by the GPL license. # This exception does not however invalidate any other reasons why the makefile, # program, whatever should not be covered the GPL. # # TOOL_GCC42MACHO := GCC v4.2.x targeting Darwin (Mac OS X) Mach-O. # Tool Specific Properties TOOL_GCC42MACHO_PREFIX ?= TOOL_GCC42MACHO_SUFFIX ?= -4.2$(HOSTSUFF_EXE) TOOL_GCC42MACHO_CC ?= $(TOOL_GCC42MACHO_PREFIX)gcc$(TOOL_GCC42MACHO_SUFFIX) TOOL_GCC42MACHO_CXX ?= $(TOOL_GCC42MACHO_PREFIX)g++$(TOOL_GCC42MACHO_SUFFIX) TOOL_GCC42MACHO_OBJC ?= $(TOOL_GCC42MACHO_PREFIX)gcc$(TOOL_GCC42MACHO_SUFFIX) TOOL_GCC42MACHO_OBJCXX ?= $(TOOL_GCC42MACHO_PREFIX)gcc$(TOOL_GCC42MACHO_SUFFIX) TOOL_GCC42MACHO_AS ?= $(TOOL_GCC42MACHO_PREFIX)gcc$(TOOL_GCC42MACHO_SUFFIX) TOOL_GCC42MACHO_LD ?= $(TOOL_GCC42MACHO_PREFIX)gcc$(TOOL_GCC42MACHO_SUFFIX) TOOL_GCC42MACHO_LD_SYSMOD ?= $(TOOL_GCC42MACHO_PREFIX)gcc$(TOOL_GCC42MACHO_SUFFIX) ifndef TOOL_GCC42MACHO_LDFLAGS.$(KBUILD_TARGET) TOOL_GCC42MACHO_LDFLAGS.dll ?= -dynamiclib else TOOL_GCC42MACHO_LDFLAGS.dll ?= $(TOOL_GCC42MACHO_LDFLAGS.$(KBUILD_TARGET)) endif TOOL_GCC42MACHO_LDFLAGS.sysmod ?= -r #TOOL_GCC42MACHO_LD_SONAME = -Wl,-dylib_install_name $(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2))) TOOL_GCC42MACHO_DSYMUTIL ?= dsymutil ifdef SLKRUNS TOOL_GCC42MACHO_CC += -fmessage-length=0 TOOL_GCC42MACHO_CXX += -fmessage-length=0 TOOL_GCC42MACHO_OBJC += -fmessage-length=0 TOOL_GCC42MACHO_OBJCXX += -fmessage-length=0 endif # General Properties used by kBuild TOOL_GCC42MACHO_COBJSUFF ?= .o TOOL_GCC42MACHO_CFLAGS ?= TOOL_GCC42MACHO_CFLAGS.debug ?= -g TOOL_GCC42MACHO_CFLAGS.profile ?= -g -O2 #-pg TOOL_GCC42MACHO_CFLAGS.release ?= -O2 TOOL_GCC42MACHO_CINCS ?= TOOL_GCC42MACHO_CDEFS ?= TOOL_GCC42MACHO_CXXOBJSUFF ?= .o TOOL_GCC42MACHO_CXXFLAGS ?= TOOL_GCC42MACHO_CXXFLAGS.debug ?= -g TOOL_GCC42MACHO_CXXFLAGS.profile ?= -g -O2 #-pg TOOL_GCC42MACHO_CXXFLAGS.release ?= -O2 TOOL_GCC42MACHO_CXXINCS ?= TOOL_GCC42MACHO_CXXDEFS ?= TOOL_GCC42MACHO_OBJCOBJSUFF ?= .o TOOL_GCC42MACHO_OBJCFLAGS ?= TOOL_GCC42MACHO_OBJCFLAGS.debug ?= -g TOOL_GCC42MACHO_OBJCFLAGS.profile?= -O2 #-g -pg TOOL_GCC42MACHO_OBJCFLAGS.release?= -O2 TOOL_GCC42MACHO_OBJCINCS ?= TOOL_GCC42MACHO_OBJCDEFS ?= TOOL_GCC42MACHO_OBJCXXOBJSUFF ?= .o TOOL_GCC42MACHO_OBJCXXFLAGS ?= TOOL_GCC42MACHO_OBJCXXFLAGS.debug ?= -g TOOL_GCC42MACHO_OBJCXXFLAGS.profile ?= -O2 #-g -pg TOOL_GCC42MACHO_OBJCXXFLAGS.release ?= -O2 TOOL_GCC42MACHO_OBJCXXINCS ?= TOOL_GCC42MACHO_OBJCXXDEFS ?= TOOL_GCC42MACHO_ASFLAGS ?= -x assembler-with-cpp TOOL_GCC42MACHO_ASFLAGS.debug ?= -g TOOL_GCC42MACHO_ASFLAGS.profile ?= -g TOOL_GCC42MACHO_ASOBJSUFF ?= .o TOOL_GCC42MACHO_AR ?= ar$(HOSTSUFF_EXE) TOOL_GCC42MACHO_ARFLAGS ?= -c -rs TOOL_GCC42MACHO_ARLIBSUFF ?= .a TOOL_GCC42MACHO_LDFLAGS ?= TOOL_GCC42MACHO_LDFLAGS.debug ?= -g TOOL_GCC42MACHO_LDFLAGS.profile ?= -g TOOL_GCC42MACHO_STRIP_PROGRAM ?= strip -SXxru TOOL_GCC42MACHO_STRIP_DLL ?= strip -Sxru TOOL_GCC42MACHO_STRIP_SYSMOD ?= strip -Sru ## # Calculate the files in the debug bundle. # @param 1 The whole output filename. # @param 2 The output filename sans suffix. TOOL_GCC42MACHO_DEBUG_BUNDLE_FN = \ $(1).dSYM/ \ $(1).dSYM/Contents/ \ $(1).dSYM/Contents/Resources/ \ $(1).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1)) ## # Calculate the files in the debug bundle. # @param 1 The whole linker output filename. # @param 2 The linker output filename sans suffix. # @param 3 The desired install name (no dir slash). # @remarks The Info.plist has some reference to the original name, but gdb # does not care and only check for a symbol file in the DWARF # directory with the same name as the debugged module. TOOL_GCC42MACHO_DEBUG_INSTALL_FN= \ $(3).dSYM/ \ $(3).dSYM/Contents/ \ $(3).dSYM/Contents/Resources/ \ $(3).dSYM/Contents/Resources/DWARF/ \ $(1).dSYM/Contents/Info.plist=>$(3).dSYM/Contents/Info.plist \ $(1).dSYM/Contents/Resources/DWARF/$(notdir $(1))=>$(3).dSYM/Contents/Resources/DWARF/$(notdir $(3)) ## Compile C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC42MACHO_COMPILE_C_DEPEND = TOOL_GCC42MACHO_COMPILE_C_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_C_USES_KOBJCACHE = 1 TOOL_GCC42MACHO_COMPILE_C_OUTPUT = $(outbase).i define TOOL_GCC42MACHO_COMPILE_C_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).i\ $(TOOL_GCC42MACHO_CC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC42MACHO_CC) -c\ $(flags) -fpreprocessed -x c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_C_OUTPUT = define TOOL_GCC42MACHO_COMPILE_C_CMDS $(QUIET)$(TOOL_GCC42MACHO_CC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KUSE_OBJCACHE ## Compile C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC42MACHO_COMPILE_CXX_DEPEND = TOOL_GCC42MACHO_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_CXX_USES_KOBJCACHE = 1 TOOL_GCC42MACHO_COMPILE_CXX_OUTPUT = $(outbase).ii define TOOL_GCC42MACHO_COMPILE_CXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC42MACHO_CXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC42MACHO_CXX) -c\ $(flags) -fpreprocessed -x c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_CXX_OUTPUT = define TOOL_GCC42MACHO_COMPILE_CXX_CMDS $(QUIET)$(TOOL_GCC42MACHO_CXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC42MACHO_COMPILE_OBJC_DEPEND = TOOL_GCC42MACHO_COMPILE_OBJC_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_OBJC_USES_KOBJCACHE = 1 TOOL_GCC42MACHO_COMPILE_OBJC_OUTPUT = $(outbase).mi define TOOL_GCC42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).ii\ $(TOOL_GCC42MACHO_OBJC) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC42MACHO_OBJC) -c\ $(flags) -fpreprocessed -x cbjective-c\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_OBJC_OUTPUT = define TOOL_GCC42MACHO_COMPILE_OBJC_CMDS $(QUIET)$(TOOL_GCC42MACHO_OBJC) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Objective-C++ source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. TOOL_GCC42MACHO_COMPILE_OBJCXX_DEPEND = TOOL_GCC42MACHO_COMPILE_OBJCXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_OBJCXX_USES_KOBJCACHE = 1 TOOL_GCC42MACHO_COMPILE_OBJCXX_OUTPUT = $(outbase).mii define TOOL_GCC42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -p\ --kObjCache-cpp $(outbase).mii\ $(TOOL_GCC42MACHO_OBJCXX) -E -o -\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ $(abspath $(source))\ --kObjCache-cc $(obj)\ $(TOOL_GCC42MACHO_OBJCXX) -c\ $(flags) -fpreprocessed -x objective-c++\ -o $(obj)\ - $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef else # !KBUILD_USE_KOBJCACHE TOOL_GCC42MACHO_COMPILE_OBJCXX_OUTPUT = define TOOL_GCC42MACHO_COMPILE_OBJCXX_CMDS $(QUIET)$(TOOL_GCC42MACHO_OBJCXX) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef endif # !KBUILD_USE_KOBJCACHE ## Compile Assembly source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). # @param $(obj) Object file name. This shall be (re)created by the compilation. # @param $(dep) Dependcy file. This shall be (re)created by the compilation. # @param $(flags) Flags. # @param $(defs) Definitions. No -D or something. # @param $(incs) Includes. No -I or something. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(outbase) Output basename (full). Use this for list files and such. # @param $(objsuff) Object suffix. # TOOL_GCC42MACHO_COMPILE_AS_OUTPUT = TOOL_GCC42MACHO_COMPILE_AS_DEPEND = TOOL_GCC42MACHO_COMPILE_AS_DEPORD = define TOOL_GCC42MACHO_COMPILE_AS_CMDS $(QUIET)$(TOOL_GCC42MACHO_AS) -c\ $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ -o $(obj)\ $(abspath $(source)) $(QUIET)$(APPEND) -n "$(dep)" "" "$(source):" "" endef ## Link library # @param $(target) Normalized main target name. # @param $(out) Library name. # @param $(objs) Object files to put in the library. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC42MACHO_LINK_LIBRARY_OUTPUT = TOOL_GCC42MACHO_LINK_LIBRARY_DEPEND = $(othersrc) TOOL_GCC42MACHO_LINK_LIBRARY_DEPORD = define TOOL_GCC42MACHO_LINK_LIBRARY_CMDS $(if $(strip $(objs)),$(call xargs,$(QUIET)$(TOOL_GCC42MACHO_AR) $(flags) $(out),$(objs))) $(foreach lib,$(othersrc)\ ,$(NL)$(TAB)$(call MSG_AR_MERGE,$(target),$(out),$(lib)) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(MKDIR) -p $(dir $(outbase))/ar.tmp.dir/ \ $(NL)$(TAB)$(QUIET)(cd $(dir $(outbase))ar.tmp.dir/ \ && $(TOOL_GCC42MACHO_AR) -x $(abspath $(lib)) \ && $(RM_EXT) -f ./__.SYMDEF* \ && $(TOOL_GCC42MACHO_AR) $(flags) $(out) *) \ $(NL)$(TAB)$(QUIET)$(RM_EXT) -f $(dir $(outbase))/ar.tmp.dir/* \ $(NL)$(TAB)$(QUIET)$(RMDIR) $(dir $(outbase))ar.tmp.dir/) endef ## Link program # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC42MACHO_LINK_PROGRAM_OUTPUT = $(outbase).rsp TOOL_GCC42MACHO_LINK_PROGRAM_OUTPUT_DEBUG = $(call TOOL_GCC42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GCC42MACHO_LINK_PROGRAM_DEBUG_INSTALL_FN = $(TOOL_GCC42MACHO_DEBUG_INSTALL_FN) TOOL_GCC42MACHO_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC42MACHO_LINK_PROGRAM_DEPORD = define TOOL_GCC42MACHO_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GCC42MACHO_LD) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GCC42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GCC42MACHO_STRIP_PROGRAM) $(out) endif endef ## Link DLL # @param $(target) Normalized main target name. # @param $(out) Program name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC42MACHO_LINK_DLL_OUTPUT = $(outbase).rsp TOOL_GCC42MACHO_LINK_DLL_OUTPUT_DEBUG = $(call TOOL_GCC42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GCC42MACHO_LINK_DLL_DEBUG_INSTALL_FN = $(TOOL_GCC42MACHO_DEBUG_INSTALL_FN) TOOL_GCC42MACHO_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC42MACHO_LINK_DLL_DEPORD = define TOOL_GCC42MACHO_LINK_DLL_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GCC42MACHO_LD) $(TOOL_GCC42MACHO_LDFLAGS.dll) $(flags) -o $(out)\ $(call TOOL_GCC42MACHO_LD_SONAME,$(target),$(out))\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GCC42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GCC42MACHO_STRIP_DLL) $(out) endif endef ## Link system module (windows aka driver, linux aka kernel module) # @param $(target) Normalized main target name. # @param $(out) System module name. # @param $(objs) Object files to link together. # @param $(libs) Libraries to search. # @param $(libpath) Library search paths. # @param $(flags) Flags. # @param $(dirdep) Directory creation dependency. # @param $(deps) Other dependencies. # @param $(othersrc) Unhandled sources. # @param $(custom_pre) Custom step invoked before linking. # @param $(custom_post) Custom step invoked after linking. # @param $(outbase) Output basename (full). Use this for list files and such. TOOL_GCC42MACHO_LINK_SYSMOD_OUTPUT = $(outbase).rsp TOOL_GCC42MACHO_LINK_SYSMOD_OUTPUT_DEBUG = $(call TOOL_GCC42MACHO_DEBUG_BUNDLE_FN,$(out)) TOOL_GCC42MACHO_LINK_SYSMOD_DEBUG_INSTALL_FN = $(TOOL_GCC42MACHO_DEBUG_INSTALL_FN) TOOL_GCC42MACHO_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) TOOL_GCC42MACHO_LINK_SYSMOD_DEPORD = define TOOL_GCC42MACHO_LINK_SYSMOD_CMDS $(QUIET)$(APPEND) -n $(outbase).rsp $(objs) $(QUIET)$(TOOL_GCC42MACHO_LD_SYSMOD) $(TOOL_GCC42MACHO_LDFLAGS.sysmod) $(flags) -o $(out)\ -filelist $(outbase).rsp\ $(foreach p,$(libpath), -L$(p))\ $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(lib)), $(lib))) ifeq ($(ld_debug),split) $(QUIET)$(TOOL_GCC42MACHO_DSYMUTIL) -o $(out).dSYM/ $(out) $(QUIET)$(TOOL_GCC42MACHO_STRIP_SYSMOD) $(out) endif endef kbuild-2695/src/0000755000000000000000000000000012247157307012230 5ustar rootrootkbuild-2695/src/kDepPre/0000755000000000000000000000000012247157306013561 5ustar rootrootkbuild-2695/src/kDepPre/Makefile.kmk0000644000000000000000000000231212247157306016000 0ustar rootroot# $Id: Makefile.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # Sub-makefile for kDepPre, the precompiler based dependency generator. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = ../.. include $(KBUILD_PATH)/subheader.kmk PROGRAMS += kDepPre kDepPre_TEMPLATE = BIN kDepPre_LIBS = $(LIB_KDEP) kDepPre_DEFS.linux = HAVE_FGETC_UNLOCKED=1 if1of ($(KBUILD_TARGET), win nt) kDepPre_DEFS += NEED_ISBLANK=1 __WIN32__=1 endif kDepPre_SOURCES = kDepPre.c include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/src/kDepPre/kDepPre.c0000644000000000000000000003375012247157306015267 0ustar rootroot/* $Id: kDepPre.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * kDepPre - Dependency Generator using Precompiler output. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include #ifdef _MSC_VER # include #else # include #endif #include "kDep.h" #ifdef HAVE_FGETC_UNLOCKED # define FGETC(s) getc_unlocked(s) #else # define FGETC(s) fgetc(s) #endif #ifdef NEED_ISBLANK # define isblank(ch) ( (unsigned char)(ch) == ' ' || (unsigned char)(ch) == '\t' ) #endif /** * Parses the output from a preprocessor of a C-style language. * * @returns 0 on success. * @returns 1 or other approriate exit code on failure. * @param pInput Input stream. (probably not seekable) */ static int ParseCPrecompiler(FILE *pInput) { enum { C_DISCOVER = 0, C_SKIP_LINE, C_PARSE_FILENAME, C_EOF } enmMode = C_DISCOVER; PDEP pDep = NULL; int ch = 0; char szBuf[8192]; for (;;) { switch (enmMode) { /* * Start of line, need to look for '#[[:space]]*line "file"' and '# "file"'. */ case C_DISCOVER: /* first find '#' */ while ((ch = FGETC(pInput)) != EOF) if (!isblank(ch)) break; if (ch == '#') { /* skip spaces */ while ((ch = FGETC(pInput)) != EOF) if (!isblank(ch)) break; /* check for "line" */ if (ch == 'l') { if ( (ch = FGETC(pInput)) == 'i' && (ch = FGETC(pInput)) == 'n' && (ch = FGETC(pInput)) == 'e') { ch = FGETC(pInput); if (isblank(ch)) { /* skip spaces */ while ((ch = FGETC(pInput)) != EOF) if (!isblank(ch)) break; } else ch = 'x'; } else ch = 'x'; } /* line number */ if (ch >= '0' && ch <= '9') { /* skip the number following spaces */ while ((ch = FGETC(pInput)) != EOF) if (!isxdigit(ch)) break; if (isblank(ch)) { while ((ch = FGETC(pInput)) != EOF) if (!isblank(ch)) break; /* quoted filename */ if (ch == '"') { enmMode = C_PARSE_FILENAME; break; } } } } enmMode = C_SKIP_LINE; break; /* * Skip past the end of the current line. */ case C_SKIP_LINE: do { if ( ch == '\r' || ch == '\n') break; } while ((ch = FGETC(pInput)) != EOF); enmMode = C_DISCOVER; break; /* * Parse the filename. */ case C_PARSE_FILENAME: { /* retreive and unescape the filename. */ char *psz = &szBuf[0]; while ( (ch = FGETC(pInput)) != EOF && psz < &szBuf[sizeof(szBuf) - 1]) { if (ch == '\\') { ch = FGETC(pInput); switch (ch) { case '\\': ch = '/'; break; case 't': ch = '\t'; break; case 'r': ch = '\r'; break; case 'n': ch = '\n'; break; case 'b': ch = '\b'; break; default: fprintf(stderr, "warning: unknown escape char '%c'\n", ch); continue; } *psz++ = ch == '\\' ? '/' : ch; } else if (ch != '"') *psz++ = ch; else { size_t cchFilename = psz - &szBuf[0]; *psz = '\0'; /* compare with current dep, add & switch on mismatch. */ if ( !pDep || pDep->cchFilename != cchFilename || memcmp(pDep->szFilename, szBuf, cchFilename)) pDep = depAdd(szBuf, cchFilename); break; } } enmMode = C_SKIP_LINE; break; } /* * Handle EOF. */ case C_EOF: if (feof(pInput)) return 0; enmMode = C_DISCOVER; break; } if (ch == EOF) enmMode = C_EOF; } return 0; } static int usage(FILE *pOut, const char *argv0) { fprintf(pOut, "usage: %s [-l=c] -o -t [-f] [-s] < - | | -e >\n" " or: %s --help\n" " or: %s --version\n", argv0, argv0, argv0); return 1; } int main(int argc, char *argv[]) { int i; /* Arguments. */ int iExec = 0; FILE *pOutput = NULL; const char *pszOutput = NULL; FILE *pInput = NULL; const char *pszTarget = NULL; int fStubs = 0; int fFixCase = 0; /* Argument parsing. */ int fInput = 0; /* set when we've found input argument. */ /* * Parse arguments. */ if (argc <= 1) return usage(stderr, argv[0]); for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { const char *psz = &argv[i][1]; if (*psz == '-') { if (!strcmp(psz, "-help")) psz = "h"; else if (!strcmp(psz, "-version")) psz = "V"; } switch (*psz) { /* * Output file. */ case 'o': { pszOutput = &argv[i][2]; if (pOutput) { fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]); return 1; } if (!*pszOutput) { if (++i >= argc) { fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", argv[0]); return 1; } pszOutput = argv[i]; } if (pszOutput[0] == '-' && !pszOutput[1]) pOutput = stdout; else pOutput = fopen(pszOutput, "w"); if (!pOutput) { fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput); return 1; } break; } /* * Language spec. */ case 'l': { const char *psz = &argv[i][2]; if (*psz == '=') psz++; if (!strcmp(psz, "c")) ; else { fprintf(stderr, "%s: error: The '%s' language is not supported.\n", argv[0], psz); return 1; } break; } /* * Target name. */ case 't': { if (pszTarget) { fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]); return 1; } pszTarget = &argv[i][2]; if (!*pszTarget) { if (++i >= argc) { fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", argv[0]); return 1; } pszTarget = argv[i]; } break; } /* * Exec. */ case 'e': { if (++i >= argc) { fprintf(stderr, "%s: syntax error: The '-e' argument is missing the command.\n", argv[0]); return 1; } iExec = i; i = argc - 1; break; } /* * Pipe input. */ case '\0': { pInput = stdin; fInput = 1; break; } /* * Fix case. */ case 'f': { fFixCase = 1; break; } /* * Generate stubs. */ case 's': { fStubs = 1; break; } /* * The obligatory help and version. */ case 'h': usage(stdout, argv[0]); return 0; case 'V': printf("kDepPre - kBuild version %d.%d.%d\n" "Copyright (C) 2005-2008 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH); return 0; /* * Invalid argument. */ default: fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]); return usage(stderr, argv[0]); } } else { pInput = fopen(argv[i], "r"); if (!pInput) { fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]); return 1; } fInput = 1; } /* * End of the line? */ if (fInput) { if (++i < argc) { fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]); return 1; } break; } } /* * Got all we require? */ if (!pInput && iExec <= 0) { fprintf(stderr, "%s: syntax error: No input!\n", argv[0]); return 1; } if (!pOutput) { fprintf(stderr, "%s: syntax error: No output!\n", argv[0]); return 1; } if (!pszTarget) { fprintf(stderr, "%s: syntax error: No target!\n", argv[0]); return 1; } /* * Spawn process? */ if (iExec > 0) { fprintf(stderr, "%s: -e is not yet implemented!\n", argv[0]); return 1; } /* * Do the parsing. */ i = ParseCPrecompiler(pInput); /* * Reap child. */ if (iExec > 0) { /* later */ } /* * Write the dependecy file. */ if (!i) { depOptimize(fFixCase, 0 /* fQuiet */); fprintf(pOutput, "%s:", pszTarget); depPrint(pOutput); if (fStubs) depPrintStubs(pOutput); } /* * Close the output, delete output on failure. */ if (!i && ferror(pOutput)) { i = 1; fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput); } fclose(pOutput); if (i) { if (unlink(pszOutput)) fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput); } return i; } kbuild-2695/src/kash/0000755000000000000000000000000012247157307013156 5ustar rootrootkbuild-2695/src/kash/expand.c0000644000000000000000000010251712247157307014607 0ustar rootroot/* $NetBSD: expand.c,v 1.71 2005/06/01 15:41:19 lukem Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; #else __RCSID("$NetBSD: expand.c,v 1.71 2005/06/01 15:41:19 lukem Exp $"); #endif /* not lint */ #endif #include #include #include #include /* * Routines to expand arguments to commands. We have to deal with * backquotes, shell variables, and file metacharacters. */ #include "shell.h" #include "main.h" #include "nodes.h" #include "eval.h" #include "expand.h" #include "syntax.h" #include "parser.h" #include "jobs.h" #include "options.h" #include "var.h" #include "input.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "mystring.h" #include "show.h" #include "shinstance.h" ///* // * Structure specifying which parts of the string should be searched // * for IFS characters. // */ // //struct ifsregion { // struct ifsregion *next; /* next region in list */ // int begoff; /* offset of start of region */ // int endoff; /* offset of end of region */ // int inquotes; /* search for nul bytes only */ //}; // // //char *expdest; /* output of current string */ //struct nodelist *argbackq; /* list of back quote expressions */ //struct ifsregion ifsfirst; /* first struct in list of ifs regions */ //struct ifsregion *ifslastp; /* last struct in list */ //struct arglist exparg; /* holds expanded arg list */ STATIC void argstr(shinstance *, char *, int); STATIC char *exptilde(shinstance *, char *, int); STATIC void expbackq(shinstance *, union node *, int, int); STATIC int subevalvar(shinstance *, char *, char *, int, int, int, int); STATIC char *evalvar(shinstance *, char *, int); STATIC int varisset(shinstance *, char *, int); STATIC void varvalue(shinstance *, char *, int, int, int); STATIC void recordregion(shinstance *, int, int, int); STATIC void removerecordregions(shinstance *, int); STATIC void ifsbreakup(shinstance *, char *, struct arglist *); STATIC void ifsfree(shinstance *); STATIC void expandmeta(shinstance *, struct strlist *, int); STATIC void expmeta(shinstance *, char *, char *); STATIC void addfname(shinstance *, char *); STATIC struct strlist *expsort(struct strlist *); STATIC struct strlist *msort(struct strlist *, int); STATIC int pmatch(char *, char *, int); STATIC char *cvtnum(shinstance *, int, char *); /* * Expand shell variables and backquotes inside a here document. */ void expandhere(shinstance *psh, union node *arg, int fd) { psh->herefd = fd; expandarg(psh, arg, (struct arglist *)NULL, 0); xwrite(psh, fd, stackblock(psh), psh->expdest - stackblock(psh)); } /* * Perform variable substitution and command substitution on an argument, * placing the resulting list of arguments in arglist. If EXP_FULL is true, * perform splitting and file name expansion. When arglist is NULL, perform * here document expansion. */ void expandarg(shinstance *psh, union node *arg, struct arglist *arglist, int flag) { struct strlist *sp; char *p; psh->argbackq = arg->narg.backquote; STARTSTACKSTR(psh, psh->expdest); psh->ifsfirst.next = NULL; psh->ifslastp = NULL; argstr(psh, arg->narg.text, flag); if (arglist == NULL) { return; /* here document expanded */ } STPUTC(psh, '\0', psh->expdest); p = grabstackstr(psh, psh->expdest); TRACE2((psh, "expandarg: p='%s'\n", p)); psh->exparg.lastp = &psh->exparg.list; /* * TODO - EXP_REDIR */ if (flag & EXP_FULL) { ifsbreakup(psh, p, &psh->exparg); *psh->exparg.lastp = NULL; psh->exparg.lastp = &psh->exparg.list; expandmeta(psh, psh->exparg.list, flag); } else { if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ rmescapes(psh, p); sp = (struct strlist *)stalloc(psh, sizeof (struct strlist)); sp->text = p; *psh->exparg.lastp = sp; psh->exparg.lastp = &sp->next; } ifsfree(psh); *psh->exparg.lastp = NULL; if (psh->exparg.list) { *arglist->lastp = psh->exparg.list; arglist->lastp = psh->exparg.lastp; } } /* * Perform variable and command substitution. * If EXP_FULL is set, output CTLESC characters to allow for further processing. * Otherwise treat $@ like $* since no splitting will be performed. */ STATIC void argstr(shinstance *psh, char *p, int flag) { char c; int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ int firsteq = 1; const char *ifs = NULL; int ifs_split = EXP_IFS_SPLIT; if (flag & EXP_IFS_SPLIT) ifs = ifsset(psh) ? ifsval(psh) : " \t\n"; if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) p = exptilde(psh, p, flag); for (;;) { switch (c = *p++) { case '\0': case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */ return; case CTLQUOTEMARK: /* "$@" syntax adherence hack */ if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=') break; if ((flag & EXP_FULL) != 0) STPUTC(psh, c, psh->expdest); ifs_split = 0; break; case CTLQUOTEEND: ifs_split = EXP_IFS_SPLIT; break; case CTLESC: if (quotes) STPUTC(psh, c, psh->expdest); c = *p++; STPUTC(psh, c, psh->expdest); break; case CTLVAR: p = evalvar(psh, p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split)); break; case CTLBACKQ: case CTLBACKQ|CTLQUOTE: expbackq(psh, psh->argbackq->n, c & CTLQUOTE, flag); psh->argbackq = psh->argbackq->next; break; case CTLENDARI: expari(psh, flag); break; case ':': case '=': /* * sort of a hack - expand tildes in variable * assignments (after the first '=' and after ':'s). */ STPUTC(psh, c, psh->expdest); if (flag & EXP_VARTILDE && *p == '~') { if (c == '=') { if (firsteq) firsteq = 0; else break; } p = exptilde(psh, p, flag); } break; default: STPUTC(psh, c, psh->expdest); if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) { /* We need to get the output split here... */ recordregion(psh, (int)(psh->expdest - stackblock(psh) - 1), (int)(psh->expdest - stackblock(psh)), 0); } break; } } } STATIC char * exptilde(shinstance *psh, char *p, int flag) { char c, *startp = p; const char *home; int quotes = flag & (EXP_FULL | EXP_CASE); while ((c = *p) != '\0') { switch(c) { case CTLESC: return (startp); case CTLQUOTEMARK: return (startp); case ':': if (flag & EXP_VARTILDE) goto done; break; case '/': goto done; } p++; } done: *p = '\0'; if (*(startp+1) == '\0') { if ((home = lookupvar(psh, "HOME")) == NULL) goto lose; } else { if ((home = sh_gethomedir(psh, startp+1)) == NULL) goto lose; } if (*home == '\0') goto lose; *p = c; while ((c = *home++) != '\0') { if (quotes && SQSYNTAX[(int)c] == CCTL) STPUTC(psh, CTLESC, psh->expdest); STPUTC(psh, c, psh->expdest); } return (p); lose: *p = c; return (startp); } STATIC void removerecordregions(shinstance *psh, int endoff) { if (psh->ifslastp == NULL) return; if (psh->ifsfirst.endoff > endoff) { while (psh->ifsfirst.next != NULL) { struct ifsregion *ifsp; INTOFF; ifsp = psh->ifsfirst.next->next; ckfree(psh, psh->ifsfirst.next); psh->ifsfirst.next = ifsp; INTON; } if (psh->ifsfirst.begoff > endoff) psh->ifslastp = NULL; else { psh->ifslastp = &psh->ifsfirst; psh->ifsfirst.endoff = endoff; } return; } psh->ifslastp = &psh->ifsfirst; while (psh->ifslastp->next && psh->ifslastp->next->begoff < endoff) psh->ifslastp=psh->ifslastp->next; while (psh->ifslastp->next != NULL) { struct ifsregion *ifsp; INTOFF; ifsp = psh->ifslastp->next->next; ckfree(psh, psh->ifslastp->next); psh->ifslastp->next = ifsp; INTON; } if (psh->ifslastp->endoff > endoff) psh->ifslastp->endoff = endoff; } /* * Expand arithmetic expression. Backup to start of expression, * evaluate, place result in (backed up) result, adjust string position. */ void expari(shinstance *psh, int flag) { char *p, *start; int result; int begoff; int quotes = flag & (EXP_FULL | EXP_CASE); int quoted; /* ifsfree(); */ /* * This routine is slightly over-complicated for * efficiency. First we make sure there is * enough space for the result, which may be bigger * than the expression if we add exponentation. Next we * scan backwards looking for the start of arithmetic. If the * next previous character is a CTLESC character, then we * have to rescan starting from the beginning since CTLESC * characters have to be processed left to right. */ #if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10 #error "integers with more than 10 digits are not supported" #endif CHECKSTRSPACE(psh, 12 - 2, psh->expdest); USTPUTC(psh, '\0', psh->expdest); start = stackblock(psh); p = psh->expdest - 1; while (*p != CTLARI && p >= start) --p; if (*p != CTLARI) error(psh, "missing CTLARI (shouldn't happen)"); if (p > start && *(p-1) == CTLESC) for (p = start; *p != CTLARI; p++) if (*p == CTLESC) p++; if (p[1] == '"') quoted=1; else quoted=0; begoff = (int)(p - start); removerecordregions(psh, begoff); if (quotes) rmescapes(psh, p+2); result = arith(psh, p+2); fmtstr(p, 12, "%d", result); while (*p++) ; if (quoted == 0) recordregion(psh, begoff, (int)(p - 1 - start), 0); result = (int)(psh->expdest - p + 1); STADJUST(psh, -result, psh->expdest); } /* * Expand stuff in backwards quotes. */ STATIC void expbackq(shinstance *psh, union node *cmd, int quoted, int flag) { struct backcmd in; int i; char buf[128]; char *p; char *dest = psh->expdest; struct ifsregion saveifs, *savelastp; struct nodelist *saveargbackq; char lastc; int startloc = (int)(dest - stackblock(psh)); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int saveherefd; int quotes = flag & (EXP_FULL | EXP_CASE); #ifdef SH_DEAL_WITH_CRLF int pending_cr = 0; #endif INTOFF; saveifs = psh->ifsfirst; savelastp = psh->ifslastp; saveargbackq = psh->argbackq; saveherefd = psh->herefd; psh->herefd = -1; p = grabstackstr(psh, dest); evalbackcmd(psh, cmd, &in); ungrabstackstr(psh, p, dest); psh->ifsfirst = saveifs; psh->ifslastp = savelastp; psh->argbackq = saveargbackq; psh->herefd = saveherefd; p = in.buf; lastc = '\0'; for (;;) { if (--in.nleft < 0) { if (in.fd < 0) break; while ((i = shfile_read(&psh->fdtab, in.fd, buf, sizeof buf)) < 0 && errno == EINTR); TRACE((psh, "expbackq: read returns %d\n", i)); if (i <= 0) break; p = buf; in.nleft = i - 1; } lastc = *p++; #ifdef SH_DEAL_WITH_CRLF if (pending_cr) { pending_cr = 0; if (lastc != '\n') { if (quotes && syntax[(int)'\r'] == CCTL) STPUTC(psh, CTLESC, dest); STPUTC(psh, '\r', dest); } } if (lastc == '\r') pending_cr = '\r'; else #endif if (lastc != '\0') { if (quotes && syntax[(int)lastc] == CCTL) STPUTC(psh, CTLESC, dest); STPUTC(psh, lastc, dest); } } #ifdef SH_DEAL_WITH_CRLF if (pending_cr) { if (quotes && syntax[(int)'\r'] == CCTL) STPUTC(psh, CTLESC, dest); STPUTC(psh, '\r', dest); } #endif /* Eat all trailing newlines */ p = stackblock(psh) + startloc; while (dest > p && dest[-1] == '\n') STUNPUTC(psh, dest); if (in.fd >= 0) shfile_close(&psh->fdtab, in.fd); if (in.buf) ckfree(psh, in.buf); if (in.jp) psh->back_exitstatus = waitforjob(psh, in.jp); if (quoted == 0) recordregion(psh, startloc, (int)(dest - stackblock(psh)), 0); TRACE((psh, "evalbackq: size=%d: \"%.*s\"\n", (dest - stackblock(psh)) - startloc, (dest - stackblock(psh)) - startloc, stackblock(psh) + startloc)); psh->expdest = dest; INTON; } STATIC int subevalvar(shinstance *psh, char *p, char *str, int strloc, int subtype, int startloc, int varflags) { char *startp; char *loc = NULL; char *q; int c = 0; int saveherefd = psh->herefd; struct nodelist *saveargbackq = psh->argbackq; int amount; psh->herefd = -1; argstr(psh, p, 0); STACKSTRNUL(psh, psh->expdest); psh->herefd = saveherefd; psh->argbackq = saveargbackq; startp = stackblock(psh) + startloc; if (str == NULL) str = stackblock(psh) + strloc; switch (subtype) { case VSASSIGN: setvar(psh, str, startp, 0); amount = (int)(startp - psh->expdest); STADJUST(psh, amount, psh->expdest); varflags &= ~VSNUL; if (c != 0) *loc = c; return 1; case VSQUESTION: if (*p != CTLENDVAR) { outfmt(&psh->errout, "%s\n", startp); error(psh, (char *)NULL); } error(psh, "%.*s: parameter %snot set", p - str - 1, str, (varflags & VSNUL) ? "null or " : nullstr); /* NOTREACHED */ case VSTRIMLEFT: for (loc = startp; loc < str; loc++) { c = *loc; *loc = '\0'; if (patmatch(psh, str, startp, varflags & VSQUOTE)) goto recordleft; *loc = c; if ((varflags & VSQUOTE) && *loc == CTLESC) loc++; } return 0; case VSTRIMLEFTMAX: for (loc = str - 1; loc >= startp;) { c = *loc; *loc = '\0'; if (patmatch(psh, str, startp, varflags & VSQUOTE)) goto recordleft; *loc = c; loc--; if ((varflags & VSQUOTE) && loc > startp && *(loc - 1) == CTLESC) { for (q = startp; q < loc; q++) if (*q == CTLESC) q++; if (q > loc) loc--; } } return 0; case VSTRIMRIGHT: for (loc = str - 1; loc >= startp;) { if (patmatch(psh, str, loc, varflags & VSQUOTE)) goto recordright; loc--; if ((varflags & VSQUOTE) && loc > startp && *(loc - 1) == CTLESC) { for (q = startp; q < loc; q++) if (*q == CTLESC) q++; if (q > loc) loc--; } } return 0; case VSTRIMRIGHTMAX: for (loc = startp; loc < str - 1; loc++) { if (patmatch(psh, str, loc, varflags & VSQUOTE)) goto recordright; if ((varflags & VSQUOTE) && *loc == CTLESC) loc++; } return 0; default: sh_abort(psh); } recordleft: *loc = c; amount = (int)(((str - 1) - (loc - startp)) - psh->expdest); STADJUST(psh, amount, psh->expdest); while (loc != str - 1) *startp++ = *loc++; return 1; recordright: amount = (int)(loc - psh->expdest); STADJUST(psh, amount, psh->expdest); STPUTC(psh, '\0', psh->expdest); STADJUST(psh, -1, psh->expdest); return 1; } /* * Expand a variable, and return a pointer to the next character in the * input string. */ STATIC char * evalvar(shinstance *psh, char *p, int flag) { int subtype; int varflags; char *var; char *val; int patloc; int c; int set; int special; int startloc; int varlen; int apply_ifs; int quotes = flag & (EXP_FULL | EXP_CASE); varflags = (unsigned char)*p++; subtype = varflags & VSTYPE; var = p; special = !is_name(*p); p = strchr(p, '=') + 1; again: /* jump here after setting a variable with ${var=text} */ if (special) { set = varisset(psh, var, varflags & VSNUL); val = NULL; } else { val = lookupvar(psh, var); if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { val = NULL; set = 0; } else set = 1; } varlen = 0; startloc = (int)(psh->expdest - stackblock(psh)); if (!set && uflag(psh)) { switch (subtype) { case VSNORMAL: case VSTRIMLEFT: case VSTRIMLEFTMAX: case VSTRIMRIGHT: case VSTRIMRIGHTMAX: case VSLENGTH: error(psh, "%.*s: parameter not set", p - var - 1, var); /* NOTREACHED */ } } if (set && subtype != VSPLUS) { /* insert the value of the variable */ if (special) { varvalue(psh, var, varflags & VSQUOTE, subtype, flag); if (subtype == VSLENGTH) { varlen = (int)(psh->expdest - stackblock(psh) - startloc); STADJUST(psh, -varlen, psh->expdest); } } else { char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX : BASESYNTAX; if (subtype == VSLENGTH) { for (;*val; val++) varlen++; } else { while (*val) { if (quotes && syntax[(int)*val] == CCTL) STPUTC(psh, CTLESC, psh->expdest); STPUTC(psh, *val++, psh->expdest); } } } } apply_ifs = ((varflags & VSQUOTE) == 0 || (*var == '@' && psh->shellparam.nparam != 1)); switch (subtype) { case VSLENGTH: psh->expdest = cvtnum(psh, varlen, psh->expdest); break; case VSNORMAL: break; case VSPLUS: set = !set; /* FALLTHROUGH */ case VSMINUS: if (!set) { argstr(psh, p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0)); /* * ${x-a b c} doesn't get split, but removing the * 'apply_ifs = 0' apparantly breaks ${1+"$@"}.. * ${x-'a b' c} should generate 2 args. */ /* We should have marked stuff already */ apply_ifs = 0; } break; case VSTRIMLEFT: case VSTRIMLEFTMAX: case VSTRIMRIGHT: case VSTRIMRIGHTMAX: if (!set) break; /* * Terminate the string and start recording the pattern * right after it */ STPUTC(psh, '\0', psh->expdest); patloc = (int)(psh->expdest - stackblock(psh)); if (subevalvar(psh, p, NULL, patloc, subtype, startloc, varflags) == 0) { int amount = (int)(psh->expdest - stackblock(psh) - patloc) + 1; STADJUST(psh, -amount, psh->expdest); } /* Remove any recorded regions beyond start of variable */ removerecordregions(psh, startloc); apply_ifs = 1; break; case VSASSIGN: case VSQUESTION: if (set) break; if (subevalvar(psh, p, var, 0, subtype, startloc, varflags)) { varflags &= ~VSNUL; /* * Remove any recorded regions beyond * start of variable */ removerecordregions(psh, startloc); goto again; } apply_ifs = 0; break; default: sh_abort(psh); } if (apply_ifs) recordregion(psh, startloc, (int)(psh->expdest - stackblock(psh)), varflags & VSQUOTE); if (subtype != VSNORMAL) { /* skip to end of alternative */ int nesting = 1; for (;;) { if ((c = *p++) == CTLESC) p++; else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { if (set) psh->argbackq = psh->argbackq->next; } else if (c == CTLVAR) { if ((*p++ & VSTYPE) != VSNORMAL) nesting++; } else if (c == CTLENDVAR) { if (--nesting == 0) break; } } } return p; } /* * Test whether a specialized variable is set. */ STATIC int varisset(shinstance *psh, char *name, int nulok) { if (*name == '!') return psh->backgndpid != -1; else if (*name == '@' || *name == '*') { if (*psh->shellparam.p == NULL) return 0; if (nulok) { char **av; for (av = psh->shellparam.p; *av; av++) if (**av != '\0') return 1; return 0; } } else if (is_digit(*name)) { char *ap; int num = atoi(name); if (num > psh->shellparam.nparam) return 0; if (num == 0) ap = psh->arg0; else ap = psh->shellparam.p[num - 1]; if (nulok && (ap == NULL || *ap == '\0')) return 0; } return 1; } /* * Add the value of a specialized variable to the stack string. */ STATIC void varvalue(shinstance *psh, char *name, int quoted, int subtype, int flag) { int num; char *p; int i; char sep; char **ap; char const *syntax; #define STRTODEST(p) \ do {\ if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \ syntax = quoted? DQSYNTAX : BASESYNTAX; \ while (*p) { \ if (syntax[(int)*p] == CCTL) \ STPUTC(psh, CTLESC, psh->expdest); \ STPUTC(psh, *p++, psh->expdest); \ } \ } else \ while (*p) \ STPUTC(psh, *p++, psh->expdest); \ } while (0) switch (*name) { case '$': num = psh->rootpid; goto numvar; case '?': num = psh->exitstatus; goto numvar; case '#': num = psh->shellparam.nparam; goto numvar; case '!': num = psh->backgndpid; numvar: psh->expdest = cvtnum(psh, num, psh->expdest); break; case '-': for (i = 0; psh->optlist[i].name; i++) { if (psh->optlist[i].val) STPUTC(psh, psh->optlist[i].letter, psh->expdest); } break; case '@': if (flag & EXP_FULL && quoted) { for (ap = psh->shellparam.p ; (p = *ap++) != NULL ; ) { STRTODEST(p); if (*ap) STPUTC(psh, '\0', psh->expdest); } break; } /* fall through */ case '*': if (ifsset(psh) != 0) sep = ifsval(psh)[0]; else sep = ' '; for (ap = psh->shellparam.p ; (p = *ap++) != NULL ; ) { STRTODEST(p); if (*ap && sep) STPUTC(psh, sep, psh->expdest); } break; case '0': p = psh->arg0; STRTODEST(p); break; default: if (is_digit(*name)) { num = atoi(name); if (num > 0 && num <= psh->shellparam.nparam) { p = psh->shellparam.p[num - 1]; STRTODEST(p); } } break; } } /* * Record the fact that we have to scan this region of the * string for IFS characters. */ STATIC void recordregion(shinstance *psh, int start, int end, int inquotes) { struct ifsregion *ifsp; if (psh->ifslastp == NULL) { ifsp = &psh->ifsfirst; } else { if (psh->ifslastp->endoff == start && psh->ifslastp->inquotes == inquotes) { /* extend previous area */ psh->ifslastp->endoff = end; return; } ifsp = (struct ifsregion *)ckmalloc(psh, sizeof (struct ifsregion)); psh->ifslastp->next = ifsp; } psh->ifslastp = ifsp; psh->ifslastp->next = NULL; psh->ifslastp->begoff = start; psh->ifslastp->endoff = end; psh->ifslastp->inquotes = inquotes; } /* * Break the argument string into pieces based upon IFS and add the * strings to the argument list. The regions of the string to be * searched for IFS characters have been stored by recordregion. */ STATIC void ifsbreakup(shinstance *psh, char *string, struct arglist *arglist) { struct ifsregion *ifsp; struct strlist *sp; char *start; char *p; char *q; const char *ifs; const char *ifsspc; int inquotes; start = string; ifsspc = NULL; inquotes = 0; if (psh->ifslastp == NULL) { /* Return entire argument, IFS doesn't apply to any of it */ sp = (struct strlist *)stalloc(psh, sizeof *sp); sp->text = start; *arglist->lastp = sp; arglist->lastp = &sp->next; return; } ifs = ifsset(psh) ? ifsval(psh) : " \t\n"; for (ifsp = &psh->ifsfirst; ifsp != NULL; ifsp = ifsp->next) { p = string + ifsp->begoff; inquotes = ifsp->inquotes; ifsspc = NULL; while (p < string + ifsp->endoff) { q = p; if (*p == CTLESC) p++; if (inquotes) { /* Only NULs (probably from "$@") end args */ if (*p != 0) { p++; continue; } } else { if (!strchr(ifs, *p)) { p++; continue; } ifsspc = strchr(" \t\n", *p); /* Ignore IFS whitespace at start */ if (q == start && ifsspc != NULL) { p++; start = p; continue; } } /* Save this argument... */ *q = '\0'; sp = (struct strlist *)stalloc(psh, sizeof *sp); sp->text = start; *arglist->lastp = sp; arglist->lastp = &sp->next; p++; if (ifsspc != NULL) { /* Ignore further trailing IFS whitespace */ for (; p < string + ifsp->endoff; p++) { q = p; if (*p == CTLESC) p++; if (strchr(ifs, *p) == NULL) { p = q; break; } if (strchr(" \t\n", *p) == NULL) { p++; break; } } } start = p; } } /* * Save anything left as an argument. * Traditionally we have treated 'IFS=':'; set -- x$IFS' as * generating 2 arguments, the second of which is empty. * Some recent clarification of the Posix spec say that it * should only generate one.... */ if (*start /* || (!ifsspc && start > string) */) { sp = (struct strlist *)stalloc(psh, sizeof *sp); sp->text = start; *arglist->lastp = sp; arglist->lastp = &sp->next; } } STATIC void ifsfree(shinstance *psh) { while (psh->ifsfirst.next != NULL) { struct ifsregion *ifsp; INTOFF; ifsp = psh->ifsfirst.next->next; ckfree(psh, psh->ifsfirst.next); psh->ifsfirst.next = ifsp; INTON; } psh->ifslastp = NULL; psh->ifsfirst.next = NULL; } /* * Expand shell metacharacters. At this point, the only control characters * should be escapes. The results are stored in the list psh->exparg. */ //char *expdir; STATIC void expandmeta(shinstance *psh, struct strlist *str, int flag) { char *p; struct strlist **savelastp; struct strlist *sp; char c; /* TODO - EXP_REDIR */ while (str) { if (fflag(psh)) goto nometa; p = str->text; for (;;) { /* fast check for meta chars */ if ((c = *p++) == '\0') goto nometa; if (c == '*' || c == '?' || c == '[' || c == '!') break; } savelastp = psh->exparg.lastp; INTOFF; if (psh->expdir == NULL) { size_t i = strlen(str->text); psh->expdir = ckmalloc(psh, i < 2048 ? 2048 : i); /* XXX */ } expmeta(psh, psh->expdir, str->text); ckfree(psh, psh->expdir); psh->expdir = NULL; INTON; if (psh->exparg.lastp == savelastp) { /* * no matches */ nometa: *psh->exparg.lastp = str; rmescapes(psh, str->text); psh->exparg.lastp = &str->next; } else { *psh->exparg.lastp = NULL; *savelastp = sp = expsort(*savelastp); while (sp->next != NULL) sp = sp->next; psh->exparg.lastp = &sp->next; } str = str->next; } } /* * Do metacharacter (i.e. *, ?, [...]) expansion. */ STATIC void expmeta(shinstance *psh, char *enddir, char *name) { char *p; const char *cp; char *q; char *start; char *endname; int metaflag; struct stat statb; shdir *dirp; shdirent *dp; int atend; int matchdot; metaflag = 0; start = name; for (p = name ; ; p++) { if (*p == '*' || *p == '?') metaflag = 1; else if (*p == '[') { q = p + 1; if (*q == '!') q++; for (;;) { while (*q == CTLQUOTEMARK) q++; if (*q == CTLESC) q++; if (*q == '/' || *q == '\0') break; if (*++q == ']') { metaflag = 1; break; } } } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { metaflag = 1; } else if (*p == '\0') break; else if (*p == CTLQUOTEMARK) continue; else if (*p == CTLESC) p++; if (*p == '/') { if (metaflag) break; start = p + 1; } } if (metaflag == 0) { /* we've reached the end of the file name */ if (enddir != psh->expdir) metaflag++; for (p = name ; ; p++) { if (*p == CTLQUOTEMARK) continue; if (*p == CTLESC) p++; *enddir++ = *p; if (*p == '\0') break; } if (metaflag == 0 || shfile_lstat(&psh->fdtab, psh->expdir, &statb) >= 0) addfname(psh, psh->expdir); TRACE2((psh, "expandarg: return #1 (metaflag=%d)\n", metaflag)); return; } endname = p; if (start != name) { p = name; while (p < start) { while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; *enddir++ = *p++; } } if (enddir == psh->expdir) { cp = "."; } else if (enddir == psh->expdir + 1 && *psh->expdir == '/') { cp = "/"; } else { cp = psh->expdir; enddir[-1] = '\0'; } if ((dirp = shfile_opendir(&psh->fdtab, cp)) == NULL) { TRACE2((psh, "expandarg: return #2 (shfile_opendir(,%s) failed)\n", cp)); return; } if (enddir != psh->expdir) enddir[-1] = '/'; if (*endname == 0) { atend = 1; } else { atend = 0; *endname++ = '\0'; } matchdot = 0; p = start; while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; if (*p == '.') matchdot++; while (! int_pending() && (dp = shfile_readdir(dirp)) != NULL) { if (dp->name[0] == '.' && ! matchdot) continue; if (patmatch(psh, start, dp->name, 0)) { if (atend) { scopy(dp->name, enddir); addfname(psh, psh->expdir); } else { for (p = enddir, cp = dp->name; (*p++ = *cp++) != '\0';) continue; p[-1] = '/'; expmeta(psh, p, endname); } } } shfile_closedir(dirp); if (! atend) endname[-1] = '/'; } /* * Add a file name to the list. */ STATIC void addfname(shinstance *psh, char *name) { char *p; struct strlist *sp; p = stalloc(psh, strlen(name) + 1); scopy(name, p); sp = (struct strlist *)stalloc(psh, sizeof *sp); sp->text = p; *psh->exparg.lastp = sp; psh->exparg.lastp = &sp->next; } /* * Sort the results of file name expansion. It calculates the number of * strings to sort and then calls msort (short for merge sort) to do the * work. */ STATIC struct strlist * expsort(struct strlist *str) { int len; struct strlist *sp; len = 0; for (sp = str ; sp ; sp = sp->next) len++; return msort(str, len); } STATIC struct strlist * msort(struct strlist *list, int len) { struct strlist *p, *q = NULL; struct strlist **lpp; int half; int n; if (len <= 1) return list; half = len >> 1; p = list; for (n = half ; --n >= 0 ; ) { q = p; p = p->next; } q->next = NULL; /* terminate first half of list */ q = msort(list, half); /* sort first half of list */ p = msort(p, len - half); /* sort second half */ lpp = &list; for (;;) { if (strcmp(p->text, q->text) < 0) { *lpp = p; lpp = &p->next; if ((p = *lpp) == NULL) { *lpp = q; break; } } else { *lpp = q; lpp = &q->next; if ((q = *lpp) == NULL) { *lpp = p; break; } } } return list; } /* * Returns true if the pattern matches the string. */ int patmatch(shinstance *psh, char *pattern, char *string, int squoted) { #ifdef notdef if (pattern[0] == '!' && pattern[1] == '!') return 1 - pmatch(pattern + 2, string); else #endif return pmatch(pattern, string, squoted); } STATIC int pmatch(char *pattern, char *string, int squoted) { char *p, *q; char c; p = pattern; q = string; for (;;) { switch (c = *p++) { case '\0': goto breakloop; case CTLESC: if (squoted && *q == CTLESC) q++; if (*q++ != *p++) return 0; break; case CTLQUOTEMARK: continue; case '?': if (squoted && *q == CTLESC) q++; if (*q++ == '\0') return 0; break; case '*': c = *p; while (c == CTLQUOTEMARK || c == '*') c = *++p; if (c != CTLESC && c != CTLQUOTEMARK && c != '?' && c != '*' && c != '[') { while (*q != c) { if (squoted && *q == CTLESC && q[1] == c) break; if (*q == '\0') return 0; if (squoted && *q == CTLESC) q++; q++; } } do { if (pmatch(p, q, squoted)) return 1; if (squoted && *q == CTLESC) q++; } while (*q++ != '\0'); return 0; case '[': { char *endp; int invert, found; char chr; endp = p; if (*endp == '!') endp++; for (;;) { while (*endp == CTLQUOTEMARK) endp++; if (*endp == '\0') goto dft; /* no matching ] */ if (*endp == CTLESC) endp++; if (*++endp == ']') break; } invert = 0; if (*p == '!') { invert++; p++; } found = 0; chr = *q++; if (squoted && chr == CTLESC) chr = *q++; if (chr == '\0') return 0; c = *p++; do { if (c == CTLQUOTEMARK) continue; if (c == CTLESC) c = *p++; if (*p == '-' && p[1] != ']') { p++; while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; if (chr >= c && chr <= *p) found = 1; p++; } else { if (chr == c) found = 1; } } while ((c = *p++) != ']'); if (found == invert) return 0; break; } dft: default: if (squoted && *q == CTLESC) q++; if (*q++ != c) return 0; break; } } breakloop: if (*q != '\0') return 0; return 1; } /* * Remove any CTLESC characters from a string. */ void rmescapes(shinstance *psh, char *str) { char *p, *q; p = str; while (*p != CTLESC && *p != CTLQUOTEMARK) { if (*p++ == '\0') return; } q = p; while (*p) { if (*p == CTLQUOTEMARK) { p++; continue; } if (*p == CTLESC) p++; *q++ = *p++; } *q = '\0'; } /* * See if a pattern matches in a case statement. */ int casematch(shinstance *psh, union node *pattern, char *val) { struct stackmark smark; int result; char *p; setstackmark(psh, &smark); psh->argbackq = pattern->narg.backquote; STARTSTACKSTR(psh, psh->expdest); psh->ifslastp = NULL; argstr(psh, pattern->narg.text, EXP_TILDE | EXP_CASE); STPUTC(psh, '\0', psh->expdest); p = grabstackstr(psh, psh->expdest); result = patmatch(psh, p, val, 0); popstackmark(psh, &smark); return result; } /* * Our own itoa(). */ STATIC char * cvtnum(shinstance *psh, int num, char *buf) { char temp[32]; int neg = num < 0; char *p = temp + 31; temp[31] = '\0'; do { *--p = num % 10 + '0'; } while ((num /= 10) != 0); if (neg) *--p = '-'; while (*p) STPUTC(psh, *p++, buf); return buf; } /* * Do most of the work for wordexp(3). */ int wordexpcmd(shinstance *psh, int argc, char **argv) { size_t len; int i; out1fmt(psh, "%d", argc - 1); out1c(psh, '\0'); for (i = 1, len = 0; i < argc; i++) len += strlen(argv[i]); out1fmt(psh, "%zd", len); out1c(psh, '\0'); for (i = 1; i < argc; i++) { out1str(psh, argv[i]); out1c(psh, '\0'); } return (0); } kbuild-2695/src/kash/alias.h0000644000000000000000000000411612247157307014422 0ustar rootroot/* $NetBSD: alias.h,v 1.6 2003/08/07 09:05:29 agc Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)alias.h 8.2 (Berkeley) 5/4/95 */ #define ALIASINUSE 1 struct alias { struct alias *next; char *name; char *val; int flag; }; struct alias *lookupalias(struct shinstance *, char *, int); char *get_alias_text(struct shinstance *, char *); int aliascmd(struct shinstance *, int, char **); int unaliascmd(struct shinstance *, int, char **); void rmaliases(struct shinstance *); kbuild-2695/src/kash/cd.c0000644000000000000000000002535412247157307013721 0ustar rootroot/* $NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $"); #endif /* not lint */ #endif #include #include #include #include /* * The cd and pwd commands. */ #include "shell.h" #include "var.h" #include "nodes.h" /* for jobs.h */ #include "jobs.h" #include "options.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "exec.h" #include "redir.h" #include "mystring.h" #include "show.h" #include "cd.h" #include "shinstance.h" STATIC int docd(shinstance *psh, char *, int); STATIC char *getcomponent(shinstance *psh); STATIC void updatepwd(shinstance *psh, char *); STATIC void find_curdir(shinstance *psh, int noerror); /*char *curdir = NULL;*/ /* current working directory */ /*char *prevdir;*/ /* previous working directory */ /*STATIC char *cdcomppath;*/ int cdcmd(shinstance *psh, int argc, char **argv) { const char *dest; const char *path; char *p, *d; struct stat statb; int print = cdprint(psh); /* set -cdprint to enable */ nextopt(psh, nullstr); /* * Try (quite hard) to have 'curdir' defined, nothing has set * it on entry to the shell, but we want 'cd fred; cd -' to work. */ getpwd(psh, 1); dest = *psh->argptr; if (dest == NULL) { dest = bltinlookup(psh, "HOME", 1); if (dest == NULL) error(psh, "HOME not set"); } else { if (psh->argptr[1]) { /* Do 'ksh' style substitution */ if (!psh->curdir) error(psh, "PWD not set"); p = strstr(psh->curdir, dest); if (!p) error(psh, "bad substitution"); d = stalloc(psh, strlen(psh->curdir) + strlen(psh->argptr[1]) + 1); memcpy(d, psh->curdir, p - psh->curdir); strcpy(d + (p - psh->curdir), psh->argptr[1]); strcat(d, p + strlen(dest)); dest = d; print = 1; } } if (dest[0] == '-' && dest[1] == '\0') { dest = psh->prevdir ? psh->prevdir : psh->curdir; print = 1; } if (*dest == '\0') dest = "."; if (IS_ROOT(dest) || (path = bltinlookup(psh, "CDPATH", 1)) == NULL) path = nullstr; while ((p = padvance(psh, &path, dest)) != NULL) { if (shfile_stat(&psh->fdtab, p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { if (!print) { /* * XXX - rethink */ if (p[0] == '.' && p[1] == '/' && p[2] != '\0') p += 2; print = strcmp(p, dest); } if (docd(psh, p, print) >= 0) return 0; } } error(psh, "can't cd to %s", dest); /* NOTREACHED */ return 1; } /* * Actually do the chdir. In an interactive shell, print the * directory name if "print" is nonzero. */ STATIC int docd(shinstance *psh, char *dest, int print) { char *p; char *q; char *component; struct stat statb; int first; int badstat; TRACE((psh, "docd(\"%s\", %d) called\n", dest, print)); /* * Check each component of the path. If we find a symlink or * something we can't stat, clear curdir to force a getcwd() * next time we get the value of the current directory. */ badstat = 0; psh->cdcomppath = stalloc(psh, strlen(dest) + 1); scopy(dest, psh->cdcomppath); STARTSTACKSTR(psh, p); if (IS_ROOT(dest)) { STPUTC(psh, '/', p); psh->cdcomppath++; } first = 1; while ((q = getcomponent(psh)) != NULL) { if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0')) continue; if (! first) STPUTC(psh, '/', p); first = 0; component = q; while (*q) STPUTC(psh, *q++, p); if (equal(component, "..")) continue; STACKSTRNUL(psh, p); if ((shfile_lstat(&psh->fdtab, stackblock(psh), &statb) < 0) || (S_ISLNK(statb.st_mode))) { /* print = 1; */ badstat = 1; break; } } INTOFF; if (shfile_chdir(&psh->fdtab, dest) < 0) { INTON; return -1; } updatepwd(psh, badstat ? NULL : dest); INTON; if (print && iflag(psh) && psh->curdir) out1fmt(psh, "%s\n", psh->curdir); return 0; } /* * Get the next component of the path name pointed to by psh->cdcomppath. * This routine overwrites the string pointed to by psh->cdcomppath. */ STATIC char * getcomponent(shinstance *psh) { char *p; char *start; if ((p = psh->cdcomppath) == NULL) return NULL; start = psh->cdcomppath; while (*p != '/' && *p != '\0') p++; if (*p == '\0') { psh->cdcomppath = NULL; } else { *p++ = '\0'; psh->cdcomppath = p; } return start; } /* * Update curdir (the name of the current directory) in response to a * cd command. We also call hashcd to let the routines in exec.c know * that the current directory has changed. */ STATIC void updatepwd(shinstance *psh, char *dir) { char *new; char *p; hashcd(psh); /* update command hash table */ /* * If our argument is NULL, we don't know the current directory * any more because we traversed a symbolic link or something * we couldn't stat(). */ if (dir == NULL || psh->curdir == NULL) { if (psh->prevdir) ckfree(psh, psh->prevdir); INTOFF; psh->prevdir = psh->curdir; psh->curdir = NULL; getpwd(psh, 1); INTON; if (psh->curdir) setvar(psh, "PWD", psh->curdir, VEXPORT); else unsetvar(psh, "PWD", 0); return; } psh->cdcomppath = stalloc(psh, strlen(dir) + 1); scopy(dir, psh->cdcomppath); STARTSTACKSTR(psh, new); if (!IS_ROOT(dir)) { p = psh->curdir; while (*p) STPUTC(psh, *p++, new); if (p[-1] == '/') STUNPUTC(psh, new); } while ((p = getcomponent(psh)) != NULL) { if (equal(p, "..")) { while (new > stackblock(psh) && (STUNPUTC(psh, new), *new) != '/'); } else if (*p != '\0' && ! equal(p, ".")) { STPUTC(psh, '/', new); while (*p) STPUTC(psh, *p++, new); } } if (new == stackblock(psh)) STPUTC(psh, '/', new); STACKSTRNUL(psh, new); INTOFF; if (psh->prevdir) ckfree(psh, psh->prevdir); psh->prevdir = psh->curdir; psh->curdir = savestr(psh, stackblock(psh)); setvar(psh, "PWD", psh->curdir, VEXPORT); INTON; } /* * Posix says the default should be 'pwd -L' (as below), however * the 'cd' command (above) does something much nearer to the * posix 'cd -P' (not the posix default of 'cd -L'). * If 'cd' is changed to support -P/L then the default here * needs to be revisited if the historic behaviour is to be kept. */ int pwdcmd(shinstance *psh, int argc, char **argv) { int i; char opt = 'L'; while ((i = nextopt(psh, "LP")) != '\0') opt = i; if (*psh->argptr) error(psh, "unexpected argument"); if (opt == 'L') getpwd(psh, 0); else find_curdir(psh, 0); setvar(psh, "PWD", psh->curdir, VEXPORT); out1str(psh, psh->curdir); out1c(psh, '\n'); return 0; } #define MAXPWD 256 /* * Find out what the current directory is. If we already know the current * directory, this routine returns immediately. */ const char * getpwd(shinstance *psh, int noerror) { char *pwd; struct stat stdot, stpwd; /*static int first = 1;*/ if (psh->curdir) return psh->curdir; if (psh->getpwd_first) { psh->getpwd_first = 0; pwd = sh_getenv(psh, "PWD"); if (pwd && IS_ROOT(pwd) && shfile_stat(&psh->fdtab, ".", &stdot) != -1 && shfile_stat(&psh->fdtab, pwd, &stpwd) != -1 && stdot.st_dev == stpwd.st_dev && stdot.st_ino == stpwd.st_ino) { psh->curdir = savestr(psh, pwd); return psh->curdir; } } find_curdir(psh, noerror); return psh->curdir; } STATIC void find_curdir(shinstance *psh, int noerror) { int i; char *pwd; /* * Things are a bit complicated here; we could have just used * getcwd, but traditionally getcwd is implemented using popen * to /bin/pwd. This creates a problem for us, since we cannot * keep track of the job if it is being ran behind our backs. * So we re-implement getcwd(), and we suppress interrupts * throughout the process. This is not completely safe, since * the user can still break out of it by killing the pwd program. * We still try to use getcwd for systems that we know have a * c implementation of getcwd, that does not open a pipe to * /bin/pwd. */ #if 1 //defined(__NetBSD__) || defined(__SVR4) || defined(__INNOTEK_LIBC__) for (i = MAXPWD;; i *= 2) { pwd = stalloc(psh, i); if (shfile_getcwd(&psh->fdtab, pwd, i) != NULL) { psh->curdir = savestr(psh, pwd); return; } stunalloc(psh, pwd); if (errno == ERANGE) continue; if (!noerror) error(psh, "getcwd() failed: %s", sh_strerror(psh, errno)); return; } #else { char *p; int status; struct job *jp; int pip[2]; pwd = stalloc(psh, MAXPWD); INTOFF; if (pipe(pip) < 0) error(psh, "Pipe call failed"); jp = makejob((union node *)NULL, 1); if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) { (void) close(pip[0]); if (pip[1] != 1) { close(1); copyfd(pip[1], 1); close(pip[1]); } (void) execl("/bin/pwd", "pwd", (char *)0); error(psh, "Cannot exec /bin/pwd"); } (void) close(pip[1]); pip[1] = -1; p = pwd; while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0 || (i == -1 && errno == EINTR)) { if (i > 0) p += i; } (void) close(pip[0]); pip[0] = -1; status = waitforjob(jp); if (status != 0) error(psh, (char *)0); if (i < 0 || p == pwd || p[-1] != '\n') { if (noerror) { INTON; return; } error(psh, "pwd command failed"); } p[-1] = '\0'; INTON; psh->curdir = savestr(pwd); return; } #endif } kbuild-2695/src/kash/show.c0000644000000000000000000002564612247157307014317 0ustar rootroot/* $NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $"); #endif /* not lint */ #endif #include #include #include #include #include "shell.h" #include "parser.h" #include "nodes.h" #include "mystring.h" #include "show.h" #include "options.h" #include "shinstance.h" #ifdef DEBUG static void shtree(union node *, int, char *, FILE*); static void shcmd(union node *, FILE *); static void sharg(union node *, FILE *); static void indent(int, char *, FILE *); static void trstring(shinstance *, char *); void showtree(shinstance *psh, union node *n) { trputs(psh, "showtree called\n"); shtree(n, 1, NULL, stdout); } static void shtree(union node *n, int ind, char *pfx, FILE *fp) { struct nodelist *lp; const char *s; if (n == NULL) return; indent(ind, pfx, fp); switch(n->type) { case NSEMI: s = "; "; goto binop; case NAND: s = " && "; goto binop; case NOR: s = " || "; binop: shtree(n->nbinary.ch1, ind, NULL, fp); /* if (ind < 0) */ fputs(s, fp); shtree(n->nbinary.ch2, ind, NULL, fp); break; case NCMD: shcmd(n, fp); if (ind >= 0) putc('\n', fp); break; case NPIPE: for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { shcmd(lp->n, fp); if (lp->next) fputs(" | ", fp); } if (n->npipe.backgnd) fputs(" &", fp); if (ind >= 0) putc('\n', fp); break; default: fprintf(fp, "", n->type); if (ind >= 0) putc('\n', fp); break; } } static void shcmd(union node *cmd, FILE *fp) { union node *np; int first; const char *s; int dftfd; first = 1; for (np = cmd->ncmd.args ; np ; np = np->narg.next) { if (! first) putchar(' '); sharg(np, fp); first = 0; } for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { if (! first) putchar(' '); switch (np->nfile.type) { case NTO: s = ">"; dftfd = 1; break; case NCLOBBER: s = ">|"; dftfd = 1; break; case NAPPEND: s = ">>"; dftfd = 1; break; case NTOFD: s = ">&"; dftfd = 1; break; case NFROM: s = "<"; dftfd = 0; break; case NFROMFD: s = "<&"; dftfd = 0; break; case NFROMTO: s = "<>"; dftfd = 0; break; default: s = "*error*"; dftfd = 0; break; } if (np->nfile.fd != dftfd) fprintf(fp, "%d", np->nfile.fd); fputs(s, fp); if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { fprintf(fp, "%d", np->ndup.dupfd); } else { sharg(np->nfile.fname, fp); } first = 0; } } static void sharg(union node *arg, FILE *fp) { char *p; struct nodelist *bqlist; int subtype; if (arg->type != NARG) { printf("\n", arg->type); abort(); } bqlist = arg->narg.backquote; for (p = arg->narg.text ; *p ; p++) { switch (*p) { case CTLESC: putc(*++p, fp); break; case CTLVAR: putc('$', fp); putc('{', fp); subtype = *++p; if (subtype == VSLENGTH) putc('#', fp); while (*p != '=') putc(*p++, fp); if (subtype & VSNUL) putc(':', fp); switch (subtype & VSTYPE) { case VSNORMAL: putc('}', fp); break; case VSMINUS: putc('-', fp); break; case VSPLUS: putc('+', fp); break; case VSQUESTION: putc('?', fp); break; case VSASSIGN: putc('=', fp); break; case VSTRIMLEFT: putc('#', fp); break; case VSTRIMLEFTMAX: putc('#', fp); putc('#', fp); break; case VSTRIMRIGHT: putc('%', fp); break; case VSTRIMRIGHTMAX: putc('%', fp); putc('%', fp); break; case VSLENGTH: break; default: printf("", subtype); } break; case CTLENDVAR: putc('}', fp); break; case CTLBACKQ: case CTLBACKQ|CTLQUOTE: putc('$', fp); putc('(', fp); shtree(bqlist->n, -1, NULL, fp); putc(')', fp); break; default: putc(*p, fp); break; } } } static void indent(int amount, char *pfx, FILE *fp) { int i; for (i = 0 ; i < amount ; i++) { if (pfx && i == amount - 1) fputs(pfx, fp); putc('\t', fp); } } #endif #ifdef DEBUG /* * Debugging stuff. */ /** @def TRY_GET_PSH_OR_RETURN * Make sure @a psh is valid, trying to fetch it from TLS * if it's NULL and returning (void) if that fails. */ # define TRY_GET_PSH_OR_RETURN(psh) \ if (!(psh)) { \ (psh) = shthread_get_shell(); \ if (!(psh)) \ return; \ } else do { } while (0) /** @def RETURN_IF_NOT_TRACING * Return if we're not tracing. */ # define RETURN_IF_NOT_TRACING(psh) \ if (debug(psh) != 1 || psh->tracefd == -1) \ return; \ else do {} while (0) /* Flushes the tracebuf. */ static void trace_flush(shinstance *psh) { size_t pos = psh->tracepos; if (pos > sizeof(psh->tracebuf)) { char *end; assert(0); end = memchr(psh->tracebuf, '\0', sizeof(psh->tracebuf)); pos = end ? end - &psh->tracebuf[0] : 0; } if (pos) { int s = errno; char prefix[40]; size_t len; len = sprintf(prefix, "[%d] ", sh_getpid(psh)); shfile_write(&psh->fdtab, psh->tracefd, prefix, len); shfile_write(&psh->fdtab, psh->tracefd, psh->tracebuf, pos); psh->tracepos = 0; psh->tracebuf[0] = '\0'; errno = s; } } /* Adds a char to the trace buffer. */ static void trace_char(shinstance *psh, int c) { size_t pos = psh->tracepos; if (pos >= sizeof(psh->tracebuf) - 1) { trace_flush(psh); pos = psh->tracepos; } psh->tracebuf[pos] = c; psh->tracepos = pos + 1; if (c == '\n') trace_flush(psh); else psh->tracebuf[pos + 1] = '\0'; } /* Add a string to the trace buffer. */ static void trace_string(shinstance *psh, const char *str) { /* push it out line by line. */ while (*str) { /* find line/string length. */ size_t pos; size_t len; const char *end = str; int flush_it = 0; while (*end) { if (*end++ == '\n') { flush_it = 1; break; } } len = end - str; /* copy to the buffer */ pos = psh->tracepos; if (pos + len <= sizeof(psh->tracebuf)) { memcpy(&psh->tracebuf[pos], str, len); psh->tracepos = pos + len; if (flush_it) trace_flush(psh); } else { /* it's too big for some reason... */ int s = errno; trace_flush(psh); shfile_write(&psh->fdtab, psh->tracefd, str, len); if (!flush_it) shfile_write(&psh->fdtab, psh->tracefd, "[too long]\n", sizeof( "[too long]\n") - 1); errno = s; } /* advance */ str = end; } } void trputc(shinstance *psh, int c) { TRY_GET_PSH_OR_RETURN(psh); RETURN_IF_NOT_TRACING(psh); trace_char(psh, c); } void trace(shinstance *psh, const char *fmt, ...) { va_list va; char buf[2048]; TRY_GET_PSH_OR_RETURN(psh); RETURN_IF_NOT_TRACING(psh); va_start(va, fmt); # ifdef _MSC_VER _vsnprintf(buf, sizeof(buf), fmt, va); # else vsnprintf(buf, sizeof(buf), fmt, va); # endif va_end(va); trace_string(psh, buf); } void tracev(shinstance *psh, const char *fmt, va_list va) { char buf[2048]; TRY_GET_PSH_OR_RETURN(psh); RETURN_IF_NOT_TRACING(psh); # ifdef _MSC_VER _vsnprintf(buf, sizeof(buf), fmt, va); # else vsnprintf(buf, sizeof(buf), fmt, va); # endif trace_string(psh, buf); } void trputs(shinstance *psh, const char *s) { TRY_GET_PSH_OR_RETURN(psh); RETURN_IF_NOT_TRACING(psh); trace_string(psh, s); trace_char(psh, '\n'); } static void trstring(shinstance *psh, char *s) { char *p; char c; TRY_GET_PSH_OR_RETURN(psh); RETURN_IF_NOT_TRACING(psh); trace_char(psh, '"'); for (p = s ; *p ; p++) { switch (*p) { case '\n': c = 'n'; goto backslash; case '\t': c = 't'; goto backslash; case '\r': c = 'r'; goto backslash; case '"': c = '"'; goto backslash; case '\\': c = '\\'; goto backslash; case CTLESC: c = 'e'; goto backslash; case CTLVAR: c = 'v'; goto backslash; case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; case CTLBACKQ: c = 'q'; goto backslash; case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; backslash: trace_char(psh, '\\'); trace_char(psh, c); break; default: if (*p >= ' ' && *p <= '~') trace_char(psh, *p); else { trace_char(psh, '\\'); trace_char(psh, *p >> 6 & 03); trace_char(psh, *p >> 3 & 07); trace_char(psh, *p & 07); } break; } } trace_char(psh, '"'); } void trargs(shinstance *psh, char **ap) { TRY_GET_PSH_OR_RETURN(psh); RETURN_IF_NOT_TRACING(psh); while (*ap) { trstring(psh, *ap++); if (*ap) trace_char(psh, ' '); else trace_char(psh, '\n'); } } void opentrace(shinstance *psh) { static const char s[] = "./trace"; TRY_GET_PSH_OR_RETURN(psh); if (debug(psh) != 1) { /* disabled */ if (psh->tracefd != -1) { trace_flush(psh); shfile_close(&psh->fdtab, psh->tracefd); psh->tracefd = -1; } return; } /* else: (re-)enabled */ if (psh->tracefd != -1) return; psh->tracefd = shfile_open(&psh->fdtab, s, O_APPEND | O_RDWR | O_CREAT, 0600); if (psh->tracefd != -1) { /* relocate it */ int want_fd = 199; while (want_fd > 10) { int fd2 = shfile_fcntl(&psh->fdtab, psh->tracefd, F_DUPFD, want_fd); if (fd2 != -1) { shfile_close(&psh->fdtab, psh->tracefd); psh->tracefd = fd2; break; } want_fd = ((want_fd + 1) / 2) - 1; } shfile_cloexec(&psh->fdtab, psh->tracefd, 1 /* close it */); } if (psh->tracefd == -1) { fprintf(stderr, "Can't open %s\n", s); debug(psh) = 0; return; } trace_string(psh, "Tracing started.\n"); } #endif /* DEBUG */ kbuild-2695/src/kash/machdep.h0000644000000000000000000000435212247157307014734 0ustar rootroot/* $NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)machdep.h 8.2 (Berkeley) 5/4/95 */ /* * Most machines require the value returned from malloc to be aligned * in some way. The following macro will get this right on many machines. */ #ifdef _MSC_VER #define SHELL_SIZE (8 - 1) #else #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1) #endif /* * It appears that grabstackstr() will barf with such alignments * because stalloc() will return a string allocated in a new stackblock. */ #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE) kbuild-2695/src/kash/mystring.c0000644000000000000000000000645212247157307015205 0ustar rootroot/* $NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $"); #endif /* not lint */ #endif /* * String functions. * * equal(s1, s2) Return true if strings are equal. * scopy(from, to) Copy a string. * scopyn(from, to, n) Like scopy, but checks for overflow. * number(s) Convert a string of digits to an integer. * is_number(s) Return true if s is a string of digits. */ #include #include "shell.h" #include "syntax.h" #include "error.h" #include "mystring.h" char nullstr[1]; /* zero length string */ /* * equal - #defined in mystring.h */ /* * scopy - #defined in mystring.h */ /* * scopyn - copy a string from "from" to "to", truncating the string * if necessary. "To" is always nul terminated, even if * truncation is performed. "Size" is the size of "to". */ void scopyn(const char *from, char *to, ssize_t size) { while (--size > 0) { if ((*to++ = *from++) == '\0') return; } *to = '\0'; } /* * prefix -- see if pfx is a prefix of string. */ int prefix(const char *pfx, const char *string) { while (*pfx) { if (*pfx++ != *string++) return 0; } return 1; } /* * Convert a string of digits to an integer, printing an error message on * failure. */ int number(shinstance *psh, const char *s) { if (! is_number(s)) error(psh, "Illegal number: %s", s); return atoi(s); } /* * Check for a valid number. This should be elsewhere. */ int is_number(const char *p) { do { if (! is_digit(*p)) return 0; } while (*++p != '\0'); return 1; } kbuild-2695/src/kash/parser.h0000644000000000000000000000704412247157307014630 0ustar rootroot/* $NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)parser.h 8.3 (Berkeley) 5/4/95 */ #ifndef ___parse_h #define ___parse_h /* control characters in argument strings */ #define CTL_FIRST '\201' /* first 'special' character */ #define CTLESC '\201' /* escape next character */ #define CTLVAR '\202' /* variable defn */ #define CTLENDVAR '\203' #define CTLBACKQ '\204' #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ /* CTLBACKQ | CTLQUOTE == '\205' */ #define CTLARI '\206' /* arithmetic expression */ #define CTLENDARI '\207' #define CTLQUOTEMARK '\210' #define CTLQUOTEEND '\211' /* only inside ${...} */ #define CTL_LAST '\211' /* last 'special' character */ /* variable substitution byte (follows CTLVAR) */ #define VSTYPE 0x0f /* type of variable substitution */ #define VSNUL 0x10 /* colon--treat the empty string as unset */ #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ /* values of VSTYPE field */ #define VSNORMAL 0x1 /* normal variable: $var or ${var} */ #define VSMINUS 0x2 /* ${var-text} */ #define VSPLUS 0x3 /* ${var+text} */ #define VSQUESTION 0x4 /* ${var?message} */ #define VSASSIGN 0x5 /* ${var=text} */ #define VSTRIMLEFT 0x6 /* ${var#pattern} */ #define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */ #define VSTRIMRIGHT 0x8 /* ${var%pattern} */ #define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */ #define VSLENGTH 0xa /* ${#var} */ /* * NEOF is returned by parsecmd when it encounters an end of file. It * must be distinct from NULL, so we use the address of a variable that * happens to be handy. */ /*extern int tokpushback;*/ #define NEOF ((union node *)&psh->tokpushback) /*extern int whichprompt;*/ /* 1 == PS1, 2 == PS2 */ union node *parsecmd(struct shinstance *, int); void fixredir(struct shinstance *, union node *, const char *, int); int goodname(const char *); const char *getprompt(struct shinstance *, void *); #endif kbuild-2695/src/kash/shinstance.h0000644000000000000000000004171012247157307015471 0ustar rootroot/* $Id: shinstance.h 2657 2012-09-10 20:57:58Z bird $ */ /** @file * The shell instance and it's methods. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef ___shinstance_h #define ___shinstance_h #include /* BUFSIZ */ #include /* NSIG */ #ifndef _MSC_VER # include # include # include # include #endif #include #ifdef _MSC_VER # define EWOULDBLOCK 140 #endif #include "shtypes.h" #include "shthread.h" #include "shfile.h" #include "shheap.h" #include "shell.h" #include "output.h" #include "options.h" #include "expand.h" #include "exec.h" #include "var.h" #include "show.h" #ifdef _MSC_VER # define strcasecmp stricmp # define strncasecmp strnicmp #endif /** * A child process. */ typedef struct shchild { pid_t pid; /**< The pid. */ #if K_OS == K_OS_WINDOWS void *hChild; /**< The process handle. */ #endif } shchild; /* memalloc.c */ #define MINSIZE 504 /* minimum size of a block */ struct stack_block { struct stack_block *prev; char space[MINSIZE]; }; /* input.c */ struct strpush { struct strpush *prev; /* preceding string on stack */ char *prevstring; int prevnleft; int prevlleft; struct alias *ap; /* if push was associated with an alias */ }; /* * The parsefile structure pointed to by the global variable parsefile * contains information about the current file being read. */ struct parsefile { struct parsefile *prev; /* preceding file on stack */ int linno; /* current line */ int fd; /* file descriptor (or -1 if string) */ int nleft; /* number of chars left in this line */ int lleft; /* number of chars left in this buffer */ char *nextc; /* next char in buffer */ char *buf; /* input buffer */ struct strpush *strpush; /* for pushing strings at this level */ struct strpush basestrpush; /* so pushing one is fast */ }; /* exec.c */ #define CMDTABLESIZE 31 /* should be prime */ #define ARB 1 /* actual size determined at run time */ struct tblentry { struct tblentry *next; /* next entry in hash chain */ union param param; /* definition of builtin function */ short cmdtype; /* index identifying command */ char rehash; /* if set, cd done since entry created */ char cmdname[ARB]; /* name of command */ }; /* expand.c */ /* * Structure specifying which parts of the string should be searched * for IFS characters. */ struct ifsregion { struct ifsregion *next; /* next region in list */ int begoff; /* offset of start of region */ int endoff; /* offset of end of region */ int inquotes; /* search for nul bytes only */ }; /** * A shell instance. * * This is the core structure of the shell, it contains all * the data associated with a shell process except that it's * running in a thread and not a separate process. */ struct shinstance { struct shinstance *next; /**< The next shell instance. */ struct shinstance *prev; /**< The previous shell instance. */ struct shinstance *parent; /**< The parent shell instance. */ pid_t pid; /**< The (fake) process id of this shell instance. */ shtid tid; /**< The thread identifier of the thread for this shell. */ shfdtab fdtab; /**< The file descriptor table. */ shsigaction_t sigactions[NSIG]; /**< The signal actions registered with this shell instance. */ shsigset_t sigmask; /**< Our signal mask. */ char **shenviron; /**< The environment vector. */ int num_children; /**< Number of children in the array. */ shchild *children; /**< The child array. */ /* alias.c */ #define ATABSIZE 39 struct alias *atab[ATABSIZE]; /* cd.c */ char *curdir; /**< current working directory */ char *prevdir; /**< previous working directory */ char *cdcomppath; int getpwd_first; /**< static in getpwd. (initialized to 1!) */ /* error.h */ struct jmploc *handler; int exception; int exerrno/* = 0 */; /**< Last exec error */ int volatile suppressint; int volatile intpending; /* error.c */ char errmsg_buf[16]; /**< static in errmsg. (bss) */ /* eval.h */ char *commandname; /**< currently executing command */ int exitstatus; /**< exit status of last command */ int back_exitstatus;/**< exit status of backquoted command */ struct strlist *cmdenviron; /**< environment for builtin command */ int funcnest; /**< depth of function calls */ int evalskip; /**< set if we are skipping commands */ int skipcount; /**< number of levels to skip */ int loopnest; /**< current loop nesting level */ /* eval.c */ int vforked; /* expand.c */ char *expdest; /**< output of current string */ struct nodelist *argbackq; /**< list of back quote expressions */ struct ifsregion ifsfirst; /**< first struct in list of ifs regions */ struct ifsregion *ifslastp; /**< last struct in list */ struct arglist exparg; /**< holds expanded arg list */ char *expdir; /**< Used by expandmeta. */ /* exec.h */ const char *pathopt; /**< set by padvance */ /* exec.c */ struct tblentry *cmdtable[CMDTABLESIZE]; int builtinloc/* = -1*/; /**< index in path of %builtin, or -1 */ /* input.h */ int plinno/* = 1 */;/**< input line number */ int parsenleft; /**< number of characters left in input buffer */ char *parsenextc; /**< next character in input buffer */ int init_editline/* = 0 */; /**< 0 == not setup, 1 == OK, -1 == failed */ /* input.c */ int parselleft; /**< copy of parsefile->lleft */ struct parsefile basepf; /**< top level input file */ char basebuf[BUFSIZ];/**< buffer for top level input file */ struct parsefile *parsefile/* = &basepf*/; /**< current input file */ #ifndef SMALL EditLine *el; /**< cookie for editline package */ #endif /* jobs.h */ pid_t backgndpid/* = -1 */; /**< pid of last background process */ int job_warning; /**< user was warned about stopped jobs */ /* jobs.c */ struct job *jobtab; /**< array of jobs */ int njobs; /**< size of array */ int jobs_invalid; /**< set in child */ int initialpgrp; /**< pgrp of shell on invocation */ int curjob/* = -1*/;/**< current job */ int ttyfd/* = -1*/; int jobctl; /**< job control enabled / disabled */ char *cmdnextc; int cmdnleft; /* mail.c */ #define MAXMBOXES 10 int nmboxes; /**< number of mailboxes */ time_t mailtime[MAXMBOXES]; /**< times of mailboxes */ /* main.h */ int rootpid; /**< pid of main shell. */ int rootshell; /**< true if we aren't a child of the main shell. */ struct shinstance *psh_rootshell; /**< The root shell pointer. (!rootshell) */ /* memalloc.h */ char *stacknxt/* = stackbase.space*/; int stacknleft/* = MINSIZE*/; int sstrnleft; int herefd/* = -1 */; /* memalloc.c */ struct stack_block stackbase; struct stack_block *stackp/* = &stackbase*/; struct stackmark *markp; /* myhistedit.h */ int displayhist; #ifndef SMALL History *hist; EditLine *el; #endif /* output.h */ struct output output; struct output errout; struct output memout; struct output *out1; struct output *out2; /* output.c */ #define OUTBUFSIZ BUFSIZ #define MEM_OUT -3 /**< output to dynamically allocated memory */ /* options.h */ struct optent optlist[NOPTS]; char *minusc; /**< argument to -c option */ char *arg0; /**< $0 */ struct shparam shellparam; /**< $@ */ char **argptr; /**< argument list for builtin commands */ char *optionarg; /**< set by nextopt */ char *optptr; /**< used by nextopt */ /* parse.h */ int tokpushback; int whichprompt; /**< 1 == PS1, 2 == PS2 */ /* parser.c */ int noalias/* = 0*/;/**< when set, don't handle aliases */ struct heredoc *heredoclist; /**< list of here documents to read */ int parsebackquote; /**< nonzero if we are inside backquotes */ int doprompt; /**< if set, prompt the user */ int needprompt; /**< true if interactive and at start of line */ int lasttoken; /**< last token read */ char *wordtext; /**< text of last word returned by readtoken */ int checkkwd; /**< 1 == check for kwds, 2 == also eat newlines */ struct nodelist *backquotelist; union node *redirnode; struct heredoc *heredoc; int quoteflag; /**< set if (part of) last token was quoted */ int startlinno; /**< line # where last token started */ /* redir.c */ struct redirtab *redirlist; int fd0_redirected/* = 0*/; /* show.c */ char tracebuf[1024]; size_t tracepos; int tracefd; /* trap.h */ int pendingsigs; /**< indicates some signal received */ /* trap.c */ char gotsig[NSIG]; /**< indicates specified signal received */ char *trap[NSIG+1]; /**< trap handler commands */ char sigmode[NSIG]; /**< current value of signal */ /* var.h */ struct localvar *localvars; struct var vatty; struct var vifs; struct var vmail; struct var vmpath; struct var vpath; #ifdef _MSC_VER struct var vpath2; #endif struct var vps1; struct var vps2; struct var vps4; #ifndef SMALL struct var vterm; struct var vhistsize; #endif struct var voptind; #ifdef PC_OS2_LIBPATHS struct var libpath_vars[4]; #endif #ifdef SMALL # define VTABSIZE 39 #else # define VTABSIZE 517 #endif struct var *vartab[VTABSIZE]; /* builtins.h */ /* bltin/test.c */ char **t_wp; struct t_op const *t_wp_op; }; extern shinstance *sh_create_root_shell(shinstance *, int, char **, char **); /* environment & pwd.h */ char *sh_getenv(shinstance *, const char *); char **sh_environ(shinstance *); const char *sh_gethomedir(shinstance *, const char *); /* signals */ #define SH_SIG_UNK ((shsig_t)(intptr_t)-199) #define SH_SIG_DFL ((shsig_t)SIG_DFL) #define SH_SIG_IGN ((shsig_t)SIG_IGN) #define SH_SIG_ERR ((shsig_t)SIG_ERR) #ifdef _MSC_VER # define SA_RESTART 0x02 # define SIG_BLOCK 1 # define SIG_UNBLOCK 2 # define SIG_SETMASK 3 # define SIGHUP 1 /* _SIGHUP_IGNORE */ /*# define SIGINT 2 */ # define SIGQUIT 3 /* _SIGQUIT_IGNORE */ /*# define SIGILL 4 */ /*# define SIGFPE 8 */ /*# define SIGSEGV 11 */ # define SIGPIPE 13 /* _SIGPIPE_IGNORE */ /*# define SIGTERM 15 */ # define SIGTTIN 16 /* _SIGIOINT_IGNORE */ # define SIGTSTP 17 /* _SIGSTOP_IGNORE */ # define SIGTTOU 18 # define SIGCONT 20 /*# define SIGBREAK 21 */ /*# define SIGABRT 22 */ # define sys_siglist sys_signame #endif /* _MSC_VER */ #ifdef __sun__ # define sys_siglist _sys_siglist #endif #ifndef HAVE_SYS_SIGNAME extern char sys_signame[NSIG][16]; #endif int sh_sigaction(shinstance *, int, const struct shsigaction *, struct shsigaction *); shsig_t sh_signal(shinstance *, int, shsig_t); int sh_siginterrupt(shinstance *, int, int); void sh_sigemptyset(shsigset_t *); void sh_sigfillset(shsigset_t *); void sh_sigaddset(shsigset_t *, int); void sh_sigdelset(shsigset_t *, int); int sh_sigismember(shsigset_t const *, int); int sh_sigprocmask(shinstance *, int, shsigset_t const *, shsigset_t *); SH_NORETURN_1 void sh_abort(shinstance *) SH_NORETURN_2; void sh_raise_sigint(shinstance *); int sh_kill(shinstance *, pid_t, int); int sh_killpg(shinstance *, pid_t, int); /* times */ #include #ifdef _MSC_VER typedef struct shtms { clock_t tms_utime; clock_t tms_stime; clock_t tms_cutime; clock_t tms_cstime; } shtms; #else # include typedef struct tms shtms; #endif clock_t sh_times(shinstance *, shtms *); int sh_sysconf_clk_tck(void); /* wait / process */ int sh_add_child(shinstance *psh, pid_t pid, void *hChild); #ifdef _MSC_VER # include # define WNOHANG 1 /* Don't hang in wait. */ # define WUNTRACED 2 /* Tell about stopped, untraced children. */ # define WCONTINUED 4 /* Report a job control continued process. */ # define _W_INT(w) (*(int *)&(w)) /* Convert union wait to int. */ # define WCOREFLAG 0200 # define _WSTATUS(x) (_W_INT(x) & 0177) # define _WSTOPPED 0177 /* _WSTATUS if process is stopped */ # define WIFSTOPPED(x) (_WSTATUS(x) == _WSTOPPED) # define WSTOPSIG(x) (_W_INT(x) >> 8) # define WIFSIGNALED(x) (_WSTATUS(x) != 0 && !WIFSTOPPED(x) && !WIFCONTINUED(x)) /* bird: made GLIBC tests happy. */ # define WTERMSIG(x) (_WSTATUS(x)) # define WIFEXITED(x) (_WSTATUS(x) == 0) # define WEXITSTATUS(x) (_W_INT(x) >> 8) # define WIFCONTINUED(x) (x == 0x13) /* 0x13 == SIGCONT */ # define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG) # define W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) # define W_STOPCODE(sig) ((sig) << 8 | _WSTOPPED) #else # include # ifdef __HAIKU__ # define WCOREDUMP(x) WIFCORED(x) # endif #endif pid_t sh_fork(shinstance *); pid_t sh_waitpid(shinstance *, pid_t, int *, int); SH_NORETURN_1 void sh__exit(shinstance *, int) SH_NORETURN_2; int sh_execve(shinstance *, const char *, const char * const*, const char * const *); uid_t sh_getuid(shinstance *); uid_t sh_geteuid(shinstance *); gid_t sh_getgid(shinstance *); gid_t sh_getegid(shinstance *); pid_t sh_getpid(shinstance *); pid_t sh_getpgrp(shinstance *); pid_t sh_getpgid(shinstance *, pid_t); int sh_setpgid(shinstance *, pid_t, pid_t); /* tc* */ pid_t sh_tcgetpgrp(shinstance *, int); int sh_tcsetpgrp(shinstance *, int, pid_t); /* sys/resource.h */ #ifdef _MSC_VER typedef int64_t shrlim_t; typedef struct shrlimit { shrlim_t rlim_cur; shrlim_t rlim_max; } shrlimit; # define RLIMIT_CPU 0 # define RLIMIT_FSIZE 1 # define RLIMIT_DATA 2 # define RLIMIT_STACK 3 # define RLIMIT_CORE 4 # define RLIMIT_RSS 5 # define RLIMIT_MEMLOCK 6 # define RLIMIT_NPROC 7 # define RLIMIT_NOFILE 8 # define RLIMIT_SBSIZE 9 # define RLIMIT_VMEM 10 # define RLIM_NLIMITS 11 # define RLIM_INFINITY (0x7fffffffffffffffLL) #else typedef rlim_t shrlim_t; typedef struct rlimit shrlimit; #endif int sh_getrlimit(shinstance *, int, shrlimit *); int sh_setrlimit(shinstance *, int, const shrlimit *); /* string.h */ const char *sh_strerror(shinstance *, int); #ifdef DEBUG # define TRACE2(param) trace param # define TRACE2V(param) tracev param #else # define TRACE2(param) do { } while (0) # define TRACE2V(param) do { } while (0) #endif #endif kbuild-2695/src/kash/shinstance.c0000644000000000000000000010452512247157307015470 0ustar rootroot/* $Id: shinstance.c 2652 2012-09-09 17:21:48Z bird $ */ /** @file * The shell instance methods. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #ifdef _MSC_VER # include #else # include # include #endif #include "shinstance.h" #if K_OS == K_OS_WINDOWS # include extern pid_t shfork_do(shinstance *psh); /* shforkA-win.asm */ #endif #if !defined(HAVE_SYS_SIGNAME) && defined(DEBUG) extern void init_sys_signame(void); #endif /******************************************************************************* * Global Variables * *******************************************************************************/ /** The mutex protecting the the globals and some shell instance members (sigs). */ static shmtx g_sh_mtx; /** The root shell instance. */ static shinstance *g_sh_root; /** The first shell instance. */ static shinstance *g_sh_head; /** The last shell instance. */ static shinstance *g_sh_tail; /** The number of shells. */ static int volatile g_num_shells; /** Per signal state for determining a common denominator. * @remarks defaults and unmasked actions aren't counted. */ struct shsigstate { /** The current signal action. */ #ifndef _MSC_VER struct sigaction sa; #else struct { void (*sa_handler)(int); int sa_flags; shsigset_t sa_mask; } sa; #endif /** The number of restarts (siginterrupt / SA_RESTART). */ int num_restart; /** The number of ignore handlers. */ int num_ignore; /** The number of specific handlers. */ int num_specific; /** The number of threads masking it. */ int num_masked; } g_sig_state[NSIG]; int shmtx_init(shmtx *pmtx) { pmtx->b[0] = 0; return 0; } void shmtx_delete(shmtx *pmtx) { pmtx->b[0] = 0; } void shmtx_enter(shmtx *pmtx, shmtxtmp *ptmp) { pmtx->b[0] = 0; ptmp->i = 0; } void shmtx_leave(shmtx *pmtx, shmtxtmp *ptmp) { pmtx->b[0] = 0; ptmp->i = 432; } /** * Links the shell instance. * * @param psh The shell. */ static void sh_int_link(shinstance *psh) { shmtxtmp tmp; shmtx_enter(&g_sh_mtx, &tmp); if (psh->rootshell) g_sh_root = psh; psh->next = NULL; psh->prev = g_sh_tail; if (g_sh_tail) g_sh_tail->next = psh; else g_sh_tail = g_sh_head = psh; g_sh_tail = psh; g_num_shells++; shmtx_leave(&g_sh_mtx, &tmp); } #if 0 /** * Unlink the shell instance. * * @param psh The shell. */ static void sh_int_unlink(shinstance *psh) { shmtxtmp tmp; shmtx_enter(&g_sh_mtx, &tmp); g_num_shells--; if (g_sh_tail == psh) g_sh_tail = psh->prev; else psh->next->prev = psh->prev; if (g_sh_head == psh) g_sh_head = psh->next; else psh->prev->next = psh->next; if (g_sh_root == psh) g_sh_root = 0; shmtx_leave(&g_sh_mtx, &tmp); } #endif /** * Destroys the shell instance. * * This will work on partially initialized instances (because I'm lazy). * * @param psh The shell instance to be destroyed. */ static void sh_destroy(shinstance *psh) { memset(psh, 0, sizeof(*psh)); sh_free(NULL, psh); } /** * Clones a string vector like enviorn or argv. * * @returns 0 on success, -1 and errno on failure. * @param psh The shell to associate the allocations with. * @param dstp Where to store the clone. * @param src The vector to be cloned. */ static int sh_clone_string_vector(shinstance *psh, char ***dstp, char **src) { char **dst; size_t items; /* count first */ items = 0; while (src[items]) items++; /* alloc clone array. */ *dstp = dst = sh_malloc(psh, sizeof(*dst) * items + 1); if (!dst) return -1; /* copy the items */ dst[items] = NULL; while (items-- > 0) { dst[items] = sh_strdup(psh, src[items]); if (!dst[items]) { /* allocation error, clean up. */ while (dst[++items]) sh_free(psh, dst[items]); sh_free(psh, dst); errno = ENOMEM; return -1; } } return 0; } /** * Creates a root shell instance. * * @param inherit The shell to inherit from. If NULL inherit from environment and such. * @param argc The argument count. * @param argv The argument vector. * @param envp The environment vector. * * @returns pointer to root shell on success, NULL on failure. */ shinstance *sh_create_root_shell(shinstance *inherit, int argc, char **argv, char **envp) { shinstance *psh; int i; /* * The allocations. */ psh = sh_calloc(NULL, sizeof(*psh), 1); if (psh) { /* Init it enought for sh_destroy() to not get upset */ /* ... */ /* Call the basic initializers. */ if ( !sh_clone_string_vector(psh, &psh->shenviron, envp) && !sh_clone_string_vector(psh, &psh->argptr, argv) && !shfile_init(&psh->fdtab, inherit ? &inherit->fdtab : NULL)) { /* the special stuff. */ #ifdef _MSC_VER psh->pid = _getpid(); #else psh->pid = getpid(); #endif /*sh_sigemptyset(&psh->sigrestartset);*/ for (i = 0; i < NSIG; i++) psh->sigactions[i].sh_handler = SH_SIG_UNK; if (inherit) psh->sigmask = psh->sigmask; else { #if defined(_MSC_VER) sh_sigemptyset(&psh->sigmask); #else sigprocmask(SIG_SETMASK, NULL, &psh->sigmask); #endif } /* memalloc.c */ psh->stacknleft = MINSIZE; psh->herefd = -1; psh->stackp = &psh->stackbase; psh->stacknxt = psh->stackbase.space; /* input.c */ psh->plinno = 1; psh->init_editline = 0; psh->parsefile = &psh->basepf; /* output.c */ psh->output.bufsize = OUTBUFSIZ; psh->output.fd = 1; psh->output.psh = psh; psh->errout.bufsize = 100; psh->errout.fd = 2; psh->errout.psh = psh; psh->memout.fd = MEM_OUT; psh->memout.psh = psh; psh->out1 = &psh->output; psh->out2 = &psh->errout; /* jobs.c */ psh->backgndpid = -1; #if JOBS psh->curjob = -1; #else # error asdf #endif psh->ttyfd = -1; /* show.c */ psh->tracefd = -1; /* link it. */ sh_int_link(psh); return psh; } sh_destroy(psh); } return NULL; } /** getenv() */ char *sh_getenv(shinstance *psh, const char *var) { size_t len; int i = 0; if (!var) return NULL; len = strlen(var); i = 0; while (psh->shenviron[i]) { const char *item = psh->shenviron[i]; if ( !strncmp(item, var, len) && item[len] == '=') return (char *)item + len + 1; } return NULL; } char **sh_environ(shinstance *psh) { return psh->shenviron; } const char *sh_gethomedir(shinstance *psh, const char *user) { const char *ret = NULL; #ifdef _MSC_VER ret = sh_getenv(psh, "HOME"); if (!ret) ret = sh_getenv(psh, "USERPROFILE"); #else struct passwd *pwd = getpwnam(user); /** @todo use getpwdnam_r */ (void)psh; ret = pwd ? pwd->pw_dir : NULL; #endif return ret; } /** * Lazy initialization of a signal state, globally. * * @param psh The shell doing the lazy work. * @param signo The signal (valid). */ static void sh_int_lazy_init_sigaction(shinstance *psh, int signo) { if (psh->sigactions[signo].sh_handler == SH_SIG_UNK) { shmtxtmp tmp; shmtx_enter(&g_sh_mtx, &tmp); if (psh->sigactions[signo].sh_handler == SH_SIG_UNK) { shsigaction_t shold; shinstance *cur; #ifndef _MSC_VER struct sigaction old; if (!sigaction(signo, NULL, &old)) { /* convert */ shold.sh_flags = old.sa_flags; shold.sh_mask = old.sa_mask; if (old.sa_handler == SIG_DFL) shold.sh_handler = SH_SIG_DFL; else { assert(old.sa_handler == SIG_IGN); shold.sh_handler = SH_SIG_IGN; } } else #endif { /* fake */ #ifndef _MSC_VER assert(0); old.sa_handler = SIG_DFL; old.sa_flags = 0; sigemptyset(&shold.sh_mask); sigaddset(&shold.sh_mask, signo); #endif shold.sh_flags = 0; sh_sigemptyset(&shold.sh_mask); sh_sigaddset(&shold.sh_mask, signo); shold.sh_handler = SH_SIG_DFL; } /* update globals */ #ifndef _MSC_VER g_sig_state[signo].sa = old; #else g_sig_state[signo].sa.sa_handler = SIG_DFL; g_sig_state[signo].sa.sa_flags = 0; g_sig_state[signo].sa.sa_mask = shold.sh_mask; #endif TRACE2((psh, "sh_int_lazy_init_sigaction: signo=%d:%s sa_handler=%p sa_flags=%#x\n", signo, sys_signame[signo], g_sig_state[signo].sa.sa_handler, g_sig_state[signo].sa.sa_flags)); /* update all shells */ for (cur = g_sh_head; cur; cur = cur->next) { assert(cur->sigactions[signo].sh_handler == SH_SIG_UNK); cur->sigactions[signo] = shold; } } shmtx_leave(&g_sh_mtx, &tmp); } } /** * Perform the default signal action on the shell. * * @param psh The shell instance. * @param signo The signal. */ static void sh_sig_do_default(shinstance *psh, int signo) { /** @todo */ } /** * Deliver a signal to a shell. * * @param psh The shell instance. * @param pshDst The shell instance to signal. * @param signo The signal. * @param locked Whether we're owning the lock or not. */ static void sh_sig_do_signal(shinstance *psh, shinstance *pshDst, int signo, int locked) { shsig_t pfn = pshDst->sigactions[signo].sh_handler; if (pfn == SH_SIG_UNK) { sh_int_lazy_init_sigaction(pshDst, signo); pfn = pshDst->sigactions[signo].sh_handler; } if (pfn == SH_SIG_DFL) sh_sig_do_default(pshDst, signo); else if (pfn == SH_SIG_IGN) /* ignore it */; else { assert(pfn != SH_SIG_ERR); pfn(pshDst, signo); } (void)locked; } /** * Handler for external signals. * * @param signo The signal. */ static void sh_sig_common_handler(int signo) { shinstance *psh; /* fprintf(stderr, "sh_sig_common_handler: signo=%d:%s\n", signo, sys_signame[signo]); */ /* * No need to take locks if there is only one shell. * Since this will be the initial case, just avoid the deadlock * hell for a litte while... */ if (g_num_shells <= 1) { psh = g_sh_head; if (psh) sh_sig_do_signal(NULL, psh, signo, 0 /* no lock */); } else { shmtxtmp tmp; shmtx_enter(&g_sh_mtx, &tmp); /** @todo signal focus chain or something? Atm there will only be one shell, * so it's not really important until we go threaded for real... */ psh = g_sh_tail; while (psh != NULL) { sh_sig_do_signal(NULL, psh, signo, 1 /* locked */); psh = psh->prev; } shmtx_leave(&g_sh_mtx, &tmp); } } int sh_sigaction(shinstance *psh, int signo, const struct shsigaction *newp, struct shsigaction *oldp) { if (newp) TRACE2((psh, "sh_sigaction: signo=%d:%s newp=%p:{.sh_handler=%p, .sh_flags=%#x} oldp=%p\n", signo, sys_signame[signo], newp, newp->sh_handler, newp->sh_flags, oldp)); else TRACE2((psh, "sh_sigaction: signo=%d:%s newp=NULL oldp=%p\n", signo, sys_signame[signo], oldp)); /* * Input validation. */ if (signo >= NSIG || signo <= 0) { errno = EINVAL; return -1; } /* * Make sure our data is correct. */ sh_int_lazy_init_sigaction(psh, signo); /* * Get the old one if requested. */ if (oldp) *oldp = psh->sigactions[signo]; /* * Set the new one if it has changed. * * This will be attempted coordinated with the other signal handlers so * that we can arrive at a common denominator. */ if ( newp && memcmp(&psh->sigactions[signo], newp, sizeof(*newp))) { shmtxtmp tmp; shmtx_enter(&g_sh_mtx, &tmp); /* Undo the accounting for the current entry. */ if (psh->sigactions[signo].sh_handler == SH_SIG_IGN) g_sig_state[signo].num_ignore--; else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL) g_sig_state[signo].num_specific--; if (psh->sigactions[signo].sh_flags & SA_RESTART) g_sig_state[signo].num_restart--; /* Set the new entry. */ psh->sigactions[signo] = *newp; /* Add the bits for the new action entry. */ if (psh->sigactions[signo].sh_handler == SH_SIG_IGN) g_sig_state[signo].num_ignore++; else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL) g_sig_state[signo].num_specific++; if (psh->sigactions[signo].sh_flags & SA_RESTART) g_sig_state[signo].num_restart++; /* * Calc new common action. * * This is quit a bit ASSUMPTIVE about the limited use. We will not * bother synching the mask, and we pretend to care about SA_RESTART. * The only thing we really actually care about is the sh_handler. * * On second though, it's possible we should just tie this to the root * shell since it only really applies to external signal ... */ if ( g_sig_state[signo].num_specific || g_sig_state[signo].num_ignore != g_num_shells) g_sig_state[signo].sa.sa_handler = sh_sig_common_handler; else if (g_sig_state[signo].num_ignore) g_sig_state[signo].sa.sa_handler = SIG_IGN; else g_sig_state[signo].sa.sa_handler = SIG_DFL; g_sig_state[signo].sa.sa_flags = psh->sigactions[signo].sh_flags & SA_RESTART; #if !defined(HAVE_SYS_SIGNAME) && defined(DEBUG) init_sys_signame(); #endif TRACE2((psh, "sh_sigaction: setting signo=%d:%s to {.sa_handler=%p, .sa_flags=%#x}\n", signo, sys_signame[signo], g_sig_state[signo].sa.sa_handler, g_sig_state[signo].sa.sa_flags)); #ifdef _MSC_VER if (signal(signo, g_sig_state[signo].sa.sa_handler) == SIG_ERR) { TRACE2((psh, "sh_sigaction: SIG_ERR, errno=%d signo=%d\n", errno, signo)); if ( signo != SIGHUP /* whatever */ && signo != SIGQUIT && signo != SIGPIPE && signo != SIGTTIN && signo != SIGTSTP && signo != SIGTTOU && signo != SIGCONT) assert(0); } #else if (sigaction(signo, &g_sig_state[signo].sa, NULL)) assert(0); #endif shmtx_leave(&g_sh_mtx, &tmp); } return 0; } shsig_t sh_signal(shinstance *psh, int signo, shsig_t handler) { shsigaction_t sa; shsig_t ret; /* * Implementation using sh_sigaction. */ if (sh_sigaction(psh, signo, NULL, &sa)) return SH_SIG_ERR; ret = sa.sh_handler; sa.sh_flags &= SA_RESTART; sa.sh_handler = handler; sh_sigemptyset(&sa.sh_mask); sh_sigaddset(&sa.sh_mask, signo); /* ?? */ if (sh_sigaction(psh, signo, &sa, NULL)) return SH_SIG_ERR; return ret; } int sh_siginterrupt(shinstance *psh, int signo, int interrupt) { shsigaction_t sa; int oldflags = 0; /* * Implementation using sh_sigaction. */ if (sh_sigaction(psh, signo, NULL, &sa)) return -1; oldflags = sa.sh_flags; if (interrupt) sa.sh_flags &= ~SA_RESTART; else sa.sh_flags |= ~SA_RESTART; if (!((oldflags ^ sa.sh_flags) & SA_RESTART)) return 0; /* unchanged. */ return sh_sigaction(psh, signo, &sa, NULL); } void sh_sigemptyset(shsigset_t *setp) { memset(setp, 0, sizeof(*setp)); } void sh_sigfillset(shsigset_t *setp) { memset(setp, 0xff, sizeof(*setp)); } void sh_sigaddset(shsigset_t *setp, int signo) { #ifdef _MSC_VER *setp |= 1U << signo; #else sigaddset(setp, signo); #endif } void sh_sigdelset(shsigset_t *setp, int signo) { #ifdef _MSC_VER *setp &= ~(1U << signo); #else sigdelset(setp, signo); #endif } int sh_sigismember(shsigset_t const *setp, int signo) { #ifdef _MSC_VER return !!(*setp & (1U << signo)); #else return !!sigismember(setp, signo); #endif } int sh_sigprocmask(shinstance *psh, int operation, shsigset_t const *newp, shsigset_t *oldp) { int rc; if ( operation != SIG_BLOCK && operation != SIG_UNBLOCK && operation != SIG_SETMASK) { errno = EINVAL; return -1; } #if defined(SH_FORKED_MODE) && !defined(_MSC_VER) rc = sigprocmask(operation, newp, oldp); if (!rc && newp) psh->sigmask = *newp; #else if (oldp) *oldp = psh->sigmask; if (newp) { /* calc the new mask */ shsigset_t mask = psh->sigmask; switch (operation) { case SIG_BLOCK: for (rc = 0; rc < NSIG; rc++) if (sh_sigismember(newp, rc)) sh_sigaddset(&mask, rc); break; case SIG_UNBLOCK: for (rc = 0; rc < NSIG; rc++) if (sh_sigismember(newp, rc)) sh_sigdelset(&mask, rc); break; case SIG_SETMASK: mask = *newp; break; } # if defined(_MSC_VER) rc = 0; # else rc = sigprocmask(operation, &mask, NULL); if (!rc) # endif psh->sigmask = mask; } #endif return rc; } SH_NORETURN_1 void sh_abort(shinstance *psh) { shsigset_t set; TRACE2((psh, "sh_abort\n")); /* block other async signals */ sh_sigfillset(&set); sh_sigdelset(&set, SIGABRT); sh_sigprocmask(psh, SIG_SETMASK, &set, NULL); sh_sig_do_signal(psh, psh, SIGABRT, 0 /* no lock */); /** @todo die in a nicer manner. */ *(char *)1 = 3; TRACE2((psh, "sh_abort returns!\n")); (void)psh; abort(); } void sh_raise_sigint(shinstance *psh) { TRACE2((psh, "sh_raise(SIGINT)\n")); sh_sig_do_signal(psh, psh, SIGINT, 0 /* no lock */); TRACE2((psh, "sh_raise(SIGINT) returns\n")); } int sh_kill(shinstance *psh, pid_t pid, int signo) { shinstance *pshDst; shmtxtmp tmp; int rc; /* * Self or any of the subshells? */ shmtx_enter(&g_sh_mtx, &tmp); pshDst = g_sh_tail; while (pshDst != NULL) { if (pshDst->pid == pid) { TRACE2((psh, "sh_kill(%d, %d): pshDst=%p\n", pid, signo, pshDst)); sh_sig_do_signal(psh, pshDst, signo, 1 /* locked */); shmtx_leave(&g_sh_mtx, &tmp); return 0; } pshDst = pshDst->prev; } shmtx_leave(&g_sh_mtx, &tmp); /* * Some other process, call kill where possible */ #if defined(SH_FORKED_MODE) # ifdef _MSC_VER errno = ENOSYS; rc = -1; # else /* fprintf(stderr, "kill(%d, %d)\n", pid, signo);*/ rc = kill(pid, signo); # endif #else #endif TRACE2((psh, "sh_kill(%d, %d) -> %d [%d]\n", pid, signo, rc, errno)); return rc; } int sh_killpg(shinstance *psh, pid_t pgid, int signo) { int rc; #if defined(SH_FORKED_MODE) # ifdef _MSC_VER errno = ENOSYS; rc = -1; # else //fprintf(stderr, "killpg(%d, %d)\n", pgid, signo); rc = killpg(pgid, signo); # endif #else #endif TRACE2((psh, "sh_killpg(%d, %d) -> %d [%d]\n", pgid, signo, rc, errno)); (void)psh; return rc; } clock_t sh_times(shinstance *psh, shtms *tmsp) { #if defined(SH_FORKED_MODE) (void)psh; # ifdef _MSC_VER errno = ENOSYS; return (clock_t)-1; # else return times(tmsp); # endif #else #endif } int sh_sysconf_clk_tck(void) { #ifdef _MSC_VER return CLK_TCK; #else return sysconf(_SC_CLK_TCK); #endif } /** * Adds a child to the shell * * @returns 0 on success, on failure -1 and errno set to ENOMEM. * * @param psh The shell instance. * @param pid The child pid. * @param hChild Windows child handle. */ int sh_add_child(shinstance *psh, pid_t pid, void *hChild) { /* get a free table entry. */ int i = psh->num_children++; if (!(i % 32)) { void *ptr = sh_realloc(psh, psh->children, sizeof(*psh->children) * (i + 32)); if (!ptr) { psh->num_children--; errno = ENOMEM; return -1; } psh->children = ptr; } /* add it */ psh->children[i].pid = pid; #if K_OS == K_OS_WINDOWS psh->children[i].hChild = hChild; #endif (void)hChild; return 0; } pid_t sh_fork(shinstance *psh) { pid_t pid; TRACE2((psh, "sh_fork\n")); #if K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE) pid = shfork_do(psh); #elif defined(SH_FORKED_MODE) # ifdef _MSC_VER pid = -1; errno = ENOSYS; # else pid = fork(); # endif #else #endif /* child: update the pid */ if (!pid) # ifdef _MSC_VER psh->pid = _getpid(); # else psh->pid = getpid(); # endif TRACE2((psh, "sh_fork -> %d [%d]\n", pid, errno)); (void)psh; return pid; } /** waitpid() */ pid_t sh_waitpid(shinstance *psh, pid_t pid, int *statusp, int flags) { pid_t pidret; #if K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE) DWORD dwRet; HANDLE hChild = INVALID_HANDLE_VALUE; int i; *statusp = 0; pidret = -1; if (pid != -1) { /* * A specific child, try look it up in the child process table * and wait for it. */ for (i = 0; i < psh->num_children; i++) if (psh->children[i].pid == pid) break; if (i < psh->num_children) { dwRet = WaitForSingleObject(psh->children[i].hChild, flags & WNOHANG ? 0 : INFINITE); if (dwRet == WAIT_OBJECT_0) hChild = psh->children[i].hChild; else if (dwRet == WAIT_TIMEOUT) { i = -1; /* don't try close anything */ pidret = 0; } else errno = ECHILD; } else errno = ECHILD; } else if (psh->num_children <= MAXIMUM_WAIT_OBJECTS) { HANDLE ahChildren[64]; for (i = 0; i < psh->num_children; i++) ahChildren[i] = psh->children[i].hChild; dwRet = WaitForMultipleObjects(psh->num_children, &ahChildren[0], FALSE, flags & WNOHANG ? 0 : INFINITE); i = dwRet - WAIT_OBJECT_0; if ((unsigned)i < (unsigned)psh->num_children) { hChild = psh->children[i].hChild; } else if (dwRet == WAIT_TIMEOUT) { i = -1; /* don't try close anything */ pidret = 0; } else { i = -1; /* don't try close anything */ errno = EINVAL; } } else { fprintf(stderr, "panic! too many children!\n"); i = -1; *(char *)1 = '\0'; /** @todo implement this! */ } /* * Close the handle, and if we succeeded collect the exit code first. */ if ( i >= 0 && i < psh->num_children) { if (hChild != INVALID_HANDLE_VALUE) { DWORD dwExitCode = 127; if (GetExitCodeProcess(hChild, &dwExitCode)) { pidret = psh->children[i].pid; if (dwExitCode && !W_EXITCODE(dwExitCode, 0)) dwExitCode |= 16; *statusp = W_EXITCODE(dwExitCode, 0); } else errno = EINVAL; } /* remove and close */ hChild = psh->children[i].hChild; psh->num_children--; if (i < psh->num_children) psh->children[i] = psh->children[psh->num_children]; i = CloseHandle(hChild); assert(i); } #elif defined(SH_FORKED_MODE) *statusp = 0; # ifdef _MSC_VER pidret = -1; errno = ENOSYS; # else pidret = waitpid(pid, statusp, flags); # endif #else #endif TRACE2((psh, "waitpid(%d, %p, %#x) -> %d [%d] *statusp=%#x (rc=%d)\n", pid, statusp, flags, pidret, errno, *statusp, WEXITSTATUS(*statusp))); (void)psh; return pidret; } SH_NORETURN_1 void sh__exit(shinstance *psh, int rc) { TRACE2((psh, "sh__exit(%d)\n", rc)); (void)psh; #if defined(SH_FORKED_MODE) _exit(rc); #else #endif } int sh_execve(shinstance *psh, const char *exe, const char * const *argv, const char * const *envp) { int rc; #ifdef DEBUG /* log it all */ TRACE2((psh, "sh_execve(%p:{%s}, %p, %p}\n", exe, exe, argv, envp)); for (rc = 0; argv[rc]; rc++) TRACE2((psh, " argv[%d]=%p:{%s}\n", rc, argv[rc], argv[rc])); #endif if (!envp) envp = (const char * const *)sh_environ(psh); #if defined(SH_FORKED_MODE) && K_OS != K_OS_WINDOWS # ifdef _MSC_VER errno = 0; { intptr_t rc2 = _spawnve(_P_WAIT, exe, (char **)argv, (char **)envp); if (rc2 != -1) { TRACE2((psh, "sh_execve: child exited, rc=%d. (errno=%d)\n", rc, errno)); rc = (int)rc2; if (!rc && rc2) rc = 16; exit(rc); } } rc = -1; # else rc = shfile_exec_unix(&psh->fdtab); if (!rc) rc = execve(exe, (char **)argv, (char **)envp); # endif #else # if K_OS == K_OS_WINDOWS { /* * This ain't quite straight forward on Windows... */ PROCESS_INFORMATION ProcInfo; STARTUPINFO StrtInfo; intptr_t hndls[3]; char *cwd = shfile_getcwd(&psh->fdtab, NULL, 0); char *cmdline; size_t cmdline_size; char *envblock; size_t env_size; char *p; int i; /* Create the environment block. */ if (!envp) envp = sh_environ(psh); env_size = 2; for (i = 0; envp[i]; i++) env_size += strlen(envp[i]) + 1; envblock = p = sh_malloc(psh, env_size); for (i = 0; envp[i]; i++) { size_t len = strlen(envp[i]) + 1; memcpy(p, envp[i], len); p += len; } *p = '\0'; /* Create the command line. */ cmdline_size = 2; for (i = 0; argv[i]; i++) cmdline_size += strlen(argv[i]) + 3; cmdline = p = sh_malloc(psh, cmdline_size); for (i = 0; argv[i]; i++) { size_t len = strlen(argv[i]); int quoted = !!strpbrk(argv[i], " \t"); /** @todo Do this quoting business right. */ if (i != 0) *(p++) = ' '; if (quoted) *(p++) = '"'; memcpy(p, argv[i], len); p += len; if (quoted) *(p++) = '"'; } p[0] = p[1] = '\0'; /* Init the info structure */ memset(&StrtInfo, '\0', sizeof(StrtInfo)); StrtInfo.cb = sizeof(StrtInfo); /* File handles. */ StrtInfo.dwFlags |= STARTF_USESTDHANDLES; StrtInfo.lpReserved2 = shfile_exec_win(&psh->fdtab, 1 /* prepare */, &StrtInfo.cbReserved2, hndls); StrtInfo.hStdInput = (HANDLE)hndls[0]; StrtInfo.hStdOutput = (HANDLE)hndls[1]; StrtInfo.hStdError = (HANDLE)hndls[2]; /* Get going... */ if (CreateProcess(exe, cmdline, NULL, /* pProcessAttributes */ NULL, /* pThreadAttributes */ TRUE, /* bInheritHandles */ 0, /* dwCreationFlags */ envblock, cwd, &StrtInfo, &ProcInfo)) { DWORD dwErr; DWORD dwExitCode; CloseHandle(ProcInfo.hThread); dwErr = WaitForSingleObject(ProcInfo.hProcess, INFINITE); assert(dwErr == WAIT_OBJECT_0); if (GetExitCodeProcess(ProcInfo.hProcess, &dwExitCode)) { CloseHandle(ProcInfo.hProcess); _exit(dwExitCode); } errno = EINVAL; } else { DWORD dwErr = GetLastError(); switch (dwErr) { case ERROR_FILE_NOT_FOUND: errno = ENOENT; break; case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_BAD_EXE_FORMAT: errno = ENOEXEC; break; case ERROR_INVALID_EXE_SIGNATURE: errno = ENOEXEC; break; default: errno = EINVAL; break; } TRACE2((psh, "sh_execve: dwErr=%d -> errno=%d\n", dwErr, errno)); } shfile_exec_win(&psh->fdtab, 0 /* done */, NULL, NULL); } rc = -1; # else errno = ENOSYS; rc = -1; # endif #endif TRACE2((psh, "sh_execve -> %d [%d]\n", rc, errno)); (void)psh; return (int)rc; } uid_t sh_getuid(shinstance *psh) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER uid_t uid = 0; # else uid_t uid = getuid(); # endif #else #endif TRACE2((psh, "sh_getuid() -> %d [%d]\n", uid, errno)); (void)psh; return uid; } uid_t sh_geteuid(shinstance *psh) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER uid_t euid = 0; # else uid_t euid = geteuid(); # endif #else #endif TRACE2((psh, "sh_geteuid() -> %d [%d]\n", euid, errno)); (void)psh; return euid; } gid_t sh_getgid(shinstance *psh) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER gid_t gid = 0; # else gid_t gid = getgid(); # endif #else #endif TRACE2((psh, "sh_getgid() -> %d [%d]\n", gid, errno)); (void)psh; return gid; } gid_t sh_getegid(shinstance *psh) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER gid_t egid = 0; # else gid_t egid = getegid(); # endif #else #endif TRACE2((psh, "sh_getegid() -> %d [%d]\n", egid, errno)); (void)psh; return egid; } pid_t sh_getpid(shinstance *psh) { pid_t pid; #if defined(SH_FORKED_MODE) # ifdef _MSC_VER pid = _getpid(); # else pid = getpid(); # endif #else #endif (void)psh; return pid; } pid_t sh_getpgrp(shinstance *psh) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER pid_t pgrp = _getpid(); # else pid_t pgrp = getpgrp(); # endif #else #endif TRACE2((psh, "sh_getpgrp() -> %d [%d]\n", pgrp, errno)); (void)psh; return pgrp; } pid_t sh_getpgid(shinstance *psh, pid_t pid) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER pid_t pgid = pid; # else pid_t pgid = getpgid(pid); # endif #else #endif TRACE2((psh, "sh_getpgid(%d) -> %d [%d]\n", pid, pgid, errno)); (void)psh; return pgid; } int sh_setpgid(shinstance *psh, pid_t pid, pid_t pgid) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER int rc = -1; errno = ENOSYS; # else int rc = setpgid(pid, pgid); # endif #else #endif TRACE2((psh, "sh_setpgid(%d, %d) -> %d [%d]\n", pid, pgid, rc, errno)); (void)psh; return rc; } pid_t sh_tcgetpgrp(shinstance *psh, int fd) { pid_t pgrp; #if defined(SH_FORKED_MODE) # ifdef _MSC_VER pgrp = -1; errno = ENOSYS; # else pgrp = tcgetpgrp(fd); # endif #else #endif TRACE2((psh, "sh_tcgetpgrp(%d) -> %d [%d]\n", fd, pgrp, errno)); (void)psh; return pgrp; } int sh_tcsetpgrp(shinstance *psh, int fd, pid_t pgrp) { int rc; TRACE2((psh, "sh_tcsetpgrp(%d, %d)\n", fd, pgrp)); #if defined(SH_FORKED_MODE) # ifdef _MSC_VER rc = -1; errno = ENOSYS; # else rc = tcsetpgrp(fd, pgrp); # endif #else #endif TRACE2((psh, "sh_tcsetpgrp(%d, %d) -> %d [%d]\n", fd, pgrp, rc, errno)); (void)psh; return rc; } int sh_getrlimit(shinstance *psh, int resid, shrlimit *limp) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER int rc = -1; errno = ENOSYS; # else int rc = getrlimit(resid, limp); # endif #else /* returned the stored limit */ #endif TRACE2((psh, "sh_getrlimit(%d, %p) -> %d [%d] {%ld,%ld}\n", resid, limp, rc, errno, (long)limp->rlim_cur, (long)limp->rlim_max)); (void)psh; return rc; } int sh_setrlimit(shinstance *psh, int resid, const shrlimit *limp) { #if defined(SH_FORKED_MODE) # ifdef _MSC_VER int rc = -1; errno = ENOSYS; # else int rc = setrlimit(resid, limp); # endif #else /* if max(shell) < limp; then setrlimit; fi if success; then store limit for later retrival and maxing. */ #endif TRACE2((psh, "sh_setrlimit(%d, %p:{%ld,%ld}) -> %d [%d]\n", resid, limp, (long)limp->rlim_cur, (long)limp->rlim_max, rc, errno)); (void)psh; return rc; } /* Wrapper for strerror that makes sure it doesn't return NULL and causes the caller or fprintf routines to crash. */ const char *sh_strerror(shinstance *psh, int error) { char *err = strerror(error); if (!err) return "strerror return NULL!"; (void)psh; return err; } kbuild-2695/src/kash/init.h0000644000000000000000000000354212247157307014276 0ustar rootroot/* $NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)init.h 8.2 (Berkeley) 5/4/95 */ void init(struct shinstance *); void reset(struct shinstance *); void initshellproc(struct shinstance *); kbuild-2695/src/kash/var.h0000644000000000000000000001234112247157307014120 0ustar rootroot/* $NetBSD: var.h,v 1.23 2004/10/02 12:16:53 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)var.h 8.2 (Berkeley) 5/4/95 */ #ifndef ___var_h___ #define ___var_h___ /* * Shell variables. */ /* flags */ #define VEXPORT 0x01 /* variable is exported */ #define VREADONLY 0x02 /* variable cannot be modified */ #define VSTRFIXED 0x04 /* variable struct is statically allocated */ #define VTEXTFIXED 0x08 /* text is statically allocated */ #define VSTACK 0x10 /* text is allocated on the stack */ #define VUNSET 0x20 /* the variable is not set */ #define VNOFUNC 0x40 /* don't call the callback function */ #define VNOSET 0x80 /* do not set variable - just readonly test */ #ifdef PC_OS2_LIBPATHS #define VOS2LIBPATH 0x8000 /* OS/2 LIBPATH related variable. */ #endif struct var { struct var *next; /* next entry in hash list */ int flags; /* flags are defined above */ char *text; /* name=value */ int name_len; /* length of name */ void (*func)(struct shinstance *, const char *); /* function to be called when */ /* the variable gets set/unset */ }; struct localvar { struct localvar *next; /* next local variable in list */ struct var *vp; /* the variable that was made local */ int flags; /* saved flags */ char *text; /* saved text */ }; /* struct localvar *localvars; #if ATTY extern struct var vatty; #endif extern struct var vifs; extern struct var vmail; extern struct var vmpath; extern struct var vpath; #ifdef _MSC_VER extern struct var vpath2; #endif extern struct var vps1; extern struct var vps2; extern struct var vps4; #ifndef SMALL extern struct var vterm; extern struct var vtermcap; extern struct var vhistsize; #endif */ /* * The following macros access the values of the above variables. * They have to skip over the name. They return the null string * for unset variables. */ #define ifsval(psh) ((psh)->vifs.text + 4) #define ifsset(psh) (((psh)->vifs.flags & VUNSET) == 0) #define mailval(psh) ((psh)->vmail.text + 5) #define mpathval(psh) ((psh)->vmpath.text + 9) #ifdef _MSC_VER # define pathval(psh) ((psh)->vpath.text[5] || !(psh)->vpath2.text ? &(psh)->vpath.text[5] : &(psh)->vpath2.text[5]) #else # define pathval(psh) ((psh)->vpath.text + 5) #endif #define ps1val(psh) ((psh)->vps1.text + 4) #define ps2val(psh) ((psh)->vps2.text + 4) #define ps4val(psh) ((psh)->vps4.text + 4) #define optindval(psh) ((psh)->voptind.text + 7) #ifndef SMALL #define histsizeval(psh) ((psh)->vhistsize.text + 9) #define termval(psh) ((psh)->vterm.text + 5) #endif #if ATTY #define attyset(psh) (((psh)->vatty.flags & VUNSET) == 0) #endif #define mpathset(psh) (((psh)->vmpath.flags & VUNSET) == 0) void initvar(struct shinstance *); void setvar(struct shinstance *, const char *, const char *, int); void setvareq(struct shinstance *, char *, int); struct strlist; void listsetvar(struct shinstance *, struct strlist *, int); char *lookupvar(struct shinstance *, const char *); char *bltinlookup(struct shinstance *, const char *, int); char **environment(struct shinstance *); void shprocvar(struct shinstance *); int showvars(struct shinstance *, const char *, int, int); int exportcmd(struct shinstance *, int, char **); int localcmd(struct shinstance *, int, char **); void mklocal(struct shinstance *, const char *, int); void listmklocal(struct shinstance *, struct strlist *, int); void poplocalvars(struct shinstance *); int setvarcmd(struct shinstance *, int, char **); int unsetcmd(struct shinstance *, int, char **); int unsetvar(struct shinstance *, const char *, int); int setvarsafe(struct shinstance *, const char *, const char *, int); void print_quoted(struct shinstance *, const char *); #endif kbuild-2695/src/kash/mail.c0000644000000000000000000000722512247157307014252 0ustar rootroot/* $NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $"); #endif /* not lint */ #endif /* * Routines to check for mail. (Perhaps make part of main.c?) */ #include #include #include "shell.h" #include "exec.h" /* defines padvance() */ #include "var.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "mail.h" #include "shinstance.h" /*#define MAXMBOXES 10*/ /*STATIC int nmboxes;*/ /* number of mailboxes */ /*STATIC time_t mailtime[MAXMBOXES];*/ /* times of mailboxes */ /* * Print appropriate message(s) if mail has arrived. If the argument is * nozero, then the value of MAIL has changed, so we just update the * values. */ void chkmail(shinstance *psh, int silent) { int i; const char *mpath; char *p; char *q; struct stackmark smark; struct stat statb; if (silent) psh->nmboxes = 10; if (psh->nmboxes == 0) return; setstackmark(psh, &smark); mpath = mpathset(psh) ? mpathval(psh) : mailval(psh); for (i = 0 ; i < psh->nmboxes ; i++) { p = padvance(psh, &mpath, nullstr); if (p == NULL) break; if (*p == '\0') continue; for (q = p ; *q ; q++); if (q[-1] != '/') sh_abort(psh); q[-1] = '\0'; /* delete trailing '/' */ #ifdef notdef /* this is what the System V shell claims to do (it lies) */ if (shfile_stat(&psh->fdtab, p, &statb) < 0) statb.st_mtime = 0; if (statb.st_mtime > psh->mailtime[i] && ! silent) { out2str(psh, psh->pathopt ? psh->pathopt : "you have mail"); out2c(psh, '\n'); } psh->mailtime[i] = statb.st_mtime; #else /* this is what it should do */ if (shfile_stat(&psh->fdtab, p, &statb) < 0) statb.st_size = 0; if (statb.st_size > psh->mailtime[i] && ! silent) { out2str(psh, psh->pathopt ? psh->pathopt : "you have mail"); out2c(psh, '\n'); } psh->mailtime[i] = statb.st_size; #endif } psh->nmboxes = i; popstackmark(psh, &smark); } kbuild-2695/src/kash/shthread.c0000644000000000000000000000544112247157307015130 0ustar rootroot/* $Id: shthread.c 2498 2011-07-22 12:05:57Z bird $ */ /** @file * * Shell Thread Management. * * Copyright (c) 2007-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "shthread.h" #include "shinstance.h" #include #if K_OS == K_OS_WINDOWS # include #elif K_OS == K_OS_OS2 # include # include #else # include #endif /******************************************************************************* * Global Variables * *******************************************************************************/ #if K_OS == K_OS_WINDOWS static DWORD sh_tls = TLS_OUT_OF_INDEXES; #elif K_OS == K_OS_OS2 static int sh_tls = -1; #else static int sh_tls_inited = 0; static pthread_key_t sh_tls; #endif /** * Stores the shell instance pointer in a TLS entry. * * This will allocate the TLS entry on the first call. We assume * there will no be races at that time. * * @param psh The shell instance. */ void shthread_set_shell(struct shinstance *psh) { #if K_OS == K_OS_WINDOWS if (sh_tls == TLS_OUT_OF_INDEXES) { sh_tls = TlsAlloc(); assert(sh_tls != TLS_OUT_OF_INDEXES); } if (!TlsSetValue(sh_tls, psh)) assert(0); #elif K_OS == K_OS_OS2 if (sh_tls == -1) { sh_tls = __libc_TLSAlloc(); assert(sh_tls != -1); } if (__libc_TLSSet(sh_tls, psh) == -1) assert(0); #else if (!sh_tls_inited) { if (pthread_key_create(&sh_tls, NULL) != 0) assert(0); sh_tls_inited = 1; } if (pthread_setspecific(sh_tls, psh) != 0) assert(0); #endif } /** * Get the shell instance pointer from TLS. * * @returns The shell instance. */ struct shinstance *shthread_get_shell(void) { shinstance *psh; #if K_OS == K_OS_WINDOWS psh = (shinstance *)TlsGetValue(sh_tls); #elif K_OS == K_OS_OS2 psh = (shinstance *)__libc_TLSGet(sh_tls); #else psh = (shinstance *)pthread_getspecific(sh_tls); #endif return psh; } kbuild-2695/src/kash/exec.c0000644000000000000000000007013512247157307014254 0ustar rootroot/* $NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; #else __RCSID("$NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $"); #endif /* not lint */ #endif #include #include #include #include /* * When commands are first encountered, they are entered in a hash table. * This ensures that a full path search will not have to be done for them * on each invocation. * * We should investigate converting to a linear search, even though that * would make the command name "hash" a misnomer. */ #include "shell.h" #include "main.h" #include "nodes.h" #include "parser.h" #include "redir.h" #include "eval.h" #include "exec.h" #include "builtins.h" #include "var.h" #include "options.h" #include "input.h" #include "output.h" #include "syntax.h" #include "memalloc.h" #include "error.h" #include "init.h" #include "mystring.h" #include "show.h" #include "jobs.h" #include "alias.h" #ifdef __INNOTEK_LIBC__ #include #endif #include "shinstance.h" //#define CMDTABLESIZE 31 /* should be prime */ //#define ARB 1 /* actual size determined at run time */ // // // //struct tblentry { // struct tblentry *next; /* next entry in hash chain */ // union param param; /* definition of builtin function */ // short cmdtype; /* index identifying command */ // char rehash; /* if set, cd done since entry created */ // char cmdname[ARB]; /* name of command */ //}; // // //STATIC struct tblentry *cmdtable[CMDTABLESIZE]; //STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */ //int exerrno = 0; /* Last exec error */ STATIC void tryexec(shinstance *, char *, char **, char **, int, int); STATIC void execinterp(shinstance *, char **, char **); STATIC void printentry(shinstance *, struct tblentry *, int); STATIC void clearcmdentry(shinstance *, int); STATIC struct tblentry *cmdlookup(shinstance *, const char *, int); STATIC void delete_cmd_entry(shinstance *); #ifdef PC_EXE_EXTS STATIC int stat_pc_exec_exts(shinstance *, char *fullname, struct stat *st, int has_ext); #endif extern char *const parsekwd[]; /* * Exec a program. Never returns. If you change this routine, you may * have to change the find_command routine as well. */ SH_NORETURN_1 void shellexec(shinstance *psh, char **argv, char **envp, const char *path, int idx, int vforked) { char *cmdname; int e; #ifdef PC_EXE_EXTS int has_ext = (int)strlen(argv[0]) - 4; has_ext = has_ext > 0 && argv[0][has_ext] == '.' /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */ && strstr("exe;" "Exe;" "EXe;" "EXE;" "ExE;" "eXe;" "eXE;" "exE;" "cmd;" "Cmd;" "CMd;" "CMD;" "CmD;" "cMd;" "cMD;" "cmD;" "com;" "Com;" "COm;" "COM;" "CoM;" "cOm;" "cOM;" "coM;" "bat;" "Bat;" "BAt;" "BAT;" "BaT;" "bAt;" "bAT;" "baT;" "btm;" "Btm;" "BTm;" "BTM;" "BtM;" "bTm;" "bTM;" "btM;", argv[0] + has_ext + 1) != NULL; #else const int has_ext = 1; #endif TRACE((psh, "shellexec: argv[0]=%s idx=%d\n", argv[0], idx)); if (strchr(argv[0], '/') != NULL) { cmdname = stalloc(psh, strlen(argv[0]) + 5); strcpy(cmdname, argv[0]); tryexec(psh, cmdname, argv, envp, vforked, has_ext); TRACE((psh, "shellexec: cmdname=%s\n", cmdname)); stunalloc(psh, cmdname); e = errno; } else { e = ENOENT; while ((cmdname = padvance(psh, &path, argv[0])) != NULL) { if (--idx < 0 && psh->pathopt == NULL) { tryexec(psh, cmdname, argv, envp, vforked, has_ext); if (errno != ENOENT && errno != ENOTDIR) e = errno; } stunalloc(psh, cmdname); } } /* Map to POSIX errors */ switch (e) { case EACCES: psh->exerrno = 126; break; case ENOENT: psh->exerrno = 127; break; default: psh->exerrno = 2; break; } TRACE((psh, "shellexec failed for '%s', errno %d, vforked %d, suppressint %d\n", argv[0], e, vforked, psh->suppressint )); exerror(psh, EXEXEC, "%s: %s", argv[0], errmsg(psh, e, E_EXEC)); /* NOTREACHED */ } STATIC void tryexec(shinstance *psh, char *cmd, char **argv, char **envp, int vforked, int has_ext) { int e; #ifdef EXEC_HASH_BANG_SCRIPT char *p; #endif #ifdef PC_EXE_EXTS /* exploit the effect of stat_pc_exec_exts which adds the * correct extentions to the file. */ struct stat st; if (!has_ext) stat_pc_exec_exts(psh, cmd, &st, 0); #endif #if defined(__INNOTEK_LIBC__) && defined(EXEC_HASH_BANG_SCRIPT) __libc_Back_gfProcessHandleHashBangScripts = 0; #endif #ifdef SYSV do { sh_execve(psh, cmd, argv, envp); } while (errno == EINTR); #else sh_execve(psh, cmd, (const char * const*)argv, (const char * const*)envp); #endif e = errno; if (e == ENOEXEC) { if (vforked) { /* We are currently vfork(2)ed, so raise an * exception, and evalcommand will try again * with a normal fork(2). */ exraise(psh, EXSHELLPROC); } initshellproc(psh); setinputfile(psh, cmd, 0); psh->commandname = psh->arg0 = savestr(psh, argv[0]); #ifdef EXEC_HASH_BANG_SCRIPT pgetc(psh); pungetc(psh); /* fill up input buffer */ p = psh->parsenextc; if (psh->parsenleft > 2 && p[0] == '#' && p[1] == '!') { argv[0] = cmd; execinterp(psh, argv, envp); } #endif setparam(psh, argv + 1); exraise(psh, EXSHELLPROC); } errno = e; } #ifdef EXEC_HASH_BANG_SCRIPT /* * Checks if NAME is the (base) name of the shell executable or something * very similar. */ STATIC int is_shell_exe_name(const char *name) { return equal(name, "kmk_ash") || equal(name, "kmk_sh") || equal(name, "kash") || equal(name, "sh"); } /* * Execute an interpreter introduced by "#!", for systems where this * feature has not been built into the kernel. If the interpreter is * the shell, return (effectively ignoring the "#!"). If the execution * of the interpreter fails, exit. * * This code peeks inside the input buffer in order to avoid actually * reading any input. It would benefit from a rewrite. */ #define NEWARGS 16 STATIC void execinterp(shinstance *psh, char **argv, char **envp) { int n; char *inp; char *outp; char c; char *p; char **ap; char *newargs[NEWARGS]; intptr_t i; char **ap2; char **new; /* Split the string into arguments. */ n = psh->parsenleft - 2; inp = psh->parsenextc + 2; ap = newargs; for (;;) { while (--n >= 0 && (*inp == ' ' || *inp == '\t')) inp++; if (n < 0) goto bad; if ((c = *inp++) == '\n') break; if (ap == &newargs[NEWARGS]) bad: error(psh, "Bad #! line"); STARTSTACKSTR(psh, outp); do { STPUTC(psh, c, outp); } while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n'); STPUTC(psh, '\0', outp); n++, inp--; *ap++ = grabstackstr(psh, outp); } /* /usr/bin/env emulation, very common with kash/kmk_ash. */ i = ap - newargs; if (i > 1 && equal(newargs[0], "/usr/bin/env")) { if ( !strchr(newargs[1], '=') && newargs[1][0] != '-') { /* shellexec below searches the PATH for us, so just drop /usr/bin/env. */ TRACE((psh, "hash bang /usr/bin/env utility, dropping /usr/bin/env\n")); ap--; i--; for (n = 0; n < i; n++) newargs[n] = newargs[n + 1]; } /* else: complicated invocation */ } /* If the interpreter is the shell or a similar shell, there is no need to exec. */ if (i == 1) { p = strrchr(newargs[0], '/'); if (!p) p = newargs[0]; if (is_shell_exe_name(p)) { TRACE((psh, "hash bang self\n")); return; } } /* Combine the two argument lists and exec. */ i = (char *)ap - (char *)newargs; /* size in bytes */ if (i == 0) error(psh, "Bad #! line"); for (ap2 = argv ; *ap2++ != NULL ; ); new = ckmalloc(psh, i + ((char *)ap2 - (char *)argv)); ap = newargs, ap2 = new; while ((i -= sizeof (char **)) >= 0) *ap2++ = *ap++; ap = argv; while ((*ap2++ = *ap++)) /* nothing*/; TRACE((psh, "hash bang '%s'\n", new[0])); shellexec(psh, new, envp, pathval(psh), 0, 0); /* NOTREACHED */ } #endif /* EXEC_HASH_BANG_SCRIPT */ /* * Do a path search. The variable path (passed by reference) should be * set to the start of the path before the first call; padvance will update * this value as it proceeds. Successive calls to padvance will return * the possible path expansions in sequence. If an option (indicated by * a percent sign) appears in the path entry then the global variable * psh->pathopt will be set to point to it; otherwise psh->pathopt will be set to * NULL. */ //const char *pathopt; char * padvance(shinstance *psh, const char **path, const char *name) { const char *p; char *q; const char *start; int len; if (*path == NULL) return NULL; start = *path; #ifdef PC_PATH_SEP for (p = start ; *p && *p != ';' && *p != '%' ; p++); #else for (p = start ; *p && *p != ':' && *p != '%' ; p++); #endif len = (int)(p - start + strlen(name) + 2); /* "2" is for '/' and '\0' */ #ifdef PC_EXE_EXTS len += 4; /* "4" is for .exe/.com/.cmd/.bat/.btm */ #endif while (stackblocksize(psh) < len) growstackblock(psh); q = stackblock(psh); if (p != start) { memcpy(q, start, p - start); q += p - start; *q++ = '/'; } strcpy(q, name); psh->pathopt = NULL; if (*p == '%') { psh->pathopt = ++p; #ifdef PC_PATH_SEP while (*p && *p != ';') p++; #else while (*p && *p != ':') p++; #endif } #ifdef PC_PATH_SEP if (*p == ';') #else if (*p == ':') #endif *path = p + 1; else *path = NULL; return stalloc(psh, len); } #ifdef PC_EXE_EXTS STATIC int stat_pc_exec_exts(shinstance *psh, char *fullname, struct stat *st, int has_ext) { /* skip the SYSV crap */ if (shfile_stat(&psh->fdtab, fullname, st) >= 0) return 0; if (!has_ext && errno == ENOENT) { char *psz = strchr(fullname, '\0'); memcpy(psz, ".exe", 5); if (shfile_stat(&psh->fdtab, fullname, st) >= 0) return 0; if (errno != ENOENT && errno != ENOTDIR) return -1; memcpy(psz, ".cmd", 5); if (shfile_stat(&psh->fdtab, fullname, st) >= 0) return 0; if (errno != ENOENT && errno != ENOTDIR) return -1; memcpy(psz, ".bat", 5); if (shfile_stat(&psh->fdtab, fullname, st) >= 0) return 0; if (errno != ENOENT && errno != ENOTDIR) return -1; memcpy(psz, ".com", 5); if (shfile_stat(&psh->fdtab, fullname, st) >= 0) return 0; if (errno != ENOENT && errno != ENOTDIR) return -1; memcpy(psz, ".btm", 5); if (shfile_stat(&psh->fdtab, fullname, st) >= 0) return 0; *psz = '\0'; } return -1; } #endif /* PC_EXE_EXTS */ /*** Command hashing code ***/ int hashcmd(shinstance *psh, int argc, char **argv) { struct tblentry **pp; struct tblentry *cmdp; int c; int verbose; struct cmdentry entry; char *name; verbose = 0; while ((c = nextopt(psh, "rv")) != '\0') { if (c == 'r') { clearcmdentry(psh, 0); } else if (c == 'v') { verbose++; } } if (*psh->argptr == NULL) { for (pp = psh->cmdtable ; pp < &psh->cmdtable[CMDTABLESIZE] ; pp++) { for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { if (verbose || cmdp->cmdtype == CMDNORMAL) printentry(psh, cmdp, verbose); } } return 0; } while ((name = *psh->argptr) != NULL) { if ((cmdp = cmdlookup(psh, name, 0)) != NULL && (cmdp->cmdtype == CMDNORMAL || (cmdp->cmdtype == CMDBUILTIN && psh->builtinloc >= 0))) delete_cmd_entry(psh); find_command(psh, name, &entry, DO_ERR, pathval(psh)); if (verbose) { if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */ cmdp = cmdlookup(psh, name, 0); printentry(psh, cmdp, verbose); } output_flushall(psh); } psh->argptr++; } return 0; } STATIC void printentry(shinstance *psh, struct tblentry *cmdp, int verbose) { int idx; const char *path; char *name; switch (cmdp->cmdtype) { case CMDNORMAL: idx = cmdp->param.index; path = pathval(psh); do { name = padvance(psh, &path, cmdp->cmdname); stunalloc(psh, name); } while (--idx >= 0); out1str(psh, name); break; case CMDSPLBLTIN: out1fmt(psh, "special builtin %s", cmdp->cmdname); break; case CMDBUILTIN: out1fmt(psh, "builtin %s", cmdp->cmdname); break; case CMDFUNCTION: out1fmt(psh, "function %s", cmdp->cmdname); if (verbose) { struct procstat ps; INTOFF; commandtext(psh, &ps, cmdp->param.func); INTON; out1str(psh, "() { "); out1str(psh, ps.cmd); out1str(psh, "; }"); } break; default: error(psh, "internal error: %s cmdtype %d", cmdp->cmdname, cmdp->cmdtype); } if (cmdp->rehash) out1c(psh, '*'); out1c(psh, '\n'); } /* * Resolve a command name. If you change this routine, you may have to * change the shellexec routine as well. */ void find_command(shinstance *psh, char *name, struct cmdentry *entry, int act, const char *path) { struct tblentry *cmdp, loc_cmd; int idx; int prev; char *fullname; struct stat statb; int e; int (*bltin)(shinstance*,int,char **); #ifdef PC_EXE_EXTS int has_ext = (int)(strlen(name) - 4); has_ext = has_ext > 0 && name[has_ext] == '.' /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */ && strstr("exe;" "Exe;" "EXe;" "EXE;" "ExE;" "eXe;" "eXE;" "exE;" "cmd;" "Cmd;" "CMd;" "CMD;" "CmD;" "cMd;" "cMD;" "cmD;" "com;" "Com;" "COm;" "COM;" "CoM;" "cOm;" "cOM;" "coM;" "bat;" "Bat;" "BAt;" "BAT;" "BaT;" "bAt;" "bAT;" "baT;" "btm;" "Btm;" "BTm;" "BTM;" "BtM;" "bTm;" "bTM;" "btM;", name + has_ext + 1) != NULL; #endif /* If name contains a slash, don't use PATH or hash table */ if (strchr(name, '/') != NULL) { if (act & DO_ABS) { while (shfile_stat(&psh->fdtab, name, &statb) < 0) { #ifdef SYSV if (errno == EINTR) continue; #endif if (errno != ENOENT && errno != ENOTDIR) e = errno; entry->cmdtype = CMDUNKNOWN; entry->u.index = -1; return; } entry->cmdtype = CMDNORMAL; entry->u.index = -1; return; } entry->cmdtype = CMDNORMAL; entry->u.index = 0; return; } if (path != pathval(psh)) act |= DO_ALTPATH; if (act & DO_ALTPATH && strstr(path, "%builtin") != NULL) act |= DO_ALTBLTIN; /* If name is in the table, check answer will be ok */ if ((cmdp = cmdlookup(psh, name, 0)) != NULL) { do { switch (cmdp->cmdtype) { case CMDNORMAL: if (act & DO_ALTPATH) { cmdp = NULL; continue; } break; case CMDFUNCTION: if (act & DO_NOFUNC) { cmdp = NULL; continue; } break; case CMDBUILTIN: if ((act & DO_ALTBLTIN) || psh->builtinloc >= 0) { cmdp = NULL; continue; } break; } /* if not invalidated by cd, we're done */ if (cmdp->rehash == 0) goto success; } while (0); } /* If %builtin not in path, check for builtin next */ if ((act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : psh->builtinloc < 0) && (bltin = find_builtin(psh, name)) != 0) goto builtin_success; /* We have to search path. */ prev = -1; /* where to start */ if (cmdp) { /* doing a rehash */ if (cmdp->cmdtype == CMDBUILTIN) prev = psh->builtinloc; else prev = cmdp->param.index; } e = ENOENT; idx = -1; loop: while ((fullname = padvance(psh, &path, name)) != NULL) { stunalloc(psh, fullname); idx++; if (psh->pathopt) { if (prefix("builtin", psh->pathopt)) { if ((bltin = find_builtin(psh, name)) == 0) goto loop; goto builtin_success; } else if (prefix("func", psh->pathopt)) { /* handled below */ } else { /* ignore unimplemented options */ goto loop; } } /* if rehash, don't redo absolute path names */ if (fullname[0] == '/' && idx <= prev) { if (idx < prev) goto loop; TRACE((psh, "searchexec \"%s\": no change\n", name)); goto success; } #ifdef PC_EXE_EXTS while (stat_pc_exec_exts(psh, fullname, &statb, has_ext) < 0) { #else while (shfile_stat(&psh->fdtab, fullname, &statb) < 0) { #endif #ifdef SYSV if (errno == EINTR) continue; #endif if (errno != ENOENT && errno != ENOTDIR) e = errno; goto loop; } e = EACCES; /* if we fail, this will be the error */ if (!S_ISREG(statb.st_mode)) goto loop; if (psh->pathopt) { /* this is a %func directory */ if (act & DO_NOFUNC) goto loop; stalloc(psh, strlen(fullname) + 1); readcmdfile(psh, fullname); if ((cmdp = cmdlookup(psh, name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION) error(psh, "%s not defined in %s", name, fullname); stunalloc(psh, fullname); goto success; } #ifdef notdef /* XXX this code stops root executing stuff, and is buggy if you need a group from the group list. */ if (statb.st_uid == sh_geteuid(psh)) { if ((statb.st_mode & 0100) == 0) goto loop; } else if (statb.st_gid == sh_getegid(psh)) { if ((statb.st_mode & 010) == 0) goto loop; } else { if ((statb.st_mode & 01) == 0) goto loop; } #endif TRACE((psh, "searchexec \"%s\" returns \"%s\"\n", name, fullname)); INTOFF; if (act & DO_ALTPATH) { stalloc(psh, strlen(fullname) + 1); cmdp = &loc_cmd; } else cmdp = cmdlookup(psh, name, 1); cmdp->cmdtype = CMDNORMAL; cmdp->param.index = idx; INTON; goto success; } /* We failed. If there was an entry for this command, delete it */ if (cmdp) delete_cmd_entry(psh); if (act & DO_ERR) outfmt(psh->out2, "%s: %s\n", name, errmsg(psh, e, E_EXEC)); entry->cmdtype = CMDUNKNOWN; return; builtin_success: INTOFF; if (act & DO_ALTPATH) cmdp = &loc_cmd; else cmdp = cmdlookup(psh, name, 1); if (cmdp->cmdtype == CMDFUNCTION) /* DO_NOFUNC must have been set */ cmdp = &loc_cmd; cmdp->cmdtype = CMDBUILTIN; cmdp->param.bltin = bltin; INTON; success: cmdp->rehash = 0; entry->cmdtype = cmdp->cmdtype; entry->u = cmdp->param; } /* * Search the table of builtin commands. */ int (*find_builtin(shinstance *psh, char *name))(shinstance *psh, int, char **) { const struct builtincmd *bp; for (bp = builtincmd ; bp->name ; bp++) { if (*bp->name == *name && equal(bp->name, name)) return bp->builtin; } return 0; } int (*find_splbltin(shinstance *psh, char *name))(shinstance *psh, int, char **) { const struct builtincmd *bp; for (bp = splbltincmd ; bp->name ; bp++) { if (*bp->name == *name && equal(bp->name, name)) return bp->builtin; } return 0; } /* * At shell startup put special builtins into hash table. * ensures they are executed first (see posix). * We stop functions being added with the same name * (as they are impossible to call) */ void hash_special_builtins(shinstance *psh) { const struct builtincmd *bp; struct tblentry *cmdp; for (bp = splbltincmd ; bp->name ; bp++) { cmdp = cmdlookup(psh, bp->name, 1); cmdp->cmdtype = CMDSPLBLTIN; cmdp->param.bltin = bp->builtin; } } /* * Called when a cd is done. Marks all commands so the next time they * are executed they will be rehashed. */ void hashcd(shinstance *psh) { struct tblentry **pp; struct tblentry *cmdp; for (pp = psh->cmdtable ; pp < &psh->cmdtable[CMDTABLESIZE] ; pp++) { for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { if (cmdp->cmdtype == CMDNORMAL || (cmdp->cmdtype == CMDBUILTIN && psh->builtinloc >= 0)) cmdp->rehash = 1; } } } /* * Fix command hash table when PATH changed. * Called before PATH is changed. The argument is the new value of PATH; * pathval(psh) still returns the old value at this point. * Called with interrupts off. */ void changepath(shinstance *psh, const char *newval) { const char *old, *new; int idx; int firstchange; int bltin; old = pathval(psh); new = newval; firstchange = 9999; /* assume no change */ idx = 0; bltin = -1; for (;;) { if (*old != *new) { firstchange = idx; #ifdef PC_PATH_SEP if ((*old == '\0' && *new == ';') || (*old == ';' && *new == '\0')) #else if ((*old == '\0' && *new == ':') || (*old == ':' && *new == '\0')) #endif firstchange++; old = new; /* ignore subsequent differences */ } if (*new == '\0') break; if (*new == '%' && bltin < 0 && prefix("builtin", new + 1)) bltin = idx; #ifdef PC_PATH_SEP if (*new == ';') { #else if (*new == ':') { #endif idx++; } new++, old++; } if (psh->builtinloc < 0 && bltin >= 0) psh->builtinloc = bltin; /* zap builtins */ if (psh->builtinloc >= 0 && bltin < 0) firstchange = 0; clearcmdentry(psh, firstchange); psh->builtinloc = bltin; } /* * Clear out command entries. The argument specifies the first entry in * PATH which has changed. */ STATIC void clearcmdentry(shinstance *psh, int firstchange) { struct tblentry **tblp; struct tblentry **pp; struct tblentry *cmdp; INTOFF; for (tblp = psh->cmdtable ; tblp < &psh->cmdtable[CMDTABLESIZE] ; tblp++) { pp = tblp; while ((cmdp = *pp) != NULL) { if ((cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange) || (cmdp->cmdtype == CMDBUILTIN && psh->builtinloc >= firstchange)) { *pp = cmdp->next; ckfree(psh, cmdp); } else { pp = &cmdp->next; } } } INTON; } /* * Delete all functions. */ #ifdef mkinit MKINIT void deletefuncs(struct shinstance *); MKINIT void hash_special_builtins(struct shinstance *); INIT { hash_special_builtins(psh); } SHELLPROC { deletefuncs(psh); } #endif void deletefuncs(shinstance *psh) { struct tblentry **tblp; struct tblentry **pp; struct tblentry *cmdp; INTOFF; for (tblp = psh->cmdtable ; tblp < &psh->cmdtable[CMDTABLESIZE] ; tblp++) { pp = tblp; while ((cmdp = *pp) != NULL) { if (cmdp->cmdtype == CMDFUNCTION) { *pp = cmdp->next; freefunc(psh, cmdp->param.func); ckfree(psh, cmdp); } else { pp = &cmdp->next; } } } INTON; } /* * Locate a command in the command hash table. If "add" is nonzero, * add the command to the table if it is not already present. The * variable "lastcmdentry" is set to point to the address of the link * pointing to the entry, so that delete_cmd_entry can delete the * entry. */ struct tblentry **lastcmdentry; STATIC struct tblentry * cmdlookup(shinstance *psh, const char *name, int add) { int hashval; const char *p; struct tblentry *cmdp; struct tblentry **pp; p = name; hashval = *p << 4; while (*p) hashval += *p++; hashval &= 0x7FFF; pp = &psh->cmdtable[hashval % CMDTABLESIZE]; for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { if (equal(cmdp->cmdname, name)) break; pp = &cmdp->next; } if (add && cmdp == NULL) { INTOFF; cmdp = *pp = ckmalloc(psh, sizeof (struct tblentry) - ARB + strlen(name) + 1); cmdp->next = NULL; cmdp->cmdtype = CMDUNKNOWN; cmdp->rehash = 0; strcpy(cmdp->cmdname, name); INTON; } lastcmdentry = pp; return cmdp; } /* * Delete the command entry returned on the last lookup. */ STATIC void delete_cmd_entry(shinstance *psh) { struct tblentry *cmdp; INTOFF; cmdp = *lastcmdentry; *lastcmdentry = cmdp->next; ckfree(psh, cmdp); INTON; } #ifdef notdef void getcmdentry(shinstance *psh, char *name, struct cmdentry *entry) { struct tblentry *cmdp = cmdlookup(psh, name, 0); if (cmdp) { entry->u = cmdp->param; entry->cmdtype = cmdp->cmdtype; } else { entry->cmdtype = CMDUNKNOWN; entry->u.index = 0; } } #endif /* * Add a new command entry, replacing any existing command entry for * the same name - except special builtins. */ STATIC void addcmdentry(shinstance *psh, char *name, struct cmdentry *entry) { struct tblentry *cmdp; INTOFF; cmdp = cmdlookup(psh, name, 1); if (cmdp->cmdtype != CMDSPLBLTIN) { if (cmdp->cmdtype == CMDFUNCTION) { freefunc(psh, cmdp->param.func); } cmdp->cmdtype = entry->cmdtype; cmdp->param = entry->u; } INTON; } /* * Define a shell function. */ void defun(shinstance *psh, char *name, union node *func) { struct cmdentry entry; INTOFF; entry.cmdtype = CMDFUNCTION; entry.u.func = copyfunc(psh, func); addcmdentry(psh, name, &entry); INTON; } /* * Delete a function if it exists. */ int unsetfunc(shinstance *psh, char *name) { struct tblentry *cmdp; if ((cmdp = cmdlookup(psh, name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { freefunc(psh, cmdp->param.func); delete_cmd_entry(psh); return (0); } return (1); } /* * Locate and print what a word is... * also used for 'command -[v|V]' */ int typecmd(shinstance *psh, int argc, char **argv) { struct cmdentry entry; struct tblentry *cmdp; char * const *pp; struct alias *ap; int err = 0; char *arg; int c; int V_flag = 0; int v_flag = 0; int p_flag = 0; while ((c = nextopt(psh, "vVp")) != 0) { switch (c) { case 'v': v_flag = 1; break; case 'V': V_flag = 1; break; case 'p': p_flag = 1; break; } } if (p_flag && (v_flag || V_flag)) error(psh, "cannot specify -p with -v or -V"); while ((arg = *psh->argptr++)) { if (!v_flag) out1str(psh, arg); /* First look at the keywords */ for (pp = parsekwd; *pp; pp++) if (**pp == *arg && equal(*pp, arg)) break; if (*pp) { if (v_flag) err = 1; else out1str(psh, " is a shell keyword\n"); continue; } /* Then look at the aliases */ if ((ap = lookupalias(psh, arg, 1)) != NULL) { if (!v_flag) out1fmt(psh, " is an alias for \n"); out1fmt(psh, "%s\n", ap->val); continue; } /* Then check if it is a tracked alias */ if ((cmdp = cmdlookup(psh, arg, 0)) != NULL) { entry.cmdtype = cmdp->cmdtype; entry.u = cmdp->param; } else { /* Finally use brute force */ find_command(psh, arg, &entry, DO_ABS, pathval(psh)); } switch (entry.cmdtype) { case CMDNORMAL: { if (strchr(arg, '/') == NULL) { const char *path = pathval(psh); char *name; int j = entry.u.index; do { name = padvance(psh, &path, arg); stunalloc(psh, name); } while (--j >= 0); if (!v_flag) out1fmt(psh, " is%s ", cmdp ? " a tracked alias for" : ""); out1fmt(psh, "%s\n", name); } else { if (shfile_access(&psh->fdtab, arg, X_OK) == 0) { if (!v_flag) out1fmt(psh, " is "); out1fmt(psh, "%s\n", arg); } else { if (!v_flag) out1fmt(psh, ": %s\n", sh_strerror(psh, errno)); else err = 126; } } break; } case CMDFUNCTION: if (!v_flag) out1str(psh, " is a shell function\n"); else out1fmt(psh, "%s\n", arg); break; case CMDBUILTIN: if (!v_flag) out1str(psh, " is a shell builtin\n"); else out1fmt(psh, "%s\n", arg); break; case CMDSPLBLTIN: if (!v_flag) out1str(psh, " is a special shell builtin\n"); else out1fmt(psh, "%s\n", arg); break; default: if (!v_flag) out1str(psh, ": not found\n"); err = 127; break; } } return err; } kbuild-2695/src/kash/shfork-win.c0000644000000000000000000002270512247157307015417 0ustar rootroot /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include "shinstance.h" #include /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** The stack size. This is also defined in shforkA-win.asm. */ #define SHFORK_STACK_SIZE (1*1024*1024) /******************************************************************************* * Global Variables * *******************************************************************************/ static void *g_stack_base = 0; static void *g_stack_limit = 0; /******************************************************************************* * Internal Functions * *******************************************************************************/ static void *shfork_string_to_ptr(const char *str, const char *argv0, const char *what); /* in shforkA-win.asm: */ extern pid_t shfork_do_it(shinstance *psh); extern void shfork_resume(void *cur, void *base, void *limit); /* called by shforkA-win.asm: */ void *shfork_maybe_forked(int argc, char **argv, char **envp); extern int shfork_body(shinstance *psh, void *stack_ptr); extern void init_syntax(void); /** * Called by shforkA-win.asm to check whether we're a forked child * process or not. * * In the former case we will resume execution at the fork resume * point. In the latter we'll allocate a new stack of the forkable * heap and return it to the caller so real_main() in main.c can be * invoked on it. * * @returns Stack or not at all. * @param argc Argument count. * @param argv Argument vector. * @param envp Environment vector. */ void *shfork_maybe_forked(int argc, char **argv, char **envp) { void *stack_ptr; /* * Are we actually forking? */ if ( argc != 8 || strcmp(argv[1], "--!forked!--") || strcmp(argv[2], "--stack-address") || strcmp(argv[4], "--stack-base") || strcmp(argv[6], "--stack-limit")) { char *stack; shheap_init(NULL); g_stack_limit = stack = (char *)sh_malloc(NULL, SHFORK_STACK_SIZE); g_stack_base = stack += SHFORK_STACK_SIZE; return stack; } /* * Do any init that needs to be done before resuming the * fork() call. */ setlocale(LC_ALL, ""); /* * Convert the stack addresses. */ stack_ptr = shfork_string_to_ptr(argv[3], argv[0], "--stack-address"); g_stack_base = shfork_string_to_ptr(argv[5], argv[0], "--stack-base"); g_stack_limit = shfork_string_to_ptr(argv[7], argv[0], "--stack-limit"); assert((uintptr_t)stack_ptr < (uintptr_t)g_stack_base); assert((uintptr_t)stack_ptr > (uintptr_t)g_stack_limit); /* * Switch stack and jump to the fork resume point. */ shfork_resume(stack_ptr, g_stack_base, g_stack_limit); /* (won't get here) */ return NULL; } /*** * Converts a string into a pointer. * * @returns Pointer. * @param argv0 The program name in case of error. * @param str The string to convert. */ static void *shfork_string_to_ptr(const char *str, const char *argv0, const char *what) { const char *start = str; intptr_t ptr = 0; if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) str += 2; while (*str) { unsigned digit; switch (*str) { case '0': digit = 0; break; case '1': digit = 1; break; case '2': digit = 2; break; case '3': digit = 3; break; case '4': digit = 4; break; case '5': digit = 5; break; case '6': digit = 6; break; case '7': digit = 7; break; case '8': digit = 8; break; case '9': digit = 9; break; case 'a': case 'A': digit = 0xa; break; case 'b': case 'B': digit = 0xb; break; case 'c': case 'C': digit = 0xc; break; case 'd': case 'D': digit = 0xd; break; case 'e': case 'E': digit = 0xe; break; case 'f': case 'F': digit = 0xf; break; default: fprintf(stderr, "%s: fatal error: Invalid %s '%s'\n", argv0, what, start); exit(2); } ptr <<= 4; ptr |= digit; str++; } return (void *)ptr; } /** * Do the fork. * @returns same as fork(). * @param psh The shell that's forking. */ int shfork_do(shinstance *psh) { /* save globals */ void *pheap_head = shheap_get_head(); pid_t pid = shfork_do_it(psh); if (pid == 0) { /* reinit stuff, only the heap is copied! */ shthread_set_shell(psh); shheap_init(pheap_head); setlocale(LC_ALL, ""); init_syntax(); } return pid; } /** * Create the child process making sure it inherits all our handles, * copy of the forkable heap and kick it off. * * Called by shfork_do_it() in shforkA-win.asm. * * @returns child pid on success, -1 and errno on failure. * @param psh The shell that's forking. * @param stack_ptr The stack address at which the guest is suppost to resume. */ int shfork_body(shinstance *psh, void *stack_ptr) { PROCESS_INFORMATION ProcInfo; STARTUPINFO StrtInfo; intptr_t hndls[3]; char szExeName[1024]; char szCmdLine[1024+256]; DWORD cch; int rc = 0; assert((uintptr_t)stack_ptr < (uintptr_t)g_stack_base); assert((uintptr_t)stack_ptr > (uintptr_t)g_stack_limit); /* * Mark all handles inheritable and get the three standard handles. */ shfile_fork_win(&psh->fdtab, 1 /* set */, &hndls[0]); /* * Create the process. */ cch = GetModuleFileName(GetModuleHandle(NULL), szExeName, sizeof(szExeName)); if (cch > 0) { #if 0 /* quoting the program name doesn't seems to be working :/ */ szCmdLine[0] = '"'; memcpy(&szCmdLine[1], szExeName, cch); szCmdLine[++cch] = '"'; #else memcpy(&szCmdLine[0], szExeName, cch); #endif cch += sprintf(&szCmdLine[cch], " --!forked!-- --stack-address %p --stack-base %p --stack-limit %p", stack_ptr, g_stack_base, g_stack_limit); szCmdLine[cch+1] = '\0'; TRACE2((NULL, "shfork_body: szCmdLine=%s\n", szCmdLine)); memset(&StrtInfo, '\0', sizeof(StrtInfo)); /* just in case. */ StrtInfo.cb = sizeof(StrtInfo); StrtInfo.lpReserved = NULL; StrtInfo.lpDesktop = NULL; StrtInfo.lpTitle = NULL; StrtInfo.dwX = 0; StrtInfo.dwY = 0; StrtInfo.dwXSize = 0; StrtInfo.dwYSize = 0; StrtInfo.dwXCountChars = 0; StrtInfo.dwYCountChars = 0; StrtInfo.dwFillAttribute = 0; StrtInfo.dwFlags = STARTF_USESTDHANDLES;; StrtInfo.wShowWindow = 0; StrtInfo.cbReserved2 = 0; StrtInfo.lpReserved2 = NULL; StrtInfo.hStdInput = (HANDLE)hndls[0]; StrtInfo.hStdOutput = (HANDLE)hndls[1]; StrtInfo.hStdError = (HANDLE)hndls[2]; if (CreateProcess(szExeName, szCmdLine, NULL, /* pProcessAttributes */ NULL, /* pThreadAttributes */ TRUE, /* bInheritHandles */ CREATE_SUSPENDED, NULL, /* pEnvironment */ NULL, /* pCurrentDirectory */ &StrtInfo, &ProcInfo)) { /* * Copy the memory to the child. */ rc = shheap_fork_copy_to_child(ProcInfo.hProcess); if (!rc) { if (ResumeThread(ProcInfo.hThread) != (DWORD)-1) { rc = sh_add_child(psh, ProcInfo.dwProcessId, ProcInfo.hProcess); if (!rc) rc = (int)ProcInfo.dwProcessId; } else { DWORD dwErr = GetLastError(); fprintf(stderr, "shfork: ResumeThread() -> %d\n", dwErr); errno = EINVAL; rc = -1; } } if (rc == -1) { TerminateProcess(ProcInfo.hProcess, 127); /* needed?: ResumeThread(ProcInfo.hThread); */ CloseHandle(ProcInfo.hProcess); } CloseHandle(ProcInfo.hThread); } else { DWORD dwErr = GetLastError(); fprintf(stderr, "shfork: CreateProcess(%s) -> %d\n", szExeName, dwErr); errno = EINVAL; rc = -1; } } else { DWORD dwErr = GetLastError(); fprintf(stderr, "shfork: GetModuleFileName() -> %d\n", dwErr); errno = EINVAL; rc = -1; } /* * Restore the handle inherit property. */ shfile_fork_win(&psh->fdtab, 0 /* restore */, NULL); return rc; } kbuild-2695/src/kash/expand.h0000644000000000000000000000561712247157307014617 0ustar rootroot/* $NetBSD: expand.h,v 1.16 2004/07/13 15:05:59 seb Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)expand.h 8.2 (Berkeley) 5/4/95 */ #ifndef ___expand_h #define ___expand_h #include "shtypes.h" struct strlist { struct strlist *next; char *text; }; struct arglist { struct strlist *list; struct strlist **lastp; }; /* * expandarg() flags */ #define EXP_FULL 0x1 /* perform word splitting & file globbing */ #define EXP_TILDE 0x2 /* do normal tilde expansion */ #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ #define EXP_IFS_SPLIT 0x20 /* need to record arguments for ifs breakup */ union node; void expandhere(struct shinstance *, union node *, int); void expandarg(struct shinstance *, union node *, struct arglist *, int); void expari(struct shinstance *, int); int patmatch(struct shinstance *, char *, char *, int); void rmescapes(struct shinstance *, char *); int casematch(struct shinstance *, union node *, char *); int wordexpcmd(struct shinstance *, int, char **); /* From arith.y */ int arith(struct shinstance *, const char *); int expcmd(struct shinstance *, int , char **); void arith_lex_reset(void); int yylex(void); #endif kbuild-2695/src/kash/jobs.c0000644000000000000000000007615512247157307014275 0ustar rootroot/* $NetBSD: jobs.c,v 1.63 2005/06/01 15:41:19 lukem Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: jobs.c,v 1.63 2005/06/01 15:41:19 lukem Exp $"); #endif /* not lint */ #endif #include #include #include #include #include "shell.h" #if JOBS && !defined(_MSC_VER) # include #endif #include "redir.h" #include "show.h" #include "main.h" #include "parser.h" #include "nodes.h" #include "jobs.h" #include "options.h" #include "trap.h" #include "syntax.h" #include "input.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "mystring.h" #include "shinstance.h" //static struct job *jobtab; /* array of jobs */ //static int njobs; /* size of array */ //static int jobs_invalid; /* set in child */ //MKINIT pid_t backgndpid = -1; /* pid of last background process */ #if JOBS //int initialpgrp; /* pgrp of shell on invocation */ //static int curjob = -1; /* current job */ #endif //static int ttyfd = -1; STATIC void restartjob(shinstance *, struct job *); STATIC void freejob(shinstance *, struct job *); STATIC struct job *getjob(shinstance *, const char *, int); STATIC int dowait(shinstance *, int, struct job *); STATIC int waitproc(shinstance *, int, struct job *, int *); STATIC void cmdtxt(shinstance *, union node *); STATIC void cmdlist(shinstance *, union node *, int); STATIC void cmdputs(shinstance *, const char *); /* * Turn job control on and off. * * Note: This code assumes that the third arg to ioctl is a character * pointer, which is true on Berkeley systems but not System V. Since * System V doesn't have job control yet, this isn't a problem now. */ //MKINIT int jobctl; void setjobctl(shinstance *psh, int on) { if (on == psh->jobctl || psh->rootshell == 0) return; if (on) { int err; int i; if (psh->ttyfd != -1) shfile_close(&psh->fdtab, psh->ttyfd); if ((psh->ttyfd = shfile_open(&psh->fdtab, "/dev/tty", O_RDWR, 0)) == -1) { for (i = 0; i < 3; i++) { if (shfile_isatty(&psh->fdtab, i) && (psh->ttyfd = shfile_dup(&psh->fdtab, i)) != -1) break; } if (i == 3) goto out; } /* Move to a high fd */ for (i = 10; i > 2; i--) { if ((err = shfile_fcntl(&psh->fdtab, psh->ttyfd, F_DUPFD, (1 << i) - 1)) != -1) break; } if (err != -1) { shfile_close(&psh->fdtab, psh->ttyfd); psh->ttyfd = err; } err = shfile_cloexec(&psh->fdtab, psh->ttyfd, 1); if (err == -1) { shfile_close(&psh->fdtab, psh->ttyfd); psh->ttyfd = -1; goto out; } do { /* while we are in the background */ if ((psh->initialpgrp = sh_tcgetpgrp(psh, psh->ttyfd)) < 0) { out: out2str(psh, "sh: can't access tty; job control turned off\n"); mflag(psh) = 0; return; } if (psh->initialpgrp == -1) psh->initialpgrp = sh_getpgrp(psh); else if (psh->initialpgrp != sh_getpgrp(psh)) { sh_killpg(psh, 0, SIGTTIN); continue; } } while (0); setsignal(psh, SIGTSTP, 0); setsignal(psh, SIGTTOU, 0); setsignal(psh, SIGTTIN, 0); if (sh_getpgid(psh, 0) != psh->rootpid && sh_setpgid(psh, 0, psh->rootpid) == -1) error(psh, "Cannot set process group (%s) at %d", sh_strerror(psh, errno), __LINE__); if (sh_tcsetpgrp(psh, psh->ttyfd, psh->rootpid) == -1) error(psh, "Cannot set tty process group (%s) at %d", sh_strerror(psh, errno), __LINE__); } else { /* turning job control off */ if (sh_getpgid(psh, 0) != psh->initialpgrp && sh_setpgid(psh, 0, psh->initialpgrp) == -1) error(psh, "Cannot set process group (%s) at %d", sh_strerror(psh, errno), __LINE__); if (sh_tcsetpgrp(psh, psh->ttyfd, psh->initialpgrp) == -1) error(psh, "Cannot set tty process group (%s) at %d", sh_strerror(psh, errno), __LINE__); shfile_close(&psh->fdtab, psh->ttyfd); psh->ttyfd = -1; setsignal(psh, SIGTSTP, 0); setsignal(psh, SIGTTOU, 0); setsignal(psh, SIGTTIN, 0); } psh->jobctl = on; } #ifdef mkinit INCLUDE SHELLPROC { psh->backgndpid = -1; #if JOBS psh->jobctl = 0; #endif } #endif #if JOBS int fgcmd(shinstance *psh, int argc, char **argv) { struct job *jp; int i; int status; nextopt(psh, ""); jp = getjob(psh, *psh->argptr, 0); if (jp->jobctl == 0) error(psh, "job not created under job control"); out1fmt(psh, "%s", jp->ps[0].cmd); for (i = 1; i < jp->nprocs; i++) out1fmt(psh, " | %s", jp->ps[i].cmd ); out1c(psh, '\n'); output_flushall(psh); for (i = 0; i < jp->nprocs; i++) if (sh_tcsetpgrp(psh, psh->ttyfd, jp->ps[i].pid) != -1) break; if (i >= jp->nprocs) { error(psh, "Cannot set tty process group (%s) at %d", sh_strerror(psh, errno), __LINE__); } restartjob(psh, jp); INTOFF; status = waitforjob(psh, jp); INTON; return status; } static void set_curjob(shinstance *psh, struct job *jp, int mode) { struct job *jp1, *jp2; int i, ji; ji = (int)(jp - psh->jobtab); /* first remove from list */ if (ji == psh->curjob) psh->curjob = jp->prev_job; else { for (i = 0; i < psh->njobs; i++) { if (psh->jobtab[i].prev_job != ji) continue; psh->jobtab[i].prev_job = jp->prev_job; break; } } /* Then re-insert in correct position */ switch (mode) { case 0: /* job being deleted */ jp->prev_job = -1; break; case 1: /* newly created job or backgrounded job, put after all stopped jobs. */ if (psh->curjob != -1 && psh->jobtab[psh->curjob].state == JOBSTOPPED) { for (jp1 = psh->jobtab + psh->curjob; ; jp1 = jp2) { if (jp1->prev_job == -1) break; jp2 = psh->jobtab + jp1->prev_job; if (jp2->state != JOBSTOPPED) break; } jp->prev_job = jp1->prev_job; jp1->prev_job = ji; break; } /* FALLTHROUGH */ case 2: /* newly stopped job - becomes psh->curjob */ jp->prev_job = psh->curjob; psh->curjob = ji; break; } } int bgcmd(shinstance *psh, int argc, char **argv) { struct job *jp; int i; nextopt(psh, ""); do { jp = getjob(psh, *psh->argptr, 0); if (jp->jobctl == 0) error(psh, "job not created under job control"); set_curjob(psh, jp, 1); out1fmt(psh, "[%ld] %s", (long)(jp - psh->jobtab + 1), jp->ps[0].cmd); for (i = 1; i < jp->nprocs; i++) out1fmt(psh, " | %s", jp->ps[i].cmd ); out1c(psh, '\n'); output_flushall(psh); restartjob(psh, jp); } while (*psh->argptr && *++psh->argptr); return 0; } STATIC void restartjob(shinstance *psh, struct job *jp) { struct procstat *ps; int i; if (jp->state == JOBDONE) return; INTOFF; for (i = 0; i < jp->nprocs; i++) if (sh_killpg(psh, jp->ps[i].pid, SIGCONT) != -1) break; if (i >= jp->nprocs) error(psh, "Cannot continue job (%s)", sh_strerror(psh, errno)); for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { if (WIFSTOPPED(ps->status)) { ps->status = -1; jp->state = JOBRUNNING; } } INTON; } #endif static void showjob(shinstance *psh, struct output *out, struct job *jp, int mode) { int procno; int st; struct procstat *ps; size_t col; char s[64]; #if JOBS if (mode & SHOW_PGID) { /* just output process (group) id of pipeline */ outfmt(out, "%ld\n", (long)jp->ps->pid); return; } #endif procno = jp->nprocs; if (!procno) return; if (mode & SHOW_PID) mode |= SHOW_MULTILINE; if ((procno > 1 && !(mode & SHOW_MULTILINE)) || (mode & SHOW_SIGNALLED)) { /* See if we have more than one status to report */ ps = jp->ps; st = ps->status; do { int st1 = ps->status; if (st1 != st) /* yes - need multi-line output */ mode |= SHOW_MULTILINE; if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1)) continue; if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f) && st1 != SIGINT && st1 != SIGPIPE)) mode |= SHOW_ISSIG; } while (ps++, --procno); procno = jp->nprocs; } if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) { if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) { TRACE((psh, "showjob: freeing job %d\n", jp - psh->jobtab + 1)); freejob(psh, jp); } return; } for (ps = jp->ps; --procno >= 0; ps++) { /* for each process */ if (ps == jp->ps) fmtstr(s, 16, "[%ld] %c ", (long)(jp - psh->jobtab + 1), #if JOBS jp == psh->jobtab + psh->curjob ? '+' : psh->curjob != -1 && jp == psh->jobtab + psh->jobtab[psh->curjob].prev_job ? '-' : #endif ' '); else fmtstr(s, 16, " " ); col = strlen(s); if (mode & SHOW_PID) { fmtstr(s + col, 16, "%ld ", (long)ps->pid); col += strlen(s + col); } if (ps->status == -1) { scopy("Running", s + col); } else if (WIFEXITED(ps->status)) { st = WEXITSTATUS(ps->status); if (st) fmtstr(s + col, 16, "Done(%d)", st); else fmtstr(s + col, 16, "Done"); } else { #if JOBS if (WIFSTOPPED(ps->status)) st = WSTOPSIG(ps->status); else /* WIFSIGNALED(ps->status) */ #endif st = WTERMSIG(ps->status); st &= 0x7f; if (st < NSIG && sys_siglist[st]) scopyn(sys_siglist[st], s + col, 32); else fmtstr(s + col, 16, "Signal %d", st); if (WCOREDUMP(ps->status)) { col += strlen(s + col); scopyn(" (core dumped)", s + col, 64 - col); } } col += strlen(s + col); outstr(s, out); do { outc(' ', out); col++; } while (col < 30); outstr(ps->cmd, out); if (mode & SHOW_MULTILINE) { if (procno > 0) { outc(' ', out); outc('|', out); } } else { while (--procno >= 0) outfmt(out, " | %s", (++ps)->cmd ); } outc('\n', out); } flushout(out); jp->changed = 0; if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) freejob(psh, jp); } int jobscmd(shinstance *psh, int argc, char **argv) { int mode, m; int sv = psh->jobs_invalid; psh->jobs_invalid = 0; mode = 0; while ((m = nextopt(psh, "lp"))) if (m == 'l') mode = SHOW_PID; else mode = SHOW_PGID; if (*psh->argptr) do showjob(psh, psh->out1, getjob(psh, *psh->argptr,0), mode); while (*++psh->argptr); else showjobs(psh, psh->out1, mode); psh->jobs_invalid = sv; return 0; } /* * Print a list of jobs. If "change" is nonzero, only print jobs whose * statuses have changed since the last call to showjobs. * * If the shell is interrupted in the process of creating a job, the * result may be a job structure containing zero processes. Such structures * will be freed here. */ void showjobs(shinstance *psh, struct output *out, int mode) { int jobno; struct job *jp; int silent = 0, gotpid; TRACE((psh, "showjobs(%x) called\n", mode)); /* If not even one one job changed, there is nothing to do */ gotpid = dowait(psh, 0, NULL); while (dowait(psh, 0, NULL) > 0) continue; #ifdef JOBS /* * Check if we are not in our foreground group, and if not * put us in it. */ if (mflag(psh) && gotpid != -1 && sh_tcgetpgrp(psh, psh->ttyfd) != sh_getpid(psh)) { if (sh_tcsetpgrp(psh, psh->ttyfd, sh_getpid(psh)) == -1) error(psh, "Cannot set tty process group (%s) at %d", sh_strerror(psh, errno), __LINE__); TRACE((psh, "repaired tty process group\n")); silent = 1; } #endif if (psh->jobs_invalid) return; for (jobno = 1, jp = psh->jobtab ; jobno <= psh->njobs ; jobno++, jp++) { if (!jp->used) continue; if (jp->nprocs == 0) { freejob(psh, jp); continue; } if ((mode & SHOW_CHANGED) && !jp->changed) continue; if (silent && jp->changed) { jp->changed = 0; continue; } showjob(psh, out, jp, mode); } } /* * Mark a job structure as unused. */ STATIC void freejob(shinstance *psh, struct job *jp) { INTOFF; if (jp->ps != &jp->ps0) { ckfree(psh, jp->ps); jp->ps = &jp->ps0; } jp->nprocs = 0; jp->used = 0; #if JOBS set_curjob(psh, jp, 0); #endif INTON; } int waitcmd(shinstance *psh, int argc, char **argv) { struct job *job; int status, retval; struct job *jp; nextopt(psh, ""); if (!*psh->argptr) { /* wait for all jobs */ jp = psh->jobtab; if (psh->jobs_invalid) return 0; for (;;) { if (jp >= psh->jobtab + psh->njobs) { /* no running procs */ return 0; } if (!jp->used || jp->state != JOBRUNNING) { jp++; continue; } if (dowait(psh, 1, (struct job *)NULL) == -1) return 128 + SIGINT; jp = psh->jobtab; } } retval = 127; /* XXXGCC: -Wuninitialized */ for (; *psh->argptr; psh->argptr++) { job = getjob(psh, *psh->argptr, 1); if (!job) { retval = 127; continue; } /* loop until process terminated or stopped */ while (job->state == JOBRUNNING) { if (dowait(psh, 1, (struct job *)NULL) == -1) return 128 + SIGINT; } status = job->ps[job->nprocs].status; if (WIFEXITED(status)) retval = WEXITSTATUS(status); #if JOBS else if (WIFSTOPPED(status)) retval = WSTOPSIG(status) + 128; #endif else { /* XXX: limits number of signals */ retval = WTERMSIG(status) + 128; } if (!iflag(psh)) freejob(psh, job); } return retval; } int jobidcmd(shinstance *psh, int argc, char **argv) { struct job *jp; int i; nextopt(psh, ""); jp = getjob(psh, *psh->argptr, 0); for (i = 0 ; i < jp->nprocs ; ) { out1fmt(psh, "%ld", (long)jp->ps[i].pid); out1c(psh, ++i < jp->nprocs ? ' ' : '\n'); } return 0; } int getjobpgrp(shinstance *psh, const char *name) { struct job *jp; jp = getjob(psh, name, 1); if (jp == 0) return 0; return -jp->ps[0].pid; } /* * Convert a job name to a job structure. */ STATIC struct job * getjob(shinstance *psh, const char *name, int noerror) { int jobno = -1; struct job *jp; int pid; int i; const char *err_msg = "No such job: %s"; if (name == NULL) { #if JOBS jobno = psh->curjob; #endif err_msg = "No current job"; } else if (name[0] == '%') { if (is_number(name + 1)) { jobno = number(psh, name + 1) - 1; } else if (!name[2]) { switch (name[1]) { #if JOBS case 0: case '+': case '%': jobno = psh->curjob; err_msg = "No current job"; break; case '-': jobno = psh->curjob; if (jobno != -1) jobno = psh->jobtab[jobno].prev_job; err_msg = "No previous job"; break; #endif default: goto check_pattern; } } else { struct job *found; check_pattern: found = NULL; for (jp = psh->jobtab, i = psh->njobs ; --i >= 0 ; jp++) { if (!jp->used || jp->nprocs <= 0) continue; if ((name[1] == '?' && strstr(jp->ps[0].cmd, name + 2)) || prefix(name + 1, jp->ps[0].cmd)) { if (found) { err_msg = "%s: ambiguous"; found = 0; break; } found = jp; } } if (found) return found; } } else if (is_number(name)) { pid = number(psh, name); for (jp = psh->jobtab, i = psh->njobs ; --i >= 0 ; jp++) { if (jp->used && jp->nprocs > 0 && jp->ps[jp->nprocs - 1].pid == pid) return jp; } } if (!psh->jobs_invalid && jobno >= 0 && jobno < psh->njobs) { jp = psh->jobtab + jobno; if (jp->used) return jp; } if (!noerror) error(psh, err_msg, name); return 0; } /* * Return a new job structure, */ struct job * makejob(shinstance *psh, union node *node, int nprocs) { int i; struct job *jp; if (psh->jobs_invalid) { for (i = psh->njobs, jp = psh->jobtab ; --i >= 0 ; jp++) { if (jp->used) freejob(psh, jp); } psh->jobs_invalid = 0; } for (i = psh->njobs, jp = psh->jobtab ; ; jp++) { if (--i < 0) { INTOFF; if (psh->njobs == 0) { psh->jobtab = ckmalloc(psh, 4 * sizeof psh->jobtab[0]); } else { jp = ckmalloc(psh, (psh->njobs + 4) * sizeof psh->jobtab[0]); memcpy(jp, psh->jobtab, psh->njobs * sizeof jp[0]); /* Relocate `ps' pointers */ for (i = 0; i < psh->njobs; i++) if (jp[i].ps == &psh->jobtab[i].ps0) jp[i].ps = &jp[i].ps0; ckfree(psh, psh->jobtab); psh->jobtab = jp; } jp = psh->jobtab + psh->njobs; for (i = 4 ; --i >= 0 ; psh->jobtab[psh->njobs++].used = 0); INTON; break; } if (jp->used == 0) break; } INTOFF; jp->state = JOBRUNNING; jp->used = 1; jp->changed = 0; jp->nprocs = 0; #if JOBS jp->jobctl = psh->jobctl; set_curjob(psh, jp, 1); #endif if (nprocs > 1) { jp->ps = ckmalloc(psh, nprocs * sizeof (struct procstat)); } else { jp->ps = &jp->ps0; } INTON; TRACE((psh, "makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, jp - psh->jobtab + 1)); return jp; } /* * Fork off a subshell. If we are doing job control, give the subshell its * own process group. Jp is a job structure that the job is to be added to. * N is the command that will be evaluated by the child. Both jp and n may * be NULL. The mode parameter can be one of the following: * FORK_FG - Fork off a foreground process. * FORK_BG - Fork off a background process. * FORK_NOJOB - Like FORK_FG, but don't give the process its own * process group even if job control is on. * * When job control is turned off, background processes have their standard * input redirected to /dev/null (except for the second and later processes * in a pipeline). */ int forkshell(shinstance *psh, struct job *jp, union node *n, int mode) { int pid; TRACE((psh, "forkshell(%%%d, %p, %d) called\n", jp - psh->jobtab, n, mode)); switch ((pid = sh_fork(psh))) { case -1: TRACE((psh, "Fork failed, errno=%d\n", errno)); INTON; error(psh, "Cannot fork"); return -1; /* won't get here */ case 0: forkchild(psh, jp, n, mode, 0); return 0; default: return forkparent(psh, jp, n, mode, pid); } } int forkparent(shinstance *psh, struct job *jp, union node *n, int mode, pid_t pid) { int pgrp; if (psh->rootshell && mode != FORK_NOJOB && mflag(psh)) { if (jp == NULL || jp->nprocs == 0) pgrp = pid; else pgrp = jp->ps[0].pid; /* This can fail because we are doing it in the child also */ (void)sh_setpgid(psh, pid, pgrp); } if (mode == FORK_BG) psh->backgndpid = pid; /* set $! */ if (jp) { struct procstat *ps = &jp->ps[jp->nprocs++]; ps->pid = pid; ps->status = -1; ps->cmd[0] = 0; if (/* iflag && rootshell && */ n) commandtext(psh, ps, n); } TRACE((psh, "In parent shell: child = %d\n", pid)); return pid; } void forkchild(shinstance *psh, struct job *jp, union node *n, int mode, int vforked) { int wasroot; int pgrp; const char *devnull = _PATH_DEVNULL; const char *nullerr = "Can't open %s"; wasroot = psh->rootshell; TRACE((psh, "Child shell %d\n", sh_getpid(psh))); if (!vforked) psh->rootshell = 0; closescript(psh, vforked); clear_traps(psh, vforked); #if JOBS if (!vforked) psh->jobctl = 0; /* do job control only in root shell */ if (wasroot && mode != FORK_NOJOB && mflag(psh)) { if (jp == NULL || jp->nprocs == 0) pgrp = sh_getpid(psh); else pgrp = jp->ps[0].pid; /* This can fail because we are doing it in the parent also. And we must ignore SIGTTOU at this point or we'll be stopped! */ (void)sh_setpgid(psh, 0, pgrp); if (mode == FORK_FG) { if (sh_tcsetpgrp(psh, psh->ttyfd, pgrp) == -1) error(psh, "Cannot set tty process group (%s) at %d", sh_strerror(psh, errno), __LINE__); } setsignal(psh, SIGTSTP, vforked); setsignal(psh, SIGTTOU, vforked); } else if (mode == FORK_BG) { ignoresig(psh, SIGINT, vforked); ignoresig(psh, SIGQUIT, vforked); if ((jp == NULL || jp->nprocs == 0) && ! fd0_redirected_p(psh)) { shfile_close(&psh->fdtab, 0); if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0) error(psh, nullerr, devnull); } } #else if (mode == FORK_BG) { ignoresig(psh, SIGINT, vforked); ignoresig(psh, SIGQUIT, vforked); if ((jp == NULL || jp->nprocs == 0) && ! fd0_redirected_p(psh)) { shfile_close(&psh->fdtab, 0); if (shfile_open(&psh->fdtab, devnull, O_RDONLY, 0) != 0) error(psh, nullerr, devnull); } } #endif if (wasroot && iflag(psh)) { setsignal(psh, SIGINT, vforked); setsignal(psh, SIGQUIT, vforked); setsignal(psh, SIGTERM, vforked); } if (!vforked) psh->jobs_invalid = 1; } /* * Wait for job to finish. * * Under job control we have the problem that while a child process is * running interrupts generated by the user are sent to the child but not * to the shell. This means that an infinite loop started by an inter- * active user may be hard to kill. With job control turned off, an * interactive user may place an interactive program inside a loop. If * the interactive program catches interrupts, the user doesn't want * these interrupts to also abort the loop. The approach we take here * is to have the shell ignore interrupt signals while waiting for a * forground process to terminate, and then send itself an interrupt * signal if the child process was terminated by an interrupt signal. * Unfortunately, some programs want to do a bit of cleanup and then * exit on interrupt; unless these processes terminate themselves by * sending a signal to themselves (instead of calling exit) they will * confuse this approach. */ int waitforjob(shinstance *psh, struct job *jp) { #if JOBS int mypgrp = sh_getpgrp(psh); #endif int status; int st; INTOFF; TRACE((psh, "waitforjob(%%%d) called\n", jp - psh->jobtab + 1)); while (jp->state == JOBRUNNING) { dowait(psh, 1, jp); } #if JOBS if (jp->jobctl) { if (sh_tcsetpgrp(psh, psh->ttyfd, mypgrp) == -1) error(psh, "Cannot set tty process group (%s) at %d", sh_strerror(psh, errno), __LINE__); } if (jp->state == JOBSTOPPED && psh->curjob != jp - psh->jobtab) set_curjob(psh, jp, 2); #endif status = jp->ps[jp->nprocs - 1].status; /* convert to 8 bits */ if (WIFEXITED(status)) st = WEXITSTATUS(status); #if JOBS else if (WIFSTOPPED(status)) st = WSTOPSIG(status) + 128; #endif else st = WTERMSIG(status) + 128; TRACE((psh, "waitforjob: job %d, nproc %d, status %x, st %x\n", jp - psh->jobtab + 1, jp->nprocs, status, st )); #if JOBS if (jp->jobctl) { /* * This is truly gross. * If we're doing job control, then we did a TIOCSPGRP which * caused us (the shell) to no longer be in the controlling * session -- so we wouldn't have seen any ^C/SIGINT. So, we * intuit from the subprocess exit status whether a SIGINT * occurred, and if so interrupt ourselves. Yuck. - mycroft */ if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) sh_raise_sigint(psh);/*raise(SIGINT);*/ } #endif if (! JOBS || jp->state == JOBDONE) freejob(psh, jp); INTON; return st; } /* * Wait for a process to terminate. */ STATIC int dowait(shinstance *psh, int block, struct job *job) { int pid; int status; struct procstat *sp; struct job *jp; struct job *thisjob; int done; int stopped; TRACE((psh, "dowait(%d) called\n", block)); do { pid = waitproc(psh, block, job, &status); TRACE((psh, "wait returns pid %d, status %d\n", pid, status)); } while (pid == -1 && errno == EINTR && psh->gotsig[SIGINT - 1] == 0); if (pid <= 0) return pid; INTOFF; thisjob = NULL; for (jp = psh->jobtab ; jp < psh->jobtab + psh->njobs ; jp++) { if (jp->used) { done = 1; stopped = 1; for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { if (sp->pid == -1) continue; if (sp->pid == pid) { TRACE((psh, "Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - psh->jobtab + 1, pid, sp->status, status)); sp->status = status; thisjob = jp; } if (sp->status == -1) stopped = 0; else if (WIFSTOPPED(sp->status)) done = 0; } if (stopped) { /* stopped or done */ int state = done ? JOBDONE : JOBSTOPPED; if (jp->state != state) { TRACE((psh, "Job %d: changing state from %d to %d\n", jp - psh->jobtab + 1, jp->state, state)); jp->state = state; #if JOBS if (done) set_curjob(psh, jp, 0); #endif } } } } if (thisjob && thisjob->state != JOBRUNNING) { int mode = 0; if (!psh->rootshell || !iflag(psh)) mode = SHOW_SIGNALLED; if (job == thisjob) mode = SHOW_SIGNALLED | SHOW_NO_FREE; if (mode) showjob(psh, psh->out2, thisjob, mode); else { TRACE((psh, "Not printing status, rootshell=%d, job=%p\n", psh->rootshell, job)); thisjob->changed = 1; } } INTON; return pid; } /* * Do a wait system call. If job control is compiled in, we accept * stopped processes. If block is zero, we return a value of zero * rather than blocking. */ STATIC int waitproc(shinstance *psh, int block, struct job *jp, int *status) { int flags = 0; #if JOBS if (jp != NULL && jp->jobctl) flags |= WUNTRACED; #endif if (block == 0) flags |= WNOHANG; return sh_waitpid(psh, -1, status, flags); } /* * return 1 if there are stopped jobs, otherwise 0 */ //int job_warning = 0; int stoppedjobs(shinstance *psh) { int jobno; struct job *jp; if (psh->job_warning || psh->jobs_invalid) return (0); for (jobno = 1, jp = psh->jobtab; jobno <= psh->njobs; jobno++, jp++) { if (jp->used == 0) continue; if (jp->state == JOBSTOPPED) { out2str(psh, "You have stopped jobs.\n"); psh->job_warning = 2; return (1); } } return (0); } /* * Return a string identifying a command (to be printed by the * jobs command). */ //STATIC char *cmdnextc; //STATIC int cmdnleft; void commandtext(shinstance *psh, struct procstat *ps, union node *n) { int len; psh->cmdnextc = ps->cmd; if (iflag(psh) || mflag(psh) || sizeof(ps->cmd) < 100) len = sizeof(ps->cmd); else len = sizeof(ps->cmd) / 10; psh->cmdnleft = len; cmdtxt(psh, n); if (psh->cmdnleft <= 0) { char *p = ps->cmd + len - 4; p[0] = '.'; p[1] = '.'; p[2] = '.'; p[3] = 0; } else *psh->cmdnextc = '\0'; TRACE((psh, "commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n", ps->cmd, psh->cmdnextc, psh->cmdnleft, ps->cmd)); } STATIC void cmdtxt(shinstance *psh, union node *n) { union node *np; struct nodelist *lp; const char *p; int i; char s[2]; if (n == NULL || psh->cmdnleft <= 0) return; switch (n->type) { case NSEMI: cmdtxt(psh, n->nbinary.ch1); cmdputs(psh, "; "); cmdtxt(psh, n->nbinary.ch2); break; case NAND: cmdtxt(psh, n->nbinary.ch1); cmdputs(psh, " && "); cmdtxt(psh, n->nbinary.ch2); break; case NOR: cmdtxt(psh, n->nbinary.ch1); cmdputs(psh, " || "); cmdtxt(psh, n->nbinary.ch2); break; case NPIPE: for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { cmdtxt(psh, lp->n); if (lp->next) cmdputs(psh, " | "); } break; case NSUBSHELL: cmdputs(psh, "("); cmdtxt(psh, n->nredir.n); cmdputs(psh, ")"); break; case NREDIR: case NBACKGND: cmdtxt(psh, n->nredir.n); break; case NIF: cmdputs(psh, "if "); cmdtxt(psh, n->nif.test); cmdputs(psh, "; then "); cmdtxt(psh, n->nif.ifpart); if (n->nif.elsepart) { cmdputs(psh, "; else "); cmdtxt(psh, n->nif.elsepart); } cmdputs(psh, "; fi"); break; case NWHILE: cmdputs(psh, "while "); goto until; case NUNTIL: cmdputs(psh, "until "); until: cmdtxt(psh, n->nbinary.ch1); cmdputs(psh, "; do "); cmdtxt(psh, n->nbinary.ch2); cmdputs(psh, "; done"); break; case NFOR: cmdputs(psh, "for "); cmdputs(psh, n->nfor.var); cmdputs(psh, " in "); cmdlist(psh, n->nfor.args, 1); cmdputs(psh, "; do "); cmdtxt(psh, n->nfor.body); cmdputs(psh, "; done"); break; case NCASE: cmdputs(psh, "case "); cmdputs(psh, n->ncase.expr->narg.text); cmdputs(psh, " in "); for (np = n->ncase.cases; np; np = np->nclist.next) { cmdtxt(psh, np->nclist.pattern); cmdputs(psh, ") "); cmdtxt(psh, np->nclist.body); cmdputs(psh, ";; "); } cmdputs(psh, "esac"); break; case NDEFUN: cmdputs(psh, n->narg.text); cmdputs(psh, "() { ... }"); break; case NCMD: cmdlist(psh, n->ncmd.args, 1); cmdlist(psh, n->ncmd.redirect, 0); break; case NARG: cmdputs(psh, n->narg.text); break; case NTO: p = ">"; i = 1; goto redir; case NCLOBBER: p = ">|"; i = 1; goto redir; case NAPPEND: p = ">>"; i = 1; goto redir; case NTOFD: p = ">&"; i = 1; goto redir; case NFROM: p = "<"; i = 0; goto redir; case NFROMFD: p = "<&"; i = 0; goto redir; case NFROMTO: p = "<>"; i = 0; goto redir; redir: if (n->nfile.fd != i) { s[0] = n->nfile.fd + '0'; s[1] = '\0'; cmdputs(psh, s); } cmdputs(psh, p); if (n->type == NTOFD || n->type == NFROMFD) { s[0] = n->ndup.dupfd + '0'; s[1] = '\0'; cmdputs(psh, s); } else { cmdtxt(psh, n->nfile.fname); } break; case NHERE: case NXHERE: cmdputs(psh, "<<..."); break; default: cmdputs(psh, "???"); break; } } STATIC void cmdlist(shinstance *psh, union node *np, int sep) { for (; np; np = np->narg.next) { if (!sep) cmdputs(psh, " "); cmdtxt(psh, np); if (sep && np->narg.next) cmdputs(psh, " "); } } STATIC void cmdputs(shinstance *psh, const char *s) { const char *p, *str = 0; char c, cc[2] = " "; char *nextc; int nleft; int subtype = 0; int quoted = 0; static char vstype[16][4] = { "", "}", "-", "+", "?", "=", "#", "##", "%", "%%" }; p = s; nextc = psh->cmdnextc; nleft = psh->cmdnleft; while (nleft > 0 && (c = *p++) != 0) { switch (c) { case CTLESC: c = *p++; break; case CTLVAR: subtype = *p++; if ((subtype & VSTYPE) == VSLENGTH) str = "${#"; else str = "${"; if (!(subtype & VSQUOTE) != !(quoted & 1)) { quoted ^= 1; c = '"'; } else c = *str++; break; case CTLENDVAR: if (quoted & 1) { c = '"'; str = "}"; } else c = '}'; quoted >>= 1; subtype = 0; break; case CTLBACKQ: c = '$'; str = "(...)"; break; case CTLBACKQ+CTLQUOTE: c = '"'; str = "$(...)\""; break; case CTLARI: c = '$'; str = "(("; break; case CTLENDARI: c = ')'; str = ")"; break; case CTLQUOTEMARK: quoted ^= 1; c = '"'; break; case '=': if (subtype == 0) break; str = vstype[subtype & VSTYPE]; if (subtype & VSNUL) c = ':'; else c = *str++; if (c != '}') quoted <<= 1; break; case '\'': case '\\': case '"': case '$': /* These can only happen inside quotes */ cc[0] = c; str = cc; c = '\\'; break; default: break; } do { *nextc++ = c; } while (--nleft > 0 && str && (c = *str++)); str = 0; } if ((quoted & 1) && nleft) { *nextc++ = '"'; nleft--; } psh->cmdnleft = nleft; psh->cmdnextc = nextc; } kbuild-2695/src/kash/shforkA-win.asm0000644000000000000000000002231112247157307016047 0ustar rootroot; $Id: shforkA-win.asm 2416 2010-09-14 00:30:30Z bird $ ;; @file ; shforkA-win.asm - assembly routines used when forking on Windows. ; ; ; Copyright (c) 2009-2010 knut st. osmundsen ; ; This file is part of kBuild. ; ; kBuild is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 3 of the License, or ; (at your option) any later version. ; ; kBuild is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with kBuild. If not, see ; ; ;******************************************************************************* ;* Defined Constants And Macros * ;******************************************************************************* %ifdef KBUILD_ARCH_AMD64 %define NAME(name) name %else %define NAME(name) _ %+ name %endif ;; The stack size. This is also defined in shfork-win.c. %define SHFORK_STACK_SIZE (1*1024*1024) ;******************************************************************************* ;* External Symbols * ;******************************************************************************* extern NAME(real_main) extern NAME(shfork_maybe_forked) extern NAME(shfork_body) [section .text] ;; ; C main() wrapper. ; NAME(main): global NAME(main) %ifdef KBUILD_ARCH_AMD64 [proc_frame main] %endif ; ; Prolog, spilling parameters from registers. ; %ifdef KBUILD_ARCH_AMD64 [pushreg rbp] push rbp [setframe rbp, 0] mov rbp, rsp [allocstack 0x40] sub rsp, 40h and rsp, ~1fh mov [rbp-08h], rcx ; argc mov [rbp-10h], rdx ; argv mov [rbp-18h], r8 ; envp [endprolog] %else push ebp mov ebp, esp sub esp, 40h and esp, ~1fh %endif ; ; Call shfork_maybe_forked. This will not return if we're forking. ; %ifndef KBUILD_ARCH_AMD64 mov ecx, [ebp + 8h] ; argc mov edx, [ebp + 0ch] ; argv mov eax, [ebp + 10h] ; envp mov [esp ], ecx mov [esp + 4h], edx mov [esp + 8h], eax %endif call NAME(shfork_maybe_forked) ; ; Ok, it returned which means we're not forking. ; ; The accumulator register is now pointing to the top of the ; stack we're going to call real_main on. Switch and call it. ; ; The TIB adjustments is required or we'll crash in longjmp/unwind. ; %ifdef KBUILD_ARCH_AMD64 mov [rsp + 18h], rax mov [rax - 8h], rsp mov r10, [gs:08h] ; StackBase (the higher value) mov r11, [gs:10h] ; StackLimit (the lower value) mov [rax - 10h], r10 mov [rax - 18h], r11 cmp rax, r10 jb .below mov [gs:08h], rax .below: lea r9, [rax - SHFORK_STACK_SIZE] cmp r9, r11 ja .above mov [gs:10h], r9 .above: mov rcx, [rbp - 08h] ; argc mov rdx, [rbp - 10h] ; argv mov r8, [rbp - 18h] ; envp lea rsp, [rax - 40h] ; Switch! %else mov [esp + 18h], eax mov [eax - 4], esp lea esp, [eax - 40h] ; Switch! mov edx, [fs:04h] ; StackBase (the higher value) mov ecx, [fs:08h] ; StackLimit (the lower value) mov [eax - 10h], edx mov [eax - 18h], ecx cmp eax, edx jb .below mov [fs:04h], eax .below: lea edx, [eax - SHFORK_STACK_SIZE] cmp edx, ecx ja .above mov [fs:08h], edx .above: mov ecx, [ebp + 8h] ; argc mov edx, [ebp + 0ch] ; argv mov eax, [ebp + 10h] ; envp mov [esp ], ecx mov [esp + 4h], edx mov [esp + 8h], eax %endif call NAME(real_main) ; ; Switch back the stack, restore the TIB fields and we're done. ; %ifdef KBUILD_ARCH_AMD64 lea r11, [rsp + 40h] mov rsp, [rsp + 38h] mov r8, [r11 - 10h] mov r9, [r11 - 18h] mov [gs:08h], r8 mov [gs:10h], r9 %else lea edx, [esp + 40h] mov esp, [esp + 2ch] mov ecx, [edx - 10h] mov edx, [edx - 18h] mov [fs:04h], ecx mov [fs:08h], edx %endif leave ret %ifdef KBUILD_ARCH_AMD64 [endproc_frame main] %endif ;; ; sh_fork() worker ; ; @returns See fork(). ; @param psh ; NAME(shfork_do_it): global NAME(shfork_do_it) %ifdef KBUILD_ARCH_AMD64 [proc_frame shfork_do_it] [pushreg rbp] push rbp [setframe rbp, 0] mov rbp, rsp [allocstack 0x400] sub rsp, 400h and rsp, ~1ffh [endprolog] %else push ebp mov ebp, esp sub esp, 400h and esp, ~1ffh %endif ; ; Save most registers so they can be restored in the child. ; %ifdef KBUILD_ARCH_AMD64 fxsave [rsp] mov [rsp + 200h], rbp mov [rsp + 208h], rax mov [rsp + 210h], rbx mov [rsp + 218h], rcx mov [rsp + 220h], rdx mov [rsp + 228h], rsi mov [rsp + 230h], rdi mov [rsp + 238h], r8 mov [rsp + 240h], r9 mov [rsp + 248h], r10 mov [rsp + 250h], r11 mov [rsp + 258h], r12 mov [rsp + 260h], r13 mov [rsp + 268h], r14 mov [rsp + 270h], r15 %else fxsave [esp] mov [esp + 200h], ebp mov [esp + 208h], eax mov [esp + 210h], ebx mov [esp + 218h], ecx mov [esp + 220h], edx mov [esp + 228h], esi mov [esp + 230h], edi %endif ; ; Call the shfork_body that will spawn the child and all that. ; %ifdef KBUILD_ARCH_AMD64 ;mov rcx, rcx ; psh mov rdx, rsp ; stack_ptr sub rsp, 20h call NAME(shfork_body) lea rsp, [rsp + 20h] %else mov edx, esp mov ecx, [ebp + 8h] ; psh sub esp, 20h mov [esp ], ecx mov [esp + 4], edx ; stack_ptr call NAME(shfork_body) lea esp, [esp + 20h] %endif ; ; Just leave the function, no need to restore things. ; leave ret %ifdef KBUILD_ARCH_AMD64 [endproc_frame shfork_do_it] %endif ;; ; Switch the stack, restore the register and leave as if we'd called shfork_do_it. ; ; @param cur Current stack pointer. ; @param base The stack base (higher value). ; @param limit The stack limit (lower value). ; NAME(shfork_resume): global NAME(shfork_resume) %ifdef KBUILD_ARCH_AMD64 mov rsp, rcx %else mov ecx, [esp + 4] mov edx, [esp + 8] mov eax, [esp + 12] mov esp, ecx %endif ; ; Adjust stack stuff in the TIB (longjmp/unwind). ; %ifdef KBUILD_ARCH_AMD64 cmp rdx, [gs:08h] ; StackBase (the higher value) jb .below mov [gs:08h], rdx .below: cmp r8, [gs:10h] ; StackLimit ja .above mov [gs:10h], r8 .above: %else cmp edx, [fs:04h] ; StackBase (the higher value) jb .below mov [fs:04h], edx .below: cmp eax, [fs:08h] ; StackLimit ja .above mov [fs:08h], eax .above: %endif ; ; Restore most of the registers. ; ;; @todo xmm registers may require explicit saving/restoring... %ifdef KBUILD_ARCH_AMD64 frstor [rsp] mov rbp, [rsp + 200h] mov rax, [rsp + 208h] mov rbx, [rsp + 210h] mov rcx, [rsp + 218h] mov rdx, [rsp + 220h] mov rsi, [rsp + 228h] mov rdi, [rsp + 230h] mov r8, [rsp + 238h] mov r9, [rsp + 240h] mov r10, [rsp + 248h] mov r11, [rsp + 250h] mov r12, [rsp + 258h] mov r13, [rsp + 260h] mov r14, [rsp + 268h] mov r15, [rsp + 270h] %else frstor [esp] mov ebp, [esp + 200h] mov eax, [esp + 208h] mov ebx, [esp + 210h] mov ecx, [esp + 218h] mov edx, [esp + 220h] mov esi, [esp + 228h] mov edi, [esp + 230h] %endif xor eax, eax ; the child returns 0. leave ret kbuild-2695/src/kash/alias.c0000644000000000000000000001512112247157307014413 0ustar rootroot/* $NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $"); #endif /* not lint */ #endif #include #include "shell.h" #include "input.h" #include "output.h" #include "error.h" #include "memalloc.h" #include "mystring.h" #include "alias.h" #include "options.h" /* XXX for argptr (should remove?) */ #include "var.h" #include "shinstance.h" /*#define ATABSIZE 39 struct alias *atab[ATABSIZE];*/ STATIC void setalias(shinstance *, char *, char *); STATIC int unalias(shinstance *, char *); STATIC struct alias **hashalias(shinstance *, char *); STATIC void setalias(shinstance *psh, char *name, char *val) { struct alias *ap, **app; app = hashalias(psh, name); for (ap = *app; ap; ap = ap->next) { if (equal(name, ap->name)) { INTOFF; ckfree(psh, ap->val); ap->val = savestr(psh, val); INTON; return; } } /* not found */ INTOFF; ap = ckmalloc(psh, sizeof (struct alias)); ap->name = savestr(psh, name); /* * XXX - HACK: in order that the parser will not finish reading the * alias value off the input before processing the next alias, we * dummy up an extra space at the end of the alias. This is a crock * and should be re-thought. The idea (if you feel inclined to help) * is to avoid alias recursions. The mechanism used is: when * expanding an alias, the value of the alias is pushed back on the * input as a string and a pointer to the alias is stored with the * string. The alias is marked as being in use. When the input * routine finishes reading the string, it markes the alias not * in use. The problem is synchronization with the parser. Since * it reads ahead, the alias is marked not in use before the * resulting token(s) is next checked for further alias sub. The * H A C K is that we add a little fluff after the alias value * so that the string will not be exhausted. This is a good * idea ------- ***NOT*** */ #ifdef notyet ap->val = savestr(psh, val); #else /* hack */ { size_t len = strlen(val); ap->val = ckmalloc(psh, len + 2); memcpy(ap->val, val, len); ap->val[len] = ' '; /* fluff */ ap->val[len+1] = '\0'; } #endif ap->next = *app; *app = ap; INTON; } STATIC int unalias(shinstance *psh, char *name) { struct alias *ap, **app; app = hashalias(psh, name); for (ap = *app; ap; app = &(ap->next), ap = ap->next) { if (equal(name, ap->name)) { /* * if the alias is currently in use (i.e. its * buffer is being used by the input routine) we * just null out the name instead of freeing it. * We could clear it out later, but this situation * is so rare that it hardly seems worth it. */ if (ap->flag & ALIASINUSE) *ap->name = '\0'; else { INTOFF; *app = ap->next; ckfree(psh, ap->name); ckfree(psh, ap->val); ckfree(psh, ap); INTON; } return (0); } } return (1); } #ifdef mkinit MKINIT void rmaliases(shinstance *psh); SHELLPROC { rmaliases(psh); } #endif void rmaliases(shinstance *psh) { struct alias *ap, *tmp; int i; INTOFF; for (i = 0; i < ATABSIZE; i++) { ap = psh->atab[i]; psh->atab[i] = NULL; while (ap) { ckfree(psh, ap->name); ckfree(psh, ap->val); tmp = ap; ap = ap->next; ckfree(psh, tmp); } } INTON; } struct alias * lookupalias(shinstance *psh, char *name, int check) { struct alias *ap = *hashalias(psh, name); for (; ap; ap = ap->next) { if (equal(name, ap->name)) { if (check && (ap->flag & ALIASINUSE)) return (NULL); return (ap); } } return (NULL); } char * get_alias_text(shinstance *psh, char *name) { struct alias *ap; ap = lookupalias(psh, name, 0); if (ap == NULL) return NULL; return ap->val; } /* * TODO - sort output */ int aliascmd(shinstance *psh, int argc, char **argv) { char *n, *v; int ret = 0; struct alias *ap; if (argc == 1) { int i; for (i = 0; i < ATABSIZE; i++) for (ap = psh->atab[i]; ap; ap = ap->next) { if (*ap->name != '\0') { out1fmt(psh, "alias %s=", ap->name); print_quoted(psh, ap->val); out1c(psh, '\n'); } } return (0); } while ((n = *++argv) != NULL) { if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */ if ((ap = lookupalias(psh, n, 0)) == NULL) { outfmt(psh->out2, "alias: %s not found\n", n); ret = 1; } else { out1fmt(psh, "alias %s=", n); print_quoted(psh, ap->val); out1c(psh, '\n'); } } else { *v++ = '\0'; setalias(psh, n, v); } } return (ret); } int unaliascmd(shinstance *psh, int argc, char **argv) { int i; while ((i = nextopt(psh, "a")) != '\0') { if (i == 'a') { rmaliases(psh); return (0); } } for (i = 0; *psh->argptr; psh->argptr++) i = unalias(psh, *psh->argptr); return (i); } STATIC struct alias ** hashalias(shinstance *psh, char *p) { unsigned int hashval; hashval = *p << 4; while (*p) hashval+= *p++; return &psh->atab[hashval % ATABSIZE]; } kbuild-2695/src/kash/funcs/0000755000000000000000000000000012247157307014274 5ustar rootrootkbuild-2695/src/kash/funcs/cmv0000644000000000000000000000420312247157307015003 0ustar rootroot# $NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)cmv 8.2 (Berkeley) 5/4/95 # Conditional move--don't replace an existing file. cmv() { if test $# != 2 then echo "cmv: arg count" return 2 fi if test -f "$2" -o -w "$2" then echo "$2 exists" return 2 fi /bin/mv "$1" "$2" } kbuild-2695/src/kash/funcs/login0000644000000000000000000000377612247157307015344 0ustar rootroot# $NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)login 8.2 (Berkeley) 5/4/95 # replaces the login builtin in the BSD shell login () exec login "$@" kbuild-2695/src/kash/funcs/suspend0000644000000000000000000000375012247157307015705 0ustar rootroot# $NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)suspend 8.2 (Berkeley) 5/4/95 suspend() { local - set +j kill -TSTP 0 } kbuild-2695/src/kash/funcs/popd0000644000000000000000000000502612247157307015164 0ustar rootroot# $NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)popd 8.2 (Berkeley) 5/4/95 # pushd, popd, and dirs --- written by Chris Bertin # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris # as modified by Patrick Elam of GTRI and Kenneth Almquist at UW pushd () { SAVE=`pwd` if [ "$1" = "" ] then if [ "$DSTACK" = "" ] then echo "pushd: directory stack empty." return 1 fi set $DSTACK cd $1 || return shift 1 DSTACK="$*" else cd $1 > /dev/null || return fi DSTACK="$SAVE $DSTACK" dirs } popd () { if [ "$DSTACK" = "" ] then echo "popd: directory stack empty." return 1 fi set $DSTACK cd $1 shift DSTACK=$* dirs } dirs () { echo "`pwd` $DSTACK" return 0 } kbuild-2695/src/kash/funcs/pushd0000644000000000000000000000503012247157307015340 0ustar rootroot# $NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)pushd 8.2 (Berkeley) 5/4/95 # pushd, popd, and dirs --- written by Chris Bertin # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris # as modified by Patrick Elam of GTRI and Kenneth Almquist at UW pushd () { SAVE=`pwd` if [ "$1" = "" ] then if [ "$DSTACK" = "" ] then echo "pushd: directory stack empty." return 1 fi set $DSTACK cd $1 || return shift 1 DSTACK="$*" else cd $1 > /dev/null || return fi DSTACK="$SAVE $DSTACK" dirs } popd () { if [ "$DSTACK" = "" ] then echo "popd: directory stack empty." return 1 fi set $DSTACK cd $1 shift DSTACK=$* dirs } dirs () { echo "`pwd` $DSTACK" return 0 } kbuild-2695/src/kash/funcs/newgrp0000644000000000000000000000372312247157307015526 0ustar rootroot# $NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)newgrp 8.2 (Berkeley) 5/4/95 newgrp() exec newgrp "$@" kbuild-2695/src/kash/funcs/kill0000644000000000000000000000416712247157307015162 0ustar rootroot# $NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)kill 8.2 (Berkeley) 5/4/95 # Convert job names to process ids and then run /bin/kill. kill() { local args x args= for x in "$@" do case $x in %*) x=`jobid "$x"` ;; esac args="$args $x" done /bin/kill $args } kbuild-2695/src/kash/funcs/dirs0000644000000000000000000000502612247157307015163 0ustar rootroot# $NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. All advertising materials mentioning features or use of this software # must display the following acknowledgement: # This product includes software developed by the University of # California, Berkeley and its contributors. # 4. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)dirs 8.2 (Berkeley) 5/4/95 # pushd, popd, and dirs --- written by Chris Bertin # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris # as modified by Patrick Elam of GTRI and Kenneth Almquist at UW pushd () { SAVE=`pwd` if [ "$1" = "" ] then if [ "$DSTACK" = "" ] then echo "pushd: directory stack empty." return 1 fi set $DSTACK cd $1 || return shift 1 DSTACK="$*" else cd $1 > /dev/null || return fi DSTACK="$SAVE $DSTACK" dirs } popd () { if [ "$DSTACK" = "" ] then echo "popd: directory stack empty." return 1 fi set $DSTACK cd $1 shift DSTACK=$* dirs } dirs () { echo "`pwd` $DSTACK" return 0 } kbuild-2695/src/kash/mkinit.sh0000755000000000000000000001115012247157307015006 0ustar rootroot#! /bin/sh # $NetBSD: mkinit.sh,v 1.2 2004/06/15 23:09:54 dsl Exp $ # Copyright (c) 2003 The NetBSD Foundation, Inc. # All rights reserved. # # This code is derived from software contributed to The NetBSD Foundation # by David Laight. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of The NetBSD Foundation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. srcs="$*" nl=' ' openparen='(' backslash='\' includes=' "shell.h" "mystring.h" "init.h" ' defines= decles= event_init= event_reset= event_shellproc= for src in $srcs; do exec <$src decnl="$nl" while IFS=; read -r line; do [ "$line" = x ] case "$line " in INIT["{ "]* ) event=init;; RESET["{ "]* ) event=reset;; SHELLPROC["{ "]* ) event=shellproc;; INCLUDE[\ \ ]* ) IFS=' ' set -- $line # ignore duplicates [ "${includes}" != "${includes%* $2 }" ] && continue includes="$includes$2 " continue ;; MKINIT\ ) # struct declaration decles="$decles$nl" while read -r line decles="${decles}${line}${nl}" [ "$line" != "};" ] do : done decnl="$nl" continue ;; MKINIT["{ "]* ) # strip initialiser def=${line#MKINIT} comment="${def#*;}" def="${def%;$comment}" def="${def%%=*}" def="${def% }" decles="${decles}${decnl}extern${def};${comment}${nl}" decnl= continue ;; \#define[\ \ ]* ) IFS=' ' set -- $line # Ignore those with arguments [ "$2" = "${2##*$openparen}" ] || continue # and multiline definitions [ "$line" = "${line%$backslash}" ] || continue defines="${defines}#undef $2${nl}${line}${nl}" continue ;; * ) continue;; esac # code for events ev="${nl} /* from $src: */${nl} {${nl}" while read -r line [ "$line" != "}" ] do # The C program indented by an extra 6 chars using # tabs then spaces. I need to compare the output :-( indent=6 while l=${line# } [ "$l" != "$line" ] do indent=$(($indent + 8)) line="$l" done while l=${line# } [ "$l" != "$line" ] do indent=$(($indent + 1)) line="$l" done [ -z "$line" -o "$line" != "${line###}" ] && indent=0 while [ $indent -ge 8 ] do ev="$ev " indent="$(($indent - 8))" done while [ $indent -gt 0 ] do ev="$ev " indent="$(($indent - 1))" done ev="${ev}${line}${nl}" done ev="${ev} }${nl}" eval event_$event=\"\$event_$event\$ev\" done done exec >init.c.tmp echo "/*" echo " * This file was generated by the mkinit program." echo " */" echo IFS=' ' for f in $includes; do echo "#include $f" done echo "#include \"shinstance.h\"" echo echo echo echo "$defines" echo echo "$decles" echo echo echo "/*" echo " * Initialization code." echo " */" echo echo "void" echo "init(shinstance *psh) {" echo "${event_init%$nl}" echo "}" echo echo echo echo "/*" echo " * This routine is called when an error or an interrupt occurs in an" echo " * interactive shell and control is returned to the main command loop." echo " */" echo echo "void" echo "reset(shinstance *psh) {" echo "${event_reset%$nl}" echo "}" echo echo echo echo "/*" echo " * This routine is called to initialize the shell to run a shell procedure." echo " */" echo echo "void" echo "initshellproc(shinstance *psh) {" echo "${event_shellproc%$nl}" echo "}" exec >&- mv init.c.tmp init.c kbuild-2695/src/kash/builtins.def0000644000000000000000000000606712247157307015500 0ustar rootroot#!/bin/sh - # $NetBSD: builtins.def,v 1.21 2004/07/13 15:05:59 seb Exp $ # # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)builtins.def 8.4 (Berkeley) 5/4/95 # # This file lists all the builtin commands. The first column is the name # of a C routine. # The -j flag specifies that this command is to be excluded from systems # without job control. # The -h flag specifies that this command is to be excluded from systems # based on the SMALL compile-time symbol. # The -s flag specifies that this is a posix 'special builtin' command. # The -u flag specifies that this is a posix 'standard utility'. # The rest of the line specifies the command name or names used to run # the command. bltincmd -u command bgcmd -j -u bg breakcmd -s break -s continue cdcmd -u cd chdir dotcmd -s . echocmd echo evalcmd -s eval execcmd -s exec exitcmd -s exit expcmd exp let exportcmd -s export -s readonly falsecmd -u false histcmd -h -u fc inputrc inputrc fgcmd -j -u fg getoptscmd -u getopts hashcmd hash jobidcmd jobid jobscmd -u jobs localcmd local #ifndef SMALL printfcmd printf #endif pwdcmd -u pwd readcmd -u read returncmd -s return setcmd -s set setvarcmd setvar shiftcmd -s shift timescmd -s times trapcmd -s trap truecmd -s : -u true typecmd type umaskcmd -u umask unaliascmd -u unalias unsetcmd -s unset waitcmd -u wait aliascmd -u alias ulimitcmd ulimit testcmd test [ killcmd -u kill # mandated by posix for 'kill %job' wordexpcmd wordexp #newgrp -u newgrp # optional command in posix #exprcmd expr kbuild-2695/src/kash/memalloc.c0000644000000000000000000001773212247157307015125 0ustar rootroot/* $NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $"); #endif /* not lint */ #endif #include #include "shell.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "machdep.h" #include "mystring.h" #include "shinstance.h" /* * Like malloc, but returns an error when out of space. */ pointer ckmalloc(shinstance *psh, size_t nbytes) { pointer p; p = sh_malloc(psh, nbytes); if (p == NULL) error(psh, "Out of space"); return p; } /* * Same for realloc. */ pointer ckrealloc(struct shinstance *psh, pointer p, size_t nbytes) { p = sh_realloc(psh, p, nbytes); if (p == NULL) error(psh, "Out of space"); return p; } /* * Make a copy of a string in safe storage. */ char * savestr(struct shinstance *psh, const char *s) { char *p; size_t len = strlen(s); p = ckmalloc(psh, len + 1); memcpy(p, s, len + 1); return p; } /* * Parse trees for commands are allocated in lifo order, so we use a stack * to make this more efficient, and also to avoid all sorts of exception * handling code to handle interrupts in the middle of a parse. * * The size 504 was chosen because the Ultrix malloc handles that size * well. */ //#define MINSIZE 504 /* minimum size of a block */ //struct stack_block { // struct stack_block *prev; // char space[MINSIZE]; //}; //struct stack_block stackbase; //struct stack_block *stackp = &stackbase; //struct stackmark *markp; //char *stacknxt = stackbase.space; //int stacknleft = MINSIZE; //int sstrnleft; //int herefd = -1; pointer stalloc(shinstance *psh, size_t nbytes) { char *p; nbytes = SHELL_ALIGN(nbytes); if (nbytes > (size_t)psh->stacknleft || psh->stacknleft < 0) { size_t blocksize; struct stack_block *sp; blocksize = nbytes; if (blocksize < MINSIZE) blocksize = MINSIZE; INTOFF; sp = ckmalloc(psh, sizeof(struct stack_block) - MINSIZE + blocksize); sp->prev = psh->stackp; psh->stacknxt = sp->space; psh->stacknleft = (int)blocksize; psh->stackp = sp; INTON; } p = psh->stacknxt; psh->stacknxt += nbytes; psh->stacknleft -= (int)nbytes; return p; } void stunalloc(shinstance *psh, pointer p) { if (p == NULL) { /*DEBUG */ shfile_write(&psh->fdtab, 2, "stunalloc\n", 10); sh_abort(psh); } psh->stacknleft += (int)(psh->stacknxt - (char *)p); psh->stacknxt = p; } void setstackmark(shinstance *psh, struct stackmark *mark) { mark->stackp = psh->stackp; mark->stacknxt = psh->stacknxt; mark->stacknleft = psh->stacknleft; mark->marknext = psh->markp; psh->markp = mark; } void popstackmark(shinstance *psh, struct stackmark *mark) { struct stack_block *sp; INTOFF; psh->markp = mark->marknext; while (psh->stackp != mark->stackp) { sp = psh->stackp; psh->stackp = sp->prev; ckfree(psh, sp); } psh->stacknxt = mark->stacknxt; psh->stacknleft = mark->stacknleft; INTON; } /* * When the parser reads in a string, it wants to stick the string on the * stack and only adjust the stack pointer when it knows how big the * string is. Stackblock (defined in stack.h) returns a pointer to a block * of space on top of the stack and stackblocklen returns the length of * this block. Growstackblock will grow this space by at least one byte, * possibly moving it (like realloc). Grabstackblock actually allocates the * part of the block that has been used. */ void growstackblock(shinstance *psh) { int newlen = SHELL_ALIGN(psh->stacknleft * 2 + 100); if (psh->stacknxt == psh->stackp->space && psh->stackp != &psh->stackbase) { struct stack_block *oldstackp; struct stackmark *xmark; struct stack_block *sp; INTOFF; oldstackp = psh->stackp; sp = psh->stackp; psh->stackp = sp->prev; sp = ckrealloc(psh, (pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen); sp->prev = psh->stackp; psh->stackp = sp; psh->stacknxt = sp->space; psh->stacknleft = newlen; /* * Stack marks pointing to the start of the old block * must be relocated to point to the new block */ xmark = psh->markp; while (xmark != NULL && xmark->stackp == oldstackp) { xmark->stackp = psh->stackp; xmark->stacknxt = psh->stacknxt; xmark->stacknleft = psh->stacknleft; xmark = xmark->marknext; } INTON; } else { char *oldspace = psh->stacknxt; int oldlen = psh->stacknleft; char *p = stalloc(psh, newlen); (void)memcpy(p, oldspace, oldlen); psh->stacknxt = p; /* free the space */ psh->stacknleft += newlen; /* we just allocated */ } } void grabstackblock(shinstance *psh, int len) { len = SHELL_ALIGN(len); psh->stacknxt += len; psh->stacknleft -= len; } /* * The following routines are somewhat easier to use than the above. * The user declares a variable of type STACKSTR, which may be declared * to be a register. The macro STARTSTACKSTR initializes things. Then * the user uses the macro STPUTC to add characters to the string. In * effect, STPUTC(psh, c, p) is the same as *p++ = c except that the stack is * grown as necessary. When the user is done, she can just leave the * string there and refer to it using stackblock(psh). Or she can allocate * the space for it using grabstackstr(). If it is necessary to allow * someone else to use the stack temporarily and then continue to grow * the string, the user should use grabstack to allocate the space, and * then call ungrabstr(p) to return to the previous mode of operation. * * USTPUTC is like STPUTC except that it doesn't check for overflow. * CHECKSTACKSPACE can be called before USTPUTC to ensure that there * is space for at least one character. */ char * growstackstr(shinstance *psh) { int len = stackblocksize(psh); if (psh->herefd >= 0 && len >= 1024) { xwrite(psh, psh->herefd, stackblock(psh), len); psh->sstrnleft = len - 1; return stackblock(psh); } growstackblock(psh); psh->sstrnleft = stackblocksize(psh) - len - 1; return stackblock(psh) + len; } /* * Called from CHECKSTRSPACE. */ char * makestrspace(shinstance *psh) { int len = stackblocksize(psh) - psh->sstrnleft; growstackblock(psh); psh->sstrnleft = stackblocksize(psh) - len; return stackblock(psh) + len; } void ungrabstackstr(shinstance *psh, char *s, char *p) { psh->stacknleft += (int)(psh->stacknxt - s); psh->stacknxt = s; psh->sstrnleft = (int)(psh->stacknleft - (p - s)); } kbuild-2695/src/kash/shfile.c0000644000000000000000000016541012247157307014603 0ustar rootroot/* $Id: shfile.c 2681 2013-04-14 18:41:58Z bird $ */ /** @file * * File management. * * Copyright (c) 2007-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "shfile.h" #include "shinstance.h" /* TRACE2 */ #include #include #include #include #if K_OS == K_OS_WINDOWS # include # ifndef PIPE_BUF # define PIPE_BUF 512 # endif # include # define WIN32_NO_STATUS # include # if !defined(_WIN32_WINNT) # define _WIN32_WINNT 0x0502 /* Windows Server 2003 */ # endif # include //NTSTATUS #else # include # include # include #endif /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** @def SHFILE_IN_USE * Whether the file descriptor table stuff is actually in use or not. */ #if K_OS == K_OS_WINDOWS \ || K_OS == K_OS_OPENBSD /* because of ugly pthread library pipe hacks */ \ || !defined(SH_FORKED_MODE) # define SHFILE_IN_USE #endif /** The max file table size. */ #define SHFILE_MAX 1024 /** The file table growth rate. */ #define SHFILE_GROW 64 /** The min native unix file descriptor. */ #define SHFILE_UNIX_MIN_FD 32 /** The path buffer size we use. */ #define SHFILE_MAX_PATH 4096 /** Set errno and return. Doing a trace in debug build. */ #define RETURN_ERROR(rc, err, msg) \ do { \ TRACE2((NULL, "%s: " ## msg ## " - returning %d / %d\n", __FUNCTION__, (rc), (err))); \ errno = (err); \ return (rc); \ } while (0) #if K_OS == K_OS_WINDOWS /* See msdos.h for description. */ # define FOPEN 0x01 # define FEOFLAG 0x02 # define FCRLF 0x04 # define FPIPE 0x08 # define FNOINHERIT 0x10 # define FAPPEND 0x20 # define FDEV 0x40 # define FTEXT 0x80 # define MY_ObjectBasicInformation 0 # define MY_FileNamesInformation 12 typedef struct { ULONG Attributes; ACCESS_MASK GrantedAccess; ULONG HandleCount; ULONG PointerCount; ULONG PagedPoolUsage; ULONG NonPagedPoolUsage; ULONG Reserved[3]; ULONG NameInformationLength; ULONG TypeInformationLength; ULONG SecurityDescriptorLength; LARGE_INTEGER CreateTime; } MY_OBJECT_BASIC_INFORMATION; #if 0 typedef struct { union { LONG Status; PVOID Pointer; }; ULONG_PTR Information; } MY_IO_STATUS_BLOCK; #else typedef IO_STATUS_BLOCK MY_IO_STATUS_BLOCK; #endif typedef MY_IO_STATUS_BLOCK *PMY_IO_STATUS_BLOCK; typedef struct { ULONG NextEntryOffset; ULONG FileIndex; ULONG FileNameLength; WCHAR FileName[1]; } MY_FILE_NAMES_INFORMATION, *PMY_FILE_NAMES_INFORMATION; typedef NTSTATUS (NTAPI * PFN_NtQueryObject)(HANDLE, int, void *, size_t, size_t *); typedef NTSTATUS (NTAPI * PFN_NtQueryDirectoryFile)(HANDLE, HANDLE, void *, void *, PMY_IO_STATUS_BLOCK, void *, ULONG, int, int, PUNICODE_STRING, int); typedef NTSTATUS (NTAPI * PFN_RtlUnicodeStringToAnsiString)(PANSI_STRING, PCUNICODE_STRING, int); #endif /* K_OS_WINDOWS */ /******************************************************************************* * Global Variables * *******************************************************************************/ #if K_OS == K_OS_WINDOWS static int g_shfile_globals_initialized = 0; static PFN_NtQueryObject g_pfnNtQueryObject = NULL; static PFN_NtQueryDirectoryFile g_pfnNtQueryDirectoryFile = NULL; static PFN_RtlUnicodeStringToAnsiString g_pfnRtlUnicodeStringToAnsiString = NULL; #endif /* K_OS_WINDOWS */ #ifdef SHFILE_IN_USE /** * Close the specified native handle. * * @param native The native file handle. * @param flags The flags in case they might come in handy later. */ static void shfile_native_close(intptr_t native, unsigned flags) { # if K_OS == K_OS_WINDOWS BOOL fRc = CloseHandle((HANDLE)native); assert(fRc); (void)fRc; # else int s = errno; close(native); errno = s; # endif (void)flags; } /** * Grows the descriptor table, making sure that it can hold @a fdMin, * * @returns The max(fdMin, fdFirstNew) on success, -1 on failure. * @param pfdtab The table to grow. * @param fdMin Grow to include this index. */ static int shfile_grow_tab_locked(shfdtab *pfdtab, int fdMin) { /* * Grow the descriptor table. */ int fdRet = -1; shfile *new_tab; int new_size = pfdtab->size + SHFILE_GROW; while (new_size < fdMin) new_size += SHFILE_GROW; new_tab = sh_realloc(shthread_get_shell(), pfdtab->tab, new_size * sizeof(shfile)); if (new_tab) { int i; for (i = pfdtab->size; i < new_size; i++) { new_tab[i].fd = -1; new_tab[i].oflags = 0; new_tab[i].shflags = 0; new_tab[i].native = -1; } fdRet = pfdtab->size; if (fdRet < fdMin) fdRet = fdMin; pfdtab->tab = new_tab; pfdtab->size = new_size; } return fdRet; } /** * Inserts the file into the descriptor table. * * If we're out of memory and cannot extend the table, we'll close the * file, set errno to EMFILE and return -1. * * @returns The file descriptor number. -1 and errno on failure. * @param pfdtab The file descriptor table. * @param native The native file handle. * @param oflags The flags the it was opened/created with. * @param shflags The shell file flags. * @param fdMin The minimum file descriptor number, pass -1 if any is ok. * @param who Who we're doing this for (for logging purposes). */ static int shfile_insert(shfdtab *pfdtab, intptr_t native, unsigned oflags, unsigned shflags, int fdMin, const char *who) { shmtxtmp tmp; int fd; int i; /* * Fend of bad stuff. */ if (fdMin >= SHFILE_MAX) { errno = EMFILE; return -1; } # if K_OS != K_OS_WINDOWS if (fcntl((int)native, F_SETFD, fcntl((int)native, F_GETFD, 0) | FD_CLOEXEC) == -1) { int e = errno; close((int)native); errno = e; return -1; } # endif shmtx_enter(&pfdtab->mtx, &tmp); /* * Search for a fitting unused location. */ fd = -1; for (i = fdMin >= 0 ? fdMin : 0; (unsigned)i < pfdtab->size; i++) if (pfdtab->tab[i].fd == -1) { fd = i; break; } if (fd == -1) fd = shfile_grow_tab_locked(pfdtab, fdMin); /* * Fill in the entry if we've found one. */ if (fd != -1) { pfdtab->tab[fd].fd = fd; pfdtab->tab[fd].oflags = oflags; pfdtab->tab[fd].shflags = shflags; pfdtab->tab[fd].native = native; } else shfile_native_close(native, oflags); shmtx_leave(&pfdtab->mtx, &tmp); if (fd == -1) errno = EMFILE; (void)who; return fd; } # if K_OS != K_OS_WINDOWS /** * Makes a copy of the native file, closes the original, and inserts the copy * into the descriptor table. * * If we're out of memory and cannot extend the table, we'll close the * file, set errno to EMFILE and return -1. * * @returns The file descriptor number. -1 and errno on failure. * @param pfdtab The file descriptor table. * @param pnative The native file handle on input, -1 on output. * @param oflags The flags the it was opened/created with. * @param shflags The shell file flags. * @param fdMin The minimum file descriptor number, pass -1 if any is ok. * @param who Who we're doing this for (for logging purposes). */ static int shfile_copy_insert_and_close(shfdtab *pfdtab, int *pnative, unsigned oflags, unsigned shflags, int fdMin, const char *who) { int fd = -1; int s = errno; int native_copy = fcntl(*pnative, F_DUPFD, SHFILE_UNIX_MIN_FD); close(*pnative); *pnative = -1; errno = s; if (native_copy != -1) fd = shfile_insert(pfdtab, native_copy, oflags, shflags, fdMin, who); return fd; } # endif /* !K_OS_WINDOWS */ /** * Gets a file descriptor and lock the file descriptor table. * * @returns Pointer to the file and table ownership on success, * NULL and errno set to EBADF on failure. * @param pfdtab The file descriptor table. * @param fd The file descriptor number. * @param ptmp See shmtx_enter. */ static shfile *shfile_get(shfdtab *pfdtab, int fd, shmtxtmp *ptmp) { shfile *file = NULL; if ( fd >= 0 && (unsigned)fd < pfdtab->size) { shmtx_enter(&pfdtab->mtx, ptmp); if ((unsigned)fd < pfdtab->size && pfdtab->tab[fd].fd != -1) file = &pfdtab->tab[fd]; else shmtx_leave(&pfdtab->mtx, ptmp); } if (!file) errno = EBADF; return file; } /** * Puts back a file descriptor and releases the table ownership. * * @param pfdtab The file descriptor table. * @param file The file. * @param ptmp See shmtx_leave. */ static void shfile_put(shfdtab *pfdtab, shfile *file, shmtxtmp *ptmp) { shmtx_leave(&pfdtab->mtx, ptmp); assert(file); (void)file; } /** * Constructs a path from the current directory and the passed in path. * * @returns 0 on success, -1 and errno set to ENAMETOOLONG or EINVAL on failure. * * @param pfdtab The file descriptor table * @param path The path the caller supplied. * @param buf Where to put the path. This is assumed to be SHFILE_MAX_PATH * chars in size. */ int shfile_make_path(shfdtab *pfdtab, const char *path, char *buf) { size_t path_len = strlen(path); if (path_len == 0) { errno = EINVAL; return -1; } if (path_len >= SHFILE_MAX_PATH) { errno = ENAMETOOLONG; return -1; } if ( *path == '/' # if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 || *path == '\\' || ( *path && path[1] == ':' && ( (*path >= 'A' && *path <= 'Z') || (*path >= 'a' && *path <= 'z'))) # endif ) { memcpy(buf, path, path_len + 1); } else { size_t cwd_len; shmtxtmp tmp; shmtx_enter(&pfdtab->mtx, &tmp); cwd_len = strlen(pfdtab->cwd); memcpy(buf, pfdtab->cwd, cwd_len); shmtx_leave(&pfdtab->mtx, &tmp); if (cwd_len + path_len + 1 >= SHFILE_MAX_PATH) { errno = ENAMETOOLONG; return -1; } if ( !cwd_len || buf[cwd_len - 1] != '/') buf[cwd_len++] = '/'; memcpy(buf + cwd_len, path, path_len + 1); } # if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 if (!strcmp(buf, "/dev/null")) strcpy(buf, "NUL"); # endif return 0; } # if K_OS == K_OS_WINDOWS /** * Adjusts the file name if it ends with a trailing directory slash. * * Windows APIs doesn't like trailing slashes. * * @returns 1 if it has a directory slash, 0 if not. * * @param abspath The path to adjust (SHFILE_MAX_PATH). */ static int shfile_trailing_slash_hack(char *abspath) { /* * Anything worth adjust here? */ size_t path_len = strlen(abspath); if ( path_len == 0 || ( abspath[path_len - 1] != '/' # if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 && abspath[path_len - 1] != '\\' # endif ) ) return 0; /* * Ok, make the adjustment. */ if (path_len + 2 <= SHFILE_MAX_PATH) { /* Add a '.' to the end. */ abspath[path_len++] = '.'; abspath[path_len] = '\0'; } else { /* No space for a dot, remove the slash if it's alone or just remove one and add a dot like above. */ if ( abspath[path_len - 2] != '/' # if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 && abspath[path_len - 2] != '\\' # endif ) abspath[--path_len] = '\0'; else abspath[path_len - 1] = '.'; } return 1; } /** * Converts a DOS(/Windows) error code to errno, * assigning it to errno. * * @returns -1 * @param err The DOS error. */ static int shfile_dos2errno(int err) { switch (err) { case ERROR_BAD_ENVIRONMENT: errno = E2BIG; break; case ERROR_ACCESS_DENIED: errno = EACCES; break; case ERROR_CURRENT_DIRECTORY: errno = EACCES; break; case ERROR_LOCK_VIOLATION: errno = EACCES; break; case ERROR_NETWORK_ACCESS_DENIED: errno = EACCES; break; case ERROR_CANNOT_MAKE: errno = EACCES; break; case ERROR_FAIL_I24: errno = EACCES; break; case ERROR_DRIVE_LOCKED: errno = EACCES; break; case ERROR_SEEK_ON_DEVICE: errno = EACCES; break; case ERROR_NOT_LOCKED: errno = EACCES; break; case ERROR_LOCK_FAILED: errno = EACCES; break; case ERROR_NO_PROC_SLOTS: errno = EAGAIN; break; case ERROR_MAX_THRDS_REACHED: errno = EAGAIN; break; case ERROR_NESTING_NOT_ALLOWED: errno = EAGAIN; break; case ERROR_INVALID_HANDLE: errno = EBADF; break; case ERROR_INVALID_TARGET_HANDLE: errno = EBADF; break; case ERROR_DIRECT_ACCESS_HANDLE: errno = EBADF; break; case ERROR_WAIT_NO_CHILDREN: errno = ECHILD; break; case ERROR_CHILD_NOT_COMPLETE: errno = ECHILD; break; case ERROR_FILE_EXISTS: errno = EEXIST; break; case ERROR_ALREADY_EXISTS: errno = EEXIST; break; case ERROR_INVALID_FUNCTION: errno = EINVAL; break; case ERROR_INVALID_ACCESS: errno = EINVAL; break; case ERROR_INVALID_DATA: errno = EINVAL; break; case ERROR_INVALID_PARAMETER: errno = EINVAL; break; case ERROR_NEGATIVE_SEEK: errno = EINVAL; break; case ERROR_TOO_MANY_OPEN_FILES: errno = EMFILE; break; case ERROR_FILE_NOT_FOUND: errno = ENOENT; break; case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_INVALID_DRIVE: errno = ENOENT; break; case ERROR_NO_MORE_FILES: errno = ENOENT; break; case ERROR_BAD_NETPATH: errno = ENOENT; break; case ERROR_BAD_NET_NAME: errno = ENOENT; break; case ERROR_BAD_PATHNAME: errno = ENOENT; break; case ERROR_FILENAME_EXCED_RANGE: errno = ENOENT; break; case ERROR_BAD_FORMAT: errno = ENOEXEC; break; case ERROR_ARENA_TRASHED: errno = ENOMEM; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; case ERROR_INVALID_BLOCK: errno = ENOMEM; break; case ERROR_NOT_ENOUGH_QUOTA: errno = ENOMEM; break; case ERROR_DISK_FULL: errno = ENOSPC; break; case ERROR_DIR_NOT_EMPTY: errno = ENOTEMPTY; break; case ERROR_BROKEN_PIPE: errno = EPIPE; break; case ERROR_NOT_SAME_DEVICE: errno = EXDEV; break; default: errno = EINVAL; break; } return -1; } /** * Converts an NT status code to errno, * assigning it to errno. * * @returns -1 * @param rcNt The NT status code. */ static int shfile_nt2errno(NTSTATUS rcNt) { switch (rcNt) { default: errno = EINVAL; break; } return -1; } DWORD shfile_query_handle_access_mask(HANDLE h, PACCESS_MASK pMask) { MY_OBJECT_BASIC_INFORMATION BasicInfo; NTSTATUS rcNt; if (!g_pfnNtQueryObject) return ERROR_NOT_SUPPORTED; rcNt = g_pfnNtQueryObject(h, MY_ObjectBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); if (rcNt >= 0) { *pMask = BasicInfo.GrantedAccess; return NO_ERROR; } if (rcNt != STATUS_INVALID_HANDLE) return ERROR_GEN_FAILURE; return ERROR_INVALID_HANDLE; } # endif /* K_OS == K_OS_WINDOWS */ #endif /* SHFILE_IN_USE */ /** * Converts DOS slashes to UNIX slashes if necessary. * * @param pszPath The path to fix. */ static void shfile_fix_slashes(char *pszPath) { #if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 while ((pszPath = strchr(pszPath, '\\'))) *pszPath++ = '/'; #else (void)pszPath; #endif } /** * Initializes the global variables in this file. */ static void shfile_init_globals(void) { #if K_OS == K_OS_WINDOWS if (!g_shfile_globals_initialized) { HMODULE hNtDll = GetModuleHandle("NTDLL"); g_pfnNtQueryObject = (PFN_NtQueryObject) GetProcAddress(hNtDll, "NtQueryObject"); g_pfnNtQueryDirectoryFile = (PFN_NtQueryDirectoryFile)GetProcAddress(hNtDll, "NtQueryDirectoryFile"); g_pfnRtlUnicodeStringToAnsiString = (PFN_RtlUnicodeStringToAnsiString)GetProcAddress(hNtDll, "RtlUnicodeStringToAnsiString"); if ( !g_pfnRtlUnicodeStringToAnsiString || !g_pfnNtQueryDirectoryFile) { /* fatal error */ } g_shfile_globals_initialized = 1; } #endif } /** * Initializes a file descriptor table. * * @returns 0 on success, -1 and errno on failure. * @param pfdtab The table to initialize. * @param inherit File descriptor table to inherit from. If not specified * we will inherit from the current process as it were. */ int shfile_init(shfdtab *pfdtab, shfdtab *inherit) { int rc; shfile_init_globals(); pfdtab->cwd = NULL; pfdtab->size = 0; pfdtab->tab = NULL; rc = shmtx_init(&pfdtab->mtx); if (!rc) { #ifdef SHFILE_IN_USE /* Get CWD with unix slashes. */ char buf[SHFILE_MAX_PATH]; if (getcwd(buf, sizeof(buf))) { shfile_fix_slashes(buf); pfdtab->cwd = sh_strdup(NULL, buf); if (!inherit) { # if K_OS == K_OS_WINDOWS static const struct { DWORD dwStdHandle; unsigned fFlags; } aStdHandles[3] = { { STD_INPUT_HANDLE, _O_RDONLY }, { STD_OUTPUT_HANDLE, _O_WRONLY }, { STD_ERROR_HANDLE, _O_WRONLY } }; int i; STARTUPINFO Info; ACCESS_MASK Mask; DWORD dwErr; rc = 0; /* Try pick up the Visual C++ CRT file descriptor info. */ __try { GetStartupInfo(&Info); } __except (EXCEPTION_EXECUTE_HANDLER) { memset(&Info, 0, sizeof(Info)); } if ( Info.cbReserved2 > sizeof(int) && (uintptr_t)Info.lpReserved2 >= 0x1000 && (i = *(int *)Info.lpReserved2) >= 1 && i <= 2048 && ( Info.cbReserved2 == i * 5 + 4 //|| Info.cbReserved2 == i * 5 + 1 - check the cygwin sources. || Info.cbReserved2 == i * 9 + 4)) { uint8_t *paf = (uint8_t *)Info.lpReserved2 + sizeof(int); int dwPerH = 1 + (Info.cbReserved2 == i * 9 + 4); DWORD *ph = (DWORD *)(paf + i) + dwPerH * i; HANDLE aStdHandles2[3]; int j; //if (Info.cbReserved2 == i * 5 + 1) - check the cygwin sources. // i--; for (j = 0; j < 3; j++) aStdHandles2[j] = GetStdHandle(aStdHandles[j].dwStdHandle); while (i-- > 0) { ph -= dwPerH; if ( (paf[i] & (FOPEN | FNOINHERIT)) == FOPEN && *ph != (uint32_t)INVALID_HANDLE_VALUE) { HANDLE h = (HANDLE)(intptr_t)*ph; int fd2; int fFlags; int fFlags2; if ( h == aStdHandles2[j = 0] || h == aStdHandles2[j = 1] || h == aStdHandles2[j = 2]) fFlags = aStdHandles[j].fFlags; else { dwErr = shfile_query_handle_access_mask(h, &Mask); if (dwErr == ERROR_INVALID_HANDLE) continue; else if (dwErr == NO_ERROR) { fFlags = 0; if ( (Mask & (GENERIC_READ | FILE_READ_DATA)) && (Mask & (GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA))) fFlags |= O_RDWR; else if (Mask & (GENERIC_READ | FILE_READ_DATA)) fFlags |= O_RDONLY; else if (Mask & (GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) fFlags |= O_WRONLY; else fFlags |= O_RDWR; if ((Mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) == FILE_APPEND_DATA) fFlags |= O_APPEND; } else fFlags = O_RDWR; } if (paf[i] & FPIPE) fFlags2 = SHFILE_FLAGS_PIPE; else if (paf[i] & FDEV) fFlags2 = SHFILE_FLAGS_TTY; else fFlags2 = 0; fd2 = shfile_insert(pfdtab, (intptr_t)h, fFlags, fFlags2, i, "shtab_init"); assert(fd2 == i); (void)fd2; if (fd2 != i) rc = -1; } } } /* Check the three standard handles. */ for (i = 0; i < 3; i++) if ( (unsigned)i >= pfdtab->size || pfdtab->tab[i].fd == -1) { HANDLE hFile = GetStdHandle(aStdHandles[i].dwStdHandle); if (hFile != INVALID_HANDLE_VALUE) { DWORD dwType = GetFileType(hFile); unsigned fFlags = aStdHandles[i].fFlags; unsigned fFlags2; int fd2; if (dwType == FILE_TYPE_CHAR) fFlags2 = SHFILE_FLAGS_TTY; else if (dwType == FILE_TYPE_PIPE) fFlags2 = SHFILE_FLAGS_PIPE; else fFlags2 = SHFILE_FLAGS_FILE; fd2 = shfile_insert(pfdtab, (intptr_t)hFile, fFlags, fFlags2, i, "shtab_init"); assert(fd2 == i); (void)fd2; if (fd2 != i) rc = -1; } } # else /* * Annoying... */ int fd; for (fd = 0; fd < 10; fd++) { int oflags = fcntl(fd, F_GETFL, 0); if (oflags != -1) { int cox = fcntl(fd, F_GETFD, 0); struct stat st; if ( cox != -1 && fstat(fd, &st) != -1) { int native; int fd2; int fFlags2 = 0; if (cox & FD_CLOEXEC) fFlags2 |= SHFILE_FLAGS_CLOSE_ON_EXEC; if (S_ISREG(st.st_mode)) fFlags2 |= SHFILE_FLAGS_FILE; else if (S_ISDIR(st.st_mode)) fFlags2 |= SHFILE_FLAGS_DIR; else if (S_ISCHR(st.st_mode)) fFlags2 |= SHFILE_FLAGS_TTY; else if (S_ISFIFO(st.st_mode)) fFlags2 |= SHFILE_FLAGS_PIPE; else fFlags2 |= SHFILE_FLAGS_TTY; native = fcntl(fd, F_DUPFD, SHFILE_UNIX_MIN_FD); if (native == -1) native = fd; fd2 = shfile_insert(pfdtab, native, oflags, fFlags2, fd, "shtab_init"); assert(fd2 == fd); (void)fd2; if (fd2 != fd) rc = -1; if (native != fd) close(fd); } } } # endif } else { /** @todo */ errno = ENOSYS; rc = -1; } } else rc = -1; #endif } return rc; } #if K_OS == K_OS_WINDOWS && defined(SHFILE_IN_USE) /** * Changes the inheritability of a file descriptro, taking console handles into * account. * * @note This MAY change the native handle for the entry. * * @returns The native handle. * @param pfd The file descriptor to change. * @param set If set, make child processes inherit the handle, if clear * make them not inherit it. */ static HANDLE shfile_set_inherit_win(shfile *pfd, int set) { HANDLE hFile = (HANDLE)pfd->native; if (!SetHandleInformation(hFile, HANDLE_FLAG_INHERIT, set ? HANDLE_FLAG_INHERIT : 0)) { /* SetHandleInformation doesn't work for console handles, so we have to duplicate the handle to change the inheritability. */ DWORD err = GetLastError(); if ( err == ERROR_INVALID_PARAMETER && DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(), &hFile, 0, set ? TRUE : FALSE /* bInheritHandle */, DUPLICATE_SAME_ACCESS)) { TRACE2((NULL, "shfile_set_inherit_win: %p -> %p (set=%d)\n", pfd->native, hFile, set)); if (!CloseHandle((HANDLE)pfd->native)) assert(0); pfd->native = (intptr_t)hFile; } else { err = GetLastError(); assert(0); hFile = (HANDLE)pfd->native; } } return hFile; } /** * Helper for shfork. * * @param pfdtab The file descriptor table. * @param set Whether to make all handles inheritable (1) or * to restore them to the rigth state (0). * @param hndls Where to store the three standard handles. */ void shfile_fork_win(shfdtab *pfdtab, int set, intptr_t *hndls) { shmtxtmp tmp; unsigned i; shmtx_enter(&pfdtab->mtx, &tmp); TRACE2((NULL, "shfile_fork_win: set=%d\n", set)); i = pfdtab->size; while (i-- > 0) { if (pfdtab->tab[i].fd == i) { shfile_set_inherit_win(&pfdtab->tab[i], set); if (set) TRACE2((NULL, " #%d: native=%#x oflags=%#x shflags=%#x\n", i, pfdtab->tab[i].native, pfdtab->tab[i].oflags, pfdtab->tab[i].shflags)); } } if (hndls) { for (i = 0; i < 3; i++) { if ( pfdtab->size > i && pfdtab->tab[i].fd == i) hndls[i] = pfdtab->tab[i].native; else hndls[i] = (intptr_t)INVALID_HANDLE_VALUE; TRACE2((NULL, "shfile_fork_win: i=%d size=%d fd=%d native=%d hndls[%d]=%p\n", i, pfdtab->size, pfdtab->tab[i].fd, pfdtab->tab[i].native, i, hndls[i])); } } shmtx_leave(&pfdtab->mtx, &tmp); } /** * Helper for sh_execve. * * This is called before and after CreateProcess. On the first call it * will mark the non-close-on-exec handles as inheritable and produce * the startup info for the CRT. On the second call, after CreateProcess, * it will restore the handle inheritability properties. * * @returns Pointer to CRT data if prepare is 1, NULL if prepare is 0. * @param pfdtab The file descriptor table. * @param prepare Which call, 1 if before and 0 if after. * @param sizep Where to store the size of the returned data. * @param hndls Where to store the three standard handles. */ void *shfile_exec_win(shfdtab *pfdtab, int prepare, unsigned short *sizep, intptr_t *hndls) { void *pvRet; shmtxtmp tmp; unsigned count; unsigned i; shmtx_enter(&pfdtab->mtx, &tmp); TRACE2((NULL, "shfile_exec_win: prepare=%p\n", prepare)); count = pfdtab->size < (0x10000-4) / (1 + sizeof(HANDLE)) ? pfdtab->size : (0x10000-4) / (1 + sizeof(HANDLE)); while (count > 3 && pfdtab->tab[count - 1].fd == -1) count--; if (prepare) { size_t cbData = sizeof(int) + count * (1 + sizeof(HANDLE)); uint8_t *pbData = sh_malloc(shthread_get_shell(), cbData); uint8_t *paf = pbData + sizeof(int); HANDLE *pah = (HANDLE *)(paf + count); *(int *)pbData = count; i = count; while (i-- > 0) { if ( pfdtab->tab[i].fd == i && !(pfdtab->tab[i].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC)) { HANDLE hFile = shfile_set_inherit_win(&pfdtab->tab[i], 1); TRACE2((NULL, " #%d: native=%#x oflags=%#x shflags=%#x\n", i, hFile, pfdtab->tab[i].oflags, pfdtab->tab[i].shflags)); paf[i] = FOPEN; if (pfdtab->tab[i].oflags & _O_APPEND) paf[i] |= FAPPEND; if (pfdtab->tab[i].oflags & _O_TEXT) paf[i] |= FTEXT; switch (pfdtab->tab[i].shflags & SHFILE_FLAGS_TYPE_MASK) { case SHFILE_FLAGS_TTY: paf[i] |= FDEV; break; case SHFILE_FLAGS_PIPE: paf[i] |= FPIPE; break; } pah[i] = hFile; } else { paf[i] = 0; pah[i] = INVALID_HANDLE_VALUE; } } for (i = 0; i < 3; i++) { if ( i < count && pfdtab->tab[i].fd == i) hndls[i] = pfdtab->tab[i].native; else hndls[i] = (intptr_t)INVALID_HANDLE_VALUE; TRACE2((NULL, "shfile_exec_win: i=%d count=%d fd=%d native=%d hndls[%d]=\n", i, count, pfdtab->tab[i].fd, pfdtab->tab[i].native, i, hndls[i])); } *sizep = (unsigned short)cbData; pvRet = pbData; } else { assert(!hndls); assert(!sizep); i = count; while (i-- > 0) { if ( pfdtab->tab[i].fd == i && !(pfdtab->tab[i].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC)) shfile_set_inherit_win(&pfdtab->tab[i], 0); } pvRet = NULL; } shmtx_leave(&pfdtab->mtx, &tmp); return pvRet; } #endif /* K_OS_WINDOWS */ #if K_OS != K_OS_WINDOWS /** * Prepare file handles for inherting before a execve call. * * This is only used in the normal mode, so we've forked and need not worry * about cleaning anything up after us. Nor do we need think about locking. * * @returns 0 on success, -1 on failure. */ int shfile_exec_unix(shfdtab *pfdtab) { int rc = 0; # ifdef SHFILE_IN_USE unsigned fd; for (fd = 0; fd < pfdtab->size; fd++) { if ( pfdtab->tab[fd].fd != -1 && !(pfdtab->tab[fd].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC) ) { TRACE2((NULL, "shfile_exec_unix: %d => %d\n", pfdtab->tab[fd].native, fd)); if (dup2(pfdtab->tab[fd].native, fd) < 0) { /* fatal_error(NULL, "shfile_exec_unix: failed to move %d to %d", pfdtab->tab[fd].fd, fd); */ rc = -1; } } } # endif return rc; } #endif /* !K_OS_WINDOWS */ /** * open(). */ int shfile_open(shfdtab *pfdtab, const char *name, unsigned flags, mode_t mode) { int fd; #ifdef SHFILE_IN_USE char absname[SHFILE_MAX_PATH]; # if K_OS == K_OS_WINDOWS HANDLE hFile; DWORD dwDesiredAccess; DWORD dwShareMode; DWORD dwCreationDisposition; DWORD dwFlagsAndAttributes; SECURITY_ATTRIBUTES SecurityAttributes; # ifndef _O_ACCMODE # define _O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR) # endif switch (flags & (_O_ACCMODE | _O_APPEND)) { case _O_RDONLY: dwDesiredAccess = GENERIC_READ; break; case _O_RDONLY | _O_APPEND: dwDesiredAccess = GENERIC_READ; break; case _O_WRONLY: dwDesiredAccess = GENERIC_WRITE; break; case _O_WRONLY | _O_APPEND: dwDesiredAccess = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); break; case _O_RDWR: dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; break; case _O_RDWR | _O_APPEND: dwDesiredAccess = GENERIC_READ | (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); break; default: RETURN_ERROR(-1, EINVAL, "invalid mode"); } dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = FALSE; if (flags & _O_CREAT) { if ((flags & (_O_EXCL | _O_TRUNC)) == (_O_EXCL | _O_TRUNC)) RETURN_ERROR(-1, EINVAL, "_O_EXCL | _O_TRUNC"); if (flags & _O_TRUNC) dwCreationDisposition = CREATE_ALWAYS; /* not 100%, but close enough */ else if (flags & _O_EXCL) dwCreationDisposition = CREATE_NEW; else dwCreationDisposition = OPEN_ALWAYS; } else if (flags & _O_TRUNC) dwCreationDisposition = TRUNCATE_EXISTING; else dwCreationDisposition = OPEN_EXISTING; if (!(flags & _O_CREAT) || (mode & 0222)) dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; else dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY; fd = shfile_make_path(pfdtab, name, &absname[0]); if (!fd) { SetLastError(0); hFile = CreateFileA(absname, dwDesiredAccess, dwShareMode, &SecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL /* hTemplateFile */); if (hFile != INVALID_HANDLE_VALUE) fd = shfile_insert(pfdtab, (intptr_t)hFile, flags, 0, -1, "shfile_open"); else fd = shfile_dos2errno(GetLastError()); } # else /* K_OS != K_OS_WINDOWS */ fd = shfile_make_path(pfdtab, name, &absname[0]); if (!fd) { fd = open(absname, flags, mode); if (fd != -1) fd = shfile_copy_insert_and_close(pfdtab, &fd, flags, 0, -1, "shfile_open"); } # endif /* K_OS != K_OS_WINDOWS */ #else fd = open(name, flags, mode); #endif TRACE2((NULL, "shfile_open(%p:{%s}, %#x, 0%o) -> %d [%d]\n", name, name, flags, mode, fd, errno)); return fd; } int shfile_pipe(shfdtab *pfdtab, int fds[2]) { int rc = -1; #ifdef SHFILE_IN_USE # if K_OS == K_OS_WINDOWS HANDLE hRead = INVALID_HANDLE_VALUE; HANDLE hWrite = INVALID_HANDLE_VALUE; SECURITY_ATTRIBUTES SecurityAttributes; SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = FALSE; fds[1] = fds[0] = -1; if (CreatePipe(&hRead, &hWrite, &SecurityAttributes, 4096)) { fds[0] = shfile_insert(pfdtab, (intptr_t)hRead, O_RDONLY, SHFILE_FLAGS_PIPE, -1, "shfile_pipe"); if (fds[0] != -1) { fds[1] = shfile_insert(pfdtab, (intptr_t)hWrite, O_WRONLY, SHFILE_FLAGS_PIPE, -1, "shfile_pipe"); if (fds[1] != -1) rc = 0; } # else int native_fds[2]; fds[1] = fds[0] = -1; if (!pipe(native_fds)) { fds[0] = shfile_copy_insert_and_close(pfdtab, &native_fds[0], O_RDONLY, SHFILE_FLAGS_PIPE, -1, "shfile_pipe"); if (fds[0] != -1) { fds[1] = shfile_copy_insert_and_close(pfdtab, &native_fds[1], O_WRONLY, SHFILE_FLAGS_PIPE, -1, "shfile_pipe"); if (fds[1] != -1) rc = 0; } # endif if (fds[1] == -1) { int s = errno; if (fds[0] != -1) { shmtxtmp tmp; shmtx_enter(&pfdtab->mtx, &tmp); rc = fds[0]; pfdtab->tab[rc].fd = -1; pfdtab->tab[rc].oflags = 0; pfdtab->tab[rc].shflags = 0; pfdtab->tab[rc].native = -1; shmtx_leave(&pfdtab->mtx, &tmp); } # if K_OS == K_OS_WINDOWS CloseHandle(hRead); CloseHandle(hWrite); # else close(native_fds[0]); close(native_fds[1]); # endif fds[0] = fds[1] = -1; errno = s; rc = -1; } } else { # if K_OS == K_OS_WINDOWS errno = shfile_dos2errno(GetLastError()); # endif rc = -1; } #else rc = pipe(fds); #endif TRACE2((NULL, "shfile_pipe() -> %d{%d,%d} [%d]\n", rc, fds[0], fds[1], errno)); return rc; } /** * dup(). */ int shfile_dup(shfdtab *pfdtab, int fd) { return shfile_fcntl(pfdtab,fd, F_DUPFD, 0); } /** * Move the file descriptor, closing any existing descriptor at @a fdto. * * @returns fdto on success, -1 and errno on failure. * @param pfdtab The file descriptor table. * @param fdfrom The descriptor to move. * @param fdto Where to move it. */ int shfile_movefd(shfdtab *pfdtab, int fdfrom, int fdto) { #ifdef SHFILE_IN_USE int rc; shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fdfrom, &tmp); if (file) { /* prepare the new entry */ if (fdto >= (int)pfdtab->size) shfile_grow_tab_locked(pfdtab, fdto); if (fdto < (int)pfdtab->size) { if (pfdtab->tab[fdto].fd != -1) shfile_native_close(pfdtab->tab[fdto].native, pfdtab->tab[fdto].oflags); /* setup the target. */ pfdtab->tab[fdto].fd = fdto; pfdtab->tab[fdto].oflags = file->oflags; pfdtab->tab[fdto].shflags = file->shflags; pfdtab->tab[fdto].native = file->native; /* close the source. */ file->fd = -1; file->oflags = 0; file->shflags = 0; file->native = -1; rc = fdto; } else { errno = EMFILE; rc = -1; } shfile_put(pfdtab, file, &tmp); } else rc = -1; return rc; #else int fdnew = dup2(fdfrom, fdto); if (fdnew >= 0) close(fdfrom); return fdnew; #endif } /** * Move the file descriptor to somewhere at @a fdMin or above. * * @returns the new file descriptor success, -1 and errno on failure. * @param pfdtab The file descriptor table. * @param fdfrom The descriptor to move. * @param fdMin The minimum descriptor. */ int shfile_movefd_above(shfdtab *pfdtab, int fdfrom, int fdMin) { #ifdef SHFILE_IN_USE int fdto; shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fdfrom, &tmp); if (file) { /* find a new place */ int i; fdto = -1; for (i = fdMin; (unsigned)i < pfdtab->size; i++) if (pfdtab->tab[i].fd == -1) { fdto = i; break; } if (fdto == -1) fdto = shfile_grow_tab_locked(pfdtab, fdMin); if (fdto != -1) { /* setup the target. */ pfdtab->tab[fdto].fd = fdto; pfdtab->tab[fdto].oflags = file->oflags; pfdtab->tab[fdto].shflags = file->shflags; pfdtab->tab[fdto].native = file->native; /* close the source. */ file->fd = -1; file->oflags = 0; file->shflags = 0; file->native = -1; } else { errno = EMFILE; fdto = -1; } shfile_put(pfdtab, file, &tmp); } else fdto = -1; return fdto; #else int fdnew = fcntl(fdfrom, F_DUPFD, fdMin); if (fdnew >= 0) close(fdfrom); return fdnew; #endif } /** * close(). */ int shfile_close(shfdtab *pfdtab, unsigned fd) { int rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { shfile_native_close(file->native, file->oflags); file->fd = -1; file->oflags = 0; file->shflags = 0; file->native = -1; shfile_put(pfdtab, file, &tmp); rc = 0; } else rc = -1; #else rc = close(fd); #endif TRACE2((NULL, "shfile_close(%d) -> %d [%d]\n", fd, rc, errno)); return rc; } /** * read(). */ long shfile_read(shfdtab *pfdtab, int fd, void *buf, size_t len) { long rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { # if K_OS == K_OS_WINDOWS DWORD dwRead = 0; if (ReadFile((HANDLE)file->native, buf, (DWORD)len, &dwRead, NULL)) rc = dwRead; else rc = shfile_dos2errno(GetLastError()); # else rc = read(file->native, buf, len); # endif shfile_put(pfdtab, file, &tmp); } else rc = -1; #else rc = read(fd, buf, len); #endif return rc; } /** * write(). */ long shfile_write(shfdtab *pfdtab, int fd, const void *buf, size_t len) { long rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { # if K_OS == K_OS_WINDOWS DWORD dwWritten = 0; if (WriteFile((HANDLE)file->native, buf, (DWORD)len, &dwWritten, NULL)) rc = dwWritten; else rc = shfile_dos2errno(GetLastError()); # else rc = write(file->native, buf, len); # endif shfile_put(pfdtab, file, &tmp); } else rc = -1; # ifdef DEBUG if (fd != shthread_get_shell()->tracefd) TRACE2((NULL, "shfile_write(%d,,%d) -> %d [%d]\n", fd, len, rc, errno)); # endif #else if (fd != shthread_get_shell()->tracefd) { int iSavedErrno = errno; struct stat s; int x; x = fstat(fd, &s); TRACE2((NULL, "shfile_write(%d) - %lu bytes (%d) - pos %lu - before; %o\n", fd, (long)s.st_size, x, (long)lseek(fd, 0, SEEK_CUR), s.st_mode )); errno = iSavedErrno; } rc = write(fd, buf, len); #endif return rc; } /** * lseek(). */ long shfile_lseek(shfdtab *pfdtab, int fd, long off, int whench) { long rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { # if K_OS == K_OS_WINDOWS assert(SEEK_SET == FILE_BEGIN); assert(SEEK_CUR == FILE_CURRENT); assert(SEEK_END == FILE_END); rc = SetFilePointer((HANDLE)file->native, off, NULL, whench); if (rc == INVALID_SET_FILE_POINTER) rc = shfile_dos2errno(GetLastError()); # else rc = lseek(file->native, off, whench); # endif shfile_put(pfdtab, file, &tmp); } else rc = -1; #else rc = lseek(fd, off, whench); #endif return rc; } int shfile_fcntl(shfdtab *pfdtab, int fd, int cmd, int arg) { int rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { switch (cmd) { case F_GETFL: rc = file->oflags; break; case F_SETFL: { unsigned mask = O_NONBLOCK | O_APPEND | O_BINARY | O_TEXT; # ifdef O_DIRECT mask |= O_DIRECT; # endif # ifdef O_ASYNC mask |= O_ASYNC; # endif # ifdef O_SYNC mask |= O_SYNC; # endif if ((file->oflags & mask) == (arg & mask)) rc = 0; else { # if K_OS == K_OS_WINDOWS assert(0); errno = EINVAL; rc = -1; # else rc = fcntl(file->native, F_SETFL, arg); if (rc != -1) file->oflags = (file->oflags & ~mask) | (arg & mask); # endif } break; } case F_DUPFD: { # if K_OS == K_OS_WINDOWS HANDLE hNew = INVALID_HANDLE_VALUE; if (DuplicateHandle(GetCurrentProcess(), (HANDLE)file->native, GetCurrentProcess(), &hNew, 0, FALSE /* bInheritHandle */, DUPLICATE_SAME_ACCESS)) rc = shfile_insert(pfdtab, (intptr_t)hNew, file->oflags, file->shflags, arg, "shfile_fcntl"); else rc = shfile_dos2errno(GetLastError()); # else int nativeNew = fcntl(file->native, F_DUPFD, SHFILE_UNIX_MIN_FD); if (nativeNew != -1) rc = shfile_insert(pfdtab, nativeNew, file->oflags, file->shflags, arg, "shfile_fcntl"); else rc = -1; # endif break; } default: errno = -EINVAL; rc = -1; break; } shfile_put(pfdtab, file, &tmp); } else rc = -1; #else rc = fcntl(fd, cmd, arg); #endif switch (cmd) { case F_GETFL: TRACE2((NULL, "shfile_fcntl(%d,F_GETFL,ignored=%d) -> %d [%d]\n", fd, arg, rc, errno)); break; case F_SETFL: TRACE2((NULL, "shfile_fcntl(%d,F_SETFL,newflags=%#x) -> %d [%d]\n", fd, arg, rc, errno)); break; case F_DUPFD: TRACE2((NULL, "shfile_fcntl(%d,F_DUPFD,minfd=%d) -> %d [%d]\n", fd, arg, rc, errno)); break; default: TRACE2((NULL, "shfile_fcntl(%d,%d,%d) -> %d [%d]\n", fd, cmd, arg, rc, errno)); break; } return rc; } int shfile_stat(shfdtab *pfdtab, const char *path, struct stat *pst) { #ifdef SHFILE_IN_USE char abspath[SHFILE_MAX_PATH]; int rc; rc = shfile_make_path(pfdtab, path, &abspath[0]); if (!rc) { # if K_OS == K_OS_WINDOWS int dir_slash = shfile_trailing_slash_hack(abspath); rc = stat(abspath, pst); /** @todo re-implement stat. */ if (!rc && dir_slash && !S_ISDIR(pst->st_mode)) { rc = -1; errno = ENOTDIR; } # else rc = stat(abspath, pst); # endif } TRACE2((NULL, "shfile_stat(,%s,) -> %d [%d]\n", path, rc, errno)); return rc; #else return stat(path, pst); #endif } int shfile_lstat(shfdtab *pfdtab, const char *path, struct stat *pst) { int rc; #ifdef SHFILE_IN_USE char abspath[SHFILE_MAX_PATH]; rc = shfile_make_path(pfdtab, path, &abspath[0]); if (!rc) { # if K_OS == K_OS_WINDOWS int dir_slash = shfile_trailing_slash_hack(abspath); rc = stat(abspath, pst); /** @todo re-implement stat. */ if (!rc && dir_slash && !S_ISDIR(pst->st_mode)) { rc = -1; errno = ENOTDIR; } # else rc = lstat(abspath, pst); # endif } #else rc = stat(path, pst); #endif TRACE2((NULL, "shfile_stat(,%s,) -> %d [%d]\n", path, rc, errno)); return rc; } /** * chdir(). */ int shfile_chdir(shfdtab *pfdtab, const char *path) { int rc; #ifdef SHFILE_IN_USE shinstance *psh = shthread_get_shell(); char abspath[SHFILE_MAX_PATH]; rc = shfile_make_path(pfdtab, path, &abspath[0]); if (!rc) { char *abspath_copy = sh_strdup(psh, abspath); char *free_me = abspath_copy; rc = chdir(abspath); if (!rc) { shmtxtmp tmp; shmtx_enter(&pfdtab->mtx, &tmp); shfile_fix_slashes(abspath_copy); free_me = pfdtab->cwd; pfdtab->cwd = abspath_copy; shmtx_leave(&pfdtab->mtx, &tmp); } sh_free(psh, free_me); } else rc = -1; #else rc = chdir(path); #endif TRACE2((NULL, "shfile_chdir(,%s) -> %d [%d]\n", path, rc, errno)); return rc; } /** * getcwd(). */ char *shfile_getcwd(shfdtab *pfdtab, char *buf, int size) { char *ret; #ifdef SHFILE_IN_USE ret = NULL; if (buf && !size) errno = -EINVAL; else { size_t cwd_size; shmtxtmp tmp; shmtx_enter(&pfdtab->mtx, &tmp); cwd_size = strlen(pfdtab->cwd) + 1; if (buf) { if (cwd_size <= (size_t)size) ret = memcpy(buf, pfdtab->cwd, cwd_size); else errno = ERANGE; } else { if ((size_t)size < cwd_size) size = (int)cwd_size; ret = sh_malloc(shthread_get_shell(), size); if (ret) ret = memcpy(ret, pfdtab->cwd, cwd_size); else errno = ENOMEM; } shmtx_leave(&pfdtab->mtx, &tmp); } #else ret = getcwd(buf, size); #endif TRACE2((NULL, "shfile_getcwd(,%p,%d) -> %s [%d]\n", buf, size, ret, errno)); return ret; } /** * access(). */ int shfile_access(shfdtab *pfdtab, const char *path, int type) { int rc; #ifdef SHFILE_IN_USE char abspath[SHFILE_MAX_PATH]; rc = shfile_make_path(pfdtab, path, &abspath[0]); if (!rc) { # ifdef _MSC_VER if (type & X_OK) type = (type & ~X_OK) | R_OK; # endif rc = access(abspath, type); } #else # ifdef _MSC_VER if (type & X_OK) type = (type & ~X_OK) | R_OK; # endif rc = access(path, type); #endif TRACE2((NULL, "shfile_access(,%s,%#x) -> %d [%d]\n", path, type, rc, errno)); return rc; } /** * isatty() */ int shfile_isatty(shfdtab *pfdtab, int fd) { int rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { # if K_OS == K_OS_WINDOWS rc = (file->shflags & SHFILE_FLAGS_TYPE_MASK) == SHFILE_FLAGS_TTY; # else rc = isatty(file->native); # endif shfile_put(pfdtab, file, &tmp); } else rc = 0; #else rc = isatty(fd); #endif TRACE2((NULL, "isatty(%d) -> %d [%d]\n", fd, rc, errno)); return rc; } /** * fcntl F_SETFD / FD_CLOEXEC. */ int shfile_cloexec(shfdtab *pfdtab, int fd, int closeit) { int rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { if (closeit) file->shflags |= SHFILE_FLAGS_CLOSE_ON_EXEC; else file->shflags &= ~SHFILE_FLAGS_CLOSE_ON_EXEC; shfile_put(pfdtab, file, &tmp); rc = 0; } else rc = -1; #else rc = fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | (closeit ? FD_CLOEXEC : 0)); #endif TRACE2((NULL, "shfile_cloexec(%d, %d) -> %d [%d]\n", fd, closeit, rc, errno)); return rc; } int shfile_ioctl(shfdtab *pfdtab, int fd, unsigned long request, void *buf) { int rc; #ifdef SHFILE_IN_USE shmtxtmp tmp; shfile *file = shfile_get(pfdtab, fd, &tmp); if (file) { # if K_OS == K_OS_WINDOWS rc = -1; errno = ENOSYS; # else rc = ioctl(file->native, request, buf); # endif shfile_put(pfdtab, file, &tmp); } else rc = -1; #else rc = ioctl(fd, request, buf); #endif TRACE2((NULL, "ioctl(%d, %#x, %p) -> %d\n", fd, request, buf, rc)); return rc; } mode_t shfile_get_umask(shfdtab *pfdtab) { /** @todo */ return 022; } void shfile_set_umask(shfdtab *pfdtab, mode_t mask) { /** @todo */ (void)mask; } shdir *shfile_opendir(shfdtab *pfdtab, const char *dir) { #if defined(SHFILE_IN_USE) && K_OS == K_OS_WINDOWS shdir *pdir = NULL; TRACE2((NULL, "shfile_opendir: dir='%s'\n", dir)); shfile_init_globals(); if (g_pfnNtQueryDirectoryFile) { char abspath[SHFILE_MAX_PATH]; if (shfile_make_path(pfdtab, dir, &abspath[0]) == 0) { HANDLE hFile; SECURITY_ATTRIBUTES SecurityAttributes; SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = FALSE; hFile = CreateFileA(abspath, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, &SecurityAttributes, OPEN_EXISTING, FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS, NULL /* hTemplateFile */); if (hFile != INVALID_HANDLE_VALUE) { pdir = (shdir *)sh_malloc(shthread_get_shell(), sizeof(*pdir)); if (pdir) { pdir->pfdtab = pfdtab; pdir->native = hFile; pdir->off = ~(size_t)0; } else CloseHandle(hFile); } else { errno = shfile_dos2errno(GetLastError()); TRACE2((NULL, "shfile_opendir: CreateFileA(%s) -> %d/%d\n", abspath, GetLastError(), errno)); } } } else errno = ENOSYS; return pdir; #else TRACE2((NULL, "shfile_opendir: dir='%s'\n", dir)); return (shdir *)opendir(dir); #endif } shdirent *shfile_readdir(struct shdir *pdir) { #if defined(SHFILE_IN_USE) && K_OS == K_OS_WINDOWS if (pdir) { NTSTATUS rcNt; if ( pdir->off == ~(size_t)0 || pdir->off + sizeof(MY_FILE_NAMES_INFORMATION) >= pdir->cb) { MY_IO_STATUS_BLOCK Ios; memset(&Ios, 0, sizeof(Ios)); rcNt = g_pfnNtQueryDirectoryFile(pdir->native, NULL /*Event*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, &Ios, &pdir->buf[0], sizeof(pdir->buf), MY_FileNamesInformation, FALSE /*ReturnSingleEntry*/, NULL /*FileName*/, pdir->off == ~(size_t)0 /*RestartScan*/); if (rcNt >= 0 && rcNt != STATUS_PENDING) { pdir->cb = Ios.Information; pdir->off = 0; } else if (rcNt == STATUS_NO_MORE_FILES) errno = 0; /* wrong? */ else shfile_nt2errno(rcNt); } if ( pdir->off != ~(size_t)0 && pdir->off + sizeof(MY_FILE_NAMES_INFORMATION) <= pdir->cb) { PMY_FILE_NAMES_INFORMATION pcur = (PMY_FILE_NAMES_INFORMATION)&pdir->buf[pdir->off]; ANSI_STRING astr; UNICODE_STRING ustr; astr.Length = astr.MaximumLength = sizeof(pdir->ent.name); astr.Buffer = &pdir->ent.name[0]; ustr.Length = ustr.MaximumLength = pcur->FileNameLength < ~(USHORT)0 ? (USHORT)pcur->FileNameLength : ~(USHORT)0; ustr.Buffer = &pcur->FileName[0]; rcNt = g_pfnRtlUnicodeStringToAnsiString(&astr, &ustr, 0/*AllocateDestinationString*/); if (rcNt < 0) sprintf(pdir->ent.name, "conversion-failed-%08x-rcNt=%08x-len=%u", pcur->FileIndex, rcNt, pcur->FileNameLength); if (pcur->NextEntryOffset) pdir->off += pcur->NextEntryOffset; else pdir->off = pdir->cb; return &pdir->ent; } } else errno = EINVAL; return NULL; #else struct dirent *pde = readdir((DIR *)pdir); return pde ? (shdirent *)&pde->d_name[0] : NULL; #endif } void shfile_closedir(struct shdir *pdir) { #if defined(SHFILE_IN_USE) && K_OS == K_OS_WINDOWS if (pdir) { CloseHandle(pdir->native); pdir->pfdtab = NULL; pdir->native = INVALID_HANDLE_VALUE; sh_free(shthread_get_shell(), pdir); } else errno = EINVAL; #else closedir((DIR *)pdir); #endif } kbuild-2695/src/kash/mktokens0000755000000000000000000000557012247157307014746 0ustar rootroot#!/bin/sh - # $NetBSD: mktokens,v 1.10 2003/08/22 11:22:23 agc Exp $ # # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)mktokens 8.1 (Berkeley) 5/31/93 # The following is a list of tokens. The second column is nonzero if the # token marks the end of a list. The third column is the name to print in # error messages. if [ -z "$TMPDIR" ]; then TMPDIR="/tmp" export TMPDIR fi F="$TMPDIR/ka$$" echo $F cat > $F <<\! TEOF 1 end of file TNL 0 newline TSEMI 0 ";" TBACKGND 0 "&" TAND 0 "&&" TOR 0 "||" TPIPE 0 "|" TLP 0 "(" TRP 1 ")" TENDCASE 1 ";;" TENDBQUOTE 1 "`" TREDIR 0 redirection TWORD 0 word TIF 0 "if" TTHEN 1 "then" TELSE 1 "else" TELIF 1 "elif" TFI 1 "fi" TWHILE 0 "while" TUNTIL 0 "until" TFOR 0 "for" TDO 1 "do" TDONE 1 "done" TBEGIN 0 "{" TEND 1 "}" TCASE 0 "case" TESAC 1 "esac" TNOT 0 "!" ! nl=`wc -l $F` exec > token.h awk '{print "#define " $1 " " NR-1}' $F echo ' /* Array indicating which tokens mark the end of a list */ const char tokendlist[] = {' awk '{print "\t" $2 ","}' $F echo '}; const char *const tokname[] = {' sed -e 's/"/\\"/g' \ -e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \ $F echo '}; ' sed 's/"//g' $F | awk ' /TIF/{print "#define KWDOFFSET " NR-1; print ""; print "const char *const parsekwd[] = {"} /TIF/,/neverfound/{print " \"" $3 "\","}' echo ' 0 };' rm $F kbuild-2695/src/kash/input.h0000644000000000000000000000550612247157307014474 0ustar rootroot/* $NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)input.h 8.2 (Berkeley) 5/4/95 */ /* PEOF (the end of file marker) is defined in syntax.h */ /* * The input line number. Input.c just defines this variable, and saves * and restores it when files are pushed and popped. The user of this * package must set its value. */ //extern int plinno; //extern int parsenleft; /* number of characters left in input buffer */ //extern char *parsenextc; /* next character in input buffer */ //extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */ char *pfgets(struct shinstance *, char *, int); int pgetc(struct shinstance *); int preadbuffer(struct shinstance *); void pungetc(struct shinstance *); void pushstring(struct shinstance *, char *, size_t, void *); void popstring(struct shinstance *); void setinputfile(struct shinstance *, const char *, int); void setinputfd(struct shinstance *, int, int); void setinputstring(struct shinstance *, char *, int); void popfile(struct shinstance *); void popallfiles(struct shinstance *); void closescript(struct shinstance *, int); #define pgetc_macro(psh) (--(psh)->parsenleft >= 0? *(psh)->parsenextc++ : preadbuffer(psh)) kbuild-2695/src/kash/syntax.h0000644000000000000000000000740112247157307014657 0ustar rootroot/* $NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include /* Syntax classes */ #define CWORD 0 /* character is nothing special */ #define CNL 1 /* newline character */ #define CBACK 2 /* a backslash character */ #define CSQUOTE 3 /* single quote */ #define CDQUOTE 4 /* double quote */ #define CBQUOTE 5 /* backwards single quote */ #define CVAR 6 /* a dollar sign */ #define CENDVAR 7 /* a '}' character */ #define CLP 8 /* a left paren in arithmetic */ #define CRP 9 /* a right paren in arithmetic */ #define CSHEOF 10 /* end of file */ #define CCTL 11 /* like CWORD, except it must be escaped */ #define CSPCL 12 /* these terminate a word */ /* Syntax classes for is_ functions */ #define ISDIGIT 01 /* a digit */ #define ISUPPER 02 /* an upper case letter */ #define ISLOWER 04 /* a lower case letter */ #define ISUNDER 010 /* an underscore */ #define ISSPECL 020 /* the name of a special parameter */ #define PEOF (CHAR_MIN - 1) #define SYNBASE (-PEOF) /* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */ #define UPEOF ((char)PEOF) #define BASESYNTAX (basesyntax + SYNBASE) #define DQSYNTAX (dqsyntax + SYNBASE) #define SQSYNTAX (sqsyntax + SYNBASE) #define ARISYNTAX (arisyntax + SYNBASE) /* These defines assume that the digits are contiguous */ #define is_digit(c) ((unsigned)((c) - '0') <= 9) #define is_alpha(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c))) #define is_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c)))) #define is_in_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c)))) #define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT)) #define digit_val(c) ((c) - '0') #ifdef _MSC_VER extern char basesyntax[]; extern char dqsyntax[]; extern char sqsyntax[]; extern char arisyntax[]; extern char is_type[]; #else extern const char basesyntax[]; extern const char dqsyntax[]; extern const char sqsyntax[]; extern const char arisyntax[]; extern const char is_type[]; #endif kbuild-2695/src/kash/redir.h0000644000000000000000000000444612247157307014444 0ustar rootroot/* $NetBSD: redir.h,v 1.15 2003/08/07 09:05:37 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)redir.h 8.2 (Berkeley) 5/4/95 */ /* flags passed to redirect */ #define REDIR_PUSH 01 /* save previous values of file descriptors */ #define REDIR_BACKQ 02 /* save the command output in memory */ #define REDIR_VFORK 04 /* running under vfork(2), be careful */ union node; void redirect(struct shinstance *, union node *, int); void popredir(struct shinstance *); int fd0_redirected_p(struct shinstance *); void clearredir(struct shinstance *, int); int copyfd(struct shinstance *, int, int); int movefd(struct shinstance *, int, int); int movefd_above(struct shinstance *, int, int); kbuild-2695/src/kash/redir.c0000644000000000000000000002364612247157307014442 0ustar rootroot/* $NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $"); #endif /* not lint */ #endif #include #include /* PIPE_BUF */ #include #include #include /* * Code for dealing with input/output redirection. */ #include "main.h" #include "shell.h" #include "nodes.h" #include "jobs.h" #include "options.h" #include "expand.h" #include "redir.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "shinstance.h" #define EMPTY -2 /* marks an unused slot in redirtab */ #ifndef PIPE_BUF # define PIPESIZE 4096 /* amount of buffering in a pipe */ #else # define PIPESIZE PIPE_BUF #endif MKINIT struct redirtab { struct redirtab *next; short renamed[10]; }; //MKINIT struct redirtab *redirlist; /* * We keep track of whether or not fd0 has been redirected. This is for * background commands, where we want to redirect fd0 to /dev/null only * if it hasn't already been redirected. */ //int fd0_redirected = 0; STATIC void openredirect(shinstance *, union node *, char[10], int); STATIC int openhere(shinstance *, union node *); /* * Process a list of redirection commands. If the REDIR_PUSH flag is set, * old file descriptors are stashed away so that the redirection can be * undone by calling popredir. If the REDIR_BACKQ flag is set, then the * standard output, and the standard error if it becomes a duplicate of * stdout, is saved in memory. */ void redirect(shinstance *psh, union node *redir, int flags) { union node *n; struct redirtab *sv = NULL; int i; int fd; int try; char memory[10]; /* file descriptors to write to memory */ for (i = 10 ; --i >= 0 ; ) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; if (flags & REDIR_PUSH) { /* We don't have to worry about REDIR_VFORK here, as * flags & REDIR_PUSH is never true if REDIR_VFORK is set. */ sv = ckmalloc(psh, sizeof (struct redirtab)); for (i = 0 ; i < 10 ; i++) sv->renamed[i] = EMPTY; sv->next = psh->redirlist; psh->redirlist = sv; } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; try = 0; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) continue; /* redirect from/to same file descriptor */ if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { INTOFF; again: if ((i = shfile_fcntl(&psh->fdtab, fd, F_DUPFD, 10)) == -1) { switch (errno) { case EBADF: if (!try) { openredirect(psh, n, memory, flags); try++; goto again; } /* FALLTHROUGH*/ default: INTON; error(psh, "%d: %s", fd, sh_strerror(psh, errno)); /* NOTREACHED */ } } if (!try) { sv->renamed[fd] = i; shfile_close(&psh->fdtab, fd); } INTON; } else { shfile_close(&psh->fdtab, fd); } if (fd == 0) psh->fd0_redirected++; if (!try) openredirect(psh, n, memory, flags); } if (memory[1]) psh->out1 = &psh->memout; if (memory[2]) psh->out2 = &psh->memout; } STATIC void openredirect(shinstance *psh, union node *redir, char memory[10], int flags) { int fd = redir->nfile.fd; char *fname; int f; int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags; /* * We suppress interrupts so that we won't leave open file * descriptors around. This may not be such a good idea because * an open of a device or a fifo can block indefinitely. */ INTOFF; memory[fd] = 0; switch (redir->nfile.type) { case NFROM: fname = redir->nfile.expfname; if (flags & REDIR_VFORK) eflags = O_NONBLOCK; else eflags = 0; if ((f = shfile_open(&psh->fdtab, fname, O_RDONLY|eflags, 0)) < 0) goto eopen; if (eflags) (void)shfile_fcntl(&psh->fdtab, f, F_SETFL, shfile_fcntl(&psh->fdtab, f, F_GETFL, 0) & ~eflags); break; case NFROMTO: fname = redir->nfile.expfname; if ((f = shfile_open(&psh->fdtab, fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) goto ecreate; break; case NTO: if (Cflag(psh)) oflags |= O_EXCL; /* FALLTHROUGH */ case NCLOBBER: fname = redir->nfile.expfname; if ((f = shfile_open(&psh->fdtab, fname, oflags, 0666)) < 0) goto ecreate; break; case NAPPEND: fname = redir->nfile.expfname; if ((f = shfile_open(&psh->fdtab, fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) goto ecreate; break; case NTOFD: case NFROMFD: if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ if (memory[redir->ndup.dupfd]) memory[fd] = 1; else copyfd(psh, redir->ndup.dupfd, fd); } INTON; return; case NHERE: case NXHERE: f = openhere(psh, redir); break; default: sh_abort(psh); } if (f != fd) { movefd(psh, f, fd); } INTON; return; ecreate: error(psh, "cannot create %s: %s", fname, errmsg(psh, errno, E_CREAT)); eopen: error(psh, "cannot open %s: %s", fname, errmsg(psh, errno, E_OPEN)); } /* * Handle here documents. Normally we fork off a process to write the * data to a pipe. If the document is short, we can stuff the data in * the pipe without forking. */ STATIC int openhere(shinstance *psh, union node *redir) { int pip[2]; size_t len = 0; if (shfile_pipe(&psh->fdtab, pip) < 0) error(psh, "Pipe call failed"); if (redir->type == NHERE) { len = strlen(redir->nhere.doc->narg.text); if (len <= PIPESIZE) { xwrite(psh, pip[1], redir->nhere.doc->narg.text, len); goto out; } } if (forkshell(psh, (struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { shfile_close(&psh->fdtab, pip[0]); sh_signal(psh, SIGINT, SH_SIG_IGN); sh_signal(psh, SIGQUIT, SH_SIG_IGN); sh_signal(psh, SIGHUP, SH_SIG_IGN); #ifdef SIGTSTP sh_signal(psh, SIGTSTP, SH_SIG_IGN); #endif sh_signal(psh, SIGPIPE, SH_SIG_DFL); if (redir->type == NHERE) xwrite(psh, pip[1], redir->nhere.doc->narg.text, len); else expandhere(psh, redir->nhere.doc, pip[1]); sh__exit(psh, 0); } out: shfile_close(&psh->fdtab, pip[1]); return pip[0]; } /* * Undo the effects of the last redirection. */ void popredir(shinstance *psh) { struct redirtab *rp = psh->redirlist; int i; for (i = 0 ; i < 10 ; i++) { if (rp->renamed[i] != EMPTY) { if (i == 0) psh->fd0_redirected--; if (rp->renamed[i] >= 0) { movefd(psh, rp->renamed[i], i); } else { shfile_close(&psh->fdtab, i); } } } INTOFF; psh->redirlist = rp->next; ckfree(psh, rp); INTON; } /* * Undo all redirections. Called on error or interrupt. */ #ifdef mkinit INCLUDE "redir.h" RESET { while (psh->redirlist) popredir(psh); } SHELLPROC { clearredir(psh, 0); } #endif /* Return true if fd 0 has already been redirected at least once. */ int fd0_redirected_p(shinstance *psh) { return psh->fd0_redirected != 0; } /* * Discard all saved file descriptors. */ void clearredir(shinstance *psh, int vforked) { struct redirtab *rp; int i; for (rp = psh->redirlist ; rp ; rp = rp->next) { for (i = 0 ; i < 10 ; i++) { if (rp->renamed[i] >= 0) { shfile_close(&psh->fdtab, rp->renamed[i]); } if (!vforked) rp->renamed[i] = EMPTY; } } } /* * Copy a file descriptor to be >= to. Returns -1 * if the source file descriptor is closed, EMPTY if there are no unused * file descriptors left. */ int copyfd(shinstance *psh, int from, int to) { int newfd; newfd = shfile_fcntl(&psh->fdtab, from, F_DUPFD, to); if (newfd < 0) { if (errno == EMFILE) return EMPTY; error(psh, "%d: %s", from, sh_strerror(psh, errno)); } return newfd; } /* * Move a file descriptor to be == to. Returns -1 * if the source file descriptor is closed, EMPTY if there are no unused * file descriptors left. */ int movefd(shinstance *psh, int from, int to) { int newfd; newfd = shfile_movefd(&psh->fdtab, from, to); if (newfd < 0) { if (errno == EMFILE) return EMPTY; error(psh, "%d: %s", from, sh_strerror(psh, errno)); } return newfd; } /* * Move a file descriptor to be >= to. Returns -1 * if the source file descriptor is closed, EMPTY if there are no unused * file descriptors left. */ int movefd_above(shinstance *psh, int from, int to) { int newfd; newfd = shfile_movefd_above(&psh->fdtab, from, to); if (newfd < 0) { if (errno == EMFILE) return EMPTY; error(psh, "%d: %s", from, sh_strerror(psh, errno)); } return newfd; } kbuild-2695/src/kash/output.h0000644000000000000000000000670112247157307014673 0ustar rootroot/* $NetBSD: output.h,v 1.17 2003/08/07 09:05:36 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)output.h 8.2 (Berkeley) 5/4/95 */ #ifndef OUTPUT_INCL #include /* The stupid, stupid, unix specification guys added dprintf to stdio.h! Wonder what kind of weed they were smoking when doing that... */ #include #undef dprintf #define dprintf mydprintf struct output { char *nextc; int nleft; char *buf; int bufsize; short fd; short flags; struct shinstance *psh; }; /*extern struct output output; extern struct output errout; extern struct output memout; extern struct output *out1; extern struct output *out2;*/ #if !defined(__GNUC__) && !defined(__attribute__) # define __attribute__(a) #endif void open_mem(char *, int, struct output *); void out1str(struct shinstance *, const char *); void out2str(struct shinstance *, const char *); void outstr(const char *, struct output *); void emptyoutbuf(struct output *); void output_flushall(struct shinstance *); void flushout(struct output *); void freestdout(struct shinstance *); void outfmt(struct output *, const char *, ...) __attribute__((__format__(__printf__,2,3))); void out1fmt(struct shinstance *, const char *, ...) __attribute__((__format__(__printf__,2,3))); void dprintf(struct shinstance *, const char *, ...) __attribute__((__format__(__printf__,2,3))); void fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4))); void doformat(struct output *, const char *, va_list); int xwrite(struct shinstance *, int, char *, size_t); int xioctl(struct shinstance *, int, unsigned long, char *); #define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c))) #define out1c(psh, c) outc(c, (psh)->out1); #define out2c(psh, c) outc(c, (psh)->out2); #define OUTPUT_INCL #endif kbuild-2695/src/kash/mystring.h0000644000000000000000000000426612247157307015213 0ustar rootroot/* $NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)mystring.h 8.2 (Berkeley) 5/4/95 */ #ifndef ___mystring_h #define ___mystring_h #include #include "shtypes.h" /* ssize_t */ void scopyn(const char *, char *, ssize_t); int prefix(const char *, const char *); int number(struct shinstance *, const char *); int is_number(const char *); #ifdef _MSC_VER size_t strlcpy(char *dst, const char *src, size_t siz); #endif #define equal(s1, s2) (strcmp(s1, s2) == 0) #define scopy(s1, s2) ((void)strcpy(s2, s1)) #endif kbuild-2695/src/kash/show.h0000644000000000000000000000410512247157307014307 0ustar rootroot/* $NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $ */ /*- * Copyright (c) 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)show.h 1.1 (Berkeley) 5/4/95 */ #ifndef ___show_h #define ___show_h #include union node; void showtree(struct shinstance *, union node *); #ifdef DEBUG void trace(struct shinstance *, const char *, ...); void tracev(struct shinstance *, const char *, va_list); void trargs(struct shinstance *, char **); void trputc(struct shinstance *, int); void trputs(struct shinstance *, const char *); void opentrace(struct shinstance *); #endif #endif kbuild-2695/src/kash/output.c0000644000000000000000000002374712247157307014677 0ustar rootroot/* $NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $"); #endif /* not lint */ #endif /* * Shell output routines. We use our own output routines because: * When a builtin command is interrupted we have to discard * any pending output. * When a builtin command appears in back quotes, we want to * save the output of the command in a region obtained * via malloc, rather than doing a fork and reading the * output of the command via a pipe. * Our output routines may be smaller than the stdio routines. */ #include #include /* defines BUFSIZ */ #include #include #include #include "shell.h" #include "syntax.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "shinstance.h" //#define OUTBUFSIZ BUFSIZ #define BLOCK_OUT -2 /* output to a fixed block of memory */ //#define MEM_OUT -3 /* output to dynamically allocated memory */ #define OUTPUT_ERR 01 /* error occurred on output */ //struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0}; //struct output errout = {NULL, 0, NULL, 100, 2, 0}; //struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0}; //struct output *out1 = &output; //struct output *out2 = &errout; #ifdef mkinit INCLUDE "output.h" INCLUDE "memalloc.h" RESET { psh->out1 = &psh->output; psh->out2 = &psh->errout; if (psh->memout.buf != NULL) { ckfree(psh, psh->memout.buf); psh->memout.buf = NULL; } } #endif #ifdef notdef /* no longer used */ /* * Set up an output file to write to memory rather than a file. */ void open_mem(char *block, int length, struct output *file) { file->nextc = block; file->nleft = --length; file->fd = BLOCK_OUT; file->flags = 0; file->psh = psh; } #endif void out1str(shinstance *psh, const char *p) { outstr(p, psh->out1); } void out2str(shinstance *psh, const char *p) { outstr(p, psh->out2); } void outstr(const char *p, struct output *file) { while (*p) outc(*p++, file); if (file->psh && file == file->psh->out2) flushout(file); } char out_junk[16]; void emptyoutbuf(struct output *dest) { int offset; shinstance *psh = dest->psh; if (dest->fd == BLOCK_OUT) { dest->nextc = out_junk; dest->nleft = sizeof out_junk; dest->flags |= OUTPUT_ERR; } else if (dest->buf == NULL) { INTOFF; dest->buf = ckmalloc(psh, dest->bufsize); dest->nextc = dest->buf; dest->nleft = dest->bufsize; INTON; } else if (dest->fd == MEM_OUT) { offset = dest->bufsize; INTOFF; dest->bufsize <<= 1; dest->buf = ckrealloc(psh, dest->buf, dest->bufsize); dest->nleft = dest->bufsize - offset; dest->nextc = dest->buf + offset; INTON; } else { flushout(dest); } dest->nleft--; } void output_flushall(shinstance *psh) { flushout(&psh->output); flushout(&psh->errout); } void flushout(struct output *dest) { if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0) return; if (xwrite(dest->psh, dest->fd, dest->buf, dest->nextc - dest->buf) < 0) dest->flags |= OUTPUT_ERR; dest->nextc = dest->buf; dest->nleft = dest->bufsize; } void freestdout(shinstance *psh) { INTOFF; if (psh->output.buf) { ckfree(psh, psh->output.buf); psh->output.buf = NULL; psh->output.nleft = 0; } INTON; } void outfmt(struct output *file, const char *fmt, ...) { va_list ap; va_start(ap, fmt); doformat(file, fmt, ap); va_end(ap); } void out1fmt(shinstance *psh, const char *fmt, ...) { va_list ap; va_start(ap, fmt); doformat(psh->out1, fmt, ap); va_end(ap); } void dprintf(shinstance *psh, const char *fmt, ...) { va_list ap; va_start(ap, fmt); doformat(psh->out2, fmt, ap); va_end(ap); flushout(psh->out2); } void fmtstr(char *outbuf, size_t length, const char *fmt, ...) { va_list ap; struct output strout; va_start(ap, fmt); strout.nextc = outbuf; strout.nleft = (int)length; strout.fd = BLOCK_OUT; strout.flags = 0; strout.psh = NULL; doformat(&strout, fmt, ap); outc('\0', &strout); if (strout.flags & OUTPUT_ERR) outbuf[length - 1] = '\0'; va_end(ap); } /* * Formatted output. This routine handles a subset of the printf formats: * - Formats supported: d, u, o, p, X, s, and c. * - The x format is also accepted but is treated like X. * - The l, ll and q modifiers are accepted. * - The - and # flags are accepted; # only works with the o format. * - Width and precision may be specified with any format except c. * - An * may be given for the width or precision. * - The obsolete practice of preceding the width with a zero to get * zero padding is not supported; use the precision field. * - A % may be printed by writing %% in the format string. */ #define TEMPSIZE 32 #ifdef BSD4_4 #define HAVE_VASPRINTF 1 #endif void doformat(struct output *dest, const char *f, va_list ap) { #ifdef HAVE_VASPRINTF char *s; vasprintf(&s, f, ap); outstr(s, dest); free(s); #else /* !HAVE_VASPRINTF */ static const char digit_lower[] = "0123456789abcdef"; static const char digit_upper[] = "0123456789ABCDEF"; const char *digit; char c; char temp[TEMPSIZE]; int flushleft; int sharp; int width; int prec; int islong; int isquad; char *p; int sign; int64_t l; uint64_t num; unsigned base; int len; int size; int pad; while ((c = *f++) != '\0') { if (c != '%') { outc(c, dest); continue; } flushleft = 0; sharp = 0; width = 0; prec = -1; islong = 0; isquad = 0; for (;;) { if (*f == '-') flushleft++; else if (*f == '#') sharp++; else break; f++; } if (*f == '*') { width = va_arg(ap, int); f++; } else { while (is_digit(*f)) { width = 10 * width + digit_val(*f++); } } if (*f == '.') { if (*++f == '*') { prec = va_arg(ap, int); f++; } else { prec = 0; while (is_digit(*f)) { prec = 10 * prec + digit_val(*f++); } } } if (*f == 'l') { f++; if (*f == 'l') { isquad++; f++; } else islong++; } else if (*f == 'q') { isquad++; f++; } digit = digit_upper; switch (*f) { case 'd': if (isquad) l = va_arg(ap, int64_t); else if (islong) l = va_arg(ap, long); else l = va_arg(ap, int); sign = 0; num = l; if (l < 0) { num = -l; sign = 1; } base = 10; goto number; case 'u': base = 10; goto uns_number; case 'o': base = 8; goto uns_number; case 'p': outc('0', dest); outc('x', dest); /*FALLTHROUGH*/ case 'x': /* we don't implement 'x'; treat like 'X' */ digit = digit_lower; case 'X': base = 16; uns_number: /* an unsigned number */ sign = 0; if (isquad) num = va_arg(ap, uint64_t); else if (islong) num = va_arg(ap, unsigned long); else num = va_arg(ap, unsigned int); number: /* process a number */ p = temp + TEMPSIZE - 1; *p = '\0'; while (num) { *--p = digit[num % base]; num /= base; } len = (int)((temp + TEMPSIZE - 1) - p); if (prec < 0) prec = 1; if (sharp && *f == 'o' && prec <= len) prec = len + 1; pad = 0; if (width) { size = len; if (size < prec) size = prec; size += sign; pad = width - size; if (flushleft == 0) { while (--pad >= 0) outc(' ', dest); } } if (sign) outc('-', dest); prec -= len; while (--prec >= 0) outc('0', dest); while (*p) outc(*p++, dest); while (--pad >= 0) outc(' ', dest); break; case 's': p = va_arg(ap, char *); pad = 0; if (width) { len = (int)strlen(p); if (prec >= 0 && len > prec) len = prec; pad = width - len; if (flushleft == 0) { while (--pad >= 0) outc(' ', dest); } } prec++; while (--prec != 0 && *p) outc(*p++, dest); while (--pad >= 0) outc(' ', dest); break; case 'c': c = va_arg(ap, int); outc(c, dest); break; default: outc(*f, dest); break; } f++; } #endif /* !HAVE_VASPRINTF */ } /* * Version of write which resumes after a signal is caught. */ int xwrite(shinstance *psh, int fd, char *buf, size_t nbytes) { int ntry; long i; size_t n; n = nbytes; ntry = 0; for (;;) { i = shfile_write(&psh->fdtab, fd, buf, n); if (i > 0) { if ((n -= i) <= 0) return (int)nbytes; buf += i; ntry = 0; } else if (i == 0) { if (++ntry > 10) return (int)(nbytes - n); } else if (errno != EINTR) { return -1; } } } kbuild-2695/src/kash/bltin/0000755000000000000000000000000012247157307014266 5ustar rootrootkbuild-2695/src/kash/bltin/printf.c0000644000000000000000000003333012247157307015736 0ustar rootroot/* $NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #if !defined(BUILTIN) && !defined(SHELL) __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"); #endif #ifndef lint static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95"; #else __RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $"); #endif /* not lint */ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "shinstance.h" #ifdef __GNUC__ #define ESCAPE '\e' #else #define ESCAPE 033 #endif static void conv_escape_str(char *, void (*)(int)); static char *conv_escape(char *, char *); static char *conv_expand(const char *); static int getchr(void); static double getdouble(void); static int getwidth(void); static intmax_t getintmax(void); static uintmax_t getuintmax(void); static char *getstr(void); static char *mklong(const char *, int); static void check_conversion(const char *, const char *); static void usage(void); static void b_count(int); static void b_output(int); static size_t b_length; static char *b_fmt; static int rval; static char **gargv; #ifdef BUILTIN /* csh builtin */ #define main progprintf #endif #ifdef SHELL /* sh (aka ash) builtin */ #define main printfcmd #include "../../bin/sh/bltin/bltin.h" #endif /* SHELL */ #define PF(f, func) { \ if (fieldwidth != -1) { \ if (precision != -1) \ (void)printf(f, fieldwidth, precision, func); \ else \ (void)printf(f, fieldwidth, func); \ } else if (precision != -1) \ (void)printf(f, precision, func); \ else \ (void)printf(f, func); \ } #define APF(cpp, f, func) { \ if (fieldwidth != -1) { \ if (precision != -1) \ (void)asprintf(cpp, f, fieldwidth, precision, func); \ else \ (void)asprintf(cpp, f, fieldwidth, func); \ } else if (precision != -1) \ (void)asprintf(cpp, f, precision, func); \ else \ (void)asprintf(cpp, f, func); \ } int main(int, char **); int main(int argc, char *argv[]) { char *fmt, *start; int fieldwidth, precision; char nextch; char *format; int ch; #if !defined(SHELL) && !defined(BUILTIN) (void)setlocale (LC_ALL, ""); #endif while ((ch = getopt(argc, argv, "")) != -1) { switch (ch) { case '?': default: usage(); return 1; } } argc -= optind; argv += optind; if (argc < 1) { usage(); return 1; } format = *argv; gargv = ++argv; #define SKIP1 "#-+ 0" #define SKIP2 "*0123456789" do { /* * Basic algorithm is to scan the format string for conversion * specifications -- once one is found, find out if the field * width or precision is a '*'; if it is, gather up value. * Note, format strings are reused as necessary to use up the * provided arguments, arguments of zero/null string are * provided to use up the format string. */ /* find next format specification */ for (fmt = format; (ch = *fmt++) != '\0';) { if (ch == '\\') { char c_ch; fmt = conv_escape(fmt, &c_ch); putchar(c_ch); continue; } if (ch != '%' || (*fmt == '%' && ++fmt)) { (void)putchar(ch); continue; } /* Ok - we've found a format specification, Save its address for a later printf(). */ start = fmt - 1; /* skip to field width */ fmt += strspn(fmt, SKIP1); fieldwidth = *fmt == '*' ? getwidth() : -1; /* skip to possible '.', get following precision */ fmt += strspn(fmt, SKIP2); if (*fmt == '.') ++fmt; precision = *fmt == '*' ? getwidth() : -1; fmt += strspn(fmt, SKIP2); ch = *fmt; if (!ch) { warnx("missing format character"); return (1); } /* null terminate format string to we can use it as an argument to printf. */ nextch = fmt[1]; fmt[1] = 0; switch (ch) { case 'B': { const char *p = conv_expand(getstr()); *fmt = 's'; PF(start, p); break; } case 'b': { /* There has to be a better way to do this, * but the string we generate might have * embedded nulls. */ static char *a, *t; char *cp = getstr(); /* Free on entry in case shell longjumped out */ if (a != NULL) free(a); a = NULL; if (t != NULL) free(t); t = NULL; /* Count number of bytes we want to output */ b_length = 0; conv_escape_str(cp, b_count); t = malloc(b_length + 1); if (t == NULL) break; memset(t, 'x', b_length); t[b_length] = 0; /* Get printf to calculate the lengths */ *fmt = 's'; APF(&a, start, t); b_fmt = a; /* Output leading spaces and data bytes */ conv_escape_str(cp, b_output); /* Add any trailing spaces */ printf("%s", b_fmt); break; } case 'c': { char p = getchr(); PF(start, p); break; } case 's': { char *p = getstr(); PF(start, p); break; } case 'd': case 'i': { intmax_t p = getintmax(); char *f = mklong(start, ch); PF(f, p); break; } case 'o': case 'u': case 'x': case 'X': { uintmax_t p = getuintmax(); char *f = mklong(start, ch); PF(f, p); break; } case 'e': case 'E': case 'f': case 'g': case 'G': { double p = getdouble(); PF(start, p); break; } default: warnx("%s: invalid directive", start); return 1; } *fmt++ = ch; *fmt = nextch; /* escape if a \c was encountered */ if (rval & 0x100) return rval & ~0x100; } } while (gargv != argv && *gargv); return rval; } /* helper functions for conv_escape_str */ static void /*ARGSUSED*/ b_count(int ch) { b_length++; } /* Output one converted character for every 'x' in the 'format' */ static void b_output(int ch) { for (;;) { switch (*b_fmt++) { case 0: b_fmt--; return; case ' ': putchar(' '); break; default: putchar(ch); return; } } } /* * Print SysV echo(1) style escape string * Halts processing string if a \c escape is encountered. */ static void conv_escape_str(char *str, void (*do_putchar)(int)) { int value; int ch; char c; while ((ch = *str++) != '\0') { if (ch != '\\') { do_putchar(ch); continue; } ch = *str++; if (ch == 'c') { /* \c as in SYSV echo - abort all processing.... */ rval |= 0x100; break; } /* * %b string octal constants are not like those in C. * They start with a \0, and are followed by 0, 1, 2, * or 3 octal digits. */ if (ch == '0') { int octnum = 0, i; for (i = 0; i < 3; i++) { if (!isdigit((unsigned char)*str) || *str > '7') break; octnum = (octnum << 3) | (*str++ - '0'); } do_putchar(octnum); continue; } /* \[M][^|-]C as defined by vis(3) */ if (ch == 'M' && *str == '-') { do_putchar(0200 | str[1]); str += 2; continue; } if (ch == 'M' && *str == '^') { str++; value = 0200; ch = '^'; } else value = 0; if (ch == '^') { ch = *str++; if (ch == '?') value |= 0177; else value |= ch & 037; do_putchar(value); continue; } /* Finally test for sequences valid in the format string */ str = conv_escape(str - 1, &c); do_putchar(c); } } /* * Print "standard" escape characters */ static char * conv_escape(char *str, char *conv_ch) { int value; int ch; char num_buf[4], *num_end; ch = *str++; switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': num_buf[0] = ch; ch = str[0]; num_buf[1] = ch; num_buf[2] = ch ? str[1] : 0; num_buf[3] = 0; value = strtoul(num_buf, &num_end, 8); str += num_end - (num_buf + 1); break; case 'x': /* Hexadecimal character constants are not required to be supported (by SuS v1) because there is no consistent way to detect the end of the constant. Supporting 2 byte constants is a compromise. */ ch = str[0]; num_buf[0] = ch; num_buf[1] = ch ? str[1] : 0; num_buf[2] = 0; value = strtoul(num_buf, &num_end, 16); str += num_end - num_buf; break; case '\\': value = '\\'; break; /* backslash */ case '\'': value = '\''; break; /* single quote */ case '"': value = '"'; break; /* double quote */ case 'a': value = '\a'; break; /* alert */ case 'b': value = '\b'; break; /* backspace */ case 'e': value = ESCAPE; break; /* escape */ case 'f': value = '\f'; break; /* form-feed */ case 'n': value = '\n'; break; /* newline */ case 'r': value = '\r'; break; /* carriage-return */ case 't': value = '\t'; break; /* tab */ case 'v': value = '\v'; break; /* vertical-tab */ default: warnx("unknown escape sequence `\\%c'", ch); rval = 1; value = ch; break; } *conv_ch = value; return str; } /* expand a string so that everything is printable */ static char * conv_expand(const char *str) { static char *conv_str; static char no_memory[] = ""; char *cp; int ch; if (conv_str) free(conv_str); /* get a buffer that is definitely large enough.... */ conv_str = malloc(4 * strlen(str) + 1); if (!conv_str) return no_memory; cp = conv_str; while ((ch = *(const unsigned char *)str++) != '\0') { switch (ch) { /* Use C escapes for expected control characters */ case '\\': ch = '\\'; break; /* backslash */ case '\'': ch = '\''; break; /* single quote */ case '"': ch = '"'; break; /* double quote */ case '\a': ch = 'a'; break; /* alert */ case '\b': ch = 'b'; break; /* backspace */ case ESCAPE: ch = 'e'; break; /* escape */ case '\f': ch = 'f'; break; /* form-feed */ case '\n': ch = 'n'; break; /* newline */ case '\r': ch = 'r'; break; /* carriage-return */ case '\t': ch = 't'; break; /* tab */ case '\v': ch = 'v'; break; /* vertical-tab */ default: /* Copy anything printable */ if (isprint(ch)) { *cp++ = ch; continue; } /* Use vis(3) encodings for the rest */ *cp++ = '\\'; if (ch & 0200) { *cp++ = 'M'; ch &= ~0200; } if (ch == 0177) { *cp++ = '^'; *cp++ = '?'; continue; } if (ch < 040) { *cp++ = '^'; *cp++ = ch | 0100; continue; } *cp++ = '-'; *cp++ = ch; continue; } *cp++ = '\\'; *cp++ = ch; } *cp = 0; return conv_str; } static char * mklong(const char *str, int ch) { static char copy[64]; size_t len; len = strlen(str) + 2; if (len > sizeof copy) { warnx("format %s too complex\n", str); len = 4; } (void)memmove(copy, str, len - 3); copy[len - 3] = 'j'; copy[len - 2] = ch; copy[len - 1] = '\0'; return copy; } static int getchr(void) { if (!*gargv) return 0; return (int)**gargv++; } static char * getstr(void) { static char empty[] = ""; if (!*gargv) return empty; return *gargv++; } static int getwidth(void) { long val; char *s, *ep; s = *gargv; if (!*gargv) return (0); gargv++; errno = 0; val = strtoul(s, &ep, 0); check_conversion(s, ep); /* Arbitrarily 'restrict' field widths to 1Mbyte */ if (val < 0 || val > 1 << 20) { warnx("%s: invalid field width", s); return 0; } return val; } static intmax_t getintmax(void) { intmax_t val; char *cp, *ep; cp = *gargv; if (cp == NULL) return 0; gargv++; if (*cp == '\"' || *cp == '\'') return *(cp+1); errno = 0; val = strtoimax(cp, &ep, 0); check_conversion(cp, ep); return val; } static uintmax_t getuintmax(void) { uintmax_t val; char *cp, *ep; cp = *gargv; if (cp == NULL) return 0; gargv++; if (*cp == '\"' || *cp == '\'') return *(cp + 1); /* strtoumax won't error -ve values */ while (isspace(*(unsigned char *)cp)) cp++; if (*cp == '-') { warnx("%s: expected positive numeric value", cp); rval = 1; return 0; } errno = 0; val = strtoumax(cp, &ep, 0); check_conversion(cp, ep); return val; } static double getdouble(void) { double val; char *ep; if (!*gargv) return (0.0); if (**gargv == '\"' || **gargv == '\'') return (double) *((*gargv++)+1); errno = 0; val = strtod(*gargv, &ep); check_conversion(*gargv++, ep); return val; } static void check_conversion(const char *s, const char *ep) { if (*ep) { if (ep == s) warnx("%s: expected numeric value", s); else warnx("%s: not completely converted", s); rval = 1; } else if (errno == ERANGE) { warnx("%s: %s", s, sh_strerror(psh, ERANGE)); rval = 1; } } static void usage(void) { (void)fprintf(stderr, "Usage: %s format [arg ...]\n", getprogname()); } kbuild-2695/src/kash/bltin/test.c0000644000000000000000000002251212247157307015413 0ustar rootroot/* $NetBSD: test.c,v 1.26 2005/02/10 06:56:55 simonb Exp $ */ /* * test(1); version 7-like -- author Erik Baalbergen * modified by Eric Gisin to be used as built-in. * modified by Arnold Robbins to add SVR3 compatibility * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). * modified by J.T. Conklin for NetBSD. * * This program is in the Public Domain. */ #if 0 #ifndef lint __RCSID("$NetBSD: test.c,v 1.26 2005/02/10 06:56:55 simonb Exp $"); #endif #endif #include #include #include #include #include #include #include #include "shell.h" #include "error.h" #include "shinstance.h" /* test(1) accepts the following grammar: oexpr ::= aexpr | aexpr "-o" oexpr ; aexpr ::= nexpr | nexpr "-a" aexpr ; nexpr ::= primary | "!" primary primary ::= unary-operator operand | operand binary-operator operand | operand | "(" oexpr ")" ; unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| "-nt"|"-ot"|"-ef"; operand ::= */ enum token { EOI, FILRD, FILWR, FILEX, FILEXIST, FILREG, FILDIR, FILCDEV, FILBDEV, FILFIFO, FILSOCK, FILSYM, FILGZ, FILTT, FILSUID, FILSGID, FILSTCK, FILNT, FILOT, FILEQ, FILUID, FILGID, STREZ, STRNZ, STREQ, STRNE, STRLT, STRGT, INTEQ, INTNE, INTGE, INTGT, INTLE, INTLT, UNOT, BAND, BOR, LPAREN, RPAREN, OPERAND }; enum token_types { UNOP, BINOP, BUNOP, BBINOP, PAREN }; static struct t_op { const char *op_text; short op_num, op_type; } const ops [] = { {"-r", FILRD, UNOP}, {"-w", FILWR, UNOP}, {"-x", FILEX, UNOP}, {"-e", FILEXIST,UNOP}, {"-f", FILREG, UNOP}, {"-d", FILDIR, UNOP}, {"-c", FILCDEV,UNOP}, {"-b", FILBDEV,UNOP}, {"-p", FILFIFO,UNOP}, {"-u", FILSUID,UNOP}, {"-g", FILSGID,UNOP}, {"-k", FILSTCK,UNOP}, {"-s", FILGZ, UNOP}, {"-t", FILTT, UNOP}, {"-z", STREZ, UNOP}, {"-n", STRNZ, UNOP}, {"-h", FILSYM, UNOP}, /* for backwards compat */ {"-O", FILUID, UNOP}, {"-G", FILGID, UNOP}, {"-L", FILSYM, UNOP}, {"-S", FILSOCK,UNOP}, {"=", STREQ, BINOP}, {"!=", STRNE, BINOP}, {"<", STRLT, BINOP}, {">", STRGT, BINOP}, {"-eq", INTEQ, BINOP}, {"-ne", INTNE, BINOP}, {"-ge", INTGE, BINOP}, {"-gt", INTGT, BINOP}, {"-le", INTLE, BINOP}, {"-lt", INTLT, BINOP}, {"-nt", FILNT, BINOP}, {"-ot", FILOT, BINOP}, {"-ef", FILEQ, BINOP}, {"!", UNOT, BUNOP}, {"-a", BAND, BBINOP}, {"-o", BOR, BBINOP}, {"(", LPAREN, PAREN}, {")", RPAREN, PAREN}, {0, 0, 0} }; //static char **t_wp; //static struct t_op const *t_wp_op; static void syntax(shinstance *, const char *, const char *); static int oexpr(shinstance *, enum token); static int aexpr(shinstance *, enum token); static int nexpr(shinstance *, enum token); static int primary(shinstance *, enum token); static int binop(shinstance *); static int filstat(shinstance *, char *, enum token); static enum token t_lex(shinstance *, char *); static int isoperand(shinstance *); static int getn(shinstance *, const char *); static int newerf(shinstance *, const char *, const char *); static int olderf(shinstance *, const char *, const char *); static int equalf(shinstance *, const char *, const char *); int testcmd(shinstance *psh, int argc, char **argv) { int res; if (strcmp(argv[0], "[") == 0) { if (strcmp(argv[--argc], "]")) error(psh, "missing ]"); argv[argc] = NULL; } if (argc < 2) return 1; psh->t_wp_op = NULL; psh->t_wp = &argv[1]; res = !oexpr(psh, t_lex(psh, *psh->t_wp)); if (*psh->t_wp != NULL && *++psh->t_wp != NULL) syntax(psh, *psh->t_wp, "unexpected operator"); return res; } static void syntax(shinstance *psh, const char *op, const char *msg) { if (op && *op) error(psh, "%s: %s", op, msg); else error(psh, "%s", msg); } static int oexpr(shinstance *psh, enum token n) { int res; res = aexpr(psh, n); if (t_lex(psh, *++psh->t_wp) == BOR) return oexpr(psh, t_lex(psh, *++psh->t_wp)) || res; psh->t_wp--; return res; } static int aexpr(shinstance *psh, enum token n) { int res; res = nexpr(psh, n); if (t_lex(psh, *++psh->t_wp) == BAND) return aexpr(psh, t_lex(psh, *++psh->t_wp)) && res; psh->t_wp--; return res; } static int nexpr(shinstance *psh, enum token n) { if (n == UNOT) return !nexpr(psh, t_lex(psh, *++psh->t_wp)); return primary(psh, n); } static int primary(shinstance *psh, enum token n) { enum token nn; int res; if (n == EOI) return 0; /* missing expression */ if (n == LPAREN) { if ((nn = t_lex(psh, *++psh->t_wp)) == RPAREN) return 0; /* missing expression */ res = oexpr(psh, nn); if (t_lex(psh, *++psh->t_wp) != RPAREN) syntax(psh, NULL, "closing paren expected"); return res; } if (psh->t_wp_op && psh->t_wp_op->op_type == UNOP) { /* unary expression */ if (*++psh->t_wp == NULL) syntax(psh, psh->t_wp_op->op_text, "argument expected"); switch (n) { case STREZ: return strlen(*psh->t_wp) == 0; case STRNZ: return strlen(*psh->t_wp) != 0; case FILTT: return shfile_isatty(&psh->fdtab, getn(psh, *psh->t_wp)); default: return filstat(psh, *psh->t_wp, n); } } if (t_lex(psh, psh->t_wp[1]), psh->t_wp_op && psh->t_wp_op->op_type == BINOP) { return binop(psh); } return strlen(*psh->t_wp) > 0; } static int binop(shinstance *psh) { const char *opnd1, *opnd2; struct t_op const *op; opnd1 = *psh->t_wp; (void) t_lex(psh, *++psh->t_wp); op = psh->t_wp_op; if ((opnd2 = *++psh->t_wp) == NULL) syntax(psh, op->op_text, "argument expected"); switch (op->op_num) { case STREQ: return strcmp(opnd1, opnd2) == 0; case STRNE: return strcmp(opnd1, opnd2) != 0; case STRLT: return strcmp(opnd1, opnd2) < 0; case STRGT: return strcmp(opnd1, opnd2) > 0; case INTEQ: return getn(psh, opnd1) == getn(psh, opnd2); case INTNE: return getn(psh, opnd1) != getn(psh, opnd2); case INTGE: return getn(psh, opnd1) >= getn(psh, opnd2); case INTGT: return getn(psh, opnd1) > getn(psh, opnd2); case INTLE: return getn(psh, opnd1) <= getn(psh, opnd2); case INTLT: return getn(psh, opnd1) < getn(psh, opnd2); case FILNT: return newerf(psh, opnd1, opnd2); case FILOT: return olderf(psh, opnd1, opnd2); case FILEQ: return equalf(psh, opnd1, opnd2); default: sh_abort(psh); /* NOTREACHED */ return -1; } } static int filstat(shinstance *psh, char *nm, enum token mode) { struct stat s; if (mode == FILSYM ? shfile_lstat(&psh->fdtab, nm, &s) : shfile_stat(&psh->fdtab, nm, &s)) return 0; switch (mode) { case FILRD: return shfile_access(&psh->fdtab, nm, R_OK) == 0; case FILWR: return shfile_access(&psh->fdtab, nm, W_OK) == 0; case FILEX: return shfile_access(&psh->fdtab, nm, X_OK) == 0; case FILEXIST: return shfile_access(&psh->fdtab, nm, F_OK) == 0; case FILREG: return S_ISREG(s.st_mode); case FILDIR: return S_ISDIR(s.st_mode); case FILCDEV: #ifdef S_ISCHR return S_ISCHR(s.st_mode); #else return 0; #endif case FILBDEV: #ifdef S_ISBLK return S_ISBLK(s.st_mode); #else return 0; #endif case FILFIFO: #ifdef S_ISFIFO return S_ISFIFO(s.st_mode); #else return 0; #endif case FILSOCK: #ifdef S_ISSOCK return S_ISSOCK(s.st_mode); #else return 0; #endif case FILSYM: return S_ISLNK(s.st_mode); case FILSUID: return (s.st_mode & S_ISUID) != 0; case FILSGID: return (s.st_mode & S_ISGID) != 0; case FILSTCK: #ifdef S_ISVTX return (s.st_mode & S_ISVTX) != 0; #else return 0; #endif case FILGZ: return s.st_size > (off_t)0; case FILUID: return s.st_uid == sh_geteuid(psh); case FILGID: return s.st_gid == sh_getegid(psh); default: return 1; } } static enum token t_lex(shinstance *psh, char *s) { struct t_op const *op; op = ops; if (s == 0) { psh->t_wp_op = NULL; return EOI; } while (op->op_text) { if (strcmp(s, op->op_text) == 0) { if ((op->op_type == UNOP && isoperand(psh)) || (op->op_num == LPAREN && *(psh->t_wp+1) == 0)) break; psh->t_wp_op = op; return op->op_num; } op++; } psh->t_wp_op = NULL; return OPERAND; } static int isoperand(shinstance *psh) { struct t_op const *op; char *s, *t; op = ops; if ((s = *(psh->t_wp+1)) == 0) return 1; if ((t = *(psh->t_wp+2)) == 0) return 0; while (op->op_text) { if (strcmp(s, op->op_text) == 0) return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); op++; } return 0; } /* atoi with error detection */ static int getn(shinstance *psh, const char *s) { char *p; long r; errno = 0; r = strtol(s, &p, 10); if (errno != 0) error(psh, "%s: out of range", s); while (isspace((unsigned char)*p)) p++; if (*p) error(psh, "%s: bad number", s); return (int) r; } static int newerf(shinstance *psh, const char *f1, const char *f2) { struct stat b1, b2; return (shfile_stat(&psh->fdtab, f1, &b1) == 0 && shfile_stat(&psh->fdtab, f2, &b2) == 0 && b1.st_mtime > b2.st_mtime); } static int olderf(shinstance *psh, const char *f1, const char *f2) { struct stat b1, b2; return (shfile_stat(&psh->fdtab, f1, &b1) == 0 && shfile_stat(&psh->fdtab, f2, &b2) == 0 && b1.st_mtime < b2.st_mtime); } static int equalf(shinstance *psh, const char *f1, const char *f2) { struct stat b1, b2; return (shfile_stat(&psh->fdtab, f1, &b1) == 0 && shfile_stat(&psh->fdtab, f2, &b2) == 0 && b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino); } kbuild-2695/src/kash/bltin/echo.10000644000000000000000000000675712247157307015305 0ustar rootroot.\" $NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc Exp $ .\" .\" Copyright (c) 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Kenneth Almquist. .\" Copyright 1989 by Kenneth Almquist .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)echo.1 8.1 (Berkeley) 5/31/93 .\" .Dd May 31, 1993 .Dt ECHO 1 .Os .Sh NAME .Nm echo .Nd produce message in a shell script .Sh SYNOPSIS .Nm .Op Fl n | Fl e .Ar args ... .Sh DESCRIPTION .Nm prints its arguments on the standard output, separated by spaces. Unless the .Fl n option is present, a newline is output following the arguments. The .Fl e option causes .Nm to treat the escape sequences specially, as described in the following paragraph. The .Fl e option is the default, and is provided solely for compatibility with other systems. Only one of the options .Fl n and .Fl e may be given. .Pp If any of the following sequences of characters is encountered during output, the sequence is not output. Instead, the specified action is performed: .Bl -tag -width indent .It Li \eb A backspace character is output. .It Li \ec Subsequent output is suppressed. This is normally used at the end of the last argument to suppress the trailing newline that .Nm would otherwise output. .It Li \ef Output a form feed. .It Li \en Output a newline character. .It Li \er Output a carriage return. .It Li \et Output a (horizontal) tab character. .It Li \ev Output a vertical tab. .It Li \e0 Ns Ar digits Output the character whose value is given by zero to three digits. If there are zero digits, a nul character is output. .It Li \e\e Output a backslash. .El .Sh HINTS Remember that backslash is special to the shell and needs to be escaped. To output a message to standard error, say .Pp .D1 echo message \*[Gt]\*[Am]2 .Sh BUGS The octal character escape mechanism .Pq Li \e0 Ns Ar digits differs from the C language mechanism. .Pp There is no way to force .Nm to treat its arguments literally, rather than interpreting them as options and escape sequences. kbuild-2695/src/kash/bltin/Makefile.kup0000644000000000000000000000000012247157307016512 0ustar rootrootkbuild-2695/src/kash/bltin/kill.c0000644000000000000000000001402312247157307015365 0ustar rootroot/* $NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $ */ /* * Copyright (c) 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #if !defined(lint) && !defined(SHELL) __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"); #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)kill.c 8.4 (Berkeley) 4/28/95"; #else __RCSID("$NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $"); #endif /* not lint */ #endif #include #include #include #include #include #include "shtypes.h" #include "jobs.h" #include "error.h" #include "shinstance.h" #ifndef HAVE_SYS_SIGNAME extern void init_sys_signame(void); extern char sys_signame[NSIG][16]; #endif static int nosig(shinstance *, char *); static void printsignals(shinstance *, struct output *); static int signame_to_signum(char *); static int usage(shinstance *psh); int killcmd(shinstance *psh, int argc, char *argv[]) { int errors, numsig, pid; char *ep; if (argc < 2) return usage(psh); numsig = SIGTERM; #ifndef HAVE_SYS_SIGNAME init_sys_signame(); #endif argc--, argv++; if (strcmp(*argv, "-l") == 0) { argc--, argv++; if (argc > 1) return usage(psh); if (argc == 1) { if (isdigit((unsigned char)**argv) == 0) return usage(psh); numsig = strtol(*argv, &ep, 10); if (*ep != '\0') { sh_errx(psh, EXIT_FAILURE, "illegal signal number: %s", *argv); /* NOTREACHED */ } if (numsig >= 128) numsig -= 128; if (numsig <= 0 || numsig >= NSIG) return nosig(psh, *argv); outfmt(psh->out1, "%s\n", sys_signame[numsig]); //sh_exit(psh, 0); return 0; } printsignals(psh, psh->out1); //sh_exit(psh, 0); return 0; } if (!strcmp(*argv, "-s")) { argc--, argv++; if (argc < 1) { sh_warnx(psh, "option requires an argument -- s"); return usage(psh); } if (strcmp(*argv, "0")) { if ((numsig = signame_to_signum(*argv)) < 0) return nosig(psh, *argv); } else numsig = 0; argc--, argv++; } else if (**argv == '-') { ++*argv; if (isalpha((unsigned char)**argv)) { if ((numsig = signame_to_signum(*argv)) < 0) return nosig(psh, *argv); } else if (isdigit((unsigned char)**argv)) { numsig = strtol(*argv, &ep, 10); if (!*argv || *ep) { sh_errx(psh, EXIT_FAILURE, "illegal signal number: %s", *argv); /* NOTREACHED */ } if (numsig < 0 || numsig >= NSIG) return nosig(psh, *argv); } else return nosig(psh, *argv); argc--, argv++; } if (argc == 0) return usage(psh); for (errors = 0; argc; argc--, argv++) { if (*argv[0] == '%') { pid = getjobpgrp(psh, *argv); if (pid == 0) { sh_warnx(psh, "illegal job id: %s", *argv); errors = 1; continue; } } else { pid = strtol(*argv, &ep, 10); if (!**argv || *ep) { sh_warnx(psh, "illegal process id: %s", *argv); errors = 1; continue; } } if (sh_kill(psh, pid, numsig) == -1) { sh_warn(psh, "%s", *argv); errors = 1; } /* Wakeup the process if it was suspended, so it can exit without an explicit 'fg'. */ if (numsig == SIGTERM || numsig == SIGHUP) sh_kill(psh, pid, SIGCONT); } //sh_exit(psh, errors); ///* NOTREACHED */ return errors; } static int signame_to_signum(char *sig) { int n; if (strncasecmp(sig, "sig", 3) == 0) sig += 3; for (n = 1; n < NSIG; n++) { if (!strcasecmp(sys_signame[n], sig)) return (n); } return (-1); } static int nosig(shinstance *psh, char *name) { sh_warnx(psh, "unknown signal %s; valid signals:", name); printsignals(psh, psh->out2); //sh_exit(psh, 1); ///* NOTREACHED */ return 1; } static void printsignals(shinstance *psh, struct output *out) { int sig; size_t len, nl; const char *name; unsigned termwidth = 80; if (shfile_isatty(&psh->fdtab, out->fd)) { sh_winsize win; if (shfile_ioctl(&psh->fdtab, out->fd, TIOCGWINSZ, &win) == 0 && win.ws_col > 0) termwidth = win.ws_col; } for (len = 0, sig = 1; sig < NSIG; sig++) { name = sys_signame[sig]; nl = 1 + strlen(name); if (len + nl >= termwidth) { outfmt(out, "\n"); len = 0; } else if (len != 0) outfmt(out, " "); len += nl; outfmt(out, "%s", name); } if (len != 0) outfmt(out, "\n"); } static int usage(shinstance *psh) { outfmt(psh->out2, "usage: %s [-s signal_name] pid ...\n" " %s -l [exit_status]\n" " %s -signal_name pid ...\n" " %s -signal_number pid ...\n", psh->commandname, psh->commandname, psh->commandname, psh->commandname); //sh_exit(psh, 1); ///* NOTREACHED */ return 1; } kbuild-2695/src/kash/bltin/echo.c0000644000000000000000000000715712247157307015362 0ustar rootroot/* $NetBSD: echo.c,v 1.12 2005/02/06 04:43:43 perry Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)echo.c 8.1 (Berkeley) 5/31/93 */ /* * Echo command. * * echo is steeped in tradition - several of them! * netbsd has supported 'echo [-n | -e] args' in spite of -e not being * documented anywhere. * Posix requires that -n be supported, output from strings containing * \ is implementation defined * The Single Unix Spec requires that \ escapes be treated as if -e * were set, but that -n not be treated as an option. * (ksh supports 'echo [-eEn] args', but not -- so that it is actually * impossible to actually output '-n') * * It is suggested that 'printf "%b" "string"' be used to get \ sequences * expanded. printf is now a builtin of netbsd's sh and csh. */ #include "shinstance.h" #include "builtins.h" int echocmd(shinstance *psh, int argc, char **argv) { char **ap; const char *p; int nflag = 0; int eflag = 0; ap = argv; if (argc) ap++; if ((p = *ap) != NULL && *p == '-') { if (p[1] == 'n' && !p[2]) { nflag = 1; ap++; } else if (p[1] == 'e' && !p[2]) { eflag = 1; ap++; } } while ((p = *ap++) != NULL) { if (!eflag) { out1str(psh, p); } else { char c; int count; while ((c = *p++) != '\0') { if (c == '\\') { switch (*p++) { case 'a': c = '\a'; break; /* bell */ case 'b': c = '\b'; break; case 'c': return 0; /* exit */ case 'e': c = 033; break; /* escape */ case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case '\\': break; /* c = '\\' */ case '0': c = 0; count = 3; while (--count >= 0 && (unsigned)(*p - '0') < 8) c = (c << 3) + (*p++ - '0'); break; default: /* Output the '/' and char following */ p--; break; } } out1c(psh, c); } } if (*ap) out1c(psh, ' '); } if (! nflag) out1c(psh, '\n'); return 0; } kbuild-2695/src/kash/generated/0000755000000000000000000000000012247157307015114 5ustar rootrootkbuild-2695/src/kash/generated/init.c0000644000000000000000000001633212247157307016230 0ustar rootroot/* * This file was generated by the mkinit program. */ #include "shell.h" #include "mystring.h" #include "init.h" #include "eval.h" #include #include "input.h" #include "error.h" #include #include "options.h" #include "output.h" #include "memalloc.h" #include "redir.h" #include #include "trap.h" #include "var.h" #include "shinstance.h" #undef PROFILE #define PROFILE 0 #undef SIGSSIZE #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) #undef MAXPWD #define MAXPWD 256 #undef ALL #define ALL (E_OPEN|E_CREAT|E_EXEC) #undef EV_EXIT #define EV_EXIT 01 /* exit after evaluating tree */ #undef EV_TESTED #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ #undef EV_BACKCMD #define EV_BACKCMD 04 /* command executing within back quotes */ #undef NEWARGS #define NEWARGS 5 #undef MAXHISTLOOPS #define MAXHISTLOOPS 4 /* max recursions through fc */ #undef DEFEDITOR #define DEFEDITOR "ed" /* default editor *should* be $EDITOR */ #undef editing #define editing (Eflag(psh) || Vflag(psh)) #undef EOF_NLEFT #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ #undef DEFINE_OPTIONS #define DEFINE_OPTIONS #undef BLOCK_OUT #define BLOCK_OUT -2 /* output to a fixed block of memory */ #undef OUTPUT_ERR #define OUTPUT_ERR 01 /* error occurred on output */ #undef TEMPSIZE #define TEMPSIZE 32 #undef HAVE_VASPRINTF #define HAVE_VASPRINTF 1 #undef EOFMARKLEN #define EOFMARKLEN 79 #undef OPENBRACE #define OPENBRACE '{' #undef CLOSEBRACE #define CLOSEBRACE '}' #undef EMPTY #define EMPTY -2 /* marks an unused slot in redirtab */ #undef S_DFL #define S_DFL 1 /* default signal handling (SIG_DFL) */ #undef S_CATCH #define S_CATCH 2 /* signal is caught */ #undef S_IGN #define S_IGN 3 /* signal is ignored (SIG_IGN) */ #undef S_HARD_IGN #define S_HARD_IGN 4 /* signal is ignored permenantly */ #undef S_RESET #define S_RESET 5 /* temporary - to reset a hard ignored sig */ #undef INCL_BASE #define INCL_BASE #undef LIBPATHSTRICT #define LIBPATHSTRICT 3 #undef QHINF_EXEINFO #define QHINF_EXEINFO 1 /* NE exeinfo. */ #undef QHINF_READRSRCTBL #define QHINF_READRSRCTBL 2 /* Reads from the resource table. */ #undef QHINF_READFILE #define QHINF_READFILE 3 /* Reads from the executable file. */ #undef QHINF_LIBPATHLENGTH #define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */ #undef QHINF_LIBPATH #define QHINF_LIBPATH 5 /* Gets the entire libpath. */ #undef QHINF_FIXENTRY #define QHINF_FIXENTRY 6 /* NE only */ #undef QHINF_STE #define QHINF_STE 7 /* NE only */ #undef QHINF_MAPSEL #define QHINF_MAPSEL 8 /* NE only */ #undef SET_LEN #define SET_LEN 6 /* initial # of bitcmd struct to malloc */ #undef SET_LEN_INCR #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */ #undef CMD2_CLR #define CMD2_CLR 0x01 #undef CMD2_SET #define CMD2_SET 0x02 #undef CMD2_GBITS #define CMD2_GBITS 0x04 #undef CMD2_OBITS #define CMD2_OBITS 0x08 #undef CMD2_UBITS #define CMD2_UBITS 0x10 #undef STANDARD_BITS #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) #undef SHMEMHDR_MAGIC_FREE #define SHMEMHDR_MAGIC_FREE 0xbeeff00d #undef SHMEMHDR_MAGIC_USED #define SHMEMHDR_MAGIC_USED 0xfeedface #undef SHMEMCHUNK_MAGIC #define SHMEMCHUNK_MAGIC 0x12345678 #undef SHHEAP_MIN_CHUNK #define SHHEAP_MIN_CHUNK 0x80000 //(1024*1024) #undef SHFILE_MAX #define SHFILE_MAX 1024 #undef SHFILE_GROW #define SHFILE_GROW 64 #undef SHFILE_UNIX_MIN_FD #define SHFILE_UNIX_MIN_FD 32 #undef SHFILE_MAX_PATH #define SHFILE_MAX_PATH 4096 #undef YY_NO_UNPUT #define YY_NO_UNPUT extern void rmaliases(shinstance *psh); extern void deletefuncs(struct shinstance *); extern void hash_special_builtins(struct shinstance *); struct redirtab { struct redirtab *next; short renamed[10]; }; /* * Initialization code. */ void init(shinstance *psh) { /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/exec.c: */ { hash_special_builtins(psh); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/input.c: */ { psh->basepf.nextc = psh->basepf.buf = psh->basebuf; } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/options.c: */ { memcpy(&psh->optlist[0], &ro_optlist[0], sizeof(psh->optlist)); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/var.c: */ { char **envp; initvar(psh); for (envp = sh_environ(psh) ; *envp ; envp++) { if (strchr(*envp, '=')) { setvareq(psh, *envp, VEXPORT|VTEXTFIXED); } } } } /* * This routine is called when an error or an interrupt occurs in an * interactive shell and control is returned to the main command loop. */ void reset(shinstance *psh) { /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/eval.c: */ { psh->evalskip = 0; psh->loopnest = 0; psh->funcnest = 0; } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/input.c: */ { if (psh->exception != EXSHELLPROC) psh->parselleft = psh->parsenleft = 0; /* clear input buffer */ popallfiles(psh); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/output.c: */ { psh->out1 = &psh->output; psh->out2 = &psh->errout; if (psh->memout.buf != NULL) { ckfree(psh, psh->memout.buf); psh->memout.buf = NULL; } } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/parser.c: */ { psh->tokpushback = 0; psh->checkkwd = 0; } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/redir.c: */ { while (psh->redirlist) popredir(psh); } } /* * This routine is called to initialize the shell to run a shell procedure. */ void initshellproc(shinstance *psh) { /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/alias.c: */ { rmaliases(psh); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/eval.c: */ { psh->exitstatus = 0; } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/exec.c: */ { deletefuncs(psh); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/input.c: */ { popallfiles(psh); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/jobs.c: */ { psh->backgndpid = -1; #if JOBS psh->jobctl = 0; #endif } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/options.c: */ { int i; for (i = 0; psh->optlist[i].name; i++) psh->optlist[i].val = 0; # if DEBUG == 2 debug(psh) = 1; # endif optschanged(psh); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/redir.c: */ { clearredir(psh, 0); } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/trap.c: */ { char *sm; clear_traps(psh, 0); for (sm = psh->sigmode ; sm < psh->sigmode + NSIG ; sm++) { if (*sm == S_IGN) *sm = S_HARD_IGN; } } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/var.c: */ { shprocvar(psh); } } kbuild-2695/src/kash/generated/arith_lex.c0000644000000000000000000013241012247157307017240 0ustar rootroot#line 2 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/out/darwin.x86/release/obj/kash/arith_lex.c" #line 4 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/out/darwin.x86/release/obj/kash/arith_lex.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 33 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef unsigned int yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define yywrap(n) 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 29 #define YY_END_OF_BUFFER 30 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[39] = { 0, 0, 0, 30, 28, 1, 1, 27, 23, 12, 6, 7, 21, 24, 25, 22, 3, 4, 17, 28, 15, 5, 11, 10, 26, 14, 9, 3, 0, 4, 19, 18, 13, 16, 20, 5, 8, 2, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, 1, 5, 6, 1, 7, 8, 9, 10, 1, 11, 1, 12, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 1, 1, 16, 17, 18, 1, 1, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 1, 1, 21, 20, 1, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 22, 20, 20, 1, 23, 1, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[25] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 3, 1, 3, 1, 1 } ; static yyconst flex_int16_t yy_base[41] = { 0, 0, 0, 47, 48, 48, 48, 29, 48, 39, 48, 48, 48, 48, 48, 48, 12, 14, 14, 27, 15, 0, 48, 20, 48, 48, 48, 22, 0, 24, 48, 48, 48, 48, 48, 0, 48, 0, 48, 38, 40 } ; static yyconst flex_int16_t yy_def[41] = { 0, 38, 1, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 38, 38, 38, 38, 38, 38, 40, 38, 38, 38, 38, 38, 38, 39, 38, 40, 0, 38, 38 } ; static yyconst flex_int16_t yy_nxt[73] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 21, 21, 22, 21, 23, 24, 27, 27, 29, 29, 29, 30, 31, 33, 34, 28, 27, 27, 29, 29, 29, 35, 35, 37, 36, 32, 26, 25, 38, 3, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38 } ; static yyconst flex_int16_t yy_chk[73] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 17, 17, 17, 18, 18, 20, 20, 16, 27, 27, 29, 29, 29, 39, 39, 40, 23, 19, 9, 7, 3, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" #define YY_NO_INPUT 1 /** @todo %option reentrant */ #line 33 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" /* $NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $"); #endif /* not lint */ #endif #include #include "arith.h" #include "error.h" #include "expand.h" #include "var.h" #include "shinstance.h" extern int yylval; extern shinstance *arith_psh; extern char *arith_buf, *arith_startbuf; #undef YY_INPUT #define YY_INPUT(buf,result,max) \ result = (*buf = *arith_buf++) ? 1 : YY_NULL; #define YY_NO_UNPUT /* Avoid unnecessary libc bits. */ #undef ECHO #define ECHO \ do {} while (0) #undef stdin #define stdin \ NULL #undef stdout #define stdout \ NULL #define YY_FATAL_ERROR(msg) \ error(arith_psh, "arith: fatal error: %s", msg) #line 554 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/out/darwin.x86/release/obj/kash/arith_lex.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 104 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" #line 707 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/out/darwin.x86/release/obj/kash/arith_lex.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 39 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 38 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_find_action: yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: /* rule 1 can match eol */ YY_RULE_SETUP #line 105 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { ; } YY_BREAK case 2: YY_RULE_SETUP #line 106 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); } YY_BREAK case 3: YY_RULE_SETUP #line 107 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); } YY_BREAK case 4: YY_RULE_SETUP #line 108 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); } YY_BREAK case 5: YY_RULE_SETUP #line 109 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { char *v = lookupvar(arith_psh, yytext); if (v) { yylval = strtol(v, &v, 0); if (*v == 0) return ARITH_NUM; } error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf); } YY_BREAK case 6: YY_RULE_SETUP #line 117 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_LPAREN); } YY_BREAK case 7: YY_RULE_SETUP #line 118 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_RPAREN); } YY_BREAK case 8: YY_RULE_SETUP #line 119 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_OR); } YY_BREAK case 9: YY_RULE_SETUP #line 120 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_AND); } YY_BREAK case 10: YY_RULE_SETUP #line 121 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_BOR); } YY_BREAK case 11: YY_RULE_SETUP #line 122 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_BXOR); } YY_BREAK case 12: YY_RULE_SETUP #line 123 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_BAND); } YY_BREAK case 13: YY_RULE_SETUP #line 124 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_EQ); } YY_BREAK case 14: YY_RULE_SETUP #line 125 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_NE); } YY_BREAK case 15: YY_RULE_SETUP #line 126 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_GT); } YY_BREAK case 16: YY_RULE_SETUP #line 127 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_GE); } YY_BREAK case 17: YY_RULE_SETUP #line 128 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_LT); } YY_BREAK case 18: YY_RULE_SETUP #line 129 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_LE); } YY_BREAK case 19: YY_RULE_SETUP #line 130 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_LSHIFT); } YY_BREAK case 20: YY_RULE_SETUP #line 131 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_RSHIFT); } YY_BREAK case 21: YY_RULE_SETUP #line 132 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_MUL); } YY_BREAK case 22: YY_RULE_SETUP #line 133 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_DIV); } YY_BREAK case 23: YY_RULE_SETUP #line 134 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_REM); } YY_BREAK case 24: YY_RULE_SETUP #line 135 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_ADD); } YY_BREAK case 25: YY_RULE_SETUP #line 136 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_SUB); } YY_BREAK case 26: YY_RULE_SETUP #line 137 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_BNOT); } YY_BREAK case 27: YY_RULE_SETUP #line 138 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { return(ARITH_NOT); } YY_BREAK case 28: YY_RULE_SETUP #line 139 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" { error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf); } YY_BREAK case 29: YY_RULE_SETUP #line 140 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" ECHO; YY_BREAK #line 939 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/out/darwin.x86/release/obj/kash/arith_lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 39 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 39 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 38); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return 0; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current token. * */ static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif #define YYTABLES_NAME "yytables" #line 140 "/Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/arith_lex.l" void arith_lex_reset() { #ifdef YY_NEW_FILE YY_NEW_FILE; #endif } void * yyalloc(yy_size_t cb) { return sh_malloc(NULL, cb); } void * yyrealloc(void *pv,yy_size_t cb) { return sh_realloc(NULL, pv, cb); } void yyfree(void *pv) { sh_free(NULL, pv); } kbuild-2695/src/kash/generated/arith.c0000644000000000000000000005244012247157307016374 0ustar rootroot#ifndef lint static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; #endif #include #include #define YYBYACC 1 #define YYMAJOR 1 #define YYMINOR 9 #define YYPATCH 20091027 #define YYEMPTY (-1) #define yyclearin (yychar = YYEMPTY) #define yyerrok (yyerrflag = 0) #define YYRECOVERING() (yyerrflag != 0) /* compatibility with bison */ #ifdef YYPARSE_PARAM /* compatibility with FreeBSD */ #ifdef YYPARSE_PARAM_TYPE #define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM) #else #define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM) #endif #else #define YYPARSE_DECL() yyparse(void) #endif /* YYPARSE_PARAM */ extern int YYPARSE_DECL(); static int yygrowstack(void); #define YYPREFIX "yy" /* $NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $"); #endif /* not lint */ #endif #include #include "expand.h" #include "shell.h" #include "error.h" #include "output.h" #include "memalloc.h" #include "shinstance.h" shinstance *arith_psh; const char *arith_buf, *arith_startbuf; void yyerror(const char *); #ifdef TESTARITH int main(int , char *[]); int error(char *); #else # undef malloc # define malloc(cb) sh_malloc(NULL, (cb)) # undef realloc # define realloc(pv,cb) sh_realloc(NULL, (pv), (cb)) # undef free # define free(pv) sh_free(NULL, (pv)) #endif #define ARITH_NUM 257 #define ARITH_LPAREN 258 #define ARITH_RPAREN 259 #define ARITH_OR 260 #define ARITH_AND 261 #define ARITH_BOR 262 #define ARITH_BXOR 263 #define ARITH_BAND 264 #define ARITH_EQ 265 #define ARITH_NE 266 #define ARITH_LT 267 #define ARITH_GT 268 #define ARITH_GE 269 #define ARITH_LE 270 #define ARITH_LSHIFT 271 #define ARITH_RSHIFT 272 #define ARITH_ADD 273 #define ARITH_SUB 274 #define ARITH_MUL 275 #define ARITH_DIV 276 #define ARITH_REM 277 #define ARITH_UNARYMINUS 278 #define ARITH_UNARYPLUS 279 #define ARITH_NOT 280 #define ARITH_BNOT 281 #define YYERRCODE 256 static const short yylhs[] = { -1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; static const short yylen[] = { 2, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, }; static const short yydefred[] = { 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 24, 23, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, }; static const short yydgoto[] = { 7, 8, }; static const short yysindex[] = { -255, 0, -255, -255, -255, -255, -255, 0, -67, -85, 0, 0, 0, 0, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, 0, -50, -34, -19, 141, -261, -233, -233, -223, -223, -223, -223, -253, -253, -248, -248, 0, 0, 0, }; static const short yyrindex[] = { 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 140, 136, 131, 125, 109, 117, 61, 73, 85, 97, 33, 47, 1, 17, 0, 0, 0, }; static const short yygindex[] = { 0, 142, }; #define YYTABLESIZE 418 static const short yytable[] = { 0, 16, 1, 2, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 17, 3, 4, 27, 28, 29, 30, 31, 5, 6, 29, 30, 31, 1, 0, 0, 14, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 0, 15, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 3, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 32, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 3, 3, 0, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, }; static const short yycheck[] = { -1, 0, 257, 258, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 0, 273, 274, 273, 274, 275, 276, 277, 280, 281, 275, 276, 277, 0, -1, -1, 0, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, -1, -1, 0, 271, 272, 273, 274, 275, 276, 277, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 2, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, -1, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 259, 260, 261, 262, 263, 264, 265, 266, 259, 260, 261, 262, 263, 264, 265, 266, 259, 260, 261, 262, 263, 264, 259, 260, 261, 262, 263, 259, 260, 261, 262, 259, 260, 261, 259, 260, -1, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, }; #define YYFINAL 7 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 281 #if YYDEBUG static const char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"ARITH_NUM","ARITH_LPAREN", "ARITH_RPAREN","ARITH_OR","ARITH_AND","ARITH_BOR","ARITH_BXOR","ARITH_BAND", "ARITH_EQ","ARITH_NE","ARITH_LT","ARITH_GT","ARITH_GE","ARITH_LE", "ARITH_LSHIFT","ARITH_RSHIFT","ARITH_ADD","ARITH_SUB","ARITH_MUL","ARITH_DIV", "ARITH_REM","ARITH_UNARYMINUS","ARITH_UNARYPLUS","ARITH_NOT","ARITH_BNOT", }; static const char *yyrule[] = { "$accept : exp", "exp : expr", "expr : ARITH_LPAREN expr ARITH_RPAREN", "expr : expr ARITH_OR expr", "expr : expr ARITH_AND expr", "expr : expr ARITH_BOR expr", "expr : expr ARITH_BXOR expr", "expr : expr ARITH_BAND expr", "expr : expr ARITH_EQ expr", "expr : expr ARITH_GT expr", "expr : expr ARITH_GE expr", "expr : expr ARITH_LT expr", "expr : expr ARITH_LE expr", "expr : expr ARITH_NE expr", "expr : expr ARITH_LSHIFT expr", "expr : expr ARITH_RSHIFT expr", "expr : expr ARITH_ADD expr", "expr : expr ARITH_SUB expr", "expr : expr ARITH_MUL expr", "expr : expr ARITH_DIV expr", "expr : expr ARITH_REM expr", "expr : ARITH_NOT expr", "expr : ARITH_BNOT expr", "expr : ARITH_SUB expr", "expr : ARITH_ADD expr", "expr : ARITH_NUM", }; #endif #ifndef YYSTYPE typedef int YYSTYPE; #endif #if YYDEBUG #include #endif /* define the initial stack-sizes */ #ifdef YYSTACKSIZE #undef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif #define YYINITSTACKSIZE 500 int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; /* variables for the parser stack */ static short *yyss; static short *yysslim; static YYSTYPE *yyvs; static unsigned yystacksize; int arith(shinstance *psh, const char *s) { long result; INTOFF; /* todo lock */ arith_psh = psh; arith_buf = arith_startbuf = s; result = yyparse(); arith_lex_reset(); /* reprime lex */ arith_psh = NULL; /* todo unlock */ INTON; return (result); } /* * The exp(1) builtin. */ int expcmd(shinstance *psh, int argc, char **argv) { const char *p; char *concat; char **ap; long i; if (argc > 1) { p = argv[1]; if (argc > 2) { /* * concatenate arguments */ STARTSTACKSTR(psh, concat); ap = argv + 2; for (;;) { while (*p) STPUTC(psh, *p++, concat); if ((p = *ap++) == NULL) break; STPUTC(psh, ' ', concat); } STPUTC(psh, '\0', concat); p = grabstackstr(psh, concat); } } else p = ""; i = arith(psh, p); out1fmt(psh, "%ld\n", i); return (! i); } /*************************/ #ifdef TEST_ARITH #include main(argc, argv) char *argv[]; { printf("%d\n", exp(argv[1])); } error(s) char *s; { fprintf(stderr, "exp: %s\n", s); exit(1); } #endif void yyerror(const char *s) { shinstance *psh = arith_psh; #ifndef YYBISON /* yyerrok references yyerrstatus which is a local variable in yyparse().*/ yyerrok; #endif yyclearin; arith_lex_reset(); /* reprime lex */ /** @todo unlock */ error(psh, "arithmetic expression: %s: \"%s\"", s, arith_startbuf); /* NOTREACHED */ } /* allocate initial stack or double stack size, up to YYMAXDEPTH */ static int yygrowstack(void) { int i; unsigned newsize; short *newss; YYSTYPE *newvs; if ((newsize = yystacksize) == 0) newsize = YYINITSTACKSIZE; else if (newsize >= YYMAXDEPTH) return -1; else if ((newsize *= 2) > YYMAXDEPTH) newsize = YYMAXDEPTH; i = yyssp - yyss; newss = (yyss != 0) ? (short *)realloc(yyss, newsize * sizeof(*newss)) : (short *)malloc(newsize * sizeof(*newss)); if (newss == 0) return -1; yyss = newss; yyssp = newss + i; newvs = (yyvs != 0) ? (YYSTYPE *)realloc(yyvs, newsize * sizeof(*newvs)) : (YYSTYPE *)malloc(newsize * sizeof(*newvs)); if (newvs == 0) return -1; yyvs = newvs; yyvsp = newvs + i; yystacksize = newsize; yysslim = yyss + newsize - 1; return 0; } #define YYABORT goto yyabort #define YYREJECT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int YYPARSE_DECL() { int yym, yyn, yystate; #if YYDEBUG const char *yys; if ((yys = getenv("YYDEBUG")) != 0) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = YYEMPTY; yystate = 0; if (yyss == NULL && yygrowstack()) goto yyoverflow; yyssp = yyss; yyvsp = yyvs; yystate = 0; *yyssp = 0; yyloop: if ((yyn = yydefred[yystate]) != 0) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, shifting to state %d\n", YYPREFIX, yystate, yytable[yyn]); #endif if (yyssp >= yysslim && yygrowstack()) { goto yyoverflow; } yystate = yytable[yyn]; *++yyssp = yytable[yyn]; *++yyvsp = yylval; yychar = YYEMPTY; if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; yyerror("syntax error"); goto yyerrlab; yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, error recovery shifting\ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); #endif if (yyssp >= yysslim && yygrowstack()) { goto yyoverflow; } yystate = yytable[yyn]; *++yyssp = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("%sdebug: error recovery discarding state %d\n", YYPREFIX, *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, error recovery discards token %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif yychar = YYEMPTY; goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("%sdebug: state %d, reducing by rule %d (%s)\n", YYPREFIX, yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; if (yym) yyval = yyvsp[1-yym]; else memset(&yyval, 0, sizeof yyval); switch (yyn) { case 1: { return (yyvsp[0]); } break; case 2: { yyval = yyvsp[-1]; } break; case 3: { yyval = yyvsp[-2] ? yyvsp[-2] : yyvsp[0] ? yyvsp[0] : 0; } break; case 4: { yyval = yyvsp[-2] ? ( yyvsp[0] ? yyvsp[0] : 0 ) : 0; } break; case 5: { yyval = yyvsp[-2] | yyvsp[0]; } break; case 6: { yyval = yyvsp[-2] ^ yyvsp[0]; } break; case 7: { yyval = yyvsp[-2] & yyvsp[0]; } break; case 8: { yyval = yyvsp[-2] == yyvsp[0]; } break; case 9: { yyval = yyvsp[-2] > yyvsp[0]; } break; case 10: { yyval = yyvsp[-2] >= yyvsp[0]; } break; case 11: { yyval = yyvsp[-2] < yyvsp[0]; } break; case 12: { yyval = yyvsp[-2] <= yyvsp[0]; } break; case 13: { yyval = yyvsp[-2] != yyvsp[0]; } break; case 14: { yyval = yyvsp[-2] << yyvsp[0]; } break; case 15: { yyval = yyvsp[-2] >> yyvsp[0]; } break; case 16: { yyval = yyvsp[-2] + yyvsp[0]; } break; case 17: { yyval = yyvsp[-2] - yyvsp[0]; } break; case 18: { yyval = yyvsp[-2] * yyvsp[0]; } break; case 19: { if (yyvsp[0] == 0) yyerror("division by zero"); yyval = yyvsp[-2] / yyvsp[0]; } break; case 20: { if (yyvsp[0] == 0) yyerror("division by zero"); yyval = yyvsp[-2] % yyvsp[0]; } break; case 21: { yyval = !(yyvsp[0]); } break; case 22: { yyval = ~(yyvsp[0]); } break; case 23: { yyval = -(yyvsp[0]); } break; case 24: { yyval = yyvsp[0]; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state 0 to\ state %d\n", YYPREFIX, YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state %d \ to state %d\n", YYPREFIX, *yyssp, yystate); #endif if (yyssp >= yysslim && yygrowstack()) { goto yyoverflow; } *++yyssp = (short) yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } kbuild-2695/src/kash/generated/token.h0000644000000000000000000000227312247157307016411 0ustar rootroot#define TEOF 0 #define TNL 1 #define TSEMI 2 #define TBACKGND 3 #define TAND 4 #define TOR 5 #define TPIPE 6 #define TLP 7 #define TRP 8 #define TENDCASE 9 #define TENDBQUOTE 10 #define TREDIR 11 #define TWORD 12 #define TIF 13 #define TTHEN 14 #define TELSE 15 #define TELIF 16 #define TFI 17 #define TWHILE 18 #define TUNTIL 19 #define TFOR 20 #define TDO 21 #define TDONE 22 #define TBEGIN 23 #define TEND 24 #define TCASE 25 #define TESAC 26 #define TNOT 27 /* Array indicating which tokens mark the end of a list */ const char tokendlist[] = { 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, }; const char *const tokname[] = { "end of file", "newline", "\";\"", "\"&\"", "\"&&\"", "\"||\"", "\"|\"", "\"(\"", "\")\"", "\";;\"", "\"`\"", "redirection", "word", "\"if\"", "\"then\"", "\"else\"", "\"elif\"", "\"fi\"", "\"while\"", "\"until\"", "\"for\"", "\"do\"", "\"done\"", "\"{\"", "\"}\"", "\"case\"", "\"esac\"", "\"!\"", }; #define KWDOFFSET 13 const char *const parsekwd[] = { "if", "then", "else", "elif", "fi", "while", "until", "for", "do", "done", "{", "}", "case", "esac", "!", 0 }; kbuild-2695/src/kash/generated/nodes.h0000644000000000000000000000440112247157307016374 0ustar rootroot/* * This file was generated by mknodes.sh */ #define NSEMI 0 #define NCMD 1 #define NPIPE 2 #define NREDIR 3 #define NBACKGND 4 #define NSUBSHELL 5 #define NAND 6 #define NOR 7 #define NIF 8 #define NWHILE 9 #define NUNTIL 10 #define NFOR 11 #define NCASE 12 #define NCLIST 13 #define NDEFUN 14 #define NARG 15 #define NTO 16 #define NCLOBBER 17 #define NFROM 18 #define NFROMTO 19 #define NAPPEND 20 #define NTOFD 21 #define NFROMFD 22 #define NHERE 23 #define NXHERE 24 #define NNOT 25 struct nbinary { int type; union node *ch1; union node *ch2; }; struct ncmd { int type; int backgnd; union node *args; union node *redirect; }; struct npipe { int type; int backgnd; struct nodelist *cmdlist; }; struct nredir { int type; union node *n; union node *redirect; }; struct nif { int type; union node *test; union node *ifpart; union node *elsepart; }; struct nfor { int type; union node *args; union node *body; char *var; }; struct ncase { int type; union node *expr; union node *cases; }; struct nclist { int type; union node *next; union node *pattern; union node *body; }; struct narg { int type; union node *next; char *text; struct nodelist *backquote; }; struct nfile { int type; union node *next; int fd; union node *fname; char *expfname; }; struct ndup { int type; union node *next; int fd; int dupfd; union node *vname; }; struct nhere { int type; union node *next; int fd; union node *doc; }; struct nnot { int type; union node *com; }; union node { int type; struct nbinary nbinary; struct ncmd ncmd; struct npipe npipe; struct nredir nredir; struct nif nif; struct nfor nfor; struct ncase ncase; struct nclist nclist; struct narg narg; struct nfile nfile; struct ndup ndup; struct nhere nhere; struct nnot nnot; }; struct nodelist { struct nodelist *next; union node *n; }; union node *copyfunc(struct shinstance *, union node *); void freefunc(struct shinstance *, union node *); kbuild-2695/src/kash/generated/builtins.c0000644000000000000000000000241312247157307017111 0ustar rootroot/* * This file was generated by the mkbuiltins program. */ #include "shell.h" #include "builtins.h" const struct builtincmd builtincmd[] = { { "command", bltincmd }, { "bg", bgcmd }, { "cd", cdcmd }, { "chdir", cdcmd }, { "echo", echocmd }, { "exp", expcmd }, { "let", expcmd }, { "false", falsecmd }, { "fc", histcmd }, { "inputrc", inputrc }, { "fg", fgcmd }, { "getopts", getoptscmd }, { "hash", hashcmd }, { "jobid", jobidcmd }, { "jobs", jobscmd }, { "local", localcmd }, #ifndef SMALL { "printf", printfcmd }, #endif { "pwd", pwdcmd }, { "read", readcmd }, { "setvar", setvarcmd }, { "true", truecmd }, { "type", typecmd }, { "umask", umaskcmd }, { "unalias", unaliascmd }, { "wait", waitcmd }, { "alias", aliascmd }, { "ulimit", ulimitcmd }, { "test", testcmd }, { "[", testcmd }, { "kill", killcmd }, { "wordexp", wordexpcmd }, { 0, 0 }, }; const struct builtincmd splbltincmd[] = { { "break", breakcmd }, { "continue", breakcmd }, { ".", dotcmd }, { "eval", evalcmd }, { "exec", execcmd }, { "exit", exitcmd }, { "export", exportcmd }, { "readonly", exportcmd }, { "return", returncmd }, { "set", setcmd }, { "shift", shiftcmd }, { "times", timescmd }, { "trap", trapcmd }, { ":", truecmd }, { "unset", unsetcmd }, { 0, 0 }, }; kbuild-2695/src/kash/generated/nodes.c0000644000000000000000000002147212247157307016376 0ustar rootroot/* * This file was generated by mknodes.sh */ /* $NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 */ #include /* * Routine for dealing with parsed shell commands. */ #include "shell.h" #include "nodes.h" #include "memalloc.h" #include "machdep.h" #include "mystring.h" #include "shinstance.h" size_t funcblocksize; /* size of structures in function */ size_t funcstringsize; /* size of strings in node */ pointer funcblock; /* block to allocate function from */ char *funcstring; /* block to allocate strings from */ static const short nodesize[26] = { SHELL_ALIGN(sizeof (struct nbinary)), SHELL_ALIGN(sizeof (struct ncmd)), SHELL_ALIGN(sizeof (struct npipe)), SHELL_ALIGN(sizeof (struct nredir)), SHELL_ALIGN(sizeof (struct nredir)), SHELL_ALIGN(sizeof (struct nredir)), SHELL_ALIGN(sizeof (struct nbinary)), SHELL_ALIGN(sizeof (struct nbinary)), SHELL_ALIGN(sizeof (struct nif)), SHELL_ALIGN(sizeof (struct nbinary)), SHELL_ALIGN(sizeof (struct nbinary)), SHELL_ALIGN(sizeof (struct nfor)), SHELL_ALIGN(sizeof (struct ncase)), SHELL_ALIGN(sizeof (struct nclist)), SHELL_ALIGN(sizeof (struct narg)), SHELL_ALIGN(sizeof (struct narg)), SHELL_ALIGN(sizeof (struct nfile)), SHELL_ALIGN(sizeof (struct nfile)), SHELL_ALIGN(sizeof (struct nfile)), SHELL_ALIGN(sizeof (struct nfile)), SHELL_ALIGN(sizeof (struct nfile)), SHELL_ALIGN(sizeof (struct ndup)), SHELL_ALIGN(sizeof (struct ndup)), SHELL_ALIGN(sizeof (struct nhere)), SHELL_ALIGN(sizeof (struct nhere)), SHELL_ALIGN(sizeof (struct nnot)), }; STATIC void calcsize(union node *); STATIC void sizenodelist(struct nodelist *); STATIC union node *copynode(union node *); STATIC struct nodelist *copynodelist(struct nodelist *); STATIC char *nodesavestr(char *); /* * Make a copy of a parse tree. */ union node * copyfunc(psh, n) struct shinstance *psh; union node *n; { if (n == NULL) return NULL; funcblocksize = 0; funcstringsize = 0; calcsize(n); funcblock = ckmalloc(psh, funcblocksize + funcstringsize); funcstring = (char *) funcblock + funcblocksize; return copynode(n); } STATIC void calcsize(n) union node *n; { if (n == NULL) return; funcblocksize += nodesize[n->type]; switch (n->type) { case NSEMI: case NAND: case NOR: case NWHILE: case NUNTIL: calcsize(n->nbinary.ch2); calcsize(n->nbinary.ch1); break; case NCMD: calcsize(n->ncmd.redirect); calcsize(n->ncmd.args); break; case NPIPE: sizenodelist(n->npipe.cmdlist); break; case NREDIR: case NBACKGND: case NSUBSHELL: calcsize(n->nredir.redirect); calcsize(n->nredir.n); break; case NIF: calcsize(n->nif.elsepart); calcsize(n->nif.ifpart); calcsize(n->nif.test); break; case NFOR: funcstringsize += strlen(n->nfor.var) + 1; calcsize(n->nfor.body); calcsize(n->nfor.args); break; case NCASE: calcsize(n->ncase.cases); calcsize(n->ncase.expr); break; case NCLIST: calcsize(n->nclist.body); calcsize(n->nclist.pattern); calcsize(n->nclist.next); break; case NDEFUN: case NARG: sizenodelist(n->narg.backquote); funcstringsize += strlen(n->narg.text) + 1; calcsize(n->narg.next); break; case NTO: case NCLOBBER: case NFROM: case NFROMTO: case NAPPEND: calcsize(n->nfile.fname); calcsize(n->nfile.next); break; case NTOFD: case NFROMFD: calcsize(n->ndup.vname); calcsize(n->ndup.next); break; case NHERE: case NXHERE: calcsize(n->nhere.doc); calcsize(n->nhere.next); break; case NNOT: calcsize(n->nnot.com); break; }; } STATIC void sizenodelist(lp) struct nodelist *lp; { while (lp) { funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); calcsize(lp->n); lp = lp->next; } } STATIC union node * copynode(n) union node *n; { union node *new; if (n == NULL) return NULL; new = funcblock; funcblock = (char *) funcblock + nodesize[n->type]; switch (n->type) { case NSEMI: case NAND: case NOR: case NWHILE: case NUNTIL: new->nbinary.ch2 = copynode(n->nbinary.ch2); new->nbinary.ch1 = copynode(n->nbinary.ch1); break; case NCMD: new->ncmd.redirect = copynode(n->ncmd.redirect); new->ncmd.args = copynode(n->ncmd.args); new->ncmd.backgnd = n->ncmd.backgnd; break; case NPIPE: new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); new->npipe.backgnd = n->npipe.backgnd; break; case NREDIR: case NBACKGND: case NSUBSHELL: new->nredir.redirect = copynode(n->nredir.redirect); new->nredir.n = copynode(n->nredir.n); break; case NIF: new->nif.elsepart = copynode(n->nif.elsepart); new->nif.ifpart = copynode(n->nif.ifpart); new->nif.test = copynode(n->nif.test); break; case NFOR: new->nfor.var = nodesavestr(n->nfor.var); new->nfor.body = copynode(n->nfor.body); new->nfor.args = copynode(n->nfor.args); break; case NCASE: new->ncase.cases = copynode(n->ncase.cases); new->ncase.expr = copynode(n->ncase.expr); break; case NCLIST: new->nclist.body = copynode(n->nclist.body); new->nclist.pattern = copynode(n->nclist.pattern); new->nclist.next = copynode(n->nclist.next); break; case NDEFUN: case NARG: new->narg.backquote = copynodelist(n->narg.backquote); new->narg.text = nodesavestr(n->narg.text); new->narg.next = copynode(n->narg.next); break; case NTO: case NCLOBBER: case NFROM: case NFROMTO: case NAPPEND: new->nfile.fname = copynode(n->nfile.fname); new->nfile.fd = n->nfile.fd; new->nfile.next = copynode(n->nfile.next); break; case NTOFD: case NFROMFD: new->ndup.vname = copynode(n->ndup.vname); new->ndup.dupfd = n->ndup.dupfd; new->ndup.fd = n->ndup.fd; new->ndup.next = copynode(n->ndup.next); break; case NHERE: case NXHERE: new->nhere.doc = copynode(n->nhere.doc); new->nhere.fd = n->nhere.fd; new->nhere.next = copynode(n->nhere.next); break; case NNOT: new->nnot.com = copynode(n->nnot.com); break; }; new->type = n->type; return new; } STATIC struct nodelist * copynodelist(lp) struct nodelist *lp; { struct nodelist *start; struct nodelist **lpp; lpp = &start; while (lp) { *lpp = funcblock; funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); (*lpp)->n = copynode(lp->n); lp = lp->next; lpp = &(*lpp)->next; } *lpp = NULL; return start; } STATIC char * nodesavestr(s) char *s; { register char *p = s; register char *q = funcstring; char *rtn = funcstring; while ((*q++ = *p++) != 0) continue; funcstring = q; return rtn; } /* * Free a parse tree. */ void freefunc(psh, n) shinstance *psh; union node *n; { if (n) ckfree(psh, n); } kbuild-2695/src/kash/generated/arith.h0000644000000000000000000000107312247157307016375 0ustar rootroot#define ARITH_NUM 257 #define ARITH_LPAREN 258 #define ARITH_RPAREN 259 #define ARITH_OR 260 #define ARITH_AND 261 #define ARITH_BOR 262 #define ARITH_BXOR 263 #define ARITH_BAND 264 #define ARITH_EQ 265 #define ARITH_NE 266 #define ARITH_LT 267 #define ARITH_GT 268 #define ARITH_GE 269 #define ARITH_LE 270 #define ARITH_LSHIFT 271 #define ARITH_RSHIFT 272 #define ARITH_ADD 273 #define ARITH_SUB 274 #define ARITH_MUL 275 #define ARITH_DIV 276 #define ARITH_REM 277 #define ARITH_UNARYMINUS 278 #define ARITH_UNARYPLUS 279 #define ARITH_NOT 280 #define ARITH_BNOT 281 kbuild-2695/src/kash/generated/builtins.h0000644000000000000000000000364312247157307017124 0ustar rootroot/* * This file was generated by the mkbuiltins program. */ #include "shtypes.h" struct builtincmd { const char *name; int (*builtin)(shinstance *, int, char **); }; extern const struct builtincmd builtincmd[]; extern const struct builtincmd splbltincmd[]; int bltincmd(shinstance *, int, char **); int bgcmd(shinstance *, int, char **); int breakcmd(shinstance *, int, char **); int cdcmd(shinstance *, int, char **); int dotcmd(shinstance *, int, char **); int echocmd(shinstance *, int, char **); int evalcmd(shinstance *, int, char **); int execcmd(shinstance *, int, char **); int exitcmd(shinstance *, int, char **); int expcmd(shinstance *, int, char **); int exportcmd(shinstance *, int, char **); int falsecmd(shinstance *, int, char **); int histcmd(shinstance *, int, char **); int inputrc(shinstance *, int, char **); int fgcmd(shinstance *, int, char **); int getoptscmd(shinstance *, int, char **); int hashcmd(shinstance *, int, char **); int jobidcmd(shinstance *, int, char **); int jobscmd(shinstance *, int, char **); int localcmd(shinstance *, int, char **); #ifndef SMALL int printfcmd(shinstance *, int, char **); #endif int pwdcmd(shinstance *, int, char **); int readcmd(shinstance *, int, char **); int returncmd(shinstance *, int, char **); int setcmd(shinstance *, int, char **); int setvarcmd(shinstance *, int, char **); int shiftcmd(shinstance *, int, char **); int timescmd(shinstance *, int, char **); int trapcmd(shinstance *, int, char **); int truecmd(shinstance *, int, char **); int typecmd(shinstance *, int, char **); int umaskcmd(shinstance *, int, char **); int unaliascmd(shinstance *, int, char **); int unsetcmd(shinstance *, int, char **); int waitcmd(shinstance *, int, char **); int aliascmd(shinstance *, int, char **); int ulimitcmd(shinstance *, int, char **); int testcmd(shinstance *, int, char **); int killcmd(shinstance *, int, char **); int wordexpcmd(shinstance *, int, char **); kbuild-2695/src/kash/exec.h0000644000000000000000000000715212247157307014260 0ustar rootroot/* $NetBSD: exec.h,v 1.21 2003/08/07 09:05:31 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)exec.h 8.3 (Berkeley) 6/8/95 */ #ifndef ___exec_h #define ___exec_h /* values of cmdtype */ #define CMDUNKNOWN -1 /* no entry in table for command */ #define CMDNORMAL 0 /* command is an executable program */ #define CMDFUNCTION 1 /* command is a shell function */ #define CMDBUILTIN 2 /* command is a shell builtin */ #define CMDSPLBLTIN 3 /* command is a special shell builtin */ union param { int index; int (*bltin)(struct shinstance*, int, char**); union node *func; }; struct cmdentry { int cmdtype; union param u; }; /* action to find_command() */ #define DO_ERR 0x01 /* prints errors */ #define DO_ABS 0x02 /* checks absolute paths */ #define DO_NOFUNC 0x04 /* don't return shell functions, for command */ #define DO_ALTPATH 0x08 /* using alternate path */ #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */ /*extern const char *pathopt;*/ /* set by padvance */ #if !defined(__GNUC__) && !defined(__attribute__) # define __attribute__(a) #endif SH_NORETURN_1 void shellexec(struct shinstance *, char **, char **, const char *, int, int) SH_NORETURN_2; char *padvance(struct shinstance *, const char **, const char *); int hashcmd(struct shinstance *, int, char **); void find_command(struct shinstance *, char *, struct cmdentry *, int, const char *); int (*find_builtin(struct shinstance *, char *))(struct shinstance *, int, char **); int (*find_splbltin(struct shinstance *, char *))(struct shinstance *, int, char **); void hashcd(struct shinstance *); void changepath(struct shinstance *, const char *); void deletefuncs(struct shinstance *); void getcmdentry(struct shinstance *, char *, struct cmdentry *); void addcmdentry(struct shinstance *, char *, struct cmdentry *); void defun(struct shinstance *, char *, union node *); int unsetfunc(struct shinstance *, char *); int typecmd(struct shinstance *, int, char **); void hash_special_builtins(struct shinstance *); #endif kbuild-2695/src/kash/miscbltin.h0000644000000000000000000000322712247157307015317 0ustar rootroot/* $NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 christos Exp $ */ /* * Copyright (c) 1997 Christos Zoulas. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ int readcmd(struct shinstance *, int, char **); int umaskcmd(struct shinstance *, int, char **); int ulimitcmd(struct shinstance *, int, char **); kbuild-2695/src/kash/error.c0000644000000000000000000002147212247157307014461 0ustar rootroot/* $NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $"); #endif /* not lint */ #endif /* * Errors and exceptions. */ #include #include #include #include #include "shell.h" #include "main.h" #include "options.h" #include "output.h" #include "error.h" #include "show.h" #include "shinstance.h" /* * Code to handle exceptions in C. */ /*struct jmploc *handler; int exception; volatile int suppressint; volatile int intpending; char *commandname;*/ SH_NORETURN_1 static void exverror(shinstance *psh, int, const char *, va_list) SH_NORETURN_2; /* * Called to raise an exception. Since C doesn't include exceptions, we * just do a longjmp to the exception handler. The type of exception is * stored in the global variable "exception". */ SH_NORETURN_1 void exraise(shinstance *psh, int e) { if (psh->handler == NULL) sh_abort(psh); psh->exception = e; longjmp(psh->handler->loc, 1); } /* * Called from trap.c when a SIGINT is received. (If the user specifies * that SIGINT is to be trapped or ignored using the trap builtin, then * this routine is not called.) Suppressint is nonzero when interrupts * are held using the INTOFF macro. The call to _exit is necessary because * there is a short period after a fork before the signal handlers are * set to the appropriate value for the child. (The test for iflag is * just defensive programming.) */ void onint(shinstance *psh) { shsigset_t nsigset; if (psh->suppressint) { psh->intpending = 1; return; } psh->intpending = 0; sh_sigemptyset(&nsigset); sh_sigprocmask(psh, SIG_SETMASK, &nsigset, NULL); if (psh->rootshell && iflag(psh)) exraise(psh, EXINT); else { sh_signal(psh, SIGINT, SH_SIG_DFL); sh_raise_sigint(psh);/*raise(psh, SIGINT);*/ } /* NOTREACHED */ } static void exvwarning(shinstance *psh, int sv_errno, const char *msg, va_list ap) { /* Partially emulate line buffered output so that: * printf '%d\n' 1 a 2 * and * printf '%d %d %d\n' 1 a 2 * both generate sensible text when stdout and stderr are merged. */ if (psh->output.nextc != psh->output.buf && psh->output.nextc[-1] == '\n') flushout(&psh->output); if (psh->commandname) outfmt(&psh->errout, "%s: ", psh->commandname); if (msg != NULL) { doformat(&psh->errout, msg, ap); if (sv_errno >= 0) outfmt(&psh->errout, ": "); } if (sv_errno >= 0) outfmt(&psh->errout, "%s", sh_strerror(psh, sv_errno)); out2c(psh, '\n'); flushout(&psh->errout); } /* * Exverror is called to raise the error exception. If the second argument * is not NULL then error prints an error message using printf style * formatting. It then raises the error exception. */ static void exverror(shinstance *psh, int cond, const char *msg, va_list ap) { CLEAR_PENDING_INT; INTOFF; #ifdef DEBUG if (msg) { va_list va2; TRACE((psh, "exverror(%d, \"", cond)); # ifdef va_copy /* MSC 2010 still doesn't have va_copy. sigh. */ va_copy(va2, ap); # else va2 = ap; # endif TRACEV((psh, msg, va2)); va_end(va2); TRACE((psh, "\") pid=%d\n", sh_getpid(psh))); } else TRACE((psh, "exverror(%d, NULL) pid=%d\n", cond, sh_getpid(psh))); #endif if (msg) exvwarning(psh, -1, msg, ap); output_flushall(psh); exraise(psh, cond); /* NOTREACHED */ } SH_NORETURN_1 void error(shinstance *psh, const char *msg, ...) { va_list ap; va_start(ap, msg); exverror(psh, EXERROR, msg, ap); /* NOTREACHED */ va_end(ap); } SH_NORETURN_1 void exerror(shinstance *psh, int cond, const char *msg, ...) { va_list ap; va_start(ap, msg); exverror(psh, cond, msg, ap); /* NOTREACHED */ va_end(ap); } /* * error/warning routines for external builtins */ SH_NORETURN_1 void sh_exit(shinstance *psh, int rval) { psh->exerrno = rval & 255; exraise(psh, EXEXEC); } SH_NORETURN_1 void sh_err(shinstance *psh, int status, const char *fmt, ...) { va_list ap; va_start(ap, fmt); exvwarning(psh, errno, fmt, ap); va_end(ap); sh_exit(psh, status); } SH_NORETURN_1 void sh_verr(shinstance *psh, int status, const char *fmt, va_list ap) { exvwarning(psh, errno, fmt, ap); sh_exit(psh, status); } SH_NORETURN_1 void sh_errx(shinstance *psh, int status, const char *fmt, ...) { va_list ap; va_start(ap, fmt); exvwarning(psh, -1, fmt, ap); va_end(ap); sh_exit(psh, status); } SH_NORETURN_1 void sh_verrx(shinstance *psh, int status, const char *fmt, va_list ap) { exvwarning(psh, -1, fmt, ap); sh_exit(psh, status); } void sh_warn(shinstance *psh, const char *fmt, ...) { va_list ap; va_start(ap, fmt); exvwarning(psh, errno, fmt, ap); va_end(ap); } void sh_vwarn(shinstance *psh, const char *fmt, va_list ap) { exvwarning(psh, errno, fmt, ap); } void sh_warnx(shinstance *psh, const char *fmt, ...) { va_list ap; va_start(ap, fmt); exvwarning(psh, -1, fmt, ap); va_end(ap); } void sh_vwarnx(shinstance *psh, const char *fmt, va_list ap) { exvwarning(psh, -1, fmt, ap); } /* * Table of error messages. */ struct errname { short errcode; /* error number */ short action; /* operation which encountered the error */ const char *msg; /* text describing the error */ }; #define ALL (E_OPEN|E_CREAT|E_EXEC) STATIC const struct errname errormsg[] = { { EINTR, ALL, "interrupted" }, { EACCES, ALL, "permission denied" }, { EIO, ALL, "I/O error" }, { EEXIST, ALL, "file exists" }, { ENOENT, E_OPEN, "no such file" }, { ENOENT, E_CREAT,"directory nonexistent" }, { ENOENT, E_EXEC, "not found" }, { ENOTDIR, E_OPEN, "no such file" }, { ENOTDIR, E_CREAT,"directory nonexistent" }, { ENOTDIR, E_EXEC, "not found" }, { EISDIR, ALL, "is a directory" }, #ifdef EMFILE { EMFILE, ALL, "too many open files" }, #endif { ENFILE, ALL, "file table overflow" }, { ENOSPC, ALL, "file system full" }, #ifdef EDQUOT { EDQUOT, ALL, "disk quota exceeded" }, #endif #ifdef ENOSR { ENOSR, ALL, "no streams resources" }, #endif { ENXIO, ALL, "no such device or address" }, { EROFS, ALL, "read-only file system" }, #ifdef ETXTBSY { ETXTBSY, ALL, "text busy" }, #endif #ifdef EAGAIN { EAGAIN, E_EXEC, "not enough memory" }, #endif { ENOMEM, ALL, "not enough memory" }, #ifdef ENOLINK { ENOLINK, ALL, "remote access failed" }, #endif #ifdef EMULTIHOP { EMULTIHOP, ALL, "remote access failed" }, #endif #ifdef ECOMM { ECOMM, ALL, "remote access failed" }, #endif #ifdef ESTALE { ESTALE, ALL, "remote access failed" }, #endif #ifdef ETIMEDOUT { ETIMEDOUT, ALL, "remote access failed" }, #endif #ifdef ELOOP { ELOOP, ALL, "symbolic link loop" }, #endif { E2BIG, E_EXEC, "argument list too long" }, #ifdef ELIBACC { ELIBACC, E_EXEC, "shared library missing" }, #endif { 0, 0, NULL }, }; /* * Return a string describing an error. The returned string may be a * pointer to a static buffer that will be overwritten on the next call. * Action describes the operation that got the error. */ const char * errmsg(shinstance *psh, int e, int action) { struct errname const *ep; /*static char buf[12];*/ for (ep = errormsg ; ep->errcode ; ep++) { if (ep->errcode == e && (ep->action & action) != 0) return ep->msg; } fmtstr(psh->errmsg_buf, sizeof psh->errmsg_buf, "error %d", e); return psh->errmsg_buf; } kbuild-2695/src/kash/trap.c0000644000000000000000000002265012247157307014275 0ustar rootroot/* $NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; #else __RCSID("$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $"); #endif /* not lint */ #endif #include #include "shell.h" #include "main.h" #include "nodes.h" /* for other headers */ #include "eval.h" #include "jobs.h" #include "show.h" #include "options.h" #include "syntax.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "trap.h" #include "mystring.h" #include "var.h" #include "shinstance.h" #ifndef HAVE_SYS_SIGNAME extern void init_sys_signame(void); extern char sys_signame[NSIG][16]; #endif /* * Sigmode records the current value of the signal handlers for the various * modes. A value of zero means that the current handler is not known. * S_HARD_IGN indicates that the signal was ignored on entry to the shell, */ #define S_DFL 1 /* default signal handling (SIG_DFL) */ #define S_CATCH 2 /* signal is caught */ #define S_IGN 3 /* signal is ignored (SIG_IGN) */ #define S_HARD_IGN 4 /* signal is ignored permenantly */ #define S_RESET 5 /* temporary - to reset a hard ignored sig */ //char *trap[NSIG+1]; /* trap handler commands */ //MKINIT char sigmode[NSIG]; /* current value of signal */ //char gotsig[NSIG]; /* indicates specified signal received */ //int pendingsigs; /* indicates some signal received */ static int getsigaction(shinstance *, int, shsig_t *); /* * return the signal number described by `p' (as a number or a name) * or -1 if it isn't one */ static int signame_to_signum(shinstance *psh, const char *p) { int i; if (is_number(p)) return number(psh, p); if (strcasecmp(p, "exit") == 0 ) return 0; if (strncasecmp(p, "sig", 3) == 0) p += 3; #ifndef HAVE_SYS_SIGNAME init_sys_signame(); #endif for (i = 0; i < NSIG; ++i) if (strcasecmp(p, sys_signame[i]) == 0) return i; return -1; } /* * Print a list of valid signal names */ static void printsignals(shinstance *psh) { int n; out1str(psh, "EXIT "); #ifndef HAVE_SYS_SIGNAME init_sys_signame(); #endif for (n = 1; n < NSIG; n++) { out1fmt(psh, "%s", sys_signame[n]); if ((n == NSIG/2) || n == (NSIG - 1)) out1str(psh, "\n"); else out1c(psh, ' '); } } /* * The trap builtin. */ int trapcmd(shinstance *psh, int argc, char **argv) { char *action; char **ap; int signo; #ifndef HAVE_SYS_SIGNAME init_sys_signame(); #endif if (argc <= 1) { for (signo = 0 ; signo <= NSIG ; signo++) if (psh->trap[signo] != NULL) { out1fmt(psh, "trap -- "); print_quoted(psh, psh->trap[signo]); out1fmt(psh, " %s\n", (signo) ? sys_signame[signo] : "EXIT"); } return 0; } ap = argv + 1; action = NULL; if (strcmp(*ap, "--") == 0) if (*++ap == NULL) return 0; if (signame_to_signum(psh, *ap) == -1) { if ((*ap)[0] == '-') { if ((*ap)[1] == '\0') ap++; else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') { printsignals(psh); return 0; } else error(psh, "bad option %s\n", *ap); } else action = *ap++; } while (*ap) { if (is_number(*ap)) signo = number(psh, *ap); else signo = signame_to_signum(psh, *ap); if (signo < 0 || signo > NSIG) error(psh, "%s: bad trap", *ap); INTOFF; if (action) action = savestr(psh, action); if (psh->trap[signo]) ckfree(psh, psh->trap[signo]); psh->trap[signo] = action; if (signo != 0) setsignal(psh, signo, 0); INTON; ap++; } return 0; } /* * Clear traps on a fork or vfork. * Takes one arg vfork, to tell it to not be destructive of * the parents variables. */ void clear_traps(shinstance *psh, int vforked) { char **tp; for (tp = psh->trap ; tp <= &psh->trap[NSIG] ; tp++) { if (*tp && **tp) { /* trap not NULL or SIG_IGN */ INTOFF; if (!vforked) { ckfree(psh, *tp); *tp = NULL; } if (tp != &psh->trap[0]) setsignal(psh, (int)(tp - psh->trap), vforked); INTON; } } } /* * Set the signal handler for the specified signal. The routine figures * out what it should be set to. */ void setsignal(shinstance *psh, int signo, int vforked) { int action; shsig_t sigact = SH_SIG_DFL; char *t, tsig; if ((t = psh->trap[signo]) == NULL) action = S_DFL; else if (*t != '\0') action = S_CATCH; else action = S_IGN; if (psh->rootshell && !vforked && action == S_DFL) { switch (signo) { case SIGINT: if (iflag(psh) || psh->minusc || sflag(psh) == 0) action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG if (debug(psh)) break; #endif /* FALLTHROUGH */ case SIGTERM: if (iflag(psh)) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: if (mflag(psh)) action = S_IGN; break; #endif } } t = &psh->sigmode[signo - 1]; tsig = *t; if (tsig == 0) { /* * current setting unknown */ if (!getsigaction(psh, signo, &sigact)) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ return; } if (sigact == SH_SIG_IGN) { if (mflag(psh) && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) { tsig = S_IGN; /* don't hard ignore these */ } else tsig = S_HARD_IGN; } else { tsig = S_RESET; /* force to be set */ } } if (tsig == S_HARD_IGN || tsig == action) return; switch (action) { case S_DFL: sigact = SH_SIG_DFL; break; case S_CATCH: sigact = onsig; break; case S_IGN: sigact = SH_SIG_IGN; break; } if (!vforked) *t = action; sh_siginterrupt(psh, signo, 1); sh_signal(psh, signo, sigact); } /* * Return the current setting for sig w/o changing it. */ static int getsigaction(shinstance *psh, int signo, shsig_t *sigact) { struct shsigaction sa; if (sh_sigaction(psh, signo, NULL, &sa) == -1) return 0; *sigact = (shsig_t)sa.sh_handler; return 1; } /* * Ignore a signal. */ void ignoresig(shinstance *psh, int signo, int vforked) { if (psh->sigmode[signo - 1] != S_IGN && psh->sigmode[signo - 1] != S_HARD_IGN) { sh_signal(psh, signo, SH_SIG_IGN); } if (!vforked) psh->sigmode[signo - 1] = S_HARD_IGN; } #ifdef mkinit INCLUDE INCLUDE "trap.h" SHELLPROC { char *sm; clear_traps(psh, 0); for (sm = psh->sigmode ; sm < psh->sigmode + NSIG ; sm++) { if (*sm == S_IGN) *sm = S_HARD_IGN; } } #endif /* * Signal handler. */ void onsig(shinstance *psh, int signo) { sh_signal(psh, signo, onsig); if (signo == SIGINT && psh->trap[SIGINT] == NULL) { onint(psh); return; } psh->gotsig[signo - 1] = 1; psh->pendingsigs++; } /* * Called to execute a trap. Perhaps we should avoid entering new trap * handlers while we are executing a trap handler. */ void dotrap(shinstance *psh) { int i; int savestatus; for (;;) { for (i = 1 ; ; i++) { if (psh->gotsig[i - 1]) break; if (i >= NSIG) goto done; } psh->gotsig[i - 1] = 0; savestatus=psh->exitstatus; evalstring(psh, psh->trap[i], 0); psh->exitstatus=savestatus; } done: psh->pendingsigs = 0; } /* * Controls whether the shell is interactive or not. */ void setinteractive(shinstance *psh, int on) { static int is_interactive; if (on == is_interactive) return; setsignal(psh, SIGINT, 0); setsignal(psh, SIGQUIT, 0); setsignal(psh, SIGTERM, 0); is_interactive = on; } /* * Called to exit the shell. */ SH_NORETURN_1 void exitshell(shinstance *psh, int status) { struct jmploc loc1, loc2; char *p; TRACE((psh, "pid %d, exitshell(%d)\n", sh_getpid(psh), status)); if (setjmp(loc1.loc)) { goto l1; } if (setjmp(loc2.loc)) { goto l2; } psh->handler = &loc1; if ((p = psh->trap[0]) != NULL && *p != '\0') { psh->trap[0] = NULL; evalstring(psh, p, 0); } l1: psh->handler = &loc2; /* probably unnecessary */ output_flushall(psh); #if JOBS setjobctl(psh, 0); #endif l2: sh__exit(psh, status); /* NOTREACHED */ } kbuild-2695/src/kash/main.h0000644000000000000000000000410012247157307014246 0ustar rootroot/* $NetBSD: main.h,v 1.10 2003/08/07 09:05:34 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)main.h 8.2 (Berkeley) 5/4/95 */ #include "shtypes.h" /*extern int rootpid;*/ /* pid of main shell */ /*extern int rootshell;*/ /* true if we aren't a child of the main shell */ void readcmdfile(struct shinstance *, char *); void cmdloop(struct shinstance *, int); int dotcmd(struct shinstance *, int, char **); int exitcmd(struct shinstance *, int, char **); kbuild-2695/src/kash/setmode.c0000644000000000000000000002574212247157307014774 0ustar rootroot/* $NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $ */ /* * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Dave Borman at Cray Research, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94"; #else __RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $"); #endif /* LIBC_SCCS and not lint */ #endif #include #include #include #include #include #include #include "shinstance.h" /* for unistd.h types/defines */ #ifdef SETMODE_DEBUG #include #endif #define SET_LEN 6 /* initial # of bitcmd struct to malloc */ #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */ typedef struct bitcmd { char cmd; char cmd2; mode_t bits; } BITCMD; #define CMD2_CLR 0x01 #define CMD2_SET 0x02 #define CMD2_GBITS 0x04 #define CMD2_OBITS 0x08 #define CMD2_UBITS 0x10 static BITCMD *addcmd(BITCMD *, int, int, int, unsigned int); static void compress_mode(BITCMD *); #ifdef SETMODE_DEBUG static void dumpmode(BITCMD *); #endif #ifndef _DIAGASSERT # define _DIAGASSERT assert #endif #ifndef S_ISTXT # ifdef S_ISVTX # define S_ISTXT S_ISVTX # else # define S_ISTXT 0 # endif #endif /* !S_ISTXT */ /* * Given the old mode and an array of bitcmd structures, apply the operations * described in the bitcmd structures to the old mode, and return the new mode. * Note that there is no '=' command; a strict assignment is just a '-' (clear * bits) followed by a '+' (set bits). */ mode_t kash_getmode(const void *bbox, mode_t omode) { const BITCMD *set; mode_t clrval, newmode, value; _DIAGASSERT(bbox != NULL); set = (const BITCMD *)bbox; newmode = omode; for (value = 0;; set++) switch(set->cmd) { /* * When copying the user, group or other bits around, we "know" * where the bits are in the mode so that we can do shifts to * copy them around. If we don't use shifts, it gets real * grundgy with lots of single bit checks and bit sets. */ case 'u': value = (newmode & S_IRWXU) >> 6; goto common; case 'g': value = (newmode & S_IRWXG) >> 3; goto common; case 'o': value = newmode & S_IRWXO; common: if (set->cmd2 & CMD2_CLR) { clrval = (set->cmd2 & CMD2_SET) ? S_IRWXO : value; if (set->cmd2 & CMD2_UBITS) newmode &= ~((clrval<<6) & set->bits); if (set->cmd2 & CMD2_GBITS) newmode &= ~((clrval<<3) & set->bits); if (set->cmd2 & CMD2_OBITS) newmode &= ~(clrval & set->bits); } if (set->cmd2 & CMD2_SET) { if (set->cmd2 & CMD2_UBITS) newmode |= (value<<6) & set->bits; if (set->cmd2 & CMD2_GBITS) newmode |= (value<<3) & set->bits; if (set->cmd2 & CMD2_OBITS) newmode |= value & set->bits; } break; case '+': newmode |= set->bits; break; case '-': newmode &= ~set->bits; break; case 'X': if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH)) newmode |= set->bits; break; case '\0': default: #ifdef SETMODE_DEBUG (void)printf("getmode:%04o -> %04o\n", omode, newmode); #endif return (newmode); } } #define ADDCMD(a, b, c, d) do { \ if (set >= endset) { \ BITCMD *newset; \ setlen += SET_LEN_INCR; \ newset = sh_realloc(NULL, saveset, sizeof(BITCMD) * setlen); \ if (newset == NULL) { \ sh_free(NULL, saveset); \ return (NULL); \ } \ set = newset + (set - saveset); \ saveset = newset; \ endset = newset + (setlen - 2); \ } \ set = addcmd(set, (a), (b), (c), (d)); \ } while (/*CONSTCOND*/0) #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) void * kash_setmode(shinstance *psh, const char *p) { int perm, who; char op, *ep; BITCMD *set, *saveset, *endset; mode_t mask; int equalopdone = 0; /* pacify gcc */ int permXbits, setlen; if (!*p) return (NULL); /* * Get a copy of the mask for the permissions that are mask relative. * Flip the bits, we want what's not set. */ mask = shfile_get_umask(&psh->fdtab); setlen = SET_LEN + 2; if ((set = sh_malloc(NULL, sizeof(BITCMD) * setlen)) == NULL) return (NULL); saveset = set; endset = set + (setlen - 2); /* * If an absolute number, get it and return; disallow non-octal digits * or illegal bits. */ if (isdigit((unsigned char)*p)) { perm = (mode_t)strtol(p, &ep, 8); if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) { sh_free(NULL, saveset); return (NULL); } ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask); set->cmd = 0; return (saveset); } /* * Build list of structures to set/clear/copy bits as described by * each clause of the symbolic mode. */ for (;;) { /* First, find out which bits might be modified. */ for (who = 0;; ++p) { switch (*p) { case 'a': who |= STANDARD_BITS; break; case 'u': who |= S_ISUID|S_IRWXU; break; case 'g': who |= S_ISGID|S_IRWXG; break; case 'o': who |= S_IRWXO; break; default: goto getop; } } getop: if ((op = *p++) != '+' && op != '-' && op != '=') { sh_free(NULL, saveset); return (NULL); } if (op == '=') equalopdone = 0; who &= ~S_ISTXT; for (perm = 0, permXbits = 0;; ++p) { switch (*p) { case 'r': perm |= S_IRUSR|S_IRGRP|S_IROTH; break; case 's': /* * If specific bits where requested and * only "other" bits ignore set-id. */ if (who == 0 || (who & ~S_IRWXO)) perm |= S_ISUID|S_ISGID; break; case 't': /* * If specific bits where requested and * only "other" bits ignore set-id. */ if (who == 0 || (who & ~S_IRWXO)) { who |= S_ISTXT; perm |= S_ISTXT; } break; case 'w': perm |= S_IWUSR|S_IWGRP|S_IWOTH; break; case 'X': permXbits = S_IXUSR|S_IXGRP|S_IXOTH; break; case 'x': perm |= S_IXUSR|S_IXGRP|S_IXOTH; break; case 'u': case 'g': case 'o': /* * When ever we hit 'u', 'g', or 'o', we have * to flush out any partial mode that we have, * and then do the copying of the mode bits. */ if (perm) { ADDCMD(op, who, perm, mask); perm = 0; } if (op == '=') equalopdone = 1; if (op == '+' && permXbits) { ADDCMD('X', who, permXbits, mask); permXbits = 0; } ADDCMD(*p, who, op, mask); break; default: /* * Add any permissions that we haven't already * done. */ if (perm || (op == '=' && !equalopdone)) { if (op == '=') equalopdone = 1; ADDCMD(op, who, perm, mask); perm = 0; } if (permXbits) { ADDCMD('X', who, permXbits, mask); permXbits = 0; } goto apply; } } apply: if (!*p) break; if (*p != ',') goto getop; ++p; } set->cmd = 0; #ifdef SETMODE_DEBUG (void)printf("Before compress_mode()\n"); dumpmode(saveset); #endif compress_mode(saveset); #ifdef SETMODE_DEBUG (void)printf("After compress_mode()\n"); dumpmode(saveset); #endif return (saveset); } static BITCMD * addcmd(set, op, who, oparg, mask) BITCMD *set; int oparg, who; int op; unsigned int mask; { _DIAGASSERT(set != NULL); switch (op) { case '=': set->cmd = '-'; set->bits = who ? who : STANDARD_BITS; set++; op = '+'; /* FALLTHROUGH */ case '+': case '-': case 'X': set->cmd = op; set->bits = (who ? (unsigned int)who : mask) & (unsigned int)oparg; break; case 'u': case 'g': case 'o': set->cmd = op; if (who) { set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) | ((who & S_IRGRP) ? CMD2_GBITS : 0) | ((who & S_IROTH) ? CMD2_OBITS : 0); set->bits = (mode_t)~0; } else { set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS; set->bits = mask; } if (oparg == '+') set->cmd2 |= CMD2_SET; else if (oparg == '-') set->cmd2 |= CMD2_CLR; else if (oparg == '=') set->cmd2 |= CMD2_SET|CMD2_CLR; break; } return (set + 1); } #ifdef SETMODE_DEBUG static void dumpmode(set) BITCMD *set; { _DIAGASSERT(set != NULL); for (; set->cmd; ++set) (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n", set->cmd, set->bits, set->cmd2 ? " cmd2:" : "", set->cmd2 & CMD2_CLR ? " CLR" : "", set->cmd2 & CMD2_SET ? " SET" : "", set->cmd2 & CMD2_UBITS ? " UBITS" : "", set->cmd2 & CMD2_GBITS ? " GBITS" : "", set->cmd2 & CMD2_OBITS ? " OBITS" : ""); } #endif /* * Given an array of bitcmd structures, compress by compacting consecutive * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u', * 'g' and 'o' commands continue to be separate. They could probably be * compacted, but it's not worth the effort. */ static void compress_mode(set) BITCMD *set; { BITCMD *nset; int setbits, clrbits, Xbits, op; _DIAGASSERT(set != NULL); for (nset = set;;) { /* Copy over any 'u', 'g' and 'o' commands. */ while ((op = nset->cmd) != '+' && op != '-' && op != 'X') { *set++ = *nset++; if (!op) return; } for (setbits = clrbits = Xbits = 0;; nset++) { if ((op = nset->cmd) == '-') { clrbits |= nset->bits; setbits &= ~nset->bits; Xbits &= ~nset->bits; } else if (op == '+') { setbits |= nset->bits; clrbits &= ~nset->bits; Xbits &= ~nset->bits; } else if (op == 'X') Xbits |= nset->bits & ~setbits; else break; } if (clrbits) { set->cmd = '-'; set->cmd2 = 0; set->bits = clrbits; set++; } if (setbits) { set->cmd = '+'; set->cmd2 = 0; set->bits = setbits; set++; } if (Xbits) { set->cmd = 'X'; set->cmd2 = 0; set->bits = Xbits; set++; } } } kbuild-2695/src/kash/syntax.c0000644000000000000000000001101612247157307014647 0ustar rootroot/* $NetBSD: syntax.c,v 1.1 2004/01/17 17:38:12 dsl Exp $ */ #include "shell.h" #include "syntax.h" #include "parser.h" #include "shinstance.h" #ifdef _MSC_VER /* doesn't implement the fancy initializers I think... */ char basesyntax[257] = {CSHEOF}; char dqsyntax[257] = {CSHEOF}; char sqsyntax[257] = {CSHEOF}; char arisyntax[257] = {CSHEOF}; char is_type[257] = {0}; void init_syntax(void) { char *tab; int i; #define ndx(ch) (ch + 1 - CHAR_MIN) #define set(ch, val) tab[ndx(ch)] = val #define set_range(s, e, val) for (i = ndx(s); i <= ndx(e); i++) tab[i] = val /*basesyntax*/ tab = basesyntax; set_range(CTL_FIRST, CTL_LAST, CCTL); set('\n', CNL); set('\\', CBACK); set('\'', CSQUOTE); set('"', CDQUOTE); set('`', CBQUOTE); set('$', CVAR); set('}', CENDVAR); set('<', CSPCL); set('>', CSPCL); set('(', CSPCL); set(')', CSPCL); set(';', CSPCL); set('&', CSPCL); set('|', CSPCL); set(' ', CSPCL); set('\t', CSPCL); tab = dqsyntax; set_range(CTL_FIRST, CTL_LAST, CCTL); set('\n', CNL); set('\\', CBACK); set('"', CDQUOTE); set('`', CBQUOTE); set('$', CVAR); set('}', CENDVAR); /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ set('!', CCTL); set('*', CCTL); set('?', CCTL); set('[', CCTL); set('=', CCTL); set('~', CCTL); set(':', CCTL); set('/', CCTL); set('-', CCTL); tab = sqsyntax; set_range(CTL_FIRST, CTL_LAST, CCTL); set('\n', CNL); set('\'', CSQUOTE); /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ set('!', CCTL); set('*', CCTL) ; set('?', CCTL); set('[', CCTL); set('=', CCTL); set('~', CCTL); set(':', CCTL); set('/', CCTL); set('-', CCTL); tab = arisyntax; set_range(CTL_FIRST, CTL_LAST, CCTL); set('\n', CNL); set('\\', CBACK); set('`', CBQUOTE); set('\'', CSQUOTE); set('"', CDQUOTE); set('$', CVAR); set('}', CENDVAR); set('(', CLP); set(')', CRP); tab = is_type; set_range('0', '9', ISDIGIT); set_range('a', 'z', ISLOWER); set_range('A', 'Z', ISUPPER); set('_', ISUNDER); set('#', ISSPECL); set('?', ISSPECL); set('$', ISSPECL); set('!', ISSPECL); set('-', ISSPECL); set('*', ISSPECL); set('@', ISSPECL); } #else /* !_MSC_VER */ #if CWORD != 0 #error initialisation assumes 'CWORD' is zero #endif #define ndx(ch) (ch + 1 - CHAR_MIN) #define set(ch, val) [ndx(ch)] = val, #define set_range(s, e, val) [ndx(s) ... ndx(e)] = val, /* syntax table used when not in quotes */ const char basesyntax[257] = { CSHEOF, set_range(CTL_FIRST, CTL_LAST, CCTL) set('\n', CNL) set('\\', CBACK) set('\'', CSQUOTE) set('"', CDQUOTE) set('`', CBQUOTE) set('$', CVAR) set('}', CENDVAR) set('<', CSPCL) set('>', CSPCL) set('(', CSPCL) set(')', CSPCL) set(';', CSPCL) set('&', CSPCL) set('|', CSPCL) set(' ', CSPCL) set('\t', CSPCL) }; /* syntax table used when in double quotes */ const char dqsyntax[257] = { CSHEOF, set_range(CTL_FIRST, CTL_LAST, CCTL) set('\n', CNL) set('\\', CBACK) set('"', CDQUOTE) set('`', CBQUOTE) set('$', CVAR) set('}', CENDVAR) /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ set('!', CCTL) set('*', CCTL) set('?', CCTL) set('[', CCTL) set('=', CCTL) set('~', CCTL) set(':', CCTL) set('/', CCTL) set('-', CCTL) }; /* syntax table used when in single quotes */ const char sqsyntax[257] = { CSHEOF, set_range(CTL_FIRST, CTL_LAST, CCTL) set('\n', CNL) set('\'', CSQUOTE) /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ set('!', CCTL) set('*', CCTL) set('?', CCTL) set('[', CCTL) set('=', CCTL) set('~', CCTL) set(':', CCTL) set('/', CCTL) set('-', CCTL) }; /* syntax table used when in arithmetic */ const char arisyntax[257] = { CSHEOF, set_range(CTL_FIRST, CTL_LAST, CCTL) set('\n', CNL) set('\\', CBACK) set('`', CBQUOTE) set('\'', CSQUOTE) set('"', CDQUOTE) set('$', CVAR) set('}', CENDVAR) set('(', CLP) set(')', CRP) }; /* character classification table */ const char is_type[257] = { 0, set_range('0', '9', ISDIGIT) set_range('a', 'z', ISLOWER) set_range('A', 'Z', ISUPPER) set('_', ISUNDER) set('#', ISSPECL) set('?', ISSPECL) set('$', ISSPECL) set('!', ISSPECL) set('-', ISSPECL) set('*', ISSPECL) set('@', ISSPECL) }; #endif /* !_MSC_VER */ kbuild-2695/src/kash/Makefile.kmk0000644000000000000000000001212312247157307015376 0ustar rootroot# $Id: Makefile.kmk 2652 2012-09-09 17:21:48Z bird $ ## @file # Sub-makefile for kash. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = ../.. include $(KBUILD_PATH)/subheader.kmk # # The program. # PROGRAMS += kash kash_TEMPLATE = BIN-THREADED kash_NAME = kmk_ash kash_ASTOOL = YASM kash_DEFS = lint SHELL SMALL kash_DEFS += SH_FORKED_MODE kash_DEFS.debug = DEBUG=2 kash_DEFS.haiku = BSD kash_DEFS.linux = BSD kash_DEFS.solaris = BSD ## @todo bring over PC_SLASHES? kash_DEFS.win = \ BSD YY_NO_UNISTD_H \ SH_DEAL_WITH_CRLF PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS EXEC_HASH_BANG_SCRIPT kash_DEFS.os2 = \ HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME PC_OS2_LIBPATHS \ SH_DEAL_WITH_CRLF PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS EXEC_HASH_BANG_SCRIPT kash_DEFS.darwin = \ HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME kash_DEFS.dragonfly = \ HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME kash_DEFS.freebsd = \ HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME kash_DEFS.openbsd = \ HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME kash_INCS = $(kash_0_OUTDIR) . # (the last is because of error.h) kash_ASFLAGS.win = -g cv8 kash_ASFLAGS.win.x86 = -f win32 kash_ASFLAGS.win.amd64 = -f win64 if "$(USER)" == "bird" && "$(KBUILD_TARGET)" != "win" kash_CFLAGS += -std=gnu99 endif kash_CFLAGS.win.amd64 = -GS- kash_LDFLAGS.win = -DYNAMICBASE:NO kash_SOURCES = \ main.c \ alias.c \ cd.c \ error.c \ eval.c \ exec.c \ expand.c \ histedit.c \ input.c \ jobs.c \ mail.c \ memalloc.c \ mystring.c \ options.c \ output.c \ parser.c \ redir.c \ show.c \ syntax.c \ trap.c \ var.c \ miscbltin.c \ bltin/echo.c \ bltin/kill.c \ bltin/test.c \ \ $(kash_0_OUTDIR)/builtins.c \ $(kash_0_OUTDIR)/init.c \ $(kash_0_OUTDIR)/nodes.c \ \ setmode.c \ shinstance.c \ shheap.c \ shthread.c \ shfile.c kash_SOURCES.haiku = \ sys_signame.c \ strlcpy.c kash_SOURCES.linux = \ sys_signame.c \ strlcpy.c kash_SOURCES.solaris = \ sys_signame.c \ strlcpy.c kash_SOURCES.win = \ sys_signame.c \ strlcpy.c \ shfork-win.c \ shforkA-win.asm kash_INTERMEDIATES = \ $(kash_0_OUTDIR)/builtins.h \ $(kash_0_OUTDIR)/nodes.h \ $(kash_0_OUTDIR)/token.h kash_CLEAN = \ $(kash_INTERMEDIATES) \ $(kash_0_OUTDIR)/builtins.c \ $(kash_0_OUTDIR)/init.c \ $(kash_0_OUTDIR)/nodes.c kash_main.c_DEFS = KBUILD_SVN_REV=$(KBUILD_SVN_REV) ## ## The manual page. ## #INSTALLS += kash.man #kash.man_TEMPLATE = usr.bin.man #kash.man_SOURCES = sh.1=>kash.1 if1of ($(KBUILD_TARGET), win os2) # # Use the pregenerated code. # kash_SOURCES += \ $(kash_0_OUTDIR)/arith.c \ $(kash_0_OUTDIR)/arith_lex.c kash_INTERMEDIATES += \ $(kash_0_OUTDIR)/arith.h define def_copy_generated $$$$(kash_0_OUTDIR)/$(src): $(PATH_SUB_CURRENT)/generated/$(src) $$(RM) -f $$@ $$(CP) -f $$^ $$@ endef $(foreach src, arith.h arith.c arith_lex.c builtins.h builtins.c nodes.h nodes.c token.h init.c,\ $(eval $(def_copy_generated))) else # # Generate the code on the fly. # USES += lex yacc kash_USES = lex yacc kash_LEXTOOL = FLEX kash_LEXFLAGS = -8 #kash_YACCTOOL = BISON kash_YACCTOOL = YACC kash_YACCFLAGS = -ld kash_SOURCES += \ arith.y \ arith_lex.l # # ATTENTION! ATTENTION! ATTENTION! # # Older ash versions has trouble with some of these scripts, great. # Kudos to the NetBSD guys for this clever move. ;) # # So, when building for the frist time, setting BOOSTRAP_SHELL=/bin/bash is good idea. # BOOTSTRAP_SHELL ?= $(SHELL) $$(kash_0_OUTDIR)/builtins.h + $$(kash_0_OUTDIR)/builtins.c: \ $$(kash_DEFPATH)/mkbuiltins \ $$(kash_DEFPATH)/shell.h \ $$(kash_DEFPATH)/builtins.def \ | $$(dir $$@) $(BOOTSTRAP_SHELL) $+ $(dir $@) [ -f $(kash_0_OUTDIR)/builtins.h ] $$(kash_0_OUTDIR)/nodes.h + $$(kash_0_OUTDIR)/nodes.c: \ $$(kash_DEFPATH)/mknodes.sh \ $$(kash_DEFPATH)/nodetypes \ $$(kash_DEFPATH)/nodes.c.pat \ | $$(dir $$@) $(BOOTSTRAP_SHELL) $+ $(dir $@) [ -f $(dir $@)/nodes.h ] $$(kash_0_OUTDIR)/token.h: $$(kash_DEFPATH)/mktokens | $$(dir $$@) $(BOOTSTRAP_SHELL) $+ $(MV) token.h $@ $$(kash_0_OUTDIR)/init.c: \ $$(kash_DEFPATH)/mkinit.sh \ $$(abspathex $$(filter-out $$(kash_0_OUTDIR)/%,$$(kash_SOURCES)), $$(kash_DEFPATH)) \ | $$(dir $$@) $(BOOTSTRAP_SHELL) $+ $(MV) init.c $@ endif # # For debugging file handle inheritance on Windows. # if "$(KBUILD_TARGET)" == win && 0 PROGRAMS += tstDump tstDump_TEMPLATE = BIN tstDump_SOURCES = tstDump.c endif # Include the sub-makefile. include $(PATH_SUB_CURRENT)/tests/Makefile.kmk include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/src/kash/shtypes.h0000644000000000000000000000650512247157307015034 0ustar rootroot/* $Id: shtypes.h 2546 2011-10-01 19:49:54Z bird $ */ /** @file * Wrapper for missing types and such. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef ___shtypes_h___ #define ___shtypes_h___ #include "k/kTypes.h" /* Use these, not the ones below. */ #include #include #ifdef __HAIKU__ # include /* silly */ #elif !defined(_MSC_VER) # include #endif #ifdef _MSC_VER typedef signed char int8_t; typedef unsigned char uint8_t; typedef short int16_t; typedef unsigned short uint16_t; typedef int int32_t; typedef unsigned int uint32_t; typedef _int64 int64_t; typedef unsigned _int64 uint64_t; # if _MSC_VER >= 1400 # include /* intptr_t and uintptr_t */ # else typedef KIPTR intptr_t; typedef KUPTR uintptr_t; # endif #define INT16_C(c) (c) #define INT32_C(c) (c) #define INT64_C(c) (c ## LL) #define UINT8_C(c) (c) #define UINT16_C(c) (c) #define UINT32_C(c) (c ## U) #define UINT64_C(c) (c ## ULL) #define INTMAX_C(c) (c ## LL) #define UINTMAX_C(c) (c ## ULL) #undef INT8_MIN #define INT8_MIN (-0x7f-1) #undef INT16_MIN #define INT16_MIN (-0x7fff-1) #undef INT32_MIN #define INT32_MIN (-0x7fffffff-1) #undef INT64_MIN #define INT64_MIN (-0x7fffffffffffffffLL-1) #undef INT8_MAX #define INT8_MAX 0x7f #undef INT16_MAX #define INT16_MAX 0x7fff #undef INT32_MAX #define INT32_MAX 0x7fffffff #undef INT64_MAX #define INT64_MAX 0x7fffffffffffffffLL #undef UINT8_MAX #define UINT8_MAX 0xff #undef UINT16_MAX #define UINT16_MAX 0xffff #undef UINT32_MAX #define UINT32_MAX 0xffffffffU #undef UINT64_MAX #define UINT64_MAX 0xffffffffffffffffULL typedef int pid_t; typedef unsigned short uid_t; typedef unsigned short gid_t; typedef int mode_t; typedef intptr_t ssize_t; #else # include #endif struct shinstance; typedef struct shinstance shinstance; #ifdef _MSC_VER typedef uint32_t shsigset_t; #else typedef sigset_t shsigset_t; #endif typedef void (*shsig_t)(shinstance *, int); typedef struct shsigaction { shsig_t sh_handler; shsigset_t sh_mask; int sh_flags; } shsigaction_t; /* SH_NORETURN_1 must be both on prototypes and definitions, while SH_NORETURN_2 should at least be on the prototype. */ #ifdef _MSC_VER # define SH_NORETURN_1 __declspec(noreturn) # define SH_NORETURN_2 #else # define SH_NORETURN_1 # define SH_NORETURN_2 __attribute__((__noreturn__)) #endif #endif kbuild-2695/src/kash/TOUR0000644000000000000000000004147712247157307013707 0ustar rootroot# $NetBSD: TOUR,v 1.8 1996/10/16 14:24:56 christos Exp $ # @(#)TOUR 8.1 (Berkeley) 5/31/93 NOTE -- This is the original TOUR paper distributed with ash and does not represent the current state of the shell. It is provided anyway since it provides helpful information for how the shell is structured, but be warned that things have changed -- the current shell is still under development. ================================================================ A Tour through Ash Copyright 1989 by Kenneth Almquist. DIRECTORIES: The subdirectory bltin contains commands which can be compiled stand-alone. The rest of the source is in the main ash directory. SOURCE CODE GENERATORS: Files whose names begin with "mk" are programs that generate source code. A complete list of these programs is: program intput files generates ------- ------------ --------- mkbuiltins builtins builtins.h builtins.c mkinit *.c init.c mknodes nodetypes nodes.h nodes.c mksignames - signames.h signames.c mksyntax - syntax.h syntax.c mktokens - token.h bltin/mkexpr unary_op binary_op operators.h operators.c There are undoubtedly too many of these. Mkinit searches all the C source files for entries looking like: INIT { x = 1; /* executed during initialization */ } RESET { x = 2; /* executed when the shell does a longjmp back to the main command loop */ } SHELLPROC { x = 3; /* executed when the shell runs a shell procedure */ } It pulls this code out into routines which are when particular events occur. The intent is to improve modularity by isolating the information about which modules need to be explicitly initialized/reset within the modules themselves. Mkinit recognizes several constructs for placing declarations in the init.c file. INCLUDE "file.h" includes a file. The storage class MKINIT makes a declaration available in the init.c file, for example: MKINIT int funcnest; /* depth of function calls */ MKINIT alone on a line introduces a structure or union declara- tion: MKINIT struct redirtab { short renamed[10]; }; Preprocessor #define statements are copied to init.c without any special action to request this. INDENTATION: The ash source is indented in multiples of six spaces. The only study that I have heard of on the subject con- cluded that the optimal amount to indent is in the range of four to six spaces. I use six spaces since it is not too big a jump from the widely used eight spaces. If you really hate six space indentation, use the adjind (source included) program to change it to something else. EXCEPTIONS: Code for dealing with exceptions appears in exceptions.c. The C language doesn't include exception handling, so I implement it using setjmp and longjmp. The global variable exception contains the type of exception. EXERROR is raised by calling error. EXINT is an interrupt. EXSHELLPROC is an excep- tion which is raised when a shell procedure is invoked. The pur- pose of EXSHELLPROC is to perform the cleanup actions associated with other exceptions. After these cleanup actions, the shell can interpret a shell procedure itself without exec'ing a new copy of the shell. INTERRUPTS: In an interactive shell, an interrupt will cause an EXINT exception to return to the main command loop. (Exception: EXINT is not raised if the user traps interrupts using the trap command.) The INTOFF and INTON macros (defined in exception.h) provide uninterruptable critical sections. Between the execution of INTOFF and the execution of INTON, interrupt signals will be held for later delivery. INTOFF and INTON can be nested. MEMALLOC.C: Memalloc.c defines versions of malloc and realloc which call error when there is no memory left. It also defines a stack oriented memory allocation scheme. Allocating off a stack is probably more efficient than allocation using malloc, but the big advantage is that when an exception occurs all we have to do to free up the memory in use at the time of the exception is to restore the stack pointer. The stack is implemented using a linked list of blocks. STPUTC: If the stack were contiguous, it would be easy to store strings on the stack without knowing in advance how long the string was going to be: p = stackptr; *p++ = c; /* repeated as many times as needed */ stackptr = p; The folloing three macros (defined in memalloc.h) perform these operations, but grow the stack if you run off the end: STARTSTACKSTR(p); STPUTC(c, p); /* repeated as many times as needed */ grabstackstr(p); We now start a top-down look at the code: MAIN.C: The main routine performs some initialization, executes the user's profile if necessary, and calls cmdloop. Cmdloop is repeatedly parses and executes commands. OPTIONS.C: This file contains the option processing code. It is called from main to parse the shell arguments when the shell is invoked, and it also contains the set builtin. The -i and -j op- tions (the latter turns on job control) require changes in signal handling. The routines setjobctl (in jobs.c) and setinteractive (in trap.c) are called to handle changes to these options. PARSING: The parser code is all in parser.c. A recursive des- cent parser is used. Syntax tables (generated by mksyntax) are used to classify characters during lexical analysis. There are three tables: one for normal use, one for use when inside single quotes, and one for use when inside double quotes. The tables are machine dependent because they are indexed by character vari- ables and the range of a char varies from machine to machine. PARSE OUTPUT: The output of the parser consists of a tree of nodes. The various types of nodes are defined in the file node- types. Nodes of type NARG are used to represent both words and the con- tents of here documents. An early version of ash kept the con- tents of here documents in temporary files, but keeping here do- cuments in memory typically results in significantly better per- formance. It would have been nice to make it an option to use temporary files for here documents, for the benefit of small machines, but the code to keep track of when to delete the tem- porary files was complex and I never fixed all the bugs in it. (AT&T has been maintaining the Bourne shell for more than ten years, and to the best of my knowledge they still haven't gotten it to handle temporary files correctly in obscure cases.) The text field of a NARG structure points to the text of the word. The text consists of ordinary characters and a number of special codes defined in parser.h. The special codes are: CTLVAR Variable substitution CTLENDVAR End of variable substitution CTLBACKQ Command substitution CTLBACKQ|CTLQUOTE Command substitution inside double quotes CTLESC Escape next character A variable substitution contains the following elements: CTLVAR type name '=' [ alternative-text CTLENDVAR ] The type field is a single character specifying the type of sub- stitution. The possible types are: VSNORMAL $var VSMINUS ${var-text} VSMINUS|VSNUL ${var:-text} VSPLUS ${var+text} VSPLUS|VSNUL ${var:+text} VSQUESTION ${var?text} VSQUESTION|VSNUL ${var:?text} VSASSIGN ${var=text} VSASSIGN|VSNUL ${var=text} In addition, the type field will have the VSQUOTE flag set if the variable is enclosed in double quotes. The name of the variable comes next, terminated by an equals sign. If the type is not VSNORMAL, then the text field in the substitution follows, ter- minated by a CTLENDVAR byte. Commands in back quotes are parsed and stored in a linked list. The locations of these commands in the string are indicated by CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether the back quotes were enclosed in double quotes. The character CTLESC escapes the next character, so that in case any of the CTL characters mentioned above appear in the input, they can be passed through transparently. CTLESC is also used to escape '*', '?', '[', and '!' characters which were quoted by the user and thus should not be used for file name generation. CTLESC characters have proved to be particularly tricky to get right. In the case of here documents which are not subject to variable and command substitution, the parser doesn't insert any CTLESC characters to begin with (so the contents of the text field can be written without any processing). Other here docu- ments, and words which are not subject to splitting and file name generation, have the CTLESC characters removed during the vari- able and command substitution phase. Words which are subject splitting and file name generation have the CTLESC characters re- moved as part of the file name phase. EXECUTION: Command execution is handled by the following files: eval.c The top level routines. redir.c Code to handle redirection of input and output. jobs.c Code to handle forking, waiting, and job control. exec.c Code to to path searches and the actual exec sys call. expand.c Code to evaluate arguments. var.c Maintains the variable symbol table. Called from expand.c. EVAL.C: Evaltree recursively executes a parse tree. The exit status is returned in the global variable exitstatus. The alter- native entry evalbackcmd is called to evaluate commands in back quotes. It saves the result in memory if the command is a buil- tin; otherwise it forks off a child to execute the command and connects the standard output of the child to a pipe. JOBS.C: To create a process, you call makejob to return a job structure, and then call forkshell (passing the job structure as an argument) to create the process. Waitforjob waits for a job to complete. These routines take care of process groups if job control is defined. REDIR.C: Ash allows file descriptors to be redirected and then restored without forking off a child process. This is accom- plished by duplicating the original file descriptors. The redir- tab structure records where the file descriptors have be dupli- cated to. EXEC.C: The routine find_command locates a command, and enters the command in the hash table if it is not already there. The third argument specifies whether it is to print an error message if the command is not found. (When a pipeline is set up, find_command is called for all the commands in the pipeline be- fore any forking is done, so to get the commands into the hash table of the parent process. But to make command hashing as transparent as possible, we silently ignore errors at that point and only print error messages if the command cannot be found later.) The routine shellexec is the interface to the exec system call. EXPAND.C: Arguments are processed in three passes. The first (performed by the routine argstr) performs variable and command substitution. The second (ifsbreakup) performs word splitting and the third (expandmeta) performs file name generation. If the "/u" directory is simulated, then when "/u/username" is replaced by the user's home directory, the flag "didudir" is set. This tells the cd command that it should print out the directory name, just as it would if the "/u" directory were implemented using symbolic links. VAR.C: Variables are stored in a hash table. Probably we should switch to extensible hashing. The variable name is stored in the same string as the value (using the format "name=value") so that no string copying is needed to create the environment of a com- mand. Variables which the shell references internally are preal- located so that the shell can reference the values of these vari- ables without doing a lookup. When a program is run, the code in eval.c sticks any environment variables which precede the command (as in "PATH=xxx command") in the variable table as the simplest way to strip duplicates, and then calls "environment" to get the value of the environment. There are two consequences of this. First, if an assignment to PATH precedes the command, the value of PATH before the assign- ment must be remembered and passed to shellexec. Second, if the program turns out to be a shell procedure, the strings from the environment variables which preceded the command must be pulled out of the table and replaced with strings obtained from malloc, since the former will automatically be freed when the stack (see the entry on memalloc.c) is emptied. BUILTIN COMMANDS: The procedures for handling these are scat- tered throughout the code, depending on which location appears most appropriate. They can be recognized because their names al- ways end in "cmd". The mapping from names to procedures is specified in the file builtins, which is processed by the mkbuil- tins command. A builtin command is invoked with argc and argv set up like a normal program. A builtin command is allowed to overwrite its arguments. Builtin routines can call nextopt to do option pars- ing. This is kind of like getopt, but you don't pass argc and argv to it. Builtin routines can also call error. This routine normally terminates the shell (or returns to the main command loop if the shell is interactive), but when called from a builtin command it causes the builtin command to terminate with an exit status of 2. The directory bltins contains commands which can be compiled in- dependently but can also be built into the shell for efficiency reasons. The makefile in this directory compiles these programs in the normal fashion (so that they can be run regardless of whether the invoker is ash), but also creates a library named bltinlib.a which can be linked with ash. The header file bltin.h takes care of most of the differences between the ash and the stand-alone environment. The user should call the main routine "main", and #define main to be the name of the routine to use when the program is linked into ash. This #define should appear before bltin.h is included; bltin.h will #undef main if the pro- gram is to be compiled stand-alone. CD.C: This file defines the cd and pwd builtins. The pwd com- mand runs /bin/pwd the first time it is invoked (unless the user has already done a cd to an absolute pathname), but then remembers the current directory and updates it when the cd com- mand is run, so subsequent pwd commands run very fast. The main complication in the cd command is in the docd command, which resolves symbolic links into actual names and informs the user where the user ended up if he crossed a symbolic link. SIGNALS: Trap.c implements the trap command. The routine set- signal figures out what action should be taken when a signal is received and invokes the signal system call to set the signal ac- tion appropriately. When a signal that a user has set a trap for is caught, the routine "onsig" sets a flag. The routine dotrap is called at appropriate points to actually handle the signal. When an interrupt is caught and no trap has been set for that signal, the routine "onint" in error.c is called. OUTPUT: Ash uses it's own output routines. There are three out- put structures allocated. "Output" represents the standard out- put, "errout" the standard error, and "memout" contains output which is to be stored in memory. This last is used when a buil- tin command appears in backquotes, to allow its output to be col- lected without doing any I/O through the UNIX operating system. The variables out1 and out2 normally point to output and errout, respectively, but they are set to point to memout when appropri- ate inside backquotes. INPUT: The basic input routine is pgetc, which reads from the current input file. There is a stack of input files; the current input file is the top file on this stack. The code allows the input to come from a string rather than a file. (This is for the -c option and the "." and eval builtin commands.) The global variable plinno is saved and restored when files are pushed and popped from the stack. The parser routines store the number of the current line in this variable. DEBUGGING: If DEBUG is defined in shell.h, then the shell will write debugging information to the file $HOME/trace. Most of this is done using the TRACE macro, which takes a set of printf arguments inside two sets of parenthesis. Example: "TRACE(("n=%d0, n))". The double parenthesis are necessary be- cause the preprocessor can't handle functions with a variable number of arguments. Defining DEBUG also causes the shell to generate a core dump if it is sent a quit signal. The tracing code is in show.c. kbuild-2695/src/kash/cd.h0000644000000000000000000000410012247157307013710 0ustar rootroot/* $NetBSD: cd.h,v 1.4 2003/08/07 09:05:30 agc Exp $ */ /*- * Copyright (c) 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ const char *getpwd(struct shinstance *, int); int cdcmd(struct shinstance *, int, char **); int pwdcmd(struct shinstance *, int, char **); #ifdef PC_DRIVE_LETTERS #define IS_ROOT(path) ( *(path) == '/' \ || *(path) == '\\' \ || ( ((*(path) >= 'A' && *(path) <= 'Z') || (*(path) >= 'a' && *(path) <= 'z')) \ && (path)[1] == ':') ) #else #define IS_ROOT(path) ( *(path) == '/' ) #endif kbuild-2695/src/kash/arith_lex.l0000644000000000000000000001105312247157307015312 0ustar rootroot%option never-interactive %option noyywrap %option noinput %option nounput %option noyyget_out %option noyy_push_state %option noyy_pop_state %option noyy_top_state %option noyy_scan_buffer %option noyy_scan_bytes %option noyy_scan_string %option noyyget_extra %option noyyset_extra %option noyyget_leng %option noyyget_text %option noyyget_lineno %option noyyset_lineno %option noyyget_in %option noyyset_in %option noyyget_out %option noyyset_out %option noyyget_lval %option noyyset_lval %option noyyget_lloc %option noyyset_lloc %option noyyget_debug %option noyyset_debug %option noyyalloc %option noyyrealloc %option noyyfree /** @todo %option reentrant */ %{ /* $NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: arith_lex.l,v 1.13 2005/03/21 22:37:09 dsl Exp $"); #endif /* not lint */ #endif #include #include "arith.h" #include "error.h" #include "expand.h" #include "var.h" #include "shinstance.h" extern int yylval; extern shinstance *arith_psh; extern char *arith_buf, *arith_startbuf; #undef YY_INPUT #define YY_INPUT(buf,result,max) \ result = (*buf = *arith_buf++) ? 1 : YY_NULL; #define YY_NO_UNPUT /* Avoid unnecessary libc bits. */ #undef ECHO #define ECHO \ do {} while (0) #undef stdin #define stdin \ NULL #undef stdout #define stdout \ NULL #undef fprintf #define fprintf(a, b, c) \ ((void)0) #undef exit #define exit(rc) \ do {} while (0) #define YY_FATAL_ERROR(msg) \ error(arith_psh, "arith: fatal error: %s", msg) %} %% [ \t\n] { ; } 0x[0-9a-fA-F]+ { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); } 0[0-7]* { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); } [1-9][0-9]* { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); } [A-Za-z_][A-Za-z_0-9]* { char *v = lookupvar(arith_psh, yytext); if (v) { yylval = strtol(v, &v, 0); if (*v == 0) return ARITH_NUM; } error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf); } "(" { return(ARITH_LPAREN); } ")" { return(ARITH_RPAREN); } "||" { return(ARITH_OR); } "&&" { return(ARITH_AND); } "|" { return(ARITH_BOR); } "^" { return(ARITH_BXOR); } "&" { return(ARITH_BAND); } "==" { return(ARITH_EQ); } "!=" { return(ARITH_NE); } ">" { return(ARITH_GT); } ">=" { return(ARITH_GE); } "<" { return(ARITH_LT); } "<=" { return(ARITH_LE); } "<<" { return(ARITH_LSHIFT); } ">>" { return(ARITH_RSHIFT); } "*" { return(ARITH_MUL); } "/" { return(ARITH_DIV); } "%" { return(ARITH_REM); } "+" { return(ARITH_ADD); } "-" { return(ARITH_SUB); } "~" { return(ARITH_BNOT); } "!" { return(ARITH_NOT); } . { error(arith_psh, "arith: syntax error: \"%s\"", arith_startbuf); } %% void arith_lex_reset() { #ifdef YY_NEW_FILE YY_NEW_FILE; #endif } void * yyalloc(yy_size_t cb) { return sh_malloc(NULL, cb); } void * yyrealloc(void *pv, yy_size_t cb) { return sh_realloc(NULL, pv, cb); } void yyfree(void *pv) { sh_free(NULL, pv); } kbuild-2695/src/kash/shthread.h0000644000000000000000000000252712247157307015137 0ustar rootroot/* $Id: shthread.h 2413 2010-09-11 17:43:04Z bird $ */ /** @file * * Shell thread methods. * * Copyright (c) 2007-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef ___shthread_h___ #define ___shthread_h___ #include "shtypes.h" typedef struct shmtx { char b[64]; } shmtx; typedef struct shmtxtmp { int i; } shmtxtmp; typedef uintptr_t shtid; void shthread_set_shell(struct shinstance *); struct shinstance *shthread_get_shell(void); int shmtx_init(shmtx *pmtx); void shmtx_delete(shmtx *pmtx); void shmtx_enter(shmtx *pmtx, shmtxtmp *ptmp); void shmtx_leave(shmtx *pmtx, shmtxtmp *ptmp); #endif kbuild-2695/src/kash/options.c0000644000000000000000000002772012247157307015025 0ustar rootroot/* $NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: options.c,v 1.38 2005/03/20 21:38:17 dsl Exp $"); #endif /* not lint */ #endif #include #include "shell.h" #define DEFINE_OPTIONS #include "options.h" #undef DEFINE_OPTIONS #include "nodes.h" /* for other header files */ #include "eval.h" #include "jobs.h" #include "input.h" #include "output.h" #include "trap.h" #include "var.h" #include "memalloc.h" #include "error.h" #include "mystring.h" #ifndef SMALL # include "myhistedit.h" #endif #include "show.h" #include "shinstance.h" //char *arg0; /* value of $0 */ //struct shparam shellparam; /* current positional parameters */ //char **argptr; /* argument list for builtin commands */ //char *optionarg; /* set by nextopt (like getopt) */ //char *optptr; /* used by nextopt */ //char *minusc; /* argument to -c option */ STATIC void options(shinstance *, int); STATIC void minus_o(shinstance *, char *, int); STATIC void setoption(shinstance *, int, int); STATIC int getopts(shinstance *, char *, char *, char **, char ***, char **); /* * Process the shell command line arguments. */ void procargs(shinstance *psh, int argc, char **argv) { int i; psh->argptr = argv; if (argc > 0) psh->argptr++; for (i = 0; i < NOPTS; i++) psh->optlist[i].val = 2; options(psh, 1); if (*psh->argptr == NULL && psh->minusc == NULL) sflag(psh) = 1; if (iflag(psh) == 2 && sflag(psh) == 1 && shfile_isatty(&psh->fdtab, 0) && shfile_isatty(&psh->fdtab, 1)) iflag(psh) = 1; if (mflag(psh) == 2) mflag(psh) = iflag(psh); for (i = 0; i < NOPTS; i++) if (psh->optlist[i].val == 2) psh->optlist[i].val = 0; #if DEBUG == 2 debug(psh) = 1; #endif psh->arg0 = argv[0]; if (sflag(psh) == 0 && psh->minusc == NULL) { psh->commandname = argv[0]; psh->arg0 = *psh->argptr++; setinputfile(psh, psh->arg0, 0); psh->commandname = psh->arg0; } /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ if (psh->minusc != NULL) { if (psh->argptr == NULL || *psh->argptr == NULL) error(psh, "Bad -c option"); psh->minusc = *psh->argptr++; if (*psh->argptr != 0) psh->arg0 = *psh->argptr++; } psh->shellparam.p = psh->argptr; psh->shellparam.reset = 1; /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ while (*psh->argptr) { psh->shellparam.nparam++; psh->argptr++; } optschanged(psh); } void optschanged(shinstance *psh) { setinteractive(psh, iflag(psh)); #ifndef SMALL histedit(psh); #endif setjobctl(psh, mflag(psh)); } /* * Process shell options. The global variable argptr contains a pointer * to the argument list; we advance it past the options. */ STATIC void options(shinstance *psh, int cmdline) { static char empty[] = ""; char *p; int val; int c; if (cmdline) psh->minusc = NULL; while ((p = *psh->argptr) != NULL) { psh->argptr++; if ((c = *p++) == '-') { val = 1; if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) { if (!cmdline) { /* "-" means turn off -x and -v */ if (p[0] == '\0') xflag(psh) = vflag(psh) = 0; /* "--" means reset params */ else if (*psh->argptr == NULL) setparam(psh, psh->argptr); } break; /* "-" or "--" terminates options */ } } else if (c == '+') { val = 0; } else { psh->argptr--; break; } while ((c = *p++) != '\0') { if (c == 'c' && cmdline) { /* command is after shell args*/ psh->minusc = empty; } else if (c == 'o') { minus_o(psh, *psh->argptr, val); if (*psh->argptr) psh->argptr++; } else { setoption(psh, c, val); } } } } static void set_opt_val(shinstance *psh, int i, int val) { int j; int flag; if (val && (flag = psh->optlist[i].opt_set)) { /* some options (eg vi/emacs) are mutually exclusive */ for (j = 0; j < NOPTS; j++) if (psh->optlist[j].opt_set == flag) psh->optlist[j].val = 0; } psh->optlist[i].val = val; #ifdef DEBUG if (&psh->optlist[i].val == &debug(psh)) opentrace(psh); #endif } STATIC void minus_o(shinstance *psh, char *name, int val) { int i; if (name == NULL) { out1str(psh, "Current option settings\n"); for (i = 0; i < NOPTS; i++) out1fmt(psh, "%-16s%s\n", psh->optlist[i].name, psh->optlist[i].val ? "on" : "off"); } else { for (i = 0; i < NOPTS; i++) if (equal(name, psh->optlist[i].name)) { set_opt_val(psh, i, val); return; } error(psh, "Illegal option -o %s", name); } } STATIC void setoption(shinstance *psh, int flag, int val) { int i; for (i = 0; i < NOPTS; i++) if (psh->optlist[i].letter == flag) { set_opt_val(psh, i, val); return; } error(psh, "Illegal option -%c", flag); /* NOTREACHED */ } #ifdef mkinit INCLUDE "options.h" INIT { memcpy(&psh->optlist[0], &ro_optlist[0], sizeof(psh->optlist)); } SHELLPROC { int i; for (i = 0; psh->optlist[i].name; i++) psh->optlist[i].val = 0; # if DEBUG == 2 debug(psh) = 1; # endif optschanged(psh); } #endif /* * Set the shell parameters. */ void setparam(shinstance *psh, char **argv) { char **newparam; char **ap; int nparam; for (nparam = 0 ; argv[nparam] ; nparam++) continue; ap = newparam = ckmalloc(psh, (nparam + 1) * sizeof *ap); while (*argv) { *ap++ = savestr(psh, *argv++); } *ap = NULL; freeparam(psh, &psh->shellparam); psh->shellparam.malloc = 1; psh->shellparam.nparam = nparam; psh->shellparam.p = newparam; psh->shellparam.optnext = NULL; } /* * Free the list of positional parameters. */ void freeparam(shinstance *psh, volatile struct shparam *param) { char **ap; if (param->malloc) { for (ap = param->p ; *ap ; ap++) ckfree(psh, *ap); ckfree(psh, param->p); } } /* * The shift builtin command. */ int shiftcmd(shinstance *psh, int argc, char **argv) { int n; char **ap1, **ap2; n = 1; if (argc > 1) n = number(psh, argv[1]); if (n > psh->shellparam.nparam) error(psh, "can't shift that many"); INTOFF; psh->shellparam.nparam -= n; for (ap1 = psh->shellparam.p ; --n >= 0 ; ap1++) { if (psh->shellparam.malloc) ckfree(psh, *ap1); } ap2 = psh->shellparam.p; while ((*ap2++ = *ap1++) != NULL); psh->shellparam.optnext = NULL; INTON; return 0; } /* * The set command builtin. */ int setcmd(shinstance *psh, int argc, char **argv) { if (argc == 1) return showvars(psh, 0, 0, 1); INTOFF; options(psh, 0); optschanged(psh); if (*psh->argptr != NULL) { setparam(psh, psh->argptr); } INTON; return 0; } void getoptsreset(shinstance *psh, const char *value) { if (number(psh, value) == 1) { psh->shellparam.optnext = NULL; psh->shellparam.reset = 1; } } /* * The getopts builtin. Shellparam.optnext points to the next argument * to be processed. Shellparam.optptr points to the next character to * be processed in the current argument. If shellparam.optnext is NULL, * then it's the first time getopts has been called. */ int getoptscmd(shinstance *psh, int argc, char **argv) { char **optbase; if (argc < 3) error(psh, "usage: getopts optstring var [arg]"); else if (argc == 3) optbase = psh->shellparam.p; else optbase = &argv[3]; if (psh->shellparam.reset == 1) { psh->shellparam.optnext = optbase; psh->shellparam.optptr = NULL; psh->shellparam.reset = 0; } return getopts(psh, argv[1], argv[2], optbase, &psh->shellparam.optnext, &psh->shellparam.optptr); } STATIC int getopts(shinstance *psh, char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr) { char *p, *q; char c = '?'; int done = 0; int ind = 0; int err = 0; char s[12]; if ((p = *optpptr) == NULL || *p == '\0') { /* Current word is done, advance */ if (*optnext == NULL) return 1; p = **optnext; if (p == NULL || *p != '-' || *++p == '\0') { atend: ind = (int)(*optnext - optfirst + 1); *optnext = NULL; p = NULL; done = 1; goto out; } (*optnext)++; if (p[0] == '-' && p[1] == '\0') /* check for "--" */ goto atend; } c = *p++; for (q = optstr; *q != c; ) { if (*q == '\0') { if (optstr[0] == ':') { s[0] = c; s[1] = '\0'; err |= setvarsafe(psh, "OPTARG", s, 0); } else { outfmt(&psh->errout, "Illegal option -%c\n", c); (void) unsetvar(psh, "OPTARG", 0); } c = '?'; goto bad; } if (*++q == ':') q++; } if (*++q == ':') { if (*p == '\0' && (p = **optnext) == NULL) { if (optstr[0] == ':') { s[0] = c; s[1] = '\0'; err |= setvarsafe(psh, "OPTARG", s, 0); c = ':'; } else { outfmt(&psh->errout, "No arg for -%c option\n", c); (void) unsetvar(psh, "OPTARG", 0); c = '?'; } goto bad; } if (p == **optnext) (*optnext)++; err |= setvarsafe(psh, "OPTARG", p, 0); p = NULL; } else err |= setvarsafe(psh, "OPTARG", "", 0); ind = (int)(*optnext - optfirst + 1); goto out; bad: ind = 1; *optnext = NULL; p = NULL; out: *optpptr = p; fmtstr(s, sizeof(s), "%d", ind); err |= setvarsafe(psh, "OPTIND", s, VNOFUNC); s[0] = c; s[1] = '\0'; err |= setvarsafe(psh, optvar, s, 0); if (err) { *optnext = NULL; *optpptr = NULL; output_flushall(psh); exraise(psh, EXERROR); } return done; } /* * XXX - should get rid of. have all builtins use getopt(3). the * library getopt must have the BSD extension static variable "optreset" * otherwise it can't be used within the shell safely. * * Standard option processing (a la getopt) for builtin routines. The * only argument that is passed to nextopt is the option string; the * other arguments are unnecessary. It return the character, or '\0' on * end of input. */ int nextopt(shinstance *psh, const char *optstring) { char *p; const char *q; char c; if ((p = psh->optptr) == NULL || *p == '\0') { p = *psh->argptr; if (p == NULL || *p != '-' || *++p == '\0') return '\0'; psh->argptr++; if (p[0] == '-' && p[1] == '\0') /* check for "--" */ return '\0'; } c = *p++; for (q = optstring ; *q != c ; ) { if (*q == '\0') error(psh, "Illegal option -%c", c); if (*++q == ':') q++; } if (*++q == ':') { if (*p == '\0' && (p = *psh->argptr++) == NULL) error(psh, "No arg for -%c option", c); psh->optionarg = p; p = NULL; } psh->optptr = p; return c; } kbuild-2695/src/kash/mknodes.sh0000755000000000000000000001233712247157307015163 0ustar rootroot#! /bin/sh # $NetBSD: mknodes.sh,v 1.1 2004/01/16 23:24:38 dsl Exp $ # Copyright (c) 2003 The NetBSD Foundation, Inc. # All rights reserved. # # This code is derived from software contributed to The NetBSD Foundation # by David Laight. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of The NetBSD Foundation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. nodetypes=$1 nodes_pat=$2 objdir="$3" exec <$nodetypes exec >$objdir/nodes.h.tmp echo "/*" echo " * This file was generated by mknodes.sh" echo " */" echo tagno=0 while IFS=; read -r line; do line="${line%%#*}" IFS=' ' set -- $line IFS= [ -z "$2" ] && continue case "$line" in [" "]* ) IFS=' ' [ $field = 0 ] && struct_list="$struct_list $struct" eval field_${struct}_$field=\"\$*\" eval numfld_$struct=\$field field=$(($field + 1)) ;; * ) define=$1 struct=$2 echo "#define $define $tagno" tagno=$(($tagno + 1)) eval define_$struct=\"\$define_$struct \$define\" struct_define="$struct_define $struct" field=0 ;; esac done echo IFS=' ' for struct in $struct_list; do echo echo echo "struct $struct {" field=0 while eval line=\"\$field_${struct}_$field\" field=$(($field + 1)) [ -n "$line" ] do IFS=' ' set -- $line name=$1 case $2 in nodeptr ) type="union node *";; nodelist ) type="struct nodelist *";; string ) type="char *";; int ) type="int ";; * ) name=; shift 2; type="$*";; esac echo " $type$name;" done echo "};" done echo echo echo "union node {" echo " int type;" for struct in $struct_list; do echo " struct $struct $struct;" done echo "};" echo echo echo "struct nodelist {" echo " struct nodelist *next;" echo " union node *n;" echo "};" echo echo echo "union node *copyfunc(struct shinstance *, union node *);" echo "void freefunc(struct shinstance *, union node *);" exec <$nodes_pat exec >$objdir/nodes.c.tmp mv -f $objdir/nodes.h.tmp $objdir/nodes.h || exit 1 echo "/*" echo " * This file was generated by mknodes.sh" echo " */" echo while IFS=; read -r line; do IFS=' ' set -- $line IFS= case "$1" in '%SIZES' ) echo "static const short nodesize[$tagno] = {" IFS=' ' for struct in $struct_define; do echo " SHELL_ALIGN(sizeof (struct $struct))," done echo "};" ;; '%CALCSIZE' ) echo " if (n == NULL)" echo " return;" echo " funcblocksize += nodesize[n->type];" echo " switch (n->type) {" IFS=' ' for struct in $struct_list; do eval defines=\"\$define_$struct\" for define in $defines; do echo " case $define:" done eval field=\$numfld_$struct while [ $field != 0 ] do eval line=\"\$field_${struct}_$field\" field=$(($field - 1)) IFS=' ' set -- $line name=$1 cl=")" case $2 in nodeptr ) fn=calcsize;; nodelist ) fn=sizenodelist;; string ) fn="funcstringsize += strlen" cl=") + 1";; * ) continue;; esac echo " ${fn}(n->$struct.$name${cl};" done echo " break;" done echo " };" ;; '%COPY' ) echo " if (n == NULL)" echo " return NULL;" echo " new = funcblock;" echo " funcblock = (char *) funcblock + nodesize[n->type];" echo " switch (n->type) {" IFS=' ' for struct in $struct_list; do eval defines=\"\$define_$struct\" for define in $defines; do echo " case $define:" done eval field=\$numfld_$struct while [ $field != 0 ] do eval line=\"\$field_${struct}_$field\" field=$(($field - 1)) IFS=' ' set -- $line name=$1 case $2 in nodeptr ) fn="copynode(";; nodelist ) fn="copynodelist(";; string ) fn="nodesavestr(";; int ) fn=;; * ) continue;; esac f="$struct.$name" echo " new->$f = ${fn}n->$f${fn:+)};" done echo " break;" done echo " };" echo " new->type = n->type;" ;; * ) echo "$line";; esac done exec >/dev/null mv -f $objdir/nodes.c.tmp $objdir/nodes.c || exit 1 kbuild-2695/src/kash/shheap.c0000644000000000000000000003701312247157307014576 0ustar rootroot/* $Id: shheap.c 2416 2010-09-14 00:30:30Z bird $ */ /** @file * The shell memory heap methods. */ /* * Copyright (c) 2009-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "shheap.h" #include #include #include #include "shinstance.h" #if K_OS == K_OS_WINDOWS # define SHHEAP_IN_USE #endif #ifdef SHHEAP_IN_USE # if K_OS == K_OS_WINDOWS # include # else # include # endif #endif /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ #ifdef SHHEAP_IN_USE /** * heap memory block header. */ typedef struct shmemhdr { size_t magic; /**< Magic value */ size_t size; /**< The block size */ struct shmemhdr *next; /**< Forward pointer. */ struct shmemhdr *prev; /**< Backward pointer. */ struct shmemhdr *next2; /**< Free/Shell list forward. */ struct shmemhdr *prev2; /**< Free/Shell list backward. */ struct shinstance *psh; /**< The shell who allocated it. */ struct shmemchunk *chunk; /**< The chunk who owns this. */ } shmemhdr; /** Free block magic (shmemhdr::magic) */ #define SHMEMHDR_MAGIC_FREE 0xbeeff00d /** Used block magic (shmemhdr::magic) */ #define SHMEMHDR_MAGIC_USED 0xfeedface typedef struct shmemchunk { struct shmemhdr *head; /**< Head of the block list. */ struct shmemhdr *free_head; /**< Head of the free list. */ struct shmemchunk *next; /**< The next block. */ struct shmemchunk *prev; /**< The previous block. */ size_t size; /**< Chunk size. */ size_t magic; /**< Magic value. */ size_t padding0; size_t padding1; } shmemchunk; /** shmemchunk::magic */ #define SHMEMCHUNK_MAGIC 0x12345678 #endif /* K_OS_WINDOWS */ /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ #define SHHEAP_ALIGN(sz) (((sz) + 31) & ~(size_t)31) #define SHHEAP_CHUNK_ALIGN(sz) (((sz) + 0xffff) & ~(size_t)0xffff) #define SHHEAP_MIN_CHUNK 0x80000 //(1024*1024) #ifdef NDEBUG # define SHHEAP_CHECK() do { } while (0) # define SHHEAP_CHECK_2() do { } while (0) # define SHHEAP_ASSERT(expr) do { } while (0) # define SHHEAP_POISON_PSH(p,v) (p) # define SHHEAP_POISON_NULL(v) NULL #else # define SHHEAP_CHECK() shheap_check() # define SHHEAP_CHECK_2() shheap_check() # define SHHEAP_ASSERT(expr) assert(expr) # define SHHEAP_POISON_PSH(p,v) ((shinstance *)(v)) # define SHHEAP_POISON_NULL(v) ((void *)(v)) #endif /******************************************************************************* * Global Variables * *******************************************************************************/ #ifdef SHHEAP_IN_USE /** The heap lock. */ static shmtx g_sh_heap_mtx; /** The heap. * This is a list of chunks. */ static shmemchunk *g_sh_heap; #endif int shheap_init(void *phead) { int rc; #ifdef SHHEAP_IN_USE SHHEAP_ASSERT(SHHEAP_ALIGN(sizeof(shmemhdr)) == sizeof(shmemhdr)); rc = shmtx_init(&g_sh_heap_mtx); g_sh_heap = (shmemchunk *)phead; /* non-zero on fork() */ #else rc = 0; #endif return rc; } #ifdef SHHEAP_IN_USE # if K_OS == K_OS_WINDOWS /** * Get the head so the child can pass it to shheap_init() after fork(). * * @returns g_sh_heap. */ void *shheap_get_head(void) { return g_sh_heap; } /** * Copies the heap into the child process. * * @returns 0 on success, -1 and errno on failure. * @param hChild Handle to the child process. */ int shheap_fork_copy_to_child(void *hChild) { shmemchunk *chunk; shmtxtmp tmp; int err = 0; shmtx_enter(&g_sh_heap_mtx, &tmp); for (chunk = g_sh_heap; chunk; chunk = chunk->next) { void *chld_chnk; chld_chnk = (shmemchunk *)VirtualAllocEx(hChild, chunk, chunk->size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (chld_chnk != chunk) { err = GetLastError(); fprintf(stderr, "shfork: VirtualAllocEx(,%p,%p,) -> %p/%d\n", chunk, chunk->size, chld_chnk, err); break; } if (!WriteProcessMemory(hChild, chunk, chunk, chunk->size, NULL /* pNumberOfBytesWritten */)) { err = GetLastError(); fprintf(stderr, "shfork: WriteProcessMemory(,%p,,%p,) -> %d\n", chunk, chunk->size, err); break; } } shmtx_leave(&g_sh_heap_mtx, &tmp); if (!err) return 0; errno = EINVAL; return -1; } # endif /* K_OS == K_OS_WINDOWS */ /** * Checks a heap chunk. * @param chunk The chunk to check. */ static void shheap_check_chunk(shmemchunk *chunk) { size_t free_count; struct shmemhdr *mem; struct shmemhdr *prev; SHHEAP_ASSERT(chunk->magic == SHMEMCHUNK_MAGIC); SHHEAP_ASSERT(chunk->head); SHHEAP_ASSERT(chunk->size == SHHEAP_CHUNK_ALIGN(chunk->size)); free_count = 0; prev = NULL; for (mem = chunk->head; mem; mem = mem->next) { size_t size = (mem->next ? (char *)mem->next : (char *)chunk + chunk->size) - (char *)(mem + 1); SHHEAP_ASSERT(mem->size == size); SHHEAP_ASSERT(mem->prev == prev); if (mem->magic == SHMEMHDR_MAGIC_FREE) free_count++; else SHHEAP_ASSERT(mem->magic == SHMEMHDR_MAGIC_USED); prev = mem; } prev = NULL; for (mem = chunk->free_head; mem; mem = mem->next2) { size_t size = (mem->next ? (char *)mem->next : (char *)chunk + chunk->size) - (char *)(mem + 1); SHHEAP_ASSERT(mem->size == size); SHHEAP_ASSERT(mem->prev2 == prev); SHHEAP_ASSERT(mem->magic == SHMEMHDR_MAGIC_FREE); free_count--; prev = mem; } SHHEAP_ASSERT(free_count == 0); } /** * Checks the heap. */ static void shheap_check(void) { shmemchunk *chunk; for (chunk = g_sh_heap; chunk; chunk = chunk->next) shheap_check_chunk(chunk); } /** * Grows the heap with another chunk carving out a block * * @returns Pointer to a used entry of size @a size1. NULL * if we're out of memory * @param size1 The size of the block to be returned (aligned). */ static shmemhdr *shheap_grow(size_t size1) { shmemchunk *chunk; shmemhdr *used; shmemhdr *avail; size_t chunk_size; /* Calc the chunk size and allocate it. */ chunk_size = SHHEAP_ALIGN(size1) + SHHEAP_ALIGN(sizeof(*chunk)) + SHHEAP_ALIGN(sizeof(*used)) * 10; if (chunk_size < SHHEAP_MIN_CHUNK) chunk_size = SHHEAP_MIN_CHUNK; else chunk_size = SHHEAP_CHUNK_ALIGN(chunk_size); # if K_OS == K_OS_WINDOWS chunk = (shmemchunk *)VirtualAlloc(NULL, chunk_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); # else chunk = NULL; # endif if (!chunk) return NULL; used = (shmemhdr *)((char *)chunk + SHHEAP_ALIGN(sizeof(*chunk))); avail = (shmemhdr *)((char *)(used + 1) + size1); used->magic = SHMEMHDR_MAGIC_USED; used->size = size1; used->next = avail; used->prev = NULL; used->next2 = SHHEAP_POISON_NULL(0x41); used->prev2 = SHHEAP_POISON_NULL(0x41); used->psh = NULL; used->chunk = chunk; avail->magic = SHMEMHDR_MAGIC_FREE; avail->size = (char *)chunk + chunk_size - (char *)(avail + 1); avail->next = NULL; avail->prev = used; avail->next2 = NULL; avail->prev2 = NULL; avail->psh = NULL; avail->chunk = chunk; chunk->head = used; chunk->free_head = avail; chunk->size = chunk_size; chunk->magic = SHMEMCHUNK_MAGIC; chunk->prev = NULL; chunk->next = g_sh_heap; if (g_sh_heap) g_sh_heap->prev = chunk; g_sh_heap = chunk; chunk->padding0 = 0; chunk->padding1 = 0; SHHEAP_CHECK_2(); return used; } /*** * Splits a big memory block into two smaller, one with the * size @a size1. * * The one with the given size is removed from the free list * while the other one remains there. * * @returns The @a size1 sized block, NULL on failure. * @param big The block that is too big. * @param size1 The size of the block to be returned (aligned). */ static shmemhdr *shheap_split(shmemhdr *big, size_t size1) { shmemhdr *split; SHHEAP_ASSERT(SHHEAP_ALIGN(sizeof(*big)) == sizeof(*big)); SHHEAP_ASSERT(big->magic == SHMEMHDR_MAGIC_FREE); SHHEAP_ASSERT(!big->next2 || big->next2->magic == SHMEMHDR_MAGIC_FREE); SHHEAP_ASSERT(!big->prev2 || big->prev2->magic == SHMEMHDR_MAGIC_FREE); split = (shmemhdr *)((uint8_t *)(big + 1) + size1); split->magic = SHMEMHDR_MAGIC_FREE; split->size = big->size - size1 - sizeof(*split); split->next = big->next; split->prev = big; split->next2 = big->next2; split->prev2 = big->prev2; split->psh = SHHEAP_POISON_NULL(0x54); split->chunk = big->chunk; if (big->next2) big->next2->prev2 = split; if (big->prev2) big->prev2->next2 = split; else big->chunk->free_head = split; big->magic = SHMEMHDR_MAGIC_USED; big->next2 = big->prev2 = SHHEAP_POISON_NULL(0x41); if (big->next) big->next->prev = split; big->next = split; big->size = size1; SHHEAP_CHECK_2(); return big; } /*** * Unlinks a free memory block. * @param mem The block to unlink. */ static void shheap_unlink_free(shmemhdr *mem) { if (mem->next2) mem->next2->prev2 = mem->prev2; if (mem->prev2) mem->prev2->next2 = mem->next2; else mem->chunk->free_head = mem->next2; mem->magic = SHMEMHDR_MAGIC_USED; mem->next2 = mem->prev2 = SHHEAP_POISON_NULL(0x42); } #endif /* SHHEAP_IN_USE */ /** free() */ void sh_free(shinstance *psh, void *ptr) { #ifdef SHHEAP_IN_USE shmemhdr *mem = (shmemhdr *)ptr - 1; shmemhdr *right; shmemhdr *left; shmtxtmp tmp; if (mem->magic != SHMEMHDR_MAGIC_USED) { SHHEAP_ASSERT(0); return; } shmtx_enter(&g_sh_heap_mtx, &tmp); SHHEAP_CHECK(); /* join right. */ right = mem->next; if ( right && right->magic == SHMEMHDR_MAGIC_FREE) { mem->next = right->next; if (right->next) right->next->prev = mem; mem->next2 = right->next2; if (right->next2) right->next2->prev2 = mem; mem->prev2 = right->prev2; if (right->prev2) mem->prev2->next2 = mem; else mem->chunk->free_head = mem; mem->size += sizeof(*right) + right->size; mem->magic = SHMEMHDR_MAGIC_FREE; right->magic = ~SHMEMHDR_MAGIC_FREE; mem->psh = SHHEAP_POISON_NULL(0x50); SHHEAP_CHECK_2(); } /* join left */ left = mem->prev; if ( left && left->magic == SHMEMHDR_MAGIC_FREE) { left->next = mem->next; if (mem->next) mem->next->prev = left; if (mem->magic == SHMEMHDR_MAGIC_FREE) { if (mem->next2) mem->next2->prev2 = mem->prev2; if (mem->prev2) mem->prev2->next2 = mem->next2; else mem->chunk->free_head = mem->next2; } left->size += sizeof(*mem) + mem->size; mem->magic = ~SHMEMHDR_MAGIC_USED; left->psh = SHHEAP_POISON_NULL(0x51); } /* insert as free if necessary */ else if (mem->magic == SHMEMHDR_MAGIC_USED) { mem->prev2 = NULL; mem->next2 = mem->chunk->free_head; if (mem->chunk->free_head) mem->chunk->free_head->prev2 = mem; mem->chunk->free_head = mem; mem->magic = SHMEMHDR_MAGIC_FREE; mem->psh = SHHEAP_POISON_NULL(0x52); } SHHEAP_CHECK(); shmtx_leave(&g_sh_heap_mtx, &tmp); #else if (ptr) free(ptr); (void)psh; #endif } /** malloc() */ void *sh_malloc(shinstance *psh, size_t size) { #ifdef SHHEAP_IN_USE shmemchunk *chunk; shmemhdr *mem; shmtxtmp tmp; size = SHHEAP_ALIGN(size); SHHEAP_ASSERT(size); if (!size) size = SHHEAP_ALIGN(1); shmtx_enter(&g_sh_heap_mtx, &tmp); SHHEAP_CHECK(); /* Search for fitting block */ mem = NULL; chunk = g_sh_heap; while (chunk) { mem = chunk->free_head; while (mem && mem->size < size) mem = mem->next2; if (mem) break; chunk = chunk->next; } if (mem) { /* split it, or just unlink it? */ if (mem->size - size > sizeof(*mem) * 2) mem = shheap_split(mem, size); else shheap_unlink_free(mem); } else { /* no block found, try grow the heap. */ mem = shheap_grow(size); if (!mem) { shmtx_leave(&g_sh_heap_mtx, &tmp); return NULL; } } SHHEAP_CHECK(); shmtx_leave(&g_sh_heap_mtx, &tmp); mem->psh = SHHEAP_POISON_PSH(psh, 0x53); return mem + 1; #else (void)psh; return malloc(size); #endif } /** calloc() */ void *sh_calloc(shinstance *psh, size_t num, size_t item_size) { #ifdef SHHEAP_IN_USE size_t size = num * item_size; void *pv = sh_malloc(psh, size); if (pv) pv = memset(pv, '\0', size); return pv; #else (void)psh; return calloc(num, item_size); #endif } /** realloc() */ void *sh_realloc(shinstance *psh, void *old, size_t new_size) { #ifdef SHHEAP_IN_USE void *pv; if (new_size) { if (old) { shmemhdr *hdr = (shmemhdr *)old - 1; if (hdr->size < new_size) { pv = sh_malloc(psh, new_size); if (pv) { memcpy(pv, old, hdr->size); sh_free(psh, old); } } else pv = old; } else pv = sh_malloc(psh, new_size); } else { sh_free(psh, old); pv = NULL; } return pv; #else return realloc(old, new_size); #endif } /** strdup() */ char *sh_strdup(shinstance *psh, const char *string) { size_t len = strlen(string); char *ret = sh_malloc(psh, len + 1); if (ret) memcpy(ret, string, len + 1); return ret; } kbuild-2695/src/kash/parser.c0000644000000000000000000012120512247157307014617 0ustar rootroot/* $NetBSD: parser.c,v 1.59 2005/03/21 20:10:29 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; #else __RCSID("$NetBSD: parser.c,v 1.59 2005/03/21 20:10:29 dsl Exp $"); #endif /* not lint */ #endif #include #include "shell.h" #include "parser.h" #include "nodes.h" #include "expand.h" /* defines rmescapes() */ #include "eval.h" /* defines commandname */ #include "redir.h" /* defines copyfd() */ #include "syntax.h" #include "options.h" #include "input.h" #include "output.h" #include "var.h" #include "error.h" #include "memalloc.h" #include "mystring.h" #include "alias.h" #include "show.h" #ifndef SMALL # include "myhistedit.h" #endif #include "cd.h" #include "shinstance.h" /* * Shell command parser. */ #define EOFMARKLEN 79 /* values returned by readtoken */ #include "token.h" #define OPENBRACE '{' #define CLOSEBRACE '}' struct heredoc { struct heredoc *next; /* next here document in list */ union node *here; /* redirection node */ char *eofmark; /* string indicating end of input */ int striptabs; /* if set, strip leading tabs */ }; //static int noalias = 0; /* when set, don't handle aliases */ //struct heredoc *heredoclist; /* list of here documents to read */ //int parsebackquote; /* nonzero if we are inside backquotes */ //int doprompt; /* if set, prompt the user */ //int needprompt; /* true if interactive and at start of line */ //int lasttoken; /* last token read */ //MKINIT int tokpushback; /* last token pushed back */ //char *wordtext; /* text of last word returned by readtoken */ //MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */ //struct nodelist *backquotelist; //union node *redirnode; //struct heredoc *heredoc; //int quoteflag; /* set if (part of) last token was quoted */ //int startlinno; /* line # where last token started */ STATIC union node *list(shinstance *, int); STATIC union node *andor(shinstance *); STATIC union node *pipeline(shinstance *); STATIC union node *command(shinstance *); STATIC union node *simplecmd(shinstance *, union node **, union node *); STATIC union node *makename(shinstance *); STATIC void parsefname(shinstance *); STATIC void parseheredoc(shinstance *); STATIC int peektoken(shinstance *); STATIC int readtoken(shinstance *); STATIC int xxreadtoken(shinstance *); STATIC int readtoken1(shinstance *, int, char const *, char *, int); STATIC int noexpand(shinstance *, char *); SH_NORETURN_1 STATIC void synexpect(shinstance *, int) SH_NORETURN_2; SH_NORETURN_1 STATIC void synerror(shinstance *, const char *) SH_NORETURN_2; STATIC void setprompt(shinstance *, int); /* * Read and parse a command. Returns NEOF on end of file. (NULL is a * valid parse tree indicating a blank line.) */ union node * parsecmd(shinstance *psh, int interact) { int t; psh->tokpushback = 0; psh->doprompt = interact; if (psh->doprompt) setprompt(psh, 1); else setprompt(psh, 0); psh->needprompt = 0; t = readtoken(psh); if (t == TEOF) return NEOF; if (t == TNL) return NULL; psh->tokpushback++; return list(psh, 1); } STATIC union node * list(shinstance *psh, int nlflag) { union node *n1, *n2, *n3; int tok; psh->checkkwd = 2; if (nlflag == 0 && tokendlist[peektoken(psh)]) return NULL; n1 = NULL; for (;;) { n2 = andor(psh); tok = readtoken(psh); if (tok == TBACKGND) { if (n2->type == NCMD || n2->type == NPIPE) { n2->ncmd.backgnd = 1; } else if (n2->type == NREDIR) { n2->type = NBACKGND; } else { n3 = (union node *)stalloc(psh, sizeof (struct nredir)); n3->type = NBACKGND; n3->nredir.n = n2; n3->nredir.redirect = NULL; n2 = n3; } } if (n1 == NULL) { n1 = n2; } else { n3 = (union node *)stalloc(psh, sizeof (struct nbinary)); n3->type = NSEMI; n3->nbinary.ch1 = n1; n3->nbinary.ch2 = n2; n1 = n3; } switch (tok) { case TBACKGND: case TSEMI: tok = readtoken(psh); /* fall through */ case TNL: if (tok == TNL) { parseheredoc(psh); if (nlflag) return n1; } else { psh->tokpushback++; } psh->checkkwd = 2; if (tokendlist[peektoken(psh)]) return n1; break; case TEOF: if (psh->heredoclist) parseheredoc(psh); else pungetc(psh); /* push back EOF on input */ return n1; default: if (nlflag) synexpect(psh, -1); psh->tokpushback++; return n1; } } } STATIC union node * andor(shinstance *psh) { union node *n1, *n2, *n3; int t; n1 = pipeline(psh); for (;;) { if ((t = readtoken(psh)) == TAND) { t = NAND; } else if (t == TOR) { t = NOR; } else { psh->tokpushback++; return n1; } n2 = pipeline(psh); n3 = (union node *)stalloc(psh, sizeof (struct nbinary)); n3->type = t; n3->nbinary.ch1 = n1; n3->nbinary.ch2 = n2; n1 = n3; } } STATIC union node * pipeline(shinstance *psh) { union node *n1, *n2, *pipenode; struct nodelist *lp, *prev; int negate; negate = 0; TRACE((psh, "pipeline: entered\n")); while (readtoken(psh) == TNOT) negate = !negate; psh->tokpushback++; n1 = command(psh); if (readtoken(psh) == TPIPE) { pipenode = (union node *)stalloc(psh, sizeof (struct npipe)); pipenode->type = NPIPE; pipenode->npipe.backgnd = 0; lp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist)); pipenode->npipe.cmdlist = lp; lp->n = n1; do { prev = lp; lp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist)); lp->n = command(psh); prev->next = lp; } while (readtoken(psh) == TPIPE); lp->next = NULL; n1 = pipenode; } psh->tokpushback++; if (negate) { n2 = (union node *)stalloc(psh, sizeof (struct nnot)); n2->type = NNOT; n2->nnot.com = n1; return n2; } else return n1; } STATIC union node * command(shinstance *psh) { union node *n1, *n2; union node *ap, **app; union node *cp, **cpp; union node *redir, **rpp; int t, negate = 0; psh->checkkwd = 2; redir = NULL; n1 = NULL; rpp = &redir; /* Check for redirection which may precede command */ while (readtoken(psh) == TREDIR) { *rpp = n2 = psh->redirnode; rpp = &n2->nfile.next; parsefname(psh); } psh->tokpushback++; while (readtoken(psh) == TNOT) { TRACE((psh, "command: TNOT recognized\n")); negate = !negate; } psh->tokpushback++; switch (readtoken(psh)) { case TIF: n1 = (union node *)stalloc(psh, sizeof (struct nif)); n1->type = NIF; n1->nif.test = list(psh, 0); if (readtoken(psh) != TTHEN) synexpect(psh, TTHEN); n1->nif.ifpart = list(psh, 0); n2 = n1; while (readtoken(psh) == TELIF) { n2->nif.elsepart = (union node *)stalloc(psh, sizeof (struct nif)); n2 = n2->nif.elsepart; n2->type = NIF; n2->nif.test = list(psh, 0); if (readtoken(psh) != TTHEN) synexpect(psh, TTHEN); n2->nif.ifpart = list(psh, 0); } if (psh->lasttoken == TELSE) n2->nif.elsepart = list(psh, 0); else { n2->nif.elsepart = NULL; psh->tokpushback++; } if (readtoken(psh) != TFI) synexpect(psh, TFI); psh->checkkwd = 1; break; case TWHILE: case TUNTIL: { int got; n1 = (union node *)stalloc(psh, sizeof (struct nbinary)); n1->type = (psh->lasttoken == TWHILE)? NWHILE : NUNTIL; n1->nbinary.ch1 = list(psh, 0); if ((got=readtoken(psh)) != TDO) { TRACE((psh, "expecting DO got %s %s\n", tokname[got], got == TWORD ? psh->wordtext : "")); synexpect(psh, TDO); } n1->nbinary.ch2 = list(psh, 0); if (readtoken(psh) != TDONE) synexpect(psh, TDONE); psh->checkkwd = 1; break; } case TFOR: if (readtoken(psh) != TWORD || psh->quoteflag || ! goodname(psh->wordtext)) synerror(psh, "Bad for loop variable"); n1 = (union node *)stalloc(psh, sizeof (struct nfor)); n1->type = NFOR; n1->nfor.var = psh->wordtext; if (readtoken(psh) == TWORD && ! psh->quoteflag && equal(psh->wordtext, "in")) { app = ≈ while (readtoken(psh) == TWORD) { n2 = (union node *)stalloc(psh, sizeof (struct narg)); n2->type = NARG; n2->narg.text = psh->wordtext; n2->narg.backquote = psh->backquotelist; *app = n2; app = &n2->narg.next; } *app = NULL; n1->nfor.args = ap; if (psh->lasttoken != TNL && psh->lasttoken != TSEMI) synexpect(psh, -1); } else { static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'}; n2 = (union node *)stalloc(psh, sizeof (struct narg)); n2->type = NARG; n2->narg.text = argvars; n2->narg.backquote = NULL; n2->narg.next = NULL; n1->nfor.args = n2; /* * Newline or semicolon here is optional (but note * that the original Bourne shell only allowed NL). */ if (psh->lasttoken != TNL && psh->lasttoken != TSEMI) psh->tokpushback++; } psh->checkkwd = 2; if ((t = readtoken(psh)) == TDO) t = TDONE; else if (t == TBEGIN) t = TEND; else synexpect(psh, -1); n1->nfor.body = list(psh, 0); if (readtoken(psh) != t) synexpect(psh, t); psh->checkkwd = 1; break; case TCASE: n1 = (union node *)stalloc(psh, sizeof (struct ncase)); n1->type = NCASE; if (readtoken(psh) != TWORD) synexpect(psh, TWORD); n1->ncase.expr = n2 = (union node *)stalloc(psh, sizeof (struct narg)); n2->type = NARG; n2->narg.text = psh->wordtext; n2->narg.backquote = psh->backquotelist; n2->narg.next = NULL; while (readtoken(psh) == TNL); if (psh->lasttoken != TWORD || ! equal(psh->wordtext, "in")) synerror(psh, "expecting \"in\""); cpp = &n1->ncase.cases; psh->noalias = 1; psh->checkkwd = 2, readtoken(psh); do { *cpp = cp = (union node *)stalloc(psh, sizeof (struct nclist)); cp->type = NCLIST; app = &cp->nclist.pattern; for (;;) { *app = ap = (union node *)stalloc(psh, sizeof (struct narg)); ap->type = NARG; ap->narg.text = psh->wordtext; ap->narg.backquote = psh->backquotelist; if (psh->checkkwd = 2, readtoken(psh) != TPIPE) break; app = &ap->narg.next; readtoken(psh); } ap->narg.next = NULL; psh->noalias = 0; if (psh->lasttoken != TRP) { synexpect(psh, TRP); } cp->nclist.body = list(psh, 0); psh->checkkwd = 2; if ((t = readtoken(psh)) != TESAC) { if (t != TENDCASE) { psh->noalias = 0; synexpect(psh, TENDCASE); } else { psh->noalias = 1; psh->checkkwd = 2; readtoken(psh); } } cpp = &cp->nclist.next; } while(psh->lasttoken != TESAC); psh->noalias = 0; *cpp = NULL; psh->checkkwd = 1; break; case TLP: n1 = (union node *)stalloc(psh, sizeof (struct nredir)); n1->type = NSUBSHELL; n1->nredir.n = list(psh, 0); n1->nredir.redirect = NULL; if (readtoken(psh) != TRP) synexpect(psh, TRP); psh->checkkwd = 1; break; case TBEGIN: n1 = list(psh, 0); if (readtoken(psh) != TEND) synexpect(psh, TEND); psh->checkkwd = 1; break; /* Handle an empty command like other simple commands. */ case TSEMI: /* * An empty command before a ; doesn't make much sense, and * should certainly be disallowed in the case of `if ;'. */ if (!redir) synexpect(psh, -1); case TAND: case TOR: case TNL: case TEOF: case TWORD: case TRP: psh->tokpushback++; n1 = simplecmd(psh, rpp, redir); goto checkneg; default: synexpect(psh, -1); /* NOTREACHED */ } /* Now check for redirection which may follow command */ while (readtoken(psh) == TREDIR) { *rpp = n2 = psh->redirnode; rpp = &n2->nfile.next; parsefname(psh); } psh->tokpushback++; *rpp = NULL; if (redir) { if (n1->type != NSUBSHELL) { n2 = (union node *)stalloc(psh, sizeof (struct nredir)); n2->type = NREDIR; n2->nredir.n = n1; n1 = n2; } n1->nredir.redirect = redir; } checkneg: if (negate) { n2 = (union node *)stalloc(psh, sizeof (struct nnot)); n2->type = NNOT; n2->nnot.com = n1; return n2; } else return n1; } STATIC union node * simplecmd(shinstance *psh, union node **rpp, union node *redir) { union node *args, **app; union node **orig_rpp = rpp; union node *n = NULL, *n2; int negate = 0; /* If we don't have any redirections already, then we must reset */ /* rpp to be the address of the local redir variable. */ if (redir == 0) rpp = &redir; args = NULL; app = &args; /* * We save the incoming value, because we need this for shell * functions. There can not be a redirect or an argument between * the function name and the open parenthesis. */ orig_rpp = rpp; while (readtoken(psh) == TNOT) { TRACE((psh, "command: TNOT recognized\n")); negate = !negate; } psh->tokpushback++; for (;;) { if (readtoken(psh) == TWORD) { n = (union node *)stalloc(psh, sizeof (struct narg)); n->type = NARG; n->narg.text = psh->wordtext; n->narg.backquote = psh->backquotelist; *app = n; app = &n->narg.next; } else if (psh->lasttoken == TREDIR) { *rpp = n = psh->redirnode; rpp = &n->nfile.next; parsefname(psh); /* read name of redirection file */ } else if (psh->lasttoken == TLP && app == &args->narg.next && rpp == orig_rpp) { /* We have a function */ if (readtoken(psh) != TRP) synexpect(psh, TRP); #ifdef notdef if (! goodname(n->narg.text)) synerror(psh, "Bad function name"); #endif n->type = NDEFUN; n->narg.next = command(psh); goto checkneg; } else { psh->tokpushback++; break; } } *app = NULL; *rpp = NULL; n = (union node *)stalloc(psh, sizeof (struct ncmd)); n->type = NCMD; n->ncmd.backgnd = 0; n->ncmd.args = args; n->ncmd.redirect = redir; checkneg: if (negate) { n2 = (union node *)stalloc(psh, sizeof (struct nnot)); n2->type = NNOT; n2->nnot.com = n; return n2; } else return n; } STATIC union node * makename(shinstance *psh) { union node *n; n = (union node *)stalloc(psh, sizeof (struct narg)); n->type = NARG; n->narg.next = NULL; n->narg.text = psh->wordtext; n->narg.backquote = psh->backquotelist; return n; } void fixredir(shinstance *psh, union node *n, const char *text, int err) { TRACE((psh, "Fix redir %s %d\n", text, err)); if (!err) n->ndup.vname = NULL; if (is_digit(text[0]) && text[1] == '\0') n->ndup.dupfd = digit_val(text[0]); else if (text[0] == '-' && text[1] == '\0') n->ndup.dupfd = -1; else { if (err) synerror(psh, "Bad fd number"); else n->ndup.vname = makename(psh); } } STATIC void parsefname(shinstance *psh) { union node *n = psh->redirnode; if (readtoken(psh) != TWORD) synexpect(psh, -1); if (n->type == NHERE) { struct heredoc *here = psh->heredoc; struct heredoc *p; size_t i; if (psh->quoteflag == 0) n->type = NXHERE; TRACE((psh, "Here document %d\n", n->type)); if (here->striptabs) { while (*psh->wordtext == '\t') psh->wordtext++; } if (! noexpand(psh, psh->wordtext) || (i = strlen(psh->wordtext)) == 0 || i > EOFMARKLEN) synerror(psh, "Illegal eof marker for << redirection"); rmescapes(psh, psh->wordtext); here->eofmark = psh->wordtext; here->next = NULL; if (psh->heredoclist == NULL) psh->heredoclist = here; else { for (p = psh->heredoclist ; p->next ; p = p->next); p->next = here; } } else if (n->type == NTOFD || n->type == NFROMFD) { fixredir(psh, n, psh->wordtext, 0); } else { n->nfile.fname = makename(psh); } } /* * Input any here documents. */ STATIC void parseheredoc(shinstance *psh) { struct heredoc *here; union node *n; while (psh->heredoclist) { here = psh->heredoclist; psh->heredoclist = here->next; if (psh->needprompt) { setprompt(psh, 2); psh->needprompt = 0; } readtoken1(psh, pgetc(psh), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, here->eofmark, here->striptabs); n = (union node *)stalloc(psh, sizeof (struct narg)); n->narg.type = NARG; n->narg.next = NULL; n->narg.text = psh->wordtext; n->narg.backquote = psh->backquotelist; here->here->nhere.doc = n; } } STATIC int peektoken(shinstance *psh) { int t; t = readtoken(psh); psh->tokpushback++; return (t); } STATIC int readtoken(shinstance *psh) { int t; int savecheckkwd = psh->checkkwd; #ifdef DEBUG int alreadyseen = psh->tokpushback; #endif struct alias *ap; top: t = xxreadtoken(psh); if (psh->checkkwd) { /* * eat newlines */ if (psh->checkkwd == 2) { psh->checkkwd = 0; while (t == TNL) { parseheredoc(psh); t = xxreadtoken(psh); } } else psh->checkkwd = 0; /* * check for keywords and aliases */ if (t == TWORD && !psh->quoteflag) { const char *const *pp; for (pp = parsekwd; *pp; pp++) { if (**pp == *psh->wordtext && equal(*pp, psh->wordtext)) { psh->lasttoken = t = (int)(pp - parsekwd + KWDOFFSET); TRACE((psh, "keyword %s recognized\n", tokname[t])); goto out; } } if(!psh->noalias && (ap = lookupalias(psh, psh->wordtext, 1)) != NULL) { pushstring(psh, ap->val, strlen(ap->val), ap); psh->checkkwd = savecheckkwd; goto top; } } out: psh->checkkwd = (t == TNOT) ? savecheckkwd : 0; } #ifdef DEBUG if (!alreadyseen) TRACE((psh, "token %s %s\n", tokname[t], t == TWORD ? psh->wordtext : "")); else TRACE((psh, "reread token %s \"%s\"\n", tokname[t], t == TWORD ? psh->wordtext : "")); #endif return (t); } /* * Read the next input token. * If the token is a word, we set psh->backquotelist to the list of cmds in * backquotes. We set psh->quoteflag to true if any part of the word was * quoted. * If the token is TREDIR, then we set psh->redirnode to a structure containing * the redirection. * In all cases, the variable psh->startlinno is set to the number of the line * on which the token starts. * * [Change comment: here documents and internal procedures] * [Readtoken shouldn't have any arguments. Perhaps we should make the * word parsing code into a separate routine. In this case, readtoken * doesn't need to have any internal procedures, but parseword does. * We could also make parseoperator in essence the main routine, and * have parseword (readtoken1?) handle both words and redirection.] */ #define RETURN(token) return psh->lasttoken = token STATIC int xxreadtoken(shinstance *psh) { int c; if (psh->tokpushback) { psh->tokpushback = 0; return psh->lasttoken; } if (psh->needprompt) { setprompt(psh, 2); psh->needprompt = 0; } psh->startlinno = psh->plinno; for (;;) { /* until token or start of word found */ c = pgetc_macro(psh); if (c == ' ' || c == '\t') continue; /* quick check for white space first */ switch (c) { case ' ': case '\t': continue; case '#': while ((c = pgetc(psh)) != '\n' && c != PEOF); pungetc(psh); continue; case '\\': if (pgetc(psh) == '\n') { psh->startlinno = ++psh->plinno; if (psh->doprompt) setprompt(psh, 2); else setprompt(psh, 0); continue; } pungetc(psh); goto breakloop; case '\n': psh->plinno++; psh->needprompt = psh->doprompt; RETURN(TNL); case PEOF: RETURN(TEOF); case '&': if (pgetc(psh) == '&') RETURN(TAND); pungetc(psh); RETURN(TBACKGND); case '|': if (pgetc(psh) == '|') RETURN(TOR); pungetc(psh); RETURN(TPIPE); case ';': if (pgetc(psh) == ';') RETURN(TENDCASE); pungetc(psh); RETURN(TSEMI); case '(': RETURN(TLP); case ')': RETURN(TRP); default: goto breakloop; } } breakloop: return readtoken1(psh, c, BASESYNTAX, (char *)NULL, 0); #undef RETURN } /* * If eofmark is NULL, read a word or a redirection symbol. If eofmark * is not NULL, read a here document. In the latter case, eofmark is the * word which marks the end of the document and striptabs is true if * leading tabs should be stripped from the document. The argument firstc * is the first character of the input token or document. * * Because C does not have internal subroutines, I have simulated them * using goto's to implement the subroutine linkage. The following macros * will run code that appears at the end of readtoken1. */ #define CHECKEND() {goto checkend; checkend_return:;} #define PARSEREDIR() {goto parseredir; parseredir_return:;} #define PARSESUB() {goto parsesub; parsesub_return:;} #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} #define PARSEARITH() {goto parsearith; parsearith_return:;} /* * Keep track of nested doublequotes in dblquote and doublequotep. * We use dblquote for the first 32 levels, and we expand to a malloc'ed * region for levels above that. Usually we never need to malloc. * This code assumes that an int is 32 bits. We don't use uint32_t, * because the rest of the code does not. */ #define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \ (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32)))) #define SETDBLQUOTE() \ if (varnest < 32) \ dblquote |= (1 << varnest); \ else \ dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32)) #define CLRDBLQUOTE() \ if (varnest < 32) \ dblquote &= ~(1 << varnest); \ else \ dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32)) STATIC int readtoken1(shinstance *psh, int firstc, char const *syntax, char *eofmark, int striptabs) { int c = firstc; char *out; int len; char line[EOFMARKLEN + 1]; struct nodelist *bqlist; int quotef; int *dblquotep = NULL; size_t maxnest = 32; int dblquote; int varnest; /* levels of variables expansion */ int arinest; /* levels of arithmetic expansion */ int parenlevel; /* levels of parens in arithmetic */ int oldstyle; char const *prevsyntax; /* syntax before arithmetic */ #if __GNUC__ /* Avoid longjmp clobbering */ (void) &maxnest; (void) &dblquotep; (void) &out; (void) "ef; (void) &dblquote; (void) &varnest; (void) &arinest; (void) &parenlevel; (void) &oldstyle; (void) &prevsyntax; (void) &syntax; #endif psh->startlinno = psh->plinno; dblquote = 0; varnest = 0; if (syntax == DQSYNTAX) { SETDBLQUOTE(); } quotef = 0; bqlist = NULL; arinest = 0; parenlevel = 0; STARTSTACKSTR(psh, out); loop: { /* for each line, until end of word */ #if ATTY if (c == '\034' && psh->doprompt && attyset() && ! equal(termval(), "emacs")) { attyline(); if (syntax == BASESYNTAX) return readtoken(psh); c = pgetc(psh); goto loop; } #endif CHECKEND(); /* set c to PEOF if at end of here document */ for (;;) { /* until end of line or end of word */ CHECKSTRSPACE(psh, 4, out); /* permit 4 calls to USTPUTC */ switch(syntax[c]) { case CNL: /* '\n' */ if (syntax == BASESYNTAX) goto endword; /* exit outer loop */ USTPUTC(psh, c, out); psh->plinno++; if (psh->doprompt) setprompt(psh, 2); else setprompt(psh, 0); c = pgetc(psh); goto loop; /* continue outer loop */ case CWORD: USTPUTC(psh, c, out); break; case CCTL: if (eofmark == NULL || ISDBLQUOTE()) USTPUTC(psh, CTLESC, out); USTPUTC(psh, c, out); break; case CBACK: /* backslash */ c = pgetc(psh); if (c == PEOF) { USTPUTC(psh, '\\', out); pungetc(psh); break; } if (c == '\n') { if (psh->doprompt) setprompt(psh, 2); else setprompt(psh, 0); break; } quotef = 1; if (ISDBLQUOTE() && c != '\\' && c != '`' && c != '$' && (c != '"' || eofmark != NULL)) USTPUTC(psh, '\\', out); if (SQSYNTAX[c] == CCTL) USTPUTC(psh, CTLESC, out); else if (eofmark == NULL) { USTPUTC(psh, CTLQUOTEMARK, out); USTPUTC(psh, c, out); if (varnest != 0) USTPUTC(psh, CTLQUOTEEND, out); break; } USTPUTC(psh, c, out); break; case CSQUOTE: if (syntax != SQSYNTAX) { if (eofmark == NULL) USTPUTC(psh, CTLQUOTEMARK, out); quotef = 1; syntax = SQSYNTAX; break; } if (eofmark != NULL && arinest == 0 && varnest == 0) { /* Ignore inside quoted here document */ USTPUTC(psh, c, out); break; } /* End of single quotes... */ if (arinest) syntax = ARISYNTAX; else { syntax = BASESYNTAX; if (varnest != 0) USTPUTC(psh, CTLQUOTEEND, out); } break; case CDQUOTE: if (eofmark != NULL && arinest == 0 && varnest == 0) { /* Ignore inside here document */ USTPUTC(psh, c, out); break; } quotef = 1; if (arinest) { if (ISDBLQUOTE()) { syntax = ARISYNTAX; CLRDBLQUOTE(); } else { syntax = DQSYNTAX; SETDBLQUOTE(); USTPUTC(psh, CTLQUOTEMARK, out); } break; } if (eofmark != NULL) break; if (ISDBLQUOTE()) { if (varnest != 0) USTPUTC(psh, CTLQUOTEEND, out); syntax = BASESYNTAX; CLRDBLQUOTE(); } else { syntax = DQSYNTAX; SETDBLQUOTE(); USTPUTC(psh, CTLQUOTEMARK, out); } break; case CVAR: /* '$' */ PARSESUB(); /* parse substitution */ break; case CENDVAR: /* CLOSEBRACE */ if (varnest > 0 && !ISDBLQUOTE()) { varnest--; USTPUTC(psh, CTLENDVAR, out); } else { USTPUTC(psh, c, out); } break; case CLP: /* '(' in arithmetic */ parenlevel++; USTPUTC(psh, c, out); break; case CRP: /* ')' in arithmetic */ if (parenlevel > 0) { USTPUTC(psh, c, out); --parenlevel; } else { if (pgetc(psh) == ')') { if (--arinest == 0) { USTPUTC(psh, CTLENDARI, out); syntax = prevsyntax; if (syntax == DQSYNTAX) SETDBLQUOTE(); else CLRDBLQUOTE(); } else USTPUTC(psh, ')', out); } else { /* * unbalanced parens * (don't 2nd guess - no error) */ pungetc(psh); USTPUTC(psh, ')', out); } } break; case CBQUOTE: /* '`' */ PARSEBACKQOLD(); break; case CSHEOF: goto endword; /* exit outer loop */ default: if (varnest == 0) goto endword; /* exit outer loop */ USTPUTC(psh, c, out); } c = pgetc_macro(psh); } } endword: if (syntax == ARISYNTAX) synerror(psh, "Missing '))'"); if (syntax != BASESYNTAX && ! psh->parsebackquote && eofmark == NULL) synerror(psh, "Unterminated quoted string"); if (varnest != 0) { psh->startlinno = psh->plinno; /* { */ synerror(psh, "Missing '}'"); } USTPUTC(psh, '\0', out); len = (int)(out - stackblock(psh)); out = stackblock(psh); if (eofmark == NULL) { if ((c == '>' || c == '<') && quotef == 0 && len <= 2 && (*out == '\0' || is_digit(*out))) { PARSEREDIR(); return psh->lasttoken = TREDIR; } else { pungetc(psh); } } psh->quoteflag = quotef; psh->backquotelist = bqlist; grabstackblock(psh, len); psh->wordtext = out; if (dblquotep != NULL) ckfree(psh, dblquotep); return psh->lasttoken = TWORD; /* end of readtoken routine */ /* * Check to see whether we are at the end of the here document. When this * is called, c is set to the first character of the next input line. If * we are at the end of the here document, this routine sets the c to PEOF. */ checkend: { if (eofmark) { if (striptabs) { while (c == '\t') c = pgetc(psh); } if (c == *eofmark) { if (pfgets(psh, line, sizeof line) != NULL) { char *p, *q; p = line; for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); if (*p == '\n' && *q == '\0') { c = PEOF; psh->plinno++; psh->needprompt = psh->doprompt; } else { pushstring(psh, line, strlen(line), NULL); } } } } goto checkend_return; } /* * Parse a redirection operator. The variable "out" points to a string * specifying the fd to be redirected. The variable "c" contains the * first character of the redirection operator. */ parseredir: { char fd = *out; union node *np; np = (union node *)stalloc(psh, sizeof (struct nfile)); if (c == '>') { np->nfile.fd = 1; c = pgetc(psh); if (c == '>') np->type = NAPPEND; else if (c == '|') np->type = NCLOBBER; else if (c == '&') np->type = NTOFD; else { np->type = NTO; pungetc(psh); } } else { /* c == '<' */ np->nfile.fd = 0; switch (c = pgetc(psh)) { case '<': if (sizeof (struct nfile) != sizeof (struct nhere)) { np = (union node *)stalloc(psh, sizeof (struct nhere)); np->nfile.fd = 0; } np->type = NHERE; psh->heredoc = (struct heredoc *)stalloc(psh, sizeof (struct heredoc)); psh->heredoc->here = np; if ((c = pgetc(psh)) == '-') { psh->heredoc->striptabs = 1; } else { psh->heredoc->striptabs = 0; pungetc(psh); } break; case '&': np->type = NFROMFD; break; case '>': np->type = NFROMTO; break; default: np->type = NFROM; pungetc(psh); break; } } if (fd != '\0') np->nfile.fd = digit_val(fd); psh->redirnode = np; goto parseredir_return; } /* * Parse a substitution. At this point, we have read the dollar sign * and nothing else. */ parsesub: { int subtype; int typeloc; int flags; char *p; static const char types[] = "}-+?="; c = pgetc(psh); if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) { USTPUTC(psh, '$', out); pungetc(psh); } else if (c == '(') { /* $(command) or $((arith)) */ if (pgetc(psh) == '(') { PARSEARITH(); } else { pungetc(psh); PARSEBACKQNEW(); } } else { USTPUTC(psh, CTLVAR, out); typeloc = (int)(out - stackblock(psh)); USTPUTC(psh, VSNORMAL, out); subtype = VSNORMAL; if (c == OPENBRACE) { c = pgetc(psh); if (c == '#') { if ((c = pgetc(psh)) == CLOSEBRACE) c = '#'; else subtype = VSLENGTH; } else subtype = 0; } if (is_name(c)) { do { STPUTC(psh, c, out); c = pgetc(psh); } while (is_in_name(c)); } else if (is_digit(c)) { do { USTPUTC(psh, c, out); c = pgetc(psh); } while (is_digit(c)); } else if (is_special(c)) { USTPUTC(psh, c, out); c = pgetc(psh); } else badsub: synerror(psh, "Bad substitution"); STPUTC(psh, '=', out); flags = 0; if (subtype == 0) { switch (c) { case ':': flags = VSNUL; c = pgetc(psh); /*FALLTHROUGH*/ default: p = strchr(types, c); if (p == NULL) goto badsub; subtype = (int)(p - types + VSNORMAL); break; case '%': case '#': { int cc = c; subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT; c = pgetc(psh); if (c == cc) subtype++; else pungetc(psh); break; } } } else { pungetc(psh); } if (ISDBLQUOTE() || arinest) flags |= VSQUOTE; *(stackblock(psh) + typeloc) = subtype | flags; if (subtype != VSNORMAL) { varnest++; if (varnest >= (int)maxnest) { dblquotep = ckrealloc(psh, dblquotep, maxnest / 8); dblquotep[(maxnest / 32) - 1] = 0; maxnest += 32; } } } goto parsesub_return; } /* * Called to parse command substitutions. Newstyle is set if the command * is enclosed inside $(...); nlpp is a pointer to the head of the linked * list of commands (passed by reference), and savelen is the number of * characters on the top of the stack which must be preserved. */ parsebackq: { struct nodelist **nlpp; int savepbq; union node *n; char *volatile str; struct jmploc jmploc; struct jmploc *volatile savehandler; int savelen; int saveprompt; #ifdef __GNUC__ (void) &saveprompt; #endif savepbq = psh->parsebackquote; if (setjmp(jmploc.loc)) { if (str) ckfree(psh, str); psh->parsebackquote = 0; psh->handler = savehandler; longjmp(psh->handler->loc, 1); } INTOFF; str = NULL; savelen = (int)(out - stackblock(psh)); if (savelen > 0) { str = ckmalloc(psh, savelen); memcpy(str, stackblock(psh), savelen); } savehandler = psh->handler; psh->handler = &jmploc; INTON; if (oldstyle) { /* We must read until the closing backquote, giving special treatment to some slashes, and then push the string and reread it as input, interpreting it normally. */ char *pout; int pc; int psavelen; char *pstr; STARTSTACKSTR(psh, pout); for (;;) { if (psh->needprompt) { setprompt(psh, 2); psh->needprompt = 0; } switch (pc = pgetc(psh)) { case '`': goto done; case '\\': if ((pc = pgetc(psh)) == '\n') { psh->plinno++; if (psh->doprompt) setprompt(psh, 2); else setprompt(psh, 0); /* * If eating a newline, avoid putting * the newline into the new character * stream (via the STPUTC after the * switch). */ continue; } if (pc != '\\' && pc != '`' && pc != '$' && (!ISDBLQUOTE() || pc != '"')) STPUTC(psh, '\\', pout); break; case '\n': psh->plinno++; psh->needprompt = psh->doprompt; break; case PEOF: psh->startlinno = psh->plinno; synerror(psh, "EOF in backquote substitution"); break; default: break; } STPUTC(psh, pc, pout); } done: STPUTC(psh, '\0', pout); psavelen = (int)(pout - stackblock(psh)); if (psavelen > 0) { pstr = grabstackstr(psh, pout); setinputstring(psh, pstr, 1); } } nlpp = &bqlist; while (*nlpp) nlpp = &(*nlpp)->next; *nlpp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist)); (*nlpp)->next = NULL; psh->parsebackquote = oldstyle; if (oldstyle) { saveprompt = psh->doprompt; psh->doprompt = 0; } n = list(psh, 0); if (oldstyle) psh->doprompt = saveprompt; else { if (readtoken(psh) != TRP) synexpect(psh, TRP); } (*nlpp)->n = n; if (oldstyle) { /* * Start reading from old file again, ignoring any pushed back * tokens left from the backquote parsing */ popfile(psh); psh->tokpushback = 0; } while (stackblocksize(psh) <= savelen) growstackblock(psh); STARTSTACKSTR(psh, out); if (str) { memcpy(out, str, savelen); STADJUST(psh, savelen, out); INTOFF; ckfree(psh, str); str = NULL; INTON; } psh->parsebackquote = savepbq; psh->handler = savehandler; if (arinest || ISDBLQUOTE()) USTPUTC(psh, CTLBACKQ | CTLQUOTE, out); else USTPUTC(psh, CTLBACKQ, out); if (oldstyle) goto parsebackq_oldreturn; else goto parsebackq_newreturn; } /* * Parse an arithmetic expansion (indicate start of one and set state) */ parsearith: { if (++arinest == 1) { prevsyntax = syntax; syntax = ARISYNTAX; USTPUTC(psh, CTLARI, out); if (ISDBLQUOTE()) USTPUTC(psh, '"',out); else USTPUTC(psh, ' ',out); } else { /* * we collapse embedded arithmetic expansion to * parenthesis, which should be equivalent */ USTPUTC(psh, '(', out); } goto parsearith_return; } } /* end of readtoken */ #ifdef mkinit RESET { psh->tokpushback = 0; psh->checkkwd = 0; } #endif /* * Returns true if the text contains nothing to expand (no dollar signs * or backquotes). */ STATIC int noexpand(shinstance *psh, char *text) { char *p; char c; p = text; while ((c = *p++) != '\0') { if (c == CTLQUOTEMARK) continue; if (c == CTLESC) p++; else if (BASESYNTAX[(int)c] == CCTL) return 0; } return 1; } /* * Return true if the argument is a legal variable name (a letter or * underscore followed by zero or more letters, underscores, and digits). */ int goodname(const char *name) { const char *p; p = name; if (! is_name(*p)) return 0; while (*++p) { if (! is_in_name(*p)) return 0; } return 1; } /* * Called when an unexpected token is read during the parse. The argument * is the token that is expected, or -1 if more than one type of token can * occur at this point. */ SH_NORETURN_1 STATIC void synexpect(shinstance *psh, int token) { char msg[64]; if (token >= 0) { fmtstr(msg, 64, "%s unexpected (expecting %s)", tokname[psh->lasttoken], tokname[token]); } else { fmtstr(msg, 64, "%s unexpected", tokname[psh->lasttoken]); } synerror(psh, msg); /* NOTREACHED */ } SH_NORETURN_1 STATIC void synerror(shinstance *psh, const char *msg) { if (psh->commandname) { TRACE((psh, "synerror: %s: %d: Syntax error: %s", psh->commandname, psh->startlinno, msg)); outfmt(&psh->errout, "%s: %d: ", psh->commandname, psh->startlinno); } else { TRACE((psh, "synerror: Syntax error: %s\n", msg)); } outfmt(&psh->errout, "Syntax error: %s\n", msg); error(psh, (char *)NULL); /* NOTREACHED */ } STATIC const char * my_basename(const char *argv0, unsigned *lenp) { const char *tmp; /* skip the path */ for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:")) argv0 = tmp + 1; if (lenp) { /* find the end, ignoring extenions */ tmp = strrchr(argv0, '.'); if (!tmp) tmp = strchr(argv0, '\0'); *lenp = (unsigned)(tmp - argv0); } return argv0; } STATIC void setprompt(shinstance *psh, int which) { psh->whichprompt = which; #ifndef SMALL if (!el) #endif { /* deal with bash prompts */ const char *prompt = getprompt(psh, NULL); if (!strchr(prompt, '\\')) { out2str(psh, prompt); } else { while (*prompt) { if (*prompt != '\\') { out2c(psh, *prompt++); } else { prompt++; switch (*prompt++) { /* simple */ case '$': out2c(psh, sh_geteuid(psh) ? '$' : '#'); break; case '\\': out2c(psh, '\\'); break; case 'a': out2c(psh, '\a'); break; case 'e': out2c(psh, 033); break; case 'n': out2c(psh, '\n'); break; case 'r': out2c(psh, '\r'); break; /* complicated */ case 's': { unsigned len; const char *arg0 = my_basename(psh->arg0, &len); outfmt(psh->out2, "%.*s", len, arg0); break; } case 'v': outfmt(psh->out2, "%d.%d", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR); break; case 'V': outfmt(psh->out2, "%d.%d.%d", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH); break; out2str(psh, getpwd(psh, 1) ? getpwd(psh, 1) : "?"); break; case 'w': case 'W': { const char *cwd = getpwd(psh, 1); const char *home = bltinlookup(psh, "HOME", 1); size_t home_len = home ? strlen(home) : 0; if (!cwd) cwd = "?"; if (!strncmp(cwd, home, home_len) && ( cwd[home_len] == '\0' || (cwd[home_len] == '/' && prompt[-1] == 'w'))) { out2c(psh, '~'); if (prompt[-1] == 'w' && cwd[home_len]) { out2str(psh, cwd + home_len); } } else if (prompt[-1] == 'w') { out2str(psh, cwd); } else { out2str(psh, my_basename(cwd, NULL)); } break; } case '0': case '1': case '2': case '3': { unsigned int ch = prompt[-1] - '0'; if (isdigit(*prompt)) { ch *= 8; ch += *prompt++ - '0'; } if (isdigit(*prompt)) { ch *= 8; ch += *prompt++ - '0'; } out2c(psh, ch); break; } /* ignore */ break; case '!': case '#': case '@': case 'A': case 'h': case 'H': case 'j': case 'l': case 't': case 'T': case 'u': case '[': if (strchr(prompt, ']')) { prompt = strchr(prompt, ']') + 1; } break; case 'D': if (*prompt == '{' && strchr(prompt, '}')) { prompt = strchr(prompt, '}') + 1; } break; } } } } } } /* * called by editline -- any expansions to the prompt * should be added here. */ const char * getprompt(shinstance *psh, void *unused) { switch (psh->whichprompt) { case 0: return ""; case 1: return ps1val(psh); case 2: return ps2val(psh); default: return ""; } } kbuild-2695/src/kash/options.h0000644000000000000000000001276612247157307015036 0ustar rootroot/* $NetBSD: options.h,v 1.18 2005/05/07 19:52:17 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)options.h 8.2 (Berkeley) 5/4/95 */ #ifndef ___options_h #define ___options_h struct shparam { int nparam; /* # of positional parameters (without $0) */ unsigned char malloc; /* if parameter list dynamically allocated */ unsigned char reset; /* if getopts has been reset */ char **p; /* parameter list */ char **optnext; /* next parameter to be processed by getopts */ char *optptr; /* used by getopts */ }; struct optent { const char *name; /* for set -o */ const char letter; /* set [+/-] and $- */ const char opt_set; /* mutually exclusive option set */ char val; /* value of flag */ }; /* Those marked [U] are required by posix, but have no effect! */ #ifdef DEBUG # define NOPTS 20 #else # define NOPTS 19 #endif #ifdef DEFINE_OPTIONS # define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0}, const struct optent ro_optlist[NOPTS + 1] = { #else # define DEF_OPTS(name, letter, opt_set) #endif #define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0) DEF_OPT( "errexit", 'e' ) /* exit on error */ #define eflag(psh) (psh)->optlist[0].val DEF_OPT( "noglob", 'f' ) /* no pathname expansion */ #define fflag(psh) (psh)->optlist[1].val DEF_OPT( "ignoreeof", 'I' ) /* do not exit on EOF */ #define Iflag(psh) (psh)->optlist[2].val DEF_OPT( "interactive",'i' ) /* interactive shell */ #define iflag(psh) (psh)->optlist[3].val DEF_OPT( "monitor", 'm' ) /* job control */ #define mflag(psh) (psh)->optlist[4].val DEF_OPT( "noexec", 'n' ) /* [U] do not exec commands */ #define nflag(psh) (psh)->optlist[5].val DEF_OPT( "stdin", 's' ) /* read from stdin */ #define sflag(psh) (psh)->optlist[6].val DEF_OPT( "xtrace", 'x' ) /* trace after expansion */ #define xflag(psh) (psh)->optlist[7].val DEF_OPT( "verbose", 'v' ) /* trace read input */ #define vflag(psh) (psh)->optlist[8].val DEF_OPTS( "vi", 'V', 'V' ) /* vi style editing */ #define Vflag(psh) (psh)->optlist[9].val DEF_OPTS( "emacs", 'E', 'V' ) /* emacs style editing */ #define Eflag(psh) (psh)->optlist[10].val DEF_OPT( "noclobber", 'C' ) /* do not overwrite files with > */ #define Cflag(psh) (psh)->optlist[11].val DEF_OPT( "allexport", 'a' ) /* export all variables */ #define aflag(psh) (psh)->optlist[12].val DEF_OPT( "notify", 'b' ) /* [U] report completion of background jobs */ #define bflag(psh) (psh)->optlist[13].val DEF_OPT( "nounset", 'u' ) /* error expansion of unset variables */ #define uflag(psh) (psh)->optlist[14].val DEF_OPT( "quietprofile", 'q' ) #define qflag(psh) (psh)->optlist[15].val DEF_OPT( "nolog", 0 ) /* [U] no functon defs in command history */ #define nolog(psh) (psh)->optlist[16].val DEF_OPT( "cdprint", 0 ) /* always print result of cd */ #define cdprint(psh) (psh)->optlist[17].val DEF_OPT( "tabcomplete", 0 ) /* causes filename expansion */ #define tabcomplete(psh) (psh)->optlist[18].val #ifdef DEBUG DEF_OPT( "debug", 0 ) /* enable debug prints */ #define debug(psh) (psh)->optlist[19].val #endif #ifdef DEFINE_OPTIONS { 0, 0, 0, 0 }, }; #else extern const struct optent ro_optlist[]; #endif #define sizeof_optlist (NOPTS * sizeof(struct optent)) /*extern char *minusc;*/ /* argument to -c option */ /*extern char *arg0;*/ /* $0 */ /*extern struct shparam shellparam;*/ /* $@ */ /*extern char **argptr;*/ /* argument list for builtin commands */ /*extern char *optionarg;*/ /* set by nextopt */ /*extern char *optptr;*/ /* used by nextopt */ void procargs(struct shinstance *, int, char **); void optschanged(struct shinstance *); void setparam(struct shinstance *, char **); void freeparam(struct shinstance *, volatile struct shparam *); int shiftcmd(struct shinstance *, int, char **); int setcmd(struct shinstance *, int, char **); int getoptscmd(struct shinstance *, int, char **); int nextopt(struct shinstance *, const char *); void getoptsreset(struct shinstance *, const char *); #endif kbuild-2695/src/kash/main.c0000644000000000000000000002601712247157307014254 0ustar rootroot/* $NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint __COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\ The Regents of the University of California. All rights reserved.\n"); #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95"; #else __RCSID("$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $"); #endif /* not lint */ #endif #include #include #include #include #include "shell.h" #include "main.h" #include "mail.h" #include "options.h" #include "output.h" #include "parser.h" #include "nodes.h" #include "expand.h" #include "eval.h" #include "jobs.h" #include "input.h" #include "trap.h" #include "var.h" #include "show.h" #include "memalloc.h" #include "error.h" #include "init.h" #include "mystring.h" #include "exec.h" #include "cd.h" #include "shinstance.h" #define PROFILE 0 /*int rootpid; int rootshell;*/ #ifdef unused_variables STATIC union node *curcmd; STATIC union node *prevcmd; #endif STATIC void read_profile(struct shinstance *, const char *); STATIC char *find_dot_file(struct shinstance *, char *); int main(int, char **, char **); SH_NORETURN_1 void shell_main(shinstance *, int, char **) SH_NORETURN_2; #ifdef _MSC_VER extern void init_syntax(void); #endif STATIC int usage(const char *argv0); STATIC int version(const char *argv0); /* * Main routine. We initialize things, parse the arguments, execute * profiles if we're a login shell, and then call cmdloop to execute * commands. The setjmp call sets up the location to jump to when an * exception occurs. When an exception occurs the variable "state" * is used to figure out how far we had gotten. */ int #if K_OS == K_OS_WINDOWS real_main(int argc, char **argv, char **envp) #else main(int argc, char **argv, char **envp) #endif { shinstance *psh; /* * Global initializations. */ setlocale(LC_ALL, ""); #ifdef _MSC_VER init_syntax(); #endif /* * Check for --version and --help. */ if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') { if (!strcmp(argv[1], "--help")) return usage(argv[0]); if (!strcmp(argv[1], "--version")) return version(argv[0]); } /* * Create the root shell instance. */ psh = sh_create_root_shell(NULL, argc, argv, envp); if (!psh) return 2; shthread_set_shell(psh); shell_main(psh, argc, psh->argptr); /* Not reached. */ return 89; } SH_NORETURN_1 void shell_main(shinstance *psh, int argc, char **argv) { struct jmploc jmploc; struct stackmark smark; volatile int state; char *shinit; state = 0; if (setjmp(jmploc.loc)) { /* * When a shell procedure is executed, we raise the * exception EXSHELLPROC to clean up before executing * the shell procedure. */ switch (psh->exception) { case EXSHELLPROC: psh->rootpid = /*getpid()*/ psh->pid; psh->rootshell = 1; psh->minusc = NULL; state = 3; break; case EXEXEC: psh->exitstatus = psh->exerrno; break; case EXERROR: psh->exitstatus = 2; break; default: break; } if (psh->exception != EXSHELLPROC) { if (state == 0 || iflag(psh) == 0 || ! psh->rootshell) exitshell(psh, psh->exitstatus); } reset(psh); if (psh->exception == EXINT #if ATTY && (! attyset(psh) || equal(termval(psh), "emacs")) #endif ) { out2c(psh, '\n'); flushout(&psh->errout); } popstackmark(psh, &smark); FORCEINTON; /* enable interrupts */ if (state == 1) goto state1; else if (state == 2) goto state2; else if (state == 3) goto state3; else goto state4; } psh->handler = &jmploc; psh->rootpid = /*getpid()*/ psh->pid; psh->rootshell = 1; #ifdef DEBUG #if DEBUG == 2 debug(psh) = 1; #endif opentrace(psh); trputs(psh, "Shell args: "); trargs(psh, argv); #endif init(psh); setstackmark(psh, &smark); procargs(psh, argc, argv); if (argv[0] && argv[0][0] == '-') { state = 1; read_profile(psh, "/etc/profile"); state1: state = 2; read_profile(psh, ".profile"); } state2: state = 3; if (sh_getuid(psh) == sh_geteuid(psh) && sh_getgid(psh) == sh_getegid(psh)) { if ((shinit = lookupvar(psh, "ENV")) != NULL && *shinit != '\0') { state = 3; read_profile(psh, shinit); } } state3: state = 4; if (sflag(psh) == 0 || psh->minusc) { static int sigs[] = { SIGINT, SIGQUIT, SIGHUP, #ifdef SIGTSTP SIGTSTP, #endif SIGPIPE }; #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) unsigned i; for (i = 0; i < SIGSSIZE; i++) setsignal(psh, sigs[i], 0); } if (psh->minusc) evalstring(psh, psh->minusc, 0); if (sflag(psh) || psh->minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */ cmdloop(psh, 1); } exitshell(psh, psh->exitstatus); /* NOTREACHED */ } /* * Read and execute commands. "Top" is nonzero for the top level command * loop; it turns on prompting if the shell is interactive. */ void cmdloop(struct shinstance *psh, int top) { union node *n; struct stackmark smark; int inter; int numeof = 0; TRACE((psh, "cmdloop(%d) called\n", top)); setstackmark(psh, &smark); for (;;) { if (psh->pendingsigs) dotrap(psh); inter = 0; if (iflag(psh) && top) { inter = 1; showjobs(psh, psh->out2, SHOW_CHANGED); chkmail(psh, 0); flushout(&psh->errout); } n = parsecmd(psh, inter); /* showtree(n); DEBUG */ if (n == NEOF) { if (!top || numeof >= 50) break; if (!stoppedjobs(psh)) { if (!Iflag(psh)) break; out2str(psh, "\nUse \"exit\" to leave shell.\n"); } numeof++; } else if (n != NULL && nflag(psh) == 0) { psh->job_warning = (psh->job_warning == 2) ? 1 : 0; numeof = 0; evaltree(psh, n, 0); } popstackmark(psh, &smark); setstackmark(psh, &smark); if (psh->evalskip == SKIPFILE) { psh->evalskip = 0; break; } } popstackmark(psh, &smark); } /* * Read /etc/profile or .profile. Return on error. */ STATIC void read_profile(struct shinstance *psh, const char *name) { int fd; int xflag_set = 0; int vflag_set = 0; INTOFF; if ((fd = shfile_open(&psh->fdtab, name, O_RDONLY, 0)) >= 0) setinputfd(psh, fd, 1); INTON; if (fd < 0) return; /* -q turns off -x and -v just when executing init files */ if (qflag(psh)) { if (xflag(psh)) xflag(psh) = 0, xflag_set = 1; if (vflag(psh)) vflag(psh) = 0, vflag_set = 1; } cmdloop(psh, 0); if (qflag(psh)) { if (xflag_set) xflag(psh) = 1; if (vflag_set) vflag(psh) = 1; } popfile(psh); } /* * Read a file containing shell functions. */ void readcmdfile(struct shinstance *psh, char *name) { int fd; INTOFF; if ((fd = shfile_open(&psh->fdtab, name, O_RDONLY, 0)) >= 0) setinputfd(psh, fd, 1); else error(psh, "Can't open %s", name); INTON; cmdloop(psh, 0); popfile(psh); } /* * Take commands from a file. To be compatible we should do a path * search for the file, which is necessary to find sub-commands. */ STATIC char * find_dot_file(struct shinstance *psh, char *basename) { char *fullname; const char *path = pathval(psh); struct stat statb; /* don't try this for absolute or relative paths */ if (strchr(basename, '/')) return basename; while ((fullname = padvance(psh, &path, basename)) != NULL) { if ((shfile_stat(&psh->fdtab, fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { /* * Don't bother freeing here, since it will * be freed by the caller. */ return fullname; } stunalloc(psh, fullname); } /* not found in the PATH */ error(psh, "%s: not found", basename); /* NOTREACHED */ return NULL; } int dotcmd(struct shinstance *psh, int argc, char **argv) { psh->exitstatus = 0; if (argc >= 2) { /* That's what SVR2 does */ char *fullname; struct stackmark smark; setstackmark(psh, &smark); fullname = find_dot_file(psh, argv[1]); setinputfile(psh, fullname, 1); psh->commandname = fullname; cmdloop(psh, 0); popfile(psh); popstackmark(psh, &smark); } return psh->exitstatus; } int exitcmd(struct shinstance *psh, int argc, char **argv) { if (stoppedjobs(psh)) return 0; if (argc > 1) psh->exitstatus = number(psh, argv[1]); exitshell(psh, psh->exitstatus); /* NOTREACHED */ return 1; } STATIC const char * strip_argv0(const char *argv0, unsigned *lenp) { const char *tmp; /* skip the path */ for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:")) argv0 = tmp + 1; /* find the end, ignoring extenions */ tmp = strrchr(argv0, '.'); if (!tmp) tmp = strchr(argv0, '\0'); *lenp = (unsigned)(tmp - argv0); return argv0; } STATIC int usage(const char *argv0) { unsigned len; argv0 = strip_argv0(argv0, &len); fprintf(stdout, "usage: %.*s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n" " [+o option_name] [command_file [argument ...]]\n" " or: %.*s -c [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n" " [+o option_name] command_string [command_name [argument ...]]\n" " or: %.*s -s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n" " [+o option_name] [argument ...]\n" " or: %.*s --help\n" " or: %.*s --version\n", len, argv0, len, argv0, len, argv0, len, argv0, len, argv0); return 0; } STATIC int version(const char *argv0) { unsigned len; strip_argv0(argv0, &len); fprintf(stdout, "%.*s - kBuild version %d.%d.%d (r%u)\n", len, argv0, KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; } /* * Local Variables: * c-file-style: bsd * End: */ kbuild-2695/src/kash/input.c0000644000000000000000000003175012247157307014467 0ustar rootroot/* $NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; #else __RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $"); #endif /* not lint */ #endif #include /* defines BUFSIZ */ #include #include #include /* * This file implements the input routines used by the parser. */ #include "shell.h" #include "redir.h" #include "syntax.h" #include "input.h" #include "output.h" #include "options.h" #include "memalloc.h" #include "error.h" #include "alias.h" #include "parser.h" #include "myhistedit.h" #include "shinstance.h" #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ //MKINIT //struct strpush { // struct strpush *prev; /* preceding string on stack */ // char *prevstring; // int prevnleft; // int prevlleft; // struct alias *ap; /* if push was associated with an alias */ //}; // ///* // * The parsefile structure pointed to by the global variable parsefile // * contains information about the current file being read. // */ // //MKINIT //struct parsefile { // struct parsefile *prev; /* preceding file on stack */ // int linno; /* current line */ // int fd; /* file descriptor (or -1 if string) */ // int nleft; /* number of chars left in this line */ // int lleft; /* number of chars left in this buffer */ // char *nextc; /* next char in buffer */ // char *buf; /* input buffer */ // struct strpush *strpush; /* for pushing strings at this level */ // struct strpush basestrpush; /* so pushing one is fast */ //}; // // //int plinno = 1; /* input line number */ //int parsenleft; /* copy of parsefile->nleft */ //MKINIT int parselleft; /* copy of parsefile->lleft */ //char *parsenextc; /* copy of parsefile->nextc */ //MKINIT struct parsefile basepf; /* top level input file */ //MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */ //struct parsefile *parsefile = &basepf; /* current input file */ //int init_editline = 0; /* editline library initialized? */ //int whichprompt; /* 1 == PS1, 2 == PS2 */ // //#ifndef SMALL //EditLine *el; /* cookie for editline package */ //#endif STATIC void pushfile(shinstance *psh); static int preadfd(shinstance *psh); #ifdef mkinit INCLUDE INCLUDE "input.h" INCLUDE "error.h" INIT { psh->basepf.nextc = psh->basepf.buf = psh->basebuf; } RESET { if (psh->exception != EXSHELLPROC) psh->parselleft = psh->parsenleft = 0; /* clear input buffer */ popallfiles(psh); } SHELLPROC { popallfiles(psh); } #endif /* * Read a line from the script. */ char * pfgets(shinstance *psh, char *line, int len) { char *p = line; int nleft = len; int c; while (--nleft > 0) { c = pgetc_macro(psh); if (c == PEOF) { if (p == line) return NULL; break; } *p++ = c; if (c == '\n') break; } *p = '\0'; return line; } /* * Read a character from the script, returning PEOF on end of file. * Nul characters in the input are silently discarded. */ int pgetc(shinstance *psh) { return pgetc_macro(psh); } static int preadfd_inner(shinstance *psh, char *buf, int bufsize) { int nr; retry: #ifndef SMALL if (psh->parsefile->fd == 0 && psh->el) { static const char *rl_cp; static int el_len; if (rl_cp == NULL) rl_cp = el_gets(psh->el, &el_len); if (rl_cp == NULL) nr = 0; else { nr = el_len; if (nr > bufsize) nr = bufsize; memcpy(buf, rl_cp, nr); if (nr != el_len) { el_len -= nr; rl_cp += nr; } else rl_cp = 0; } } else #endif nr = shfile_read(&psh->fdtab, psh->parsefile->fd, buf, bufsize); if (nr <= 0) { if (nr < 0) { if (errno == EINTR) goto retry; if (psh->parsefile->fd == 0 && errno == EWOULDBLOCK) { int flags = shfile_fcntl(&psh->fdtab, 0, F_GETFL, 0); if (flags >= 0 && flags & O_NONBLOCK) { flags &=~ O_NONBLOCK; if (shfile_fcntl(&psh->fdtab, 0, F_SETFL, flags) >= 0) { out2str(psh, "sh: turning off NDELAY mode\n"); goto retry; } } } } nr = -1; } return nr; } static int preadfd(shinstance *psh) { int nr; char *buf = psh->parsefile->buf; psh->parsenextc = buf; #ifdef SH_DEAL_WITH_CRLF /* Convert CRLF to LF. */ nr = preadfd_inner(psh, buf, BUFSIZ - 9); if (nr > 0) { char *cr = memchr(buf, '\r', nr); while (cr) { size_t left = nr - (cr - buf); if (left > 1 && cr[1] == '\n') { left--; nr--; memmove(cr, cr + 1, left); cr = memchr(cr, '\r', left); } else if (left == 1) { /* Special case: \r at buffer end. Read one more char. Screw \r\r\n sequences. */ int nr2 = preadfd_inner(psh, cr + 1, 1); if (nr2 != 1) break; if (cr[1] == '\n') { *cr = '\n'; } else { nr++; } break; } else { cr = memchr(cr + 1, '\r', left); } } } #else nr = preadfd_inner(psh, buf, BUFSIZ - 8); #endif return nr; } /* * Refill the input buffer and return the next input character: * * 1) If a string was pushed back on the input, pop it; * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading * from a string so we can't refill the buffer, return EOF. * 3) If the is more stuff in this buffer, use it else call read to fill it. * 4) Process input up to the next newline, deleting nul characters. */ int preadbuffer(shinstance *psh) { char *p, *q; int more; int something; char savec; if (psh->parsefile->strpush) { popstring(psh); if (--psh->parsenleft >= 0) return (*psh->parsenextc++); } if (psh->parsenleft == EOF_NLEFT || psh->parsefile->buf == NULL) return PEOF; flushout(&psh->output); flushout(&psh->errout); again: if (psh->parselleft <= 0) { if ((psh->parselleft = preadfd(psh)) == -1) { psh->parselleft = psh->parsenleft = EOF_NLEFT; return PEOF; } } q = p = psh->parsenextc; /* delete nul characters */ something = 0; for (more = 1; more;) { switch (*p) { case '\0': p++; /* Skip nul */ goto check; case '\t': case ' ': break; case '\n': psh->parsenleft = (int)(q - psh->parsenextc); more = 0; /* Stop processing here */ break; default: something = 1; break; } *q++ = *p++; check: if (--psh->parselleft <= 0) { psh->parsenleft = (int)(q - psh->parsenextc - 1); if (psh->parsenleft < 0) goto again; *q = '\0'; more = 0; } } savec = *q; *q = '\0'; #ifndef SMALL if (psh->parsefile->fd == 0 && hist && something) { HistEvent he; INTOFF; history(hist, &he, psh->whichprompt == 1? H_ENTER : H_APPEND, psh->parsenextc); INTON; } #endif if (vflag(psh)) { out2str(psh, psh->parsenextc); flushout(psh->out2); } *q = savec; return *psh->parsenextc++; } /* * Undo the last call to pgetc. Only one character may be pushed back. * PEOF may be pushed back. */ void pungetc(shinstance *psh) { psh->parsenleft++; psh->parsenextc--; } /* * Push a string back onto the input at this current parsefile level. * We handle aliases this way. */ void pushstring(shinstance *psh, char *s, size_t len, void *ap) { struct strpush *sp; INTOFF; /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ if (psh->parsefile->strpush) { sp = ckmalloc(psh, sizeof (struct strpush)); sp->prev = psh->parsefile->strpush; psh->parsefile->strpush = sp; } else sp = psh->parsefile->strpush = &(psh->parsefile->basestrpush); sp->prevstring = psh->parsenextc; sp->prevnleft = psh->parsenleft; sp->prevlleft = psh->parselleft; sp->ap = (struct alias *)ap; if (ap) ((struct alias *)ap)->flag |= ALIASINUSE; psh->parsenextc = s; psh->parsenleft = (int)len; INTON; } void popstring(shinstance *psh) { struct strpush *sp = psh->parsefile->strpush; INTOFF; psh->parsenextc = sp->prevstring; psh->parsenleft = sp->prevnleft; psh->parselleft = sp->prevlleft; /*dprintf("*** calling popstring: restoring to '%s'\n", psh->parsenextc);*/ if (sp->ap) sp->ap->flag &= ~ALIASINUSE; psh->parsefile->strpush = sp->prev; if (sp != &(psh->parsefile->basestrpush)) ckfree(psh, sp); INTON; } /* * Set the input to take input from a file. If push is set, push the * old input onto the stack first. */ void setinputfile(shinstance *psh, const char *fname, int push) { int fd; int fd2; INTOFF; /** @todo shfile fixme */ if ((fd = shfile_open(&psh->fdtab, fname, O_RDONLY, 0)) < 0) error(psh, "Can't open %s", fname); if (fd < 10) { fd2 = movefd_above(psh, fd, 10); if (fd2 < 0) error(psh, "Out of file descriptors"); fd = fd2; } setinputfd(psh, fd, push); INTON; } /* * Like setinputfile, but takes an open file descriptor. Call this with * interrupts off. */ void setinputfd(shinstance *psh, int fd, int push) { (void) shfile_cloexec(&psh->fdtab, fd, 1 /* close it */); if (push) { pushfile(psh); psh->parsefile->buf = ckmalloc(psh, BUFSIZ); } if (psh->parsefile->fd > 0) shfile_close(&psh->fdtab, psh->parsefile->fd); psh->parsefile->fd = fd; if (psh->parsefile->buf == NULL) psh->parsefile->buf = ckmalloc(psh, BUFSIZ); psh->parselleft = psh->parsenleft = 0; psh->plinno = 1; } /* * Like setinputfile, but takes input from a string. */ void setinputstring(shinstance *psh, char *string, int push) { INTOFF; if (push) pushfile(psh); psh->parsenextc = string; psh->parselleft = psh->parsenleft = (int)strlen(string); psh->parsefile->buf = NULL; psh->plinno = 1; INTON; } /* * To handle the "." command, a stack of input files is used. Pushfile * adds a new entry to the stack and popfile restores the previous level. */ STATIC void pushfile(shinstance *psh) { struct parsefile *pf; psh->parsefile->nleft = psh->parsenleft; psh->parsefile->lleft = psh->parselleft; psh->parsefile->nextc = psh->parsenextc; psh->parsefile->linno = psh->plinno; pf = (struct parsefile *)ckmalloc(psh, sizeof (struct parsefile)); pf->prev = psh->parsefile; pf->fd = -1; pf->strpush = NULL; pf->basestrpush.prev = NULL; psh->parsefile = pf; } void popfile(shinstance *psh) { struct parsefile *pf = psh->parsefile; INTOFF; if (pf->fd >= 0) shfile_close(&psh->fdtab, pf->fd); if (pf->buf) ckfree(psh, pf->buf); while (pf->strpush) popstring(psh); psh->parsefile = pf->prev; ckfree(psh, pf); psh->parsenleft = psh->parsefile->nleft; psh->parselleft = psh->parsefile->lleft; psh->parsenextc = psh->parsefile->nextc; psh->plinno = psh->parsefile->linno; INTON; } /* * Return to top level. */ void popallfiles(shinstance *psh) { while (psh->parsefile != &psh->basepf) popfile(psh); } /* * Close the file(s) that the shell is reading commands from. Called * after a fork is done. * * Takes one arg, vfork, which tells it to not modify its global vars * as it is still running in the parent. * * This code is (probably) unnecessary as the 'close on exec' flag is * set and should be enough. In the vfork case it is definitely wrong * to close the fds as another fork() may be done later to feed data * from a 'here' document into a pipe and we don't want to close the * pipe! */ void closescript(shinstance *psh, int vforked) { if (vforked) return; popallfiles(psh); if (psh->parsefile->fd > 0) { shfile_close(&psh->fdtab, psh->parsefile->fd); psh->parsefile->fd = 0; } } kbuild-2695/src/kash/shfile.h0000644000000000000000000001267412247157307014613 0ustar rootroot/* $Id: shfile.h 2546 2011-10-01 19:49:54Z bird $ */ /** @file * File management. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef ___shfile_h #define ___shfile_h #include "shtypes.h" #include "shthread.h" #include #include #ifdef _MSC_VER # define _PATH_DEVNULL "nul" # define _PATH_DEFPATH "." #else # if !defined(__sun__) # include # endif # ifndef _PATH_DEVNULL # define _PATH_DEVNULL "/dev/null" # endif # ifndef _PATH_DEFPATH # define _PATH_DEFPATH "/bin:/usr/bin:/sbin:/usr/sbin" # endif #endif #ifndef _MSC_VER # include # include # ifndef O_BINARY # define O_BINARY 0 # endif # ifndef O_TEXT # define O_TEXT 0 # endif #else # include # include # define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) # define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) # define S_ISLNK(m) 0 # define S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC) # define S_IXUSR _S_IEXEC # define S_IWUSR _S_IWRITE # define S_IRUSR _S_IREAD # define S_IRWXG 0000070 # define S_IRGRP 0000040 # define S_IWGRP 0000020 # define S_IXGRP 0000010 # define S_IRWXO 0000007 # define S_IROTH 0000004 # define S_IWOTH 0000002 # define S_IXOTH 0000001 # define S_ISUID 0004000 # define S_ISGID 0002000 # define ALLPERMS 0000777 # define F_DUPFD 0 # define F_GETFD 1 # define F_SETFD 2 # define F_GETFL 3 # define F_SETFL 4 # define FD_CLOEXEC 1 # define F_OK 0 # define X_OK 1 # define W_OK 2 # define R_OK 4 # define O_NONBLOCK 0 /** @todo */ #endif /** * One file. */ typedef struct shfile { int fd; /**< The shell file descriptor number. */ unsigned oflags; /**< Open flags. */ unsigned shflags; /**< The shell file descriptor flags. */ intptr_t native; /**< The native file descriptor number. */ } shfile; /** @name shfile::shflags values. * @{ */ #define SHFILE_FLAGS_CLOSE_ON_EXEC 0x0001 #define SHFILE_FLAGS_TYPE_MASK 0x00f0 #define SHFILE_FLAGS_FILE 0x0000 #define SHFILE_FLAGS_PIPE 0x0010 #define SHFILE_FLAGS_DIR 0x0020 #define SHFILE_FLAGS_TTY 0x0030 /** @} */ /** * The file descriptor table for a shell. */ typedef struct shfdtab { shmtx mtx; /**< Mutex protecting any operations on the table and it's handles. */ char *cwd; /**< The current directory for this shell instance. */ unsigned size; /**< The size of the table (number of entries). */ shfile *tab; /**< Pointer to the table. */ } shfdtab; int shfile_init(shfdtab *, shfdtab *); void shfile_fork_win(shfdtab *pfdtab, int set, intptr_t *hndls); void *shfile_exec_win(shfdtab *pfdtab, int prepare, unsigned short *sizep, intptr_t *hndls); int shfile_exec_unix(shfdtab *pfdtab); int shfile_open(shfdtab *, const char *, unsigned, mode_t); int shfile_pipe(shfdtab *, int [2]); int shfile_close(shfdtab *, unsigned); long shfile_read(shfdtab *, int, void *, size_t); long shfile_write(shfdtab *, int, const void *, size_t); long shfile_lseek(shfdtab *, int, long, int); int shfile_fcntl(shfdtab *, int fd, int cmd, int arg); int shfile_dup(shfdtab *, int fd); int shfile_movefd(shfdtab *, int fdfrom, int fdto); int shfile_movefd_above(shfdtab *, int fdfrom, int fdmin); int shfile_stat(shfdtab *, const char *, struct stat *); int shfile_lstat(shfdtab *, const char *, struct stat *); int shfile_chdir(shfdtab *, const char *); char *shfile_getcwd(shfdtab *, char *, int); int shfile_access(shfdtab *, const char *, int); int shfile_isatty(shfdtab *, int); int shfile_cloexec(shfdtab *, int, int); int shfile_ioctl(shfdtab *, int, unsigned long, void *); #if defined(_MSC_VER) || defined(__OS2__) # define TIOCGWINSZ 0x4201 typedef struct sh_winsize { unsigned ws_row; /**< Rows, in characters. */ unsigned ws_col; /**< Columns, in characters. */ unsigned ws_xpixel; /**< Horizontal size, pixels. */ unsigned ws_ypixel; /**< Vertical size, pixels. */ } sh_winsize; #else typedef struct winsize sh_winsize; #endif mode_t shfile_get_umask(shfdtab *); void shfile_set_umask(shfdtab *, mode_t); typedef struct sh_dirent { char name[260]; } shdirent; typedef struct shdir { shfdtab *pfdtab; void *native; shdirent ent; #if K_OS == K_OS_WINDOWS size_t off; size_t cb; char buf[32768 - sizeof(void *) * 2 - sizeof(shdirent) * 2]; #endif } shdir; shdir *shfile_opendir(shfdtab *, const char *); shdirent *shfile_readdir(struct shdir *); void shfile_closedir(struct shdir *); #endif kbuild-2695/src/kash/shheap.h0000644000000000000000000000245412247157307014604 0ustar rootroot/* $Id: shheap.h 2416 2010-09-14 00:30:30Z bird $ */ /** @file * The shell memory heap methods. */ /* * Copyright (c) 2009-2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef ___shheap_h #define ___shheap_h #include "shtypes.h" /* heap */ int shheap_init(void *phead); void *shheap_get_head(void); int shheap_fork_copy_to_child(void *); void *sh_malloc(shinstance *, size_t); void *sh_calloc(shinstance *, size_t, size_t); void *sh_realloc(shinstance *, void *, size_t); char *sh_strdup(shinstance *, const char *); void sh_free(shinstance *, void *); #endif kbuild-2695/src/kash/myhistedit.h0000644000000000000000000000416112247157307015514 0ustar rootroot/* $NetBSD: myhistedit.h,v 1.10 2003/08/07 09:05:35 agc Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)myhistedit.h 8.2 (Berkeley) 5/4/95 */ #ifndef SMALL #include /*extern History *hist; extern EditLine *el;*/ #endif /*extern int displayhist;*/ void histedit(struct shinstance *); void sethistsize(struct shinstance *, const char *); void setterm(struct shinstance *, const char *); int histcmd(struct shinstance *, int, char **); int inputrc(struct shinstance *, int, char **); int not_fcnumber(struct shinstance *, char *); int str_to_event(struct shinstance *, const char *, int); kbuild-2695/src/kash/arith.y0000644000000000000000000001232612247157307014463 0ustar rootroot%{ /* $NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $"); #endif /* not lint */ #endif #include #include "expand.h" #include "shell.h" #include "error.h" #include "output.h" #include "memalloc.h" #include "shinstance.h" shinstance *arith_psh; const char *arith_buf, *arith_startbuf; void yyerror(const char *); #ifdef TESTARITH int main(int , char *[]); int error(char *); #else # undef malloc # define malloc(cb) sh_malloc(NULL, (cb)) # undef realloc # define realloc(pv,cb) sh_realloc(NULL, (pv), (cb)) # undef free # define free(pv) sh_free(NULL, (pv)) #endif %} %token ARITH_NUM ARITH_LPAREN ARITH_RPAREN %left ARITH_OR %left ARITH_AND %left ARITH_BOR %left ARITH_BXOR %left ARITH_BAND %left ARITH_EQ ARITH_NE %left ARITH_LT ARITH_GT ARITH_GE ARITH_LE %left ARITH_LSHIFT ARITH_RSHIFT %left ARITH_ADD ARITH_SUB %left ARITH_MUL ARITH_DIV ARITH_REM %left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT %% exp: expr { return ($1); } ; expr: ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; } | expr ARITH_OR expr { $$ = $1 ? $1 : $3 ? $3 : 0; } | expr ARITH_AND expr { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } | expr ARITH_BOR expr { $$ = $1 | $3; } | expr ARITH_BXOR expr { $$ = $1 ^ $3; } | expr ARITH_BAND expr { $$ = $1 & $3; } | expr ARITH_EQ expr { $$ = $1 == $3; } | expr ARITH_GT expr { $$ = $1 > $3; } | expr ARITH_GE expr { $$ = $1 >= $3; } | expr ARITH_LT expr { $$ = $1 < $3; } | expr ARITH_LE expr { $$ = $1 <= $3; } | expr ARITH_NE expr { $$ = $1 != $3; } | expr ARITH_LSHIFT expr { $$ = $1 << $3; } | expr ARITH_RSHIFT expr { $$ = $1 >> $3; } | expr ARITH_ADD expr { $$ = $1 + $3; } | expr ARITH_SUB expr { $$ = $1 - $3; } | expr ARITH_MUL expr { $$ = $1 * $3; } | expr ARITH_DIV expr { if ($3 == 0) yyerror("division by zero"); $$ = $1 / $3; } | expr ARITH_REM expr { if ($3 == 0) yyerror("division by zero"); $$ = $1 % $3; } | ARITH_NOT expr { $$ = !($2); } | ARITH_BNOT expr { $$ = ~($2); } | ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); } | ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; } | ARITH_NUM ; %% int arith(shinstance *psh, const char *s) { long result; INTOFF; /* todo lock */ arith_psh = psh; arith_buf = arith_startbuf = s; result = yyparse(); arith_lex_reset(); /* reprime lex */ arith_psh = NULL; /* todo unlock */ INTON; return (result); } /* * The exp(1) builtin. */ int expcmd(shinstance *psh, int argc, char **argv) { const char *p; char *concat; char **ap; long i; if (argc > 1) { p = argv[1]; if (argc > 2) { /* * concatenate arguments */ STARTSTACKSTR(psh, concat); ap = argv + 2; for (;;) { while (*p) STPUTC(psh, *p++, concat); if ((p = *ap++) == NULL) break; STPUTC(psh, ' ', concat); } STPUTC(psh, '\0', concat); p = grabstackstr(psh, concat); } } else p = ""; i = arith(psh, p); out1fmt(psh, "%ld\n", i); return (! i); } /*************************/ #ifdef TEST_ARITH #include main(argc, argv) char *argv[]; { printf("%d\n", exp(argv[1])); } error(s) char *s; { fprintf(stderr, "exp: %s\n", s); exit(1); } #endif void yyerror(const char *s) { shinstance *psh = arith_psh; #ifndef YYBISON /* yyerrok references yyerrstatus which is a local variable in yyparse().*/ yyerrok; #endif yyclearin; arith_lex_reset(); /* reprime lex */ /** @todo unlock */ error(psh, "arithmetic expression: %s: \"%s\"", s, arith_startbuf); /* NOTREACHED */ } kbuild-2695/src/kash/sh.10000644000000000000000000016023212247157307013656 0ustar rootroot.\" $NetBSD: sh.1,v 1.80 2005/05/24 00:03:52 wiz Exp $ .\" Copyright (c) 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Kenneth Almquist. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" .Dd May 7, 2005 .Os .Dt SH 1 .Sh NAME .Nm sh .Nd command interpreter (shell) .Sh SYNOPSIS .Nm .Bk -words .Op Fl aCefnuvxIimqVEb .Op Cm +aCefnuvxIimqVEb .Ek .Bk -words .Op Fl o Ar option_name .Op Cm +o Ar option_name .Ek .Bk -words .Op Ar command_file Oo Ar argument ... Oc .Ek .Nm .Fl c .Bk -words .Op Fl aCefnuvxIimqVEb .Op Cm +aCefnuvxIimqVEb .Ek .Bk -words .Op Fl o Ar option_name .Op Cm +o Ar option_name .Ek .Bk -words .Ar command_string .Op Ar command_name Oo Ar argument ... Oc .Ek .Nm .Fl s .Bk -words .Op Fl aCefnuvxIimqVEb .Op Cm +aCefnuvxIimqVEb .Ek .Bk -words .Op Fl o Ar option_name .Op Cm +o Ar option_name .Ek .Bk -words .Op Ar argument ... .Ek .Sh DESCRIPTION .Nm is the standard command interpreter for the system. The current version of .Nm is in the process of being changed to conform with the .Tn POSIX 1003.2 and 1003.2a specifications for the shell. This version has many features which make it appear similar in some respects to the Korn shell, but it is not a Korn shell clone (see .Xr ksh 1 ) . Only features designated by .Tn POSIX , plus a few Berkeley extensions, are being incorporated into this shell. .\" We expect .\" .Tn POSIX .\" conformance by the time 4.4 BSD is released. This man page is not intended to be a tutorial or a complete specification of the shell. .Ss Overview The shell is a command that reads lines from either a file or the terminal, interprets them, and generally executes other commands. It is the program that is running when a user logs into the system (although a user can select a different shell with the .Xr chsh 1 command). The shell implements a language that has flow control constructs, a macro facility that provides a variety of features in addition to data storage, along with built in history and line editing capabilities. It incorporates many features to aid interactive use and has the advantage that the interpretative language is common to both interactive and non-interactive use (shell scripts). That is, commands can be typed directly to the running shell or can be put into a file and the file can be executed directly by the shell. .Ss Invocation If no args are present and if the standard input of the shell is connected to a terminal (or if the .Fl i flag is set), and the .Fl c option is not present, the shell is considered an interactive shell. An interactive shell generally prompts before each command and handles programming and command errors differently (as described below). When first starting, the shell inspects argument 0, and if it begins with a dash .Sq - , the shell is also considered a login shell. This is normally done automatically by the system when the user first logs in. A login shell first reads commands from the files .Pa /etc/profile and .Pa .profile if they exist. If the environment variable .Ev ENV is set on entry to a shell, or is set in the .Pa .profile of a login shell, the shell next reads commands from the file named in .Ev ENV . Therefore, a user should place commands that are to be executed only at login time in the .Pa .profile file, and commands that are executed for every shell inside the .Ev ENV file. To set the .Ev ENV variable to some file, place the following line in your .Pa .profile of your home directory .Pp .Dl ENV=$HOME/.shinit; export ENV .Pp substituting for .Dq .shinit any filename you wish. Since the .Ev ENV file is read for every invocation of the shell, including shell scripts and non-interactive shells, the following paradigm is useful for restricting commands in the .Ev ENV file to interactive invocations. Place commands within the .Dq case and .Dq esac below (these commands are described later): .Pp .Bl -item -compact -offset indent .It .Li case $- in *i*) .Bl -item -compact -offset indent .It .Li # commands for interactive use only .It .Li ... .El .It .Li esac .El .Pp If command line arguments besides the options have been specified, then the shell treats the first argument as the name of a file from which to read commands (a shell script), and the remaining arguments are set as the positional parameters of the shell ($1, $2, etc). Otherwise, the shell reads commands from its standard input. .Ss Argument List Processing All of the single letter options have a corresponding name that can be used as an argument to the .Fl o option. The set .Fl o name is provided next to the single letter option in the description below. Specifying a dash .Dq - turns the option on, while using a plus .Dq + disables the option. The following options can be set from the command line or with the .Ic set builtin (described later). .Bl -tag -width aaaallexportfoo -offset indent .It Fl a Em allexport Export all variables assigned to. .It Fl c Read commands from the .Ar command_string operand instead of from the standard input. Special parameter 0 will be set from the .Ar command_name operand and the positional parameters ($1, $2, etc.) set from the remaining argument operands. .It Fl C Em noclobber Don't overwrite existing files with .Dq \*[Gt] . .It Fl e Em errexit If not interactive, exit immediately if any untested command fails. The exit status of a command is considered to be explicitly tested if the command is used to control an .Ic if , .Ic elif , .Ic while , or .Ic until ; or if the command is the left hand operand of an .Dq \*[Am]\*[Am] or .Dq || operator. .It Fl f Em noglob Disable pathname expansion. .It Fl n Em noexec If not interactive, read commands but do not execute them. This is useful for checking the syntax of shell scripts. .It Fl u Em nounset Write a message to standard error when attempting to expand a variable that is not set, and if the shell is not interactive, exit immediately. .It Fl v Em verbose The shell writes its input to standard error as it is read. Useful for debugging. .It Fl x Em xtrace Write each command to standard error (preceded by a .Sq +\ ) before it is executed. Useful for debugging. .It Fl q Em quietprofile If the .Fl v or .Fl x options have been set, do not apply them when reading initialization files, these being .Pa /etc/profile , .Pa .profile , and the file specified by the .Ev ENV environment variable. .It Fl I Em ignoreeof Ignore EOF's from input when interactive. .It Fl i Em interactive Force the shell to behave interactively. .It Fl m Em monitor Turn on job control (set automatically when interactive). .It Fl s Em stdin Read commands from standard input (set automatically if no file arguments are present). This option has no effect when set after the shell has already started running (i.e. with .Ic set ) . .It Fl V Em vi Enable the built-in .Xr vi 1 command line editor (disables .Fl E if it has been set). (See the .Sx Command Line Editing section below.) .It Fl E Em emacs Enable the built-in emacs style command line editor (disables .Fl V if it has been set). (See the .Sx Command Line Editing section below.) .It Fl b Em notify Enable asynchronous notification of background job completion. (UNIMPLEMENTED for 4.4alpha) .It "\ \ " Em cdprint Make an interactive shell always print the new directory name when changed by the .Ic cd command. .It "\ \ " Em tabcomplete Enables filename completion in the command line editor. Typing a tab character will extend the current input word to match a filename. If more than one filename matches it is only extended to be the common prefix. Typing a second tab character will list all the matching names. .El .Ss Lexical Structure The shell reads input in terms of lines from a file and breaks it up into words at whitespace (blanks and tabs), and at certain sequences of characters that are special to the shell called .Dq operators . There are two types of operators: control operators and redirection operators (their meaning is discussed later). Following is a list of operators: .Bl -ohang -offset indent .It "Control operators:" .Dl \*[Am] \*[Am]\*[Am] \&( \&) \&; ;; | || \*[Lt]newline\*[Gt] .It "Redirection operators:" .Dl \*[Lt] \*[Gt] \*[Gt]| \*[Lt]\*[Lt] \*[Gt]\*[Gt] \*[Lt]\*[Am] \*[Gt]\*[Am] \*[Lt]\*[Lt]- \*[Lt]\*[Gt] .El .Ss Quoting Quoting is used to remove the special meaning of certain characters or words to the shell, such as operators, whitespace, or keywords. There are three types of quoting: matched single quotes, matched double quotes, and backslash. .Ss Backslash A backslash preserves the literal meaning of the following character, with the exception of .Aq newline . A backslash preceding a .Aq newline is treated as a line continuation. .Ss Single Quotes Enclosing characters in single quotes preserves the literal meaning of all the characters (except single quotes, making it impossible to put single-quotes in a single-quoted string). .Ss Double Quotes Enclosing characters within double quotes preserves the literal meaning of all characters except dollarsign .Pq $ , backquote .Pq ` , and backslash .Pq \e . The backslash inside double quotes is historically weird, and serves to quote only the following characters: .Dl $ ` \*q \e \*[Lt]newline\*[Gt] . Otherwise it remains literal. .Ss Reserved Words Reserved words are words that have special meaning to the shell and are recognized at the beginning of a line and after a control operator. The following are reserved words: .Bl -column while while while while while -offset indent .It ! Ta elif Ta fi Ta while Ta case .It else Ta for Ta then Ta { Ta } .It do Ta done Ta until Ta if Ta esac .El .Pp Their meaning is discussed later. .Ss Aliases An alias is a name and corresponding value set using the .Ic alias builtin command. Whenever a reserved word may occur (see above), and after checking for reserved words, the shell checks the word to see if it matches an alias. If it does, it replaces it in the input stream with its value. For example, if there is an alias called .Dq lf with the value .Dq "ls -F" , then the input: .Pp .Dl lf foobar Aq return .Pp would become .Pp .Dl ls -F foobar Aq return .Pp Aliases provide a convenient way for naive users to create shorthands for commands without having to learn how to create functions with arguments. They can also be used to create lexically obscure code. This use is discouraged. .Ss Commands The shell interprets the words it reads according to a language, the specification of which is outside the scope of this man page (refer to the BNF in the .Tn POSIX 1003.2 document). Essentially though, a line is read and if the first word of the line (or after a control operator) is not a reserved word, then the shell has recognized a simple command. Otherwise, a complex command or some other special construct may have been recognized. .Ss Simple Commands If a simple command has been recognized, the shell performs the following actions: .Bl -enum -offset indent .It Leading words of the form .Dq name=value are stripped off and assigned to the environment of the simple command. Redirection operators and their arguments (as described below) are stripped off and saved for processing. .It The remaining words are expanded as described in the section called .Dq Expansions , and the first remaining word is considered the command name and the command is located. The remaining words are considered the arguments of the command. If no command name resulted, then the .Dq name=value variable assignments recognized in item 1 affect the current shell. .It Redirections are performed as described in the next section. .El .Ss Redirections Redirections are used to change where a command reads its input or sends its output. In general, redirections open, close, or duplicate an existing reference to a file. The overall format used for redirection is: .Pp .Dl [n] Va redir-op Ar file .Pp where .Va redir-op is one of the redirection operators mentioned previously. Following is a list of the possible redirections. The .Bq n is an optional number, as in .Sq 3 (not .Sq Bq 3 ) , that refers to a file descriptor. .Bl -tag -width aaabsfiles -offset indent .It [n] Ns \*[Gt] file Redirect standard output (or n) to file. .It [n] Ns \*[Gt]| file Same, but override the .Fl C option. .It [n] Ns \*[Gt]\*[Gt] file Append standard output (or n) to file. .It [n] Ns \*[Lt] file Redirect standard input (or n) from file. .It [n1] Ns \*[Lt]\*[Am] Ns n2 Duplicate standard input (or n1) from file descriptor n2. .It [n] Ns \*[Lt]\*[Am]- Close standard input (or n). .It [n1] Ns \*[Gt]\*[Am] Ns n2 Duplicate standard output (or n1) to n2. .It [n] Ns \*[Gt]\*[Am]- Close standard output (or n). .It [n] Ns \*[Lt]\*[Gt] file Open file for reading and writing on standard input (or n). .El .Pp The following redirection is often called a .Dq here-document . .Bl -item -offset indent .It .Li [n]\*[Lt]\*[Lt] delimiter .Dl here-doc-text ... .Li delimiter .El .Pp All the text on successive lines up to the delimiter is saved away and made available to the command on standard input, or file descriptor n if it is specified. If the delimiter as specified on the initial line is quoted, then the here-doc-text is treated literally, otherwise the text is subjected to parameter expansion, command substitution, and arithmetic expansion (as described in the section on .Dq Expansions ) . If the operator is .Dq \*[Lt]\*[Lt]- instead of .Dq \*[Lt]\*[Lt] , then leading tabs in the here-doc-text are stripped. .Ss Search and Execution There are three types of commands: shell functions, builtin commands, and normal programs -- and the command is searched for (by name) in that order. They each are executed in a different way. .Pp When a shell function is executed, all of the shell positional parameters (except $0, which remains unchanged) are set to the arguments of the shell function. The variables which are explicitly placed in the environment of the command (by placing assignments to them before the function name) are made local to the function and are set to the values given. Then the command given in the function definition is executed. The positional parameters are restored to their original values when the command completes. This all occurs within the current shell. .Pp Shell builtins are executed internally to the shell, without spawning a new process. .Pp Otherwise, if the command name doesn't match a function or builtin, the command is searched for as a normal program in the file system (as described in the next section). When a normal program is executed, the shell runs the program, passing the arguments and the environment to the program. If the program is not a normal executable file (i.e., if it does not begin with the "magic number" whose .Tn ASCII representation is "#!", so .Xr execve 2 returns .Er ENOEXEC then) the shell will interpret the program in a subshell. The child shell will reinitialize itself in this case, so that the effect will be as if a new shell had been invoked to handle the ad-hoc shell script, except that the location of hashed commands located in the parent shell will be remembered by the child. .Pp Note that previous versions of this document and the source code itself misleadingly and sporadically refer to a shell script without a magic number as a "shell procedure". .Ss Path Search When locating a command, the shell first looks to see if it has a shell function by that name. Then it looks for a builtin command by that name. If a builtin command is not found, one of two things happen: .Bl -enum .It Command names containing a slash are simply executed without performing any searches. .It The shell searches each entry in .Ev PATH in turn for the command. The value of the .Ev PATH variable should be a series of entries separated by colons. Each entry consists of a directory name. The current directory may be indicated implicitly by an empty directory name, or explicitly by a single period. .El .Ss Command Exit Status Each command has an exit status that can influence the behavior of other shell commands. The paradigm is that a command exits with zero for normal or success, and non-zero for failure, error, or a false indication. The man page for each command should indicate the various exit codes and what they mean. Additionally, the builtin commands return exit codes, as does an executed shell function. .Pp If a command consists entirely of variable assignments then the exit status of the command is that of the last command substitution if any, otherwise 0. .Ss Complex Commands Complex commands are combinations of simple commands with control operators or reserved words, together creating a larger complex command. More generally, a command is one of the following: .Bl -bullet .It simple command .It pipeline .It list or compound-list .It compound command .It function definition .El .Pp Unless otherwise stated, the exit status of a command is that of the last simple command executed by the command. .Ss Pipelines A pipeline is a sequence of one or more commands separated by the control operator |. The standard output of all but the last command is connected to the standard input of the next command. The standard output of the last command is inherited from the shell, as usual. .Pp The format for a pipeline is: .Pp .Dl [!] command1 [ | command2 ...] .Pp The standard output of command1 is connected to the standard input of command2. The standard input, standard output, or both of a command is considered to be assigned by the pipeline before any redirection specified by redirection operators that are part of the command. .Pp If the pipeline is not in the background (discussed later), the shell waits for all commands to complete. .Pp If the reserved word ! does not precede the pipeline, the exit status is the exit status of the last command specified in the pipeline. Otherwise, the exit status is the logical NOT of the exit status of the last command. That is, if the last command returns zero, the exit status is 1; if the last command returns greater than zero, the exit status is zero. .Pp Because pipeline assignment of standard input or standard output or both takes place before redirection, it can be modified by redirection. For example: .Pp .Dl $ command1 2\*[Gt]\*[Am]1 | command2 .Pp sends both the standard output and standard error of command1 to the standard input of command2. .Pp A ; or .Aq newline terminator causes the preceding AND-OR-list (described next) to be executed sequentially; a \*[Am] causes asynchronous execution of the preceding AND-OR-list. .Pp Note that unlike some other shells, each process in the pipeline is a child of the invoking shell (unless it is a shell builtin, in which case it executes in the current shell -- but any effect it has on the environment is wiped). .Ss Background Commands -- \*[Am] If a command is terminated by the control operator ampersand (\*[Am]), the shell executes the command asynchronously -- that is, the shell does not wait for the command to finish before executing the next command. .Pp The format for running a command in background is: .Pp .Dl command1 \*[Am] [command2 \*[Am] ...] .Pp If the shell is not interactive, the standard input of an asynchronous command is set to .Pa /dev/null . .Ss Lists -- Generally Speaking A list is a sequence of zero or more commands separated by newlines, semicolons, or ampersands, and optionally terminated by one of these three characters. The commands in a list are executed in the order they are written. If command is followed by an ampersand, the shell starts the command and immediately proceed onto the next command; otherwise it waits for the command to terminate before proceeding to the next one. .Ss Short-Circuit List Operators .Dq \*[Am]\*[Am] and .Dq || are AND-OR list operators. .Dq \*[Am]\*[Am] executes the first command, and then executes the second command if and only if the exit status of the first command is zero. .Dq || is similar, but executes the second command if and only if the exit status of the first command is nonzero. .Dq \*[Am]\*[Am] and .Dq || both have the same priority. Note that these operators are left-associative, so .Dq true || echo bar && echo baz writes .Dq baz and nothing else. This is not the way it works in C. .Ss Flow-Control Constructs -- if, while, for, case The syntax of the if command is .Bd -literal -offset indent if list then list [ elif list then list ] ... [ else list ] fi .Ed .Pp The syntax of the while command is .Bd -literal -offset indent while list do list done .Ed .Pp The two lists are executed repeatedly while the exit status of the first list is zero. The until command is similar, but has the word until in place of while, which causes it to repeat until the exit status of the first list is zero. .Pp The syntax of the for command is .Bd -literal -offset indent for variable in word ... do list done .Ed .Pp The words are expanded, and then the list is executed repeatedly with the variable set to each word in turn. do and done may be replaced with .Dq { and .Dq } . .Pp The syntax of the break and continue command is .Bd -literal -offset indent break [ num ] continue [ num ] .Ed .Pp Break terminates the num innermost for or while loops. Continue continues with the next iteration of the innermost loop. These are implemented as builtin commands. .Pp The syntax of the case command is .Bd -literal -offset indent case word in pattern) list ;; \&... esac .Ed .Pp The pattern can actually be one or more patterns (see .Sx Shell Patterns described later), separated by .Dq \*(Ba characters. .Ss Grouping Commands Together Commands may be grouped by writing either .Pp .Dl (list) .Pp or .Pp .Dl { list; } .Pp The first of these executes the commands in a subshell. Builtin commands grouped into a (list) will not affect the current shell. The second form does not fork another shell so is slightly more efficient. Grouping commands together this way allows you to redirect their output as though they were one program: .Pp .Bd -literal -offset indent { echo -n \*q hello \*q ; echo \*q world" ; } \*[Gt] greeting .Ed .Pp Note that .Dq } must follow a control operator (here, .Dq \&; ) so that it is recognized as a reserved word and not as another command argument. .Ss Functions The syntax of a function definition is .Pp .Dl name ( ) command .Pp A function definition is an executable statement; when executed it installs a function named name and returns an exit status of zero. The command is normally a list enclosed between .Dq { and .Dq } . .Pp Variables may be declared to be local to a function by using a local command. This should appear as the first statement of a function, and the syntax is .Pp .Dl local [ variable | - ] ... .Pp Local is implemented as a builtin command. .Pp When a variable is made local, it inherits the initial value and exported and readonly flags from the variable with the same name in the surrounding scope, if there is one. Otherwise, the variable is initially unset. The shell uses dynamic scoping, so that if you make the variable x local to function f, which then calls function g, references to the variable x made inside g will refer to the variable x declared inside f, not to the global variable named x. .Pp The only special parameter that can be made local is .Dq - . Making .Dq - local any shell options that are changed via the set command inside the function to be restored to their original values when the function returns. .Pp The syntax of the return command is .Pp .Dl return [ exitstatus ] .Pp It terminates the currently executing function. Return is implemented as a builtin command. .Ss Variables and Parameters The shell maintains a set of parameters. A parameter denoted by a name is called a variable. When starting up, the shell turns all the environment variables into shell variables. New variables can be set using the form .Pp .Dl name=value .Pp Variables set by the user must have a name consisting solely of alphabetics, numerics, and underscores - the first of which must not be numeric. A parameter can also be denoted by a number or a special character as explained below. .Ss Positional Parameters A positional parameter is a parameter denoted by a number (n \*[Gt] 0). The shell sets these initially to the values of its command line arguments that follow the name of the shell script. The .Ic set builtin can also be used to set or reset them. .Ss Special Parameters A special parameter is a parameter denoted by one of the following special characters. The value of the parameter is listed next to its character. .Bl -tag -width thinhyphena .It * Expands to the positional parameters, starting from one. When the expansion occurs within a double-quoted string it expands to a single field with the value of each parameter separated by the first character of the .Ev IFS variable, or by a .Aq space if .Ev IFS is unset. .It @ Expands to the positional parameters, starting from one. When the expansion occurs within double-quotes, each positional parameter expands as a separate argument. If there are no positional parameters, the expansion of @ generates zero arguments, even when @ is double-quoted. What this basically means, for example, is if $1 is .Dq abc and $2 is .Dq def ghi , then .Qq $@ expands to the two arguments: .Pp .Sm off .Dl \*q abc \*q \ \*q def\ ghi \*q .Sm on .It # Expands to the number of positional parameters. .It \&? Expands to the exit status of the most recent pipeline. .It - (Hyphen.) Expands to the current option flags (the single-letter option names concatenated into a string) as specified on invocation, by the set builtin command, or implicitly by the shell. .It $ Expands to the process ID of the invoked shell. A subshell retains the same value of $ as its parent. .It \&! Expands to the process ID of the most recent background command executed from the current shell. For a pipeline, the process ID is that of the last command in the pipeline. .It 0 (Zero.) Expands to the name of the shell or shell script. .El .Ss Word Expansions This clause describes the various expansions that are performed on words. Not all expansions are performed on every word, as explained later. .Pp Tilde expansions, parameter expansions, command substitutions, arithmetic expansions, and quote removals that occur within a single word expand to a single field. It is only field splitting or pathname expansion that can create multiple fields from a single word. The single exception to this rule is the expansion of the special parameter @ within double-quotes, as was described above. .Pp The order of word expansion is: .Bl -enum .It Tilde Expansion, Parameter Expansion, Command Substitution, Arithmetic Expansion (these all occur at the same time). .It Field Splitting is performed on fields generated by step (1) unless the .Ev IFS variable is null. .It Pathname Expansion (unless set .Fl f is in effect). .It Quote Removal. .El .Pp The $ character is used to introduce parameter expansion, command substitution, or arithmetic evaluation. .Ss Tilde Expansion (substituting a user's home directory) A word beginning with an unquoted tilde character (~) is subjected to tilde expansion. All the characters up to a slash (/) or the end of the word are treated as a username and are replaced with the user's home directory. If the username is missing (as in .Pa ~/foobar ) , the tilde is replaced with the value of the .Va HOME variable (the current user's home directory). .Ss Parameter Expansion The format for parameter expansion is as follows: .Pp .Dl ${expression} .Pp where expression consists of all characters until the matching .Dq } . Any .Dq } escaped by a backslash or within a quoted string, and characters in embedded arithmetic expansions, command substitutions, and variable expansions, are not examined in determining the matching .Dq } . .Pp The simplest form for parameter expansion is: .Pp .Dl ${parameter} .Pp The value, if any, of parameter is substituted. .Pp The parameter name or symbol can be enclosed in braces, which are optional except for positional parameters with more than one digit or when parameter is followed by a character that could be interpreted as part of the name. If a parameter expansion occurs inside double-quotes: .Bl -enum .It Pathname expansion is not performed on the results of the expansion. .It Field splitting is not performed on the results of the expansion, with the exception of the special rules for @. .El .Pp In addition, a parameter expansion can be modified by using one of the following formats. .Bl -tag -width aaparameterwordaaaaa .It ${parameter:-word} Use Default Values. If parameter is unset or null, the expansion of word is substituted; otherwise, the value of parameter is substituted. .It ${parameter:=word} Assign Default Values. If parameter is unset or null, the expansion of word is assigned to parameter. In all cases, the final value of parameter is substituted. Only variables, not positional parameters or special parameters, can be assigned in this way. .It ${parameter:?[word]} Indicate Error if Null or Unset. If parameter is unset or null, the expansion of word (or a message indicating it is unset if word is omitted) is written to standard error and the shell exits with a nonzero exit status. Otherwise, the value of parameter is substituted. An interactive shell need not exit. .It ${parameter:+word} Use Alternative Value. If parameter is unset or null, null is substituted; otherwise, the expansion of word is substituted. .El .Pp In the parameter expansions shown previously, use of the colon in the format results in a test for a parameter that is unset or null; omission of the colon results in a test for a parameter that is only unset. .Bl -tag -width aaparameterwordaaaaa .It ${#parameter} String Length. The length in characters of the value of parameter. .El .Pp The following four varieties of parameter expansion provide for substring processing. In each case, pattern matching notation (see .Sx Shell Patterns ) , rather than regular expression notation, is used to evaluate the patterns. If parameter is * or @, the result of the expansion is unspecified. Enclosing the full parameter expansion string in double-quotes does not cause the following four varieties of pattern characters to be quoted, whereas quoting characters within the braces has this effect. .Bl -tag -width aaparameterwordaaaaa .It ${parameter%word} Remove Smallest Suffix Pattern. The word is expanded to produce a pattern. The parameter expansion then results in parameter, with the smallest portion of the suffix matched by the pattern deleted. .It ${parameter%%word} Remove Largest Suffix Pattern. The word is expanded to produce a pattern. The parameter expansion then results in parameter, with the largest portion of the suffix matched by the pattern deleted. .It ${parameter#word} Remove Smallest Prefix Pattern. The word is expanded to produce a pattern. The parameter expansion then results in parameter, with the smallest portion of the prefix matched by the pattern deleted. .It ${parameter##word} Remove Largest Prefix Pattern. The word is expanded to produce a pattern. The parameter expansion then results in parameter, with the largest portion of the prefix matched by the pattern deleted. .El .Ss Command Substitution Command substitution allows the output of a command to be substituted in place of the command name itself. Command substitution occurs when the command is enclosed as follows: .Pp .Dl $(command) .Pp or .Po .Dq backquoted version .Pc : .Pp .Dl `command` .Pp The shell expands the command substitution by executing command in a subshell environment and replacing the command substitution with the standard output of the command, removing sequences of one or more .Ao newline Ac Ns s at the end of the substitution. (Embedded .Ao newline Ac Ns s before the end of the output are not removed; however, during field splitting, they may be translated into .Ao space Ac Ns s , depending on the value of .Ev IFS and quoting that is in effect.) .Ss Arithmetic Expansion Arithmetic expansion provides a mechanism for evaluating an arithmetic expression and substituting its value. The format for arithmetic expansion is as follows: .Pp .Dl $((expression)) .Pp The expression is treated as if it were in double-quotes, except that a double-quote inside the expression is not treated specially. The shell expands all tokens in the expression for parameter expansion, command substitution, and quote removal. .Pp Next, the shell treats this as an arithmetic expression and substitutes the value of the expression. .Ss White Space Splitting (Field Splitting) After parameter expansion, command substitution, and arithmetic expansion the shell scans the results of expansions and substitutions that did not occur in double-quotes for field splitting and multiple fields can result. .Pp The shell treats each character of the .Ev IFS as a delimiter and use the delimiters to split the results of parameter expansion and command substitution into fields. .Pp Non-whitespace characters in .Ev IFS are treated strictly as parameter terminators. So adjacent non-whitespace .Ev IFS characters will produce empty parameters. .Pp If .Ev IFS is unset it is assumed to contain space, tab, and newline. .Ss Pathname Expansion (File Name Generation) Unless the .Fl f flag is set, file name generation is performed after word splitting is complete. Each word is viewed as a series of patterns, separated by slashes. The process of expansion replaces the word with the names of all existing files whose names can be formed by replacing each pattern with a string that matches the specified pattern. There are two restrictions on this: first, a pattern cannot match a string containing a slash, and second, a pattern cannot match a string starting with a period unless the first character of the pattern is a period. The next section describes the patterns used for both Pathname Expansion and the .Ic case command. .Ss Shell Patterns A pattern consists of normal characters, which match themselves, and meta-characters. The meta-characters are .Dq \&! , .Dq * , .Dq \&? , and .Dq \&[ . These characters lose their special meanings if they are quoted. When command or variable substitution is performed and the dollar sign or back quotes are not double quoted, the value of the variable or the output of the command is scanned for these characters and they are turned into meta-characters. .Pp An asterisk .Pq Dq * matches any string of characters. A question mark matches any single character. A left bracket .Pq Dq \&[ introduces a character class. The end of the character class is indicated by a .Pq Dq \&] ; if the .Dq \&] is missing then the .Dq \&[ matches a .Dq \&[ rather than introducing a character class. A character class matches any of the characters between the square brackets. A range of characters may be specified using a minus sign. The character class may be complemented by making an exclamation point the first character of the character class. .Pp To include a .Dq \&] in a character class, make it the first character listed (after the .Dq \&! , if any). To include a minus sign, make it the first or last character listed. .Ss Builtins This section lists the builtin commands which are builtin because they need to perform some operation that can't be performed by a separate process. In addition to these, there are several other commands that may be builtin for efficiency (e.g. .Xr printf 1 , .Xr echo 1 , .Xr test 1 , etc). .Bl -tag -width 5n .It : A null command that returns a 0 (true) exit value. .It \&. file The commands in the specified file are read and executed by the shell. .It alias Op Ar name Ns Op Ar "=string ..." If .Ar name=string is specified, the shell defines the alias .Ar name with value .Ar string . If just .Ar name is specified, the value of the alias .Ar name is printed. With no arguments, the .Ic alias builtin prints the names and values of all defined aliases (see .Ic unalias ) . .It bg [ Ar job ] ... Continue the specified jobs (or the current job if no jobs are given) in the background. .It Xo command .Op Fl p .Op Fl v .Op Fl V .Ar command .Op Ar arg ... .Xc Execute the specified command but ignore shell functions when searching for it. (This is useful when you have a shell function with the same name as a builtin command.) .Bl -tag -width 5n .It Fl p search for command using a .Ev PATH that guarantees to find all the standard utilities. .It Fl V Do not execute the command but search for the command and print the resolution of the command search. This is the same as the type builtin. .It Fl v Do not execute the command but search for the command and print the absolute pathname of utilities, the name for builtins or the expansion of aliases. .El .It cd Op Ar directory Op Ar replace Switch to the specified directory (default .Ev $HOME ) . If .Ar replace is specified, then the new directory name is generated by replacing the first occurrence of .Ar directory in the current directory name with .Ar replace . Otherwise if an entry for .Ev CDPATH appears in the environment of the .Ic cd command or the shell variable .Ev CDPATH is set and the directory name does not begin with a slash, then the directories listed in .Ev CDPATH will be searched for the specified directory. The format of .Ev CDPATH is the same as that of .Ev PATH . In an interactive shell, the .Ic cd command will print out the name of the directory that it actually switched to if this is different from the name that the user gave. These may be different either because the .Ev CDPATH mechanism was used or because a symbolic link was crossed. .It eval Ar string ... Concatenate all the arguments with spaces. Then re-parse and execute the command. .It exec Op Ar command arg ... Unless command is omitted, the shell process is replaced with the specified program (which must be a real program, not a shell builtin or function). Any redirections on the .Ic exec command are marked as permanent, so that they are not undone when the .Ic exec command finishes. .It exit Op Ar exitstatus Terminate the shell process. If .Ar exitstatus is given it is used as the exit status of the shell; otherwise the exit status of the preceding command is used. .It export Ar name ... .It export Fl p The specified names are exported so that they will appear in the environment of subsequent commands. The only way to un-export a variable is to unset it. The shell allows the value of a variable to be set at the same time it is exported by writing .Pp .Dl export name=value .Pp With no arguments the export command lists the names of all exported variables. With the .Fl p option specified the output will be formatted suitably for non-interactive use. .It Xo fc Op Fl e Ar editor .Op Ar first Op Ar last .Xc .It Xo fc Fl l .Op Fl nr .Op Ar first Op Ar last .Xc .It Xo fc Fl s Op Ar old=new .Op Ar first .Xc The .Ic fc builtin lists, or edits and re-executes, commands previously entered to an interactive shell. .Bl -tag -width 5n .It Fl e No editor Use the editor named by editor to edit the commands. The editor string is a command name, subject to search via the .Ev PATH variable. The value in the .Ev FCEDIT variable is used as a default when .Fl e is not specified. If .Ev FCEDIT is null or unset, the value of the .Ev EDITOR variable is used. If .Ev EDITOR is null or unset, .Xr ed 1 is used as the editor. .It Fl l No (ell) List the commands rather than invoking an editor on them. The commands are written in the sequence indicated by the first and last operands, as affected by .Fl r , with each command preceded by the command number. .It Fl n Suppress command numbers when listing with -l. .It Fl r Reverse the order of the commands listed (with .Fl l ) or edited (with neither .Fl l nor .Fl s ) . .It Fl s Re-execute the command without invoking an editor. .It first .It last Select the commands to list or edit. The number of previous commands that can be accessed are determined by the value of the .Ev HISTSIZE variable. The value of first or last or both are one of the following: .Bl -tag -width 5n .It [+]number A positive number representing a command number; command numbers can be displayed with the .Fl l option. .It Fl number A negative decimal number representing the command that was executed number of commands previously. For example, \-1 is the immediately previous command. .El .It string A string indicating the most recently entered command that begins with that string. If the old=new operand is not also specified with .Fl s , the string form of the first operand cannot contain an embedded equal sign. .El .Pp The following environment variables affect the execution of fc: .Bl -tag -width HISTSIZE .It Ev FCEDIT Name of the editor to use. .It Ev HISTSIZE The number of previous commands that are accessible. .El .It fg Op Ar job Move the specified job or the current job to the foreground. .It getopts Ar optstring var The .Tn POSIX .Ic getopts command, not to be confused with the .Em Bell Labs -derived .Xr getopt 1 . .Pp The first argument should be a series of letters, each of which may be optionally followed by a colon to indicate that the option requires an argument. The variable specified is set to the parsed option. .Pp The .Ic getopts command deprecates the older .Xr getopt 1 utility due to its handling of arguments containing whitespace. .Pp The .Ic getopts builtin may be used to obtain options and their arguments from a list of parameters. When invoked, .Ic getopts places the value of the next option from the option string in the list in the shell variable specified by .Va var and its index in the shell variable .Ev OPTIND . When the shell is invoked, .Ev OPTIND is initialized to 1. For each option that requires an argument, the .Ic getopts builtin will place it in the shell variable .Ev OPTARG . If an option is not allowed for in the .Va optstring , then .Ev OPTARG will be unset. .Pp .Va optstring is a string of recognized option letters (see .Xr getopt 3 ) . If a letter is followed by a colon, the option is expected to have an argument which may or may not be separated from it by whitespace. If an option character is not found where expected, .Ic getopts will set the variable .Va var to a .Dq \&? ; .Ic getopts will then unset .Ev OPTARG and write output to standard error. By specifying a colon as the first character of .Va optstring all errors will be ignored. .Pp A nonzero value is returned when the last option is reached. If there are no remaining arguments, .Ic getopts will set .Va var to the special option, .Dq -- , otherwise, it will set .Va var to .Dq \&? . .Pp The following code fragment shows how one might process the arguments for a command that can take the options .Op a and .Op b , and the option .Op c , which requires an argument. .Pp .Bd -literal -offset indent while getopts abc: f do case $f in a | b) flag=$f;; c) carg=$OPTARG;; \\?) echo $USAGE; exit 1;; esac done shift `expr $OPTIND - 1` .Ed .Pp This code will accept any of the following as equivalent: .Pp .Bd -literal -offset indent cmd \-acarg file file cmd \-a \-c arg file file cmd \-carg -a file file cmd \-a \-carg \-\- file file .Ed .It hash Fl rv Ar command ... The shell maintains a hash table which remembers the locations of commands. With no arguments whatsoever, the .Ic hash command prints out the contents of this table. Entries which have not been looked at since the last .Ic cd command are marked with an asterisk; it is possible for these entries to be invalid. .Pp With arguments, the .Ic hash command removes the specified commands from the hash table (unless they are functions) and then locates them. With the .Fl v option, hash prints the locations of the commands as it finds them. The .Fl r option causes the hash command to delete all the entries in the hash table except for functions. .It inputrc Ar file Read the .Va file to set keybindings as defined by .Xr editrc 5 . .It jobid Op Ar job Print the process id's of the processes in the job. If the .Ar job argument is omitted, the current job is used. .It jobs This command lists out all the background processes which are children of the current shell process. .It pwd Op Fl LP Print the current directory. If .Fl L is specified the cached value (initially set from .Ev PWD ) is checked to see if it refers to the current directory, if it does the value is printed. Otherwise the current directory name is found using .Xr getcwd(3) . The environment variable .Ev PWD is set to printed value. .Pp The default is .Ic pwd .Fl L , but note that the builtin .Ic cd command doesn't currently support .Fl L or .Fl P and will cache (almost) the absolute path. If .Ic cd is changed, .Ic pwd may be changed to default to .Ic pwd .Fl P . .Pp If the current directory is renamed and replaced by a symlink to the same directory, or the initial .Ev PWD value followed a symbolic link, then the cached value may not be the absolute path. .Pp The builtin command may differ from the program of the same name because the program will use .Ev PWD and the builtin uses a separately cached value. .It Xo read Op Fl p Ar prompt .Op Fl r .Ar variable .Op Ar ... .Xc The prompt is printed if the .Fl p option is specified and the standard input is a terminal. Then a line is read from the standard input. The trailing newline is deleted from the line and the line is split as described in the section on word splitting above, and the pieces are assigned to the variables in order. If there are more pieces than variables, the remaining pieces (along with the characters in .Ev IFS that separated them) are assigned to the last variable. If there are more variables than pieces, the remaining variables are assigned the null string. The .Ic read builtin will indicate success unless EOF is encountered on input, in which case failure is returned. .Pp By default, unless the .Fl r option is specified, the backslash .Dq \e acts as an escape character, causing the following character to be treated literally. If a backslash is followed by a newline, the backslash and the newline will be deleted. .It readonly Ar name ... .It readonly Fl p The specified names are marked as read only, so that they cannot be subsequently modified or unset. The shell allows the value of a variable to be set at the same time it is marked read only by writing .Pp .Dl readonly name=value .Pp With no arguments the readonly command lists the names of all read only variables. With the .Fl p option specified the output will be formatted suitably for non-interactive use. .Pp .It Xo set .Oo { .Fl options | Cm +options | Cm -- } .Oc Ar arg ... .Xc The .Ic set command performs three different functions. .Pp With no arguments, it lists the values of all shell variables. .Pp If options are given, it sets the specified option flags, or clears them as described in the section called .Sx Argument List Processing . .Pp The third use of the set command is to set the values of the shell's positional parameters to the specified args. To change the positional parameters without changing any options, use .Dq -- as the first argument to set. If no args are present, the set command will clear all the positional parameters (equivalent to executing .Dq shift $# . ) .It setvar Ar variable Ar value Assigns value to variable. (In general it is better to write variable=value rather than using .Ic setvar . .Ic setvar is intended to be used in functions that assign values to variables whose names are passed as parameters.) .It shift Op Ar n Shift the positional parameters n times. A .Ic shift sets the value of .Va $1 to the value of .Va $2 , the value of .Va $2 to the value of .Va $3 , and so on, decreasing the value of .Va $# by one. If there are zero positional parameters, .Ic shift does nothing. .It Xo trap .Op Fl l .Xc .It Xo trap .Op Ar action .Ar signal ... .Xc Cause the shell to parse and execute action when any of the specified signals are received. The signals are specified by signal number or as the name of the signal. If .Ar signal is .Li 0 , the action is executed when the shell exits. .Ar action may be null, which cause the specified signals to be ignored. With .Ar action omitted or set to `-' the specified signals are set to their default action. When the shell forks off a subshell, it resets trapped (but not ignored) signals to the default action. The .Ic trap command has no effect on signals that were ignored on entry to the shell. Issuing .Ic trap with option .Ar -l will print a list of valid signal names. .Ic trap without any arguments cause it to write a list of signals and their associated action to the standard output in a format that is suitable as an input to the shell that achieves the same trapping results. .Pp Examples: .Pp .Dl trap .Pp List trapped signals and their corresponding action .Pp .Dl trap -l .Pp Print a list of valid signals .Pp .Dl trap '' INT QUIT tstp 30 .Pp Ignore signals INT QUIT TSTP USR1 .Pp .Dl trap date INT .Pp Print date upon receiving signal INT .It type Op Ar name ... Interpret each name as a command and print the resolution of the command search. Possible resolutions are: shell keyword, alias, shell builtin, command, tracked alias and not found. For aliases the alias expansion is printed; for commands and tracked aliases the complete pathname of the command is printed. .It ulimit Xo .Op Fl H \*(Ba Fl S .Op Fl a \*(Ba Fl tfdscmlpn Op Ar value .Xc Inquire about or set the hard or soft limits on processes or set new limits. The choice between hard limit (which no process is allowed to violate, and which may not be raised once it has been lowered) and soft limit (which causes processes to be signaled but not necessarily killed, and which may be raised) is made with these flags: .Bl -tag -width Fl .It Fl H set or inquire about hard limits .It Fl S set or inquire about soft limits. If neither .Fl H nor .Fl S is specified, the soft limit is displayed or both limits are set. If both are specified, the last one wins. .El .Pp .Bl -tag -width Fl The limit to be interrogated or set, then, is chosen by specifying any one of these flags: .It Fl a show all the current limits .It Fl b show or set the limit on the socket buffer size of a process (in bytes) .It Fl t show or set the limit on CPU time (in seconds) .It Fl f show or set the limit on the largest file that can be created (in 512-byte blocks) .It Fl d show or set the limit on the data segment size of a process (in kilobytes) .It Fl s show or set the limit on the stack size of a process (in kilobytes) .It Fl c show or set the limit on the largest core dump size that can be produced (in 512-byte blocks) .It Fl m show or set the limit on the total physical memory that can be in use by a process (in kilobytes) .It Fl l show or set the limit on how much memory a process can lock with .Xr mlock 2 (in kilobytes) .It Fl p show or set the limit on the number of processes this user can have at one time .It Fl n show or set the limit on the number of files a process can have open at once .El .Pp If none of these is specified, it is the limit on file size that is shown or set. If value is specified, the limit is set to that number; otherwise the current limit is displayed. .Pp Limits of an arbitrary process can be displayed or set using the .Xr sysctl 8 utility. .Pp .It umask Op Ar mask Set the value of umask (see .Xr umask 2 ) to the specified octal value. If the argument is omitted, the umask value is printed. .It unalias Xo .Op Fl a .Op Ar name .Xc If .Ar name is specified, the shell removes that alias. If .Fl a is specified, all aliases are removed. .It unset Ar name ... The specified variables and functions are unset and unexported. If a given name corresponds to both a variable and a function, both the variable and the function are unset. .It wait Op Ar job Wait for the specified job to complete and return the exit status of the last process in the job. If the argument is omitted, wait for all jobs to complete and then return an exit status of zero. .El .Ss Command Line Editing When .Nm is being used interactively from a terminal, the current command and the command history (see .Ic fc in .Sx Builtins ) can be edited using emacs-mode or vi-mode command-line editing. The command .Ql set -o emacs enables emacs-mode editing. The command .Ql set -o vi enables vi-mode editing and places sh into vi insert mode. (See the .Sx Argument List Processing section above.) .Pp The vi mode uses commands similar to a subset of those described in the .Xr vi 1 man page. With vi-mode enabled, sh can be switched between insert mode and command mode. It's similar to vi: typing .Aq ESC will throw you into command VI command mode. Hitting .Aq return while in command mode will pass the line to the shell. .Pp The emacs mode uses commands similar to a subset available in the emacs editor. With emacs-mode enabled, special keys can be used to modify the text in the buffer using the control key. .Pp .Nm uses the .Xr editline 3 library. .Sh EXIT STATUS Errors that are detected by the shell, such as a syntax error, will cause the shell to exit with a non-zero exit status. If the shell is not an interactive shell, the execution of the shell file will be aborted. Otherwise the shell will return the exit status of the last command executed, or if the exit builtin is used with a numeric argument, it will return the argument. .Sh ENVIRONMENT .Bl -tag -width MAILCHECK .It Ev HOME Set automatically by .Xr login 1 from the user's login directory in the password file .Pq Xr passwd 5 . This environment variable also functions as the default argument for the cd builtin. .It Ev PATH The default search path for executables. See the above section .Sx Path Search . .It Ev CDPATH The search path used with the cd builtin. .It Ev LANG The string used to specify localization information that allows users to work with different culture-specific and language conventions. See .Xr nls 7 . .It Ev MAIL The name of a mail file, that will be checked for the arrival of new mail. Overridden by .Ev MAILPATH . .It Ev MAILCHECK The frequency in seconds that the shell checks for the arrival of mail in the files specified by the .Ev MAILPATH or the .Ev MAIL file. If set to 0, the check will occur at each prompt. .It Ev MAILPATH A colon .Dq \&: separated list of file names, for the shell to check for incoming mail. This environment setting overrides the .Ev MAIL setting. There is a maximum of 10 mailboxes that can be monitored at once. .It Ev PS1 The primary prompt string, which defaults to .Dq $ \ , unless you are the superuser, in which case it defaults to .Dq # \ . .It Ev PS2 The secondary prompt string, which defaults to .Dq \*[Gt] \ . .It Ev PS4 Output before each line when execution trace (set -x) is enabled, defaults to .Dq + \ . .It Ev IFS Input Field Separators. This is normally set to .Aq space , .Aq tab , and .Aq newline . See the .Sx White Space Splitting section for more details. .It Ev TERM The default terminal setting for the shell. This is inherited by children of the shell, and is used in the history editing modes. .It Ev HISTSIZE The number of lines in the history buffer for the shell. .El .Sh FILES .Bl -item -width HOMEprofilexxxx .It .Pa $HOME/.profile .It .Pa /etc/profile .El .Sh SEE ALSO .Xr csh 1 , .Xr echo 1 , .Xr getopt 1 , .Xr ksh 1 , .Xr login 1 , .Xr printf 1 , .Xr test 1 , .Xr editline 3 , .Xr getopt 3 , .\" .Xr profile 4 , .Xr editrc 5 , .Xr passwd 5 , .Xr environ 7 , .Xr nls 7 , .Xr sysctl 8 .Sh HISTORY A .Nm command appeared in .At v1 . It was, however, unmaintainable so we wrote this one. .Sh BUGS Setuid shell scripts should be avoided at all costs, as they are a significant security risk. .Pp PS1, PS2, and PS4 should be subject to parameter expansion before being displayed. .Pp The characters generated by filename completion should probably be quoted to ensure that the filename is still valid after the input line has been processed. kbuild-2695/src/kash/eval.h0000644000000000000000000000536412247157307014266 0ustar rootroot/* $NetBSD: eval.h,v 1.14 2003/08/07 09:05:31 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)eval.h 8.2 (Berkeley) 5/4/95 */ /*extern char *commandname;*/ /* currently executing command */ /*extern int exitstatus;*/ /* exit status of last command */ /*extern int back_exitstatus;*/ /* exit status of backquoted command */ /*extern struct strlist *cmdenviron;*/ /* environment for builtin command */ struct backcmd { /* result of evalbackcmd */ int fd; /* file descriptor to read from */ char *buf; /* buffer */ int nleft; /* number of chars in buffer */ struct job *jp; /* job structure for command */ }; void evalstring(struct shinstance *, char *, int); union node; /* BLETCH for ansi C */ void evaltree(struct shinstance *, union node *, int); void evalbackcmd(struct shinstance *, union node *, struct backcmd *); /* in_function returns nonzero if we are currently evaluating a function */ #define in_function(psh) (psh)->funcnest /*extern int funcnest; extern int evalskip;*/ /* reasons for skipping commands (see comment on breakcmd routine) */ #define SKIPBREAK 1 #define SKIPCONT 2 #define SKIPFUNC 3 #define SKIPFILE 4 kbuild-2695/src/kash/var.c0000644000000000000000000005021612247157307014116 0ustar rootroot/* $NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $"); #endif /* not lint */ #endif #include #include #include #ifdef PC_OS2_LIBPATHS #define INCL_BASE #include #ifndef LIBPATHSTRICT #define LIBPATHSTRICT 3 #endif extern APIRET #ifdef APIENTRY APIENTRY #endif DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction); #define QHINF_EXEINFO 1 /* NE exeinfo. */ #define QHINF_READRSRCTBL 2 /* Reads from the resource table. */ #define QHINF_READFILE 3 /* Reads from the executable file. */ #define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */ #define QHINF_LIBPATH 5 /* Gets the entire libpath. */ #define QHINF_FIXENTRY 6 /* NE only */ #define QHINF_STE 7 /* NE only */ #define QHINF_MAPSEL 8 /* NE only */ #endif /* * Shell variables. */ #include "shell.h" #include "output.h" #include "expand.h" #include "nodes.h" /* for other headers */ #include "eval.h" /* defines cmdenviron */ #include "exec.h" #include "syntax.h" #include "options.h" #include "mail.h" #include "var.h" #include "memalloc.h" #include "error.h" #include "mystring.h" #include "parser.h" #include "show.h" #ifndef SMALL # include "myhistedit.h" #endif #include "shinstance.h" //#ifdef SMALL //#define VTABSIZE 39 //#else //#define VTABSIZE 517 //#endif struct varinit { unsigned var_off; int flags; const char *text; void (*func)(shinstance *, const char *); }; //#if ATTY //struct var vatty; //#endif //#ifndef SMALL //struct var vhistsize; //struct var vterm; //#endif //struct var vifs; //struct var vmail; //struct var vmpath; //struct var vpath; //#ifdef _MSC_VER //struct var vpath2; //#endif //struct var vps1; //struct var vps2; //struct var vps4; //struct var vvers; - unused //struct var voptind; #ifdef PC_OS2_LIBPATHS //static struct var libpath_vars[4]; static const char * const libpath_envs[4] = {"LIBPATH=", "BEGINLIBPATH=", "ENDLIBPATH=", "LIBPATHSTRICT="}; #endif const struct varinit varinit[] = { #if ATTY { offsetof(shinstance, vatty), VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", NULL }, #endif #ifndef SMALL { offsetof(shinstance, vhistsize), VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", sethistsize }, #endif { offsetof(shinstance, vifs), VSTRFIXED|VTEXTFIXED, "IFS= \t\n", NULL }, { offsetof(shinstance, vmail), VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", NULL }, { offsetof(shinstance, vmpath), VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", NULL }, { offsetof(shinstance, vpath), VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, changepath }, /* * vps1 depends on uid */ { offsetof(shinstance, vps2), VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL }, { offsetof(shinstance, vps4), VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL }, #ifndef SMALL { offsetof(shinstance, vterm), VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", setterm }, #endif { offsetof(shinstance, voptind), VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1", getoptsreset }, { 0, 0, NULL, NULL } }; //struct var *vartab[VTABSIZE]; STATIC int strequal(const char *, const char *); STATIC struct var *find_var(shinstance *, const char *, struct var ***, int *); /* * Initialize the varable symbol tables and import the environment */ #ifdef mkinit INCLUDE "var.h" INIT { char **envp; initvar(psh); for (envp = sh_environ(psh) ; *envp ; envp++) { if (strchr(*envp, '=')) { setvareq(psh, *envp, VEXPORT|VTEXTFIXED); } } } #endif /* * This routine initializes the builtin variables. It is called when the * shell is initialized and again when a shell procedure is spawned. */ void initvar(shinstance *psh) { const struct varinit *ip; struct var *vp; struct var **vpp; #ifdef PC_OS2_LIBPATHS char *psz = ckmalloc(psh, 2048); int rc; int i; for (i = 0; i < 4; i++) { psh->libpath_vars[i].flags = VSTRFIXED | VOS2LIBPATH; psh->libpath_vars[i].func = NULL; if (i > 0) { psz[0] = psz[1] = psz[2] = psz[3] = '\0'; rc = DosQueryExtLIBPATH(psz, i); } else { rc = DosQueryHeaderInfo(NULLHANDLE, 0, psz, 2048, QHINF_LIBPATH); psh->libpath_vars[i].flags |= VREADONLY; } if (!rc && *psz) { int cch1 = strlen(libpath_envs[i]); int cch2 = strlen(psz) + 1; psh->libpath_vars[i].text = ckmalloc(psh, cch1 + cch2); memcpy(psh->libpath_vars[i].text, libpath_envs[i], cch1); memcpy(psh->libpath_vars[i].text + cch1, psz, cch2); } else { psh->libpath_vars[i].flags |= VUNSET | VTEXTFIXED; psh->libpath_vars[i].text = (char*)libpath_envs[i]; } if (find_var(psh, psh->libpath_vars[i].text, &vpp, &psh->libpath_vars[i].name_len) != NULL) continue; psh->libpath_vars[i].next = *vpp; *vpp = &psh->libpath_vars[i]; } ckfree(psh, psz); #endif for (ip = varinit; ip->text; ip++) { vp = (struct var *)((char *)psh + ip->var_off); if (find_var(psh, ip->text, &vpp, &vp->name_len) != NULL) continue; vp->next = *vpp; *vpp = vp; vp->text = sh_strdup(psh, ip->text); vp->flags = ip->flags; vp->func = ip->func; } /* * PS1 depends on uid */ if (find_var(psh, "PS1", &vpp, &psh->vps1.name_len) == NULL) { psh->vps1.next = *vpp; *vpp = &psh->vps1; #ifdef KBUILD_VERSION_MAJOR psh->vps1.text = sh_strdup(psh, sh_geteuid(psh) ? "PS1=kash$ " : "PS1=kash# "); #else psh->vps1.text = sh_strdup(psh, sh_geteuid(psh) ? "PS1=$ " : "PS1=# "); #endif psh->vps1.flags = VSTRFIXED|VTEXTFIXED; } } /* * Safe version of setvar, returns 1 on success 0 on failure. */ int setvarsafe(shinstance *psh, const char *name, const char *val, int flags) { struct jmploc jmploc; struct jmploc *volatile savehandler = psh->handler; int err = 0; #ifdef __GNUC__ (void) &err; #endif if (setjmp(jmploc.loc)) err = 1; else { psh->handler = &jmploc; setvar(psh, name, val, flags); } psh->handler = savehandler; return err; } /* * Set the value of a variable. The flags argument is ored with the * flags of the variable. If val is NULL, the variable is unset. */ void setvar(shinstance *psh, const char *name, const char *val, int flags) { const char *p; const char *q; char *d; size_t len; int namelen; char *nameeq; int isbad; isbad = 0; p = name; if (! is_name(*p)) isbad = 1; p++; for (;;) { if (! is_in_name(*p)) { if (*p == '\0' || *p == '=') break; isbad = 1; } p++; } namelen = (int)(p - name); if (isbad) error(psh, "%.*s: bad variable name", namelen, name); len = namelen + 2; /* 2 is space for '=' and '\0' */ if (val == NULL) { flags |= VUNSET; } else { len += strlen(val); } d = nameeq = ckmalloc(psh, len); q = name; while (--namelen >= 0) *d++ = *q++; *d++ = '='; *d = '\0'; if (val) scopy(val, d); setvareq(psh, nameeq, flags); } /* * Same as setvar except that the variable and value are passed in * the first argument as name=value. Since the first argument will * be actually stored in the table, it should not be a string that * will go away. */ void setvareq(shinstance *psh, char *s, int flags) { struct var *vp, **vpp; int nlen; #if defined(_MSC_VER) || defined(_WIN32) /* On Windows PATH is often spelled 'Path', correct this here. */ if ( s[0] == 'P' && s[1] == 'a' && s[2] == 't' && s[3] == 'h' && (s[4] == '\0' || s[4] == '=') ) { s[1] = 'A'; s[2] = 'T'; s[3] = 'H'; } #endif if (aflag(psh)) flags |= VEXPORT; vp = find_var(psh, s, &vpp, &nlen); if (vp != NULL) { if (vp->flags & VREADONLY) error(psh, "%.*s: is read only", vp->name_len, s); if (flags & VNOSET) return; INTOFF; if (vp->func && (flags & VNOFUNC) == 0) (*vp->func)(psh, s + vp->name_len + 1); if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) ckfree(psh, vp->text); vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); vp->flags |= flags & ~VNOFUNC; vp->text = s; #ifdef PC_OS2_LIBPATHS if ((vp->flags & VOS2LIBPATH) && (vp->flags & VEXPORT)) vp->flags &= ~VEXPORT; #endif /* * We could roll this to a function, to handle it as * a regular variable function callback, but why bother? */ if (vp == &psh->vmpath || (vp == &psh->vmail && ! mpathset(psh))) chkmail(psh, 1); INTON; return; } /* not found */ if (flags & VNOSET) return; vp = ckmalloc(psh, sizeof (*vp)); vp->flags = flags & ~VNOFUNC; vp->text = s; vp->name_len = nlen; vp->next = *vpp; vp->func = NULL; *vpp = vp; } /* * Process a linked list of variable assignments. */ void listsetvar(shinstance *psh, struct strlist *list, int flags) { struct strlist *lp; INTOFF; for (lp = list ; lp ; lp = lp->next) { setvareq(psh, savestr(psh, lp->text), flags); } INTON; } void listmklocal(shinstance *psh, struct strlist *list, int flags) { struct strlist *lp; for (lp = list ; lp ; lp = lp->next) mklocal(psh, lp->text, flags); } /* * Find the value of a variable. Returns NULL if not set. */ char * lookupvar(shinstance *psh, const char *name) { struct var *v; v = find_var(psh, name, NULL, NULL); if (v == NULL || v->flags & VUNSET) return NULL; return v->text + v->name_len + 1; } /* * Search the environment of a builtin command. If the second argument * is nonzero, return the value of a variable even if it hasn't been * exported. */ char * bltinlookup(shinstance *psh, const char *name, int doall) { struct strlist *sp; struct var *v; for (sp = psh->cmdenviron ; sp ; sp = sp->next) { if (strequal(sp->text, name)) return strchr(sp->text, '=') + 1; } v = find_var(psh, name, NULL, NULL); if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT))) return NULL; return v->text + v->name_len + 1; } /* * Generate a list of exported variables. This routine is used to construct * the third argument to execve when executing a program. */ char ** environment(shinstance *psh) { int nenv; struct var **vpp; struct var *vp; char **env; char **ep; nenv = 0; for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) { for (vp = *vpp ; vp ; vp = vp->next) if (vp->flags & VEXPORT) nenv++; } ep = env = stalloc(psh, (nenv + 1) * sizeof *env); for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) { for (vp = *vpp ; vp ; vp = vp->next) if (vp->flags & VEXPORT) *ep++ = vp->text; } *ep = NULL; #ifdef PC_OS2_LIBPATHS /* * Set the libpaths now as this is exec() time. */ for (nenv = 0; nenv < 3; nenv++) DosSetExtLIBPATH(strchr(psh->libpath_vars[nenv].text, '=') + 1, nenv); #endif return env; } /* * Called when a shell procedure is invoked to clear out nonexported * variables. It is also necessary to reallocate variables of with * VSTACK set since these are currently allocated on the stack. */ #ifdef mkinit void shprocvar(shinstance *psh); SHELLPROC { shprocvar(psh); } #endif void shprocvar(shinstance *psh) { struct var **vpp; struct var *vp, **prev; for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) { for (prev = vpp ; (vp = *prev) != NULL ; ) { if ((vp->flags & VEXPORT) == 0) { *prev = vp->next; if ((vp->flags & VTEXTFIXED) == 0) ckfree(psh, vp->text); if ((vp->flags & VSTRFIXED) == 0) ckfree(psh, vp); } else { if (vp->flags & VSTACK) { vp->text = savestr(psh, vp->text); vp->flags &=~ VSTACK; } prev = &vp->next; } } } initvar(psh); } /* * Command to list all variables which are set. Currently this command * is invoked from the set command when the set command is called without * any variables. */ void print_quoted(shinstance *psh, const char *p) { const char *q; if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { out1fmt(psh, "%s", p); return; } while (*p) { if (*p == '\'') { out1fmt(psh, "\\'"); p++; continue; } q = strchr(p, '\''); if (!q) { out1fmt(psh, "'%s'", p ); return; } out1fmt(psh, "'%.*s'", (int)(q - p), p ); p = q; } } static int sort_var(const void *v_v1, const void *v_v2) { const struct var * const *v1 = v_v1; const struct var * const *v2 = v_v2; /* XXX Will anyone notice we include the '=' of the shorter name? */ return strcoll((*v1)->text, (*v2)->text); } /* * POSIX requires that 'set' (but not export or readonly) output the * variables in lexicographic order - by the locale's collating order (sigh). * Maybe we could keep them in an ordered balanced binary tree * instead of hashed lists. * For now just roll 'em through qsort for printing... */ int showvars(shinstance *psh, const char *name, int flag, int show_value) { struct var **vpp; struct var *vp; const char *p; static struct var **list; /* static in case we are interrupted */ static int list_len; int count = 0; if (!list) { list_len = 32; list = ckmalloc(psh, list_len * sizeof(*list)); } for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) { for (vp = *vpp ; vp ; vp = vp->next) { if (flag && !(vp->flags & flag)) continue; if (vp->flags & VUNSET && !(show_value & 2)) continue; if (count >= list_len) { list = ckrealloc(psh, list, (list_len << 1) * sizeof(*list)); list_len <<= 1; } list[count++] = vp; } } qsort(list, count, sizeof(*list), sort_var); for (vpp = list; count--; vpp++) { vp = *vpp; if (name) out1fmt(psh, "%s ", name); for (p = vp->text ; *p != '=' ; p++) out1c(psh, *p); if (!(vp->flags & VUNSET) && show_value) { out1fmt(psh, "="); print_quoted(psh, ++p); } out1c(psh, '\n'); } return 0; } /* * The export and readonly commands. */ int exportcmd(shinstance *psh, int argc, char **argv) { struct var *vp; char *name; const char *p; int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; int pflag; pflag = nextopt(psh, "p") == 'p' ? 3 : 0; if (argc <= 1 || pflag) { showvars(psh, pflag ? argv[0] : 0, flag, pflag ); return 0; } while ((name = *psh->argptr++) != NULL) { if ((p = strchr(name, '=')) != NULL) { p++; } else { vp = find_var(psh, name, NULL, NULL); if (vp != NULL) { vp->flags |= flag; continue; } } setvar(psh, name, p, flag); } return 0; } /* * The "local" command. */ int localcmd(shinstance *psh, int argc, char **argv) { char *name; if (! in_function(psh)) error(psh, "Not in a function"); while ((name = *psh->argptr++) != NULL) { mklocal(psh, name, 0); } return 0; } /* * Make a variable a local variable. When a variable is made local, it's * value and flags are saved in a localvar structure. The saved values * will be restored when the shell function returns. We handle the name * "-" as a special case. */ void mklocal(shinstance *psh, const char *name, int flags) { struct localvar *lvp; struct var **vpp; struct var *vp; INTOFF; lvp = ckmalloc(psh, sizeof (struct localvar)); if (name[0] == '-' && name[1] == '\0') { char *p; p = ckmalloc(psh, sizeof_optlist); lvp->text = memcpy(p, psh->optlist, sizeof_optlist); vp = NULL; } else { vp = find_var(psh, name, &vpp, NULL); if (vp == NULL) { if (strchr(name, '=')) setvareq(psh, savestr(psh, name), VSTRFIXED|flags); else setvar(psh, name, NULL, VSTRFIXED|flags); vp = *vpp; /* the new variable */ lvp->text = NULL; lvp->flags = VUNSET; } else { lvp->text = vp->text; lvp->flags = vp->flags; vp->flags |= VSTRFIXED|VTEXTFIXED; if (name[vp->name_len] == '=') setvareq(psh, savestr(psh, name), flags); } } lvp->vp = vp; lvp->next = psh->localvars; psh->localvars = lvp; INTON; } /* * Called after a function returns. */ void poplocalvars(shinstance *psh) { struct localvar *lvp; struct var *vp; while ((lvp = psh->localvars) != NULL) { psh->localvars = lvp->next; vp = lvp->vp; TRACE((psh, "poplocalvar %s", vp ? vp->text : "-")); if (vp == NULL) { /* $- saved */ memcpy(psh->optlist, lvp->text, sizeof_optlist); ckfree(psh, lvp->text); } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { (void)unsetvar(psh, vp->text, 0); } else { if (vp->func && (vp->flags & VNOFUNC) == 0) (*vp->func)(psh, lvp->text + vp->name_len + 1); if ((vp->flags & VTEXTFIXED) == 0) ckfree(psh, vp->text); vp->flags = lvp->flags; vp->text = lvp->text; } ckfree(psh, lvp); } } int setvarcmd(shinstance *psh, int argc, char **argv) { if (argc <= 2) return unsetcmd(psh, argc, argv); else if (argc == 3) setvar(psh, argv[1], argv[2], 0); else error(psh, "List assignment not implemented"); return 0; } /* * The unset builtin command. We unset the function before we unset the * variable to allow a function to be unset when there is a readonly variable * with the same name. */ int unsetcmd(shinstance *psh, int argc, char **argv) { char **ap; int i; int flg_func = 0; int flg_var = 0; int ret = 0; while ((i = nextopt(psh, "evf")) != '\0') { if (i == 'f') flg_func = 1; else flg_var = i; } if (flg_func == 0 && flg_var == 0) flg_var = 1; for (ap = psh->argptr; *ap ; ap++) { if (flg_func) ret |= unsetfunc(psh, *ap); if (flg_var) ret |= unsetvar(psh, *ap, flg_var == 'e'); } return ret; } /* * Unset the specified variable. */ int unsetvar(shinstance *psh, const char *s, int unexport) { struct var **vpp; struct var *vp; vp = find_var(psh, s, &vpp, NULL); if (vp == NULL) return 1; if (vp->flags & VREADONLY) return (1); INTOFF; if (unexport) { vp->flags &= ~VEXPORT; } else { if (vp->text[vp->name_len + 1] != '\0') setvar(psh, s, nullstr, 0); vp->flags &= ~VEXPORT; vp->flags |= VUNSET; if ((vp->flags & VSTRFIXED) == 0) { if ((vp->flags & VTEXTFIXED) == 0) ckfree(psh, vp->text); *vpp = vp->next; ckfree(psh, vp); } } INTON; return 0; } /* * Returns true if the two strings specify the same varable. The first * variable name is terminated by '='; the second may be terminated by * either '=' or '\0'. */ STATIC int strequal(const char *p, const char *q) { while (*p == *q++) { if (*p++ == '=') return 1; } if (*p == '=' && *(q - 1) == '\0') return 1; return 0; } /* * Search for a variable. * 'name' may be terminated by '=' or a NUL. * vppp is set to the pointer to vp, or the list head if vp isn't found * lenp is set to the number of charactets in 'name' */ STATIC struct var * find_var(shinstance *psh, const char *name, struct var ***vppp, int *lenp) { unsigned int hashval; int len; struct var *vp, **vpp; const char *p = name; hashval = 0; while (*p && *p != '=') hashval = 2 * hashval + (unsigned char)*p++; len = (int)(p - name); if (lenp) *lenp = len; vpp = &psh->vartab[hashval % VTABSIZE]; if (vppp) *vppp = vpp; for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { if (vp->name_len != len) continue; if (memcmp(vp->text, name, len) != 0) continue; if (vppp) *vppp = vpp; return vp; } return NULL; } kbuild-2695/src/kash/mail.h0000644000000000000000000000344012247157307014252 0ustar rootroot/* $NetBSD: mail.h,v 1.10 2003/08/07 09:05:34 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)mail.h 8.2 (Berkeley) 5/4/95 */ void chkmail(struct shinstance *, int); kbuild-2695/src/kash/nodes.c.pat0000644000000000000000000000732312247157307015222 0ustar rootroot/* $NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 */ #include /* * Routine for dealing with parsed shell commands. */ #include "shell.h" #include "nodes.h" #include "memalloc.h" #include "machdep.h" #include "mystring.h" #include "shinstance.h" size_t funcblocksize; /* size of structures in function */ size_t funcstringsize; /* size of strings in node */ pointer funcblock; /* block to allocate function from */ char *funcstring; /* block to allocate strings from */ %SIZES STATIC void calcsize(union node *); STATIC void sizenodelist(struct nodelist *); STATIC union node *copynode(union node *); STATIC struct nodelist *copynodelist(struct nodelist *); STATIC char *nodesavestr(char *); /* * Make a copy of a parse tree. */ union node * copyfunc(psh, n) struct shinstance *psh; union node *n; { if (n == NULL) return NULL; funcblocksize = 0; funcstringsize = 0; calcsize(n); funcblock = ckmalloc(psh, funcblocksize + funcstringsize); funcstring = (char *) funcblock + funcblocksize; return copynode(n); } STATIC void calcsize(n) union node *n; { %CALCSIZE } STATIC void sizenodelist(lp) struct nodelist *lp; { while (lp) { funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); calcsize(lp->n); lp = lp->next; } } STATIC union node * copynode(n) union node *n; { union node *new; %COPY return new; } STATIC struct nodelist * copynodelist(lp) struct nodelist *lp; { struct nodelist *start; struct nodelist **lpp; lpp = &start; while (lp) { *lpp = funcblock; funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); (*lpp)->n = copynode(lp->n); lp = lp->next; lpp = &(*lpp)->next; } *lpp = NULL; return start; } STATIC char * nodesavestr(s) char *s; { register char *p = s; register char *q = funcstring; char *rtn = funcstring; while ((*q++ = *p++) != 0) continue; funcstring = q; return rtn; } /* * Free a parse tree. */ void freefunc(psh, n) shinstance *psh; union node *n; { if (n) ckfree(psh, n); } kbuild-2695/src/kash/tstDump.c0000644000000000000000000000542112247157307014764 0ustar rootroot/* $Id: tstDump.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * tstDump - dump inherited file handle information on Windows. */ /* * Copyright (c) 2010 knut st. osmundsen * * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include int main() { STARTUPINFO Info; GetStartupInfo(&Info); printf("tst: hStdInput =%p / %p\n", Info.hStdInput, GetStdHandle(STD_INPUT_HANDLE)); printf("tst: hStdOutput=%p / %p\n", Info.hStdOutput, GetStdHandle(STD_OUTPUT_HANDLE)); printf("tst: hStdError =%p / %p\n", Info.hStdError, GetStdHandle(STD_ERROR_HANDLE)); printf("tst: cbReserved2=%d (%#x) lpReserved2=%p\n", Info.cbReserved2, Info.cbReserved2, Info.lpReserved2); if (Info.cbReserved2 > sizeof(int) && Info.lpReserved2) { int count = *(int *)Info.lpReserved2; unsigned char *paf = (unsigned char *)Info.lpReserved2 + sizeof(int); HANDLE *pah = (HANDLE *)(paf + count); int i; printf("tst: count=%d\n", count); for (i = 0; i < count; i++) { if (paf[i] == 0 && pah[i] == INVALID_HANDLE_VALUE) continue; printf("tst: #%02d: native=%#p flags=%#x", i, pah[i], paf[i]); if (paf[i] & 0x01) printf(" FOPEN"); if (paf[i] & 0x02) printf(" FEOFLAG"); if (paf[i] & 0x02) printf(" FEOFLAG"); if (paf[i] & 0x04) printf(" FCRLF"); if (paf[i] & 0x08) printf(" FPIPE"); if (paf[i] & 0x10) printf(" FNOINHERIT"); if (paf[i] & 0x20) printf(" FAPPEND"); if (paf[i] & 0x40) printf(" FDEV"); if (paf[i] & 0x80) printf(" FTEXT"); printf("\n"); } } return 0; } kbuild-2695/src/kash/nodetypes0000644000000000000000000001211012247157307015106 0ustar rootroot# $NetBSD: nodetypes,v 1.12 2003/08/22 11:22:23 agc Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)nodetypes 8.2 (Berkeley) 5/4/95 # This file describes the nodes used in parse trees. Unindented lines # contain a node type followed by a structure tag. Subsequent indented # lines specify the fields of the structure. Several node types can share # the same structure, in which case the fields of the structure should be # specified only once. # # A field of a structure is described by the name of the field followed # by a type. The currently implemented types are: # nodeptr - a pointer to a node # nodelist - a pointer to a list of nodes # string - a pointer to a nul terminated string # int - an integer # other - any type that can be copied by assignment # temp - a field that doesn't have to be copied when the node is copied # The last two types should be followed by the text of a C declaration for # the field. NSEMI nbinary # two commands separated by a semicolon type int ch1 nodeptr # the first child ch2 nodeptr # the second child NCMD ncmd # a simple command type int backgnd int # set to run command in background args nodeptr # the arguments redirect nodeptr # list of file redirections NPIPE npipe # a pipeline type int backgnd int # set to run pipeline in background cmdlist nodelist # the commands in the pipeline NREDIR nredir # redirection (of a complex command) type int n nodeptr # the command redirect nodeptr # list of file redirections NBACKGND nredir # run command in background NSUBSHELL nredir # run command in a subshell NAND nbinary # the && operator NOR nbinary # the || operator NIF nif # the if statement. Elif clauses are handled type int # using multiple if nodes. test nodeptr # if test ifpart nodeptr # then ifpart elsepart nodeptr # else elsepart NWHILE nbinary # the while statement. First child is the test NUNTIL nbinary # the until statement NFOR nfor # the for statement type int args nodeptr # for var in args body nodeptr # do body; done var string # the for variable NCASE ncase # a case statement type int expr nodeptr # the word to switch on cases nodeptr # the list of cases (NCLIST nodes) NCLIST nclist # a case type int next nodeptr # the next case in list pattern nodeptr # list of patterns for this case body nodeptr # code to execute for this case NDEFUN narg # define a function. The "next" field contains # the body of the function. NARG narg # represents a word type int next nodeptr # next word in list text string # the text of the word backquote nodelist # list of commands in back quotes NTO nfile # fd> fname NCLOBBER nfile # fd>| fname NFROM nfile # fd< fname NFROMTO nfile # fd<> fname NAPPEND nfile # fd>> fname type int next nodeptr # next redirection in list fd int # file descriptor being redirected fname nodeptr # file name, in a NARG node expfname temp char *expfname # actual file name NTOFD ndup # fd<&dupfd NFROMFD ndup # fd>&dupfd type int next nodeptr # next redirection in list fd int # file descriptor being redirected dupfd int # file descriptor to duplicate vname nodeptr # file name if fd>&$var NHERE nhere # fd<<\! NXHERE nhere # fd< /* * Types of operations (passed to the errmsg routine). */ #define E_OPEN 01 /* opening a file */ #define E_CREAT 02 /* creating a file */ #define E_EXEC 04 /* executing a program */ /* * We enclose jmp_buf in a structure so that we can declare pointers to * jump locations. The global variable handler contains the location to * jump to when an exception occurs, and the global variable exception * contains a code identifying the exeception. To implement nested * exception handlers, the user should save the value of handler on entry * to an inner scope, set handler to point to a jmploc structure for the * inner scope, and restore handler on exit from the scope. */ #ifndef __HAIKU__ # include #else # include /** @todo silly */ #endif struct jmploc { jmp_buf loc; }; /* extern struct jmploc *handler; extern int exception; extern int exerrno;*/ /* error for EXEXEC */ /* exceptions */ #define EXINT 0 /* SIGINT received */ #define EXERROR 1 /* a generic error */ #define EXSHELLPROC 2 /* execute a shell procedure */ #define EXEXEC 3 /* command execution failed */ /* * These macros allow the user to suspend the handling of interrupt signals * over a period of time. This is similar to SIGHOLD to or sigblock, but * much more efficient and portable. (But hacking the kernel is so much * more fun than worrying about efficiency and portability. :-)) */ /*extern volatile int suppressint; extern volatile int intpending;*/ #define INTOFF psh->suppressint++ #define INTON { if (--psh->suppressint == 0 && psh->intpending) onint(psh); } #define FORCEINTON {psh->suppressint = 0; if (psh->intpending) onint(psh);} #define CLEAR_PENDING_INT psh->intpending = 0 #define int_pending() psh->intpending #if !defined(__GNUC__) && !defined(__attribute__) # define __attribute__(a) #endif SH_NORETURN_1 void exraise(struct shinstance *, int) SH_NORETURN_2; void onint(struct shinstance *); SH_NORETURN_1 void error(struct shinstance *, const char *, ...) SH_NORETURN_2; SH_NORETURN_1 void exerror(struct shinstance *, int, const char *, ...) SH_NORETURN_2; const char *errmsg(struct shinstance *, int, int); SH_NORETURN_1 void sh_err(struct shinstance *, int, const char *, ...) SH_NORETURN_2; SH_NORETURN_1 void sh_verr(struct shinstance *, int, const char *, va_list) SH_NORETURN_2; SH_NORETURN_1 void sh_errx(struct shinstance *, int, const char *, ...) SH_NORETURN_2; SH_NORETURN_1 void sh_verrx(struct shinstance *, int, const char *, va_list) SH_NORETURN_2; void sh_warn(struct shinstance *, const char *, ...); void sh_vwarn(struct shinstance *, const char *, va_list); void sh_warnx(struct shinstance *, const char *, ...); void sh_vwarnx(struct shinstance *, const char *, va_list); SH_NORETURN_1 void sh_exit(struct shinstance *, int) SH_NORETURN_2; /* * BSD setjmp saves the signal mask, which violates ANSI C and takes time, * so we use _setjmp instead. */ #if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__) \ && !defined(__KLIBC__) && !defined(_MSC_VER) && !defined(__HAIKU__) #define setjmp(jmploc) _setjmp(jmploc) #define longjmp(jmploc, val) _longjmp(jmploc, val) #endif #endif kbuild-2695/src/kash/mkbuiltins0000755000000000000000000000634612247157307015276 0ustar rootroot#!/bin/sh - # $NetBSD: mkbuiltins,v 1.21 2004/06/06 07:03:11 christos Exp $ # # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # # This code is derived from software contributed to Berkeley by # Kenneth Almquist. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # @(#)mkbuiltins 8.2 (Berkeley) 5/4/95 havehist=1 if [ "X$1" = "X-h" ]; then havehist=0 shift fi shell=$1 builtins=$2 objdir=$3 havejobs=0 if grep '^#define JOBS[ ]*1' ${shell} > /dev/null then havejobs=1 fi exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h echo '/* * This file was generated by the mkbuiltins program. */ #include "shell.h" #include "builtins.h" const struct builtincmd builtincmd[] = { ' >&3 echo '/* * This file was generated by the mkbuiltins program. */ #include "shtypes.h" struct builtincmd { const char *name; int (*builtin)(shinstance *, int, char **); }; extern const struct builtincmd builtincmd[]; extern const struct builtincmd splbltincmd[]; ' >&4 specials= while read line do set -- $line [ -z "$1" ] && continue case "$1" in \#if*|\#def*|\#end*) echo $line >&3 echo $line >&4 continue ;; esac l1="${line###}" [ "$l1" != "$line" ] && continue func=$1 shift [ x"$1" = x'-j' ] && { [ $havejobs = 0 ] && continue shift } [ x"$1" = x'-h' ] && { [ $havehist = 0 ] && continue shift } echo 'int '"$func"'(shinstance *, int, char **);' >&4 while [ $# != 0 -a "$1" != '#' ] do [ "$1" = '-s' ] && { specials="$specials $2 $func" shift 2 continue; } [ "$1" = '-u' ] && shift echo ' { "'$1'", '"$func"' },' >&3 shift done done echo ' { 0, 0 },' >&3 echo '};' >&3 echo >&3 echo 'const struct builtincmd splbltincmd[] = {' >&3 set -- $specials while [ $# != 0 ] do echo ' { "'$1'", '"$2"' },' >&3 shift 2 done echo ' { 0, 0 },' >&3 echo "};" >&3 kbuild-2695/src/kash/strlcpy.c0000644000000000000000000000501012247157307015016 0ustar rootroot/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $"); #include //__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.7 2003/05/01 19:03:14 nectar Exp $"); #endif /* LIBC_SCCS and not lint */ #endif #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } kbuild-2695/src/kash/eval.c0000644000000000000000000007232412247157307014261 0ustar rootroot/* $NetBSD: eval.c,v 1.84 2005/06/23 23:05:29 christos Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; #else __RCSID("$NetBSD: eval.c,v 1.84 2005/06/23 23:05:29 christos Exp $"); #endif /* not lint */ #endif #include #include #include #ifdef HAVE_SYSCTL_H # ifdef __OpenBSD__ /* joyful crap */ # include # undef psh # endif # include #endif /* * Evaluate a command. */ #include "shell.h" #include "nodes.h" #include "syntax.h" #include "expand.h" #include "parser.h" #include "jobs.h" #include "eval.h" #include "builtins.h" #include "options.h" #include "exec.h" #include "redir.h" #include "input.h" #include "output.h" #include "trap.h" #include "var.h" #include "memalloc.h" #include "error.h" #include "show.h" #include "mystring.h" #include "main.h" #ifndef SMALL # include "myhistedit.h" #endif #include "shinstance.h" /* flags in argument to evaltree */ #define EV_EXIT 01 /* exit after evaluating tree */ #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ #define EV_BACKCMD 04 /* command executing within back quotes */ /*int evalskip;*/ /* set if we are skipping commands */ /*STATIC int skipcount;*/ /* number of levels to skip */ /*MKINIT int loopnest;*/ /* current loop nesting level */ /*int funcnest;*/ /* depth of function calls */ /*char *commandname;*/ /*struct strlist *cmdenviron;*/ /*int exitstatus;*/ /* exit status of last command */ /*int back_exitstatus;*/ /* exit status of backquoted command */ STATIC void evalloop(shinstance *, union node *, int); STATIC void evalfor(shinstance *, union node *, int); STATIC void evalcase(shinstance *, union node *, int); STATIC void evalsubshell(shinstance *, union node *, int); STATIC void expredir(shinstance *, union node *); STATIC void evalpipe(shinstance *, union node *); STATIC void evalcommand(shinstance *, union node *, int, struct backcmd *); STATIC void prehash(shinstance *, union node *); /* * Called to reset things after an exception. */ #ifdef mkinit INCLUDE "eval.h" RESET { psh->evalskip = 0; psh->loopnest = 0; psh->funcnest = 0; } SHELLPROC { psh->exitstatus = 0; } #endif static int sh_pipe(shinstance *psh, int fds[2]) { int nfd; if (shfile_pipe(&psh->fdtab, fds)) return -1; if (fds[0] < 3) { nfd = shfile_fcntl(&psh->fdtab, fds[0], F_DUPFD, 3); if (nfd != -1) { shfile_close(&psh->fdtab, fds[0]); fds[0] = nfd; } } if (fds[1] < 3) { nfd = shfile_fcntl(&psh->fdtab, fds[1], F_DUPFD, 3); if (nfd != -1) { shfile_close(&psh->fdtab, fds[1]); fds[1] = nfd; } } return 0; } /* * The eval commmand. */ int evalcmd(shinstance *psh, int argc, char **argv) { char *p; char *concat; char **ap; if (argc > 1) { p = argv[1]; if (argc > 2) { STARTSTACKSTR(psh, concat); ap = argv + 2; for (;;) { while (*p) STPUTC(psh, *p++, concat); if ((p = *ap++) == NULL) break; STPUTC(psh, ' ', concat); } STPUTC(psh, '\0', concat); p = grabstackstr(psh, concat); } evalstring(psh, p, EV_TESTED); } return psh->exitstatus; } /* * Execute a command or commands contained in a string. */ void evalstring(shinstance *psh, char *s, int flag) { union node *n; struct stackmark smark; setstackmark(psh, &smark); setinputstring(psh, s, 1); while ((n = parsecmd(psh, 0)) != NEOF) { evaltree(psh, n, flag); popstackmark(psh, &smark); } popfile(psh); popstackmark(psh, &smark); } /* * Evaluate a parse tree. The value is left in the global variable * exitstatus. */ void evaltree(shinstance *psh, union node *n, int flags) { if (n == NULL) { TRACE((psh, "evaltree(NULL) called\n")); psh->exitstatus = 0; goto out; } #ifndef SMALL psh->displayhist = 1; /* show history substitutions done with fc */ #endif TRACE((psh, "pid %d, evaltree(%p: %d, %d) called\n", sh_getpid(psh), n, n->type, flags)); switch (n->type) { case NSEMI: evaltree(psh, n->nbinary.ch1, flags & EV_TESTED); if (psh->evalskip) goto out; evaltree(psh, n->nbinary.ch2, flags); break; case NAND: evaltree(psh, n->nbinary.ch1, EV_TESTED); if (psh->evalskip || psh->exitstatus != 0) goto out; evaltree(psh, n->nbinary.ch2, flags); break; case NOR: evaltree(psh, n->nbinary.ch1, EV_TESTED); if (psh->evalskip || psh->exitstatus == 0) goto out; evaltree(psh, n->nbinary.ch2, flags); break; case NREDIR: expredir(psh, n->nredir.redirect); redirect(psh, n->nredir.redirect, REDIR_PUSH); evaltree(psh, n->nredir.n, flags); popredir(psh); break; case NSUBSHELL: evalsubshell(psh, n, flags); break; case NBACKGND: evalsubshell(psh, n, flags); break; case NIF: { evaltree(psh, n->nif.test, EV_TESTED); if (psh->evalskip) goto out; if (psh->exitstatus == 0) evaltree(psh, n->nif.ifpart, flags); else if (n->nif.elsepart) evaltree(psh, n->nif.elsepart, flags); else psh->exitstatus = 0; break; } case NWHILE: case NUNTIL: evalloop(psh, n, flags); break; case NFOR: evalfor(psh, n, flags); break; case NCASE: evalcase(psh, n, flags); break; case NDEFUN: defun(psh, n->narg.text, n->narg.next); psh->exitstatus = 0; break; case NNOT: evaltree(psh, n->nnot.com, EV_TESTED); psh->exitstatus = !psh->exitstatus; break; case NPIPE: evalpipe(psh, n); break; case NCMD: evalcommand(psh, n, flags, (struct backcmd *)NULL); break; default: out1fmt(psh, "Node type = %d\n", n->type); flushout(&psh->output); break; } out: if (psh->pendingsigs) dotrap(psh); if ((flags & EV_EXIT) != 0) exitshell(psh, psh->exitstatus); } STATIC void evalloop(shinstance *psh, union node *n, int flags) { int status; psh->loopnest++; status = 0; for (;;) { evaltree(psh, n->nbinary.ch1, EV_TESTED); if (psh->evalskip) { skipping: if (psh->evalskip == SKIPCONT && --psh->skipcount <= 0) { psh->evalskip = 0; continue; } if (psh->evalskip == SKIPBREAK && --psh->skipcount <= 0) psh->evalskip = 0; break; } if (n->type == NWHILE) { if (psh->exitstatus != 0) break; } else { if (psh->exitstatus == 0) break; } evaltree(psh, n->nbinary.ch2, flags & EV_TESTED); status = psh->exitstatus; if (psh->evalskip) goto skipping; } psh->loopnest--; psh->exitstatus = status; } STATIC void evalfor(shinstance *psh, union node *n, int flags) { struct arglist arglist; union node *argp; struct strlist *sp; struct stackmark smark; int status = 0; setstackmark(psh, &smark); arglist.lastp = &arglist.list; for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE); if (psh->evalskip) goto out; } *arglist.lastp = NULL; psh->loopnest++; for (sp = arglist.list ; sp ; sp = sp->next) { setvar(psh, n->nfor.var, sp->text, 0); evaltree(psh, n->nfor.body, flags & EV_TESTED); status = psh->exitstatus; if (psh->evalskip) { if (psh->evalskip == SKIPCONT && --psh->skipcount <= 0) { psh->evalskip = 0; continue; } if (psh->evalskip == SKIPBREAK && --psh->skipcount <= 0) psh->evalskip = 0; break; } } psh->loopnest--; psh->exitstatus = status; out: popstackmark(psh, &smark); } STATIC void evalcase(shinstance *psh, union node *n, int flags) { union node *cp; union node *patp; struct arglist arglist; struct stackmark smark; int status = 0; setstackmark(psh, &smark); arglist.lastp = &arglist.list; expandarg(psh, n->ncase.expr, &arglist, EXP_TILDE); for (cp = n->ncase.cases ; cp && psh->evalskip == 0 ; cp = cp->nclist.next) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { if (casematch(psh, patp, arglist.list->text)) { if (psh->evalskip == 0) { evaltree(psh, cp->nclist.body, flags); status = psh->exitstatus; } goto out; } } } out: psh->exitstatus = status; popstackmark(psh, &smark); } /* * Kick off a subshell to evaluate a tree. */ STATIC void evalsubshell(shinstance *psh, union node *n, int flags) { struct job *jp; int backgnd = (n->type == NBACKGND); expredir(psh, n->nredir.redirect); INTOFF; jp = makejob(psh, n, 1); if (forkshell(psh, jp, n, backgnd ? FORK_BG : FORK_FG) == 0) { INTON; if (backgnd) flags &=~ EV_TESTED; redirect(psh, n->nredir.redirect, 0); /* never returns */ evaltree(psh, n->nredir.n, flags | EV_EXIT); } if (! backgnd) psh->exitstatus = waitforjob(psh, jp); INTON; } /* * Compute the names of the files in a redirection list. */ STATIC void expredir(shinstance *psh, union node *n) { union node *redir; for (redir = n ; redir ; redir = redir->nfile.next) { struct arglist fn; fn.lastp = &fn.list; switch (redir->type) { case NFROMTO: case NFROM: case NTO: case NCLOBBER: case NAPPEND: expandarg(psh, redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); redir->nfile.expfname = fn.list->text; break; case NFROMFD: case NTOFD: if (redir->ndup.vname) { expandarg(psh, redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); fixredir(psh, redir, fn.list->text, 1); } break; } } } /* * Evaluate a pipeline. All the processes in the pipeline are children * of the process creating the pipeline. (This differs from some versions * of the shell, which make the last process in a pipeline the parent * of all the rest.) */ STATIC void evalpipe(shinstance *psh, union node *n) { struct job *jp; struct nodelist *lp; int pipelen; int prevfd; int pip[2]; TRACE((psh, "evalpipe(0x%lx) called\n", (long)n)); pipelen = 0; for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) pipelen++; INTOFF; jp = makejob(psh, n, pipelen); prevfd = -1; for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { prehash(psh, lp->n); pip[1] = -1; if (lp->next) { if (sh_pipe(psh, pip) < 0) { shfile_close(&psh->fdtab, prevfd); error(psh, "Pipe call failed"); } } if (forkshell(psh, jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) { INTON; if (prevfd > 0) { movefd(psh, prevfd, 0); } if (pip[1] >= 0) { shfile_close(&psh->fdtab, pip[0]); if (pip[1] != 1) { movefd(psh, pip[1], 1); } } evaltree(psh, lp->n, EV_EXIT); } if (prevfd >= 0) shfile_close(&psh->fdtab, prevfd); prevfd = pip[0]; shfile_close(&psh->fdtab, pip[1]); } if (n->npipe.backgnd == 0) { psh->exitstatus = waitforjob(psh, jp); TRACE((psh, "evalpipe: job done exit status %d\n", psh->exitstatus)); } INTON; } /* * Execute a command inside back quotes. If it's a builtin command, we * want to save its output in a block obtained from malloc. Otherwise * we fork off a subprocess and get the output of the command via a pipe. * Should be called with interrupts off. */ void evalbackcmd(shinstance *psh, union node *n, struct backcmd *result) { int pip[2]; struct job *jp; struct stackmark smark; /* unnecessary */ setstackmark(psh, &smark); result->fd = -1; result->buf = NULL; result->nleft = 0; result->jp = NULL; if (n == NULL) { goto out; } #ifdef notyet /* * For now we disable executing builtins in the same * context as the shell, because we are not keeping * enough state to recover from changes that are * supposed only to affect subshells. eg. echo "`cd /`" */ if (n->type == NCMD) { psh->exitstatus = opsh->exitstatus; evalcommand(psh, n, EV_BACKCMD, result); } else #endif { INTOFF; if (sh_pipe(psh, pip) < 0) error(psh, "Pipe call failed"); jp = makejob(psh, n, 1); if (forkshell(psh, jp, n, FORK_NOJOB) == 0) { FORCEINTON; shfile_close(&psh->fdtab, pip[0]); if (pip[1] != 1) { movefd(psh, pip[1], 1); } eflag(psh) = 0; evaltree(psh, n, EV_EXIT); /* NOTREACHED */ } shfile_close(&psh->fdtab, pip[1]); result->fd = pip[0]; result->jp = jp; INTON; } out: popstackmark(psh, &smark); TRACE((psh, "evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", result->fd, result->buf, result->nleft, result->jp)); } static const char * syspath(shinstance *psh) { #ifdef CTL_USER static char *sys_path = NULL; static int mib[] = {CTL_USER, USER_CS_PATH}; #endif #ifdef PC_PATH_SEP static char def_path[] = "PATH=/usr/bin;/bin;/usr/sbin;/sbin"; #else static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; #endif #ifdef CTL_USER size_t len; if (sys_path == NULL) { if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && (sys_path = ckmalloc(psh, len + 5)) != NULL && sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { memcpy(sys_path, "PATH=", 5); } else { ckfree(psh, sys_path); /* something to keep things happy */ sys_path = def_path; } } return sys_path; #else return def_path; #endif } static int parse_command_args(shinstance *psh, int argc, char **argv, int *use_syspath) { int sv_argc = argc; char *cp, c; *use_syspath = 0; for (;;) { argv++; if (--argc == 0) break; cp = *argv; if (*cp++ != '-') break; if (*cp == '-' && cp[1] == 0) { argv++; argc--; break; } while ((c = *cp++)) { switch (c) { case 'p': *use_syspath = 1; break; default: /* run 'typecmd' for other options */ return 0; } } } return sv_argc - argc; } /*int vforked = 0;*/ /* * Execute a simple command. */ STATIC void evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd) { struct stackmark smark; union node *argp; struct arglist arglist; struct arglist varlist; char **argv; int argc; char **envp; int numvars; struct strlist *sp; int mode; int pip[2]; struct cmdentry cmdentry; struct job *jp; struct jmploc jmploc; struct jmploc *volatile savehandler; char *volatile savecmdname; volatile struct shparam saveparam; struct localvar *volatile savelocalvars; volatile int e; char *lastarg; const char *path = pathval(psh); volatile int temp_path; #if __GNUC__ /* Avoid longjmp clobbering */ (void) &argv; (void) &argc; (void) &lastarg; (void) &flags; #endif psh->vforked = 0; /* First expand the arguments. */ TRACE((psh, "evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); setstackmark(psh, &smark); psh->back_exitstatus = 0; arglist.lastp = &arglist.list; /* Expand arguments, ignoring the initial 'name=value' ones */ for (argp = cmd->ncmd.args, numvars = 0 ; argp ; argp = argp->narg.next, numvars++) { char *p = argp->narg.text; char ch = *p; if (is_name(ch)) { do ch = *++p; while (is_in_name(ch)); if (ch == '=') continue; } break; } for (/*continue on argp from above. */ ; argp ; argp = argp->narg.next) expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE); *arglist.lastp = NULL; expredir(psh, cmd->ncmd.redirect); /* Now do the initial 'name=value' ones we skipped above */ varlist.lastp = &varlist.list; for (argp = cmd->ncmd.args ; numvars > 0 && argp ; argp = argp->narg.next, numvars--) expandarg(psh, argp, &varlist, EXP_VARTILDE); *varlist.lastp = NULL; argc = 0; for (sp = arglist.list ; sp ; sp = sp->next) argc++; argv = stalloc(psh, sizeof (char *) * (argc + 1)); for (sp = arglist.list ; sp ; sp = sp->next) { TRACE((psh, "evalcommand arg: %s\n", sp->text)); *argv++ = sp->text; } *argv = NULL; lastarg = NULL; if (iflag(psh) && psh->funcnest == 0 && argc > 0) lastarg = argv[-1]; argv -= argc; /* Print the command if xflag is set. */ if (xflag(psh)) { char sep = 0; out2str(psh, ps4val(psh)); for (sp = varlist.list ; sp ; sp = sp->next) { if (sep != 0) outc(sep, &psh->errout); out2str(psh, sp->text); sep = ' '; } for (sp = arglist.list ; sp ; sp = sp->next) { if (sep != 0) outc(sep, &psh->errout); out2str(psh, sp->text); sep = ' '; } outc('\n', &psh->errout); flushout(&psh->errout); } /* Now locate the command. */ if (argc == 0) { cmdentry.cmdtype = CMDSPLBLTIN; cmdentry.u.bltin = bltincmd; } else { static const char PATH[] = "PATH="; int cmd_flags = DO_ERR; /* * Modify the command lookup path, if a PATH= assignment * is present */ for (sp = varlist.list; sp; sp = sp->next) if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) path = sp->text + sizeof(PATH) - 1; do { int argsused, use_syspath; find_command(psh, argv[0], &cmdentry, cmd_flags, path); if (cmdentry.cmdtype == CMDUNKNOWN) { psh->exitstatus = 127; flushout(&psh->errout); goto out; } /* implement the 'command' builtin here */ if (cmdentry.cmdtype != CMDBUILTIN || cmdentry.u.bltin != bltincmd) break; cmd_flags |= DO_NOFUNC; argsused = parse_command_args(psh, argc, argv, &use_syspath); if (argsused == 0) { /* use 'type' builting to display info */ cmdentry.u.bltin = typecmd; break; } argc -= argsused; argv += argsused; if (use_syspath) path = syspath(psh) + 5; } while (argc != 0); if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC) /* posix mandates that 'command ' act as if was a normal builtin */ cmdentry.cmdtype = CMDBUILTIN; } /* Fork off a child process if necessary. */ if (cmd->ncmd.backgnd || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) || ((flags & EV_BACKCMD) != 0 && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN) || cmdentry.u.bltin == dotcmd || cmdentry.u.bltin == evalcmd))) { INTOFF; jp = makejob(psh, cmd, 1); mode = cmd->ncmd.backgnd; if (flags & EV_BACKCMD) { mode = FORK_NOJOB; if (sh_pipe(psh, pip) < 0) error(psh, "Pipe call failed"); } #ifdef DO_SHAREDVFORK /* It is essential that if DO_SHAREDVFORK is defined that the * child's address space is actually shared with the parent as * we rely on this. */ if (cmdentry.cmdtype == CMDNORMAL) { pid_t pid; savelocalvars = psh->localvars; psh->localvars = NULL; psh->vforked = 1; switch (pid = vfork()) { case -1: TRACE((psh, "Vfork failed, errno=%d\n", errno)); INTON; error(psh, "Cannot vfork"); break; case 0: /* Make sure that exceptions only unwind to * after the vfork(2) */ if (setjmp(jmploc.loc)) { if (psh->exception == EXSHELLPROC) { /* We can't progress with the vfork, * so, set vforked = 2 so the parent * knows, and _exit(); */ psh->vforked = 2; sh__exit(psh, 0); } else { sh__exit(psh, psh->exerrno); } } savehandler = psh->handler; psh->handler = &jmploc; listmklocal(psh, varlist.list, VEXPORT | VNOFUNC); forkchild(psh, jp, cmd, mode, psh->vforked); break; default: psh->handler = savehandler; /* restore from vfork(2) */ poplocalvars(psh); psh->localvars = savelocalvars; if (psh->vforked == 2) { psh->vforked = 0; (void)sh_waitpid(psh, pid, NULL, 0); /* We need to progress in a normal fork fashion */ goto normal_fork; } psh->vforked = 0; forkparent(psh, jp, cmd, mode, pid); goto parent; } } else { normal_fork: #endif if (forkshell(psh, jp, cmd, mode) != 0) goto parent; /* at end of routine */ FORCEINTON; #ifdef DO_SHAREDVFORK } #endif if (flags & EV_BACKCMD) { if (!psh->vforked) { FORCEINTON; } shfile_close(&psh->fdtab, pip[0]); if (pip[1] != 1) { movefd(psh, pip[1], 1); } } flags |= EV_EXIT; } /* This is the child process if a fork occurred. */ /* Execute the command. */ switch (cmdentry.cmdtype) { case CMDFUNCTION: #ifdef DEBUG trputs(psh, "Shell function: "); trargs(psh, argv); #endif redirect(psh, cmd->ncmd.redirect, REDIR_PUSH); saveparam = psh->shellparam; psh->shellparam.malloc = 0; psh->shellparam.reset = 1; psh->shellparam.nparam = argc - 1; psh->shellparam.p = argv + 1; psh->shellparam.optnext = NULL; INTOFF; savelocalvars = psh->localvars; psh->localvars = NULL; INTON; if (setjmp(jmploc.loc)) { if (psh->exception == EXSHELLPROC) { freeparam(psh, (volatile struct shparam *) &saveparam); } else { freeparam(psh, &psh->shellparam); psh->shellparam = saveparam; } poplocalvars(psh); psh->localvars = savelocalvars; psh->handler = savehandler; longjmp(psh->handler->loc, 1); } savehandler = psh->handler; psh->handler = &jmploc; listmklocal(psh, varlist.list, 0); /* stop shell blowing its stack */ if (++psh->funcnest > 1000) error(psh, "too many nested function calls"); evaltree(psh, cmdentry.u.func, flags & EV_TESTED); psh->funcnest--; INTOFF; poplocalvars(psh); psh->localvars = savelocalvars; freeparam(psh, &psh->shellparam); psh->shellparam = saveparam; psh->handler = savehandler; popredir(psh); INTON; if (psh->evalskip == SKIPFUNC) { psh->evalskip = 0; psh->skipcount = 0; } if (flags & EV_EXIT) exitshell(psh, psh->exitstatus); break; case CMDBUILTIN: case CMDSPLBLTIN: #ifdef DEBUG trputs(psh, "builtin command: "); trargs(psh, argv); #endif mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH; if (flags == EV_BACKCMD) { psh->memout.nleft = 0; psh->memout.nextc = psh->memout.buf; psh->memout.bufsize = 64; mode |= REDIR_BACKQ; } e = -1; savehandler = psh->handler; savecmdname = psh->commandname; psh->handler = &jmploc; if (!setjmp(jmploc.loc)) { /* We need to ensure the command hash table isn't * corruped by temporary PATH assignments. * However we must ensure the 'local' command works! */ if (path != pathval(psh) && (cmdentry.u.bltin == hashcmd || cmdentry.u.bltin == typecmd)) { savelocalvars = psh->localvars; psh->localvars = 0; mklocal(psh, path - 5 /* PATH= */, 0); temp_path = 1; } else temp_path = 0; redirect(psh, cmd->ncmd.redirect, mode); /* exec is a special builtin, but needs this list... */ psh->cmdenviron = varlist.list; /* we must check 'readonly' flag for all builtins */ listsetvar(psh, varlist.list, cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET); psh->commandname = argv[0]; /* initialize nextopt */ psh->argptr = argv + 1; psh->optptr = NULL; /* and getopt */ #if 0 /** @todo fix getop usage! */ #if defined(__FreeBSD__) || defined(__EMX__) || defined(__APPLE__) optreset = 1; optind = 1; #else optind = 0; /* init */ #endif #endif psh->exitstatus = cmdentry.u.bltin(psh, argc, argv); } else { e = psh->exception; psh->exitstatus = e == EXINT ? SIGINT + 128 : e == EXEXEC ? psh->exerrno : 2; } psh->handler = savehandler; output_flushall(psh); psh->out1 = &psh->output; psh->out2 = &psh->errout; freestdout(psh); if (temp_path) { poplocalvars(psh); psh->localvars = savelocalvars; } psh->cmdenviron = NULL; if (e != EXSHELLPROC) { psh->commandname = savecmdname; if (flags & EV_EXIT) exitshell(psh, psh->exitstatus); } if (e != -1) { if ((e != EXERROR && e != EXEXEC) || cmdentry.cmdtype == CMDSPLBLTIN) exraise(psh, e); FORCEINTON; } if (cmdentry.u.bltin != execcmd) popredir(psh); if (flags == EV_BACKCMD) { backcmd->buf = psh->memout.buf; backcmd->nleft = (int)(psh->memout.nextc - psh->memout.buf); psh->memout.buf = NULL; } break; default: #ifdef DEBUG trputs(psh, "normal command: "); trargs(psh, argv); #endif clearredir(psh, psh->vforked); redirect(psh, cmd->ncmd.redirect, psh->vforked ? REDIR_VFORK : 0); if (!psh->vforked) for (sp = varlist.list ; sp ; sp = sp->next) setvareq(psh, sp->text, VEXPORT|VSTACK); envp = environment(psh); shellexec(psh, argv, envp, path, cmdentry.u.index, psh->vforked); break; } goto out; parent: /* parent process gets here (if we forked) */ if (mode == FORK_FG) { /* argument to fork */ psh->exitstatus = waitforjob(psh, jp); } else if (mode == FORK_NOJOB) { backcmd->fd = pip[0]; shfile_close(&psh->fdtab, pip[1]); backcmd->jp = jp; } FORCEINTON; out: if (lastarg) /* dsl: I think this is intended to be used to support * '_' in 'vi' command mode during line editing... * However I implemented that within libedit itself. */ setvar(psh, "_", lastarg, 0); popstackmark(psh, &smark); if (eflag(psh) && psh->exitstatus && !(flags & EV_TESTED)) exitshell(psh, psh->exitstatus); } /* * Search for a command. This is called before we fork so that the * location of the command will be available in the parent as well as * the child. The check for "goodname" is an overly conservative * check that the name will not be subject to expansion. */ STATIC void prehash(shinstance *psh, union node *n) { struct cmdentry entry; if (n->type == NCMD && n->ncmd.args) if (goodname(n->ncmd.args->narg.text)) find_command(psh, n->ncmd.args->narg.text, &entry, 0, pathval(psh)); } /* * Builtin commands. Builtin commands whose functions are closely * tied to evaluation are implemented here. */ /* * No command given. */ int bltincmd(shinstance *psh, int argc, char **argv) { /* * Preserve psh->exitstatus of a previous possible redirection * as POSIX mandates */ return psh->back_exitstatus; } /* * Handle break and continue commands. Break, continue, and return are * all handled by setting the psh->evalskip flag. The evaluation routines * above all check this flag, and if it is set they start skipping * commands rather than executing them. The variable skipcount is * the number of loops to break/continue, or the number of function * levels to return. (The latter is always 1.) It should probably * be an error to break out of more loops than exist, but it isn't * in the standard shell so we don't make it one here. */ int breakcmd(shinstance *psh, int argc, char **argv) { int n = argc > 1 ? number(psh, argv[1]) : 1; if (n > psh->loopnest) n = psh->loopnest; if (n > 0) { psh->evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; psh->skipcount = n; } return 0; } /* * The return command. */ int returncmd(shinstance *psh, int argc, char **argv) { #if 0 int ret = argc > 1 ? number(psh, argv[1]) : psh->exitstatus; #else int ret; if (argc > 1) { /* make return -1 and VSC lite work ... */ if (argv[1][0] != '-' || !is_number(&argv[1][1])) ret = number(psh, argv[1]); else ret = -number(psh, &argv[1][1]) & 255; /* take the bash approach */ } else { ret = psh->exitstatus; } #endif if (psh->funcnest) { psh->evalskip = SKIPFUNC; psh->skipcount = 1; return ret; } else { /* Do what ksh does; skip the rest of the file */ psh->evalskip = SKIPFILE; psh->skipcount = 1; return ret; } } int falsecmd(shinstance *psh, int argc, char **argv) { return 1; } int truecmd(shinstance *psh, int argc, char **argv) { return 0; } int execcmd(shinstance *psh, int argc, char **argv) { if (argc > 1) { struct strlist *sp; iflag(psh) = 0; /* exit on error */ mflag(psh) = 0; optschanged(psh); for (sp = psh->cmdenviron; sp; sp = sp->next) setvareq(psh, sp->text, VEXPORT|VSTACK); shellexec(psh, argv + 1, environment(psh), pathval(psh), 0, 0); } return 0; } static int conv_time(clock_t ticks, char *seconds, size_t l) { static clock_t tpm = 0; clock_t mins; size_t i; if (!tpm) tpm = /*sysconf(_SC_CLK_TCK)*/sh_sysconf_clk_tck() * 60; mins = ticks / tpm; #ifdef _MSC_VER { char tmp[64]; sprintf(tmp, "%.4f", (ticks - mins * tpm) * 60.0 / tpm); strlcpy(seconds, tmp, l); } #else snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm ); #endif if (seconds[0] == '6' && seconds[1] == '0') { /* 59.99995 got rounded up... */ mins++; strlcpy(seconds, "0.0", l); return mins; } /* suppress trailing zeros */ i = strlen(seconds) - 1; for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--) seconds[i] = 0; return mins; } int timescmd(shinstance *psh, int argc, char **argv) { shtms tms; int u, s, cu, cs; char us[8], ss[8], cus[8], css[8]; nextopt(psh, ""); sh_times(psh, &tms); u = conv_time(tms.tms_utime, us, sizeof(us)); s = conv_time(tms.tms_stime, ss, sizeof(ss)); cu = conv_time(tms.tms_cutime, cus, sizeof(cus)); cs = conv_time(tms.tms_cstime, css, sizeof(css)); outfmt(psh->out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n", u, us, s, ss, cu, cus, cs, css); return 0; } kbuild-2695/src/kash/histedit.c0000644000000000000000000002754712247157307015156 0ustar rootroot/* $NetBSD: histedit.c,v 1.36 2005/05/09 11:35:19 christos Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: histedit.c,v 1.36 2005/05/09 11:35:19 christos Exp $"); #endif /* not lint */ #endif #include #include /* * Editline and history functions (and glue). */ #include "shell.h" #include "parser.h" #include "var.h" #include "options.h" #include "main.h" #include "output.h" #include "mystring.h" #include "myhistedit.h" #include "error.h" #ifndef SMALL #include "eval.h" #include "memalloc.h" #define MAXHISTLOOPS 4 /* max recursions through fc */ #define DEFEDITOR "ed" /* default editor *should* be $EDITOR */ History *hist; /* history cookie */ EditLine *el; /* editline cookie */ int displayhist; static FILE *el_in, *el_out; unsigned char _el_fn_complete(EditLine *, int); STATIC const char *fc_replace(const char *, char *, char *); #ifdef DEBUG extern FILE *tracefile; #endif /* * Set history and editing status. Called whenever the status may * have changed (figures out what to do). */ void histedit(void) { FILE *el_err; #define editing (Eflag(psh) || Vflag(psh)) if (iflag(psh)) { if (!hist) { /* * turn history on */ INTOFF; hist = history_init(); INTON; if (hist != NULL) sethistsize(histsizeval()); else out2str(psh, "sh: can't initialize history\n"); } if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ /* * turn editing on */ char *term, *shname; INTOFF; if (el_in == NULL) el_in = fdopen(0, "r"); if (el_out == NULL) el_out = fdopen(2, "w"); if (el_in == NULL || el_out == NULL) goto bad; el_err = el_out; #if DEBUG if (tracefile) el_err = tracefile; #endif term = lookupvar(psh, "TERM"); if (term) setenv("TERM", term, 1); else unsetenv("TERM"); shname = psh->arg0; if (shname[0] == '-') shname++; el = el_init(shname, el_in, el_out, el_err); if (el != NULL) { if (hist) el_set(el, EL_HIST, history, hist); el_set(el, EL_PROMPT, getprompt); el_set(el, EL_SIGNAL, 1); el_set(el, EL_ADDFN, "rl-complete", "ReadLine compatible completion function", _el_fn_complete); } else { bad: out2str(psh, "sh: can't initialize editing\n"); } INTON; } else if (!editing && el) { INTOFF; el_end(el); el = NULL; INTON; } if (el) { if (Vflag(psh)) el_set(el, EL_EDITOR, "vi"); else if (Eflag(psh)) el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_BIND, "^I", tabcomplete(psh) ? "rl-complete" : "ed-insert", NULL); el_source(el, NULL); } } else { INTOFF; if (el) { /* no editing if not interactive */ el_end(el); el = NULL; } if (hist) { history_end(hist); hist = NULL; } INTON; } } void sethistsize(shinstance *psh, const char *hs) { int histsize; HistEvent he; if (hist != NULL) { if (hs == NULL || *hs == '\0' || (histsize = atoi(hs)) < 0) histsize = 100; history(hist, &he, H_SETSIZE, histsize); } } void setterm(shinstance *psh, const char *term) { if (el != NULL && term != NULL) if (el_set(el, EL_TERMINAL, term) != 0) { outfmt(psh->out2, "sh: Can't set terminal type %s\n", term); outfmt(psh->out2, "sh: Using dumb terminal settings.\n"); } } int inputrc(argc, argv) int argc; char **argv; { if (argc != 2) { out2str(psh, "usage: inputrc file\n"); return 1; } if (el != NULL) { if (el_source(el, argv[1])) { out2str(psh, "inputrc: failed\n"); return 1; } else return 0; } else { out2str(psh, "sh: inputrc ignored, not editing\n"); return 1; } } /* * This command is provided since POSIX decided to standardize * the Korn shell fc command. Oh well... */ int histcmd(int argc, char **argv) { int ch; const char *editor = NULL; HistEvent he; int lflg = 0, nflg = 0, rflg = 0, sflg = 0; int i, retval; const char *firststr, *laststr; int first, last, direction; char *pat = NULL, *repl; /* ksh "fc old=new" crap */ static int active = 0; struct jmploc jmploc; struct jmploc *volatile savehandler; char editfile[MAXPATHLEN + 1]; FILE *efp; #ifdef __GNUC__ /* Avoid longjmp clobbering */ (void) &editor; (void) &lflg; (void) &nflg; (void) &rflg; (void) &sflg; (void) &firststr; (void) &laststr; (void) &pat; (void) &repl; (void) &efp; (void) &argc; (void) &argv; #endif if (hist == NULL) error(psh, "history not active"); if (argc == 1) error(psh, "missing history argument"); optreset = 1; optind = 1; /* initialize getopt */ while (not_fcnumber(argv[optind]) && (ch = getopt(argc, argv, ":e:lnrs")) != -1) switch ((char)ch) { case 'e': editor = optionarg; break; case 'l': lflg = 1; break; case 'n': nflg = 1; break; case 'r': rflg = 1; break; case 's': sflg = 1; break; case ':': error(psh, "option -%c expects argument", optopt); /* NOTREACHED */ case '?': default: error(psh, "unknown option: -%c", optopt); /* NOTREACHED */ } argc -= optind, argv += optind; /* * If executing... */ if (lflg == 0 || editor || sflg) { lflg = 0; /* ignore */ editfile[0] = '\0'; /* * Catch interrupts to reset active counter and * cleanup temp files. */ if (setjmp(jmploc.loc)) { active = 0; if (*editfile) unlink(editfile); handler = savehandler; longjmp(handler->loc, 1); } savehandler = handler; handler = &jmploc; if (++active > MAXHISTLOOPS) { active = 0; displayhist = 0; error(psh, "called recursively too many times"); } /* * Set editor. */ if (sflg == 0) { if (editor == NULL && (editor = bltinlookup(psh, "FCEDIT", 1)) == NULL && (editor = bltinlookup(psh, "EDITOR", 1)) == NULL) editor = DEFEDITOR; if (editor[0] == '-' && editor[1] == '\0') { sflg = 1; /* no edit */ editor = NULL; } } } /* * If executing, parse [old=new] now */ if (lflg == 0 && argc > 0 && ((repl = strchr(argv[0], '=')) != NULL)) { pat = argv[0]; *repl++ = '\0'; argc--, argv++; } /* * determine [first] and [last] */ switch (argc) { case 0: firststr = lflg ? "-16" : "-1"; laststr = "-1"; break; case 1: firststr = argv[0]; laststr = lflg ? "-1" : argv[0]; break; case 2: firststr = argv[0]; laststr = argv[1]; break; default: error(psh, "too many args"); /* NOTREACHED */ } /* * Turn into event numbers. */ first = str_to_event(firststr, 0); last = str_to_event(laststr, 1); if (rflg) { i = last; last = first; first = i; } /* * XXX - this should not depend on the event numbers * always increasing. Add sequence numbers or offset * to the history element in next (diskbased) release. */ direction = first < last ? H_PREV : H_NEXT; /* * If editing, grab a temp file. */ if (editor) { int fd; INTOFF; /* easier */ snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP); if ((fd = mkstemp(editfile)) < 0) error(psh, "can't create temporary file %s", editfile); if ((efp = fdopen(fd, "w")) == NULL) { shfile_close(&psh->fdtab, fd); error(psh, "can't allocate stdio buffer for temp"); } } /* * Loop through selected history events. If listing or executing, * do it now. Otherwise, put into temp file and call the editor * after. * * The history interface needs rethinking, as the following * convolutions will demonstrate. */ history(hist, &he, H_FIRST); retval = history(hist, &he, H_NEXT_EVENT, first); for (;retval != -1; retval = history(hist, &he, direction)) { if (lflg) { if (!nflg) out1fmt(psh, "%5d ", he.num); out1str(psh, he.str); } else { const char *s = pat ? fc_replace(he.str, pat, repl) : he.str; if (sflg) { if (displayhist) { out2str(psh, s); } evalstring(psh, strcpy(stalloc(psh, strlen(s) + 1), s), 0); if (displayhist && hist) { /* * XXX what about recursive and * relative histnums. */ history(hist, &he, H_ENTER, s); } } else fputs(s, efp); } /* * At end? (if we were to lose last, we'd sure be * messed up). */ if (he.num == last) break; } if (editor) { char *editcmd; fclose(efp); editcmd = stalloc(psh, strlen(editor) + strlen(editfile) + 2); sprintf(editcmd, "%s %s", editor, editfile); evalstring(psh, editcmd, 0); /* XXX - should use no JC command */ INTON; readcmdfile(psh, editfile); /* XXX - should read back - quick tst */ unlink(editfile); } if (lflg == 0 && active > 0) --active; if (displayhist) displayhist = 0; return 0; } STATIC const char * fc_replace(const char *s, char *p, char *r) { char *dest; int plen = strlen(p); STARTSTACKSTR(psh, dest); while (*s) { if (*s == *p && strncmp(s, p, plen) == 0) { while (*r) STPUTC(psh, *r++, dest); s += plen; *p = '\0'; /* so no more matches */ } else STPUTC(psh, *s++, dest); } STACKSTRNUL(psh, dest); dest = grabstackstr(psh, dest); return (dest); } int not_fcnumber(char *s) { if (s == NULL) return 0; if (*s == '-') s++; return (!is_number(s)); } int str_to_event(const char *str, int last) { HistEvent he; const char *s = str; int relative = 0; int i, retval; retval = history(hist, &he, H_FIRST); switch (*s) { case '-': relative = 1; /*FALLTHROUGH*/ case '+': s++; } if (is_number(s)) { i = atoi(s); if (relative) { while (retval != -1 && i--) { retval = history(hist, &he, H_NEXT); } if (retval == -1) retval = history(hist, &he, H_LAST); } else { retval = history(hist, &he, H_NEXT_EVENT, i); if (retval == -1) { /* * the notion of first and last is * backwards to that of the history package */ retval = history(hist, &he, last ? H_FIRST : H_LAST); } } if (retval == -1) error(psh, "history number %s not found (internal error)", str); } else { /* * pattern */ retval = history(hist, &he, H_PREV_STR, str); if (retval == -1) error(psh, "history pattern not found: %s", str); } return (he.num); } #else /* SMALL */ int histcmd(shinstance *psh, int argc, char **argv) { error(psh, "not compiled with history support"); /* NOTREACHED */ return -1; } int inputrc(shinstance *psh, int argc, char **argv) { error(psh, "not compiled with history support"); /* NOTREACHED */ return -1; } #endif /* SMALL */ kbuild-2695/src/kash/memalloc.h0000644000000000000000000000670112247157307015124 0ustar rootroot/* $NetBSD: memalloc.h,v 1.14 2003/08/07 09:05:34 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)memalloc.h 8.2 (Berkeley) 5/4/95 */ struct stackmark { struct stack_block *stackp; char *stacknxt; int stacknleft; struct stackmark *marknext; }; /*extern char *stacknxt; extern int stacknleft; extern int sstrnleft; extern int herefd;*/ pointer ckmalloc(struct shinstance *, size_t); pointer ckrealloc(struct shinstance *, pointer, size_t); char *savestr(struct shinstance *, const char *); pointer stalloc(struct shinstance *, size_t); void stunalloc(struct shinstance *, pointer); void setstackmark(struct shinstance *, struct stackmark *); void popstackmark(struct shinstance *, struct stackmark *); void growstackblock(struct shinstance *); void grabstackblock(struct shinstance *, int); char *growstackstr(struct shinstance *); char *makestrspace(struct shinstance *); void ungrabstackstr(struct shinstance *, char *, char *); #define stackblock(psh) (psh)->stacknxt #define stackblocksize(psh) (psh)->stacknleft #define STARTSTACKSTR(psh, p) p = stackblock(psh), (psh)->sstrnleft = stackblocksize(psh) #define STPUTC(psh, c, p) (--(psh)->sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(psh), *p++ = (c))) #define CHECKSTRSPACE(psh, n, p) { if ((psh)->sstrnleft < n) p = makestrspace(psh); } #define USTPUTC(psh, c, p) (--(psh)->sstrnleft, *p++ = (c)) #define STACKSTRNUL(psh, p) ((psh)->sstrnleft == 0? (p = growstackstr(psh), *p = '\0') : (*p = '\0')) #define STUNPUTC(psh, p) (++(psh)->sstrnleft, --p) #define STTOPC(psh, p) p[-1] #define STADJUST(psh, amount, p) (p += (amount), (psh)->sstrnleft -= (amount)) #define grabstackstr(psh, p) stalloc((psh), stackblocksize(psh) - (psh)->sstrnleft) #define ckfree(psh, p) sh_free(psh, (pointer)(p)) kbuild-2695/src/kash/shell.h0000644000000000000000000000576012247157307014446 0ustar rootroot/* $NetBSD: shell.h,v 1.17 2003/08/07 09:05:38 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)shell.h 8.2 (Berkeley) 5/4/95 */ /* * The follow should be set to reflect the type of system you have: * JOBS -> 1 if you have Berkeley job control, 0 otherwise. * SHORTNAMES -> 1 if your linker cannot handle long names. * define BSD if you are running 4.2 BSD or later. * define SYSV if you are running under System V. * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) * define DEBUG=2 to compile in and turn on debugging. * define DO_SHAREDVFORK to indicate that vfork(2) shares its address * with its parent. * * When debugging is on, debugging info will be written to ./trace and * a quit signal will generate a core dump. */ #ifndef ___shell_h #define ___shell_h #ifndef _MSC_VER # include #endif #define JOBS 1 #ifndef BSD # define BSD 1 #endif #ifndef DO_SHAREDVFORK # if __NetBSD_Version__ >= 104000000 # define DO_SHAREDVFORK # endif #endif typedef void *pointer; #ifndef NULL # define NULL (void *)0 #endif #define STATIC /* empty */ #define MKINIT /* empty */ #ifdef HAVE_SYS_CDEFS_H # include #endif extern char nullstr[1]; /* null string */ #ifdef DEBUG # define TRACE(param) trace param # define TRACEV(param) tracev param #else # define TRACE(param) # define TRACEV(param) #endif #include "shtypes.h" #endif kbuild-2695/src/kash/miscbltin.c0000644000000000000000000002275512247157307015321 0ustar rootroot/* $NetBSD: miscbltin.c,v 1.35 2005/03/19 14:22:50 dsl Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; #else __RCSID("$NetBSD: miscbltin.c,v 1.35 2005/03/19 14:22:50 dsl Exp $"); #endif /* not lint */ #endif /* * Miscelaneous builtins. */ #include #include #include #include #include "shell.h" #include "options.h" #include "var.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "miscbltin.h" #include "mystring.h" #include "shinstance.h" #include "shfile.h" #undef rflag void *kash_setmode(shinstance *psh, const char *p); mode_t kash_getmode(const void *bbox, mode_t omode); /* * The read builtin. * Backslahes escape the next char unless -r is specified. * * This uses unbuffered input, which may be avoidable in some cases. * * Note that if IFS=' :' then read x y should work so that: * 'a b' x='a', y='b' * ' a b ' x='a', y='b' * ':b' x='', y='b' * ':' x='', y='' * '::' x='', y='' * ': :' x='', y='' * ':::' x='', y='::' * ':b c:' x='', y='b c:' */ int readcmd(shinstance *psh, int argc, char **argv) { char **ap; char c; int rflag; char *prompt; const char *ifs; char *p; int startword; int status; int i; int is_ifs; int saveall = 0; rflag = 0; prompt = NULL; while ((i = nextopt(psh, "p:r")) != '\0') { if (i == 'p') prompt = psh->optionarg; else rflag = 1; } if (prompt && shfile_isatty(&psh->fdtab, 0)) { out2str(psh, prompt); output_flushall(psh); } if (*(ap = psh->argptr) == NULL) error(psh, "arg count"); if ((ifs = bltinlookup(psh, "IFS", 1)) == NULL) ifs = " \t\n"; status = 0; startword = 2; STARTSTACKSTR(psh, p); for (;;) { if (shfile_read(&psh->fdtab, 0, &c, 1) != 1) { status = 1; break; } if (c == '\0') continue; if (c == '\\' && !rflag) { if (shfile_read(&psh->fdtab, 0, &c, 1) != 1) { status = 1; break; } if (c != '\n') STPUTC(psh, c, p); continue; } if (c == '\n') break; if (strchr(ifs, c)) is_ifs = strchr(" \t\n", c) ? 1 : 2; else is_ifs = 0; if (startword != 0) { if (is_ifs == 1) { /* Ignore leading IFS whitespace */ if (saveall) STPUTC(psh, c, p); continue; } if (is_ifs == 2 && startword == 1) { /* Only one non-whitespace IFS per word */ startword = 2; if (saveall) STPUTC(psh, c, p); continue; } } if (is_ifs == 0) { /* append this character to the current variable */ startword = 0; if (saveall) /* Not just a spare terminator */ saveall++; STPUTC(psh, c, p); continue; } /* end of variable... */ startword = is_ifs; if (ap[1] == NULL) { /* Last variable needs all IFS chars */ saveall++; STPUTC(psh, c, p); continue; } STACKSTRNUL(psh, p); setvar(psh, *ap, stackblock(psh), 0); ap++; STARTSTACKSTR(psh, p); } STACKSTRNUL(psh, p); /* Remove trailing IFS chars */ for (; stackblock(psh) <= --p; *p = 0) { if (!strchr(ifs, *p)) break; if (strchr(" \t\n", *p)) /* Always remove whitespace */ continue; if (saveall > 1) /* Don't remove non-whitespace unless it was naked */ break; } setvar(psh, *ap, stackblock(psh), 0); /* Set any remaining args to "" */ while (*++ap != NULL) setvar(psh, *ap, nullstr, 0); return status; } int umaskcmd(shinstance *psh, int argc, char **argv) { char *ap; int mask; int i; int symbolic_mode = 0; while ((i = nextopt(psh, "S")) != '\0') { symbolic_mode = 1; } mask = shfile_get_umask(&psh->fdtab); if ((ap = *psh->argptr) == NULL) { if (symbolic_mode) { char u[4], g[4], o[4]; i = 0; if ((mask & S_IRUSR) == 0) u[i++] = 'r'; if ((mask & S_IWUSR) == 0) u[i++] = 'w'; if ((mask & S_IXUSR) == 0) u[i++] = 'x'; u[i] = '\0'; i = 0; if ((mask & S_IRGRP) == 0) g[i++] = 'r'; if ((mask & S_IWGRP) == 0) g[i++] = 'w'; if ((mask & S_IXGRP) == 0) g[i++] = 'x'; g[i] = '\0'; i = 0; if ((mask & S_IROTH) == 0) o[i++] = 'r'; if ((mask & S_IWOTH) == 0) o[i++] = 'w'; if ((mask & S_IXOTH) == 0) o[i++] = 'x'; o[i] = '\0'; out1fmt(psh, "u=%s,g=%s,o=%s\n", u, g, o); } else { out1fmt(psh, "%.4o\n", mask); } } else { if (isdigit((unsigned char)*ap)) { mask = 0; do { if (*ap >= '8' || *ap < '0') error(psh, "Illegal number: %s", argv[1]); mask = (mask << 3) + (*ap - '0'); } while (*++ap != '\0'); shfile_set_umask(&psh->fdtab, mask); } else { void *set; INTOFF; if ((set = kash_setmode(psh, ap)) != 0) { mask = kash_getmode(set, ~mask & 0777); ckfree(psh, set); } INTON; if (!set) error(psh, "Illegal mode: %s", ap); shfile_set_umask(&psh->fdtab, ~mask & 0777); } } return 0; } /* * ulimit builtin * * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with * ash by J.T. Conklin. * * Public domain. */ struct limits { const char *name; int cmd; int factor; /* multiply by to get rlim_{cur,max} values */ char option; }; static const struct limits limits[] = { #ifdef RLIMIT_CPU { "time(seconds)", RLIMIT_CPU, 1, 't' }, #endif #ifdef RLIMIT_FSIZE { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, #endif #ifdef RLIMIT_DATA { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, #endif #ifdef RLIMIT_STACK { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, #endif #ifdef RLIMIT_CORE { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, #endif #ifdef RLIMIT_RSS { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, #endif #ifdef RLIMIT_MEMLOCK { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, #endif #ifdef RLIMIT_NPROC { "process(processes)", RLIMIT_NPROC, 1, 'p' }, #endif #ifdef RLIMIT_NOFILE { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' }, #endif #ifdef RLIMIT_VMEM { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, #endif #ifdef RLIMIT_SWAP { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' }, #endif #ifdef RLIMIT_SBSIZE { "sbsize(bytes)", RLIMIT_SBSIZE, 1, 'b' }, #endif { (char *) 0, 0, 0, '\0' } }; int ulimitcmd(shinstance *psh, int argc, char **argv) { int c; shrlim_t val = 0; enum { SOFT = 0x1, HARD = 0x2 } how = SOFT | HARD; const struct limits *l; int set, all = 0; int optc, what; shrlimit limit; what = 'f'; while ((optc = nextopt(psh, "HSabtfdsmcnpl")) != '\0') switch (optc) { case 'H': how = HARD; break; case 'S': how = SOFT; break; case 'a': all = 1; break; default: what = optc; } for (l = limits; l->name && l->option != what; l++) ; if (!l->name) error(psh, "internal error (%c)", what); set = *psh->argptr ? 1 : 0; if (set) { char *p = *psh->argptr; if (all || psh->argptr[1]) error(psh, "too many arguments"); if (strcmp(p, "unlimited") == 0) val = RLIM_INFINITY; else { val = (shrlim_t) 0; while ((c = *p++) >= '0' && c <= '9') { val = (val * 10) + (long)(c - '0'); if (val < (shrlim_t) 0) break; } if (c) error(psh, "bad number"); val *= l->factor; } } if (all) { for (l = limits; l->name; l++) { sh_getrlimit(psh, l->cmd, &limit); if (how & SOFT) val = limit.rlim_cur; else if (how & HARD) val = limit.rlim_max; out1fmt(psh, "%-20s ", l->name); if (val == RLIM_INFINITY) out1fmt(psh, "unlimited\n"); else { val /= l->factor; out1fmt(psh, "%lld\n", (long long) val); } } return 0; } sh_getrlimit(psh, l->cmd, &limit); if (set) { if (how & HARD) limit.rlim_max = val; if (how & SOFT) limit.rlim_cur = val; if (sh_setrlimit(psh, l->cmd, &limit) < 0) error(psh, "error setting limit (%s)", sh_strerror(psh, errno)); } else { if (how & SOFT) val = limit.rlim_cur; else if (how & HARD) val = limit.rlim_max; if (val == RLIM_INFINITY) out1fmt(psh, "unlimited\n"); else { val /= l->factor; out1fmt(psh, "%lld\n", (long long) val); } } return 0; } kbuild-2695/src/kash/sys_signame.c0000644000000000000000000000343012247157307015643 0ustar rootroot/* * Fake sys_signame. */ #include "shinstance.h" /* for MSC */ #include #include static char sys_signame_initialized = 0; char sys_signame[NSIG][16]; void init_sys_signame(void) { unsigned i; if (sys_signame_initialized) return; for (i = 0; i < NSIG; ++i) sprintf(sys_signame[i], "%d", i); #define SET_SIG_STR(sig) strcpy(sys_signame[SIG##sig], #sig); #ifdef SIGHUP SET_SIG_STR(HUP); #endif #ifdef SIGINT SET_SIG_STR(INT); #endif #ifdef SIGQUIT SET_SIG_STR(QUIT); #endif #ifdef SIGILL SET_SIG_STR(ILL); #endif #ifdef SIGTRAP SET_SIG_STR(TRAP); #endif #ifdef SIGABRT SET_SIG_STR(ABRT); #endif #ifdef SIGIOT SET_SIG_STR(IOT); #endif #ifdef SIGBUS SET_SIG_STR(BUS); #endif #ifdef SIGFPE SET_SIG_STR(FPE); #endif #ifdef SIGKILL SET_SIG_STR(KILL); #endif #ifdef SIGUSR1 SET_SIG_STR(USR1); #endif #ifdef SIGSEGV SET_SIG_STR(SEGV); #endif #ifdef SIGUSR2 SET_SIG_STR(USR2); #endif #ifdef SIGPIPE SET_SIG_STR(PIPE); #endif #ifdef SIGALRM SET_SIG_STR(ALRM); #endif #ifdef SIGTERM SET_SIG_STR(TERM); #endif #ifdef SIGSTKFLT SET_SIG_STR(STKFLT); #endif #ifdef SIGCHLD SET_SIG_STR(CHLD); #endif #ifdef SIGCONT SET_SIG_STR(CONT); #endif #ifdef SIGSTOP SET_SIG_STR(STOP); #endif #ifdef SIGTSTP SET_SIG_STR(TSTP); #endif #ifdef SIGTTIN SET_SIG_STR(TTIN); #endif #ifdef SIGTTOU SET_SIG_STR(TTOU); #endif #ifdef SIGURG SET_SIG_STR(URG); #endif #ifdef SIGXCPU SET_SIG_STR(XCPU); #endif #ifdef SIGXFSZ SET_SIG_STR(XFSZ); #endif #ifdef SIGVTALRM SET_SIG_STR(VTALRM); #endif #ifdef SIGPROF SET_SIG_STR(PROF); #endif #ifdef SIGWINCH SET_SIG_STR(WINCH); #endif #ifdef SIGIO SET_SIG_STR(IO); #endif #ifdef SIGPWR SET_SIG_STR(PWR); #endif #ifdef SIGSYS SET_SIG_STR(SYS); #endif #ifdef SIGBREAK SET_SIG_STR(BREAK); #endif #undef SET_SIG_STR sys_signame_initialized = 1; } kbuild-2695/src/kash/tests/0000755000000000000000000000000012247157307014320 5ustar rootrootkbuild-2695/src/kash/tests/netbsd/0000755000000000000000000000000012247157307015577 5ustar rootrootkbuild-2695/src/kash/tests/netbsd/waitjob0000755000000000000000000000014112247157307017160 0ustar rootroot#!/bin/sh sleep 3 & sleep 1 & wait %1 [ $? = 0 ] || echo fail1 wait %2 [ $? = 0 ] || echo fail2 kbuild-2695/src/kash/tests/netbsd/exit10000755000000000000000000000014612247157307016560 0ustar rootroot#!/bin/sh x=`( trap 'echo exiting' EXIT; /usr/bin/true )` if [ -z "$x" ] then echo failed exit 1 fi kbuild-2695/src/kash/tests/netbsd/var10000755000000000000000000000014312247157307016374 0ustar rootroot#!/bin/sh line='/foo/bar/*/baz' if [ "/foo/bar/" != ${line%%\**}"" ] then echo broken exit 1 fi kbuild-2695/src/kash/tests/redirect-10000755000000000000000000000046312247157307016210 0ustar rootroot#!/bin/sh # Redirect output from a builtin command. . ${KASH_TEST_DIR}/common-include.sh TMPFILE="/tmp/redirect-1.$$.tmp" echo 1 > $TMPFILE VAR=`$CMD_CAT $TMPFILE` $CMD_RM -f $TMPFILE if test "$VAR" != "1"; then echo "redirect-1: FAILURE - VAR=$VAR" exit 1 fi echo "redirect-1: SUCCESS" exit 0 kbuild-2695/src/kash/tests/trap-int-10000755000000000000000000000012412247157307016137 0ustar rootroot#!/bin/sh trap 'echo "trap-int-1: caught SIGINT"; exit 0' INT kill -INT $$ exit 2 kbuild-2695/src/kash/tests/common-include.sh0000755000000000000000000000053312247157307017571 0ustar rootroot# File to be sourced. Contains pointers to a bunch of shell utilities. CMD_PREFIX=kmk_ CMD_CAT=${CMD_PREFIX}cat CMD_CP=${CMD_PREFIX}cp CMD_EXPR=${CMD_PREFIX}expr CMD_INSTALL=${CMD_PREFIX}install CMD_LN=${CMD_PREFIX}ln CMD_MV=${CMD_PREFIX}mv CMD_RM=${CMD_PREFIX}rm CMD_SED=${CMD_PREFIX}sed CMD_SLEEP=${CMD_PREFIX}sleep CMD_TIME=${CMD_PREFIX}time kbuild-2695/src/kash/tests/pipe-20000644000000000000000000000116712247157307015344 0ustar rootroot#!/bin/sh # Pipes input from an builtin command thru an external one. . ${KASH_TEST_DIR}/common-include.sh TMPFILE="/tmp/pipe-2.$$.tmp" echo piped > $TMPFILE $CMD_CAT $TMPFILE \ | $CMD_SED -e 's/piped/abc/' \ | $CMD_SED -e 's/abc/def/' \ | $CMD_SED -e 's/def/ghi/' \ | $CMD_SED -e 's/ghi/jkl/' \ | $CMD_SED -e 's/jkl/mno/' \ | $CMD_SED -e 's/mno/pqr/' \ | $CMD_SED -e 's/pqr/stu/' \ | $CMD_SED -e 's/stu/vwx/' \ | $CMD_SED -e 's/vwx/yz_/' \ > $TMPFILE VAR=`$CMD_CAT $TMPFILE` $CMD_RM -f $TMPFILE if test "$VAR" != "yz_"; then echo "pipe-2: FAILURE - VAR=$VAR" exit 1 fi echo "pipe-2: SUCCESS" exit 0 kbuild-2695/src/kash/tests/tick-10000755000000000000000000000024012247157307015332 0ustar rootroot#!/bin/sh VAR=`echo "echoed string"` if test "$VAR" != "echoed string"; then echo "tick-1: failure: VAR=$VAR" exit 1 fi echo 'tick-1: SUCCESS' exit 0 kbuild-2695/src/kash/tests/Makefile.kmk0000644000000000000000000000337012247157307016544 0ustar rootroot# $Id: Makefile.kmk 2423 2010-10-17 23:43:35Z bird $ ## @file # Sub-makefile for kash tests. # # # Copyright (c) 2005-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = ../../.. include $(KBUILD_PATH)/subheader.kmk # # The program. # TESTING += kash_tests KASH_TEST_BIN = $(if $(kash_1_TARGET),$(kash_1_TARGET),$(PATH_INS)/$(TEMPLATE_BIN_INST)kmk_ash$(SUFF_EXE)) KASH_TEST_DIR := $(PATH_SUB_CURRENT) KASH_TESTCASES := $(addprefix $(KASH_TEST_DIR)/,\ trap-exit-1 \ trap-int-1 \ trap-term-1 \ tick-1 \ redirect-1 \ redirect-2 \ redirect-3 \ pipe-1 \ pipe-2 \ exec-1 \ ) kash_tests:: $(ECHO) "kash tests..." @export KASH_TEST_DIR=$(KASH_TEST_DIR); \ KASH_FAILURE=0; \ $(foreach test,$(KASH_TESTCASES)\ ,echo " * $(KASH_TEST_BIN) $(test)"; \ if ! $(KASH_TEST_BIN) $(test); then \ echo " => FAILURE!"; \ KASH_FAILURE=`$(EXPR_EXT) $${KASH_FAILURE} + 1`; \ fi; \ ) \ if test $$KASH_FAILURE -eq 0; then \ echo 'kash tests: All tests succeeded.'; \ else \ echo "kash tests: $$KASH_FAILURE tests failed"'!!'; \ echo ""; \ exit 1; \ fi include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/src/kash/tests/redirect-30000755000000000000000000000054612247157307016214 0ustar rootroot#!/bin/sh # Redirect input to an external command. . ${KASH_TEST_DIR}/common-include.sh TMPFILE="/tmp/redirect-3.$$.tmp" echo 1 > $TMPFILE echo 2 >> $TMPFILE echo 3 >> $TMPFILE VAR=`$CMD_SED -e '/2/!d' < $TMPFILE` $CMD_RM -f $TMPFILE if test "$VAR" != "2"; then echo "redirect-3: FAILURE - VAR=$VAR." exit 1 fi echo "redirect-3: SUCCESS" exit 0 kbuild-2695/src/kash/tests/trap-term-10000755000000000000000000000013012247157307016311 0ustar rootroot#!/bin/sh trap 'echo "trap-term-1: caught SIGTERM"; exit 0' TERM kill -TERM $$ exit 2 kbuild-2695/src/kash/tests/pipe-10000644000000000000000000000053012247157307015334 0ustar rootroot#!/bin/sh # Pipes input from an builtin command thru an external one. . ${KASH_TEST_DIR}/common-include.sh TMPFILE="/tmp/pipe-1.$$.tmp" echo piped | $CMD_SED -e 's/piped/1/' > $TMPFILE VAR=`$CMD_CAT $TMPFILE` $CMD_RM -f $TMPFILE if test "$VAR" != "1"; then echo "pipe-1: FAILURE - VAR=$VAR" exit 1 fi echo "pipe-1: SUCCESS" exit 0 kbuild-2695/src/kash/tests/trap-exit-10000755000000000000000000000012512247157307016317 0ustar rootroot#!/bin/sh trap 'echo "trap-exit-1: overriding exit 1"; exit 0' EXIT exit 1 exit 2 kbuild-2695/src/kash/tests/redirect-20000755000000000000000000000054112247157307016206 0ustar rootroot#!/bin/sh # Redirect output from builtin commands in a subshell. . ${KASH_TEST_DIR}/common-include.sh TMPFILE="/tmp/redirect-2.$$.tmp" (echo -n 1 ; echo -n 2 ; echo -n 3 ) > $TMPFILE VAR=`$CMD_CAT $TMPFILE` $CMD_RM -f $TMPFILE if test "$VAR" != "123"; then echo "redirect-2: FAILURE - VAR=$VAR" exit 1 fi echo "redirect-2: SUCCESS" exit 0 kbuild-2695/src/kash/trap.h0000644000000000000000000000421412247157307014276 0ustar rootroot/* $NetBSD: trap.h,v 1.17 2003/08/07 09:05:39 agc Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)trap.h 8.3 (Berkeley) 6/5/95 */ /*extern int pendingsigs;*/ int trapcmd(struct shinstance *, int, char **); void clear_traps(struct shinstance *, int); void setsignal(struct shinstance *, int, int); void ignoresig(struct shinstance *, int, int); void onsig(struct shinstance *, int); void dotrap(struct shinstance *); void setinteractive(struct shinstance *, int); SH_NORETURN_1 void exitshell(struct shinstance *, int) SH_NORETURN_2; kbuild-2695/src/misc/0000755000000000000000000000000012247157306013162 5ustar rootrootkbuild-2695/src/misc/kmk_time.c0000644000000000000000000002511012247157306015125 0ustar rootroot/* $Id: kmk_time.c 2546 2011-10-01 19:49:54Z bird $ */ /** @file * kmk_time - Time program execution. * * This is based on kmk/kmkbuiltin/redirect.c. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include #include #include #if defined(_MSC_VER) # include # include # include # include #else # include # include # include # include #endif #ifdef __OS2__ # define INCL_BASE # include # ifndef LIBPATHSTRICT # define LIBPATHSTRICT 3 # endif #endif #ifndef _MSC_VER static const char *my_strsignal(int signo) { #define CASE_SIG_RET_STR(sig) if (signo == SIG##sig) return #sig #ifdef SIGHUP CASE_SIG_RET_STR(HUP); #endif #ifdef SIGINT CASE_SIG_RET_STR(INT); #endif #ifdef SIGQUIT CASE_SIG_RET_STR(QUIT); #endif #ifdef SIGILL CASE_SIG_RET_STR(ILL); #endif #ifdef SIGTRAP CASE_SIG_RET_STR(TRAP); #endif #ifdef SIGABRT CASE_SIG_RET_STR(ABRT); #endif #ifdef SIGIOT CASE_SIG_RET_STR(IOT); #endif #ifdef SIGBUS CASE_SIG_RET_STR(BUS); #endif #ifdef SIGFPE CASE_SIG_RET_STR(FPE); #endif #ifdef SIGKILL CASE_SIG_RET_STR(KILL); #endif #ifdef SIGUSR1 CASE_SIG_RET_STR(USR1); #endif #ifdef SIGSEGV CASE_SIG_RET_STR(SEGV); #endif #ifdef SIGUSR2 CASE_SIG_RET_STR(USR2); #endif #ifdef SIGPIPE CASE_SIG_RET_STR(PIPE); #endif #ifdef SIGALRM CASE_SIG_RET_STR(ALRM); #endif #ifdef SIGTERM CASE_SIG_RET_STR(TERM); #endif #ifdef SIGSTKFLT CASE_SIG_RET_STR(STKFLT); #endif #ifdef SIGCHLD CASE_SIG_RET_STR(CHLD); #endif #ifdef SIGCONT CASE_SIG_RET_STR(CONT); #endif #ifdef SIGSTOP CASE_SIG_RET_STR(STOP); #endif #ifdef SIGTSTP CASE_SIG_RET_STR(TSTP); #endif #ifdef SIGTTIN CASE_SIG_RET_STR(TTIN); #endif #ifdef SIGTTOU CASE_SIG_RET_STR(TTOU); #endif #ifdef SIGURG CASE_SIG_RET_STR(URG); #endif #ifdef SIGXCPU CASE_SIG_RET_STR(XCPU); #endif #ifdef SIGXFSZ CASE_SIG_RET_STR(XFSZ); #endif #ifdef SIGVTALRM CASE_SIG_RET_STR(VTALRM); #endif #ifdef SIGPROF CASE_SIG_RET_STR(PROF); #endif #ifdef SIGWINCH CASE_SIG_RET_STR(WINCH); #endif #ifdef SIGIO CASE_SIG_RET_STR(IO); #endif #ifdef SIGPWR CASE_SIG_RET_STR(PWR); #endif #ifdef SIGSYS CASE_SIG_RET_STR(SYS); #endif #ifdef SIGBREAK CASE_SIG_RET_STR(BREAK); #endif #undef CASE_SIG_RET_STR return "???"; } #endif /* unix */ static const char *name(const char *pszName) { const char *psz = strrchr(pszName, '/'); #if defined(_MSC_VER) || defined(__OS2__) const char *psz2 = strrchr(pszName, '\\'); if (!psz2) psz2 = strrchr(pszName, ':'); if (psz2 && (!psz || psz2 > psz)) psz = psz2; #endif return psz ? psz + 1 : pszName; } static int usage(FILE *pOut, const char *argv0) { fprintf(pOut, "usage: %s [args]\n" " or: %s --help\n" " or: %s --version\n" , argv0, argv0, argv0); return 1; } int main(int argc, char **argv) { int i, j; int cTimes = 1; #if defined(_MSC_VER) FILETIME ftStart, ft; unsigned _int64 usMin, usMax, usAvg, usTotal, usCur; unsigned _int64 iStart; intptr_t rc; #else struct timeval tvStart, tv; unsigned long long usMin, usMax, usAvg, usTotal, usCur; pid_t pid; int rc; #endif int rcExit = 0; /* * Parse arguments. */ if (argc <= 1) return usage(stderr, name(argv[0])); for (i = 1; i < argc; i++) { char *psz = &argv[i][0]; if (*psz++ != '-') break; if (*psz == '-') { /* '--' ? */ if (!psz[1]) { i++; break; } /* convert to short. */ if (!strcmp(psz, "-help")) psz = "h"; else if (!strcmp(psz, "-version")) psz = "V"; else if (!strcmp(psz, "-iterations")) psz = "i"; } switch (*psz) { case 'h': usage(stdout, name(argv[0])); return 0; case 'V': printf("kmk_time - kBuild version %d.%d.%d (r%u)\n" "Copyright (C) 2007-2009 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; case 'i': if (i + 1 >= argc) { fprintf(stderr, "%s: syntax error: missing iteration count\n", name(argv[0])); return 1; } cTimes = atoi(argv[++i]); if (cTimes <= 0) { fprintf(stderr, "%s: error: invalid interation count '%s'.\n", name(argv[0]), argv[i]); return 1; } break; default: fprintf(stderr, "%s: error: syntax error '%s'\n", name(argv[0]), argv[i]); return 1; } } /* * Make sure there's something to execute. */ if (i >= argc) { fprintf(stderr, "%s: syntax error: nothing to execute!\n", name(argv[0])); return usage(stderr, name(argv[0])); } /* * Execute the program the specified number of times. */ usMax = usMin = usTotal = 0; usMin--; /* wraps to max value */ for (j = 0; j < cTimes; j++) { /* * Execute the program (it's actually supposed to be a command I think, but wtf). */ #if defined(_MSC_VER) /** @todo * We'll have to find the '--' in the commandline and pass that * on to CreateProcess or spawn. Otherwise, the argument qouting * is gonna be messed up. */ GetSystemTimeAsFileTime(&ftStart); rc = _spawnvp(_P_WAIT, argv[i], &argv[i]); if (rc == -1) { fprintf(stderr, "%s: error: _spawnvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno)); return 8; } GetSystemTimeAsFileTime(&ft); iStart = ftStart.dwLowDateTime | ((unsigned _int64)ftStart.dwHighDateTime << 32); usCur = ft.dwLowDateTime | ((unsigned _int64)ft.dwHighDateTime << 32); usCur -= iStart; usCur /= 10; /* to usecs */ printf("%s: ", name(argv[0])); if (cTimes != 1) printf("#%02u ", j + 1); printf("%um%u.%06us - exit code: %d\n", (unsigned)(usCur / (60 * 1000000)), (unsigned)(usCur % (60 * 1000000)) / 1000000, (unsigned)(usCur % 1000000), rc); #else /* unix: */ gettimeofday(&tvStart, NULL); pid = fork(); if (!pid) { /* child */ execvp(argv[i], &argv[i]); fprintf(stderr, "%s: error: _execvp(\"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno)); return 8; } if (pid < 0) { fprintf(stderr, "%s: error: fork() failed: %s\n", name(argv[0]), strerror(errno)); return 9; } /* parent, wait for child. */ rc = 9; while (waitpid(pid, &rc, 0) == -1 && errno == EINTR) /* nothing */; gettimeofday(&tv, NULL); /* calc elapsed time */ tv.tv_sec -= tvStart.tv_sec; if (tv.tv_usec > tvStart.tv_usec) tv.tv_usec -= tvStart.tv_usec; else { tv.tv_sec--; tv.tv_usec = tv.tv_usec + 1000000 - tvStart.tv_usec; } usCur = tv.tv_sec * 1000000ULL + tv.tv_usec; printf("%s: ", name(argv[0])); if (cTimes != 1) printf("#%02u ", j + 1); printf("%um%u.%06us", (unsigned)(tv.tv_sec / 60), (unsigned)(tv.tv_sec % 60), (unsigned)tv.tv_usec); if (WIFEXITED(rc)) { printf(" - normal exit: %d\n", WEXITSTATUS(rc)); rc = WEXITSTATUS(rc); } # ifndef __HAIKU__ /**@todo figure how haiku signals that a core was dumped. */ else if (WIFSIGNALED(rc) && WCOREDUMP(rc)) { printf(" - dumped core: %s (%d)\n", my_strsignal(WTERMSIG(rc)), WTERMSIG(rc)); rc = 10; } # endif else if (WIFSIGNALED(rc)) { printf(" - killed by: %s (%d)\n", my_strsignal(WTERMSIG(rc)), WTERMSIG(rc)); rc = 11; } else if (WIFSTOPPED(rc)) { printf(" - stopped by: %s (%d)\n", my_strsignal(WSTOPSIG(rc)), WSTOPSIG(rc)); rc = 12; } else { printf(" unknown exit status %#x (%d)\n", rc, rc); rc = 13; } #endif /* unix */ if (rc && !rcExit) rcExit = (int)rc; /* calc min/max/avg */ usTotal += usCur; if (usMax < usCur) usMax = usCur; if (usMin > usCur) usMin = usCur; } /* * Summary if more than one run. */ if (cTimes != 1) { usAvg = usTotal / cTimes; printf("%s: avg %um%u.%06us\n", name(argv[0]), (unsigned)(usAvg / 60000000), (unsigned)(usAvg % 60000000) / 1000000, (unsigned)(usAvg % 1000000)); printf("%s: min %um%u.%06us\n", name(argv[0]), (unsigned)(usMin / 60000000), (unsigned)(usMin % 60000000) / 1000000, (unsigned)(usMin % 1000000)); printf("%s: max %um%u.%06us\n", name(argv[0]), (unsigned)(usMax / 60000000), (unsigned)(usMax % 60000000) / 1000000, (unsigned)(usMax % 1000000)); } return rcExit; } kbuild-2695/src/misc/Makefile.kmk0000644000000000000000000000202612247157306015403 0ustar rootroot# $Id: Makefile.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # Sub-makefile for kmk_time. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = ../.. include $(PATH_KBUILD)/subheader.kmk PROGRAMS += kmk_time kmk_time_TEMPLATE = BIN kmk_time_DEFS = KBUILD_SVN_REV=$(KBUILD_SVN_REV) kmk_time_SOURCES = kmk_time.c include $(KBUILD_PATH)/subfooter.kmk kbuild-2695/src/Makefile.kmk0000644000000000000000000000234712247157306014456 0ustar rootroot# $Id: Makefile.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # Sub-makefile for the source directory. # # # Copyright (c) 2004-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = .. include $(KBUILD_PATH)/subheader.kmk include $(PATH_SUB_CURRENT)/lib/Makefile.kmk include $(PATH_SUB_CURRENT)/sed/Makefile.kmk include $(PATH_SUB_CURRENT)/kmk/Makefile.kmk include $(PATH_SUB_CURRENT)/kash/Makefile.kmk include $(PATH_SUB_CURRENT)/kDepPre/Makefile.kmk include $(PATH_SUB_CURRENT)/kObjCache/Makefile.kmk include $(PATH_SUB_CURRENT)/misc/Makefile.kmk include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/src/kmk/0000755000000000000000000000000012247157307013012 5ustar rootrootkbuild-2695/src/kmk/inlined_memchr.h0000644000000000000000000001076312247157306016146 0ustar rootroot#define _GNU_SOURCE 1 #include #ifdef _MSC_VER _inline void * #else static __inline__ void * #endif my_inline_memchr(const void *pv, int ch, register size_t cb) { register const unsigned int uch = (unsigned)ch; register const unsigned char *pb = (const unsigned char *)pv; #if 0 /* 8-byte loop unroll */ while (cb >= 8) { if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; if (pb[5] == uch) return (unsigned char *)pb + 5; if (pb[6] == uch) return (unsigned char *)pb + 6; if (pb[7] == uch) return (unsigned char *)pb + 7; cb -= 8; pb += 8; } switch (cb & 7) { case 0: break; case 1: if (*pb == uch) return (unsigned char *)pb; break; case 2: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; break; case 3: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; break; case 4: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; break; case 5: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; break; case 6: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; if (pb[5] == uch) return (unsigned char *)pb + 5; break; case 7: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; if (pb[4] == uch) return (unsigned char *)pb + 4; if (pb[5] == uch) return (unsigned char *)pb + 5; if (pb[6] == uch) return (unsigned char *)pb + 6; break; } #elif 1 /* 4 byte loop unroll */ while (cb >= 4) { if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; if (pb[3] == uch) return (unsigned char *)pb + 3; cb -= 4; pb += 4; } switch (cb & 3) { case 0: break; case 1: if (*pb == uch) return (unsigned char *)pb; break; case 2: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; break; case 3: if (*pb == uch) return (unsigned char *)pb; if (pb[1] == uch) return (unsigned char *)pb + 1; if (pb[2] == uch) return (unsigned char *)pb + 2; break; } #else /* the basic loop */ while (cb > 0) { if (*pb == uch) return (void *)pb; cb--; pb++; } #endif return 0; } #define memchr my_inline_memchr kbuild-2695/src/kmk/README.cvs0000644000000000000000000001576212247157306014476 0ustar rootroot -*-text-*- ------------------------------------------------------------------------------- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ------------------------------------------------------------------------------- Obtaining CVS Code ------------------ This seems redundant, since if you're reading this you most likely have already performed this step; however, for completeness, you can obtain the GNU make source code via anonymous CVS from the FSF's Savannah project : $ cvs -d:pserver:anoncvs@cvs.savannah.gnu.org:/sources/make co make You might want to use the "-z3" option to get compression, and you most certainly will want the -P option to avoid unneeded directories cluttering up your source. Personally I add these (as well as -dP for update) to my ~/.cvsrc file. If you have an older version of CVS, you might have to login first. There is no password; just hit the ENTER key if you are asked for one. Building From CVS ----------------- To build GNU make from CVS, you will need Autoconf, Automake, and Gettext, and any tools that those utilities require (GNU m4, Perl, etc.). See the configure.in file to find the minimum versions of each of these tools. You will also need a copy of wget. When building from CVS you must build in the source directory: "VPATH builds" from remote directories are not supported. Once you've created a distribution, of course, you can unpack it and do a VPATH build from there. After checking out the code, you will need to perform these steps to get to the point where you can run "make". 1) $ autoreconf -i This rebuilds all the things that need rebuilding, installing missing files as symbolic links. You may get warnings here about missing files like README, etc. Ignore them, they are harmless. 2) $ ./configure Generate a Makefile 3) $ make update Use wget to retrieve various other files that GNU make relies on, but does not keep in its own source tree. NB: You may need GNU make to correctly perform this step; if you use a platform-local make you may get problems with missing files in doc/. At this point you have successfully brought your CVS copy of the GNU make source directory up to the point where it can be treated more-or-less like the official package you would get from ftp.gnu.org. That is, you can just run: $ make && make check && make install to build and install GNU make. Windows builds from CVS ----------------------- If you have a UNIX emulation like CYGWIN you can opt to run the general build procedure above; it will work. Be sure to read README.W32.template for information on options you might want to use when running ./configure. If you can't or don't want to do that, then rename the file README.W32.template to README.W32 and follow those instructions. Creating a Package ------------------ Once you have performed the above steps (including the configuration and build) you can create a GNU make package. This is very simple, just run: $ make dist-gzip and, if you like: $ make dist-bzip2 Even better, you should run this: $ make distcheck Which will build both .gz and .bz2 package files, then unpack them into a temporary location, try to build them, and repack them, verifying that everything works, you get the same results, _and_ no extraneous files are left over after the "distclean" rule--whew!! Now, _that_ is why converting to Automake is worth the trouble! A big "huzzah!" to Tom T. and the AutoToolers! Steps to Release ---------------- Here are the things that need to be done (in more or less this order) before making an official release: * Update the configure.in file with the new release number. * Update the NEWS file with the release number and date. * Create the new release in the Savannah "Bugs" Administration for both the "Component Version" and "Fixed Release" fields. * Create the new release in the Savannah "Patches" Administration for the "Fixed Release" field. * Update the Savannah bug list URL in the NEWS file to use the correct "Fixed Release" ID number. * Run "make distcheck" to be sure it all works. * Commit everything. * cvs tag where RTAG is constructed by replacing each "." in the version with "-" and prefixing it with "make-". Publishing a Package -------------------- In order to publish a package on the FSF FTP site, either the release site ftp://ftp.gnu.org, or the prerelease site ftp://alpha.gnu.org, you first need to have my GPG private key and my passphrase to unlock it. And, you can't have them! So there! But, just so I remember here's what you do: Make sure the "Steps to Release" are complete and committed and tagged. cvs -d :pserver:anonymous@cvs.savannah.gnu.org:/sources/make \ export -r -d make-release make cd make-release make upload-alpha # for alpha.gnu.org (pre-releases) -OR- make upload-ftp # for ftp.gnu.org (official releases) It will ask for the GPG passphrase _THREE_ times. Sigh. For both final releases and pre-releases, send an email with the URL of the package to the GNU translation robot to allow the translators to work on it: Where to Announce ----------------- Create the announcement in a text file, then sign it with GPG. gpg --clearsign Upload to gnu.org, then login and send from my account there. Email to: make-alpha@gnu.org, bug-make@gnu.org, help-make@gnu.org, make-w32@gnu.org. Email to: info-gnu@gnu.org Add a news item to the Savannah project site. Add an update to freshmeat.net. Appendix A - For The Brave -------------------------- For those of you who trust me implicitly, or are just brave (or foolhardy), here is a canned sequence of commands to build a GNU make distribution package from a virgin CVS source checkout (assuming all the prerequisites are available of course). This list is eminently suitable for a quick swipe o' the mouse and a swift click o' mouse-2 into an xterm. Go for it! autoreconf -i ./configure make update make make check Or, for a debugging version: autoreconf -i && ./configure CFLAGS=-g && make update && make && make check Or, all-in-one: autoreconf -i && ./configure && make update && make && make check kbuild-2695/src/kmk/expand.c0000644000000000000000000010542612247157306014444 0ustar rootroot/* Variable expansion functions for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include #include "filedef.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" /* Initially, any errors reported when expanding strings will be reported against the file where the error appears. */ const struct floc **expanding_var = &reading_file; /* The next two describe the variable output buffer. This buffer is used to hold the variable-expansion of a line of the makefile. It is made bigger with realloc whenever it is too small. variable_buffer_length is the size currently allocated. variable_buffer is the address of the buffer. For efficiency, it's guaranteed that the buffer will always have VARIABLE_BUFFER_ZONE extra bytes allocated. This allows you to add a few extra chars without having to call a function. Note you should never use these bytes unless you're _sure_ you have room (you know when the buffer length was last checked. */ #define VARIABLE_BUFFER_ZONE 5 #ifndef KMK static unsigned int variable_buffer_length; #else unsigned int variable_buffer_length; #endif char *variable_buffer; #ifdef CONFIG_WITH_VALUE_LENGTH struct recycled_buffer { struct recycled_buffer *next; unsigned int length; }; struct recycled_buffer *recycled_head; #endif /* CONFIG_WITH_VALUE_LENGTH */ #ifndef KMK /* Subroutine of variable_expand and friends: The text to add is LENGTH chars starting at STRING to the variable_buffer. The text is added to the buffer at PTR, and the updated pointer into the buffer is returned as the value. Thus, the value returned by each call to variable_buffer_output should be the first argument to the following call. */ char * variable_buffer_output (char *ptr, const char *string, unsigned int length) { register unsigned int newlen = length + (ptr - variable_buffer); if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length) { unsigned int offset = ptr - variable_buffer; variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length ? newlen + 100 : 2 * variable_buffer_length); variable_buffer = xrealloc (variable_buffer, variable_buffer_length); ptr = variable_buffer + offset; } memcpy (ptr, string, length); return ptr + length; } #endif /* Return a pointer to the beginning of the variable buffer. */ static char * initialize_variable_output (void) { /* If we don't have a variable output buffer yet, get one. */ #ifdef CONFIG_WITH_VALUE_LENGTH if (variable_buffer == 0) { struct recycled_buffer *recycled = recycled_head; if (recycled) { recycled_head = recycled->next; variable_buffer_length = recycled->length; variable_buffer = (char *)recycled; } else { variable_buffer_length = 384; variable_buffer = xmalloc (variable_buffer_length); } variable_buffer[0] = '\0'; } #else /* CONFIG_WITH_VALUE_LENGTH */ if (variable_buffer == 0) { variable_buffer_length = 200; variable_buffer = xmalloc (variable_buffer_length); variable_buffer[0] = '\0'; } #endif /* CONFIG_WITH_VALUE_LENGTH */ return variable_buffer; } /* Recursively expand V. The returned string is malloc'd. */ static char *allocated_variable_append (const struct variable *v); char * #ifndef CONFIG_WITH_VALUE_LENGTH recursively_expand_for_file (struct variable *v, struct file *file) #else recursively_expand_for_file (struct variable *v, struct file *file, unsigned int *value_lenp) #endif { char *value; const struct floc *this_var; const struct floc **saved_varp; struct variable_set_list *save = 0; int set_reading = 0; /* Don't install a new location if this location is empty. This can happen for command-line variables, builtin variables, etc. */ saved_varp = expanding_var; if (v->fileinfo.filenm) { this_var = &v->fileinfo; expanding_var = &this_var; } /* If we have no other file-reading context, use the variable's context. */ if (!reading_file) { set_reading = 1; reading_file = &v->fileinfo; } if (v->expanding) { if (!v->exp_count) /* Expanding V causes infinite recursion. Lose. */ fatal (*expanding_var, _("Recursive variable `%s' references itself (eventually)"), v->name); --v->exp_count; } if (file) { save = current_variable_set_list; current_variable_set_list = file->variables; } v->expanding = 1; #ifndef CONFIG_WITH_VALUE_LENGTH if (v->append) value = allocated_variable_append (v); else value = allocated_variable_expand (v->value); #else /* CONFIG_WITH_VALUE_LENGTH */ if (!v->append) value = allocated_variable_expand_2 (v->value, v->value_length, value_lenp); else { value = allocated_variable_append (v); if (value_lenp) *value_lenp = strlen (value); } #endif /* CONFIG_WITH_VALUE_LENGTH */ v->expanding = 0; if (set_reading) reading_file = 0; if (file) current_variable_set_list = save; expanding_var = saved_varp; return value; } #ifdef CONFIG_WITH_VALUE_LENGTH /* Static worker for reference_variable() that expands the recursive variable V. The main difference between this and recursively_expand[_for_file] is that this worker avoids the temporary buffer and outputs directly into the current variable buffer (O). */ static char * reference_recursive_variable (char *o, struct variable *v) { const struct floc *this_var; const struct floc **saved_varp; int set_reading = 0; /* Don't install a new location if this location is empty. This can happen for command-line variables, builtin variables, etc. */ saved_varp = expanding_var; if (v->fileinfo.filenm) { this_var = &v->fileinfo; expanding_var = &this_var; } /* If we have no other file-reading context, use the variable's context. */ if (!reading_file) { set_reading = 1; reading_file = &v->fileinfo; } if (v->expanding) { if (!v->exp_count) /* Expanding V causes infinite recursion. Lose. */ fatal (*expanding_var, _("Recursive variable `%s' references itself (eventually)"), v->name); --v->exp_count; } v->expanding = 1; if (!v->append) /* Expand directly into the variable buffer. */ variable_expand_string_2 (o, v->value, v->value_length, &o); else { /* XXX: Feel free to optimize appending target variables as well. */ char *value = allocated_variable_append (v); unsigned int value_len = strlen (value); o = variable_buffer_output (o, value, value_len); free (value); } v->expanding = 0; if (set_reading) reading_file = 0; expanding_var = saved_varp; return o; } #endif /* CONFIG_WITH_VALUE_LENGTH */ /* Expand a simple reference to variable NAME, which is LENGTH chars long. */ #ifdef MY_INLINE /* bird */ MY_INLINE char * #else #if defined(__GNUC__) __inline #endif static char * #endif reference_variable (char *o, const char *name, unsigned int length) { struct variable *v; #ifndef CONFIG_WITH_VALUE_LENGTH char *value; #endif v = lookup_variable (name, length); if (v == 0) warn_undefined (name, length); /* If there's no variable by that name or it has no value, stop now. */ if (v == 0 || (*v->value == '\0' && !v->append)) return o; #ifdef CONFIG_WITH_VALUE_LENGTH assert (v->value_length == strlen (v->value)); if (!v->recursive) o = variable_buffer_output (o, v->value, v->value_length); else o = reference_recursive_variable (o, v); #else /* !CONFIG_WITH_VALUE_LENGTH */ value = (v->recursive ? recursively_expand (v) : v->value); o = variable_buffer_output (o, value, strlen (value)); if (v->recursive) free (value); #endif /* !CONFIG_WITH_VALUE_LENGTH */ return o; } #ifndef CONFIG_WITH_VALUE_LENGTH /* Only using variable_expand_string_2! */ /* Scan STRING for variable references and expansion-function calls. Only LENGTH bytes of STRING are actually scanned. If LENGTH is -1, scan until a null byte is found. Write the results to LINE, which must point into `variable_buffer'. If LINE is NULL, start at the beginning of the buffer. Return a pointer to LINE, or to the beginning of the buffer if LINE is NULL. */ char * variable_expand_string (char *line, const char *string, long length) { struct variable *v; const char *p, *p1; char *abuf = NULL; char *o; unsigned int line_offset; if (!line) line = initialize_variable_output(); o = line; line_offset = line - variable_buffer; if (length == 0) { variable_buffer_output (o, "", 1); return (variable_buffer); } /* If we want a subset of the string, allocate a temporary buffer for it. Most of the functions we use here don't work with length limits. */ if (length > 0 && string[length] != '\0') { abuf = xmalloc(length+1); memcpy(abuf, string, length); abuf[length] = '\0'; string = abuf; } p = string; while (1) { /* Copy all following uninteresting chars all at once to the variable output buffer, and skip them. Uninteresting chars end at the next $ or the end of the input. */ p1 = strchr (p, '$'); o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1); if (p1 == 0) break; p = p1 + 1; /* Dispatch on the char that follows the $. */ switch (*p) { case '$': /* $$ seen means output one $ to the variable output buffer. */ o = variable_buffer_output (o, p, 1); break; case '(': case '{': /* $(...) or ${...} is the general case of substitution. */ { char openparen = *p; char closeparen = (openparen == '(') ? ')' : '}'; const char *begp; const char *beg = p + 1; char *op; char *abeg = NULL; const char *end, *colon; op = o; begp = p; if (handle_function (&op, &begp)) { o = op; p = begp; break; } /* Is there a variable reference inside the parens or braces? If so, expand it before expanding the entire reference. */ end = strchr (beg, closeparen); if (end == 0) /* Unterminated variable reference. */ fatal (*expanding_var, _("unterminated variable reference")); p1 = lindex (beg, end, '$'); if (p1 != 0) { /* BEG now points past the opening paren or brace. Count parens or braces until it is matched. */ int count = 0; for (p = beg; *p != '\0'; ++p) { if (*p == openparen) ++count; else if (*p == closeparen && --count < 0) break; } /* If COUNT is >= 0, there were unmatched opening parens or braces, so we go to the simple case of a variable name such as `$($(a)'. */ if (count < 0) { abeg = expand_argument (beg, p); /* Expand the name. */ beg = abeg; end = strchr (beg, '\0'); } } else /* Advance P to the end of this reference. After we are finished expanding this one, P will be incremented to continue the scan. */ p = end; /* This is not a reference to a built-in function and any variable references inside are now expanded. Is the resultant text a substitution reference? */ colon = lindex (beg, end, ':'); if (colon) { /* This looks like a substitution reference: $(FOO:A=B). */ const char *subst_beg, *subst_end, *replace_beg, *replace_end; subst_beg = colon + 1; subst_end = lindex (subst_beg, end, '='); if (subst_end == 0) /* There is no = in sight. Punt on the substitution reference and treat this as a variable name containing a colon, in the code below. */ colon = 0; else { replace_beg = subst_end + 1; replace_end = end; /* Extract the variable name before the colon and look up that variable. */ v = lookup_variable (beg, colon - beg); if (v == 0) warn_undefined (beg, colon - beg); /* If the variable is not empty, perform the substitution. */ if (v != 0 && *v->value != '\0') { char *pattern, *replace, *ppercent, *rpercent; char *value = (v->recursive ? recursively_expand (v) : v->value); /* Copy the pattern and the replacement. Add in an extra % at the beginning to use in case there isn't one in the pattern. */ pattern = alloca (subst_end - subst_beg + 2); *(pattern++) = '%'; memcpy (pattern, subst_beg, subst_end - subst_beg); pattern[subst_end - subst_beg] = '\0'; replace = alloca (replace_end - replace_beg + 2); *(replace++) = '%'; memcpy (replace, replace_beg, replace_end - replace_beg); replace[replace_end - replace_beg] = '\0'; /* Look for %. Set the percent pointers properly based on whether we find one or not. */ ppercent = find_percent (pattern); if (ppercent) { ++ppercent; rpercent = find_percent (replace); if (rpercent) ++rpercent; } else { ppercent = pattern; rpercent = replace; --pattern; --replace; } o = patsubst_expand_pat (o, value, pattern, replace, ppercent, rpercent); if (v->recursive) free (value); } } } if (colon == 0) /* This is an ordinary variable reference. Look up the value of the variable. */ o = reference_variable (o, beg, end - beg); if (abeg) free (abeg); } break; case '\0': break; default: if (isblank ((unsigned char)p[-1])) break; /* A $ followed by a random char is a variable reference: $a is equivalent to $(a). */ o = reference_variable (o, p, 1); break; } if (*p == '\0') break; ++p; } if (abuf) free (abuf); variable_buffer_output (o, "", 1); return (variable_buffer + line_offset); } #else /* CONFIG_WITH_VALUE_LENGTH */ /* Scan STRING for variable references and expansion-function calls. Only LENGTH bytes of STRING are actually scanned. If LENGTH is -1, scan until a null byte is found. Write the results to LINE, which must point into `variable_buffer'. If LINE is NULL, start at the beginning of the buffer. Return a pointer to LINE, or to the beginning of the buffer if LINE is NULL. Set EOLP to point to the string terminator. */ char * variable_expand_string_2 (char *line, const char *string, long length, char **eolp) { struct variable *v; const char *p, *p1, *eos; char *o; unsigned int line_offset; if (!line) line = initialize_variable_output(); o = line; line_offset = line - variable_buffer; if (length < 0) length = strlen (string); else MY_ASSERT_MSG (string + length == (p1 = memchr (string, '\0', length)) || !p1, ("len=%ld p1=%p %s\n", length, p1, line)); /* Simple 1: Emptry string. */ if (length == 0) { o = variable_buffer_output (o, "\0", 2); *eolp = o - 2; return (variable_buffer + line_offset); } /* Simple 2: Nothing to expand. ~50% if the kBuild calls. */ p1 = (const char *)memchr (string, '$', length); if (p1 == 0) { o = variable_buffer_output (o, string, length); o = variable_buffer_output (o, "\0", 2); *eolp = o - 2; assert (strchr (variable_buffer + line_offset, '\0') == *eolp); return (variable_buffer + line_offset); } p = string; eos = p + length; while (1) { /* Copy all following uninteresting chars all at once to the variable output buffer, and skip them. Uninteresting chars end at the next $ or the end of the input. */ o = variable_buffer_output (o, p, p1 != 0 ? (p1 - p) : (eos - p)); if (p1 == 0) break; p = p1 + 1; /* Dispatch on the char that follows the $. */ switch (*p) { case '$': /* $$ seen means output one $ to the variable output buffer. */ o = variable_buffer_output (o, p, 1); break; case '(': case '{': /* $(...) or ${...} is the general case of substitution. */ { char openparen = *p; char closeparen = (openparen == '(') ? ')' : '}'; const char *begp; const char *beg = p + 1; char *op; char *abeg = NULL; unsigned int alen = 0; const char *end, *colon; op = o; begp = p; end = may_be_function_name (p + 1, eos); if ( end && handle_function (&op, &begp, end, eos)) { o = op; p = begp; MY_ASSERT_MSG (!(p1 = memchr (variable_buffer + line_offset, '\0', o - (variable_buffer + line_offset))), ("line=%p o/exp_end=%p act_end=%p\n", variable_buffer + line_offset, o, p1)); break; } /* Is there a variable reference inside the parens or braces? If so, expand it before expanding the entire reference. */ end = memchr (beg, closeparen, eos - beg); if (end == 0) /* Unterminated variable reference. */ fatal (*expanding_var, _("unterminated variable reference")); p1 = lindex (beg, end, '$'); if (p1 != 0) { /* BEG now points past the opening paren or brace. Count parens or braces until it is matched. */ int count = 0; for (p = beg; p < eos; ++p) { if (*p == openparen) ++count; else if (*p == closeparen && --count < 0) break; } /* If COUNT is >= 0, there were unmatched opening parens or braces, so we go to the simple case of a variable name such as `$($(a)'. */ if (count < 0) { unsigned int len; char saved; /* Expand the name. */ saved = *p; *(char *)p = '\0'; /* XXX: proove that this is safe! XXX2: shouldn't be necessary any longer! */ abeg = allocated_variable_expand_3 (beg, p - beg, &len, &alen); beg = abeg; end = beg + len; *(char *)p = saved; } } else /* Advance P to the end of this reference. After we are finished expanding this one, P will be incremented to continue the scan. */ p = end; /* This is not a reference to a built-in function and any variable references inside are now expanded. Is the resultant text a substitution reference? */ colon = lindex (beg, end, ':'); if (colon) { /* This looks like a substitution reference: $(FOO:A=B). */ const char *subst_beg, *subst_end, *replace_beg, *replace_end; subst_beg = colon + 1; subst_end = lindex (subst_beg, end, '='); if (subst_end == 0) /* There is no = in sight. Punt on the substitution reference and treat this as a variable name containing a colon, in the code below. */ colon = 0; else { replace_beg = subst_end + 1; replace_end = end; /* Extract the variable name before the colon and look up that variable. */ v = lookup_variable (beg, colon - beg); if (v == 0) warn_undefined (beg, colon - beg); /* If the variable is not empty, perform the substitution. */ if (v != 0 && *v->value != '\0') { char *pattern, *replace, *ppercent, *rpercent; char *value = (v->recursive ? recursively_expand (v) : v->value); /* Copy the pattern and the replacement. Add in an extra % at the beginning to use in case there isn't one in the pattern. */ pattern = alloca (subst_end - subst_beg + 2); *(pattern++) = '%'; memcpy (pattern, subst_beg, subst_end - subst_beg); pattern[subst_end - subst_beg] = '\0'; replace = alloca (replace_end - replace_beg + 2); *(replace++) = '%'; memcpy (replace, replace_beg, replace_end - replace_beg); replace[replace_end - replace_beg] = '\0'; /* Look for %. Set the percent pointers properly based on whether we find one or not. */ ppercent = find_percent (pattern); if (ppercent) { ++ppercent; rpercent = find_percent (replace); if (rpercent) ++rpercent; } else { ppercent = pattern; rpercent = replace; --pattern; --replace; } o = patsubst_expand_pat (o, value, pattern, replace, ppercent, rpercent); if (v->recursive) free (value); } } } if (colon == 0) /* This is an ordinary variable reference. Look up the value of the variable. */ o = reference_variable (o, beg, end - beg); if (abeg) recycle_variable_buffer (abeg, alen); } break; case '\0': assert (p == eos); break; default: if (isblank ((unsigned char)p[-1])) /* XXX: This looks incorrect, previous is '$' */ break; /* A $ followed by a random char is a variable reference: $a is equivalent to $(a). */ o = reference_variable (o, p, 1); break; } if (++p >= eos) break; p1 = memchr (p, '$', eos - p); } o = variable_buffer_output (o, "\0", 2); /* KMK: compensate for the strlen + 1 that was removed above. */ *eolp = o - 2; MY_ASSERT_MSG (strchr (variable_buffer + line_offset, '\0') == *eolp, ("expected=%d actual=%d\nlength=%ld string=%.*s\n", (int)(*eolp - variable_buffer + line_offset), (int)strlen(variable_buffer + line_offset), length, (int)length, string)); return (variable_buffer + line_offset); } #endif /* CONFIG_WITH_VALUE_LENGTH */ /* Scan LINE for variable references and expansion-function calls. Build in `variable_buffer' the result of expanding the references and calls. Return the address of the resulting string, which is null-terminated and is valid only until the next time this function is called. */ char * variable_expand (const char *line) { #ifndef CONFIG_WITH_VALUE_LENGTH return variable_expand_string(NULL, line, (long)-1); #else /* CONFIG_WITH_VALUE_LENGTH */ char *s; /* this function is abused a lot like this: variable_expand(""). */ if (!*line) { s = variable_buffer_output (initialize_variable_output (), "\0", 2); return s - 2; } return variable_expand_string_2 (NULL, line, (long)-1, &s); #endif /* CONFIG_WITH_VALUE_LENGTH */ } /* Expand an argument for an expansion function. The text starting at STR and ending at END is variable-expanded into a null-terminated string that is returned as the value. This is done without clobbering `variable_buffer' or the current variable-expansion that is in progress. */ char * expand_argument (const char *str, const char *end) { #ifndef CONFIG_WITH_VALUE_LENGTH char *tmp, *alloc = NULL; char *r; #endif if (str == end) return xstrdup(""); #ifndef CONFIG_WITH_VALUE_LENGTH if (!end || *end == '\0') return allocated_variable_expand (str); if (end - str + 1 > 1000) tmp = alloc = xmalloc (end - str + 1); else tmp = alloca (end - str + 1); memcpy (tmp, str, end - str); tmp[end - str] = '\0'; r = allocated_variable_expand (tmp); if (alloc) free (alloc); return r; #else /* CONFIG_WITH_VALUE_LENGTH */ if (!end) return allocated_variable_expand_2 (str, ~0U, NULL); return allocated_variable_expand_2 (str, end - str, NULL); #endif /* CONFIG_WITH_VALUE_LENGTH */ } /* Expand LINE for FILE. Error messages refer to the file and line where FILE's commands were found. Expansion uses FILE's variable set list. */ char * variable_expand_for_file (const char *line, struct file *file) { char *result; struct variable_set_list *savev; const struct floc *savef; if (file == 0) return variable_expand (line); savev = current_variable_set_list; current_variable_set_list = file->variables; savef = reading_file; if (file->cmds && file->cmds->fileinfo.filenm) reading_file = &file->cmds->fileinfo; else reading_file = 0; result = variable_expand (line); current_variable_set_list = savev; reading_file = savef; return result; } #if defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_COMMANDS_FUNC) /* Expand LINE for FILE. Error messages refer to the file and line where FILE's commands were found. Expansion uses FILE's variable set list. Differs from variable_expand_for_file in that it takes a pointer to where in the variable buffer to start outputting the expanded string, and that it can returned the length of the string if you wish. */ char * variable_expand_for_file_2 (char *o, const char *line, unsigned int length, struct file *file, unsigned int *value_lenp) { char *result; struct variable_set_list *savev; const struct floc *savef; long len = length == ~0U ? (long)-1 : (long)length; char *eol; if (!o) o = initialize_variable_output(); if (file == 0) result = variable_expand_string_2 (o, line, len, &eol); else { savev = current_variable_set_list; current_variable_set_list = file->variables; savef = reading_file; if (file->cmds && file->cmds->fileinfo.filenm) reading_file = &file->cmds->fileinfo; else reading_file = 0; result = variable_expand_string_2 (o, line, len, &eol); current_variable_set_list = savev; reading_file = savef; } if (value_lenp) *value_lenp = eol - result; return result; } #endif /* CONFIG_WITH_VALUE_LENGTH || CONFIG_WITH_COMMANDS_FUNC */ /* Like allocated_variable_expand, but for += target-specific variables. First recursively construct the variable value from its appended parts in any upper variable sets. Then expand the resulting value. */ static char * variable_append (const char *name, unsigned int length, const struct variable_set_list *set) { const struct variable *v; char *buf = 0; /* If there's nothing left to check, return the empty buffer. */ if (!set) return initialize_variable_output (); /* Try to find the variable in this variable set. */ v = lookup_variable_in_set (name, length, set->set); /* If there isn't one, look to see if there's one in a set above us. */ if (!v) return variable_append (name, length, set->next); /* If this variable type is append, first get any upper values. If not, initialize the buffer. */ if (v->append) buf = variable_append (name, length, set->next); else buf = initialize_variable_output (); /* Append this value to the buffer, and return it. If we already have a value, first add a space. */ if (buf > variable_buffer) buf = variable_buffer_output (buf, " ", 1); #ifdef CONFIG_WITH_VALUE_LENGTH assert (v->value_length == strlen (v->value)); #endif /* Either expand it or copy it, depending. */ if (! v->recursive) #ifdef CONFIG_WITH_VALUE_LENGTH return variable_buffer_output (buf, v->value, v->value_length); #else return variable_buffer_output (buf, v->value, strlen (v->value)); #endif #ifdef CONFIG_WITH_VALUE_LENGTH variable_expand_string_2 (buf, v->value, v->value_length, &buf); return buf; #else buf = variable_expand_string (buf, v->value, strlen (v->value)); return (buf + strlen (buf)); #endif } #ifdef CONFIG_WITH_VALUE_LENGTH /* Expands the specified string, appending it to the specified variable value. */ void append_expanded_string_to_variable (struct variable *v, const char *value, unsigned int value_len, int append) { char *p = (char *) memchr (value, '$', value_len); if (!p) /* fast path */ append_string_to_variable (v,value, value_len, append); else if (value_len) { unsigned int off_dollar = p - (char *)value; /* Install a fresh variable buffer. */ char *saved_buffer; unsigned int saved_buffer_length; install_variable_buffer (&saved_buffer, &saved_buffer_length); p = variable_buffer; if (append || !v->value_length) { /* Copy the current value into it and append a space. */ if (v->value_length) { p = variable_buffer_output (p, v->value, v->value_length); p = variable_buffer_output (p, " ", 1); } /* Append the assignment value. */ p = variable_buffer_output (p, value, off_dollar); variable_expand_string_2 (p, value + off_dollar, value_len - off_dollar, &p); } else { /* Expand the assignemnt value. */ p = variable_buffer_output (p, value, off_dollar); variable_expand_string_2 (p, value + off_dollar, value_len - off_dollar, &p); /* Append a space followed by the old value. */ p = variable_buffer_output (p, " ", 1); p = variable_buffer_output (p, v->value, v->value_length + 1) - 1; } /* Replace the variable with the variable buffer. */ #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (v->rdonly_val) v->rdonly_val = 0; else #endif free (v->value); v->value = variable_buffer; v->value_length = p - v->value; v->value_alloc_len = variable_buffer_length; /* Restore the variable buffer, but without freeing the current. */ variable_buffer = NULL; restore_variable_buffer (saved_buffer, saved_buffer_length); } /* else: Drop empty strings. Use $(NO_SUCH_VARIABLE) if a space is wanted. */ } #endif /* CONFIG_WITH_VALUE_LENGTH */ static char * allocated_variable_append (const struct variable *v) { char *val; /* Construct the appended variable value. */ char *obuf = variable_buffer; unsigned int olen = variable_buffer_length; variable_buffer = 0; assert ((unsigned int)v->length == strlen (v->name)); /* bird */ val = variable_append (v->name, strlen (v->name), current_variable_set_list); variable_buffer_output (val, "", 1); val = variable_buffer; variable_buffer = obuf; variable_buffer_length = olen; return val; } /* Like variable_expand_for_file, but the returned string is malloc'd. This function is called a lot. It wants to be efficient. */ char * allocated_variable_expand_for_file (const char *line, struct file *file) { char *value; char *obuf = variable_buffer; unsigned int olen = variable_buffer_length; variable_buffer = 0; value = variable_expand_for_file (line, file); variable_buffer = obuf; variable_buffer_length = olen; return value; } #ifdef CONFIG_WITH_VALUE_LENGTH /* Handle the most common case in allocated_variable_expand_for_file specially and provide some additional string length features. */ char * allocated_variable_expand_2 (const char *line, unsigned int length, unsigned int *value_lenp) { char *value; char *obuf = variable_buffer; unsigned int olen = variable_buffer_length; long len = length == ~0U ? -1L : (long)length; char *eol; variable_buffer = 0; value = variable_expand_string_2 (NULL, line, len, &eol); if (value_lenp) *value_lenp = eol - value; variable_buffer = obuf; variable_buffer_length = olen; return value; } /* Initially created for handling a special case for variable_expand_string2 where the variable name is expanded and freed right afterwards. This variant allows the variable_buffer to be recycled and thus avoid bothering with a slow free implementation. (Darwin is horrible slow.) */ char * allocated_variable_expand_3 (const char *line, unsigned int length, unsigned int *value_lenp, unsigned int *buffer_lengthp) { char *obuf = variable_buffer; unsigned int olen = variable_buffer_length; long len = (long)length; char *value; char *eol; variable_buffer = 0; value = variable_expand_string_2 (NULL, line, len, &eol); if (value_lenp) *value_lenp = eol - value; *buffer_lengthp = variable_buffer_length; variable_buffer = obuf; variable_buffer_length = olen; return value; } /* recycle a buffer. */ void recycle_variable_buffer (char *buffer, unsigned int length) { struct recycled_buffer *recycled = (struct recycled_buffer *)buffer; assert (!(length & 31)); assert (length >= 384); recycled->length = length; recycled->next = recycled_head; recycled_head = recycled; } #endif /* CONFIG_WITH_VALUE_LENGTH */ /* Install a new variable_buffer context, returning the current one for safe-keeping. */ void install_variable_buffer (char **bufp, unsigned int *lenp) { *bufp = variable_buffer; *lenp = variable_buffer_length; variable_buffer = 0; initialize_variable_output (); } /* Restore a previously-saved variable_buffer setting (free the current one). */ void restore_variable_buffer (char *buf, unsigned int len) { #ifndef CONFIG_WITH_VALUE_LENGTH free (variable_buffer); #else if (variable_buffer) recycle_variable_buffer (variable_buffer, variable_buffer_length); #endif variable_buffer = buf; variable_buffer_length = len; } kbuild-2695/src/kmk/README.W32.template0000644000000000000000000002663612247157306016072 0ustar rootrootThis version of GNU make has been tested on Microsoft Windows 2000/XP/2003. It has also been used on Windows 95/98/NT, and on OS/2. It builds with the MinGW port of GCC (tested with GCC 3.4.2). It also builds with MSVC 2.x, 4.x, 5.x, 6.x, and 2003 as well as with .NET 7.x and .NET 2003. The Windows 32-bit port of GNU make is maintained jointly by various people. It was originally made by Rob Tulloh. Do this first, regardless of the build method you choose: --------------------------------------------------------- 1. At the Windows command prompt run: if not exist NMakefile copy NMakefile.template NMakefile if not exist config.h copy config.h.W32 config.h Then edit config.h to your liking (especially the few shell-related defines near the end, or HAVE_CASE_INSENSITIVE_FS which corresponds to './configure --enable-case-insensitive-file-system'). Using make_msvc_net2003.vcproj ------------------------------ 2. Open make_msvc_net2003.vcproj in MSVS71 or MSVC71 or any compatible IDE, then build this project as usual. There's also a solution file for Studio 2003. Building with (MinGW-)GCC using build_w32.bat --------------------------------------------- 2. Open a W32 command prompt for your installed (MinGW-)GCC, setup a correct PATH and other environment variables for it, then execute ... build_w32.bat gcc This produces gnumake.exe in the current directory. Building with (MSVC++-)cl using build_w32.bat or NMakefile ---------------------------------------------------------- 2. Open a W32 command prompt for your installed (MSVC++-)cl, setup a correct PATH and other environment variables for it (usually via executing vcvars32.bat or vsvars32.bat from the cl-installation, e.g. "%VS71COMNTOOLS%vsvars32.bat"; or using a corresponding start menue entry from the cl-installation), then execute EITHER ... build_w32.bat (this produces WinDebug/gnumake.exe and WinRel/gnumake.exe) ... OR ... nmake /f NMakefile (this produces WinDebug/make.exe and WinRel/make.exe). ------------------- -- Notes/Caveats -- ------------------- GNU make on Windows 32-bit platforms: This version of make is ported natively to Windows32 platforms (Windows NT 3.51, Windows NT 4.0, Windows 2000, Windows XP, Windows 95, and Windows 98). It does not rely on any 3rd party software or add-on packages for building. The only thing needed is a Windows compiler. Two compilers supported officially are the MinGW port of GNU GCC, and the various versions of the Microsoft C compiler. Do not confuse this port of GNU make with other Windows32 projects which provide a GNU make binary. These are separate projects and are not connected to this port effort. GNU make and sh.exe: This port prefers if you have a working sh.exe somewhere on your system. If you don't have sh.exe, the port falls back to MSDOS mode for launching programs (via a batch file). The MSDOS mode style execution has not been tested that carefully though (The author uses GNU bash as sh.exe). There are very few true ports of Bourne shell for NT right now. There is a version of GNU bash available from Cygnus "Cygwin" porting effort (http://www.cygwin.com/). Other possibilities are the MKS version of sh.exe, or building your own with a package like NutCracker (DataFocus) or Portage (Consensys). Also MinGW includes sh (http://mingw.org/). GNU make and brain-dead shells (BATCH_MODE_ONLY_SHELL): Some versions of Bourne shell do not behave well when invoked as 'sh -c' from CreateProcess(). The main problem is they seem to have a hard time handling quoted strings correctly. This can be circumvented by writing commands to be executed to a batch file and then executing the command by calling 'sh file'. To work around this difficulty, this version of make supports a batch mode. When BATCH_MODE_ONLY_SHELL is defined at compile time, make forces all command lines to be executed via script files instead of by command line. In this mode you must have a working sh.exe in order to use parallel builds (-j). A native Windows32 system with no Bourne shell will also run in batch mode. All command lines will be put into batch files and executed via $(COMSPEC) (%COMSPEC%). However, parallel builds ARE supported with Windows shells (cmd.exe and command.com). See the next section about some peculiarities of parallel builds on Windows. Support for parallel builds Parallel builds (-jN) are supported in this port, with 2 limitations: - The number of concurrent processes has a hard limit of 64, due to the way this port implements waiting for its subprocesses; - The job server method (available when Make runs on Posix platforms) is not supported, which means you must pass an explicit -jN switch to sub-Make's in a recursive Makefile. If a sub-Make does not receive an explicit -jN switch, it will default to -j1, i.e. no parallelism in sub-Make's. GNU make and Cygnus GNU Windows32 tools: Good news! Make now has native support for Cygwin sh. To enable, define the HAVE_CYGWIN_SHELL in config.h and rebuild make from scratch. This version of make tested with B20.1 of Cygwin. Do not define BATCH_MODE_ONLY_SHELL if you use HAVE_CYGWIN_SHELL. GNU make and the MKS shell: There is now semi-official support for the MKS shell. To turn this support on, define HAVE_MKS_SHELL in the config.h.W32 before you build make. Do not define BATCH_MODE_ONLY_SHELL if you turn on HAVE_MKS_SHELL. GNU make handling of drive letters in pathnames (PATH, vpath, VPATH): There is a caveat that should be noted with respect to handling single character pathnames on Windows systems. When colon is used in PATH variables, make tries to be smart about knowing when you are using colon as a separator versus colon as a drive letter. Unfortunately, something as simple as the string 'x:/' could be interpreted 2 ways: (x and /) or (x:/). Make chooses to interpret a letter plus colon (e.g. x:/) as a drive letter pathname. If it is necessary to use single character directories in paths (VPATH, vpath, Path, PATH), the user must do one of two things: a. Use semicolon as the separator to disambiguate colon. For example use 'x;/' if you want to say 'x' and '/' are separate components. b. Qualify the directory name so that there is more than one character in the path(s) used. For example, none of these settings are ambiguous: ./x:./y /some/path/x:/some/path/y x:/some/path/x:x:/some/path/y Please note that you are free to mix colon and semi-colon in the specification of paths. Make is able to figure out the intended result and convert the paths internally to the format needed when interacting with the operating system, providing the path is not within quotes, e.g. "x:/test/test.c". You are encouraged to use colon as the separator character. This should ease the pain of deciding how to handle various path problems which exist between platforms. If colon is used on both Unix and Windows systems, then no ifdef'ing will be necessary in the makefile source. GNU make test suite: I verified all functionality with a slightly modified version of make-test-%VERSION% (modifications to get test suite to run on Windows NT). All tests pass in an environment that includes sh.exe. Tests were performed on both Windows NT and Windows 95. Pathnames and white space: Unlike Unix, Windows 95/NT systems encourage pathnames which contain white space (e.g. C:\Program Files\). These sorts of pathnames are valid on Unix too, but are never encouraged. There is at least one place in make (VPATH/vpath handling) where paths containing white space will simply not work. There may be others too. I chose to not try and port make in such a way so that these sorts of paths could be handled. I offer these suggestions as workarounds: 1. Use 8.3 notation. i.e. "x:/long~1/", which is actually "x:\longpathtest". Type "dir /x" to view these filenames within the cmd.exe shell. 2. Rename the directory so it does not contain white space. If you are unhappy with this choice, this is free software and you are free to take a crack at making this work. The code in w32/pathstuff.c and vpath.c would be the places to start. Pathnames and Case insensitivity: Unlike Unix, Windows 95/NT systems are case insensitive but case preserving. For example if you tell the file system to create a file named "Target", it will preserve the case. Subsequent access to the file with other case permutations will succeed (i.e. opening a file named "target" or "TARGET" will open the file "Target"). By default, GNU make retains its case sensitivity when comparing target names and existing files or directories. It can be configured, however, into a case preserving and case insensitive mode by adding a define for HAVE_CASE_INSENSITIVE_FS to config.h.W32. For example, the following makefile will create a file named Target in the directory subdir which will subsequently be used to satisfy the dependency of SUBDIR/DepTarget on SubDir/TARGET. Without HAVE_CASE_INSENSITIVE_FS configured, the dependency link will not be made: subdir/Target: touch $@ SUBDIR/DepTarget: SubDir/TARGET cp $^ $@ Reliance on this behavior also eliminates the ability of GNU make to use case in comparison of matching rules. For example, it is not possible to set up a C++ rule using %.C that is different than a C rule using %.c. GNU make will consider these to be the same rule and will issue a warning. SAMBA/NTFS/VFAT: I have not had any success building the debug version of this package using SAMBA as my file server. The reason seems to be related to the way VC++ 4.0 changes the case name of the pdb filename it is passed on the command line. It seems to change the name always to to lower case. I contend that the VC++ compiler should not change the casename of files that are passed as arguments on the command line. I don't think this was a problem in MSVC 2.x, but I know it is a problem in MSVC 4.x. The package builds fine on VFAT and NTFS filesystems. Most all of the development I have done to date has been using NTFS and long file names. I have not done any considerable work under VFAT. VFAT users may wish to be aware that this port of make does respect case sensitivity. FAT: Version 3.76 added support for FAT filesystems. Make works around some difficulties with stat'ing of files and caching of filenames and directories internally. Bug reports: Please submit bugs via the normal bug reporting mechanism which is described in the GNU make manual and the base README. ------------------------------------------------------------------------------- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/Makefile.DOS.template0000644000000000000000000004626412247157307016724 0ustar rootroot# -*-Makefile-*- template for DJGPP # Makefile.in generated automatically by automake 1.2 from Makefile.am # # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, # 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . SHELL = /bin/sh srcdir = . VPATH = $(srcdir) # $DJDIR is defined automatically by DJGPP to point # to the root of the DJGPP installation tree. prefix = /dev/env/DJDIR exec_prefix = ${prefix} bindir = /bin datadir = /share libdir = /lib infodir = /info mandir = /man includedir = /include oldincludedir = c:/djgpp/include DESTDIR = /dev/env/DJDIR pkgdatadir = $(datadir)/make pkglibdir = $(libdir)/make pkgincludedir = $(includedir)/make localedir = $(datadir)/locale INSTALL = ${exec_prefix}/bin/ginstall -c INSTALL_PROGRAM = ${exec_prefix}/bin/ginstall -c INSTALL_DATA = ${exec_prefix}/bin/ginstall -c -m 644 INSTALL_SCRIPT = ${exec_prefix}/bin/ginstall -c transform = s,x,x, # This will fail even if they don't have a Unix-like shell (stock DOS # shell doesn't know about `false'). The only difference is that they # get "Error -1" instead of "Error 1". EXIT_FAIL = false NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : EXEEXT = .exe OBJEXT = o AR = ar AWK = gawk CC = gcc CPP = gcc -E LIBOBJS = MAKEINFO = ${exec_prefix}/bin/makeinfo PACKAGE = make PERL = perl RANLIB = ranlib REMOTE = stub VERSION = %VERSION% AUTOMAKE_OPTIONS = 1.2 bin_PROGRAMS = %PROGRAMS%$(EXEEXT) make_SOURCES = %SOURCES% # This should include the glob/ prefix libglob_a_SOURCES = %GLOB_SOURCES% make_LDADD = glob/libglob.a man_MANS = make.1 INCLUDES = -I$(srcdir)/glob -DLIBDIR=\"$(prefix)$(libdir)\" -DINCLUDEDIR=\"$(prefix)$(includedir)\" -DLOCALEDIR=\"$(prefix)$(localedir)\" BUILT_SOURCES = README build.sh-in EXTRA_DIST = $(BUILT_SOURCES) $(man_MANS) README.customs remote-cstms.c make-stds.texi texinfo.tex SCOPTIONS SMakefile Makefile.ami README.Amiga config.ami amiga.c amiga.h NMakefile README.DOS configh.dos configure.bat makefile.com README.W32 build_w32.bat config.h-W32 subproc.bat make.lnk config.h-vms makefile.vms readme.vms vmsdir.h vmsfunctions.c vmsify.c SUBDIRS = glob doc mkinstalldirs = ${exec_prefix}/bin/gmkdir -p CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = build.sh PROGRAMS = $(bin_PROGRAMS) MAKE_HOST = i386-pc-msdosdjgpp DEFS = -I. -I$(srcdir) -I. CPPFLAGS = -DHAVE_CONFIG_H LDFLAGS = LIBS = make_OBJECTS = %OBJECTS% make_DEPENDENCIES = glob/libglob.a make_LDFLAGS = libglob_a_LIBADD = libglob_a_OBJECTS = %GLOB_OBJECTS% noinst_LIBRARIES = glob/libglob.a CFLAGS = -O2 -g COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ TEXI2DVI = texi2dvi TEXINFO_TEX = $(srcdir)/config/texinfo.tex INFO_DEPS = doc/make.info DVIS = doc/make.dvi TEXINFOS = doc/make.texi noinst_TEXINFOS = doc/fdl.texi doc/make-stds.texi man1dir = $(mandir)/man1 MANS = $(man_MANS) NROFF = nroff DIST_COMMON = README ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS acconfig.h aclocal.m4 alloca.c build.sh-in config.h-in configure configure.in getloadavg.c DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = gtar GZIP = --best SOURCES = $(make_SOURCES) OBJECTS = $(make_OBJECTS) HEADERS = $(wildcard $(srcdir)/*.h) default: all .SUFFIXES: .SUFFIXES: .c .dvi .info .o .obj .ps .texi .tex .html mostlyclean-hdr: clean-hdr: distclean-hdr: -rm -f config.h maintainer-clean-hdr: mostlyclean-binPROGRAMS: clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) distclean-binPROGRAMS: maintainer-clean-binPROGRAMS: install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do if test -f $$p; then echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p | sed '$(transform)'`"; $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p | sed '$(transform)'`; else :; fi; done uninstall-binPROGRAMS: $(NORMAL_UNINSTALL) list='$(bin_PROGRAMS)'; for p in $$list; do rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`.exe; done .c.o: $(COMPILE) -c $< clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) mostlyclean-compile: -rm -f *.$(OBJEXT) *$(EXEEXT) make.new core clean-compile: distclean-compile: -rm -f *.tab.c *_tab.c maintainer-clean-compile: make$(EXEEXT): $(make_OBJECTS) $(make_DEPENDENCIES) @command.com /c if exist make del make @command.com /c if exist make.exe del make.exe $(LINK) $(make_LDFLAGS) $(make_OBJECTS) $(make_LDADD) $(LIBS) # Documentation make.info: make.texi make.dvi: make.texi make.ps: make.dvi make.texi make.html: make.texi DVIPS = dvips .texi.info: @command.com /c if exist make.info* del make.info* @command.com /c if exist make.i* del make.i* $(MAKEINFO) -I$(srcdir) --no-split $< -o ./$@ .texi: @command.com /c if exist make.info* del make.info* @command.com /c if exist make.i* del make.i* $(MAKEINFO) -I$(srcdir) --no-split $< -o ./$@ .texi.dvi: TEXINPUTS="$(srcdir);$$TEXINPUTS" MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< .dvi.ps: $(DVIPS) $< -o $@ # Other documentation formats html: html-recursive .texi.html: @command.com /c if exist make.html* del make.html* $(MAKEINFO) --html -I$(srcdir) --no-split $< -o ./$@ install-info-am: $(INFO_DEPS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(infodir) @for file in $(INFO_DEPS); do iifile=`echo $$file | sed "s|doc/||"`; d=$(srcdir); for ifile in `cd $$d && echo $$file`; do if test -f $$d/$$ifile; then echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$iifile"; $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$iifile; else : ; fi; done; done @$(POST_INSTALL) @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then for file in $(INFO_DEPS); do iifile=`echo $$file | sed "s|doc/||"`; echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$iifile"; install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$iifile || :; done; else : ; fi uninstall-info: $(PRE_UNINSTALL) @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then ii=yes; else ii=; fi; for file in $(INFO_DEPS); do test -z $ii || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; done $(NORMAL_UNINSTALL) for file in $(INFO_DEPS); do (cd $(DESTDIR)$(infodir) && rm -f $$file); done dist-info: $(INFO_DEPS) for base in $(INFO_DEPS); do d=$(srcdir); for file in `cd $$d && eval echo $$base*`; do test -f $(distdir)/$$file || ln $$d/$$file $(distdir)/$$file 2> /dev/null || cp -p $$d/$$file $(distdir)/$$file; done; done mostlyclean-aminfo: -rm -f $(srcdir)/doc/make.aux $(srcdir)/doc/make.cp $(srcdir)/doc/make.cps $(srcdir)/doc/make.dvi \ $(srcdir)/doc/make.fn $(srcdir)/doc/make.fns $(srcdir)/doc/make.ky $(srcdir)/doc/make.kys \ $(srcdir)/doc/make.ps $(srcdir)/doc/make.log $(srcdir)/doc/make.pg $(srcdir)/doc/make.toc \ $(srcdir)/doc/make.tp $(srcdir)/doc/make.tps $(srcdir)/doc/make.vr $(srcdir)/doc/make.vrs \ $(srcdir)/doc/make.op $(srcdir)/doc/make.tr $(srcdir)/doc/make.cv $(srcdir)/doc/make.cn \ $(srcdir)/doc/make.html clean-aminfo: distclean-aminfo: maintainer-clean-aminfo: for i in $(INFO_DEPS); do rm -f $$i*; done install-man1: $(mkinstalldirs) $(DESTDIR)$(man1dir) @list='$(man1_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ done uninstall-man1: @list='$(man1_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ rm -f $(DESTDIR)$(man1dir)/$$inst; \ done install-man: $(MANS) @$(NORMAL_INSTALL) $(MAKE) install-man1 uninstall-man: @$(NORMAL_UNINSTALL) $(MAKE) uninstall-man1 # Assume that the only thing to do in glob is to build libglob.a, # but do a sanity check: if $SUBDIRS will ever have more than # a single directory, yell bloody murder. all-recursive: ifeq ($(findstring glob, $(SUBDIRS)), glob) @command.com /c if not exist glob\\nul md glob @echo Making all in glob $(MAKE) -C glob -f ../Makefile INCLUDES='-I$(srcdir) -I$(srcdir)/glob' DEFS='-I.. -I$(srcdir)' VPATH=$(srcdir)/glob libglob.a endif $(SUBDIRS): command.com /c md $@ libglob.a: $(libglob_a_OBJECTS) command.com /c if exist libglob.a del libglob.a $(AR) cru libglob.a $(libglob_a_OBJECTS) $(libglob_a_LIBADD) $(RANLIB) libglob.a mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive check-recursive: ifeq ($(words $(SUBDIRS)), 2) @echo Making $(shell echo $@ | sed s/-recursive//) in glob $(MAKE) -C glob -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am @echo Making $(shell echo $@ | sed s/-recursive//) in doc $(MAKE) -C doc -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am else @echo FATAL: There is more than two directory in "($(SUBDIRS))" @$(EXIT_FAIL) endif tags-in-glob: $(libglob_a_SOURCES) etags $(addprefix $(srcdir)/,$^) -o ./glob/TAGS tags-recursive: ifeq ($(words $(SUBDIRS)), 2) $(MAKE) tags-in-glob else @echo FATAL: There is more than two directory in "($(SUBDIRS))" @$(EXIT_FAIL) endif tags: TAGS ID: $(HEADERS) $(SOURCES) mkid $(srcdir)/$(SOURCES) $(srcdir)/$(libglob_a_SOURCES) ./config.h $(HEADERS) TAGS: tags-recursive $(HEADERS) $(srcdir)/$(SOURCES) config.h $(TAGS_DEPENDENCIES) etags -i ./glob/TAGS $(ETAGS_ARGS) $(srcdir)/$(SOURCES) ./config.h $(HEADERS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist rm -rf $(distdir) GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz mkdir $(distdir)/=build mkdir $(distdir)/=inst dc_install_base=`cd $(distdir)/=inst && pwd`; cd $(distdir)/=build && ../configure --srcdir=.. --prefix=$$dc_install_base && $(MAKE) && $(MAKE) dvi && $(MAKE) check && $(MAKE) install && $(MAKE) installcheck && $(MAKE) dist rm -rf $(distdir) @echo "========================"; echo "$(distdir).tar.gz is ready for distribution"; echo "========================" dist: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir) rm -rf $(distdir) dist-all: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir) rm -rf $(distdir) distdir: $(DISTFILES) rm -rf $(distdir) mkdir $(distdir) -chmod 777 $(distdir) @for file in $(DISTFILES); do d=$(srcdir); test -f $(distdir)/$$file || ln $$d/$$file $(distdir)/$$file 2> /dev/null || cp -p $$d/$$file $(distdir)/$$file; done; for subdir in $(SUBDIRS); do test -d $(distdir)/$$subdir || mkdir $(distdir)/$$subdir || exit 1; chmod 777 $(distdir)/$$subdir; (cd $$subdir && $(MAKE) top_distdir=../$(top_distdir)/$$subdir distdir=../$(distdir)/$$subdir distdir) || exit 1; done $(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info $(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook info: info-recursive info-recursive: ifeq ($(findstring doc, $(SUBDIRS)), doc) @command.com /c if not exist doc\\nul md doc @echo Making all in doc $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.info endif dvi: dvi-recursive dvi-recursive: ifeq ($(findstring doc, $(SUBDIRS)), doc) @command.com /c if not exist doc\\nul md doc @echo Making all in doc $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.dvi endif ps: ps-recursive ps-recursive: ifeq ($(findstring doc, $(SUBDIRS)), doc) @command.com /c if not exist doc\\nul md doc @echo Making all in doc $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.ps endif html-recursive: ifeq ($(findstring doc, $(SUBDIRS)), doc) @command.com /c if not exist doc\\nul md doc @echo Making all in doc $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.html endif check: all-am check-recursive check-local @: installcheck: installcheck-recursive all-recursive-am: config.h $(MAKE) all-recursive all-am: Makefile $(PROGRAMS) config.h info install-exec-am: install-binPROGRAMS install-data-am: install-info-am uninstall-am: uninstall-binPROGRAMS uninstall-info install-exec: install-exec-recursive install-exec-am @$(NORMAL_INSTALL) install-data: install-data-recursive install-data-am @$(NORMAL_INSTALL) install-recursive uninstall-recursive: @: install: install-recursive install-exec-am install-data-am @: uninstall: uninstall-recursive uninstall-am all: all-recursive-am all-am install-strip: $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install installdirs: installdirs-recursive $(mkinstalldirs) $(bindir) $(infodir) mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f Makefile $(DISTCLEANFILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS mostlyclean-compile mostlyclean-aminfo mostlyclean-tags mostlyclean-generic clean-am: clean-hdr clean-binPROGRAMS clean-compile clean-aminfo clean-tags clean-generic mostlyclean-am distclean-am: distclean-hdr distclean-binPROGRAMS distclean-compile distclean-aminfo distclean-tags distclean-generic clean-am maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS maintainer-clean-compile maintainer-clean-aminfo maintainer-clean-tags maintainer-clean-generic distclean-am mostlyclean: mostlyclean-recursive mostlyclean-am clean: clean-noinstLIBRARIES clean-recursive clean-am distclean: distclean-recursive distclean-am rm -f config.status maintainer-clean: maintainer-clean-recursive maintainer-clean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f config.status .PHONY: default mostlyclean-hdr distclean-hdr clean-hdr \ maintainer-clean-hdr mostlyclean-binPROGRAMS distclean-binPROGRAMS \ clean-binPROGRAMS maintainer-clean-binPROGRAMS uninstall-binPROGRAMS \ install-binPROGRAMS mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile install-info-am uninstall-info \ mostlyclean-aminfo distclean-aminfo clean-aminfo \ maintainer-clean-aminfo install-data-recursive uninstall-data-recursive \ install-exec-recursive uninstall-exec-recursive installdirs-recursive \ uninstalldirs-recursive all-recursive check-recursive check-am \ installcheck-recursive info-recursive dvi-recursive \ mostlyclean-recursive distclean-recursive clean-recursive \ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ distclean-tags clean-tags maintainer-clean-tags distdir \ mostlyclean-depend distclean-depend clean-depend \ maintainer-clean-depend info dvi check-local installcheck \ all-recursive-am all-am install-exec-am install-data-am uninstall-am \ install-exec install-data install uninstall all installdirs \ mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean \ html # --------------- Local DIST Section # Install the w32 subdirectory # dist-hook: (cd $(srcdir); \ w32=`find w32 -follow \( -name CVS -prune \) -o -type f -print`; \ tar chf - $$w32) \ | (cd $(distdir); tar xfBp -) # --------------- Local CHECK Section # Note: check-loadavg is NOT a prerequisite of check-local, since # there's no uptime utility, and the test it does doesn't make sense # on MSDOS anyway. check-local: check-shell check-regression @banner=" Regression PASSED: GNU Make $(VERSION) ($(MAKE_HOST)) built with $(CC) "; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes"; \ echo .PHONY: check-loadavg check-shell check-regression # > check-shell # # check-shell is designed to fail if they don't have a Unixy shell # installed. The test suite requires such a shell. check-shell: @echo If Make says Error -1, you do not have Unix-style shell installed @foo=bar.exe : # > check-loadavg # loadavg: loadavg.c config.h @rm -f loadavg $(LINK) -DTEST $(make_LDFLAGS) loadavg.c $(LIBS) # We copy getloadavg.c into a different file rather than compiling it # directly because some compilers clobber getloadavg.o in the process. loadavg.c: getloadavg.c ln $(srcdir)/getloadavg.c loadavg.c || \ cp $(srcdir)/getloadavg.c loadavg.c check-loadavg: loadavg @echo The system uptime program believes the load average to be: -uptime @echo The GNU load average checking code believes: -./loadavg # > check-regression # # Look for the make test suite, and run it if found. Look in MAKE_TEST if # specified, or else in the srcdir or the distdir, their parents, and _their_ # parents. # check-regression: @if test -f "$(srcdir)/tests/run_make_tests"; then \ if $(PERL) -v >/dev/null 2>&1; then \ case `cd $(srcdir); pwd` in `pwd`) : ;; \ *) test -d tests || mkdir tests; \ for f in run_make_tests run_make_tests.pl test_driver.pl scripts; do \ rm -rf tests/$$f; cp -pr $(srcdir)/tests/$$f tests; \ done ;; \ esac; \ echo "cd tests && $(PERL) ./run_make_tests.pl -make ../make.exe $(MAKETESTFLAGS)"; \ cd tests && $(PERL) ./run_make_tests.pl -make ../make.exe $(MAKETESTFLAGS); \ else \ echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \ fi; \ else \ echo "Can't find the GNU Make test suite ($(srcdir)/tests)."; \ fi # --------------- Maintainer's Section # Note this requires GNU make. Not to worry, since it will only be included # in the Makefile if we're in the maintainer's environment. #include $(srcdir)/maintMakefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: # --------------- DEPENDENCIES kbuild-2695/src/kmk/hash.h0000644000000000000000000002237612247157307014120 0ustar rootroot/* hash.h -- decls for hash table Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc. Written by Greg McGary GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _hash_h_ #define _hash_h_ #include #include #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ || !defined __P # undef __P # define __P(protos) protos # endif #else /* Not C++ or ANSI C. */ # undef __P # define __P(protos) () /* We can get away without defining `const' here only because in this file it is used only inside the prototype for `fnmatch', which is elided in non-ANSI C where `const' is problematical. */ #endif /* C++ or ANSI C. */ typedef unsigned long (*hash_func_t) __P((void const *key)); typedef int (*hash_cmp_func_t) __P((void const *x, void const *y)); typedef void (*hash_map_func_t) __P((void const *item)); typedef void (*hash_map_arg_func_t) __P((void const *item, void *arg)); struct hash_table { void **ht_vec; unsigned long ht_size; /* total number of slots (power of 2) */ unsigned long ht_capacity; /* usable slots, limited by loading-factor */ unsigned long ht_fill; /* items in table */ unsigned long ht_empty_slots; /* empty slots not including deleted slots */ unsigned long ht_collisions; /* # of failed calls to comparison function */ unsigned long ht_lookups; /* # of queries */ unsigned int ht_rehashes; /* # of times we've expanded table */ hash_func_t ht_hash_1; /* primary hash function */ hash_func_t ht_hash_2; /* secondary hash function */ hash_cmp_func_t ht_compare; /* comparison function */ #ifdef CONFIG_WITH_STRCACHE2 struct strcache2 *ht_strcache; /* the string cache pointer. */ unsigned int ht_off_string; /* offsetof (struct key, string) */ #endif }; typedef int (*qsort_cmp_t) __P((void const *, void const *)); void hash_init __P((struct hash_table *ht, unsigned long size, hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp)); void hash_load __P((struct hash_table *ht, void *item_table, unsigned long cardinality, unsigned long size)); void **hash_find_slot __P((struct hash_table *ht, void const *key)); void *hash_find_item __P((struct hash_table *ht, void const *key)); void *hash_insert __P((struct hash_table *ht, const void *item)); void *hash_insert_at __P((struct hash_table *ht, const void *item, void const *slot)); void *hash_delete __P((struct hash_table *ht, void const *item)); void *hash_delete_at __P((struct hash_table *ht, void const *slot)); void hash_delete_items __P((struct hash_table *ht)); void hash_free_items __P((struct hash_table *ht)); void hash_free __P((struct hash_table *ht, int free_items)); #ifdef CONFIG_WITH_ALLOC_CACHES void hash_free_items_cached __P((struct hash_table *ht, struct alloccache *cache)); void hash_free_cached __P((struct hash_table *ht, int free_items, struct alloccache *cache)); #endif void hash_map __P((struct hash_table *ht, hash_map_func_t map)); void hash_map_arg __P((struct hash_table *ht, hash_map_arg_func_t map, void *arg)); void hash_print_stats __P((struct hash_table *ht, FILE *out_FILE)); void **hash_dump __P((struct hash_table *ht, void **vector_0, qsort_cmp_t compare)); #ifdef CONFIG_WITH_STRCACHE2 void hash_init_strcached __P((struct hash_table *ht, unsigned long size, struct strcache2 *strcache, unsigned int off_strptr)); void **hash_find_slot_strcached __P((struct hash_table *ht, const void *key)); void *hash_find_item_strcached __P((struct hash_table *ht, void const *key)); void *hash_insert_strcached __P((struct hash_table *ht, const void *item)); void *hash_delete_strcached __P((struct hash_table *ht, void const *item)); #endif /* CONFIG_WITH_STRCACHE2 */ extern void *hash_deleted_item; #define HASH_VACANT(item) ((item) == 0 || (void *) (item) == hash_deleted_item) /* hash and comparison macros for case-sensitive string keys. */ /* Due to the strcache, it's not uncommon for the string pointers to be identical. Take advantage of that to short-circuit string compares. */ #define STRING_HASH_1(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0xf)); \ } while (0) #define return_STRING_HASH_1(KEY) do { \ unsigned long _result_ = 0; \ STRING_HASH_1 ((KEY), _result_); \ return _result_; \ } while (0) #define STRING_HASH_2(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0x7)); \ } while (0) #define return_STRING_HASH_2(KEY) do { \ unsigned long _result_ = 0; \ STRING_HASH_2 ((KEY), _result_); \ return _result_; \ } while (0) #define STRING_COMPARE(X, Y, RESULT) do { \ RESULT = (X) == (Y) ? 0 : strcmp ((X), (Y)); \ } while (0) #define return_STRING_COMPARE(X, Y) do { \ return (X) == (Y) ? 0 : strcmp ((X), (Y)); \ } while (0) #define STRING_N_HASH_1(KEY, N, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ int _n_ = (N); \ if (_n_) \ while (--_n_ && *++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0xf)); \ (RESULT) += *++_key_; \ } while (0) #define return_STRING_N_HASH_1(KEY, N) do { \ unsigned long _result_ = 0; \ STRING_N_HASH_1 ((KEY), (N), _result_); \ return _result_; \ } while (0) #define STRING_N_HASH_2(KEY, N, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ int _n_ = (N); \ if (_n_) \ while (--_n_ && *++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0x7)); \ (RESULT) += *++_key_; \ } while (0) #define return_STRING_N_HASH_2(KEY, N) do { \ unsigned long _result_ = 0; \ STRING_N_HASH_2 ((KEY), (N), _result_); \ return _result_; \ } while (0) #define STRING_N_COMPARE(X, Y, N, RESULT) do { \ RESULT = (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \ } while (0) #define return_STRING_N_COMPARE(X, Y, N) do { \ return (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \ } while (0) #ifdef HAVE_CASE_INSENSITIVE_FS /* hash and comparison macros for case-insensitive string _key_s. */ #define ISTRING_HASH_1(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0xf)); \ } while (0) #define return_ISTRING_HASH_1(KEY) do { \ unsigned long _result_ = 0; \ ISTRING_HASH_1 ((KEY), _result_); \ return _result_; \ } while (0) #define ISTRING_HASH_2(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0x7)); \ } while (0) #define return_ISTRING_HASH_2(KEY) do { \ unsigned long _result_ = 0; \ ISTRING_HASH_2 ((KEY), _result_); \ return _result_; \ } while (0) #define ISTRING_COMPARE(X, Y, RESULT) do { \ RESULT = (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \ } while (0) #define return_ISTRING_COMPARE(X, Y) do { \ return (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \ } while (0) #else #define ISTRING_HASH_1(KEY, RESULT) STRING_HASH_1 ((KEY), (RESULT)) #define return_ISTRING_HASH_1(KEY) return_STRING_HASH_1 (KEY) #define ISTRING_HASH_2(KEY, RESULT) STRING_HASH_2 ((KEY), (RESULT)) #define return_ISTRING_HASH_2(KEY) return_STRING_HASH_2 (KEY) #define ISTRING_COMPARE(X, Y, RESULT) STRING_COMPARE ((X), (Y), (RESULT)) #define return_ISTRING_COMPARE(X, Y) return_STRING_COMPARE ((X), (Y)) #endif /* hash and comparison macros for integer _key_s. */ #define INTEGER_HASH_1(KEY, RESULT) do { \ (RESULT) += ((unsigned long)(KEY)); \ } while (0) #define return_INTEGER_HASH_1(KEY) do { \ unsigned long _result_ = 0; \ INTEGER_HASH_1 ((KEY), _result_); \ return _result_; \ } while (0) #define INTEGER_HASH_2(KEY, RESULT) do { \ (RESULT) += ~((unsigned long)(KEY)); \ } while (0) #define return_INTEGER_HASH_2(KEY) do { \ unsigned long _result_ = 0; \ INTEGER_HASH_2 ((KEY), _result_); \ return _result_; \ } while (0) #define INTEGER_COMPARE(X, Y, RESULT) do { \ (RESULT) = X - Y; \ } while (0) #define return_INTEGER_COMPARE(X, Y) do { \ int _result_; \ INTEGER_COMPARE (X, Y, _result_); \ return _result_; \ } while (0) /* hash and comparison macros for address keys. */ #define ADDRESS_HASH_1(KEY, RESULT) INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3, (RESULT)) #define ADDRESS_HASH_2(KEY, RESULT) INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3, (RESULT)) #define ADDRESS_COMPARE(X, Y, RESULT) INTEGER_COMPARE ((X), (Y), (RESULT)) #define return_ADDRESS_HASH_1(KEY) return_INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3) #define return_ADDRESS_HASH_2(KEY) return_INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3) #define return_ADDRESS_COMPARE(X, Y) return_INTEGER_COMPARE ((X), (Y)) #endif /* not _hash_h_ */ kbuild-2695/src/kmk/glob/0000755000000000000000000000000012247157306013734 5ustar rootrootkbuild-2695/src/kmk/glob/glob.c0000644000000000000000000010613712247157306015033 0ustar rootroot/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ /* AIX requires this to be the first thing in the file. */ #if defined _AIX && !defined __GNUC__ #pragma alloca #endif #ifdef HAVE_CONFIG_H # include #endif /* Enable GNU extensions in glob.h. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #include #include #include /* Outcomment the following line for production quality code. */ /* #define NDEBUG 1 */ #include #include /* Needed on stupid SunOS for assert. */ /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GLOB_INTERFACE_VERSION 1 #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 # include # if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE #if defined STDC_HEADERS || defined __GNU_LIBRARY__ # include #endif #if defined HAVE_UNISTD_H || defined _LIBC # include # ifndef POSIX # ifdef _POSIX_VERSION # define POSIX # endif # endif #endif #if !defined _AMIGA && !defined VMS && !defined WINDOWS32 # include #endif #if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS extern int errno; #endif #ifndef __set_errno # define __set_errno(val) errno = (val) #endif #ifndef NULL # define NULL 0 #endif #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif # ifdef HAVE_VMSDIR_H # include "vmsdir.h" # endif /* HAVE_VMSDIR_H */ #endif /* In GNU systems, defines this macro for us. */ #ifdef _D_NAMLEN # undef NAMLEN # define NAMLEN(d) _D_NAMLEN(d) #endif /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available if the `d_type' member for `struct dirent' is available. */ #ifdef _DIRENT_HAVE_D_TYPE # define HAVE_D_TYPE 1 #endif #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ # define REAL_DIR_ENTRY(dp) 1 #else # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) #endif /* POSIX */ #if defined STDC_HEADERS || defined __GNU_LIBRARY__ # include # include # define ANSI_STRING #else /* No standard headers. */ extern char *getenv (); # ifdef HAVE_STRING_H # include # define ANSI_STRING # else # include # endif # ifdef HAVE_MEMORY_H # include # endif extern char *malloc (), *realloc (); extern void free (); extern void qsort (); extern void abort (), exit (); #endif /* Standard headers. */ #ifndef ANSI_STRING # ifndef bzero extern void bzero (); # endif # ifndef bcopy extern void bcopy (); # endif # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define strrchr rindex /* memset is only used for zero here, but let's be paranoid. */ # define memset(s, better_be_zero, n) \ ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0))) #endif /* Not ANSI_STRING. */ #if !defined HAVE_STRCOLL && !defined _LIBC # define strcoll strcmp #endif #if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1 # define HAVE_MEMPCPY 1 # undef mempcpy # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len) #endif #if !defined __GNU_LIBRARY__ && !defined __DJGPP__ && !defined ELECTRIC_HEAP && !defined __APPLE__ /* bird (last two) */ # ifdef __GNUC__ __inline # endif # ifndef __SASC # ifdef WINDOWS32 # include static void * my_realloc (void *p, unsigned int n) # else static char * my_realloc (p, n) char *p; unsigned int n; # endif { /* These casts are the for sake of the broken Ultrix compiler, which warns of illegal pointer combinations otherwise. */ if (p == NULL) return (char *) malloc (n); return (char *) realloc (p, n); } # define realloc my_realloc # endif /* __SASC */ #endif /* __GNU_LIBRARY__ || __DJGPP__ */ #if !defined __alloca && !defined __GNU_LIBRARY__ # ifdef __GNUC__ # undef alloca # define alloca(n) __builtin_alloca (n) # else /* Not GCC. */ # ifdef HAVE_ALLOCA_H # include # else /* Not HAVE_ALLOCA_H. */ # ifndef _AIX # ifdef WINDOWS32 # include # else extern char *alloca (); # endif /* WINDOWS32 */ # endif /* Not _AIX. */ # endif /* sparc or HAVE_ALLOCA_H. */ # endif /* GCC. */ # define __alloca alloca #endif #ifndef __GNU_LIBRARY__ # define __stat stat # ifdef STAT_MACROS_BROKEN # undef S_ISDIR # endif # ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) # endif #endif #ifdef _LIBC # undef strdup # define strdup(str) __strdup (str) # define sysconf(id) __sysconf (id) # define closedir(dir) __closedir (dir) # define opendir(name) __opendir (name) # define readdir(str) __readdir (str) # define getpwnam_r(name, bufp, buf, len, res) \ __getpwnam_r (name, bufp, buf, len, res) # ifndef __stat # define __stat(fname, buf) __xstat (_STAT_VER, fname, buf) # endif #endif #if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) # undef size_t # define size_t unsigned int #endif /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ #ifndef __GNU_LIBRARY__ # undef FNM_PATHNAME # undef FNM_NOESCAPE # undef FNM_PERIOD #endif #include /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ #ifndef __GNU_LIBRARY__ # undef GLOB_ERR # undef GLOB_MARK # undef GLOB_NOSORT # undef GLOB_DOOFFS # undef GLOB_NOCHECK # undef GLOB_APPEND # undef GLOB_NOESCAPE # undef GLOB_PERIOD #endif #include #ifdef HAVE_GETLOGIN_R extern int getlogin_r __P ((char *, size_t)); #else extern char *getlogin __P ((void)); #endif static #if __GNUC__ - 0 >= 2 inline #endif const char *next_brace_sub __P ((const char *begin)); static int glob_in_dir __P ((const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), glob_t *pglob)); static int prefix_array __P ((const char *prefix, char **array, size_t n)); static int collated_compare __P ((const __ptr_t, const __ptr_t)); #if !defined _LIBC || !defined NO_GLOB_PATTERN_P int __glob_pattern_p __P ((const char *pattern, int quote)); #endif /* Find the end of the sub-pattern in a brace expression. We define this as an inline function if the compiler permits. */ static #if __GNUC__ - 0 >= 2 inline #endif const char * next_brace_sub (begin) const char *begin; { unsigned int depth = 0; const char *cp = begin; while (1) { if (depth == 0) { if (*cp != ',' && *cp != '}' && *cp != '\0') { if (*cp == '{') ++depth; ++cp; continue; } } else { while (*cp != '\0' && (*cp != '}' || depth > 0)) { if (*cp == '}') --depth; ++cp; } if (*cp == '\0') /* An incorrectly terminated brace expression. */ return NULL; continue; } break; } return cp; } /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, it is called with the pathname that caused the error, and the `errno' value from the failing call; if it returns non-zero `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. Otherwise, `glob' returns zero. */ int glob (pattern, flags, errfunc, pglob) const char *pattern; int flags; int (*errfunc) __P ((const char *, int)); glob_t *pglob; { const char *filename; const char *dirname; size_t dirlen; int status; __size_t oldcount; /* bird: correct type. */ if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) { __set_errno (EINVAL); return -1; } if (flags & GLOB_BRACE) { const char *begin = strchr (pattern, '{'); if (begin != NULL) { /* Allocate working buffer large enough for our work. Note that we have at least an opening and closing brace. */ size_t firstc; /* bird: correct type. */ char *alt_start; const char *p; const char *next; const char *rest; size_t rest_len; #ifdef __GNUC__ char onealt[strlen (pattern) - 1]; #else char *onealt = (char *) malloc (strlen (pattern) - 1); if (onealt == NULL) { if (!(flags & GLOB_APPEND)) globfree (pglob); return GLOB_NOSPACE; } #endif /* We know the prefix for all sub-patterns. */ #ifdef HAVE_MEMPCPY alt_start = mempcpy (onealt, pattern, begin - pattern); #else memcpy (onealt, pattern, begin - pattern); alt_start = &onealt[begin - pattern]; #endif /* Find the first sub-pattern and at the same time find the rest after the closing brace. */ next = next_brace_sub (begin + 1); if (next == NULL) { /* It is an illegal expression. */ #ifndef __GNUC__ free (onealt); #endif return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); } /* Now find the end of the whole brace expression. */ rest = next; while (*rest != '}') { rest = next_brace_sub (rest + 1); if (rest == NULL) { /* It is an illegal expression. */ #ifndef __GNUC__ free (onealt); #endif return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); } } /* Please note that we now can be sure the brace expression is well-formed. */ rest_len = strlen (++rest) + 1; /* We have a brace expression. BEGIN points to the opening {, NEXT points past the terminator of the first element, and END points past the final }. We will accumulate result names from recursive runs for each brace alternative in the buffer using GLOB_APPEND. */ if (!(flags & GLOB_APPEND)) { /* This call is to set a new vector, so clear out the vector so we can append to it. */ pglob->gl_pathc = 0; pglob->gl_pathv = NULL; } firstc = pglob->gl_pathc; p = begin + 1; while (1) { int result; /* Construct the new glob expression. */ #ifdef HAVE_MEMPCPY mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); #else memcpy (alt_start, p, next - p); memcpy (&alt_start[next - p], rest, rest_len); #endif result = glob (onealt, ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) | GLOB_APPEND), errfunc, pglob); /* If we got an error, return it. */ if (result && result != GLOB_NOMATCH) { #ifndef __GNUC__ free (onealt); #endif if (!(flags & GLOB_APPEND)) globfree (pglob); return result; } if (*next == '}') /* We saw the last entry. */ break; p = next + 1; next = next_brace_sub (p); assert (next != NULL); } #ifndef __GNUC__ free (onealt); #endif if (pglob->gl_pathc != firstc) /* We found some entries. */ return 0; else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) return GLOB_NOMATCH; } } /* Find the filename. */ filename = strrchr (pattern, '/'); #if defined __MSDOS__ || defined WINDOWS32 /* The case of "d:pattern". Since `:' is not allowed in file names, we can safely assume that wherever it happens in pattern, it signals the filename part. This is so we could some day support patterns like "[a-z]:foo". */ if (filename == NULL) filename = strchr (pattern, ':'); #endif /* __MSDOS__ || WINDOWS32 */ if (filename == NULL) { /* This can mean two things: a simple name or "~name". The later case is nothing but a notation for a directory. */ if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') { dirname = pattern; dirlen = strlen (pattern); /* Set FILENAME to NULL as a special flag. This is ugly but other solutions would require much more code. We test for this special case below. */ filename = NULL; } else { filename = pattern; #ifdef _AMIGA dirname = ""; #else dirname = "."; #endif dirlen = 0; } } else if (filename == pattern) { /* "/pattern". */ dirname = "/"; dirlen = 1; ++filename; } else { char *newp; dirlen = filename - pattern; #if defined __MSDOS__ || defined WINDOWS32 if (*filename == ':' || (filename > pattern + 1 && filename[-1] == ':')) { char *drive_spec; ++dirlen; drive_spec = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; #else memcpy (drive_spec, pattern, dirlen); drive_spec[dirlen] = '\0'; #endif /* For now, disallow wildcards in the drive spec, to prevent infinite recursion in glob. */ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) return GLOB_NOMATCH; /* If this is "d:pattern", we need to copy `:' to DIRNAME as well. If it's "d:/pattern", don't remove the slash from "d:/", since "d:" and "d:/" are not the same.*/ } #endif newp = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; #else memcpy (newp, pattern, dirlen); newp[dirlen] = '\0'; #endif dirname = newp; ++filename; if (filename[0] == '\0' #if defined __MSDOS__ || defined WINDOWS32 && dirname[dirlen - 1] != ':' && (dirlen < 3 || dirname[dirlen - 2] != ':' || dirname[dirlen - 1] != '/') #endif && dirlen > 1) /* "pattern/". Expand "pattern", appending slashes. */ { int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); if (val == 0) pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK)); return val; } } if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; } oldcount = pglob->gl_pathc; #ifndef VMS if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') { if (dirname[1] == '\0' || dirname[1] == '/') { /* Look up home directory. */ #ifdef VMS /* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */ const char *home_dir = getenv ("SYS$LOGIN"); #else const char *home_dir = getenv ("HOME"); #endif # ifdef _AMIGA if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS:"; # else # ifdef WINDOWS32 if (home_dir == NULL || home_dir[0] == '\0') home_dir = "c:/users/default"; /* poor default */ # else # ifdef VMS /* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */ if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS$DISK:[]"; # else if (home_dir == NULL || home_dir[0] == '\0') { int success; char *name; # if defined HAVE_GETLOGIN_R || defined _LIBC size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; if (buflen == 0) /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try a moderate value. */ buflen = 20; name = (char *) __alloca (buflen); success = getlogin_r (name, buflen) >= 0; # else success = (name = getlogin ()) != NULL; # endif if (success) { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; struct passwd pwbuf; int save = errno; if (pwbuflen == -1) /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a moderate value. */ pwbuflen = 1024; pwtmpbuf = (char *) __alloca (pwbuflen); while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) != 0) { if (errno != ERANGE) { p = NULL; break; } pwbuflen *= 2; pwtmpbuf = (char *) __alloca (pwbuflen); __set_errno (save); } # else p = getpwnam (name); # endif if (p != NULL) home_dir = p->pw_dir; } } if (home_dir == NULL || home_dir[0] == '\0') { if (flags & GLOB_TILDE_CHECK) return GLOB_NOMATCH; else home_dir = "~"; /* No luck. */ } # endif /* VMS */ # endif /* WINDOWS32 */ # endif /* Now construct the full directory. */ if (dirname[1] == '\0') dirname = home_dir; else { char *newp; size_t home_len = strlen (home_dir); newp = (char *) __alloca (home_len + dirlen); # ifdef HAVE_MEMPCPY mempcpy (mempcpy (newp, home_dir, home_len), &dirname[1], dirlen); # else memcpy (newp, home_dir, home_len); memcpy (&newp[home_len], &dirname[1], dirlen); # endif dirname = newp; } } # if !defined _AMIGA && !defined WINDOWS32 && !defined VMS else { char *end_name = strchr (dirname, '/'); const char *user_name; const char *home_dir; if (end_name == NULL) user_name = dirname + 1; else { char *newp; newp = (char *) __alloca (end_name - dirname); # ifdef HAVE_MEMPCPY *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) = '\0'; # else memcpy (newp, dirname + 1, end_name - dirname); newp[end_name - dirname - 1] = '\0'; # endif user_name = newp; } /* Look up specific user's home directory. */ { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; struct passwd pwbuf; int save = errno; if (buflen == -1) /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a moderate value. */ buflen = 1024; pwtmpbuf = (char *) __alloca (buflen); while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) { if (errno != ERANGE) { p = NULL; break; } buflen *= 2; pwtmpbuf = __alloca (buflen); __set_errno (save); } # else p = getpwnam (user_name); # endif if (p != NULL) home_dir = p->pw_dir; else home_dir = NULL; } /* If we found a home directory use this. */ if (home_dir != NULL) { char *newp; size_t home_len = strlen (home_dir); size_t rest_len = end_name == NULL ? 0 : strlen (end_name); newp = (char *) __alloca (home_len + rest_len + 1); # ifdef HAVE_MEMPCPY *((char *) mempcpy (mempcpy (newp, home_dir, home_len), end_name, rest_len)) = '\0'; # else memcpy (newp, home_dir, home_len); memcpy (&newp[home_len], end_name, rest_len); newp[home_len + rest_len] = '\0'; # endif dirname = newp; } else if (flags & GLOB_TILDE_CHECK) /* We have to regard it as an error if we cannot find the home directory. */ return GLOB_NOMATCH; } # endif /* Not Amiga && not WINDOWS32 && not VMS. */ } #endif /* Not VMS. */ /* Now test whether we looked for "~" or "~NAME". In this case we can give the answer now. */ if (filename == NULL) { struct stat st; /* Return the directory if we don't check for error or if it exists. */ if ((flags & GLOB_NOCHECK) || (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (dirname, &st) : __stat (dirname, &st)) == 0 && S_ISDIR (st.st_mode))) { pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; #if defined HAVE_STRDUP || defined _LIBC pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname); #else { size_t len = strlen (dirname) + 1; char *dircopy = malloc (len); if (dircopy != NULL) pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname, len); } #endif if (pglob->gl_pathv[pglob->gl_pathc] == NULL) { free (pglob->gl_pathv); return GLOB_NOSPACE; } pglob->gl_pathv[++pglob->gl_pathc] = NULL; pglob->gl_flags = flags; return 0; } /* Not found. */ return GLOB_NOMATCH; } if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) { /* The directory name contains metacharacters, so we have to glob for the directory, and then glob for the pattern in each directory found. */ glob_t dirs; register __size_t i; /* bird: correct type. */ status = glob (dirname, ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs); if (status != 0) return status; /* We have successfully globbed the preceding directory name. For each name we found, call glob_in_dir on it and FILENAME, appending the results to PGLOB. */ for (i = 0; i < dirs.gl_pathc; ++i) { int old_pathc; #ifdef SHELL { /* Make globbing interruptible in the bash shell. */ extern int interrupt_state; if (interrupt_state) { globfree (&dirs); globfree (&files); return GLOB_ABORTED; } } #endif /* SHELL. */ old_pathc = pglob->gl_pathc; status = glob_in_dir (filename, dirs.gl_pathv[i], ((flags | GLOB_APPEND) & ~(GLOB_NOCHECK | GLOB_ERR)), errfunc, pglob); if (status == GLOB_NOMATCH) /* No matches in this directory. Try the next. */ continue; if (status != 0) { globfree (&dirs); globfree (pglob); return status; } /* Stick the directory on the front of each name. */ if (prefix_array (dirs.gl_pathv[i], &pglob->gl_pathv[old_pathc], pglob->gl_pathc - old_pathc)) { globfree (&dirs); globfree (pglob); return GLOB_NOSPACE; } } flags |= GLOB_MAGCHAR; /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. But if we have not found any matching entry and thie GLOB_NOCHECK flag was set we must return the list consisting of the disrectory names followed by the filename. */ if (pglob->gl_pathc == oldcount) { /* No matches. */ if (flags & GLOB_NOCHECK) { size_t filename_len = strlen (filename) + 1; char **new_pathv; struct stat st; /* This is an pessimistic guess about the size. */ pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) { globfree (&dirs); return GLOB_NOSPACE; } if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; for (i = 0; i < dirs.gl_pathc; ++i) { const char *dir = dirs.gl_pathv[i]; size_t dir_len = strlen (dir); /* First check whether this really is a directory. */ if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0 || !S_ISDIR (st.st_mode)) /* No directory, ignore this entry. */ continue; pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1 + filename_len); if (pglob->gl_pathv[pglob->gl_pathc] == NULL) { globfree (&dirs); globfree (pglob); return GLOB_NOSPACE; } #ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len), "/", 1), filename, filename_len); #else memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len); pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/'; memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1], filename, filename_len); #endif ++pglob->gl_pathc; } pglob->gl_pathv[pglob->gl_pathc] = NULL; pglob->gl_flags = flags; /* Now we know how large the gl_pathv vector must be. */ new_pathv = (char **) realloc (pglob->gl_pathv, ((pglob->gl_pathc + 1) * sizeof (char *))); if (new_pathv != NULL) pglob->gl_pathv = new_pathv; } else return GLOB_NOMATCH; } globfree (&dirs); } else { status = glob_in_dir (filename, dirname, flags, errfunc, pglob); if (status != 0) return status; if (dirlen > 0) { /* Stick the directory on the front of each name. */ __size_t ignore = oldcount; /* bird: correct type. */ if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs) ignore = pglob->gl_offs; if (prefix_array (dirname, &pglob->gl_pathv[ignore], pglob->gl_pathc - ignore)) { globfree (pglob); return GLOB_NOSPACE; } } } if (flags & GLOB_MARK) { /* Append slashes to directory names. */ __size_t i; /* bird: correct type. */ struct stat st; for (i = oldcount; i < pglob->gl_pathc; ++i) if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) : __stat (pglob->gl_pathv[i], &st)) == 0 && S_ISDIR (st.st_mode)) { size_t len = strlen (pglob->gl_pathv[i]) + 2; char *new = realloc (pglob->gl_pathv[i], len); if (new == NULL) { globfree (pglob); return GLOB_NOSPACE; } strcpy (&new[len - 2], "/"); pglob->gl_pathv[i] = new; } } if (!(flags & GLOB_NOSORT)) { /* Sort the vector. */ int non_sort = oldcount; if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount) non_sort = pglob->gl_offs; qsort ((__ptr_t) &pglob->gl_pathv[non_sort], pglob->gl_pathc - non_sort, sizeof (char *), collated_compare); } return 0; } /* Free storage allocated in PGLOB by a previous `glob' call. */ void globfree (pglob) register glob_t *pglob; { if (pglob->gl_pathv != NULL) { register __size_t i; /* bird: correct type */ for (i = 0; i < pglob->gl_pathc; ++i) if (pglob->gl_pathv[i] != NULL) free ((__ptr_t) pglob->gl_pathv[i]); free ((__ptr_t) pglob->gl_pathv); } } /* Do a collated comparison of A and B. */ static int collated_compare (a, b) const __ptr_t a; const __ptr_t b; { const char *const s1 = *(const char *const * const) a; const char *const s2 = *(const char *const * const) b; if (s1 == s2) return 0; if (s1 == NULL) return 1; if (s2 == NULL) return -1; return strcoll (s1, s2); } /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's elements in place. Return nonzero if out of memory, zero if successful. A slash is inserted between DIRNAME and each elt of ARRAY, unless DIRNAME is just "/". Each old element of ARRAY is freed. */ static int prefix_array (dirname, array, n) const char *dirname; char **array; size_t n; { register size_t i; size_t dirlen = strlen (dirname); #if defined __MSDOS__ || defined WINDOWS32 int sep_char = '/'; # define DIRSEP_CHAR sep_char #else # define DIRSEP_CHAR '/' #endif if (dirlen == 1 && dirname[0] == '/') /* DIRNAME is just "/", so normal prepending would get us "//foo". We want "/foo" instead, so don't prepend any chars from DIRNAME. */ dirlen = 0; #if defined __MSDOS__ || defined WINDOWS32 else if (dirlen > 1) { if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ --dirlen; else if (dirname[dirlen - 1] == ':') { /* DIRNAME is "d:". Use `:' instead of `/'. */ --dirlen; sep_char = ':'; } } #endif for (i = 0; i < n; ++i) { size_t eltlen = strlen (array[i]) + 1; char *new = (char *) malloc (dirlen + 1 + eltlen); if (new == NULL) { while (i > 0) free ((__ptr_t) array[--i]); return 1; } #ifdef HAVE_MEMPCPY { char *endp = (char *) mempcpy (new, dirname, dirlen); *endp++ = DIRSEP_CHAR; mempcpy (endp, array[i], eltlen); } #else memcpy (new, dirname, dirlen); new[dirlen] = DIRSEP_CHAR; memcpy (&new[dirlen + 1], array[i], eltlen); #endif free ((__ptr_t) array[i]); array[i] = new; } return 0; } /* We must not compile this function twice. */ #if !defined _LIBC || !defined NO_GLOB_PATTERN_P /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ int __glob_pattern_p (pattern, quote) const char *pattern; int quote; { register const char *p; int open = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) { case '?': case '*': return 1; case '\\': if (quote && p[1] != '\0') ++p; break; case '[': open = 1; break; case ']': if (open) return 1; break; } return 0; } # ifdef _LIBC weak_alias (__glob_pattern_p, glob_pattern_p) # endif #endif /* Like `glob', but PATTERN is a final pathname component, and matches are searched for in DIRECTORY. The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. The GLOB_APPEND flag is assumed to be set (always appends). */ static int glob_in_dir (pattern, directory, flags, errfunc, pglob) const char *pattern; const char *directory; int flags; int (*errfunc) __P ((const char *, int)); glob_t *pglob; { __ptr_t stream = NULL; struct globlink { struct globlink *next; char *name; }; struct globlink *names = NULL; size_t nfound; int meta; int save; #ifdef VMS if (*directory == 0) directory = "[]"; #endif meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); if (meta == 0) { if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)) /* We need not do any tests. The PATTERN contains no meta characters and we must not return an error therefore the result will always contain exactly one name. */ flags |= GLOB_NOCHECK; else { /* Since we use the normal file functions we can also use stat() to verify the file is there. */ struct stat st; size_t patlen = strlen (pattern); size_t dirlen = strlen (directory); char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); # ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), "/", 1), pattern, patlen + 1); # else memcpy (fullname, directory, dirlen); fullname[dirlen] = '/'; memcpy (&fullname[dirlen + 1], pattern, patlen + 1); # endif if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (fullname, &st) : __stat (fullname, &st)) == 0) /* We found this file to be existing. Now tell the rest of the function to copy this name into the result. */ flags |= GLOB_NOCHECK; } nfound = 0; } else { if (pattern[0] == '\0') { /* This is a special case for matching directories like in "*a/". */ names = (struct globlink *) __alloca (sizeof (struct globlink)); names->name = (char *) malloc (1); if (names->name == NULL) goto memory_error; names->name[0] = '\0'; names->next = NULL; nfound = 1; meta = 0; } else { stream = ((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_opendir) (directory) : (__ptr_t) opendir (directory)); if (stream == NULL) { if (errno != ENOTDIR && ((errfunc != NULL && (*errfunc) (directory, errno)) || (flags & GLOB_ERR))) return GLOB_ABORTED; nfound = 0; meta = 0; } else { int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) #if defined HAVE_CASE_INSENSITIVE_FS | FNM_CASEFOLD #endif ); nfound = 0; flags |= GLOB_MAGCHAR; while (1) { const char *name; size_t len; struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_readdir) (stream) : readdir ((DIR *) stream)); if (d == NULL) break; if (! REAL_DIR_ENTRY (d)) continue; #ifdef HAVE_D_TYPE /* If we shall match only directories use the information provided by the dirent call if possible. */ if ((flags & GLOB_ONLYDIR) && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR) continue; #endif name = d->d_name; if (fnmatch (pattern, name, fnm_flags) == 0) { struct globlink *new = (struct globlink *) __alloca (sizeof (struct globlink)); len = NAMLEN (d); new->name = (char *) malloc (len + 1); if (new->name == NULL) goto memory_error; #ifdef HAVE_MEMPCPY *((char *) mempcpy ((__ptr_t) new->name, name, len)) = '\0'; #else memcpy ((__ptr_t) new->name, name, len); new->name[len] = '\0'; #endif new->next = names; names = new; ++nfound; } } } } } if (nfound == 0 && (flags & GLOB_NOCHECK)) { size_t len = strlen (pattern); nfound = 1; names = (struct globlink *) __alloca (sizeof (struct globlink)); names->next = NULL; names->name = (char *) malloc (len + 1); if (names->name == NULL) goto memory_error; #ifdef HAVE_MEMPCPY *((char *) mempcpy (names->name, pattern, len)) = '\0'; #else memcpy (names->name, pattern, len); names->name[len] = '\0'; #endif } if (nfound != 0) { pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + nfound + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) goto memory_error; if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; for (; names != NULL; names = names->next) pglob->gl_pathv[pglob->gl_pathc++] = names->name; pglob->gl_pathv[pglob->gl_pathc] = NULL; pglob->gl_flags = flags; } save = errno; if (stream != NULL) { if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else closedir ((DIR *) stream); } __set_errno (save); return nfound == 0 ? GLOB_NOMATCH : 0; memory_error: { int save = errno; if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else closedir ((DIR *) stream); __set_errno (save); } while (names != NULL) { if (names->name != NULL) free ((__ptr_t) names->name); names = names->next; } return GLOB_NOSPACE; } #endif /* Not ELIDE_CODE. */ kbuild-2695/src/kmk/glob/fnmatch.h0000644000000000000000000000556312247157306015536 0ustar rootroot/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _FNMATCH_H #define _FNMATCH_H 1 #ifdef __cplusplus extern "C" { #endif #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ # undef __P # define __P(protos) protos # endif #else /* Not C++ or ANSI C. */ # undef __P # define __P(protos) () /* We can get away without defining `const' here only because in this file it is used only inside the prototype for `fnmatch', which is elided in non-ANSI C where `const' is problematical. */ #endif /* C++ or ANSI C. */ #ifndef const # if (defined __STDC__ && __STDC__) || defined __cplusplus || defined WINDOWS32 # define __const const # else # define __const # endif #endif /* We #undef these before defining them because some losing systems (HP-UX A.08.07 for example) define these in . */ #undef FNM_PATHNAME #undef FNM_NOESCAPE #undef FNM_PERIOD /* Bits set in the FLAGS argument to `fnmatch'. */ #define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ #define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ #define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ #if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE # define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ # define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ # define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ #endif /* Value returned by `fnmatch' if STRING does not match PATTERN. */ #define FNM_NOMATCH 1 /* This value is returned if the implementation does not support `fnmatch'. Since this is not the case here it will never be returned but the conformance test suites still require the symbol to be defined. */ #ifdef _XOPEN_SOURCE # define FNM_NOSYS (-1) #endif /* Match NAME against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ extern int fnmatch __P ((__const char *__pattern, __const char *__name, int __flags)); #ifdef __cplusplus } #endif #endif /* fnmatch.h */ kbuild-2695/src/kmk/glob/Makefile.ami0000644000000000000000000000377612247157306016156 0ustar rootroot# Makefile for standalone libglob.a (fnmatch, glob). -*-Makefile-*- # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # Ultrix 2.2 make doesn't expand the value of VPATH. VPATH = /glob/ # This must repeat the value, because configure will remove `VPATH = .'. srcdir = /glob/ CC = sc RM = delete CPPFLAGS = CFLAGS = # Information determined by configure. DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \ Define HAVE_DIRENT_H # How to invoke ar. AR = join ARFLAGS = as # How to invoke ranlib. RANLIB = ; .PHONY: all all: glob.lib glob.lib : glob.o fnmatch.o $(AR) $(ARFLAGS) $@ glob.o fnmatch.o $(RANLIB) $@ # For some reason, Unix make wants the dependencies on the source files. # Otherwise it refuses to use an implicit rule! # And, get this: it doesn't work to use $(srcdir)foo.c!! glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c fnmatch.o: $(srcdir)fnmatch.h fnmatch.c OUTPUT_OPTION = .c.o: $(CC) IDir "" \ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) .PHONY: clean realclean glob-clean glob-realclean distclean clean glob-clean: -$(RM) glob.lib "#?.o" core distclean glob-realclean: clean -$(RM) TAGS tags Makefile config.status config.h config.log realcean: distclean # For inside the C library. glob.tar glob.tar.Z: $(MAKE) -C .. $@ kbuild-2695/src/kmk/glob/fnmatch.c0000644000000000000000000003114712247157306015526 0ustar rootroot/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #if HAVE_CONFIG_H # include #endif /* Enable GNU extensions in fnmatch.h. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #include #include #include #if HAVE_STRING_H || defined _LIBC # include #else # include #endif #if defined STDC_HEADERS || defined _LIBC # include #endif /* For platform which support the ISO C amendement 1 functionality we support user defined character classes. */ #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) /* Solaris 2.5 has a bug: must be included before . */ # include # include #endif /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined _LIBC || !defined __GNU_LIBRARY__ # if defined STDC_HEADERS || !defined isascii # define ISASCII(c) 1 # else # define ISASCII(c) isascii(c) # endif # ifdef isblank # define ISBLANK(c) (ISASCII (c) && isblank (c)) # else # define ISBLANK(c) ((c) == ' ' || (c) == '\t') # endif # ifdef isgraph # define ISGRAPH(c) (ISASCII (c) && isgraph (c)) # else # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) # endif # define ISPRINT(c) (ISASCII (c) && isprint (c)) # define ISDIGIT(c) (ISASCII (c) && isdigit (c)) # define ISALNUM(c) (ISASCII (c) && isalnum (c)) # define ISALPHA(c) (ISASCII (c) && isalpha (c)) # define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) # define ISLOWER(c) (ISASCII (c) && islower (c)) # define ISPUNCT(c) (ISASCII (c) && ispunct (c)) # define ISSPACE(c) (ISASCII (c) && isspace (c)) # define ISUPPER(c) (ISASCII (c) && isupper (c)) # define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) # define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) /* The GNU C library provides support for user-defined character classes and the functions from ISO C amendement 1. */ # ifdef CHARCLASS_NAME_MAX # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX # else /* This shouldn't happen but some implementation might still have this problem. Use a reasonable default value. */ # define CHAR_CLASS_MAX_LENGTH 256 # endif # ifdef _LIBC # define IS_CHAR_CLASS(string) __wctype (string) # else # define IS_CHAR_CLASS(string) wctype (string) # endif # else # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ # define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ || STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "cntrl") || STREQ (string, "blank")) # endif /* Avoid depending on library functions or files whose names are inconsistent. */ # if !defined _LIBC && !defined getenv && !defined _MSC_VER extern char *getenv (); # endif # ifndef errno extern int errno; # endif /* This function doesn't exist on most systems. */ # if !defined HAVE___STRCHRNUL && !defined _LIBC static char * __strchrnul (s, c) const char *s; int c; { char *result = strchr (s, c); if (result == NULL) result = strchr (s, '\0'); return result; } # endif # ifndef internal_function /* Inside GNU libc we mark some function in a special way. In other environments simply ignore the marking. */ # define internal_function # endif /* Match STRING against the filename pattern PATTERN, returning zero if it matches, nonzero if not. */ static int internal_fnmatch __P ((const char *pattern, const char *string, int no_leading_period, int flags)) internal_function; static int internal_function internal_fnmatch (pattern, string, no_leading_period, flags) const char *pattern; const char *string; int no_leading_period; int flags; { register const char *p = pattern, *n = string; register unsigned char c; /* Note that this evaluates C many times. */ # ifdef _LIBC # define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) # else # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) # endif while ((c = *p++) != '\0') { c = FOLD (c); switch (c) { case '?': if (*n == '\0') return FNM_NOMATCH; else if (*n == '/' && (flags & FNM_FILE_NAME)) return FNM_NOMATCH; else if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; break; case '\\': if (!(flags & FNM_NOESCAPE)) { c = *p++; if (c == '\0') /* Trailing \ loses. */ return FNM_NOMATCH; c = FOLD (c); } if (FOLD ((unsigned char) *n) != c) return FNM_NOMATCH; break; case '*': if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; for (c = *p++; c == '?' || c == '*'; c = *p++) { if (*n == '/' && (flags & FNM_FILE_NAME)) /* A slash does not match a wildcard under FNM_FILE_NAME. */ return FNM_NOMATCH; else if (c == '?') { /* A ? needs to match one character. */ if (*n == '\0') /* There isn't another character; no match. */ return FNM_NOMATCH; else /* One character of the string is consumed in matching this ? wildcard, so *??? won't match if there are less than three characters. */ ++n; } } if (c == '\0') /* The wildcard(s) is/are the last element of the pattern. If the name is a file name and contains another slash this does mean it cannot match. */ return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL ? FNM_NOMATCH : 0); else { const char *endp; endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); if (c == '[') { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); for (--p; n < endp; ++n) if (internal_fnmatch (p, n, (no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))), flags2) == 0) return 0; } else if (c == '/' && (flags & FNM_FILE_NAME)) { while (*n != '\0' && *n != '/') ++n; if (*n == '/' && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, flags) == 0)) return 0; } else { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); if (c == '\\' && !(flags & FNM_NOESCAPE)) c = *p; c = FOLD (c); for (--p; n < endp; ++n) if (FOLD ((unsigned char) *n) == c && (internal_fnmatch (p, n, (no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))), flags2) == 0)) return 0; } } /* If we come here no match is possible with the wildcard. */ return FNM_NOMATCH; case '[': { /* Nonzero if the sense of the character class is inverted. */ static int posixly_correct; register int not; char cold; if (posixly_correct == 0) posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; if (*n == '\0') return FNM_NOMATCH; if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; if (*n == '/' && (flags & FNM_FILE_NAME)) /* `/' cannot be matched. */ return FNM_NOMATCH; not = (*p == '!' || (posixly_correct < 0 && *p == '^')); if (not) ++p; c = *p++; for (;;) { unsigned char fn = FOLD ((unsigned char) *n); if (!(flags & FNM_NOESCAPE) && c == '\\') { if (*p == '\0') return FNM_NOMATCH; c = FOLD ((unsigned char) *p); ++p; if (c == fn) goto matched; } else if (c == '[' && *p == ':') { /* Leave room for the null. */ char str[CHAR_CLASS_MAX_LENGTH + 1]; size_t c1 = 0; # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) wctype_t wt; # endif const char *startp = p; for (;;) { if (c1 == CHAR_CLASS_MAX_LENGTH) /* The name is too long and therefore the pattern is ill-formed. */ return FNM_NOMATCH; c = *++p; if (c == ':' && p[1] == ']') { p += 2; break; } if (c < 'a' || c >= 'z') { /* This cannot possibly be a character class name. Match it as a normal range. */ p = startp; c = '['; goto normal_bracket; } str[c1++] = c; } str[c1] = '\0'; # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) wt = IS_CHAR_CLASS (str); if (wt == 0) /* Invalid character class name. */ return FNM_NOMATCH; if (__iswctype (__btowc ((unsigned char) *n), wt)) goto matched; # else if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) goto matched; # endif } else if (c == '\0') /* [ (unterminated) loses. */ return FNM_NOMATCH; else { normal_bracket: if (FOLD (c) == fn) goto matched; cold = c; c = *p++; if (c == '-' && *p != ']') { /* It is a range. */ unsigned char cend = *p++; if (!(flags & FNM_NOESCAPE) && cend == '\\') cend = *p++; if (cend == '\0') return FNM_NOMATCH; if (cold <= fn && fn <= FOLD (cend)) goto matched; c = *p++; } } if (c == ']') break; } if (!not) return FNM_NOMATCH; break; matched: /* Skip the rest of the [...] that already matched. */ while (c != ']') { if (c == '\0') /* [... (unterminated) loses. */ return FNM_NOMATCH; c = *p++; if (!(flags & FNM_NOESCAPE) && c == '\\') { if (*p == '\0') return FNM_NOMATCH; /* XXX 1003.2d11 is unclear if this is right. */ ++p; } else if (c == '[' && *p == ':') { do if (*++p == '\0') return FNM_NOMATCH; while (*p != ':' || p[1] == ']'); p += 2; c = *p; } } if (not) return FNM_NOMATCH; } break; default: if (c != FOLD ((unsigned char) *n)) return FNM_NOMATCH; } ++n; } if (*n == '\0') return 0; if ((flags & FNM_LEADING_DIR) && *n == '/') /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ return 0; return FNM_NOMATCH; # undef FOLD } int fnmatch (pattern, string, flags) const char *pattern; const char *string; int flags; { return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); } #endif /* _LIBC or not __GNU_LIBRARY__. */ kbuild-2695/src/kmk/glob/SMakefile0000644000000000000000000000376312247157306015530 0ustar rootroot# Makefile for standalone distribution of libglob.a (fnmatch, glob). # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # Ultrix 2.2 make doesn't expand the value of VPATH. VPATH = /glob/ # This must repeat the value, because configure will remove `VPATH = .'. srcdir = /glob/ CC = sc CPPFLAGS = CFLAGS = MAKE = smake RM = delete # Information determined by configure. DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \ Define HAVE_DIRENT_H # How to invoke ar. AR = join ARFLAGS = as # How to invoke ranlib. RANLIB = ; .PHONY: all all: glob.lib glob.lib : glob.o fnmatch.o $(AR) $(ARFLAGS) $@ glob.o fnmatch.o $(RANLIB) $@ # For some reason, Unix make wants the dependencies on the source files. # Otherwise it refuses to use an implicit rule! # And, get this: it doesn't work to use $(srcdir)foo.c!! glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c fnmatch.o: $(srcdir)fnmatch.h fnmatch.c .c.o: $(CC) IDir "" \ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) .PHONY: clean realclean glob-clean glob-realclean distclean clean glob-clean: -$(RM) -f glob.lib *.o core distclean glob-realclean: clean -$(RM) -f TAGS tags Makefile config.status config.h config.log realcean: distclean # For inside the C library. glob.tar glob.tar.Z: $(MAKE) -C .. $@ kbuild-2695/src/kmk/glob/Makefile.am0000644000000000000000000000214412247157306015771 0ustar rootroot# -*-Makefile-*-, or close enough # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . AUTOMAKE_OPTIONS = foreign # Only build the library when the system doesn't already have GNU glob. if USE_LOCAL_GLOB noinst_LIBRARIES = libglob.a endif libglob_a_SOURCES = glob.c glob.h fnmatch.c fnmatch.h EXTRA_DIST = COPYING.LIB Makefile.ami SCOPTIONS SMakefile \ configure.bat kbuild-2695/src/kmk/glob/COPYING.LIB0000644000000000000000000006125712247157306015407 0ustar rootroot GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! kbuild-2695/src/kmk/glob/glob.h0000644000000000000000000001644612247157306015043 0ustar rootroot/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _GLOB_H #define _GLOB_H 1 #ifdef __cplusplus extern "C" { #endif #undef __ptr_t #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ # undef __P # undef __PMT # define __P(protos) protos # define __PMT(protos) protos # if !defined __GNUC__ || __GNUC__ < 2 # undef __const # define __const const # endif # endif # define __ptr_t void * #else /* Not C++ or ANSI C. */ # undef __P # undef __PMT # define __P(protos) () # define __PMT(protos) () # undef __const # define __const # define __ptr_t char * #endif /* C++ or ANSI C. */ /* We need `size_t' for the following definitions. */ #ifndef __size_t # if defined __FreeBSD__ # define __size_t size_t # else # if defined __GNUC__ && __GNUC__ >= 2 typedef __SIZE_TYPE__ __size_t; # else /* This is a guess. */ /*hb * Conflicts with DECCs aready defined type __size_t. * Defining an own type with a name beginning with '__' is no good. * Anyway if DECC is used and __SIZE_T is defined then __size_t is * already defined (and I hope it's exactly the one we need here). */ # if !(defined __DECC && defined __SIZE_T) typedef unsigned long int __size_t; # endif # endif # endif #else /* The GNU CC stddef.h version defines __size_t as empty. We need a real definition. */ # undef __size_t # define __size_t size_t #endif /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ #define GLOB_NOSORT (1 << 2)/* Don't sort the names. */ #define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */ #define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */ #define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */ #define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */ #define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */ #if (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _BSD_SOURCE \ || defined _GNU_SOURCE) # define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */ # define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */ # define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */ # define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ # define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */ # define GLOB_ONLYDIR (1 << 13)/* Match only directories. */ # define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error if the user name is not available. */ # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) #else # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ GLOB_PERIOD) #endif /* Error returns from `glob'. */ #define GLOB_NOSPACE 1 /* Ran out of memory. */ #define GLOB_ABORTED 2 /* Read error. */ #define GLOB_NOMATCH 3 /* No matches found. */ #define GLOB_NOSYS 4 /* Not implemented. */ #ifdef _GNU_SOURCE /* Previous versions of this file defined GLOB_ABEND instead of GLOB_ABORTED. Provide a compatibility definition here. */ # define GLOB_ABEND GLOB_ABORTED #endif /* Structure describing a globbing run. */ #if !defined _AMIGA && !defined VMS /* Buggy compiler. */ struct stat; #endif typedef struct { __size_t gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ /* If the GLOB_ALTDIRFUNC flag is set, the following functions are used instead of the normal file access functions. */ void (*gl_closedir) __PMT ((void *)); struct dirent *(*gl_readdir) __PMT ((void *)); __ptr_t (*gl_opendir) __PMT ((__const char *)); int (*gl_lstat) __PMT ((__const char *, struct stat *)); #if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE) int (*gl_stat) __PMT ((__const char *, struct stat *, ...)); #else int (*gl_stat) __PMT ((__const char *, struct stat *)); #endif } glob_t; #ifdef _LARGEFILE64_SOURCE struct stat64; typedef struct { __size_t gl_pathc; char **gl_pathv; __size_t gl_offs; int gl_flags; /* If the GLOB_ALTDIRFUNC flag is set, the following functions are used instead of the normal file access functions. */ void (*gl_closedir) __PMT ((void *)); struct dirent64 *(*gl_readdir) __PMT ((void *)); __ptr_t (*gl_opendir) __PMT ((__const char *)); int (*gl_lstat) __PMT ((__const char *, struct stat64 *)); int (*gl_stat) __PMT ((__const char *, struct stat64 *)); } glob64_t; #endif #if _FILE_OFFSET_BITS == 64 && __GNUC__ < 2 # define glob glob64 # define globfree globfree64 #else # ifdef _LARGEFILE64_SOURCE extern int glob64 __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob64_t *__pglob)); extern void globfree64 __P ((glob64_t *__pglob)); # endif #endif /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, it is called with the pathname that caused the error, and the `errno' value from the failing call; if it returns non-zero `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. Otherwise, `glob' returns zero. */ #if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2 extern int glob __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob_t *__pglob)); /* Free storage allocated in PGLOB by a previous `glob' call. */ extern void globfree __P ((glob_t *__pglob)); #else extern int glob __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob_t *__pglob)) __asm__ ("glob64"); extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64"); #endif #ifdef _GNU_SOURCE /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. This function is not part of the interface specified by POSIX.2 but several programs want to use it. */ extern int glob_pattern_p __P ((__const char *__pattern, int __quote)); #endif #ifdef __cplusplus } #endif #endif /* glob.h */ kbuild-2695/src/kmk/glob/configure.bat0000644000000000000000000000332412247157306016407 0ustar rootroot@echo off rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, rem 2004, 2005, 2006, 2007 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . echo Configuring glob for DJGPP rem This batch file assumes a unix-type "sed" program echo # Makefile generated by "configure.bat"> Makefile if exist config.sed del config.sed echo "s/@srcdir@/./ ">> config.sed echo "s/@CC@/gcc/ ">> config.sed echo "s/@CFLAGS@/-O2 -g/ ">> config.sed echo "s/@CPPFLAGS@/-DHAVE_CONFIG_H -I../ ">> config.sed echo "s/@AR@/ar/ ">> config.sed echo "s/@RANLIB@/ranlib/ ">> config.sed echo "s/@LDFLAGS@// ">> config.sed echo "s/@DEFS@// ">> config.sed echo "s/@ALLOCA@// ">> config.sed echo "s/@LIBS@// ">> config.sed echo "s/@LIBOBJS@// ">> config.sed echo "s/^Makefile *:/_Makefile:/ ">> config.sed echo "s/^config.h *:/_config.h:/ ">> config.sed sed -e "s/^\"//" -e "s/\"$//" -e "s/[ ]*$//" config.sed > config2.sed sed -f config2.sed Makefile.in >> Makefile del config.sed del config2.sed kbuild-2695/src/kmk/glob/ChangeLog0000644000000000000000000001507212247157306015513 0ustar rootroot2008-09-28 Juan Manuel Guerrero * glob.c (my_realloc) [__DJGPP__]: Don't define, and don't redefine realloc to call it, since the DJGPP's realloc handles NULL pointers correctly. 2007-12-22 Juan Manuel Guerrero (tiny change) * glob.c [__GNU_LIBRARY__ && __DJGPP__]: Add a realloc declaration that matches the one in the DJGPP libc. 2006-02-24 Eli Zaretskii * glob.c (my_malloc) [WINDOWS32]: Provide a full ISO C prototype, to avoid compiler warnings. 2005-06-25 Paul D. Smith * fnmatch.h, glob.h [WINDOWS32]: Fix ifdefs in headers. Fixes Savannah bug #13477. 2005-03-11 Paul D. Smith * glob.c (glob_in_dir): Change FNM_CASEFOLD to be enabled if HAVE_CASE_INSENSITIVE_FS is defined. 2003-01-30 Paul D. Smith * glob.h: Patch for FreeBSD by Mike Barcroft Reported by Gerald Pfeifer . On FreeBSD, declare __size_t to simply size_t. 2002-04-22 Paul D. Smith * Makefile.am: Use automake 1.6. Use new automake condition USE_LOCAL_GLOB to decide whether or not to build the local GNU glob library or use the system one. 1999-09-12 Paul D. Smith * fnmatch.c: Last GLIBC version wouldn't compile outside of GLIBC (undefined reference to internal_function). Update to the latest version 1999-09-11 Paul Eggert * glob.h (glob): If #defining to glob64, do this before declaring it, so that all declarations and uses match, and do not declare glob64, to avoid a declaration clash. (globfree): Likewise with globfree64. 1999-09-08 Eli Zaretskii * glob.c (prefix_array) [__MSDOS__,WINDOWS32]: Keep the trailing slash unless DIRNAME is just "x:/". 1999-09-06 Paul D. Smith * fnmatch.c: Update to latest version from GLIBC. 1999-07-21 Paul D. Smith * glob.c, glob.h, fnmatch.c, fnmatch.h: Update to latest version from GLIBC. * fnmatch.c (internal_fnmatch): Use K&R definition syntax, not ANSI. (__strchrnul): This won't exist outside GLIBC, so create one. * glob.c: Move getlogin{,_r} prototypes below glob.h to get __P() macro. 1998-08-05 Paul D. Smith * configure.in: Remove; configuration for glob is handled by the make configure.in. 1998-07-29 Paul D. Smith * glob.c, fnmatch.c: New versions from the GLIBC folks (Ulrich Drepper). Fixes a bug reported by Eli Zaretski. Integrates DOS/Windows32 support. 1998-07-27 Kaveh R. Ghazi * glob.c (glob): Cast away const on assignment of pattern to dirname. Cast the return type of __alloca() for traditional C compilers. 1998-07-23 Paul D. Smith * glob.c, fnmatch.c: New versions of these files from the GLIBC folks (Ulrich Drepper). Had to re-integrate some DOS/Windows code. 1998-07-10 Paul D. Smith * glob.c (glob_in_dir): If no meta chars exist in PATTERN and GLOB_NOCHECK is present, don't look for the file--whether it's found or not, we'll always return it, so why bother searching? Also, if we are searching and there are no meta chars, don't bother trying fnmatch() if the strcmp() fails. 1998-05-30 Eli Zaretskii * glob.c (glob) [__MSDOS__, WINDOWS32]: Compute the directory and filename parts of the pattern correctly when it includes a drive spec. Disallow wildcards in the drive spec. Prevent recursion when dirname is of the form "d:/" or "d:". (prefix_array) [__MSDOS__, WINDOWS32]: Don't append a slash to "d:/" and "d:". 1998-05-13 Paul D. Smith * SMakefile, Makefile.ami, glob.c, glob.h, fnmatch.c: Updated from the latest glibc version. 1998-04-17 Paul D. Smith * configure.in: Create a config.h file instead of setting things on the compile line. This is because when build.sh runs it merely passes -DHAVE_CONFIG_H to the glob files, just as it does to the make files. * config.h.in: Created by autoheader. Tue Aug 12 10:52:34 1997 Paul D. Smith * configure.in: Require autoconf 2.12. * glob: Updates from latest GNU libc glob code. * glob.c,glob.h,fnmatch.h: Change all WIN32 references to WINDOWS32. * glob.h: OSF4 defines macros in such a way that GLOB_ALTDIRFUNC is not defined. Added a test to the #if which defines it if _GNU_SOURCE is defined; that's set by both glob.c and GNU make. * glob.c: SunOS4 w/ cc needs #include , since assert.h requires stderr but doesn't include stdio.h :-/. (next_brace_sub): De-protoize function definition. (glob): Cast __alloca(); on SunOS4 it uses the default return type of int. (glob): Irix defines getlogin_r() to return a char*; move the extern for that into the _LIBC area since it isn't used except in LIBC anyway. Likewise, move extern getlogin() into the "else". Sat Jul 20 21:55:31 1996 Roland McGrath Win32 hacks from . * posix/glob.c [WIN32]: Don't include ; don't use d_ino; use void * for my_realloc; include for alloca. (glob) [WIN32]: Use "c:/users/default" for ~ if no HOME variable. * posix/fnmatch.h [WIN32]: Use prototypes even if [!__STDC__]. * posix/glob.h: Likewise. Fri Jul 19 16:56:41 1996 Roland McGrath * posix/glob.h [!_AMIGA && !VMS]: Check this instead of just [!_AMIGA] for `struct stat;' forward decl. Sat Jun 22 10:44:09 1996 Roland McGrath * posix/glob.c: Include only [HAVE_ALLOCA_H], not [sparc]. Fri Jun 21 00:27:51 1996 Roland McGrath * posix/fnmatch.c (fnmatch): Fix \*[*?]+ case to increment name ptr only for ?s, not for *s. Fix from Chet Ramey. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/glob/SCOPTIONS0000644000000000000000000000030312247157306015234 0ustar rootrootERRORREXX OPTIMIZE NOVERSION OPTIMIZERTIME OPTIMIZERALIAS DEFINE INCLUDEDIR="include:" DEFINE LIBDIR="lib:" DEFINE NO_ALLOCA DEFINE NO_FLOAT DEFINE NO_ARCHIVES IGNORE=161 IGNORE=100 STARTUP=cres kbuild-2695/src/kmk/README.template0000644000000000000000000001576412247157306015520 0ustar rootrootThis directory contains the %VERSION% release of GNU Make. See the file NEWS for the user-visible changes from previous releases. In addition, there have been bugs fixed. Please check the system-specific notes below for any caveats related to your operating system. For general building and installation instructions, see the file INSTALL. If you need to build GNU Make and have no other `make' program to use, you can use the shell script `build.sh' instead. To do this, first run `configure' as described in INSTALL. Then, instead of typing `make' to build the program, type `sh build.sh'. This should compile the program in the current directory. Then you will have a Make program that you can use for `./make install', or whatever else. Some systems' Make programs are broken and cannot process the Makefile for GNU Make. If you get errors from your system's Make when building GNU Make, try using `build.sh' instead. GNU Make is free software. See the file COPYING for copying conditions. Downloading ----------- GNU Make can be obtained in many different ways. See a description here: http://www.gnu.org/software/software.html Documentation ------------- GNU make is fully documented in the GNU Make manual, which is contained in this distribution as the file make.texinfo. You can also find on-line and preformatted (PostScript and DVI) versions at the FSF's web site. There is information there about ordering hardcopy documentation. http://www.gnu.org/ http://www.gnu.org/doc/doc.html http://www.gnu.org/manual/manual.html Development ----------- GNU Make development is hosted by Savannah, the FSF's online development management tool. Savannah is here: http://savannah.gnu.org And the GNU Make development page is here: http://savannah.gnu.org/projects/make/ You can find most information concerning the development of GNU Make at this site. Bug Reporting ------------- You can send GNU make bug reports to . Please see the section of the GNU make manual entitled `Problems and Bugs' for information on submitting useful and complete bug reports. You can also use the online bug tracking system in the Savannah GNU Make project to submit new problem reports or search for existing ones: http://savannah.gnu.org/bugs/?group=make If you need help using GNU make, try these forums: help-make@gnu.org help-utils@gnu.org news:gnu.utils.help news:gnu.utils.bug http://savannah.gnu.org/support/?group=make You may also find interesting patches to GNU Make available here: http://savannah.gnu.org/patch/?group=make Note these patches are provided by our users as a service and we make no statements regarding their correctness. Please contact the authors directly if you have a problem or suggestion for a patch available on this page. CVS Access ---------- The GNU make source repository is available via anonymous CVS from the GNU Subversions CVS server; look here for details: http://savannah.gnu.org/cvs/?group=make Please note: you won't be able to build GNU make from CVS without installing appropriate maintainer's tools, such as GNU m4, automake, autoconf, Perl, GNU make, and GCC. See the README.cvs file for hints on how to build GNU make once these tools are available. We make no guarantees about the contents or quality of the latest code in the CVS repository: it is not unheard of for code that is known to be broken to be checked in. Use at your own risk. System-specific Notes --------------------- It has been reported that the XLC 1.2 compiler on AIX 3.2 is buggy such that if you compile make with `cc -O' on AIX 3.2, it will not work correctly. It is said that using `cc' without `-O' does work. The standard /bin/sh on SunOS 4.1.3_U1 and 4.1.4 is broken and cannot be used to configure GNU make. Please install a different shell such as bash or pdksh in order to run "configure". See this message for more information: http://mail.gnu.org/archive/html/bug-autoconf/2003-10/msg00190.html One area that is often a problem in configuration and porting is the code to check the system's current load average. To make it easier to test and debug this code, you can do `make check-loadavg' to see if it works properly on your system. (You must run `configure' beforehand, but you need not build Make itself to run this test.) Another potential source of porting problems is the support for large files (LFS) in configure for those operating systems that provide it. Please report any bugs that you find in this area. If you run into difficulties, then as a workaround you should be able to disable LFS by adding the `--disable-largefile' option to the `configure' script. On systems that support micro- and nano-second timestamp values and where stat(2) provides this information, GNU make will use it when comparing timestamps to get the most accurate possible result. However, note that many current implementations of tools that *set* timestamps do not preserve micro- or nano-second granularity. This means that "cp -p" and other similar tools (tar, etc.) may not exactly duplicate timestamps with micro- and nano-second granularity on some systems. If your build system contains rules that depend on proper behavior of tools like "cp -p", you should consider using the .LOW_RESOLUTION_TIME pseudo-target to force make to treat them properly. See the manual for details. Ports ----- - See README.customs for details on integrating GNU make with the Customs distributed build environment from the Pmake distribution. - See readme.vms for details about GNU Make on OpenVMS. - See README.Amiga for details about GNU Make on AmigaDOS. - See README.W32 for details about GNU Make on Windows NT, 95, or 98. - See README.DOS for compilation instructions on MS-DOS and MS-Windows using DJGPP tools. A precompiled binary of the MSDOS port of GNU Make is available as part of DJGPP; see the WWW page http://www.delorie.com/djgpp/ for more information. Please note there are two _separate_ ports of GNU make for Microsoft systems: a native Windows tool built with (for example) MSVC or Cygwin, and a DOS-based tool built with DJGPP. Please be sure you are looking at the right README! ------------------------------------------------------------------------------- Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/make.h0000644000000000000000000006615512247157306014114 0ustar rootroot/* Miscellaneous global declarations and portability cruft for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because make.h was found in $srcdir). */ #include #undef HAVE_CONFIG_H #define HAVE_CONFIG_H 1 /* Specify we want GNU source code. This must be defined before any system headers are included. */ #define _GNU_SOURCE 1 /* AIX requires this to be the first thing in the file. */ #if HAVE_ALLOCA_H # include #else # ifdef _AIX #pragma alloca # else # if !defined(__GNUC__) && !defined(WINDOWS32) # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #ifdef CRAY /* This must happen before #include so that the declaration therein is changed. */ # define signal bsdsignal #endif /* If we're compiling for the dmalloc debugger, turn off string inlining. */ #if defined(HAVE_DMALLOC_H) && defined(__GNUC__) # define __NO_STRING_INLINES #endif #include #include #include #include #include #ifdef HAVE_SYS_TIMEB_H /* SCO 3.2 "devsys 4.2" has a prototype for `ftime' in that bombs unless has been included first. Does every system have a ? If any does not, configure should check for it. */ # include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #ifndef errno extern int errno; #endif #ifndef isblank # define isblank(c) ((c) == ' ' || (c) == '\t') #endif #ifdef HAVE_UNISTD_H # include /* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get POSIX.1 behavior with `cc -YPOSIX', which predefines POSIX itself! */ # if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS) # define POSIX 1 # endif #endif /* Some systems define _POSIX_VERSION but are not really POSIX.1. */ #if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386))) # undef POSIX #endif #if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE) # define POSIX 1 #endif #ifndef RETSIGTYPE # define RETSIGTYPE void #endif #ifndef sigmask # define sigmask(sig) (1 << ((sig) - 1)) #endif #ifndef HAVE_SA_RESTART # define SA_RESTART 0 #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifndef PATH_MAX # ifndef POSIX # define PATH_MAX MAXPATHLEN # endif #endif #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif #ifdef PATH_MAX # define GET_PATH_MAX PATH_MAX # define PATH_VAR(var) char var[PATH_MAX] #else # define NEED_GET_PATH_MAX 1 # define GET_PATH_MAX (get_path_max ()) # define PATH_VAR(var) char *var = alloca (GET_PATH_MAX) unsigned int get_path_max (void); #endif #if defined (KMK) || defined (CONFIG_WITH_VALUE_LENGTH) \ || defined (CONFIG_WITH_ALLOC_CACHES) \ || defined (CONFIG_WITH_STRCACHE2) # ifdef _MSC_VER # define MY_INLINE _inline static # elif defined(__GNUC__) # define MY_INLINE static __inline__ # else # define MY_INLINE static # endif # ifdef __GNUC__ # define MY_PREDICT_TRUE(expr) __builtin_expect(!!(expr), 1) # define MY_PREDICT_FALSE(expr) __builtin_expect(!!(expr), 0) # else # define MY_PREDICT_TRUE(expr) (expr) # define MY_PREDICT_FALSE(expr) (expr) # endif #endif #if defined (KMK) || defined (CONFIG_WITH_VALUE_LENGTH) \ || defined (CONFIG_WITH_STRCACHE2) # ifdef _MSC_VER # define MY_DBGBREAK __debugbreak() # elif defined(__GNUC__) # if defined(__i386__) || defined(__x86_64__) # define MY_DBGBREAK __asm__ __volatile__ ("int3") # else # define MY_DBGBREAK assert(0) # endif # else # define MY_DBGBREAK assert(0) # endif # ifndef NDEBUG # define MY_ASSERT_MSG(expr, printfargs) \ do { if (!(expr)) { printf printfargs; MY_DBGBREAK; } } while (0) # else # define MY_ASSERT_MSG(expr, printfargs) do { } while (0) # endif #endif #ifdef KMK # include # if 1 /* See if this speeds things up (Windows is doing this anyway, so, we might as well try be consistent in speed + features). */ # if 1 # define MY_IS_BLANK(ch) ((ch) == ' ' || (ch) == '\t') # define MY_IS_BLANK_OR_EOS(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\0') # else # define MY_IS_BLANK(ch) (((ch) == ' ') | ((ch) == '\t')) # define MY_IS_BLANK_OR_EOS(ch) (((ch) == ' ') | ((ch) == '\t') | ((ch) == '\0')) # endif # undef isblank # define isblank(ch) MY_IS_BLANK(ch) # else # define MY_IS_BLANK(ch) isblank ((unsigned char)(ch)) # define MY_IS_BLANK_OR_EOS(ch) (isblank ((unsigned char)(ch)) || (ch) == '\0') # endif #endif #ifdef CONFIG_WITH_MAKE_STATS extern long make_stats_allocations; extern long make_stats_reallocations; extern unsigned long make_stats_allocated; extern unsigned long make_stats_ht_lookups; extern unsigned long make_stats_ht_collisions; # ifdef __APPLE__ # include # define SIZE_OF_HEAP_BLOCK(ptr) malloc_good_size(ptr) # elif defined(__linux__) /* glibc */ # include # define SIZE_OF_HEAP_BLOCK(ptr) malloc_usable_size(ptr) # elif defined(_MSC_VER) || defined(__OS2__) # define SIZE_OF_HEAP_BLOCK(ptr) _msize(ptr) # else # include # define SIZE_OF_HEAP_BLOCK(ptr) 0 #endif # define MAKE_STATS_3(expr) do { expr; } while (0) # define MAKE_STATS_2(expr) do { expr; } while (0) # define MAKE_STATS(expr) do { expr; } while (0) #else # define MAKE_STATS_3(expr) do { } while (0) # define MAKE_STATS_2(expr) do { } while (0) # define MAKE_STATS(expr) do { } while (0) #endif /* bird - start */ #define COMMA , #ifdef CONFIG_WITH_VALUE_LENGTH # define IF_WITH_VALUE_LENGTH(a_Expr) a_Expr # define IF_WITH_VALUE_LENGTH_PARAM(a_Expr) , a_Expr #else # define IF_WITH_VALUE_LENGTH(a_Expr) # define IF_WITH_VALUE_LENGTH_PARAM(a_Expr) #endif #ifdef CONFIG_WITH_ALLOC_CACHES # define IF_WITH_ALLOC_CACHES(a_Expr) a_Expr # define IF_WITH_ALLOC_CACHES_PARAM(a_Expr) , a_Expr #else # define IF_WITH_ALLOC_CACHES(a_Expr) # define IF_WITH_ALLOC_CACHES_PARAM(a_Expr) #endif #ifdef CONFIG_WITH_COMMANDS_FUNC # define IF_WITH_COMMANDS_FUNC(a_Expr) a_Expr # define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr) , a_Expr #else # define IF_WITH_COMMANDS_FUNC(a_Expr) # define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr) #endif /* bird - end */ #ifndef CHAR_BIT # define CHAR_BIT 8 #endif /* Nonzero if the integer type T is signed. */ #define INTEGER_TYPE_SIGNED(t) ((t) -1 < 0) /* The minimum and maximum values for the integer type T. Use ~ (t) 0, not -1, for portability to 1's complement hosts. */ #define INTEGER_TYPE_MINIMUM(t) \ (! INTEGER_TYPE_SIGNED (t) ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)) #define INTEGER_TYPE_MAXIMUM(t) (~ (t) 0 - INTEGER_TYPE_MINIMUM (t)) #ifndef CHAR_MAX # define CHAR_MAX INTEGER_TYPE_MAXIMUM (char) #endif #ifdef STAT_MACROS_BROKEN # ifdef S_ISREG # undef S_ISREG # endif # ifdef S_ISDIR # undef S_ISDIR # endif #endif /* STAT_MACROS_BROKEN. */ #ifndef S_ISREG # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #ifdef VMS # include # include # include # include /* Needed to use alloca on VMS. */ # include #endif #ifndef __attribute__ /* This feature is available in gcc versions 2.5 and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ # define __attribute__(x) # endif /* The __-protected variants of `format' and `printf' attributes are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __format__ format # define __printf__ printf # endif #endif #define UNUSED __attribute__ ((unused)) #if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) # include # include # define ANSI_STRING 1 #else /* No standard headers. */ # ifdef HAVE_STRING_H # include # define ANSI_STRING 1 # else # include # endif # ifdef HAVE_MEMORY_H # include # endif # ifdef HAVE_STDLIB_H # include # else void *malloc (int); void *realloc (void *, int); void free (void *); void abort (void) __attribute__ ((noreturn)); void exit (int) __attribute__ ((noreturn)); # endif /* HAVE_STDLIB_H. */ #endif /* Standard headers. */ /* These should be in stdlib.h. Make sure we have them. */ #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifndef ANSI_STRING /* SCO Xenix has a buggy macro definition in . */ #undef strerror #if !defined(__DECC) char *strerror (int errnum); #endif #endif /* !ANSI_STRING. */ #undef ANSI_STRING #if HAVE_INTTYPES_H # include #endif #define FILE_TIMESTAMP uintmax_t #if !defined(HAVE_STRSIGNAL) char *strsignal (int signum); #endif /* ISDIGIT offers the following features: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. NOTE! Make relies on this behavior, don't change it! - It's typically faster. POSIX 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that only '0' through '9' are digits. Prefer ISDIGIT to isdigit() unless it's important to use the locale's definition of `digit' even when the host does not conform to POSIX. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) /* Test if two strings are equal. Is this worthwhile? Should be profiled. */ #define streq(a, b) \ ((a) == (b) || \ (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1)))) /* Test if two strings are equal, but match case-insensitively on systems which have case-insensitive filesystems. Should only be used for filenames! */ #ifdef HAVE_CASE_INSENSITIVE_FS # define patheq(a, b) \ ((a) == (b) \ || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \ && (*(a) == '\0' || !strcasecmp ((a) + 1, (b) + 1)))) #else # define patheq(a, b) streq(a, b) #endif #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0) #if (defined(__GNUC__) || defined(ENUM_BITFIELDS)) && !defined(NO_ENUM_BITFIELDS) # define ENUM_BITFIELD(bits) :bits #else # define ENUM_BITFIELD(bits) #endif /* Handle gettext and locales. */ #if HAVE_LOCALE_H # include #else # define setlocale(category, locale) #endif #include #define _(msgid) gettext (msgid) #define N_(msgid) gettext_noop (msgid) #define S_(msg1,msg2,num) ngettext (msg1,msg2,num) /* Handle other OSs. */ #ifndef PATH_SEPARATOR_CHAR # if defined(HAVE_DOS_PATHS) # define PATH_SEPARATOR_CHAR ';' # elif defined(VMS) # define PATH_SEPARATOR_CHAR ',' # else # define PATH_SEPARATOR_CHAR ':' # endif #endif /* This is needed for getcwd() and chdir(), on some W32 systems. */ #if defined(HAVE_DIRECT_H) # include #endif #ifdef WINDOWS32 # include # include # define pipe(_p) _pipe((_p), 512, O_BINARY) # define kill(_pid,_sig) w32_kill((_pid),(_sig)) void sync_Path_environment (void); int w32_kill (pid_t pid, int sig); char *end_of_token_w32 (const char *s, char stopchar); int find_and_set_default_shell (const char *token); /* indicates whether or not we have Bourne shell */ extern int no_default_sh_exe; /* is default_shell unixy? */ extern int unixy_shell; #endif /* WINDOWS32 */ #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) # define SET_STACK_SIZE #endif #ifdef SET_STACK_SIZE # include struct rlimit stack_limit; #endif struct floc { const char *filenm; unsigned long lineno; }; #define NILF ((struct floc *)0) #define STRING_SIZE_TUPLE(_s) (_s), (sizeof (_s)-1) #if defined (CONFIG_WITH_MATH) \ || defined (CONFIG_WITH_NANOTS) \ || defined (CONFIG_WITH_FILE_SIZE) \ || defined (CONFIG_WITH_PRINT_TIME_SWITCH) /* bird */ # ifdef _MSC_VER typedef __int64 big_int; # define BIG_INT_C(c) (c ## LL) typedef unsigned __int64 big_uint; # define BIG_UINT_C(c) (c ## ULL) # else # include typedef int64_t big_int; # define BIG_INT_C(c) INT64_C(c) typedef uint64_t big_uint; # define BIG_UINT_C(c) UINT64_C(c) # endif #endif /* We have to have stdarg.h or varargs.h AND v*printf or doprnt to use variadic versions of these functions. */ #if HAVE_STDARG_H || HAVE_VARARGS_H # if HAVE_VPRINTF || HAVE_DOPRNT # define USE_VARIADIC 1 # endif #endif #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H const char *concat (unsigned int, ...); void message (int prefix, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); void error (const struct floc *flocp, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); void fatal (const struct floc *flocp, const char *fmt, ...) __attribute__ ((noreturn, __format__ (__printf__, 2, 3))); #else const char *concat (); void message (); void error (); void fatal (); #endif void die (int) __attribute__ ((noreturn)); void log_working_directory (int); void pfatal_with_name (const char *) __attribute__ ((noreturn)); void perror_with_name (const char *, const char *); void *xmalloc (unsigned int); void *xcalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); char *xstrndup (const char *, unsigned int); #ifdef CONFIG_WITH_PRINT_STATS_SWITCH void print_heap_stats (void); #endif char *find_next_token (const char **, unsigned int *); char *next_token (const char *); char *end_of_token (const char *); #ifdef KMK char *find_next_token_eos (const char **ptr, const char *eos, unsigned int *lengthptr); #endif #ifndef CONFIG_WITH_VALUE_LENGTH void collapse_continuations (char *); #else char *collapse_continuations (char *, unsigned int); #endif #ifdef CONFIG_WITH_OPTIMIZATION_HACKS /* memchr is usually compiler intrinsic, thus faster. */ # define lindex(s, limit, c) ((char *)memchr((s), (c), (limit) - (s))) #else char *lindex (const char *, const char *, int); #endif int alpha_compare (const void *, const void *); void print_spaces (unsigned int); char *find_percent (char *); const char *find_percent_cached (const char **); FILE *open_tmpfile (char **, const char *); #ifndef NO_ARCHIVES int ar_name (const char *); void ar_parse_name (const char *, char **, char **); int ar_touch (const char *); time_t ar_member_date (const char *); typedef long int (*ar_member_func_t) (int desc, const char *mem, int truncated, long int hdrpos, long int datapos, long int size, long int date, int uid, int gid, int mode, const void *arg); long int ar_scan (const char *archive, ar_member_func_t function, const void *arg); int ar_name_equal (const char *name, const char *mem, int truncated); #ifndef VMS int ar_member_touch (const char *arname, const char *memname); #endif #endif int dir_file_exists_p (const char *, const char *); int file_exists_p (const char *); int file_impossible_p (const char *); void file_impossible (const char *); const char *dir_name (const char *); void hash_init_directories (void); void define_default_variables (void); void set_default_suffixes (void); void install_default_suffix_rules (void); void install_default_implicit_rules (void); void build_vpath_lists (void); void construct_vpath_list (char *pattern, char *dirpath); const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* vpath_index, unsigned int* path_index); int gpath_search (const char *file, unsigned int len); void construct_include_path (const char **arg_dirs); void user_access (void); void make_access (void); void child_access (void); void close_stdout (void); char *strip_whitespace (const char **begpp, const char **endpp); #ifdef CONFIG_WITH_ALLOC_CACHES /* alloccache (misc.c) */ struct alloccache_free_ent { struct alloccache_free_ent *next; }; struct alloccache { char *free_start; char *free_end; struct alloccache_free_ent *free_head; unsigned int size; unsigned int total_count; unsigned long alloc_count; unsigned long free_count; const char *name; struct alloccache *next; void *grow_arg; void *(*grow_alloc)(void *grow_arg, unsigned int size); }; void alloccache_init (struct alloccache *cache, unsigned int size, const char *name, void *(*grow_alloc)(void *grow_arg, unsigned int size), void *grow_arg); void alloccache_term (struct alloccache *cache, void (*term_free)(void *term_arg, void *ptr, unsigned int size), void *term_arg); void alloccache_join (struct alloccache *cache, struct alloccache *eat); void alloccache_print (struct alloccache *cache); void alloccache_print_all (void); struct alloccache_free_ent *alloccache_alloc_grow (struct alloccache *cache); void alloccache_free (struct alloccache *cache, void *item); /* Allocate an item. */ MY_INLINE void * alloccache_alloc (struct alloccache *cache) { struct alloccache_free_ent *f; # ifndef CONFIG_WITH_ALLOCCACHE_DEBUG f = cache->free_head; if (f) cache->free_head = f->next; else if (cache->free_start != cache->free_end) { f = (struct alloccache_free_ent *)cache->free_start; cache->free_start += cache->size; } else # endif f = alloccache_alloc_grow (cache); MAKE_STATS(cache->alloc_count++;); return f; } /* Allocate a cleared item. */ MY_INLINE void * alloccache_calloc (struct alloccache *cache) { void *item = alloccache_alloc (cache); memset (item, '\0', cache->size); return item; } /* the alloc caches */ extern struct alloccache dep_cache; extern struct alloccache file_cache; extern struct alloccache commands_cache; extern struct alloccache nameseq_cache; extern struct alloccache variable_cache; extern struct alloccache variable_set_cache; extern struct alloccache variable_set_list_cache; #endif /* CONFIG_WITH_ALLOC_CACHES */ /* String caching */ void strcache_init (void); void strcache_print_stats (const char *prefix); #ifndef CONFIG_WITH_STRCACHE2 int strcache_iscached (const char *str); const char *strcache_add (const char *str); const char *strcache_add_len (const char *str, int len); int strcache_setbufsize (int size); #else /* CONFIG_WITH_STRCACHE2 */ # include "strcache2.h" extern struct strcache2 file_strcache; extern const char *suffixes_strcached; # define strcache_iscached(str) strcache2_is_cached(&file_strcache, str) # define strcache_add(str) strcache2_add_file(&file_strcache, str, strlen (str)) # define strcache_add_len(str, len) strcache2_add_file(&file_strcache, str, len) # define strcache_get_len(str) strcache2_get_len(&file_strcache, str) /* FIXME: replace this and related checks ... */ #endif /* CONFIG_WITH_STRCACHE2 */ #ifdef HAVE_VFORK_H # include #endif /* We omit these declarations on non-POSIX systems which define _POSIX_VERSION, because such systems often declare them in header files anyway. */ #if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32) long int atol (); # ifndef VMS long int lseek (); # endif #endif /* Not GNU C library or POSIX. */ #ifdef HAVE_GETCWD # if !defined(VMS) && !defined(__DECC) && !defined(_MSC_VER) /* bird: MSC */ char *getcwd (); # endif #else char *getwd (); # define getcwd(buf, len) getwd (buf) #endif #if !HAVE_STRCASECMP # if HAVE_STRICMP # define strcasecmp stricmp # elif HAVE_STRCMPI # define strcasecmp strcmpi # else /* Create our own, in misc.c */ int strcasecmp (const char *s1, const char *s2); # endif #endif #if !HAVE_STRNCASECMP # if HAVE_STRNICMP # define strncasecmp strnicmp # elif HAVE_STRNCMPI # define strncasecmp strncmpi # else /* Create our own, in misc.c */ int strncasecmp (const char *s1, const char *s2, int n); # endif #endif extern const struct floc *reading_file; extern const struct floc **expanding_var; #if !defined(_MSC_VER) /* bird */ extern char **environ; #endif extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag; extern int print_data_base_flag, question_flag, touch_flag, always_make_flag; extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag; extern int print_version_flag, print_directory_flag, check_symlink_flag; extern int warn_undefined_variables_flag, posix_pedantic, not_parallel; extern int second_expansion, clock_skew_detected, rebuilding_makefiles; extern int one_shell; #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION extern int second_target_expansion; #endif #ifdef CONFIG_PRETTY_COMMAND_PRINTING extern int pretty_command_printing; #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH extern int print_time_min, print_time_width; #endif #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) extern int make_expensive_statistics; #endif /* can we run commands via 'sh -c xxx' or must we use batch files? */ extern int batch_mode_shell; /* Resetting the command script introduction prefix character. */ #define RECIPEPREFIX_NAME ".RECIPEPREFIX" #define RECIPEPREFIX_DEFAULT '\t' extern char cmd_prefix; extern unsigned int job_slots; extern int job_fds[2]; extern int job_rfd; #ifndef NO_FLOAT extern double max_load_average; #else extern int max_load_average; #endif extern char *program; extern char *starting_directory; extern unsigned int makelevel; extern char *version_string, *remote_description, *make_host; extern unsigned int commands_started; extern int handling_fatal_signal; #ifndef MIN #define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) #endif #ifndef MAX #define MAX(_a,_b) ((_a)>(_b)?(_a):(_b)) #endif #ifdef VMS # define MAKE_SUCCESS 1 # define MAKE_TROUBLE 2 # define MAKE_FAILURE 3 #else # define MAKE_SUCCESS 0 # define MAKE_TROUBLE 1 # define MAKE_FAILURE 2 #endif /* Set up heap debugging library dmalloc. */ #ifdef HAVE_DMALLOC_H #include #endif #ifndef initialize_main # ifdef __EMX__ # define initialize_main(pargc, pargv) \ { _wildcard(pargc, pargv); _response(pargc, pargv); } # else # define initialize_main(pargc, pargv) # endif #endif #ifdef __EMX__ # if !defined chdir # define chdir _chdir2 # endif # if !defined getcwd # define getcwd _getcwd2 # endif /* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of chdir() and getcwd(). This avoids some error messages for the make testsuite but restricts the drive letter support. */ # ifdef NO_CHDIR2 # warning NO_CHDIR2: usage of drive letters restricted # undef chdir # undef getcwd # endif #endif #ifndef initialize_main # define initialize_main(pargc, pargv) #endif /* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag properly according to POSIX. So, we try to wrap common system calls with checks for EINTR. Note that there are still plenty of system calls that can fail with EINTR but this, reportedly, gets the vast majority of failure cases. If you still experience failures you'll need to either get a system where SA_RESTART works, or you need to avoid -j. */ #define EINTRLOOP(_v,_c) while (((_v)=_c)==-1 && errno==EINTR) /* While system calls that return integers are pretty consistent about returning -1 on failure and setting errno in that case, functions that return pointers are not always so well behaved. Sometimes they return NULL for expected behavior: one good example is readdir() which returns NULL at the end of the directory--and _doesn't_ reset errno. So, we have to do it ourselves here. */ #define ENULLLOOP(_v,_c) do { errno = 0; (_v) = _c; } \ while((_v)==0 && errno==EINTR) #if defined(__EMX__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS) /* bird: saves 40-100ms on libc. */ static inline void *__my_rawmemchr (const void *__s, int __c); #undef strchr #define strchr(s, c) \ (__extension__ (__builtin_constant_p (c) \ ? ((c) == '\0' \ ? (char *) __my_rawmemchr ((s), (c)) \ : __my_strchr_c ((s), ((c) & 0xff) << 8)) \ : __my_strchr_g ((s), (c)))) static inline char *__my_strchr_c (const char *__s, int __c) { register unsigned long int __d0; register char *__res; __asm__ __volatile__ ("1:\n\t" "movb (%0),%%al\n\t" "cmpb %%ah,%%al\n\t" "je 2f\n\t" "leal 1(%0),%0\n\t" "testb %%al,%%al\n\t" "jne 1b\n\t" "xorl %0,%0\n" "2:" : "=r" (__res), "=&a" (__d0) : "0" (__s), "1" (__c), "m" ( *(struct { char __x[0xfffffff]; } *)__s) : "cc"); return __res; } static inline char *__my_strchr_g (__const char *__s, int __c) { register unsigned long int __d0; register char *__res; __asm__ __volatile__ ("movb %%al,%%ah\n" "1:\n\t" "movb (%0),%%al\n\t" "cmpb %%ah,%%al\n\t" "je 2f\n\t" "leal 1(%0),%0\n\t" "testb %%al,%%al\n\t" "jne 1b\n\t" "xorl %0,%0\n" "2:" : "=r" (__res), "=&a" (__d0) : "0" (__s), "1" (__c), "m" ( *(struct { char __x[0xfffffff]; } *)__s) : "cc"); return __res; } static inline void *__my_rawmemchr (const void *__s, int __c) { register unsigned long int __d0; register unsigned char *__res; __asm__ __volatile__ ("cld\n\t" "repne; scasb\n\t" : "=D" (__res), "=&c" (__d0) : "a" (__c), "0" (__s), "1" (0xffffffff), "m" ( *(struct { char __x[0xfffffff]; } *)__s) : "cc"); return __res - 1; } #undef memchr #define memchr(a,b,c) __my_memchr((a),(b),(c)) static inline void *__my_memchr (__const void *__s, int __c, size_t __n) { register unsigned long int __d0; register unsigned char *__res; if (__n == 0) return NULL; __asm__ __volatile__ ("repne; scasb\n\t" "je 1f\n\t" "movl $1,%0\n" "1:" : "=D" (__res), "=&c" (__d0) : "a" (__c), "0" (__s), "1" (__n), "m" ( *(struct { __extension__ char __x[__n]; } *)__s) : "cc"); return __res - 1; } #endif /* __EMX__ (bird) */ #ifdef CONFIG_WITH_IF_CONDITIONALS extern int expr_eval_if_conditionals(const char *line, const struct floc *flocp); extern char *expr_eval_to_string(char *o, const char *expr); #endif #ifdef KMK extern char *abspath(const char *name, char *apath); extern char *func_breakpoint(char *o, char **argv, const char *funcname); #endif #if defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_PRINT_TIME_SWITCH) /* misc.c */ extern big_int nano_timestamp (void); extern int format_elapsed_nano (char *buf, size_t size, big_int ts); #endif kbuild-2695/src/kmk/electric.c0000644000000000000000000001122212247157306014745 0ustar rootroot/* $Id: electric.c 2626 2012-08-09 14:11:47Z bird $ */ /** @file * A simple electric heap implementation. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifdef ELECTRIC_HEAP # ifdef WINDOWS32 # include # else # include # include # endif # include # include # include # define FREED_ENTRIES 512 static struct { void *ptr; unsigned aligned; } freed[FREED_ENTRIES]; static unsigned freed_head = 0; static unsigned freed_tail = 0; static void fatal_error (const char *msg) { #ifdef _MSC_VER fprintf (stderr, "electric heap error: %s\n", msg); __debugbreak (); #else fprintf (stderr, "electric heap error: %s (errno=%d)\n", msg, errno); __asm__ ("int3"); /* not portable... */ #endif abort (); exit (1); } static void free_it (void *ptr, unsigned aligned) { # ifdef WINDOWS32 if (!VirtualFree (ptr, 0, MEM_RELEASE)) fatal_error ("VirtualFree failed"); # else if (munmap(ptr, aligned)) fatal_error ("munmap failed"); # endif } /* Return 1 if something was freed, 0 otherwise. */ static int free_up_some (void) { if (freed_tail == freed_head) return 0; free_it (freed[freed_tail].ptr, freed[freed_tail].aligned); freed[freed_tail].ptr = NULL; freed[freed_tail].aligned = 0; freed_tail = (freed_tail + 1) % FREED_ENTRIES; return 1; } static unsigned *get_hdr (void *ptr) { if (((uintptr_t)ptr & 0xfff) < sizeof(unsigned)) return (unsigned *)(((uintptr_t)ptr - 0x1000) & ~0xfff); return (unsigned *)((uintptr_t)ptr & ~0xfff); } void xfree (void *ptr) { unsigned int size, aligned; unsigned *hdr; # ifdef WINDOWS32 DWORD fFlags = PAGE_NOACCESS; # endif if (!ptr) return; hdr = get_hdr (ptr); size = *hdr; aligned = (size + 0x1fff + sizeof(unsigned)) & ~0xfff; # ifdef WINDOWS32 if (!VirtualProtect (hdr, aligned - 0x1000, fFlags, &fFlags)) fatal_error ("failed to protect freed memory"); # else if (mprotect(hdr, aligned - 0x1000, PROT_NONE)) fatal_error ("failed to protect freed memory"); # endif freed[freed_head].ptr = hdr; freed[freed_head].aligned = aligned; if (((freed_head + 1) % FREED_ENTRIES) == freed_tail) free_up_some(); freed_head = (freed_head + 1) % FREED_ENTRIES; } void * xmalloc (unsigned int size) { /* Make sure we don't allocate 0, for pre-ANSI libraries. */ unsigned int aligned = (size + 0x1fff + sizeof(unsigned)) & ~0xfff; unsigned *hdr; unsigned i; for (i = 0; i < FREED_ENTRIES; i++) { # ifdef WINDOWS32 DWORD fFlags = PAGE_NOACCESS; hdr = VirtualAlloc(NULL, aligned, MEM_COMMIT, PAGE_READWRITE); if (hdr && !VirtualProtect((char *)hdr + aligned - 0x1000, 0x1000, fFlags, &fFlags)) fatal_error ("failed to set guard page protection"); # else hdr = mmap(NULL, aligned, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if (hdr == MAP_FAILED) hdr = 0; if (hdr && mprotect((char *)hdr + aligned - 0x1000, 0x1000, PROT_NONE)) fatal_error ("failed to set guard page protection"); # endif if (hdr) break; if (!free_up_some ()) break; } if (hdr == 0) fatal_error ("virtual memory exhausted"); *hdr = size; # if 0 return hdr + 1; # else return (char *)hdr + aligned - 0x1000 - size; # endif } void * xcalloc (unsigned size) { void *result; result = xmalloc (size); return memset (result, 0, size); } void * xrealloc (void *ptr, unsigned int size) { void *result; result = xmalloc (size); if (ptr) { unsigned *hdr = get_hdr (ptr); unsigned int oldsize = *hdr; memcpy (result, ptr, oldsize >= size ? size : oldsize); xfree (ptr); } return result; } char * xstrdup (const char *ptr) { if (ptr) { size_t size = strlen (ptr) + 1; char *result = xmalloc (size); return memcpy (result, ptr, size); } return NULL; } #else /* !ELECTRIC_HEAP */ extern void electric_heap_keep_ansi_c_quiet (void); #endif /* !ELECTRIC_HEAP */ kbuild-2695/src/kmk/w32/0000755000000000000000000000000012247157306013424 5ustar rootrootkbuild-2695/src/kmk/w32/imagecache.c0000644000000000000000000001126312247157306015641 0ustar rootroot/* $Id: imagecache.c 2640 2012-09-09 01:49:16Z bird $ */ /** @file * kBuild specific executable image cache for Windows. */ /* * Copyright (c) 2012 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /* No GNU coding style here! */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "make.h" #include /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ typedef struct EXECCACHEENTRY { /** The name hash value. */ unsigned uHash; /** The name length. */ unsigned cchName; /** Pointer to the next name with the same hash. */ struct EXECCACHEENTRY *pNext; /** When it was last referenced. */ unsigned uLastRef; /** The module handle. */ HMODULE hmod1; /** The module handle. */ HMODULE hmod2; /** The executable path. */ char szName[1]; } EXECCACHEENTRY; typedef EXECCACHEENTRY *PEXECCACHEENTRY; /******************************************************************************* * Global Variables * *******************************************************************************/ /** The number of cached images. */ static unsigned g_cCached; /** Used noting when entries was last used. * Increased on each kmk_cache_exec_image call. */ static unsigned g_uNow; /** The size of the hash table. */ #define EXECCACHE_HASHTAB_SIZE 128 /** The hash table. */ static PEXECCACHEENTRY g_apHashTab[EXECCACHE_HASHTAB_SIZE]; /* sdbm: This algorithm was created for sdbm (a public-domain reimplementation of ndbm) database library. it was found to do well in scrambling bits, causing better distribution of the keys and fewer splits. it also happens to be a good general hashing function with good distribution. the actual function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below is the faster version used in gawk. [there is even a faster, duff-device version] the magic constant 65599 was picked out of thin air while experimenting with different constants, and turns out to be a prime. this is one of the algorithms used in berkeley db (see sleepycat) and elsewhere. */ static unsigned execcache_calc_hash(const char *psz, unsigned *pcch) { unsigned char *puch = (unsigned char *)psz; unsigned hash = 0; int ch; while ((ch = *puch++)) hash = ch + (hash << 6) + (hash << 16) - hash; *pcch = (unsigned)(puch - psz - 1); return hash; } extern void kmk_cache_exec_image(const char *pszExec) { /* * Lookup the name. */ unsigned cchName; const unsigned uHash = execcache_calc_hash(pszExec, &cchName); PEXECCACHEENTRY *ppCur = &g_apHashTab[uHash % EXECCACHE_HASHTAB_SIZE]; PEXECCACHEENTRY pCur = *ppCur; while (pCur) { if ( pCur->uHash == uHash && pCur->cchName == cchName && !memcmp(pCur->szName, pszExec, cchName)) { pCur->uLastRef = ++g_uNow; return; } ppCur = &pCur->pNext; pCur = pCur->pNext; } /* * Not found, create a new entry. */ pCur = xmalloc(sizeof(*pCur) + cchName); pCur->uHash = uHash; pCur->cchName = cchName; pCur->pNext = NULL; pCur->uLastRef = ++g_uNow; memcpy(pCur->szName, pszExec, cchName + 1); pCur->hmod1 = LoadLibraryEx(pszExec, NULL, LOAD_LIBRARY_AS_DATAFILE); if (pCur->hmod1 != NULL) pCur->hmod2 = LoadLibraryEx(pszExec, NULL, DONT_RESOLVE_DLL_REFERENCES); else pCur->hmod2 = NULL; *ppCur = pCur; g_cCached++; } kbuild-2695/src/kmk/w32/subproc/0000755000000000000000000000000012247157306015101 5ustar rootrootkbuild-2695/src/kmk/w32/subproc/w32err.c0000644000000000000000000000404212247157306016371 0ustar rootroot/* Error handling for Windows Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "w32err.h" /* * Description: the windows32 version of perror() * * Returns: a pointer to a static error * * Notes/Dependencies: I got this from * comp.os.ms-windows.programmer.win32 */ char * map_windows32_error_to_string (DWORD ercode) { /* __declspec (thread) necessary if you will use multiple threads on MSVC */ #ifdef _MSC_VER __declspec (thread) static char szMessageBuffer[128]; #else static char szMessageBuffer[128]; #endif /* Fill message buffer with a default message in * case FormatMessage fails */ wsprintf (szMessageBuffer, "Error %ld\n", ercode); /* * Special code for winsock error handling. */ if (ercode > WSABASEERR) { HMODULE hModule = GetModuleHandle("wsock32"); if (hModule != NULL) { FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, hModule, ercode, LANG_NEUTRAL, szMessageBuffer, sizeof(szMessageBuffer), NULL); FreeLibrary(hModule); } } else { /* * Default system message handling */ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ercode, LANG_NEUTRAL, szMessageBuffer, sizeof(szMessageBuffer), NULL); } return szMessageBuffer; } kbuild-2695/src/kmk/w32/subproc/NMakefile0000644000000000000000000000365312247157306016666 0ustar rootroot# NOTE: If you have no `make' program at all to process this makefile, run # `build.bat' instead. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # # NMakefile for GNU Make (subproc library) # LIB = lib CC = cl MAKE = nmake OUTDIR=. MAKEFILE=NMakefile CFLAGS_any = /nologo /MT /W4 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS -I. -I../include -I../../ CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/ CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/ all: Release Debug Release: $(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib Debug: $(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib clean: rmdir /s /q WinRel WinDebug erase *.pdb $(OUTDIR): if not exist .\$@\nul mkdir .\$@ OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj $(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS) $(LIB) -out:$@ @<< $(OBJS) << .c{$(OUTDIR)}.obj: $(CC) $(CFLAGS) /c $< $(OUTDIR)/misc.obj: misc.c proc.h $(OUTDIR)/sub_proc.obj: sub_proc.c ../include/sub_proc.h ../include/w32err.h proc.h $(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h kbuild-2695/src/kmk/w32/subproc/misc.c0000644000000000000000000000402112247157306016175 0ustar rootroot/* Process handling for Windows Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include "proc.h" /* * Description: Convert a NULL string terminated UNIX environment block to * an environment block suitable for a windows32 system call * * Returns: TRUE= success, FALSE=fail * * Notes/Dependencies: the environment block is sorted in case-insensitive * order, is double-null terminated, and is a char *, not a char ** */ int _cdecl compare(const void *a1, const void *a2) { return _stricoll(*((char**)a1),*((char**)a2)); } bool_t arr2envblk(char **arr, char **envblk_out) { char **tmp; int size_needed; int arrcnt; char *ptr; arrcnt = 0; while (arr[arrcnt]) { arrcnt++; } tmp = (char**) calloc(arrcnt + 1, sizeof(char *)); if (!tmp) { return FALSE; } arrcnt = 0; size_needed = 0; while (arr[arrcnt]) { tmp[arrcnt] = arr[arrcnt]; size_needed += strlen(arr[arrcnt]) + 1; arrcnt++; } size_needed++; qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare); ptr = *envblk_out = calloc(size_needed, 1); if (!ptr) { free(tmp); return FALSE; } arrcnt = 0; while (tmp[arrcnt]) { strcpy(ptr, tmp[arrcnt]); ptr += strlen(tmp[arrcnt]) + 1; arrcnt++; } free(tmp); return TRUE; } kbuild-2695/src/kmk/w32/subproc/proc.h0000644000000000000000000000175312247157306016223 0ustar rootroot/* Definitions for Windows Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _PROC_H #define _PROC_H typedef int bool_t; #define E_SCALL 101 #define E_IO 102 #define E_NO_MEM 103 #define E_FORK 104 extern bool_t arr2envblk(char **arr, char **envblk_out); #endif kbuild-2695/src/kmk/w32/subproc/sub_proc.c0000644000000000000000000010042712247157306017065 0ustar rootroot/* Process handling for Windows. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #ifdef _MSC_VER # include /* for intptr_t */ #else # include #endif #include /* for msvc _beginthreadex, _endthreadex */ #include #include #include "sub_proc.h" #include "proc.h" #include "w32err.h" #include "debug.h" static char *make_command_line(char *shell_name, char *exec_path, char **argv); extern char *xmalloc (unsigned int); #ifdef KMK extern void kmk_cache_exec_image(const char *); /* imagecache.c */ #endif typedef struct sub_process_t { intptr_t sv_stdin[2]; intptr_t sv_stdout[2]; intptr_t sv_stderr[2]; int using_pipes; char *inp; DWORD incnt; char * volatile outp; volatile DWORD outcnt; char * volatile errp; volatile DWORD errcnt; pid_t pid; int exit_code; int signal; long last_err; long lerrno; } sub_process; static long process_file_io_private(sub_process *pproc, BOOL fNeedToWait); /* bird */ /* keep track of children so we can implement a waitpid-like routine */ static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS]; static int proc_index = 0; static int fake_exits_pending = 0; /* * When a process has been waited for, adjust the wait state * array so that we don't wait for it again */ static void process_adjust_wait_state(sub_process* pproc) { int i; if (!proc_index) return; for (i = 0; i < proc_index; i++) if (proc_array[i]->pid == pproc->pid) break; if (i < proc_index) { proc_index--; if (i != proc_index) memmove(&proc_array[i], &proc_array[i+1], (proc_index-i) * sizeof(sub_process*)); proc_array[proc_index] = NULL; } } /* * Waits for any of the registered child processes to finish. */ static sub_process * process_wait_for_any_private(void) { HANDLE handles[MAXIMUM_WAIT_OBJECTS]; DWORD retval, which; int i; if (!proc_index) return NULL; /* build array of handles to wait for */ for (i = 0; i < proc_index; i++) { handles[i] = (HANDLE) proc_array[i]->pid; if (fake_exits_pending && proc_array[i]->exit_code) break; } /* wait for someone to exit */ if (!fake_exits_pending) { retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE); which = retval - WAIT_OBJECT_0; } else { fake_exits_pending--; retval = !WAIT_FAILED; which = i; } /* return pointer to process */ if (retval != WAIT_FAILED) { sub_process* pproc = proc_array[which]; process_adjust_wait_state(pproc); return pproc; } else return NULL; } /* * Terminate a process. */ BOOL process_kill(HANDLE proc, int signal) { sub_process* pproc = (sub_process*) proc; pproc->signal = signal; return (TerminateProcess((HANDLE) pproc->pid, signal)); } /* * Use this function to register processes you wish to wait for by * calling process_file_io(NULL) or process_wait_any(). This must be done * because it is possible for callers of this library to reuse the same * handle for multiple processes launches :-( */ void process_register(HANDLE proc) { if (proc_index < MAXIMUM_WAIT_OBJECTS) proc_array[proc_index++] = (sub_process *) proc; } /* * Return the number of processes that we are still waiting for. */ int process_used_slots(void) { return proc_index; } /* * Public function which works kind of like waitpid(). Wait for any * of the children to die and return results. To call this function, * you must do 1 of things: * * x = process_easy(...); * * or * * x = process_init_fd(); * process_register(x); * * or * * x = process_init(); * process_register(x); * * You must NOT then call process_pipe_io() because this function is * not capable of handling automatic notification of any child * death. */ HANDLE process_wait_for_any(void) { sub_process* pproc = process_wait_for_any_private(); if (!pproc) return NULL; else { /* * Ouch! can't tell caller if this fails directly. Caller * will have to use process_last_err() */ #ifdef KMK (void) process_file_io_private(pproc, FALSE); #else (void) process_file_io(pproc); #endif return ((HANDLE) pproc); } } long process_signal(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return 0; return (((sub_process *)proc)->signal); } long process_last_err(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; return (((sub_process *)proc)->last_err); } long process_exit_code(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE; return (((sub_process *)proc)->exit_code); } /* 2006-02: All the following functions are currently unused. All of them would crash gmake if called with argument INVALID_HANDLE_VALUE. Hence whoever wants to use one of this functions must invent and implement a reasonable error handling for this function. char * process_outbuf(HANDLE proc) { return (((sub_process *)proc)->outp); } char * process_errbuf(HANDLE proc) { return (((sub_process *)proc)->errp); } int process_outcnt(HANDLE proc) { return (((sub_process *)proc)->outcnt); } int process_errcnt(HANDLE proc) { return (((sub_process *)proc)->errcnt); } void process_pipes(HANDLE proc, int pipes[3]) { pipes[0] = ((sub_process *)proc)->sv_stdin[0]; pipes[1] = ((sub_process *)proc)->sv_stdout[0]; pipes[2] = ((sub_process *)proc)->sv_stderr[0]; return; } */ HANDLE process_init() { sub_process *pproc; /* * open file descriptors for attaching stdin/stdout/sterr */ HANDLE stdin_pipes[2]; HANDLE stdout_pipes[2]; HANDLE stderr_pipes[2]; SECURITY_ATTRIBUTES inherit; BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; pproc = malloc(sizeof(*pproc)); memset(pproc, 0, sizeof(*pproc)); /* We can't use NULL for lpSecurityDescriptor because that uses the default security descriptor of the calling process. Instead we use a security descriptor with no DACL. This allows nonrestricted access to the associated objects. */ if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd), SECURITY_DESCRIPTOR_REVISION)) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } inherit.nLength = sizeof(inherit); inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd); inherit.bInheritHandle = TRUE; // By convention, parent gets pipe[0], and child gets pipe[1] // This means the READ side of stdin pipe goes into pipe[1] // and the WRITE side of the stdout and stderr pipes go into pipe[1] if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE || CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE || CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } // // Mark the parent sides of the pipes as non-inheritable // if (SetHandleInformation(stdin_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE || SetHandleInformation(stdout_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE || SetHandleInformation(stderr_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0]; pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1]; pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0]; pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1]; pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0]; pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1]; pproc->using_pipes = 1; pproc->lerrno = 0; return((HANDLE)pproc); } HANDLE process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) { sub_process *pproc; pproc = malloc(sizeof(*pproc)); memset(pproc, 0, sizeof(*pproc)); /* * Just pass the provided file handles to the 'child side' of the * pipe, bypassing pipes altogether. */ pproc->sv_stdin[1] = (intptr_t) stdinh; pproc->sv_stdout[1] = (intptr_t) stdouth; pproc->sv_stderr[1] = (intptr_t) stderrh; pproc->last_err = pproc->lerrno = 0; return((HANDLE)pproc); } static HANDLE find_file(const char *exec_path, const char *path_var, char *full_fname, DWORD full_len) { HANDLE exec_handle; char *fname; char *ext; DWORD req_len; int i; static const char *extensions[] = /* Should .com come before no-extension case? */ { ".exe", ".cmd", ".bat", "", ".com", NULL }; fname = xmalloc(strlen(exec_path) + 5); strcpy(fname, exec_path); ext = fname + strlen(fname); for (i = 0; extensions[i]; i++) { strcpy(ext, extensions[i]); if (((req_len = SearchPath (path_var, fname, NULL, full_len, full_fname, NULL)) > 0 /* For compatibility with previous code, which used OpenFile, and with Windows operation in general, also look in various default locations, such as Windows directory and Windows System directory. Warning: this also searches PATH in the Make's environment, which might not be what the Makefile wants, but it seems to be OK as a fallback, after the previous SearchPath failed to find on child's PATH. */ || (req_len = SearchPath (NULL, fname, NULL, full_len, full_fname, NULL)) > 0) && req_len <= full_len && (exec_handle = CreateFile(full_fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { free(fname); return(exec_handle); } } free(fname); return INVALID_HANDLE_VALUE; } /* * Description: Create the child process to be helped * * Returns: success <=> 0 * * Notes/Dependencies: */ long process_begin( HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user) { sub_process *pproc = (sub_process *)proc; char *shell_name = 0; int file_not_found=0; HANDLE exec_handle; char exec_fname[MAX_PATH]; const char *path_var = NULL; char **ep; char buf[256]; DWORD bytes_returned; DWORD flags; char *command_line; STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; char *envblk=NULL; #ifdef KMK size_t exec_path_len; #endif /* * Shell script detection... if the exec_path starts with #! then * we want to exec shell-script-name exec-path, not just exec-path * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not * hard-code the path to the shell or perl or whatever: Instead, we * assume it's in the path somewhere (generally, the NT tools * bin directory) */ #ifdef KMK /* kmk performance: Don't bother looking for shell scripts in .exe files. */ exec_path_len = strlen(exec_path); if (exec_path_len > 4 && exec_path[exec_path_len - 4] == '.' && !stricmp(exec_path + exec_path_len - 3, "exe")) { exec_handle = INVALID_HANDLE_VALUE; exec_fname[0] = '\0'; } else { #endif /* KMK */ /* Use the Makefile's value of PATH to look for the program to execute, because it could be different from Make's PATH (e.g., if the target sets its own value. */ if (envp) for (ep = envp; *ep; ep++) { if (strncmp (*ep, "PATH=", 5) == 0 || strncmp (*ep, "Path=", 5) == 0) { path_var = *ep + 5; break; } } exec_handle = find_file(exec_path, path_var, exec_fname, sizeof(exec_fname)); #ifdef KMK } #endif /* * If we couldn't open the file, just assume that Windows will be * somehow able to find and execute it. */ if (exec_handle == INVALID_HANDLE_VALUE) { file_not_found++; } else { /* Attempt to read the first line of the file */ if (ReadFile( exec_handle, buf, sizeof(buf) - 1, /* leave room for trailing NULL */ &bytes_returned, 0) == FALSE || bytes_returned < 2) { pproc->last_err = GetLastError(); pproc->lerrno = E_IO; CloseHandle(exec_handle); return(-1); } if (buf[0] == '#' && buf[1] == '!') { /* * This is a shell script... Change the command line from * exec_path args to shell_name exec_path args */ char *p; /* Make sure buf is NULL terminated */ buf[bytes_returned] = 0; /* * Depending on the file system type, etc. the first line * of the shell script may end with newline or newline-carriage-return * Whatever it ends with, cut it off. */ p= strchr(buf, '\n'); if (p) *p = 0; p = strchr(buf, '\r'); if (p) *p = 0; /* * Find base name of shell */ shell_name = strrchr( buf, '/'); if (shell_name) { shell_name++; } else { shell_name = &buf[2];/* skipping "#!" */ } } CloseHandle(exec_handle); } flags = 0; if (file_not_found) command_line = make_command_line( shell_name, exec_path, argv); else command_line = make_command_line( shell_name, exec_fname, argv); if ( command_line == NULL ) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; return(-1); } if (envp) { if (arr2envblk(envp, &envblk) ==FALSE) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; free( command_line ); return(-1); } } if ((shell_name) || (file_not_found)) { exec_path = 0; /* Search for the program in %Path% */ } else { exec_path = exec_fname; } /* * Set up inherited stdin, stdout, stderr for child */ GetStartupInfo(&startInfo); #ifndef KMK startInfo.dwFlags = STARTF_USESTDHANDLES; #endif startInfo.lpReserved = 0; startInfo.cbReserved2 = 0; startInfo.lpReserved2 = 0; startInfo.lpTitle = shell_name ? shell_name : exec_path; #ifndef KMK startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; #else if ( pproc->sv_stdin[1] || pproc->sv_stdout[1] || pproc->sv_stderr[1]) { startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; } else { startInfo.dwFlags = 0; startInfo.hStdInput = 0; startInfo.hStdOutput = 0; startInfo.hStdError = 0; } #endif if (as_user) { if (envblk) free(envblk); return -1; } else { DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", exec_path ? exec_path : "NULL", command_line ? command_line : "NULL")); #ifdef KMK if (exec_fname[0]) kmk_cache_exec_image(exec_fname); else if (exec_path) kmk_cache_exec_image(exec_path); else if (argv[0]) kmk_cache_exec_image(argv[0]); #endif if (CreateProcess( exec_path, command_line, NULL, 0, /* default security attributes for thread */ TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ flags, envblk, 0, /* default starting directory */ &startInfo, &procInfo) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_FORK; #ifdef KMK if (pproc->last_err == ERROR_FILE_NOT_FOUND) pproc->exit_code = 127; /* see execve failure in job.c. */ #endif fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path ? exec_path : "NULL", command_line); if (envblk) free(envblk); free( command_line ); return(-1); } } pproc->pid = (pid_t)procInfo.hProcess; /* Close the thread handle -- we'll just watch the process */ CloseHandle(procInfo.hThread); /* Close the halves of the pipes we don't need */ #ifndef KMK CloseHandle((HANDLE)pproc->sv_stdin[1]); CloseHandle((HANDLE)pproc->sv_stdout[1]); CloseHandle((HANDLE)pproc->sv_stderr[1]); pproc->sv_stdin[1] = 0; pproc->sv_stdout[1] = 0; pproc->sv_stderr[1] = 0; #else if ((HANDLE)pproc->sv_stdin[1]) { CloseHandle((HANDLE)pproc->sv_stdin[1]); pproc->sv_stdin[1] = 0; } if ((HANDLE)pproc->sv_stdout[1]) { CloseHandle((HANDLE)pproc->sv_stdout[1]); pproc->sv_stdout[1] = 0; } if ((HANDLE)pproc->sv_stderr[1]) { CloseHandle((HANDLE)pproc->sv_stderr[1]); pproc->sv_stderr[1] = 0; } #endif free( command_line ); if (envblk) free(envblk); pproc->lerrno=0; return 0; } static DWORD proc_stdin_thread(sub_process *pproc) { DWORD in_done; for (;;) { if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt, &in_done, NULL) == FALSE) _endthreadex(0); // This if should never be true for anonymous pipes, but gives // us a chance to change I/O mechanisms later if (in_done < pproc->incnt) { pproc->incnt -= in_done; pproc->inp += in_done; } else { _endthreadex(0); } } return 0; // for compiler warnings only.. not reached } static DWORD proc_stdout_thread(sub_process *pproc) { DWORD bufsize = 1024; char c; DWORD nread; pproc->outp = malloc(bufsize); if (pproc->outp == NULL) _endthreadex(0); pproc->outcnt = 0; for (;;) { if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL) == FALSE) { /* map_windows32_error_to_string(GetLastError());*/ _endthreadex(0); } if (nread == 0) _endthreadex(0); if (pproc->outcnt + nread > bufsize) { bufsize += nread + 512; pproc->outp = realloc(pproc->outp, bufsize); if (pproc->outp == NULL) { pproc->outcnt = 0; _endthreadex(0); } } pproc->outp[pproc->outcnt++] = c; } return 0; } static DWORD proc_stderr_thread(sub_process *pproc) { DWORD bufsize = 1024; char c; DWORD nread; pproc->errp = malloc(bufsize); if (pproc->errp == NULL) _endthreadex(0); pproc->errcnt = 0; for (;;) { if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) { map_windows32_error_to_string(GetLastError()); _endthreadex(0); } if (nread == 0) _endthreadex(0); if (pproc->errcnt + nread > bufsize) { bufsize += nread + 512; pproc->errp = realloc(pproc->errp, bufsize); if (pproc->errp == NULL) { pproc->errcnt = 0; _endthreadex(0); } } pproc->errp[pproc->errcnt++] = c; } return 0; } /* * Purpose: collects output from child process and returns results * * Description: * * Returns: * * Notes/Dependencies: */ long process_pipe_io( HANDLE proc, char *stdin_data, int stdin_data_len) { sub_process *pproc = (sub_process *)proc; bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE; HANDLE childhand = (HANDLE) pproc->pid; HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL; unsigned int dwStdin, dwStdout, dwStderr; HANDLE wait_list[4]; DWORD wait_count; DWORD wait_return; HANDLE ready_hand; bool_t child_dead = FALSE; BOOL GetExitCodeResult; /* * Create stdin thread, if needed */ pproc->inp = stdin_data; pproc->incnt = stdin_data_len; if (!pproc->inp) { stdin_eof = TRUE; CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; } else { tStdin = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stdin_thread, pproc, 0, &dwStdin); if (tStdin == 0) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } } /* * Assume child will produce stdout and stderr */ tStdout = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0, &dwStdout); tStderr = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0, &dwStderr); if (tStdout == 0 || tStderr == 0) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } /* * Wait for all I/O to finish and for the child process to exit */ while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) { wait_count = 0; if (!stdin_eof) { wait_list[wait_count++] = tStdin; } if (!stdout_eof) { wait_list[wait_count++] = tStdout; } if (!stderr_eof) { wait_list[wait_count++] = tStderr; } if (!child_dead) { wait_list[wait_count++] = childhand; } wait_return = WaitForMultipleObjects(wait_count, wait_list, FALSE, /* don't wait for all: one ready will do */ child_dead? 1000 :INFINITE); /* after the child dies, subthreads have one second to collect all remaining output */ if (wait_return == WAIT_FAILED) { /* map_windows32_error_to_string(GetLastError());*/ pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } ready_hand = wait_list[wait_return - WAIT_OBJECT_0]; if (ready_hand == tStdin) { CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; CloseHandle(tStdin); tStdin = 0; stdin_eof = TRUE; } else if (ready_hand == tStdout) { CloseHandle((HANDLE)pproc->sv_stdout[0]); pproc->sv_stdout[0] = 0; CloseHandle(tStdout); tStdout = 0; stdout_eof = TRUE; } else if (ready_hand == tStderr) { CloseHandle((HANDLE)pproc->sv_stderr[0]); pproc->sv_stderr[0] = 0; CloseHandle(tStderr); tStderr = 0; stderr_eof = TRUE; } else if (ready_hand == childhand) { DWORD ierr; GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); if (ierr == CONTROL_C_EXIT) { pproc->signal = SIGINT; } else { pproc->exit_code = ierr; } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } child_dead = TRUE; } else { /* ?? Got back a handle we didn't query ?? */ pproc->last_err = 0; pproc->lerrno = E_FAIL; goto done; } } done: if (tStdin != 0) CloseHandle(tStdin); if (tStdout != 0) CloseHandle(tStdout); if (tStderr != 0) CloseHandle(tStderr); if (pproc->lerrno) return(-1); else return(0); } /* * Purpose: collects output from child process and returns results * * Description: * * Returns: * * Notes/Dependencies: */ long process_file_io( HANDLE proc) { sub_process *pproc; if (proc == NULL) pproc = process_wait_for_any_private(); else pproc = (sub_process *)proc; /* some sort of internal error */ if (!pproc) return -1; return process_file_io_private(proc, TRUE); } /* private function, avoid some kernel calls. (bird) */ static long process_file_io_private( sub_process *pproc, BOOL fNeedToWait) { HANDLE childhand; DWORD wait_return; BOOL GetExitCodeResult; DWORD ierr; childhand = (HANDLE) pproc->pid; /* * This function is poorly named, and could also be used just to wait * for child death if you're doing your own pipe I/O. If that is * the case, close the pipe handles here. */ if (pproc->sv_stdin[0]) { CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; } if (pproc->sv_stdout[0]) { CloseHandle((HANDLE)pproc->sv_stdout[0]); pproc->sv_stdout[0] = 0; } if (pproc->sv_stderr[0]) { CloseHandle((HANDLE)pproc->sv_stderr[0]); pproc->sv_stderr[0] = 0; } #ifdef KMK if (childhand == NULL || childhand == INVALID_HANDLE_VALUE) { goto done2; } #endif /* * Wait for the child process to exit it we didn't do that already. */ if (fNeedToWait) { wait_return = WaitForSingleObject(childhand, INFINITE); if (wait_return != WAIT_OBJECT_0) { /* map_windows32_error_to_string(GetLastError());*/ pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done2; } } GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); if (ierr == CONTROL_C_EXIT) { pproc->signal = SIGINT; } else { pproc->exit_code = ierr; } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; } done2: if (pproc->lerrno) return(-1); else return(0); } /* * Description: Clean up any leftover handles, etc. It is up to the * caller to manage and free the input, ouput, and stderr buffers. */ void process_cleanup( HANDLE proc) { sub_process *pproc = (sub_process *)proc; int i; if (pproc->using_pipes) { for (i= 0; i <= 1; i++) { if ((HANDLE)pproc->sv_stdin[i]) CloseHandle((HANDLE)pproc->sv_stdin[i]); if ((HANDLE)pproc->sv_stdout[i]) CloseHandle((HANDLE)pproc->sv_stdout[i]); if ((HANDLE)pproc->sv_stderr[i]) CloseHandle((HANDLE)pproc->sv_stderr[i]); } } if ((HANDLE)pproc->pid) CloseHandle((HANDLE)pproc->pid); free(pproc); } /* * Description: * Create a command line buffer to pass to CreateProcess * * Returns: the buffer or NULL for failure * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ... * Otherwise: argv[0] argv[1] argv[2] ... * * Notes/Dependencies: * CreateProcess does not take an argv, so this command creates a * command line for the executable. */ static char * make_command_line( char *shell_name, char *full_exec_path, char **argv) { int argc = 0; char** argvi; int* enclose_in_quotes = NULL; int* enclose_in_quotes_i; unsigned int bytes_required = 0; char* command_line; char* command_line_i; int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */ int have_sh = 0; /* HAVE_CYGWIN_SHELL */ #undef HAVE_CYGWIN_SHELL #ifdef HAVE_CYGWIN_SHELL have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe")); cygwin_mode = 1; #endif if (shell_name && full_exec_path) { bytes_required = strlen(shell_name) + 1 + strlen(full_exec_path); /* * Skip argv[0] if any, when shell_name is given. */ if (*argv) argv++; /* * Add one for the intervening space. */ if (*argv) bytes_required++; } argvi = argv; while (*(argvi++)) argc++; if (argc) { enclose_in_quotes = (int*) calloc(1, argc * sizeof(int)); if (!enclose_in_quotes) { return NULL; } } /* We have to make one pass through each argv[i] to see if we need * to enclose it in ", so we might as well figure out how much * memory we'll need on the same pass. */ argvi = argv; enclose_in_quotes_i = enclose_in_quotes; while(*argvi) { char* p = *argvi; unsigned int backslash_count = 0; /* * We have to enclose empty arguments in ". */ if (!(*p)) *enclose_in_quotes_i = 1; while(*p) { switch (*p) { case '\"': /* * We have to insert a backslash for each " * and each \ that precedes the ". */ bytes_required += (backslash_count + 1); backslash_count = 0; break; #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) case '\\': backslash_count++; break; #endif /* * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so * that argv in always equals argv out. This was removed. Say you have * such a program named glob.exe. You enter * glob '*' * at the sh command prompt. Obviously the intent is to make glob do the * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?', * then the command line that glob would see would be * glob "*" * and the _setargv in SETARGV.OBJ would _not_ expand the *. */ case ' ': case '\t': *enclose_in_quotes_i = 1; /* fall through */ default: backslash_count = 0; break; } /* * Add one for each character in argv[i]. */ bytes_required++; p++; } if (*enclose_in_quotes_i) { /* * Add one for each enclosing ", * and one for each \ that precedes the * closing ". */ bytes_required += (backslash_count + 2); } /* * Add one for the intervening space. */ if (*(++argvi)) bytes_required++; enclose_in_quotes_i++; } /* * Add one for the terminating NULL. */ bytes_required++; #ifdef KMK /* for the space before the final " in case we need it. */ bytes_required++; #endif command_line = (char*) malloc(bytes_required); if (!command_line) { if (enclose_in_quotes) free(enclose_in_quotes); return NULL; } command_line_i = command_line; if (shell_name && full_exec_path) { while(*shell_name) { *(command_line_i++) = *(shell_name++); } *(command_line_i++) = ' '; while(*full_exec_path) { *(command_line_i++) = *(full_exec_path++); } if (*argv) { *(command_line_i++) = ' '; } } argvi = argv; enclose_in_quotes_i = enclose_in_quotes; while(*argvi) { char* p = *argvi; unsigned int backslash_count = 0; if (*enclose_in_quotes_i) { *(command_line_i++) = '\"'; } while(*p) { if (*p == '\"') { if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */ /* instead of a \", cygwin likes "" */ *(command_line_i++) = '\"'; } else { /* * We have to insert a backslash for the " * and each \ that precedes the ". */ backslash_count++; while(backslash_count) { *(command_line_i++) = '\\'; backslash_count--; }; } #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) } else if (*p == '\\') { backslash_count++; } else { backslash_count = 0; #endif } /* * Copy the character. */ *(command_line_i++) = *(p++); } if (*enclose_in_quotes_i) { #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) /* * Add one \ for each \ that precedes the * closing ". */ while(backslash_count--) { *(command_line_i++) = '\\'; }; #endif #ifdef KMK /* * ash it put off by echo "hello world" ending up as: * G:/.../kmk_ash.exe -c "echo ""hello world""" * It wants a space before the last '"'. * (The 'test_shell' goals in Makefile.kmk tests this problem.) */ if (command_line_i[-1] == '\"' /* && cygwin_mode && have_sh*/ && !argvi[1]) { *(command_line_i++) = ' '; } #endif *(command_line_i++) = '\"'; } /* * Append an intervening space. */ if (*(++argvi)) { *(command_line_i++) = ' '; } enclose_in_quotes_i++; } /* * Append the terminating NULL. */ *command_line_i = '\0'; if (enclose_in_quotes) free(enclose_in_quotes); return command_line; } /* * Description: Given an argv and optional envp, launch the process * using the default stdin, stdout, and stderr handles. * Also, register process so that process_wait_for_any_private() * can be used via process_file_io(NULL) or * process_wait_for_any(). * * Returns: * * Notes/Dependencies: */ HANDLE process_easy( char **argv, char **envp) { #ifndef KMK HANDLE hIn; HANDLE hOut; HANDLE hErr; #endif HANDLE hProcess; if (proc_index >= MAXIMUM_WAIT_OBJECTS) { DB (DB_JOBS, ("process_easy: All process slots used up\n")); return INVALID_HANDLE_VALUE; } #ifndef KMK if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), GetCurrentProcess(), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fprintf(stderr, "process_easy: DuplicateHandle(In) failed (e=%ld)\n", GetLastError()); return INVALID_HANDLE_VALUE; } if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE), GetCurrentProcess(), &hOut, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fprintf(stderr, "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", GetLastError()); return INVALID_HANDLE_VALUE; } if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fprintf(stderr, "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", GetLastError()); return INVALID_HANDLE_VALUE; } hProcess = process_init_fd(hIn, hOut, hErr); #else hProcess = process_init_fd(0, 0, 0); #endif /* !KMK */ if (process_begin(hProcess, argv, envp, argv[0], NULL)) { fake_exits_pending++; /* process_begin() failed: make a note of that. */ if (!((sub_process*) hProcess)->last_err) ((sub_process*) hProcess)->last_err = -1; #ifdef KMK if (!((sub_process*) hProcess)->exit_code) #endif ((sub_process*) hProcess)->exit_code = process_last_err(hProcess); #ifndef KMK /* close up unused handles */ CloseHandle(hIn); CloseHandle(hOut); CloseHandle(hErr); #endif } process_register(hProcess); return hProcess; } kbuild-2695/src/kmk/w32/subproc/build.bat0000644000000000000000000000504112247157306016670 0ustar rootroot@if "%1" == "gcc" GoTo GCCBuild if not exist .\WinDebug\nul mkdir .\WinDebug cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib .\WinDebug/misc.obj .\WinDebug/sub_proc.obj .\WinDebug/w32err.obj if not exist .\WinRel\nul mkdir .\WinRel cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c cl.exe /nologo /MT /W4 /GX /YX /O2 /I ../include /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib .\WinRel/misc.obj .\WinRel/sub_proc.obj .\WinRel/w32err.obj GoTo BuildEnd :GCCBuild gcc -mthreads -Wall -gdwarf-2 -g3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c misc.c -o ../../w32_misc.o gcc -mthreads -Wall -gdwarf-2 -g3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c sub_proc.c -o ../../sub_proc.o gcc -mthreads -Wall -gdwarf-2 -g3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 -c w32err.c -o ../../w32err.o :BuildEnd @echo off rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, rem 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . kbuild-2695/src/kmk/w32/compat/0000755000000000000000000000000012247157306014707 5ustar rootrootkbuild-2695/src/kmk/w32/compat/dirent.c0000644000000000000000000001074012247157306016342 0ustar rootroot/* Directory entry code for Window platforms. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #ifdef KMK_PRF # include #endif #include "dirent.h" DIR* opendir(const char* pDirName) { struct stat sb; DIR* pDir; char* pEndDirName; int nBufferLen; /* sanity checks */ if (!pDirName) { errno = EINVAL; return NULL; } if (stat(pDirName, &sb) != 0) { errno = ENOENT; return NULL; } if ((sb.st_mode & S_IFMT) != S_IFDIR) { errno = ENOTDIR; return NULL; } /* allocate a DIR structure to return */ pDir = (DIR *) malloc(sizeof (DIR)); if (!pDir) return NULL; /* input directory name length */ nBufferLen = strlen(pDirName); /* copy input directory name to DIR buffer */ strcpy(pDir->dir_pDirectoryName, pDirName); /* point to end of the copied directory name */ pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1]; /* if directory name did not end in '/' or '\', add '/' */ if ((*pEndDirName != '/') && (*pEndDirName != '\\')) { pEndDirName++; *pEndDirName = '/'; } /* now append the wildcard character to the buffer */ pEndDirName++; *pEndDirName = '*'; pEndDirName++; *pEndDirName = '\0'; /* other values defaulted */ pDir->dir_nNumFiles = 0; pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; pDir->dir_ulCookie = __DIRENT_COOKIE; #ifdef KMK_PRF fprintf(stderr, "opendir(%s) -> %p\n", pDirName, pDir); #endif return pDir; } void closedir(DIR *pDir) { /* got a valid pointer? */ if (!pDir) { errno = EINVAL; return; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return; } /* close the WINDOWS32 directory handle */ if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) FindClose(pDir->dir_hDirHandle); free(pDir); return; } struct dirent * readdir(DIR* pDir) { WIN32_FIND_DATA wfdFindData; if (!pDir) { errno = EINVAL; return NULL; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return NULL; } if (pDir->dir_nNumFiles == 0) { pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData); if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE) return NULL; } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData)) return NULL; /* bump count for next call to readdir() or telldir() */ pDir->dir_nNumFiles++; /* fill in struct dirent values */ pDir->dir_sdReturn.d_ino = (ino_t)-1; strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName); return &pDir->dir_sdReturn; } void rewinddir(DIR* pDir) { if (!pDir) { errno = EINVAL; return; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return; } /* close the WINDOWS32 directory handle */ if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) if (!FindClose(pDir->dir_hDirHandle)) errno = EBADF; /* reset members which control readdir() */ pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; pDir->dir_nNumFiles = 0; return; } int telldir(DIR* pDir) { if (!pDir) { errno = EINVAL; return -1; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return -1; } /* return number of times readdir() called */ return pDir->dir_nNumFiles; } void seekdir(DIR* pDir, long nPosition) { if (!pDir) return; /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) return; /* go back to beginning of directory */ rewinddir(pDir); /* loop until we have found position we care about */ for (--nPosition; nPosition && readdir(pDir); nPosition--); /* flag invalid nPosition value */ if (nPosition) errno = EINVAL; return; } kbuild-2695/src/kmk/w32/pathstuff.c0000644000000000000000000002115712247157306015602 0ustar rootroot/* Path conversion for Windows pathnames. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include /* bird */ #include "make.h" #include #include #include "pathstuff.h" /* * Convert delimiter separated vpath to Canonical format. */ char * convert_vpath_to_windows32(char *Path, char to_delim) { char *etok; /* token separator for old Path */ /* * Convert all spaces to delimiters. Note that pathnames which * contain blanks get trounced here. Use 8.3 format as a workaround. */ for (etok = Path; etok && *etok; etok++) if (isblank ((unsigned char) *etok)) *etok = to_delim; return (convert_Path_to_windows32(Path, to_delim)); } /* * Convert delimiter separated path to Canonical format. */ char * convert_Path_to_windows32(char *Path, char to_delim) { char *etok; /* token separator for old Path */ char *p; /* points to element of old Path */ /* is this a multi-element Path ? */ /* FIXME: Perhaps use ":;\"" in strpbrk to convert all quotes to delimiters as well, as a way to handle quoted directories in PATH? */ for (p = Path, etok = strpbrk(p, ":;"); etok; etok = strpbrk(p, ":;")) if ((etok - p) == 1) { if (*(etok - 1) == ';' || *(etok - 1) == ':') { etok[-1] = to_delim; etok[0] = to_delim; p = ++etok; continue; /* ignore empty bucket */ } else if (!isalpha ((unsigned char) *p)) { /* found one to count, handle things like '.' */ *etok = to_delim; p = ++etok; } else if ((*etok == ':') && (etok = strpbrk(etok+1, ":;"))) { /* found one to count, handle drive letter */ *etok = to_delim; p = ++etok; } else /* all finished, force abort */ p += strlen(p); } else if (*p == '"') { /* a quoted directory */ for (p++; *p && *p != '"'; p++) /* skip quoted part */ ; etok = strpbrk(p, ":;"); /* find next delimiter */ if (etok) { *etok = to_delim; p = ++etok; } else p += strlen(p); } else { /* found another one, no drive letter */ *etok = to_delim; p = ++etok; } return Path; } #if 1 /* bird */ extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull); #endif /* * Convert to forward slashes. Resolve to full pathname optionally */ char * w32ify(const char *filename, int resolve) { static char w32_path[FILENAME_MAX]; char *p; #if 1 /* bird */ if (resolve) { nt_fullpath(filename, w32_path, sizeof(w32_path)); } else { w32_path[0] = '\0'; strncat(w32_path, filename, sizeof(w32_path)); } #else /* !bird */ if (resolve) { _fullpath(w32_path, filename, sizeof (w32_path)); } else strncpy(w32_path, filename, sizeof (w32_path)); #endif /* !bird */ for (p = w32_path; p && *p; p++) if (*p == '\\') *p = '/'; return w32_path; } char * getcwd_fs(char* buf, int len) { char *p = getcwd(buf, len); if (p) { char *q = w32ify(buf, 0); #if 1 /* bird */ buf[0] = '\0'; strncat(buf, q, len); #else /* !bird */ strncpy(buf, q, len); #endif /* !bird */ } return p; } #ifdef unused /* * Convert delimiter separated pathnames (e.g. PATH) or single file pathname * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that * _NutPathToNutc() fails to convert, just return the path we were handed * and assume the caller will know what to do with it (It was probably * a mistake to try and convert it anyway due to some of the bizarre things * that might look like pathnames in makefiles). */ char * convert_path_to_nutc(char *path) { int count; /* count of path elements */ char *nutc_path; /* new NutC path */ int nutc_path_len; /* length of buffer to allocate for new path */ char *pathp; /* pointer to nutc_path used to build it */ char *etok; /* token separator for old path */ char *p; /* points to element of old path */ char sep; /* what flavor of separator used in old path */ char *rval; /* is this a multi-element path ? */ for (p = path, etok = strpbrk(p, ":;"), count = 0; etok; etok = strpbrk(p, ":;")) if ((etok - p) == 1) { if (*(etok - 1) == ';' || *(etok - 1) == ':') { p = ++etok; continue; /* ignore empty bucket */ } else if (etok = strpbrk(etok+1, ":;")) /* found one to count, handle drive letter */ p = ++etok, count++; else /* all finished, force abort */ p += strlen(p); } else /* found another one, no drive letter */ p = ++etok, count++; if (count) { count++; /* x1;x2;x3 <- need to count x3 */ /* * Hazard a guess on how big the buffer needs to be. * We have to convert things like c:/foo to /c=/foo. */ nutc_path_len = strlen(path) + (count*2) + 1; nutc_path = xmalloc(nutc_path_len); pathp = nutc_path; *pathp = '\0'; /* * Loop through PATH and convert one elemnt of the path at at * a time. Single file pathnames will fail this and fall * to the logic below loop. */ for (p = path, etok = strpbrk(p, ":;"); etok; etok = strpbrk(p, ":;")) { /* don't trip up on device specifiers or empty path slots */ if ((etok - p) == 1) if (*(etok - 1) == ';' || *(etok - 1) == ':') { p = ++etok; continue; } else if ((etok = strpbrk(etok+1, ":;")) == NULL) break; /* thing found was a WINDOWS32 pathname */ /* save separator */ sep = *etok; /* terminate the current path element -- temporarily */ *etok = '\0'; #ifdef __NUTC__ /* convert to NutC format */ if (_NutPathToNutc(p, pathp, 0) == FALSE) { free(nutc_path); rval = savestring(path, strlen(path)); return rval; } #else *pathp++ = '/'; *pathp++ = p[0]; *pathp++ = '='; *pathp++ = '/'; strcpy(pathp, &p[2]); #endif pathp += strlen(pathp); *pathp++ = ':'; /* use Unix style path separtor for new path */ *pathp = '\0'; /* make sure we are null terminaed */ /* restore path separator */ *etok = sep; /* point p to first char of next path element */ p = ++etok; } } else { nutc_path_len = strlen(path) + 3; nutc_path = xmalloc(nutc_path_len); pathp = nutc_path; *pathp = '\0'; p = path; } /* * OK, here we handle the last element in PATH (e.g. c of a;b;c) * or the path was a single filename and will be converted * here. Note, testing p here assures that we don't trip up * on paths like a;b; which have trailing delimiter followed by * nothing. */ if (*p != '\0') { #ifdef __NUTC__ if (_NutPathToNutc(p, pathp, 0) == FALSE) { free(nutc_path); rval = savestring(path, strlen(path)); return rval; } #else *pathp++ = '/'; *pathp++ = p[0]; *pathp++ = '='; *pathp++ = '/'; strcpy(pathp, &p[2]); #endif } else *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */ rval = savestring(nutc_path, strlen(nutc_path)); free(nutc_path); return rval; } #endif kbuild-2695/src/kmk/w32/tstFileInfo.c0000644000000000000000000001167612247157306016031 0ustar rootroot/* $Id: $ */ /** @file * Test program for some NtQueryInformationFile functionality. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #include #include typedef enum _FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, FileFullDirectoryInformation, // 2 FileBothDirectoryInformation, // 3 FileBasicInformation, // 4 wdm FileStandardInformation, // 5 wdm FileInternalInformation, // 6 FileEaInformation, // 7 FileAccessInformation, // 8 FileNameInformation, // 9 FileRenameInformation, // 10 FileLinkInformation, // 11 FileNamesInformation, // 12 FileDispositionInformation, // 13 FilePositionInformation, // 14 wdm FileFullEaInformation, // 15 FileModeInformation, // 16 FileAlignmentInformation, // 17 FileAllInformation, // 18 FileAllocationInformation, // 19 FileEndOfFileInformation, // 20 wdm FileAlternateNameInformation, // 21 FileStreamInformation, // 22 FilePipeInformation, // 23 FilePipeLocalInformation, // 24 FilePipeRemoteInformation, // 25 FileMailslotQueryInformation, // 26 FileMailslotSetInformation, // 27 FileCompressionInformation, // 28 FileObjectIdInformation, // 29 FileCompletionInformation, // 30 FileMoveClusterInformation, // 31 FileQuotaInformation, // 32 FileReparsePointInformation, // 33 FileNetworkOpenInformation, // 34 FileAttributeTagInformation, // 35 FileTrackingInformation, // 36 FileIdBothDirectoryInformation, // 37 FileIdFullDirectoryInformation, // 38 FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; typedef struct _FILE_NAME_INFORMATION { ULONG FileNameLength; WCHAR FileName[1]; } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; typedef LONG NTSTATUS; typedef struct _IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; }; ULONG_PTR Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); int main(int argc, char **argv) { int rc = 0; int i; NTSTATUS (NTAPI *pfnNtQueryInformationFile)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); pfnNtQueryInformationFile = GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryInformationFile"); for (i = 1; i < argc; i++) { HANDLE hFile = CreateFile(argv[i], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile) { long rcNt; char abBuf[4096]; IO_STATUS_BLOCK Ios; memset(abBuf, 0, sizeof(abBuf)); memset(&Ios, 0, sizeof(Ios)); rcNt = pfnNtQueryInformationFile(hFile, &Ios, abBuf, sizeof(abBuf), FileNameInformation); if (rcNt >= 0) { PFILE_NAME_INFORMATION pFileNameInfo = (PFILE_NAME_INFORMATION)abBuf; printf("#%d: %s - rcNt=%#x - FileNameInformation:\n" " FileName: %ls\n" " FileNameLength: %lu\n", i, argv[i], rcNt, pFileNameInfo->FileName, pFileNameInfo->FileNameLength ); } else printf("#%d: %s - rcNt=%#x - FileNameInformation!\n", i, argv[i], rcNt); CloseHandle(hFile); } else { printf("#%d: %s - open failed, last error %d\n", i, argv[i], GetLastError()); rc = 1; } } return rc; } kbuild-2695/src/kmk/w32/Makefile.am0000644000000000000000000000202212247157306015454 0ustar rootroot# Makefile.am to create libw32.a for mingw32 host. # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . noinst_LIBRARIES = libw32.a libw32_a_SOURCES = subproc/misc.c subproc/sub_proc.c subproc/w32err.c \ pathstuff.c libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir) kbuild-2695/src/kmk/w32/include/0000755000000000000000000000000012247157306015047 5ustar rootrootkbuild-2695/src/kmk/w32/include/dirent.h0000644000000000000000000000301412247157306016503 0ustar rootroot/* Windows version of dirent.h Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _DIRENT_H #define _DIRENT_H #ifdef __MINGW32__ # include # include_next #else #include #include #include #include #ifndef NAME_MAX #define NAME_MAX 255 #endif #define __DIRENT_COOKIE 0xfefeabab struct dirent { ino_t d_ino; /* unused - no equivalent on WINDOWS32 */ char d_name[NAME_MAX+1]; }; typedef struct dir_struct { ULONG dir_ulCookie; HANDLE dir_hDirHandle; DWORD dir_nNumFiles; char dir_pDirectoryName[NAME_MAX+1]; struct dirent dir_sdReturn; } DIR; DIR *opendir(const char *); struct dirent *readdir(DIR *); void rewinddir(DIR *); void closedir(DIR *); int telldir(DIR *); void seekdir(DIR *, long); #endif /* !__MINGW32__ */ #endif kbuild-2695/src/kmk/w32/include/w32err.h0000644000000000000000000000177412247157306016355 0ustar rootroot/* Definitions for Windows error handling. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _W32ERR_H_ #define _W32ERR_H_ #ifndef EXTERN_DECL #define EXTERN_DECL(entry, args) entry args #endif EXTERN_DECL(char * map_windows32_error_to_string, (DWORD error)); #endif /* !_W32ERR_H */ kbuild-2695/src/kmk/w32/include/pathstuff.h0000644000000000000000000000206712247157306017231 0ustar rootroot/* Definitions for Windows path manipulation. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _PATHSTUFF_H #define _PATHSTUFF_H char *convert_Path_to_windows32(char *Path, char to_delim); char *convert_vpath_to_windows32(char *Path, char to_delim); char *w32ify(const char *filename, int resolve); char *getcwd_fs(char *buf, int len); #endif kbuild-2695/src/kmk/w32/include/sub_proc.h0000644000000000000000000000441712247157306017042 0ustar rootroot/* Definitions for Windows process invocation. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef SUB_PROC_H #define SUB_PROC_H /* * Component Name: * * $Date: 2010/07/13 01:20:43 $ * * $Source: /sources/make/make/w32/include/sub_proc.h,v $ * * $Id: sub_proc.h,v 1.12 2010/07/13 01:20:43 psmith Exp $ */ #define EXTERN_DECL(entry, args) extern entry args #define VOID_DECL void EXTERN_DECL(HANDLE process_init, (VOID_DECL)); EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)); EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user)); EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data, int stdin_data_len)); EXTERN_DECL(long process_file_io, (HANDLE proc)); EXTERN_DECL(void process_cleanup, (HANDLE proc)); EXTERN_DECL(HANDLE process_wait_for_any, (VOID_DECL)); EXTERN_DECL(void process_register, (HANDLE proc)); EXTERN_DECL(HANDLE process_easy, (char** argv, char** env)); EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal)); EXTERN_DECL(int process_used_slots, (VOID_DECL)); /* support routines */ EXTERN_DECL(long process_errno, (HANDLE proc)); EXTERN_DECL(long process_last_err, (HANDLE proc)); EXTERN_DECL(long process_exit_code, (HANDLE proc)); EXTERN_DECL(long process_signal, (HANDLE proc)); EXTERN_DECL(char * process_outbuf, (HANDLE proc)); EXTERN_DECL(char * process_errbuf, (HANDLE proc)); EXTERN_DECL(int process_outcnt, (HANDLE proc)); EXTERN_DECL(int process_errcnt, (HANDLE proc)); EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3])); #endif kbuild-2695/src/kmk/w32/Makefile.kmk0000644000000000000000000000174412247157306015653 0ustar rootroot# $Id: $ ## @file # Sub-makefile for tstFileInfo / w32. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = ../../.. include $(KBUILD_PATH)/subheader.kmk # # tstFileInfo # PROGRAMS.win += tstFileInfo tstFileInfo_TEMPLATE = BIN tstFileInfo_SOURCES = tstFileInfo.c include $(FILE_KBUILD_SUB_FOOTER) kbuild-2695/src/kmk/job.c0000644000000000000000000032046012247157306013734 0ustar rootroot/* Job execution and handling for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include #include "job.h" #include "debug.h" #include "filedef.h" #include "commands.h" #include "variable.h" #include "debug.h" #ifdef CONFIG_WITH_KMK_BUILTIN # include "kmkbuiltin.h" #endif #ifdef KMK # include "kbuild.h" #endif #include /* Default shell to use. */ #ifdef WINDOWS32 #include char *default_shell = "sh.exe"; int no_default_sh_exe = 1; int batch_mode_shell = 1; HANDLE main_thread; #elif defined (_AMIGA) char default_shell[] = ""; extern int MyExecute (char **); int batch_mode_shell = 0; #elif defined (__MSDOS__) /* The default shell is a pointer so we can change it if Makefile says so. It is without an explicit path so we get a chance to search the $PATH for it (since MSDOS doesn't have standard directories we could trust). */ char *default_shell = "command.com"; int batch_mode_shell = 0; #elif defined (__EMX__) char *default_shell = "sh.exe"; /* bird changed this from "/bin/sh" as that doesn't make sense on OS/2. */ int batch_mode_shell = 0; #elif defined (VMS) # include char default_shell[] = ""; int batch_mode_shell = 0; #elif defined (__riscos__) char default_shell[] = ""; int batch_mode_shell = 0; #else char default_shell[] = "/bin/sh"; int batch_mode_shell = 0; #endif #ifdef __MSDOS__ # include static int execute_by_shell; static int dos_pid = 123; int dos_status; int dos_command_running; #endif /* __MSDOS__ */ #ifdef _AMIGA # include static int amiga_pid = 123; static int amiga_status; static char amiga_bname[32]; static int amiga_batch_file; #endif /* Amiga. */ #ifdef VMS # ifndef __GNUC__ # include # endif # include # include static void vmsWaitForChildren (int *); #endif #ifdef WINDOWS32 # include # include # include # include "sub_proc.h" # include "w32err.h" # include "pathstuff.h" #endif /* WINDOWS32 */ #ifdef __EMX__ # include #endif #if defined (HAVE_SYS_WAIT_H) || defined (HAVE_UNION_WAIT) # include #endif #ifdef HAVE_WAITPID # define WAIT_NOHANG(status) waitpid (-1, (status), WNOHANG) #else /* Don't have waitpid. */ # ifdef HAVE_WAIT3 # ifndef wait3 extern int wait3 (); # endif # define WAIT_NOHANG(status) wait3 ((status), WNOHANG, (struct rusage *) 0) # endif /* Have wait3. */ #endif /* Have waitpid. */ #if !defined (wait) && !defined (POSIX) int wait (); #endif #ifndef HAVE_UNION_WAIT # define WAIT_T int # ifndef WTERMSIG # define WTERMSIG(x) ((x) & 0x7f) # endif # ifndef WCOREDUMP # define WCOREDUMP(x) ((x) & 0x80) # endif # ifndef WEXITSTATUS # define WEXITSTATUS(x) (((x) >> 8) & 0xff) # endif # ifndef WIFSIGNALED # define WIFSIGNALED(x) (WTERMSIG (x) != 0) # endif # ifndef WIFEXITED # define WIFEXITED(x) (WTERMSIG (x) == 0) # endif #else /* Have `union wait'. */ # define WAIT_T union wait # ifndef WTERMSIG # define WTERMSIG(x) ((x).w_termsig) # endif # ifndef WCOREDUMP # define WCOREDUMP(x) ((x).w_coredump) # endif # ifndef WEXITSTATUS # define WEXITSTATUS(x) ((x).w_retcode) # endif # ifndef WIFSIGNALED # define WIFSIGNALED(x) (WTERMSIG(x) != 0) # endif # ifndef WIFEXITED # define WIFEXITED(x) (WTERMSIG(x) == 0) # endif #endif /* Don't have `union wait'. */ #if !defined(HAVE_UNISTD_H) && !defined(WINDOWS32) # ifndef _MSC_VER /* bird */ int dup2 (); int execve (); void _exit (); # endif /* bird */ # ifndef VMS int geteuid (); int getegid (); int setgid (); int getgid (); # endif #endif /* Different systems have different requirements for pid_t. Plus we have to support gettext string translation... Argh. */ static const char * pid2str (pid_t pid) { static char pidstring[100]; #if defined(WINDOWS32) && (__GNUC__ > 3 || _MSC_VER > 1300) /* %Id is only needed for 64-builds, which were not supported by older versions of Windows compilers. */ sprintf (pidstring, "%Id", pid); #else sprintf (pidstring, "%lu", (unsigned long) pid); #endif return pidstring; } int getloadavg (double loadavg[], int nelem); int start_remote_job (char **argv, char **envp, int stdin_fd, int *is_remote, int *id_ptr, int *used_stdin); int start_remote_job_p (int); int remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr, int block); RETSIGTYPE child_handler (int); static void free_child (struct child *); static void start_job_command (struct child *child); static int load_too_high (void); static int job_next_command (struct child *); static int start_waiting_job (struct child *); #ifdef CONFIG_WITH_PRINT_TIME_SWITCH static void print_job_time (struct child *); #endif /* Chain of all live (or recently deceased) children. */ struct child *children = 0; /* Number of children currently running. */ unsigned int job_slots_used = 0; /* Nonzero if the `good' standard input is in use. */ static int good_stdin_used = 0; /* Chain of children waiting to run until the load average goes down. */ static struct child *waiting_jobs = 0; /* Non-zero if we use a *real* shell (always so on Unix). */ int unixy_shell = 1; /* Number of jobs started in the current second. */ unsigned long job_counter = 0; /* Number of jobserver tokens this instance is currently using. */ unsigned int jobserver_tokens = 0; #ifdef WINDOWS32 /* * The macro which references this function is defined in make.h. */ int w32_kill(pid_t pid, int sig) { return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1); } /* This function creates a temporary file name with an extension specified * by the unixy arg. * Return an xmalloc'ed string of a newly created temp file and its * file descriptor, or die. */ static char * create_batch_file (char const *base, int unixy, int *fd) { const char *const ext = unixy ? "sh" : "bat"; const char *error_string = NULL; char temp_path[MAXPATHLEN]; /* need to know its length */ unsigned path_size = GetTempPath(sizeof temp_path, temp_path); int path_is_dot = 0; unsigned uniq = 1; const unsigned sizemax = strlen (base) + strlen (ext) + 10; if (path_size == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } while (path_size > 0 && path_size + sizemax < sizeof temp_path && uniq < 0x10000) { unsigned size = sprintf (temp_path + path_size, "%s%s-%x.%s", temp_path[path_size - 1] == '\\' ? "" : "\\", base, uniq, ext); HANDLE h = CreateFile (temp_path, /* file name */ GENERIC_READ | GENERIC_WRITE, /* desired access */ 0, /* no share mode */ NULL, /* default security attributes */ CREATE_NEW, /* creation disposition */ FILE_ATTRIBUTE_NORMAL | /* flags and attributes */ FILE_ATTRIBUTE_TEMPORARY, /* we'll delete it */ NULL); /* no template file */ if (h == INVALID_HANDLE_VALUE) { const DWORD er = GetLastError(); if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS) ++uniq; /* the temporary path is not guaranteed to exist */ else if (path_is_dot == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } else { error_string = map_windows32_error_to_string (er); break; } } else { const unsigned final_size = path_size + size + 1; char *const path = xmalloc (final_size); memcpy (path, temp_path, final_size); *fd = _open_osfhandle ((intptr_t)h, 0); if (unixy) { char *p; int ch; for (p = path; (ch = *p) != 0; ++p) if (ch == '\\') *p = '/'; } return path; /* good return */ } } *fd = -1; if (error_string == NULL) error_string = _("Cannot create a temporary file\n"); fatal (NILF, error_string); /* not reached */ return NULL; } #endif /* WINDOWS32 */ #ifdef __EMX__ /* returns whether path is assumed to be a unix like shell. */ int _is_unixy_shell (const char *path) { /* list of non unix shells */ const char *known_os2shells[] = { "cmd.exe", "cmd", "4os2.exe", "4os2", "4dos.exe", "4dos", "command.com", "command", NULL }; /* find the rightmost '/' or '\\' */ const char *name = strrchr (path, '/'); const char *p = strrchr (path, '\\'); unsigned i; if (name && p) /* take the max */ name = (name > p) ? name : p; else if (p) /* name must be 0 */ name = p; else if (!name) /* name and p must be 0 */ name = path; if (*name == '/' || *name == '\\') name++; i = 0; while (known_os2shells[i] != NULL) { if (strcasecmp (name, known_os2shells[i]) == 0) return 0; /* not a unix shell */ i++; } /* in doubt assume a unix like shell */ return 1; } #endif /* __EMX__ */ /* determines whether path looks to be a Bourne-like shell. */ int is_bourne_compatible_shell (const char *path) { /* list of known unix (Bourne-like) shells */ const char *unix_shells[] = { "sh", "bash", "ksh", "rksh", "zsh", "ash", "dash", NULL }; unsigned i, len; /* find the rightmost '/' or '\\' */ const char *name = strrchr (path, '/'); char *p = strrchr (path, '\\'); if (name && p) /* take the max */ name = (name > p) ? name : p; else if (p) /* name must be 0 */ name = p; else if (!name) /* name and p must be 0 */ name = path; if (*name == '/' || *name == '\\') name++; /* this should be able to deal with extensions on Windows-like systems */ for (i = 0; unix_shells[i] != NULL; i++) { len = strlen(unix_shells[i]); #if defined(WINDOWS32) || defined(__MSDOS__) if ((strncasecmp (name, unix_shells[i], len) == 0) && (strlen(name) >= len && (name[len] == '\0' || name[len] == '.'))) #else if ((strncmp (name, unix_shells[i], len) == 0) && (strlen(name) >= len && name[len] == '\0')) #endif return 1; /* a known unix-style shell */ } /* if not on the list, assume it's not a Bourne-like shell */ return 0; } /* Write an error message describing the exit status given in EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME. Append "(ignored)" if IGNORED is nonzero. */ static void child_error (const char *target_name, int exit_code, int exit_sig, int coredump, int ignored) { if (ignored && silent_flag) return; #ifdef VMS if (!(exit_code & 1)) error (NILF, (ignored ? _("*** [%s] Error 0x%x (ignored)") : _("*** [%s] Error 0x%x")), target_name, exit_code); #else if (exit_sig == 0) error (NILF, ignored ? _("[%s] Error %d (ignored)") : _("*** [%s] Error %d"), target_name, exit_code); else error (NILF, "*** [%s] %s%s", target_name, strsignal (exit_sig), coredump ? _(" (core dumped)") : ""); #endif /* VMS */ } /* Handle a dead child. This handler may or may not ever be installed. If we're using the jobserver feature, we need it. First, installing it ensures the read will interrupt on SIGCHLD. Second, we close the dup'd read FD to ensure we don't enter another blocking read without reaping all the dead children. In this case we don't need the dead_children count. If we don't have either waitpid or wait3, then make is unreliable, but we use the dead_children count to reap children as best we can. */ static unsigned int dead_children = 0; RETSIGTYPE child_handler (int sig UNUSED) { ++dead_children; if (job_rfd >= 0) { close (job_rfd); job_rfd = -1; } #if defined __EMX__ && !defined(__INNOTEK_LIBC__) /* bird */ /* The signal handler must called only once! */ signal (SIGCHLD, SIG_DFL); #endif /* This causes problems if the SIGCHLD interrupts a printf(). DB (DB_JOBS, (_("Got a SIGCHLD; %u unreaped children.\n"), dead_children)); */ } extern int shell_function_pid, shell_function_completed; /* Reap all dead children, storing the returned status and the new command state (`cs_finished') in the `file' member of the `struct child' for the dead child, and removing the child from the chain. In addition, if BLOCK nonzero, we block in this function until we've reaped at least one complete child, waiting for it to die if necessary. If ERR is nonzero, print an error message first. */ void reap_children (int block, int err) { #ifndef WINDOWS32 WAIT_T status; /* Initially, assume we have some. */ int reap_more = 1; #endif #ifdef WAIT_NOHANG # define REAP_MORE reap_more #else # define REAP_MORE dead_children #endif /* As long as: We have at least one child outstanding OR a shell function in progress, AND We're blocking for a complete child OR there are more children to reap we'll keep reaping children. */ while ((children != 0 || shell_function_pid != 0) && (block || REAP_MORE)) { int remote = 0; pid_t pid; int exit_code, exit_sig, coredump; register struct child *lastc, *c; int child_failed; int any_remote, any_local; int dontcare; #ifdef CONFIG_WITH_KMK_BUILTIN struct child *completed_child = NULL; #endif if (err && block) { static int printed = 0; /* We might block for a while, so let the user know why. Only print this message once no matter how many jobs are left. */ fflush (stdout); if (!printed) error (NILF, _("*** Waiting for unfinished jobs....")); printed = 1; } /* We have one less dead child to reap. As noted in child_handler() above, this count is completely unimportant for all modern, POSIX-y systems that support wait3() or waitpid(). The rest of this comment below applies only to early, broken pre-POSIX systems. We keep the count only because... it's there... The test and decrement are not atomic; if it is compiled into: register = dead_children - 1; dead_children = register; a SIGCHLD could come between the two instructions. child_handler increments dead_children. The second instruction here would lose that increment. But the only effect of dead_children being wrong is that we might wait longer than necessary to reap a child, and lose some parallelism; and we might print the "Waiting for unfinished jobs" message above when not necessary. */ if (dead_children > 0) --dead_children; any_remote = 0; any_local = shell_function_pid != 0; for (c = children; c != 0; c = c->next) { any_remote |= c->remote; any_local |= ! c->remote; #ifdef CONFIG_WITH_KMK_BUILTIN if (c->has_status) { completed_child = c; DB (DB_JOBS, (_("builtin child %p (%s) PID %s %s Status %ld\n"), (void *)c, c->file->name, pid2str (c->pid), c->remote ? _(" (remote)") : "", (long) c->status)); } else #endif DB (DB_JOBS, (_("Live child %p (%s) PID %s %s\n"), (void *)c, c->file->name, pid2str (c->pid), c->remote ? _(" (remote)") : "")); #ifdef VMS break; #endif } /* First, check for remote children. */ if (any_remote) pid = remote_status (&exit_code, &exit_sig, &coredump, 0); else pid = 0; if (pid > 0) /* We got a remote child. */ remote = 1; else if (pid < 0) { /* A remote status command failed miserably. Punt. */ remote_status_lose: pfatal_with_name ("remote_status"); } else { /* No remote children. Check for local children. */ #ifdef CONFIG_WITH_KMK_BUILTIN if (completed_child) { pid = completed_child->pid; # if defined(WINDOWS32) exit_code = completed_child->status; exit_sig = 0; coredump = 0; # else status = (WAIT_T)completed_child->status; # endif } else #endif /* CONFIG_WITH_KMK_BUILTIN */ #if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32) if (any_local) { #ifdef VMS vmsWaitForChildren (&status); pid = c->pid; #else #ifdef WAIT_NOHANG if (!block) pid = WAIT_NOHANG (&status); else #endif EINTRLOOP(pid, wait (&status)); #endif /* !VMS */ } else pid = 0; if (pid < 0) { /* The wait*() failed miserably. Punt. */ pfatal_with_name ("wait"); } else if (pid > 0) { /* We got a child exit; chop the status word up. */ exit_code = WEXITSTATUS (status); exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0; coredump = WCOREDUMP (status); /* If we have started jobs in this second, remove one. */ if (job_counter) --job_counter; } else { /* No local children are dead. */ reap_more = 0; if (!block || !any_remote) break; /* Now try a blocking wait for a remote child. */ pid = remote_status (&exit_code, &exit_sig, &coredump, 1); if (pid < 0) goto remote_status_lose; else if (pid == 0) /* No remote children either. Finally give up. */ break; /* We got a remote child. */ remote = 1; } #endif /* !__MSDOS__, !Amiga, !WINDOWS32. */ #ifdef __MSDOS__ /* Life is very different on MSDOS. */ pid = dos_pid - 1; status = dos_status; exit_code = WEXITSTATUS (status); if (exit_code == 0xff) exit_code = -1; exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0; coredump = 0; #endif /* __MSDOS__ */ #ifdef _AMIGA /* Same on Amiga */ pid = amiga_pid - 1; status = amiga_status; exit_code = amiga_status; exit_sig = 0; coredump = 0; #endif /* _AMIGA */ #ifdef WINDOWS32 { HANDLE hPID; int werr; HANDLE hcTID, hcPID; exit_code = 0; exit_sig = 0; coredump = 0; /* Record the thread ID of the main process, so that we could suspend it in the signal handler. */ if (!main_thread) { hcTID = GetCurrentThread (); hcPID = GetCurrentProcess (); if (!DuplicateHandle (hcPID, hcTID, hcPID, &main_thread, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DWORD e = GetLastError (); fprintf (stderr, "Determine main thread ID (Error %ld: %s)\n", e, map_windows32_error_to_string(e)); } else DB (DB_VERBOSE, ("Main thread handle = %p\n", main_thread)); } /* wait for anything to finish */ hPID = process_wait_for_any(); if (hPID) { /* was an error found on this process? */ werr = process_last_err(hPID); /* get exit data */ exit_code = process_exit_code(hPID); if (werr) fprintf(stderr, "make (e=%d): %s", exit_code, map_windows32_error_to_string(exit_code)); /* signal */ exit_sig = process_signal(hPID); /* cleanup process */ process_cleanup(hPID); coredump = 0; } else if (!process_used_slots()) { /* The wait*() failed miserably. Punt. */ errno = ECHILD; pfatal_with_name ("wait"); } pid = (pid_t) hPID; } #endif /* WINDOWS32 */ } /* Check if this is the child of the `shell' function. */ if (!remote && pid == shell_function_pid) { /* It is. Leave an indicator for the `shell' function. */ if (exit_sig == 0 && exit_code == 127) shell_function_completed = -1; else shell_function_completed = 1; break; } child_failed = exit_sig != 0 || exit_code != 0; /* Search for a child matching the deceased one. */ lastc = 0; for (c = children; c != 0; lastc = c, c = c->next) if (c->remote == remote && c->pid == pid) break; if (c == 0) /* An unknown child died. Ignore it; it was inherited from our invoker. */ continue; DB (DB_JOBS, (child_failed ? _("Reaping losing child %p PID %s %s\n") : _("Reaping winning child %p PID %s %s\n"), (void *)c, pid2str (c->pid), c->remote ? _(" (remote)") : "")); if (c->sh_batch_file) { DB (DB_JOBS, (_("Cleaning up temp batch file %s\n"), c->sh_batch_file)); /* just try and remove, don't care if this fails */ remove (c->sh_batch_file); /* all done with memory */ free (c->sh_batch_file); c->sh_batch_file = NULL; } /* If this child had the good stdin, say it is now free. */ if (c->good_stdin) good_stdin_used = 0; dontcare = c->dontcare; if (child_failed && !c->noerror && !ignore_errors_flag) { /* The commands failed. Write an error message, delete non-precious targets, and abort. */ static int delete_on_error = -1; if (!dontcare) #ifdef KMK { child_error (c->file->name, exit_code, exit_sig, coredump, 0); if (( c->file->cmds->lines_flags[c->command_line - 1] & (COMMANDS_SILENT | COMMANDS_RECURSE)) == COMMANDS_SILENT) message (0, "The failing command:\n%s", c->file->cmds->command_lines[c->command_line - 1]); } #else /* !KMK */ child_error (c->file->name, exit_code, exit_sig, coredump, 0); #endif /* !KMK */ c->file->update_status = 2; if (delete_on_error == -1) { struct file *f = lookup_file (".DELETE_ON_ERROR"); delete_on_error = f != 0 && f->is_target; } if (exit_sig != 0 || delete_on_error) delete_child_targets (c); } else { if (child_failed) { /* The commands failed, but we don't care. */ child_error (c->file->name, exit_code, exit_sig, coredump, 1); child_failed = 0; } /* If there are more commands to run, try to start them. */ if (job_next_command (c)) { if (handling_fatal_signal) { /* Never start new commands while we are dying. Since there are more commands that wanted to be run, the target was not completely remade. So we treat this as if a command had failed. */ c->file->update_status = 2; } else { /* Check again whether to start remotely. Whether or not we want to changes over time. Also, start_remote_job may need state set up by start_remote_job_p. */ c->remote = start_remote_job_p (0); start_job_command (c); /* Fatal signals are left blocked in case we were about to put that child on the chain. But it is already there, so it is safe for a fatal signal to arrive now; it will clean up this child's targets. */ unblock_sigs (); if (c->file->command_state == cs_running) /* We successfully started the new command. Loop to reap more children. */ continue; } if (c->file->update_status != 0) /* We failed to start the commands. */ delete_child_targets (c); } else /* There are no more commands. We got through them all without an unignored error. Now the target has been successfully updated. */ c->file->update_status = 0; } /* When we get here, all the commands for C->file are finished (or aborted) and C->file->update_status contains 0 or 2. But C->file->command_state is still cs_running if all the commands ran; notice_finish_file looks for cs_running to tell it that it's interesting to check the file's modtime again now. */ if (! handling_fatal_signal) /* Notice if the target of the commands has been changed. This also propagates its values for command_state and update_status to its also_make files. */ notice_finished_file (c->file); DB (DB_JOBS, (_("Removing child %p PID %s%s from chain.\n"), (void *)c, pid2str (c->pid), c->remote ? _(" (remote)") : "")); /* Block fatal signals while frobnicating the list, so that children and job_slots_used are always consistent. Otherwise a fatal signal arriving after the child is off the chain and before job_slots_used is decremented would believe a child was live and call reap_children again. */ block_sigs (); /* There is now another slot open. */ if (job_slots_used > 0) --job_slots_used; /* Remove the child from the chain and free it. */ if (lastc == 0) children = c->next; else lastc->next = c->next; free_child (c); unblock_sigs (); /* If the job failed, and the -k flag was not given, die, unless we are already in the process of dying. */ if (!err && child_failed && !dontcare && !keep_going_flag && /* fatal_error_signal will die with the right signal. */ !handling_fatal_signal) die (2); /* Only block for one child. */ block = 0; } return; } /* Free the storage allocated for CHILD. */ static void free_child (struct child *child) { #ifdef CONFIG_WITH_PRINT_TIME_SWITCH print_job_time (child); #endif if (!jobserver_tokens) fatal (NILF, "INTERNAL: Freeing child %p (%s) but no tokens left!\n", (void *)child, child->file->name); /* If we're using the jobserver and this child is not the only outstanding job, put a token back into the pipe for it. */ if (job_fds[1] >= 0 && jobserver_tokens > 1) { char token = '+'; int r; /* Write a job token back to the pipe. */ EINTRLOOP (r, write (job_fds[1], &token, 1)); if (r != 1) pfatal_with_name (_("write jobserver")); DB (DB_JOBS, (_("Released token for child %p (%s).\n"), (void *)child, child->file->name)); } --jobserver_tokens; if (handling_fatal_signal) /* Don't bother free'ing if about to die. */ return; if (child->command_lines != 0) { register unsigned int i; for (i = 0; i < child->file->cmds->ncommand_lines; ++i) free (child->command_lines[i]); free (child->command_lines); } if (child->environment != 0) { register char **ep = child->environment; while (*ep != 0) free (*ep++); free (child->environment); } #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS /* Free the chopped command lines for simple targets when there are no more active references to them. */ child->file->cmds->refs--; if ( !child->file->intermediate && !child->file->pat_variables && child->file->cmds->refs == 0) { struct commands *cmds = child->file->cmds; unsigned int i; for (i = 0; i < cmds->ncommand_lines; ++i) { free (cmds->command_lines[i]); cmds->command_lines[i] = 0; } free (cmds->command_lines); cmds->command_lines = 0; free (cmds->lines_flags); cmds->lines_flags = 0; cmds->ncommand_lines = 0; } #endif /* CONFIG_WITH_MEMORY_OPTIMIZATIONS */ free (child); } #ifdef POSIX extern sigset_t fatal_signal_set; #endif void block_sigs (void) { #ifdef POSIX (void) sigprocmask (SIG_BLOCK, &fatal_signal_set, (sigset_t *) 0); #else # ifdef HAVE_SIGSETMASK (void) sigblock (fatal_signal_mask); # endif #endif } #ifdef POSIX void unblock_sigs (void) { sigset_t empty; sigemptyset (&empty); sigprocmask (SIG_SETMASK, &empty, (sigset_t *) 0); } #endif #ifdef MAKE_JOBSERVER RETSIGTYPE job_noop (int sig UNUSED) { } /* Set the child handler action flags to FLAGS. */ static void set_child_handler_action_flags (int set_handler, int set_alarm) { struct sigaction sa; int rval = 0; #if defined(__EMX__) && !defined(__KLIBC__) /* bird */ /* The child handler must be turned off here. */ signal (SIGCHLD, SIG_DFL); #endif memset (&sa, '\0', sizeof sa); sa.sa_handler = child_handler; sa.sa_flags = set_handler ? 0 : SA_RESTART; #if defined SIGCHLD rval = sigaction (SIGCHLD, &sa, NULL); #endif #if defined SIGCLD && SIGCLD != SIGCHLD rval = sigaction (SIGCLD, &sa, NULL); #endif if (rval != 0) fprintf (stderr, "sigaction: %s (%d)\n", strerror (errno), errno); #if defined SIGALRM if (set_alarm) { /* If we're about to enter the read(), set an alarm to wake up in a second so we can check if the load has dropped and we can start more work. On the way out, turn off the alarm and set SIG_DFL. */ alarm (set_handler ? 1 : 0); sa.sa_handler = set_handler ? job_noop : SIG_DFL; sa.sa_flags = 0; sigaction (SIGALRM, &sa, NULL); } #endif } #endif /* Start a job to run the commands specified in CHILD. CHILD is updated to reflect the commands and ID of the child process. NOTE: On return fatal signals are blocked! The caller is responsible for calling `unblock_sigs', once the new child is safely on the chain so it can be cleaned up in the event of a fatal signal. */ static void start_job_command (struct child *child) { #if !defined(_AMIGA) && !defined(WINDOWS32) static int bad_stdin = -1; #endif char *p; /* Must be volatile to silence bogus GCC warning about longjmp/vfork. */ /*volatile*/ int flags; #ifdef VMS char *argv; #else char **argv; # if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32) && !defined(VMS) char ** volatile volatile_argv; int volatile volatile_flags; # endif #endif /* If we have a completely empty commandset, stop now. */ if (!child->command_ptr) goto next_command; #ifdef CONFIG_WITH_PRINT_TIME_SWITCH if (child->start_ts == -1) child->start_ts = nano_timestamp (); #endif /* Combine the flags parsed for the line itself with the flags specified globally for this target. */ flags = (child->file->command_flags | child->file->cmds->lines_flags[child->command_line - 1]); p = child->command_ptr; child->noerror = ((flags & COMMANDS_NOERROR) != 0); while (*p != '\0') { if (*p == '@') flags |= COMMANDS_SILENT; else if (*p == '+') flags |= COMMANDS_RECURSE; else if (*p == '-') child->noerror = 1; #ifdef CONFIG_WITH_COMMANDS_FUNC else if (*p == '%') flags |= COMMAND_GETTER_SKIP_IT; #endif else if (!isblank ((unsigned char)*p)) #ifndef CONFIG_WITH_KMK_BUILTIN break; #else /* CONFIG_WITH_KMK_BUILTIN */ { if ( !(flags & COMMANDS_KMK_BUILTIN) && !strncmp(p, "kmk_builtin_", sizeof("kmk_builtin_") - 1)) flags |= COMMANDS_KMK_BUILTIN; break; } #endif /* CONFIG_WITH_KMK_BUILTIN */ ++p; } /* Update the file's command flags with any new ones we found. We only keep the COMMANDS_RECURSE setting. Even this isn't 100% correct; we are now marking more commands recursive than should be in the case of multiline define/endef scripts where only one line is marked "+". In order to really fix this, we'll have to keep a lines_flags for every actual line, after expansion. */ child->file->cmds->lines_flags[child->command_line - 1] |= flags & COMMANDS_RECURSE; /* Figure out an argument list from this command line. */ { char *end = 0; #ifdef VMS argv = p; #else argv = construct_command_argv (p, &end, child->file, child->file->cmds->lines_flags[child->command_line - 1], &child->sh_batch_file); #endif if (end == NULL) child->command_ptr = NULL; else { *end++ = '\0'; child->command_ptr = end; } } /* If -q was given, say that updating `failed' if there was any text on the command line, or `succeeded' otherwise. The exit status of 1 tells the user that -q is saying `something to do'; the exit status for a random error is 2. */ if (argv != 0 && question_flag && !(flags & COMMANDS_RECURSE)) { #ifndef VMS free (argv[0]); free (argv); #endif child->file->update_status = 1; notice_finished_file (child->file); return; } if (touch_flag && !(flags & COMMANDS_RECURSE)) { /* Go on to the next command. It might be the recursive one. We construct ARGV only to find the end of the command line. */ #ifndef VMS if (argv) { free (argv[0]); free (argv); } #endif argv = 0; } if (argv == 0) { next_command: #ifdef __MSDOS__ execute_by_shell = 0; /* in case construct_command_argv sets it */ #endif /* This line has no commands. Go to the next. */ if (job_next_command (child)) start_job_command (child); else { /* No more commands. Make sure we're "running"; we might not be if (e.g.) all commands were skipped due to -n. */ set_command_state (child->file, cs_running); child->file->update_status = 0; notice_finished_file (child->file); } return; } /* Print out the command. If silent, we call `message' with null so it can log the working directory before the command's own error messages appear. */ #ifdef CONFIG_PRETTY_COMMAND_PRINTING if ( pretty_command_printing && (just_print_flag || (!(flags & COMMANDS_SILENT) && !silent_flag)) && argv[0][0] != '\0') { unsigned i; for (i = 0; argv[i]; i++) message (0, "%s'%s'%s", i ? "\t" : "> ", argv[i], argv[i + 1] ? " \\" : ""); } else #endif /* CONFIG_PRETTY_COMMAND_PRINTING */ message (0, (just_print_flag || (!(flags & COMMANDS_SILENT) && !silent_flag)) ? "%s" : (char *) 0, p); /* Tell update_goal_chain that a command has been started on behalf of this target. It is important that this happens here and not in reap_children (where we used to do it), because reap_children might be reaping children from a different target. We want this increment to guaranteedly indicate that a command was started for the dependency chain (i.e., update_file recursion chain) we are processing. */ ++commands_started; /* Optimize an empty command. People use this for timestamp rules, so avoid forking a useless shell. Do this after we increment commands_started so make still treats this special case as if it performed some action (makes a difference as to what messages are printed, etc. */ #if !defined(VMS) && !defined(_AMIGA) if ( #if defined __MSDOS__ || defined (__EMX__) unixy_shell /* the test is complicated and we already did it */ #else (argv[0] && is_bourne_compatible_shell(argv[0])) #endif && (argv[1] && argv[1][0] == '-' && ((argv[1][1] == 'c' && argv[1][2] == '\0') || (argv[1][1] == 'e' && argv[1][2] == 'c' && argv[1][3] == '\0'))) && (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0') && argv[3] == NULL) { free (argv[0]); free (argv); goto next_command; } #endif /* !VMS && !_AMIGA */ /* If -n was given, recurse to get the next line in the sequence. */ if (just_print_flag && !(flags & COMMANDS_RECURSE)) { #ifndef VMS free (argv[0]); free (argv); #endif goto next_command; } #ifdef CONFIG_WITH_KMK_BUILTIN /* If builtin command then pass it on to the builtin shell interpreter. */ if ((flags & COMMANDS_KMK_BUILTIN) && !just_print_flag) { int rc; char **argv_spawn = NULL; char **p2 = argv; while (*p2 && strncmp (*p2, "kmk_builtin_", sizeof("kmk_builtin_") - 1)) p2++; assert (*p2); set_command_state (child->file, cs_running); child->pid = 0; if (p2 != argv) rc = kmk_builtin_command (*p2, &argv_spawn, &child->pid); else { int argc = 1; while (argv[argc]) argc++; rc = kmk_builtin_command_parsed (argc, argv, &argv_spawn, &child->pid); } # ifndef VMS free (argv[0]); free ((char *) argv); # endif /* synchronous command execution? */ if (!rc && !argv_spawn) goto next_command; /* spawned a child? */ if (!rc && child->pid) { ++job_counter; return; } /* failure? */ if (rc) { child->pid = (pid_t)42424242; child->status = rc << 8; child->has_status = 1; unblock_sigs(); return; } /* conditional check == true; kicking off a child (not kmk_builtin_*). */ argv = argv_spawn; } #endif /* CONFIG_WITH_KMK_BUILTIN */ /* Flush the output streams so they won't have things written twice. */ fflush (stdout); fflush (stderr); #ifndef VMS #if !defined(WINDOWS32) && !defined(_AMIGA) && !defined(__MSDOS__) /* Set up a bad standard input that reads from a broken pipe. */ if (bad_stdin == -1) { /* Make a file descriptor that is the read end of a broken pipe. This will be used for some children's standard inputs. */ int pd[2]; if (pipe (pd) == 0) { /* Close the write side. */ (void) close (pd[1]); /* Save the read side. */ bad_stdin = pd[0]; /* Set the descriptor to close on exec, so it does not litter any child's descriptor table. When it is dup2'd onto descriptor 0, that descriptor will not close on exec. */ CLOSE_ON_EXEC (bad_stdin); } } #endif /* !WINDOWS32 && !_AMIGA && !__MSDOS__ */ /* Decide whether to give this child the `good' standard input (one that points to the terminal or whatever), or the `bad' one that points to the read side of a broken pipe. */ child->good_stdin = !good_stdin_used; if (child->good_stdin) good_stdin_used = 1; #endif /* !VMS */ child->deleted = 0; #ifndef _AMIGA /* Set up the environment for the child. */ if (child->environment == 0) child->environment = target_environment (child->file); #endif #if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32) #ifndef VMS /* start_waiting_job has set CHILD->remote if we can start a remote job. */ if (child->remote) { int is_remote, id, used_stdin; if (start_remote_job (argv, child->environment, child->good_stdin ? 0 : bad_stdin, &is_remote, &id, &used_stdin)) /* Don't give up; remote execution may fail for various reasons. If so, simply run the job locally. */ goto run_local; else { if (child->good_stdin && !used_stdin) { child->good_stdin = 0; good_stdin_used = 0; } child->remote = is_remote; child->pid = id; } } else #endif /* !VMS */ { /* Fork the child process. */ char **parent_environ; run_local: block_sigs (); child->remote = 0; #ifdef VMS if (!child_execute_job (argv, child)) { /* Fork failed! */ perror_with_name ("vfork", ""); goto error; } #else parent_environ = environ; # ifdef __EMX__ /* If we aren't running a recursive command and we have a jobserver pipe, close it before exec'ing. */ if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0) { CLOSE_ON_EXEC (job_fds[0]); CLOSE_ON_EXEC (job_fds[1]); } if (job_rfd >= 0) CLOSE_ON_EXEC (job_rfd); /* Never use fork()/exec() here! Use spawn() instead in exec_command() */ child->pid = child_execute_job (child->good_stdin ? 0 : bad_stdin, 1, argv, child->environment); if (child->pid < 0) { /* spawn failed! */ unblock_sigs (); perror_with_name ("spawn", ""); goto error; } /* undo CLOSE_ON_EXEC() after the child process has been started */ if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0) { fcntl (job_fds[0], F_SETFD, 0); fcntl (job_fds[1], F_SETFD, 0); } if (job_rfd >= 0) fcntl (job_rfd, F_SETFD, 0); #else /* !__EMX__ */ volatile_argv = argv; /* shut up gcc */ volatile_flags = flags; /* ditto */ child->pid = vfork (); environ = parent_environ; /* Restore value child may have clobbered. */ argv = volatile_argv; /* shut up gcc */ if (child->pid == 0) { /* We are the child side. */ unblock_sigs (); /* If we aren't running a recursive command and we have a jobserver pipe, close it before exec'ing. */ if (!(volatile_flags & COMMANDS_RECURSE) && job_fds[0] >= 0) { close (job_fds[0]); close (job_fds[1]); } if (job_rfd >= 0) close (job_rfd); #ifdef SET_STACK_SIZE /* Reset limits, if necessary. */ if (stack_limit.rlim_cur) setrlimit (RLIMIT_STACK, &stack_limit); #endif child_execute_job (child->good_stdin ? 0 : bad_stdin, 1, argv, child->environment); } else if (child->pid < 0) { /* Fork failed! */ unblock_sigs (); perror_with_name ("vfork", ""); goto error; } # endif /* !__EMX__ */ #endif /* !VMS */ } #else /* __MSDOS__ or Amiga or WINDOWS32 */ #ifdef __MSDOS__ { int proc_return; block_sigs (); dos_status = 0; /* We call `system' to do the job of the SHELL, since stock DOS shell is too dumb. Our `system' knows how to handle long command lines even if pipes/redirection is needed; it will only call COMMAND.COM when its internal commands are used. */ if (execute_by_shell) { char *cmdline = argv[0]; /* We don't have a way to pass environment to `system', so we need to save and restore ours, sigh... */ char **parent_environ = environ; environ = child->environment; /* If we have a *real* shell, tell `system' to call it to do everything for us. */ if (unixy_shell) { /* A *real* shell on MSDOS may not support long command lines the DJGPP way, so we must use `system'. */ cmdline = argv[2]; /* get past "shell -c" */ } dos_command_running = 1; proc_return = system (cmdline); environ = parent_environ; execute_by_shell = 0; /* for the next time */ } else { dos_command_running = 1; proc_return = spawnvpe (P_WAIT, argv[0], argv, child->environment); } /* Need to unblock signals before turning off dos_command_running, so that child's signals will be treated as such (see fatal_error_signal). */ unblock_sigs (); dos_command_running = 0; /* If the child got a signal, dos_status has its high 8 bits set, so be careful not to alter them. */ if (proc_return == -1) dos_status |= 0xff; else dos_status |= (proc_return & 0xff); ++dead_children; child->pid = dos_pid++; } #endif /* __MSDOS__ */ #ifdef _AMIGA amiga_status = MyExecute (argv); ++dead_children; child->pid = amiga_pid++; if (amiga_batch_file) { amiga_batch_file = 0; DeleteFile (amiga_bname); /* Ignore errors. */ } #endif /* Amiga */ #ifdef WINDOWS32 { HANDLE hPID; char* arg0; /* make UNC paths safe for CreateProcess -- backslash format */ arg0 = argv[0]; if (arg0 && arg0[0] == '/' && arg0[1] == '/') for ( ; arg0 && *arg0; arg0++) if (*arg0 == '/') *arg0 = '\\'; /* make sure CreateProcess() has Path it needs */ sync_Path_environment(); hPID = process_easy(argv, child->environment); if (hPID != INVALID_HANDLE_VALUE) child->pid = (pid_t) hPID; else { int i; unblock_sigs(); fprintf(stderr, _("process_easy() failed to launch process (e=%ld)\n"), process_last_err(hPID)); for (i = 0; argv[i]; i++) fprintf(stderr, "%s ", argv[i]); fprintf(stderr, _("\nCounted %d args in failed launch\n"), i); goto error; } } #endif /* WINDOWS32 */ #endif /* __MSDOS__ or Amiga or WINDOWS32 */ /* Bump the number of jobs started in this second. */ ++job_counter; /* We are the parent side. Set the state to say the commands are running and return. */ set_command_state (child->file, cs_running); /* Free the storage used by the child's argument list. */ #ifdef KMK /* leak */ cleanup_argv: #endif #ifndef VMS free (argv[0]); free (argv); #endif return; error: child->file->update_status = 2; notice_finished_file (child->file); #ifdef KMK /* fix leak */ goto cleanup_argv; #else return; #endif } /* Try to start a child running. Returns nonzero if the child was started (and maybe finished), or zero if the load was too high and the child was put on the `waiting_jobs' chain. */ static int start_waiting_job (struct child *c) { struct file *f = c->file; #ifdef DB_KMK DB (DB_KMK, (_("start_waiting_job %p (`%s') command_flags=%#x slots=%d/%d\n"), (void *)c, c->file->name, c->file->command_flags, job_slots_used, job_slots)); #endif /* If we can start a job remotely, we always want to, and don't care about the local load average. We record that the job should be started remotely in C->remote for start_job_command to test. */ c->remote = start_remote_job_p (1); #ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL if (c->file->command_flags & COMMANDS_NOTPARALLEL) { DB (DB_KMK, (_("not_parallel %d -> %d (file=%p `%s') [start_waiting_job]\n"), not_parallel, not_parallel + 1, (void *)c->file, c->file->name)); assert(not_parallel >= 0); ++not_parallel; } #endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ /* If we are running at least one job already and the load average is too high, make this one wait. */ if (!c->remote #ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL && ((job_slots_used > 0 && (not_parallel > 0 || load_too_high ())) #else && ((job_slots_used > 0 && load_too_high ()) #endif #ifdef WINDOWS32 || (process_used_slots () >= MAXIMUM_WAIT_OBJECTS) #endif )) { #ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL /* Put this child on the chain of children waiting for the load average to go down. */ set_command_state (f, cs_running); c->next = waiting_jobs; waiting_jobs = c; #else /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ /* Put this child on the chain of children waiting for the load average to go down. If not parallel, put it last. */ set_command_state (f, cs_running); c->next = waiting_jobs; if (c->next && (c->file->command_flags & COMMANDS_NOTPARALLEL)) { struct child *prev = waiting_jobs; while (prev->next) prev = prev->next; c->next = 0; prev->next = c; } else /* FIXME: insert after the last node with COMMANDS_NOTPARALLEL set */ waiting_jobs = c; DB (DB_KMK, (_("queued child %p (`%s')\n"), (void *)c, c->file->name)); #endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ return 0; } /* Start the first command; reap_children will run later command lines. */ start_job_command (c); switch (f->command_state) { case cs_running: c->next = children; DB (DB_JOBS, (_("Putting child %p (%s) PID %s%s on the chain.\n"), (void *)c, c->file->name, pid2str (c->pid), c->remote ? _(" (remote)") : "")); children = c; /* One more job slot is in use. */ ++job_slots_used; unblock_sigs (); break; case cs_not_started: /* All the command lines turned out to be empty. */ f->update_status = 0; /* FALLTHROUGH */ case cs_finished: notice_finished_file (f); free_child (c); break; default: assert (f->command_state == cs_finished); break; } return 1; } /* Create a `struct child' for FILE and start its commands running. */ void new_job (struct file *file) { struct commands *cmds = file->cmds; struct child *c; char **lines; unsigned int i; /* Let any previously decided-upon jobs that are waiting for the load to go down start before this new one. */ start_waiting_jobs (); /* Reap any children that might have finished recently. */ reap_children (0, 0); /* Chop the commands up into lines if they aren't already. */ chop_commands (cmds); #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS cmds->refs++; /* retain the chopped lines. */ #endif /* Expand the command lines and store the results in LINES. */ lines = xmalloc (cmds->ncommand_lines * sizeof (char *)); for (i = 0; i < cmds->ncommand_lines; ++i) { /* Collapse backslash-newline combinations that are inside variable or function references. These are left alone by the parser so that they will appear in the echoing of commands (where they look nice); and collapsed by construct_command_argv when it tokenizes. But letting them survive inside function invocations loses because we don't want the functions to see them as part of the text. */ char *in, *out, *ref; /* IN points to where in the line we are scanning. OUT points to where in the line we are writing. When we collapse a backslash-newline combination, IN gets ahead of OUT. */ in = out = cmds->command_lines[i]; while ((ref = strchr (in, '$')) != 0) { ++ref; /* Move past the $. */ if (out != in) /* Copy the text between the end of the last chunk we processed (where IN points) and the new chunk we are about to process (where REF points). */ memmove (out, in, ref - in); /* Move both pointers past the boring stuff. */ out += ref - in; in = ref; if (*ref == '(' || *ref == '{') { char openparen = *ref; char closeparen = openparen == '(' ? ')' : '}'; int count; char *p; *out++ = *in++; /* Copy OPENPAREN. */ /* IN now points past the opening paren or brace. Count parens or braces until it is matched. */ count = 0; while (*in != '\0') { if (*in == closeparen && --count < 0) break; else if (*in == '\\' && in[1] == '\n') { /* We have found a backslash-newline inside a variable or function reference. Eat it and any following whitespace. */ int quoted = 0; for (p = in - 1; p > ref && *p == '\\'; --p) quoted = !quoted; if (quoted) /* There were two or more backslashes, so this is not really a continuation line. We don't collapse the quoting backslashes here as is done in collapse_continuations, because the line will be collapsed again after expansion. */ *out++ = *in++; else { /* Skip the backslash, newline and any following whitespace. */ in = next_token (in + 2); /* Discard any preceding whitespace that has already been written to the output. */ while (out > ref && isblank ((unsigned char)out[-1])) --out; /* Replace it all with a single space. */ *out++ = ' '; } } else { if (*in == openparen) ++count; *out++ = *in++; } } } } /* There are no more references in this line to worry about. Copy the remaining uninteresting text to the output. */ if (out != in) memmove (out, in, strlen (in) + 1); /* Finally, expand the line. */ lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i], file); } /* Start the command sequence, record it in a new `struct child', and add that to the chain. */ c = xcalloc (sizeof (struct child)); c->file = file; c->command_lines = lines; c->sh_batch_file = NULL; #ifdef CONFIG_WITH_PRINT_TIME_SWITCH c->start_ts = -1; #endif /* Cache dontcare flag because file->dontcare can be changed once we return. Check dontcare inheritance mechanism for details. */ c->dontcare = file->dontcare; /* Fetch the first command line to be run. */ job_next_command (c); /* Wait for a job slot to be freed up. If we allow an infinite number don't bother; also job_slots will == 0 if we're using the jobserver. */ if (job_slots != 0) while (job_slots_used == job_slots) reap_children (1, 0); #ifdef MAKE_JOBSERVER /* If we are controlling multiple jobs make sure we have a token before starting the child. */ /* This can be inefficient. There's a decent chance that this job won't actually have to run any subprocesses: the command script may be empty or otherwise optimized away. It would be nice if we could defer obtaining a token until just before we need it, in start_job_command. To do that we'd need to keep track of whether we'd already obtained a token (since start_job_command is called for each line of the job, not just once). Also more thought needs to go into the entire algorithm; this is where the old parallel job code waits, so... */ else if (job_fds[0] >= 0) while (1) { char token; int got_token; int saved_errno; DB (DB_JOBS, ("Need a job token; we %shave children\n", children ? "" : "don't ")); /* If we don't already have a job started, use our "free" token. */ if (!jobserver_tokens) break; /* Read a token. As long as there's no token available we'll block. We enable interruptible system calls before the read(2) so that if we get a SIGCHLD while we're waiting, we'll return with EINTR and we can process the death(s) and return tokens to the free pool. Once we return from the read, we immediately reinstate restartable system calls. This allows us to not worry about checking for EINTR on all the other system calls in the program. There is one other twist: there is a span between the time reap_children() does its last check for dead children and the time the read(2) call is entered, below, where if a child dies we won't notice. This is extremely serious as it could cause us to deadlock, given the right set of events. To avoid this, we do the following: before we reap_children(), we dup(2) the read FD on the jobserver pipe. The read(2) call below uses that new FD. In the signal handler, we close that FD. That way, if a child dies during the section mentioned above, the read(2) will be invoked with an invalid FD and will return immediately with EBADF. */ /* Make sure we have a dup'd FD. */ if (job_rfd < 0) { DB (DB_JOBS, ("Duplicate the job FD\n")); job_rfd = dup (job_fds[0]); } /* Reap anything that's currently waiting. */ reap_children (0, 0); /* Kick off any jobs we have waiting for an opportunity that can run now (ie waiting for load). */ start_waiting_jobs (); /* If our "free" slot has become available, use it; we don't need an actual token. */ if (!jobserver_tokens) break; /* There must be at least one child already, or we have no business waiting for a token. */ if (!children) fatal (NILF, "INTERNAL: no children as we go to sleep on read\n"); /* Set interruptible system calls, and read() for a job token. */ set_child_handler_action_flags (1, waiting_jobs != NULL); got_token = read (job_rfd, &token, 1); saved_errno = errno; set_child_handler_action_flags (0, waiting_jobs != NULL); /* If we got one, we're done here. */ if (got_token == 1) { DB (DB_JOBS, (_("Obtained token for child %p (%s).\n"), (void *)c, c->file->name)); break; } /* If the error _wasn't_ expected (EINTR or EBADF), punt. Otherwise, go back and reap_children(), and try again. */ errno = saved_errno; if (errno != EINTR && errno != EBADF) pfatal_with_name (_("read jobs pipe")); if (errno == EBADF) DB (DB_JOBS, ("Read returned EBADF.\n")); } #endif ++jobserver_tokens; /* The job is now primed. Start it running. (This will notice if there is in fact no recipe.) */ if (cmds->fileinfo.filenm) DB (DB_BASIC, (_("Invoking recipe from %s:%lu to update target `%s'.\n"), cmds->fileinfo.filenm, cmds->fileinfo.lineno, c->file->name)); else DB (DB_BASIC, (_("Invoking builtin recipe to update target `%s'.\n"), c->file->name)); start_waiting_job (c); #ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL if (job_slots == 1 || not_parallel) /* Since there is only one job slot, make things run linearly. Wait for the child to die, setting the state to `cs_finished'. */ while (file->command_state == cs_running) reap_children (1, 0); #else /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ if (job_slots == 1 || not_parallel < 0) { /* Since there is only one job slot, make things run linearly. Wait for the child to die, setting the state to `cs_finished'. */ while (file->command_state == cs_running) reap_children (1, 0); } else if (not_parallel > 0) { /* wait for all live children to finish and then continue with the not-parallel child(s). FIXME: this loop could be better? */ while (file->command_state == cs_running && (children != 0 || shell_function_pid != 0) /* reap_child condition */ && not_parallel > 0) reap_children (1, 0); } #endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ return; } /* Move CHILD's pointers to the next command for it to execute. Returns nonzero if there is another command. */ static int job_next_command (struct child *child) { while (child->command_ptr == 0 || *child->command_ptr == '\0') { /* There are no more lines in the expansion of this line. */ if (child->command_line == child->file->cmds->ncommand_lines) { /* There are no more lines to be expanded. */ child->command_ptr = 0; return 0; } else /* Get the next line to run. */ child->command_ptr = child->command_lines[child->command_line++]; } return 1; } /* Determine if the load average on the system is too high to start a new job. The real system load average is only recomputed once a second. However, a very parallel make can easily start tens or even hundreds of jobs in a second, which brings the system to its knees for a while until that first batch of jobs clears out. To avoid this we use a weighted algorithm to try to account for jobs which have been started since the last second, and guess what the load average would be now if it were computed. This algorithm was provided by Thomas Riedl , who writes: ! calculate something load-oid and add to the observed sys.load, ! so that latter can catch up: ! - every job started increases jobctr; ! - every dying job decreases a positive jobctr; ! - the jobctr value gets zeroed every change of seconds, ! after its value*weight_b is stored into the 'backlog' value last_sec ! - weight_a times the sum of jobctr and last_sec gets ! added to the observed sys.load. ! ! The two weights have been tried out on 24 and 48 proc. Sun Solaris-9 ! machines, using a several-thousand-jobs-mix of cpp, cc, cxx and smallish ! sub-shelled commands (rm, echo, sed...) for tests. ! lowering the 'direct influence' factor weight_a (e.g. to 0.1) ! resulted in significant excession of the load limit, raising it ! (e.g. to 0.5) took bad to small, fast-executing jobs and didn't ! reach the limit in most test cases. ! ! lowering the 'history influence' weight_b (e.g. to 0.1) resulted in ! exceeding the limit for longer-running stuff (compile jobs in ! the .5 to 1.5 sec. range),raising it (e.g. to 0.5) overrepresented ! small jobs' effects. */ #define LOAD_WEIGHT_A 0.25 #define LOAD_WEIGHT_B 0.25 static int load_too_high (void) { #if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__) || defined(__HAIKU__) return 1; #else static double last_sec; static time_t last_now; double load, guess; time_t now; #ifdef WINDOWS32 /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS children */ if (process_used_slots () >= MAXIMUM_WAIT_OBJECTS) return 1; #endif if (max_load_average < 0) return 0; /* Find the real system load average. */ make_access (); if (getloadavg (&load, 1) != 1) { static int lossage = -1; /* Complain only once for the same error. */ if (lossage == -1 || errno != lossage) { if (errno == 0) /* An errno value of zero means getloadavg is just unsupported. */ error (NILF, _("cannot enforce load limits on this operating system")); else perror_with_name (_("cannot enforce load limit: "), "getloadavg"); } lossage = errno; load = 0; } user_access (); /* If we're in a new second zero the counter and correct the backlog value. Only keep the backlog for one extra second; after that it's 0. */ now = time (NULL); if (last_now < now) { if (last_now == now - 1) last_sec = LOAD_WEIGHT_B * job_counter; else last_sec = 0.0; job_counter = 0; last_now = now; } /* Try to guess what the load would be right now. */ guess = load + (LOAD_WEIGHT_A * (job_counter + last_sec)); DB (DB_JOBS, ("Estimated system load = %f (actual = %f) (max requested = %f)\n", guess, load, max_load_average)); return guess >= max_load_average; #endif } /* Start jobs that are waiting for the load to be lower. */ void start_waiting_jobs (void) { struct child *job; if (waiting_jobs == 0) return; do { /* Check for recently deceased descendants. */ reap_children (0, 0); /* Take a job off the waiting list. */ job = waiting_jobs; waiting_jobs = job->next; #ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL /* If it's a not-parallel job, we've already counted it once when it was queued in start_waiting_job, so decrement before sending it to start_waiting_job again. */ if (job->file->command_flags & COMMANDS_NOTPARALLEL) { DB (DB_KMK, (_("not_parallel %d -> %d (file=%p `%s') [start_waiting_jobs]\n"), not_parallel, not_parallel - 1, (void *) job->file, job->file->name)); assert(not_parallel > 0); --not_parallel; } #endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ /* Try to start that job. We break out of the loop as soon as start_waiting_job puts one back on the waiting list. */ } while (start_waiting_job (job) && waiting_jobs != 0); return; } #ifndef WINDOWS32 /* EMX: Start a child process. This function returns the new pid. */ # if defined __EMX__ int child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp) { int pid; /* stdin_fd == 0 means: nothing to do for stdin; stdout_fd == 1 means: nothing to do for stdout */ int save_stdin = (stdin_fd != 0) ? dup (0) : 0; int save_stdout = (stdout_fd != 1) ? dup (1): 1; /* < 0 only if dup() failed */ if (save_stdin < 0) fatal (NILF, _("no more file handles: could not duplicate stdin\n")); if (save_stdout < 0) fatal (NILF, _("no more file handles: could not duplicate stdout\n")); /* Close unnecessary file handles for the child. */ if (save_stdin != 0) CLOSE_ON_EXEC (save_stdin); if (save_stdout != 1) CLOSE_ON_EXEC (save_stdout); /* Connect the pipes to the child process. */ if (stdin_fd != 0) (void) dup2 (stdin_fd, 0); if (stdout_fd != 1) (void) dup2 (stdout_fd, 1); /* stdin_fd and stdout_fd must be closed on exit because we are still in the parent process */ if (stdin_fd != 0) CLOSE_ON_EXEC (stdin_fd); if (stdout_fd != 1) CLOSE_ON_EXEC (stdout_fd); /* Run the command. */ pid = exec_command (argv, envp); /* Restore stdout/stdin of the parent and close temporary FDs. */ if (stdin_fd != 0) { if (dup2 (save_stdin, 0) != 0) fatal (NILF, _("Could not restore stdin\n")); else close (save_stdin); } if (stdout_fd != 1) { if (dup2 (save_stdout, 1) != 1) fatal (NILF, _("Could not restore stdout\n")); else close (save_stdout); } return pid; } #elif !defined (_AMIGA) && !defined (__MSDOS__) && !defined (VMS) /* UNIX: Replace the current process with one executing the command in ARGV. STDIN_FD and STDOUT_FD are used as the process's stdin and stdout; ENVP is the environment of the new program. This function does not return. */ void child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp) { if (stdin_fd != 0) (void) dup2 (stdin_fd, 0); if (stdout_fd != 1) (void) dup2 (stdout_fd, 1); if (stdin_fd != 0) (void) close (stdin_fd); if (stdout_fd != 1) (void) close (stdout_fd); /* Run the command. */ exec_command (argv, envp); } #endif /* !AMIGA && !__MSDOS__ && !VMS */ #endif /* !WINDOWS32 */ #ifndef _AMIGA /* Replace the current process with one running the command in ARGV, with environment ENVP. This function does not return. */ /* EMX: This function returns the pid of the child process. */ # ifdef __EMX__ int # else void # endif exec_command (char **argv, char **envp) { #ifdef VMS /* to work around a problem with signals and execve: ignore them */ #ifdef SIGCHLD signal (SIGCHLD,SIG_IGN); #endif /* Run the program. */ execve (argv[0], argv, envp); perror_with_name ("execve: ", argv[0]); _exit (EXIT_FAILURE); #else #ifdef WINDOWS32 HANDLE hPID; HANDLE hWaitPID; int err = 0; int exit_code = EXIT_FAILURE; /* make sure CreateProcess() has Path it needs */ sync_Path_environment(); /* launch command */ hPID = process_easy(argv, envp); /* make sure launch ok */ if (hPID == INVALID_HANDLE_VALUE) { int i; fprintf(stderr, _("process_easy() failed to launch process (e=%ld)\n"), process_last_err(hPID)); for (i = 0; argv[i]; i++) fprintf(stderr, "%s ", argv[i]); fprintf(stderr, _("\nCounted %d args in failed launch\n"), i); exit(EXIT_FAILURE); } /* wait and reap last child */ hWaitPID = process_wait_for_any(); while (hWaitPID) { /* was an error found on this process? */ err = process_last_err(hWaitPID); /* get exit data */ exit_code = process_exit_code(hWaitPID); if (err) fprintf(stderr, "make (e=%d, rc=%d): %s", err, exit_code, map_windows32_error_to_string(err)); /* cleanup process */ process_cleanup(hWaitPID); /* expect to find only last pid, warn about other pids reaped */ if (hWaitPID == hPID) break; else { char *pidstr = xstrdup (pid2str ((pid_t)hWaitPID)); fprintf(stderr, _("make reaped child pid %s, still waiting for pid %s\n"), pidstr, pid2str ((pid_t)hPID)); free (pidstr); } } /* return child's exit code as our exit code */ exit(exit_code); #else /* !WINDOWS32 */ # ifdef __EMX__ int pid; # endif /* Be the user, permanently. */ child_access (); # ifdef __EMX__ /* Run the program. */ pid = spawnvpe (P_NOWAIT, argv[0], argv, envp); if (pid >= 0) return pid; /* the file might have a strange shell extension */ if (errno == ENOENT) errno = ENOEXEC; # else /* Run the program. */ environ = envp; execvp (argv[0], argv); # endif /* !__EMX__ */ switch (errno) { case ENOENT: error (NILF, _("%s: Command not found"), argv[0]); break; case ENOEXEC: { /* The file is not executable. Try it as a shell script. */ extern char *getenv (); char *shell; char **new_argv; int argc; int i=1; # ifdef __EMX__ /* Do not use $SHELL from the environment */ struct variable *p = lookup_variable ("SHELL", 5); if (p) shell = p->value; else shell = 0; # else shell = getenv ("SHELL"); # endif if (shell == 0) shell = default_shell; argc = 1; while (argv[argc] != 0) ++argc; # ifdef __EMX__ if (!unixy_shell) ++argc; # endif new_argv = alloca ((1 + argc + 1) * sizeof (char *)); new_argv[0] = shell; # ifdef __EMX__ if (!unixy_shell) { new_argv[1] = "/c"; ++i; --argc; } # endif new_argv[i] = argv[0]; while (argc > 0) { new_argv[i + argc] = argv[argc]; --argc; } # ifdef __EMX__ pid = spawnvpe (P_NOWAIT, shell, new_argv, envp); if (pid >= 0) break; # else execvp (shell, new_argv); # endif if (errno == ENOENT) error (NILF, _("%s: Shell program not found"), shell); else perror_with_name ("execvp: ", shell); break; } # ifdef __EMX__ case EINVAL: /* this nasty error was driving me nuts :-( */ error (NILF, _("spawnvpe: environment space might be exhausted")); /* FALLTHROUGH */ # endif default: perror_with_name ("execvp: ", argv[0]); break; } # ifdef __EMX__ return pid; # else _exit (127); # endif #endif /* !WINDOWS32 */ #endif /* !VMS */ } #else /* On Amiga */ void exec_command (char **argv) { MyExecute (argv); } void clean_tmp (void) { DeleteFile (amiga_bname); } #endif /* On Amiga */ #ifndef VMS /* Figure out the argument list necessary to run LINE as a command. Try to avoid using a shell. This routine handles only ' quoting, and " quoting when no backslash, $ or ` characters are seen in the quotes. Starting quotes may be escaped with a backslash. If any of the characters in sh_chars[] is seen, or any of the builtin commands listed in sh_cmds[] is the first word of a line, the shell is used. If RESTP is not NULL, *RESTP is set to point to the first newline in LINE. If *RESTP is NULL, newlines will be ignored. SHELL is the shell to use, or nil to use the default shell. IFS is the value of $IFS, or nil (meaning the default). FLAGS is the value of lines_flags for this command line. It is used in the WINDOWS32 port to check whether + or $(MAKE) were found in this command line, in which case the effect of just_print_flag is overridden. */ static char ** construct_command_argv_internal (char *line, char **restp, char *shell, char *shellflags, char *ifs, int flags, char **batch_filename_ptr) { #ifdef __MSDOS__ /* MSDOS supports both the stock DOS shell and ports of Unixy shells. We call `system' for anything that requires ``slow'' processing, because DOS shells are too dumb. When $SHELL points to a real (unix-style) shell, `system' just calls it to do everything. When $SHELL points to a DOS shell, `system' does most of the work internally, calling the shell only for its internal commands. However, it looks on the $PATH first, so you can e.g. have an external command named `mkdir'. Since we call `system', certain characters and commands below are actually not specific to COMMAND.COM, but to the DJGPP implementation of `system'. In particular: The shell wildcard characters are in DOS_CHARS because they will not be expanded if we call the child via `spawnXX'. The `;' is in DOS_CHARS, because our `system' knows how to run multiple commands on a single line. DOS_CHARS also include characters special to 4DOS/NDOS, so we won't have to tell one from another and have one more set of commands and special characters. */ static char sh_chars_dos[] = "*?[];|<>%^&()"; static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls", "copy", "ctty", "date", "del", "dir", "echo", "erase", "exit", "for", "goto", "if", "md", "mkdir", "path", "pause", "prompt", "rd", "rmdir", "rem", "ren", "rename", "set", "shift", "time", "type", "ver", "verify", "vol", ":", 0 }; static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^"; static char *sh_cmds_sh[] = { "cd", "echo", "eval", "exec", "exit", "login", "logout", "set", "umask", "wait", "while", "for", "case", "if", ":", ".", "break", "continue", "export", "read", "readonly", "shift", "times", "trap", "switch", "unset", "ulimit", 0 }; char *sh_chars; char **sh_cmds; #elif defined (__EMX__) static char sh_chars_dos[] = "*?[];|<>%^&()"; static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls", "copy", "ctty", "date", "del", "dir", "echo", "erase", "exit", "for", "goto", "if", "md", "mkdir", "path", "pause", "prompt", "rd", "rmdir", "rem", "ren", "rename", "set", "shift", "time", "type", "ver", "verify", "vol", ":", 0 }; static char sh_chars_os2[] = "*?[];|<>%^()\"'&"; static char *sh_cmds_os2[] = { "call", "cd", "chcp", "chdir", "cls", "copy", "date", "del", "detach", "dir", "echo", "endlocal", "erase", "exit", "for", "goto", "if", "keys", "md", "mkdir", "move", "path", "pause", "prompt", "rd", "rem", "ren", "rename", "rmdir", "set", "setlocal", "shift", "start", "time", "type", "ver", "verify", "vol", ":", 0 }; static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^~'"; static char *sh_cmds_sh[] = { "echo", "cd", "eval", "exec", "exit", "login", "logout", "set", "umask", "wait", "while", "for", "case", "if", ":", ".", "break", "continue", "export", "read", "readonly", "shift", "times", "trap", "switch", "unset", 0 }; char *sh_chars; char **sh_cmds; #elif defined (_AMIGA) static char sh_chars[] = "#;\"|<>()?*$`"; static char *sh_cmds[] = { "cd", "eval", "if", "delete", "echo", "copy", "rename", "set", "setenv", "date", "makedir", "skip", "else", "endif", "path", "prompt", "unset", "unsetenv", "version", 0 }; #elif defined (WINDOWS32) static char sh_chars_dos[] = "\"|&<>"; static char *sh_cmds_dos[] = { "assoc", "break", "call", "cd", "chcp", "chdir", "cls", "color", "copy", "ctty", "date", "del", "dir", "echo", "echo.", "endlocal", "erase", "exit", "for", "ftype", "goto", "if", "if", "md", "mkdir", "path", "pause", "prompt", "rd", "rem", "ren", "rename", "rmdir", "set", "setlocal", "shift", "time", "title", "type", "ver", "verify", "vol", ":", 0 }; static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^"; static char *sh_cmds_sh[] = { "cd", "eval", "exec", "exit", "login", "logout", "set", "umask", "wait", "while", "for", "case", "if", ":", ".", "break", "continue", "export", "read", "readonly", "shift", "times", "trap", "switch", "test", #ifdef BATCH_MODE_ONLY_SHELL "echo", #endif 0 }; char* sh_chars; char** sh_cmds; #elif defined(__riscos__) static char sh_chars[] = ""; static char *sh_cmds[] = { 0 }; #else /* must be UNIX-ish */ static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^~!"; /* kmk: +_sh */ static char *sh_cmds_sh[] = { ".", ":", "break", "case", "cd", "continue", /* kmk: +_sh */ "eval", "exec", "exit", "export", "for", "if", "login", "logout", "read", "readonly", "set", "shift", "switch", "test", "times", "trap", "ulimit", "umask", "unset", "wait", "while", 0 }; # ifdef HAVE_DOS_PATHS /* This is required if the MSYS/Cygwin ports (which do not define WINDOWS32) are compiled with HAVE_DOS_PATHS defined, which uses sh_chars_sh[] directly (see below). */ static char *sh_chars_sh = sh_chars; # endif /* HAVE_DOS_PATHS */ char* sh_chars = sh_chars_sh; /* kmk: +_sh */ char** sh_cmds = sh_cmds_sh; /* kmk: +_sh */ #endif #ifdef KMK static char sh_chars_kash[] = "#;*?[]&|<>(){}$`^~!"; /* note: no \" - good idea? */ static char *sh_cmds_kash[] = { ".", ":", "break", "case", "cd", "continue", "echo", "eval", "exec", "exit", "export", "for", "if", "login", "logout", "read", "readonly", "set", "shift", "switch", "test", "times", "trap", "umask", "wait", "while", 0 }; int is_kmk_shell = 0; #endif int i; char *p; char *ap; char *end; int instring, word_has_equals, seen_nonequals, last_argument_was_empty; char **new_argv = 0; char *argstr = 0; #ifdef WINDOWS32 int slow_flag = 0; if (!unixy_shell) { sh_cmds = sh_cmds_dos; sh_chars = sh_chars_dos; } else { sh_cmds = sh_cmds_sh; sh_chars = sh_chars_sh; } #endif /* WINDOWS32 */ if (restp != NULL) *restp = NULL; /* Make sure not to bother processing an empty line. */ while (isblank ((unsigned char)*line)) ++line; if (*line == '\0') return 0; /* See if it is safe to parse commands internally. */ #ifdef KMK /* kmk_ash and kmk_kash are both fine, kmk_ash is the default btw. */ if (shell == 0) { is_kmk_shell = 1; shell = (char *)get_default_kbuild_shell (); } else if (!strcmp (shell, get_default_kbuild_shell())) is_kmk_shell = 1; else { const char *psz = strstr (shell, "/kmk_ash"); if (psz) psz += sizeof ("/kmk_ash") - 1; else { psz = strstr (shell, "/kmk_kash"); if (psz) psz += sizeof ("/kmk_kash") - 1; } # if defined (__OS2__) || defined (_WIN32) || defined (WINDOWS32) is_kmk_shell = psz && (*psz == '\0' || !stricmp (psz, ".exe")); # else is_kmk_shell = psz && *psz == '\0'; # endif } if (is_kmk_shell) { sh_chars = sh_chars_kash; sh_cmds = sh_cmds_kash; } #else /* !KMK */ if (shell == 0) shell = default_shell; #endif /* !KMK */ #ifdef WINDOWS32 else if (strcmp (shell, default_shell)) { char *s1 = _fullpath (NULL, shell, 0); char *s2 = _fullpath (NULL, default_shell, 0); slow_flag = strcmp ((s1 ? s1 : ""), (s2 ? s2 : "")); if (s1) free (s1); if (s2) free (s2); } if (slow_flag) goto slow; #else /* not WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) else if (strcasecmp (shell, default_shell)) { extern int _is_unixy_shell (const char *_path); DB (DB_BASIC, (_("$SHELL changed (was `%s', now `%s')\n"), default_shell, shell)); unixy_shell = _is_unixy_shell (shell); /* we must allocate a copy of shell: construct_command_argv() will free * shell after this function returns. */ default_shell = xstrdup (shell); } if (unixy_shell) { sh_chars = sh_chars_sh; sh_cmds = sh_cmds_sh; } else { sh_chars = sh_chars_dos; sh_cmds = sh_cmds_dos; # ifdef __EMX__ if (_osmode == OS2_MODE) { sh_chars = sh_chars_os2; sh_cmds = sh_cmds_os2; } # endif } #else /* !__MSDOS__ */ else if (strcmp (shell, default_shell)) goto slow; #endif /* !__MSDOS__ && !__EMX__ */ #endif /* not WINDOWS32 */ if (ifs != 0) for (ap = ifs; *ap != '\0'; ++ap) if (*ap != ' ' && *ap != '\t' && *ap != '\n') goto slow; if (shellflags != 0) if (shellflags[0] != '-' || ((shellflags[1] != 'c' || shellflags[2] != '\0') && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0'))) goto slow; i = strlen (line) + 1; /* More than 1 arg per character is impossible. */ new_argv = xmalloc (i * sizeof (char *)); /* All the args can fit in a buffer as big as LINE is. */ ap = new_argv[0] = argstr = xmalloc (i); end = ap + i; /* I is how many complete arguments have been found. */ i = 0; instring = word_has_equals = seen_nonequals = last_argument_was_empty = 0; for (p = line; *p != '\0'; ++p) { assert (ap <= end); if (instring) { /* Inside a string, just copy any char except a closing quote or a backslash-newline combination. */ if (*p == instring) { instring = 0; if (ap == new_argv[0] || *(ap-1) == '\0') last_argument_was_empty = 1; } else if (*p == '\\' && p[1] == '\n') { /* Backslash-newline is handled differently depending on what kind of string we're in: inside single-quoted strings you keep them; in double-quoted strings they disappear. For DOS/Windows/OS2, if we don't have a POSIX shell, we keep the pre-POSIX behavior of removing the backslash-newline. */ if (instring == '"' #if defined (__MSDOS__) || defined (__EMX__) || defined (WINDOWS32) || !unixy_shell #endif ) ++p; else { *(ap++) = *(p++); *(ap++) = *p; } } else if (*p == '\n' && restp != NULL) { /* End of the command line. */ *restp = p; goto end_of_line; } /* Backslash, $, and ` are special inside double quotes. If we see any of those, punt. But on MSDOS, if we use COMMAND.COM, double and single quotes have the same effect. */ else if (instring == '"' && strchr ("\\$`", *p) != 0 && unixy_shell) goto slow; else *ap++ = *p; } else if (strchr (sh_chars, *p) != 0) #ifdef KMK { /* Tilde is only special if at the start of a path spec, i.e. don't get excited when we by 8.3 files on windows. */ if ( *p == '~' && p > line && !isspace (p[-1]) && p[-1] != '=' && p[-1] != ':' && p[-1] != '"' && p[-1] != '\'') *ap++ = *p; else /* Not inside a string, but it's a special char. */ goto slow; } #else /* !KMK */ /* Not inside a string, but it's a special char. */ goto slow; #endif /* !KMK */ else if (one_shell && *p == '\n') /* In .ONESHELL mode \n is a separator like ; or && */ goto slow; #ifdef __MSDOS__ else if (*p == '.' && p[1] == '.' && p[2] == '.' && p[3] != '.') /* `...' is a wildcard in DJGPP. */ goto slow; #endif else /* Not a special char. */ switch (*p) { case '=': /* Equals is a special character in leading words before the first word with no equals sign in it. This is not the case with sh -k, but we never get here when using nonstandard shell flags. */ if (! seen_nonequals && unixy_shell) goto slow; word_has_equals = 1; *ap++ = '='; break; case '\\': /* Backslash-newline has special case handling, ref POSIX. We're in the fastpath, so emulate what the shell would do. */ if (p[1] == '\n') { /* Throw out the backslash and newline. */ ++p; /* If there's nothing in this argument yet, skip any whitespace before the start of the next word. */ if (ap == new_argv[i]) p = next_token (p + 1) - 1; } else if (p[1] != '\0') { #ifdef HAVE_DOS_PATHS /* Only remove backslashes before characters special to Unixy shells. All other backslashes are copied verbatim, since they are probably DOS-style directory separators. This still leaves a small window for problems, but at least it should work for the vast majority of naive users. */ #ifdef __MSDOS__ /* A dot is only special as part of the "..." wildcard. */ if (strneq (p + 1, ".\\.\\.", 5)) { *ap++ = '.'; *ap++ = '.'; p += 4; } else #endif if (p[1] != '\\' && p[1] != '\'' && !isspace ((unsigned char)p[1]) # ifdef KMK && strchr (sh_chars, p[1]) == 0 && (p[1] != '"' || !unixy_shell)) # else && strchr (sh_chars_sh, p[1]) == 0) # endif /* back up one notch, to copy the backslash */ --p; #endif /* HAVE_DOS_PATHS */ /* Copy and skip the following char. */ *ap++ = *++p; } break; case '\'': case '"': instring = *p; break; case '\n': if (restp != NULL) { /* End of the command line. */ *restp = p; goto end_of_line; } else /* Newlines are not special. */ *ap++ = '\n'; break; case ' ': case '\t': /* We have the end of an argument. Terminate the text of the argument. */ *ap++ = '\0'; new_argv[++i] = ap; last_argument_was_empty = 0; /* Update SEEN_NONEQUALS, which tells us if every word heretofore has contained an `='. */ seen_nonequals |= ! word_has_equals; if (word_has_equals && ! seen_nonequals) /* An `=' in a word before the first word without one is magical. */ goto slow; word_has_equals = 0; /* Prepare for the next word. */ /* If this argument is the command name, see if it is a built-in shell command. If so, have the shell handle it. */ if (i == 1) { register int j; for (j = 0; sh_cmds[j] != 0; ++j) { if (streq (sh_cmds[j], new_argv[0])) goto slow; # ifdef __EMX__ /* Non-Unix shells are case insensitive. */ if (!unixy_shell && strcasecmp (sh_cmds[j], new_argv[0]) == 0) goto slow; # endif } } /* Ignore multiple whitespace chars. */ p = next_token (p) - 1; break; default: *ap++ = *p; break; } } end_of_line: if (instring) /* Let the shell deal with an unterminated quote. */ goto slow; /* Terminate the last argument and the argument list. */ *ap = '\0'; if (new_argv[i][0] != '\0' || last_argument_was_empty) ++i; new_argv[i] = 0; if (i == 1) { register int j; for (j = 0; sh_cmds[j] != 0; ++j) if (streq (sh_cmds[j], new_argv[0])) goto slow; } if (new_argv[0] == 0) { /* Line was empty. */ free (argstr); free (new_argv); return 0; } return new_argv; slow:; /* We must use the shell. */ if (new_argv != 0) { /* Free the old argument list we were working on. */ free (argstr); free (new_argv); } #ifdef __MSDOS__ execute_by_shell = 1; /* actually, call `system' if shell isn't unixy */ #endif #ifdef _AMIGA { char *ptr; char *buffer; char *dptr; buffer = xmalloc (strlen (line)+1); ptr = line; for (dptr=buffer; *ptr; ) { if (*ptr == '\\' && ptr[1] == '\n') ptr += 2; else if (*ptr == '@') /* Kludge: multiline commands */ { ptr += 2; *dptr++ = '\n'; } else *dptr++ = *ptr++; } *dptr = 0; new_argv = xmalloc (2 * sizeof (char *)); new_argv[0] = buffer; new_argv[1] = 0; } #else /* Not Amiga */ #ifdef WINDOWS32 /* * Not eating this whitespace caused things like * * sh -c "\n" * * which gave the shell fits. I think we have to eat * whitespace here, but this code should be considered * suspicious if things start failing.... */ /* Make sure not to bother processing an empty line. */ while (isspace ((unsigned char)*line)) ++line; if (*line == '\0') return 0; #endif /* WINDOWS32 */ { /* SHELL may be a multi-word command. Construct a command line "$(SHELL) $(.SHELLFLAGS) LINE", with all special chars in LINE escaped. Then recurse, expanding this command line to get the final argument list. */ unsigned int shell_len = strlen (shell); unsigned int line_len = strlen (line); unsigned int sflags_len = strlen (shellflags); char *command_ptr = NULL; /* used for batch_mode_shell mode */ char *new_line; # ifdef __EMX__ /* is this necessary? */ if (!unixy_shell) shellflags[0] = '/'; /* "/c" */ # endif /* In .ONESHELL mode we are allowed to throw the entire current recipe string at a single shell and trust that the user has configured the shell and shell flags, and formatted the string, appropriately. */ if (one_shell) { /* If the shell is Bourne compatible, we must remove and ignore interior special chars [@+-] because they're meaningless to the shell itself. If, however, we're in .ONESHELL mode and have changed SHELL to something non-standard, we should leave those alone because they could be part of the script. In this case we must also leave in place any leading [@+-] for the same reason. */ /* Remove and ignore interior prefix chars [@+-] because they're meaningless given a single shell. */ #if defined __MSDOS__ || defined (__EMX__) if (unixy_shell) /* the test is complicated and we already did it */ #else if (is_bourne_compatible_shell(shell)) #endif { const char *f = line; char *t = line; /* Copy the recipe, removing and ignoring interior prefix chars [@+-]: they're meaningless in .ONESHELL mode. */ while (f[0] != '\0') { int esc = 0; /* This is the start of a new recipe line. Skip whitespace and prefix characters. */ while (isblank (*f) || *f == '-' || *f == '@' || *f == '+') ++f; /* Copy until we get to the next logical recipe line. */ while (*f != '\0') { *(t++) = *(f++); if (f[-1] == '\\') esc = !esc; else { /* On unescaped newline, we're done with this line. */ if (f[-1] == '\n' && ! esc) break; /* Something else: reset the escape sequence. */ esc = 0; } } } *t = '\0'; } new_argv = xmalloc (4 * sizeof (char *)); new_argv[0] = xstrdup(shell); new_argv[1] = xstrdup(shellflags); new_argv[2] = line; new_argv[3] = NULL; return new_argv; } new_line = alloca (shell_len + 1 + sflags_len + 1 + (line_len*2) + 1); ap = new_line; memcpy (ap, shell, shell_len); ap += shell_len; *(ap++) = ' '; memcpy (ap, shellflags, sflags_len); ap += sflags_len; *(ap++) = ' '; command_ptr = ap; for (p = line; *p != '\0'; ++p) { if (restp != NULL && *p == '\n') { *restp = p; break; } else if (*p == '\\' && p[1] == '\n') { /* POSIX says we keep the backslash-newline. If we don't have a POSIX shell on DOS/Windows/OS2, mimic the pre-POSIX behavior and remove the backslash/newline. */ #if defined (__MSDOS__) || defined (__EMX__) || defined (WINDOWS32) # define PRESERVE_BSNL unixy_shell #else # define PRESERVE_BSNL 1 #endif if (PRESERVE_BSNL) { *(ap++) = '\\'; /* Only non-batch execution needs another backslash, because it will be passed through a recursive invocation of this function. */ if (!batch_mode_shell) *(ap++) = '\\'; *(ap++) = '\n'; } ++p; continue; } /* DOS shells don't know about backslash-escaping. */ if (unixy_shell && !batch_mode_shell && (*p == '\\' || *p == '\'' || *p == '"' || isspace ((unsigned char)*p) || strchr (sh_chars, *p) != 0)) *ap++ = '\\'; #ifdef __MSDOS__ else if (unixy_shell && strneq (p, "...", 3)) { /* The case of `...' wildcard again. */ strcpy (ap, "\\.\\.\\"); ap += 5; p += 2; } #endif *ap++ = *p; } if (ap == new_line + shell_len + sflags_len + 2) /* Line was empty. */ return 0; *ap = '\0'; #ifdef WINDOWS32 /* Some shells do not work well when invoked as 'sh -c xxx' to run a command line (e.g. Cygnus GNUWIN32 sh.exe on WIN32 systems). In these cases, run commands via a script file. */ if (just_print_flag && !(flags & COMMANDS_RECURSE)) { /* Need to allocate new_argv, although it's unused, because start_job_command will want to free it and its 0'th element. */ new_argv = xmalloc(2 * sizeof (char *)); new_argv[0] = xstrdup (""); new_argv[1] = NULL; } else if ((no_default_sh_exe || batch_mode_shell) && batch_filename_ptr) { int temp_fd; FILE* batch = NULL; int id = GetCurrentProcessId(); PATH_VAR(fbuf); /* create a file name */ sprintf(fbuf, "make%d", id); *batch_filename_ptr = create_batch_file (fbuf, unixy_shell, &temp_fd); DB (DB_JOBS, (_("Creating temporary batch file %s\n"), *batch_filename_ptr)); /* Create a FILE object for the batch file, and write to it the commands to be executed. Put the batch file in TEXT mode. */ _setmode (temp_fd, _O_TEXT); batch = _fdopen (temp_fd, "wt"); if (!unixy_shell) fputs ("@echo off\n", batch); fputs (command_ptr, batch); fputc ('\n', batch); fclose (batch); DB (DB_JOBS, (_("Batch file contents:%s\n\t%s\n"), !unixy_shell ? "\n\t@echo off" : "", command_ptr)); /* create argv */ new_argv = xmalloc(3 * sizeof (char *)); if (unixy_shell) { new_argv[0] = xstrdup (shell); new_argv[1] = *batch_filename_ptr; /* only argv[0] gets freed later */ } else { new_argv[0] = xstrdup (*batch_filename_ptr); new_argv[1] = NULL; } new_argv[2] = NULL; } else #endif /* WINDOWS32 */ if (unixy_shell) new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0, flags, 0); #ifdef __EMX__ else if (!unixy_shell) { /* new_line is local, must not be freed therefore We use line here instead of new_line because we run the shell manually. */ size_t line_len = strlen (line); char *p = new_line; char *q = new_line; memcpy (new_line, line, line_len + 1); /* Replace all backslash-newline combination and also following tabs. Important: stop at the first '\n' because that's what the loop above did. The next line starting at restp[0] will be executed during the next call of this function. */ while (*q != '\0' && *q != '\n') { if (q[0] == '\\' && q[1] == '\n') q += 2; /* remove '\\' and '\n' */ else *p++ = *q++; } *p = '\0'; # ifndef NO_CMD_DEFAULT if (strnicmp (new_line, "echo", 4) == 0 && (new_line[4] == ' ' || new_line[4] == '\t')) { /* the builtin echo command: handle it separately */ size_t echo_len = line_len - 5; char *echo_line = new_line + 5; /* special case: echo 'x="y"' cmd works this way: a string is printed as is, i.e., no quotes are removed. But autoconf uses a command like echo 'x="y"' to determine whether make works. autoconf expects the output x="y" so we will do exactly that. Note: if we do not allow cmd to be the default shell we do not need this kind of voodoo */ if (echo_line[0] == '\'' && echo_line[echo_len - 1] == '\'' && strncmp (echo_line + 1, "ac_maketemp=", strlen ("ac_maketemp=")) == 0) { /* remove the enclosing quotes */ memmove (echo_line, echo_line + 1, echo_len - 2); echo_line[echo_len - 2] = '\0'; } } # endif { /* Let the shell decide what to do. Put the command line into the 2nd command line argument and hope for the best ;-) */ size_t sh_len = strlen (shell); /* exactly 3 arguments + NULL */ new_argv = xmalloc (4 * sizeof (char *)); /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times the trailing '\0' */ new_argv[0] = xmalloc (sh_len + line_len + 5); memcpy (new_argv[0], shell, sh_len + 1); new_argv[1] = new_argv[0] + sh_len + 1; memcpy (new_argv[1], "/c", 3); new_argv[2] = new_argv[1] + 3; memcpy (new_argv[2], new_line, line_len + 1); new_argv[3] = NULL; } } #elif defined(__MSDOS__) else { /* With MSDOS shells, we must construct the command line here instead of recursively calling ourselves, because we cannot backslash-escape the special characters (see above). */ new_argv = xmalloc (sizeof (char *)); line_len = strlen (new_line) - shell_len - sflags_len - 2; new_argv[0] = xmalloc (line_len + 1); strncpy (new_argv[0], new_line + shell_len + sflags_len + 2, line_len); new_argv[0][line_len] = '\0'; } #else else fatal (NILF, _("%s (line %d) Bad shell context (!unixy && !batch_mode_shell)\n"), __FILE__, __LINE__); #endif } #endif /* ! AMIGA */ return new_argv; } #endif /* !VMS */ /* Figure out the argument list necessary to run LINE as a command. Try to avoid using a shell. This routine handles only ' quoting, and " quoting when no backslash, $ or ` characters are seen in the quotes. Starting quotes may be escaped with a backslash. If any of the characters in sh_chars[] is seen, or any of the builtin commands listed in sh_cmds[] is the first word of a line, the shell is used. If RESTP is not NULL, *RESTP is set to point to the first newline in LINE. If *RESTP is NULL, newlines will be ignored. FILE is the target whose commands these are. It is used for variable expansion for $(SHELL) and $(IFS). */ char ** construct_command_argv (char *line, char **restp, struct file *file, int cmd_flags, char **batch_filename_ptr) { char *shell, *ifs, *shellflags; char **argv; #ifdef VMS char *cptr; int argc; argc = 0; cptr = line; for (;;) { while ((*cptr != 0) && (isspace ((unsigned char)*cptr))) cptr++; if (*cptr == 0) break; while ((*cptr != 0) && (!isspace((unsigned char)*cptr))) cptr++; argc++; } argv = xmalloc (argc * sizeof (char *)); if (argv == 0) abort (); cptr = line; argc = 0; for (;;) { while ((*cptr != 0) && (isspace ((unsigned char)*cptr))) cptr++; if (*cptr == 0) break; DB (DB_JOBS, ("argv[%d] = [%s]\n", argc, cptr)); argv[argc++] = cptr; while ((*cptr != 0) && (!isspace((unsigned char)*cptr))) cptr++; if (*cptr != 0) *cptr++ = 0; } #else { /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; shell = allocated_variable_expand_for_file ("$(SHELL)", file); #ifdef WINDOWS32 /* * Convert to forward slashes so that construct_command_argv_internal() * is not confused. */ if (shell) { char *p = w32ify (shell, 0); strcpy (shell, p); } #endif #ifdef __EMX__ { static const char *unixroot = NULL; static const char *last_shell = ""; static int init = 0; if (init == 0) { unixroot = getenv ("UNIXROOT"); /* unixroot must be NULL or not empty */ if (unixroot && unixroot[0] == '\0') unixroot = NULL; init = 1; } /* if we have an unixroot drive and if shell is not default_shell (which means it's either cmd.exe or the test has already been performed) and if shell is an absolute path without drive letter, try whether it exists e.g.: if "/bin/sh" does not exist use "$UNIXROOT/bin/sh" instead. */ if (unixroot && shell && strcmp (shell, last_shell) != 0 && (shell[0] == '/' || shell[0] == '\\')) { /* trying a new shell, check whether it exists */ size_t size = strlen (shell); char *buf = xmalloc (size + 7); memcpy (buf, shell, size); memcpy (buf + size, ".exe", 5); /* including the trailing '\0' */ if (access (shell, F_OK) != 0 && access (buf, F_OK) != 0) { /* try the same for the unixroot drive */ memmove (buf + 2, buf, size + 5); buf[0] = unixroot[0]; buf[1] = unixroot[1]; if (access (buf, F_OK) == 0) /* we have found a shell! */ /* free(shell); */ shell = buf; else free (buf); } else free (buf); } } #endif /* __EMX__ */ shellflags = allocated_variable_expand_for_file ("$(.SHELLFLAGS)", file); ifs = allocated_variable_expand_for_file ("$(IFS)", file); warn_undefined_variables_flag = save; } #ifdef CONFIG_WITH_KMK_BUILTIN /* If it's a kmk_builtin command, make sure we're treated like a unix shell and and don't get batch files. */ if ( ( !unixy_shell || batch_mode_shell # ifdef WINDOWS32 || no_default_sh_exe # endif ) && line && !strncmp(line, "kmk_builtin_", sizeof("kmk_builtin_") - 1)) { int saved_batch_mode_shell = batch_mode_shell; int saved_unixy_shell = unixy_shell; # ifdef WINDOWS32 int saved_no_default_sh_exe = no_default_sh_exe; no_default_sh_exe = 0; # endif unixy_shell = 1; batch_mode_shell = 0; argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs, cmd_flags, batch_filename_ptr); batch_mode_shell = saved_batch_mode_shell; unixy_shell = saved_unixy_shell; # ifdef WINDOWS32 no_default_sh_exe = saved_no_default_sh_exe; # endif } else #endif /* CONFIG_WITH_KMK_BUILTIN */ argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs, cmd_flags, batch_filename_ptr); free (shell); free (shellflags); free (ifs); #endif /* !VMS */ return argv; } #if !defined(HAVE_DUP2) && !defined(_AMIGA) int dup2 (int old, int new) { int fd; (void) close (new); fd = dup (old); if (fd != new) { (void) close (fd); errno = EMFILE; return -1; } return fd; } #endif /* !HAVE_DUP2 && !_AMIGA */ #ifdef CONFIG_WITH_PRINT_TIME_SWITCH /* Prints the time elapsed while executing the commands for the given job. */ void print_job_time (struct child *c) { if ( !handling_fatal_signal && print_time_min != -1 && c->start_ts != -1) { big_int elapsed = nano_timestamp () - c->start_ts; if (elapsed >= print_time_min * BIG_INT_C(1000000000)) { char buf[64]; int len = format_elapsed_nano (buf, sizeof (buf), elapsed); if (len > print_time_width) print_time_width = len; message (1, _("%*s - %s"), print_time_width, buf, c ->file->name); } } } #endif /* On VMS systems, include special VMS functions. */ #ifdef VMS #include "vmsjobs.c" #endif kbuild-2695/src/kmk/kmkbuiltin.c0000644000000000000000000001742512247157307015340 0ustar rootroot/* $Id: kmkbuiltin.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * kMk Builtin command execution. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include #include #include #ifdef _MSC_VER # include #endif #include "kmkbuiltin/err.h" #include "kmkbuiltin.h" #ifndef _MSC_VER extern char **environ; #endif int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pPidSpawned) { int argc; char **argv; int rc; /* * Check and skip the prefix. */ if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1)) { printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd); return 1; } /* * Parse arguments. */ argc = 0; argv = NULL; while (*pszCmd) { const char *pszEnd; const char *pszNext; int fEscaped = 0; size_t cch; /* * Find start and end of the current command. */ if (*pszCmd == '"' || *pszCmd == '\'') { pszEnd = pszCmd; for (;;) { pszEnd = strchr(pszEnd + 1, *pszCmd); if (!pszEnd) { printf("kmk_builtin: Unbalanced quote in argument %d: %s\n", argc + 1, pszCmd); while (argc--) free(argv[argc]); free(argv); return 1; } /* two quotes -> escaped quote. */ if (pszEnd[0] != pszEnd[1]) break; fEscaped = 1; } pszNext = pszEnd + 1; pszCmd++; } else { pszEnd = pszCmd; while (!isspace(*pszEnd) && *pszEnd) pszEnd++; pszNext = pszEnd; } /* * Make argument. */ if (!(argc % 16)) { void *pv = realloc(argv, sizeof(char *) * (argc + 17)); if (!pv) { printf("kmk_builtin: out of memory. argc=%d\n", argc); break; } argv = (char **)pv; } cch = pszEnd - pszCmd; argv[argc] = malloc(cch + 1); if (!argv[argc]) { printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, (int)(pszEnd - pszCmd + 1)); break; } memcpy(argv[argc], pszCmd, cch); argv[argc][cch] = '\0'; /* unescape quotes? */ if (fEscaped) { char ch = pszCmd[-1]; char *pszW = argv[argc]; char *pszR = argv[argc]; while (*pszR) { if (*pszR == ch) pszR++; *pszW++ = *pszR++; } *pszW = '\0'; } /* commit it */ argv[++argc] = NULL; /* * Next */ pszCmd = pszNext; if (isspace(*pszCmd) && *pszCmd) pszCmd++; } /* * Execute the command if parsing was successful. */ if (!*pszCmd) rc = kmk_builtin_command_parsed(argc, argv, ppapszArgvToSpawn, pPidSpawned); else rc = 1; /* clean up and return. */ while (argc--) free(argv[argc]); free(argv); return rc; } int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn, pid_t *pPidSpawned) { const char *pszCmd = argv[0]; int iumask; int rc; /* * Check and skip the prefix. */ if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1)) { printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd); return 1; } pszCmd += sizeof("kmk_builtin_") - 1; /* * String switch on the command. */ iumask = umask(0); umask(iumask); if (!strcmp(pszCmd, "append")) rc = kmk_builtin_append(argc, argv, environ); else if (!strcmp(pszCmd, "printf")) rc = kmk_builtin_printf(argc, argv, environ); else if (!strcmp(pszCmd, "echo")) rc = kmk_builtin_echo(argc, argv, environ); else if (!strcmp(pszCmd, "install")) rc = kmk_builtin_install(argc, argv, environ); else if (!strcmp(pszCmd, "kDepIDB")) rc = kmk_builtin_kDepIDB(argc, argv, environ); else if (!strcmp(pszCmd, "mkdir")) rc = kmk_builtin_mkdir(argc, argv, environ); else if (!strcmp(pszCmd, "mv")) rc = kmk_builtin_mv(argc, argv, environ); /*else if (!strcmp(pszCmd, "redirect")) rc = kmk_builtin_redirect(argc, argv, environ, pPidSpawned);*/ else if (!strcmp(pszCmd, "rm")) rc = kmk_builtin_rm(argc, argv, environ); else if (!strcmp(pszCmd, "rmdir")) rc = kmk_builtin_rmdir(argc, argv, environ); else if (!strcmp(pszCmd, "test")) rc = kmk_builtin_test(argc, argv, environ, ppapszArgvToSpawn); /* rarely used commands: */ else if (!strcmp(pszCmd, "kDepObj")) rc = kmk_builtin_kDepObj(argc, argv, environ); else if (!strcmp(pszCmd, "chmod")) rc = kmk_builtin_chmod(argc, argv, environ); else if (!strcmp(pszCmd, "cp")) rc = kmk_builtin_cp(argc, argv, environ); else if (!strcmp(pszCmd, "expr")) rc = kmk_builtin_expr(argc, argv, environ); else if (!strcmp(pszCmd, "ln")) rc = kmk_builtin_ln(argc, argv, environ); else if (!strcmp(pszCmd, "md5sum")) rc = kmk_builtin_md5sum(argc, argv, environ); else if (!strcmp(pszCmd, "cmp")) rc = kmk_builtin_cmp(argc, argv, environ); else if (!strcmp(pszCmd, "cat")) rc = kmk_builtin_cat(argc, argv, environ); else if (!strcmp(pszCmd, "sleep")) rc = kmk_builtin_sleep(argc, argv, environ); else { printf("kmk_builtin: Unknown command '%s'!\n", pszCmd); return 1; } /* * Cleanup. */ g_progname = "kmk"; /* paranoia, make sure it's not pointing at a freed argv[0]. */ umask(iumask); /* * If we've executed a conditional test or something that wishes to execute * some child process, check if the child is a kmk_builtin thing. We recurse * here, both because I'm lazy and because it's easier to debug a problem then * (the call stack shows what's been going on). */ if ( !rc && *ppapszArgvToSpawn && !strncmp(**ppapszArgvToSpawn, "kmk_builtin_", sizeof("kmk_builtin_") - 1)) { char **argv_new = *ppapszArgvToSpawn; int argc_new = 1; while (argv_new[argc_new]) argc_new++; assert(argv_new[0] != argv[0]); assert(!*pPidSpawned); *ppapszArgvToSpawn = NULL; rc = kmk_builtin_command_parsed(argc_new, argv_new, ppapszArgvToSpawn, pPidSpawned); free(argv_new[0]); free(argv_new); } return rc; } kbuild-2695/src/kmk/po/0000755000000000000000000000000012247157306013427 5ustar rootrootkbuild-2695/src/kmk/po/POTFILES.in0000644000000000000000000000204412247157306015204 0ustar rootroot# List of source files containing translatable strings. # Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, # 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . ar.c arscan.c commands.c dir.c expand.c file.c function.c getopt.c hash.c implicit.c job.c kbuild.c main.c misc.c read.c remake.c remote-cstms.c rule.c signame.c strcache.c variable.c variable.h vmsfunctions.c vmsjobs.c vpath.c kbuild-2695/src/kmk/po/LINGUAS0000644000000000000000000000027212247157306014455 0ustar rootroot# Set of available languages: 24 languages be da de es fi fr ga gl he hr id it ja ko lt nl pl pt_BR ru sv tr uk vi zh_CN # Can't seem to get en@quot and en@boldquot to build properly? kbuild-2695/src/kmk/po/Makevars0000644000000000000000000000506712247157306015133 0ustar rootroot# This is a -*-Makefile-*- # Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free # Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation; either version 3 of the License, or (at your option) # any later version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Free Software Foundation, Inc. # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = bug-make@gnu.org # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = kbuild-2695/src/kmk/po/ChangeLog0000644000000000000000000000467512247157306015215 0ustar rootroot2009-09-16 Paul Smith * LINGUAS: Added new translation for Italian (it). 2008-05-17 Paul Smith * LINGUAS: Added new translation for Lithuanian (lt). 2007-08-15 Paul Smith * LINGUAS: The Kinyarwanda (rw) translation has disappeared from the translation site, so remove it. 2006-01-28 Paul D. Smith * LINGUAS: Added new translation for Vietnamese (vi). 2005-07-14 Paul D. Smith * LINGUAS: Added new translation for Indonesian (id). 2005-05-09 Paul D. Smith * POTFILES.in: Add new file vmsjobs.c. 2005-04-06 Paul D. Smith * LINGUAS: Added a new translation for Kinywarwanda (rw). 2005-02-09 Paul D. Smith * LINGUAS: Added a new translation for Irish (ga). 2005-02-01 Paul D. Smith * LINGUAS: Added a new translation for Finnish (fi). 2003-10-18 Paul D. Smith * LINGUAS: Added a new translation for Belarusian (be). 2002-12-19 Paul D. Smith * LINGUAS: Added a new translation for Ukrainian (uk). 2002-10-05 Paul D. Smith * POTFILES.in: Add variable.h as it has a translatable string. 2002-08-08 Paul D. Smith * LINGUAS: Add a new translation for Chinese (simplified) (zh_CN). 2002-08-02 Paul D. Smith * LINGUAS: Add a new translation for Swedish (sv). 2002-04-21 Paul D. Smith * LINGUAS, hr.po: Added new translation: Croatian. * da.po, de.po, es.po, fr.po, gl.po, he.po, ja.po, ko.po, nl.po, pl.po, pt_BR.po, ru.po, tr.po: Moved from i18n to here. * .cvsignore: Moved from i18n to here. * POTFILES.in, LINGUAS, Makevars: Created. Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/getopt1.c0000644000000000000000000001047712247157306014551 0ustar rootroot/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt.h" #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (int argc, char **argv) { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ kbuild-2695/src/kmk/gettext.h0000644000000000000000000000504612247157307014654 0ustar rootroot/* Convenience header for conditional use of GNU . Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ #if ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include #else /* Disabled NLS. The casts to 'const char *' serve the purpose of producing warnings for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ # define gettext(Msgid) ((const char *) (Msgid)) # define dgettext(Domainname, Msgid) ((const char *) (Msgid)) # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dngettext(Domainname, Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define textdomain(Domainname) ((const char *) (Domainname)) # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) #endif /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. The argument, String, should be a literal string. Concatenated strings and other string expressions won't work. The macro's expansion is not parenthesized, so that it is suitable as initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String #endif /* _LIBGETTEXT_H */ kbuild-2695/src/kmk/testcase-libpath.kmk0000644000000000000000000000245512247157306016757 0ustar rootroot all: @kmk_builtin_echo "" @kmk_builtin_echo "Warning: This testcase requires manual inspection and is intended for OS/2 only." @kmk_builtin_echo "" @kmk_builtin_echo "getting:" @kmk_builtin_echo "libpath BEGINLIBPATH: $(libpath BEGINLIBPATH)" @kmk_builtin_echo "libpath LIBPATH: $(libpath LIBPATH)" @kmk_builtin_echo "libpath ENDLIBPATH: $(libpath ENDLIBPATH)" @kmk_builtin_echo "libpath LIBPATHSTRICT: $(libpath LIBPATHSTRICT)" @kmk_builtin_echo "setting:" @kmk_builtin_echo "libpath ENDLIBPATH,\foobar: $(libpath ENDLIBPATH,\foobar) -> $(libpath ENDLIBPATH)" @kmk_builtin_echo "libpath ENDLIBPATH,: $(libpath ENDLIBPATH,) -> $(libpath ENDLIBPATH)" @kmk_builtin_echo "libpath BEGINLIBPATH,\qwerty: $(libpath BEGINLIBPATH,\qwerty) -> $(libpath BEGINLIBPATH)" @kmk_builtin_echo "libpath BEGINLIBPATH,: $(libpath BEGINLIBPATH,) -> $(libpath BEGINLIBPATH)" @kmk_builtin_echo "libpath LIBPATHSTRICT,T: $(libpath LIBPATHSTRICT,T) -> $(libpath LIBPATHSTRICT)" @kmk_builtin_echo "libpath LIBPATHSTRICT,qwerty: $(libpath LIBPATHSTRICT,qwerty) -> $(libpath LIBPATHSTRICT)" @kmk_builtin_echo "libpath LIBPATHSTRICT,F: $(libpath LIBPATHSTRICT,F) -> $(libpath LIBPATHSTRICT)" @kmk_builtin_echo "libpath LIBPATHSTRICT,: $(libpath LIBPATHSTRICT,) -> $(libpath LIBPATHSTRICT)" kbuild-2695/src/kmk/hash.c0000644000000000000000000003250612247157307014107 0ustar rootroot/* hash.c -- hash table maintenance Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc. Written by Greg McGary GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "hash.h" #ifdef CONFIG_WITH_STRCACHE2 # include #endif #define CALLOC(t, n) ((t *) calloc (sizeof (t), (n))) #define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n))) #define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n))) #define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n))) static void hash_rehash __P((struct hash_table* ht)); static unsigned long round_up_2 __P((unsigned long rough)); /* Implement double hashing with open addressing. The table size is always a power of two. The secondary (`increment') hash function is forced to return an odd-value, in order to be relatively prime to the table size. This guarantees that the increment can potentially hit every slot in the table during collision resolution. */ void *hash_deleted_item = &hash_deleted_item; /* Force the table size to be a power of two, possibly rounding up the given size. */ void hash_init (struct hash_table *ht, unsigned long size, hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp) { ht->ht_size = round_up_2 (size); ht->ht_empty_slots = ht->ht_size; ht->ht_vec = (void**) CALLOC (struct token *, ht->ht_size); if (ht->ht_vec == 0) { fprintf (stderr, _("can't allocate %lu bytes for hash table: memory exhausted"), ht->ht_size * (unsigned long) sizeof (struct token *)); exit (1); } ht->ht_capacity = ht->ht_size - (ht->ht_size / 16); /* 93.75% loading factor */ ht->ht_fill = 0; ht->ht_collisions = 0; ht->ht_lookups = 0; ht->ht_rehashes = 0; ht->ht_hash_1 = hash_1; ht->ht_hash_2 = hash_2; ht->ht_compare = hash_cmp; #ifdef CONFIG_WITH_STRCACHE2 ht->ht_strcache = 0; ht->ht_off_string = 0; #endif } #ifdef CONFIG_WITH_STRCACHE2 /* Same as hash_init, except that no callbacks are needed since all keys - including the ones being searched for - are from a string cache. This means that any give string will only have one pointer value and that the hash and length can be retrived very cheaply, thus permitting some nice optimizations. STRCACHE points to the string cache, while OFF_STRING gives the offset of the string pointer in the item structures the hash table entries points to. */ void hash_init_strcached (struct hash_table *ht, unsigned long size, struct strcache2 *strcache, unsigned int off_string) { hash_init (ht, size, 0, 0, 0); ht->ht_strcache = strcache; ht->ht_off_string = off_string; } #endif /* CONFIG_WITH_STRCACHE2 */ /* Load an array of items into `ht'. */ void hash_load (struct hash_table *ht, void *item_table, unsigned long cardinality, unsigned long size) { char *items = (char *) item_table; #ifndef CONFIG_WITH_STRCACHE2 while (cardinality--) { hash_insert (ht, items); items += size; } #else /* CONFIG_WITH_STRCACHE2 */ if (ht->ht_strcache) while (cardinality--) { hash_insert_strcached (ht, items); items += size; } else while (cardinality--) { hash_insert (ht, items); items += size; } #endif /* CONFIG_WITH_STRCACHE2 */ } /* Returns the address of the table slot matching `key'. If `key' is not found, return the address of an empty slot suitable for inserting `key'. The caller is responsible for incrementing ht_fill on insertion. */ void ** hash_find_slot (struct hash_table *ht, const void *key) { void **slot; void **deleted_slot = 0; unsigned int hash_2 = 0; unsigned int hash_1 = (*ht->ht_hash_1) (key); #ifdef CONFIG_WITH_STRCACHE2 assert (ht->ht_strcache == 0); #endif MAKE_STATS (ht->ht_lookups++); MAKE_STATS_3 (make_stats_ht_lookups++); for (;;) { hash_1 &= (ht->ht_size - 1); slot = &ht->ht_vec[hash_1]; if (*slot == 0) return (deleted_slot ? deleted_slot : slot); if (*slot == hash_deleted_item) { if (deleted_slot == 0) deleted_slot = slot; } else { if (key == *slot) return slot; if ((*ht->ht_compare) (key, *slot) == 0) return slot; MAKE_STATS (ht->ht_collisions++); MAKE_STATS_3 (make_stats_ht_collisions++); } if (!hash_2) hash_2 = (*ht->ht_hash_2) (key) | 1; hash_1 += hash_2; } } #ifdef CONFIG_WITH_STRCACHE2 /* hash_find_slot version for tables created with hash_init_strcached. */ void ** hash_find_slot_strcached (struct hash_table *ht, const void *key) { void **slot; void **deleted_slot = 0; const char *str1 = *(const char **)((const char *)key + ht->ht_off_string); const char *str2; unsigned int hash_1 = strcache2_calc_ptr_hash (ht->ht_strcache, str1); unsigned int hash_2; #ifdef CONFIG_WITH_STRCACHE2 assert (ht->ht_strcache != 0); #endif MAKE_STATS (ht->ht_lookups++); MAKE_STATS_3 (make_stats_ht_lookups++); /* first iteration unrolled. */ hash_1 &= (ht->ht_size - 1); slot = &ht->ht_vec[hash_1]; if (*slot == 0) return slot; if (*slot != hash_deleted_item) { str2 = *(const char **)((const char *)(*slot) + ht->ht_off_string); if (str1 == str2) return slot; MAKE_STATS (ht->ht_collisions++); MAKE_STATS_3 (make_stats_ht_collisions++); } else deleted_slot = slot; /* the rest of the loop. */ hash_2 = strcache2_get_hash (ht->ht_strcache, str1) | 1; hash_1 += hash_2; for (;;) { hash_1 &= (ht->ht_size - 1); slot = &ht->ht_vec[hash_1]; if (*slot == 0) return (deleted_slot ? deleted_slot : slot); if (*slot == hash_deleted_item) { if (deleted_slot == 0) deleted_slot = slot; } else { str2 = *(const char **)((const char *)(*slot) + ht->ht_off_string); if (str1 == str2) return slot; MAKE_STATS (ht->ht_collisions++); MAKE_STATS_3 (make_stats_ht_collisions++); } hash_1 += hash_2; } } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_find_item (struct hash_table *ht, const void *key) { void **slot = hash_find_slot (ht, key); return ((HASH_VACANT (*slot)) ? 0 : *slot); } #ifdef CONFIG_WITH_STRCACHE2 void * hash_find_item_strcached (struct hash_table *ht, const void *key) { void **slot = hash_find_slot_strcached (ht, key); return ((HASH_VACANT (*slot)) ? 0 : *slot); } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_insert (struct hash_table *ht, const void *item) { void **slot = hash_find_slot (ht, item); const void *old_item = *slot; hash_insert_at (ht, item, slot); return (void *)((HASH_VACANT (old_item)) ? 0 : old_item); } #ifdef CONFIG_WITH_STRCACHE2 void * hash_insert_strcached (struct hash_table *ht, const void *item) { void **slot = hash_find_slot_strcached (ht, item); const void *old_item = slot ? *slot : 0; hash_insert_at (ht, item, slot); return (void *)((HASH_VACANT (old_item)) ? 0 : old_item); } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_insert_at (struct hash_table *ht, const void *item, const void *slot) { const void *old_item = *(void **) slot; if (HASH_VACANT (old_item)) { ht->ht_fill++; if (old_item == 0) ht->ht_empty_slots--; old_item = item; } *(void const **) slot = item; if (ht->ht_empty_slots < ht->ht_size - ht->ht_capacity) { hash_rehash (ht); #ifdef CONFIG_WITH_STRCACHE2 if (ht->ht_strcache) return (void *)hash_find_slot_strcached (ht, item); #endif /* CONFIG_WITH_STRCACHE2 */ return (void *) hash_find_slot (ht, item); } else return (void *) slot; } void * hash_delete (struct hash_table *ht, const void *item) { void **slot = hash_find_slot (ht, item); return hash_delete_at (ht, slot); } #ifdef CONFIG_WITH_STRCACHE2 void * hash_delete_strcached (struct hash_table *ht, const void *item) { void **slot = hash_find_slot_strcached (ht, item); return hash_delete_at (ht, slot); } #endif /* CONFIG_WITH_STRCACHE2 */ void * hash_delete_at (struct hash_table *ht, const void *slot) { void *item = *(void **) slot; if (!HASH_VACANT (item)) { *(void const **) slot = hash_deleted_item; ht->ht_fill--; return item; } else return 0; } void hash_free_items (struct hash_table *ht) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) { void *item = *vec; if (!HASH_VACANT (item)) free (item); *vec = 0; } ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } #ifdef CONFIG_WITH_ALLOC_CACHES void hash_free_items_cached (struct hash_table *ht, struct alloccache *cache) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) { void *item = *vec; if (!HASH_VACANT (item)) alloccache_free (cache, item); *vec = 0; } ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } #endif /* CONFIG_WITH_ALLOC_CACHES */ void hash_delete_items (struct hash_table *ht) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) *vec = 0; ht->ht_fill = 0; ht->ht_collisions = 0; ht->ht_lookups = 0; ht->ht_rehashes = 0; ht->ht_empty_slots = ht->ht_size; } void hash_free (struct hash_table *ht, int free_items) { if (free_items) hash_free_items (ht); else { ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } free (ht->ht_vec); ht->ht_vec = 0; ht->ht_capacity = 0; } #ifdef CONFIG_WITH_ALLOC_CACHES void hash_free_cached (struct hash_table *ht, int free_items, struct alloccache *cache) { if (free_items) hash_free_items_cached (ht, cache); else { ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } free (ht->ht_vec); ht->ht_vec = 0; ht->ht_capacity = 0; } #endif /* CONFIG_WITH_ALLOC_CACHES */ void hash_map (struct hash_table *ht, hash_map_func_t map) { void **slot; void **end = &ht->ht_vec[ht->ht_size]; for (slot = ht->ht_vec; slot < end; slot++) { if (!HASH_VACANT (*slot)) (*map) (*slot); } } void hash_map_arg (struct hash_table *ht, hash_map_arg_func_t map, void *arg) { void **slot; void **end = &ht->ht_vec[ht->ht_size]; for (slot = ht->ht_vec; slot < end; slot++) { if (!HASH_VACANT (*slot)) (*map) (*slot, arg); } } /* Double the size of the hash table in the event of overflow... */ static void hash_rehash (struct hash_table *ht) { unsigned long old_ht_size = ht->ht_size; void **old_vec = ht->ht_vec; void **ovp; if (ht->ht_fill >= ht->ht_capacity) { ht->ht_size *= 2; ht->ht_capacity = ht->ht_size - (ht->ht_size >> 4); } ht->ht_rehashes++; ht->ht_vec = (void **) CALLOC (struct token *, ht->ht_size); #ifndef CONFIG_WITH_STRCACHE2 for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++) { if (! HASH_VACANT (*ovp)) { void **slot = hash_find_slot (ht, *ovp); *slot = *ovp; } } #else /* CONFIG_WITH_STRCACHE2 */ if (ht->ht_strcache) for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++) { if (! HASH_VACANT (*ovp)) { void **slot = hash_find_slot_strcached (ht, *ovp); *slot = *ovp; } } else for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++) { if (! HASH_VACANT (*ovp)) { void **slot = hash_find_slot (ht, *ovp); *slot = *ovp; } } #endif /* CONFIG_WITH_STRCACHE2 */ ht->ht_empty_slots = ht->ht_size - ht->ht_fill; free (old_vec); } void hash_print_stats (struct hash_table *ht, FILE *out_FILE) { /* GKM FIXME: honor NO_FLOAT */ fprintf (out_FILE, _("Load=%ld/%ld=%.0f%%, "), ht->ht_fill, ht->ht_size, 100.0 * (double) ht->ht_fill / (double) ht->ht_size); fprintf (out_FILE, _("Rehash=%d, "), ht->ht_rehashes); MAKE_STATS( fprintf (out_FILE, _("Collisions=%ld/%ld=%.0f%%"), ht->ht_collisions, ht->ht_lookups, (ht->ht_lookups ? (100.0 * (double) ht->ht_collisions / (double) ht->ht_lookups) : 0)); ); } /* Dump all items into a NULL-terminated vector. Use the user-supplied vector, or malloc one. */ void ** hash_dump (struct hash_table *ht, void **vector_0, qsort_cmp_t compare) { void **vector; void **slot; void **end = &ht->ht_vec[ht->ht_size]; if (vector_0 == 0) vector_0 = MALLOC (void *, ht->ht_fill + 1); vector = vector_0; for (slot = ht->ht_vec; slot < end; slot++) if (!HASH_VACANT (*slot)) *vector++ = *slot; *vector = 0; if (compare) qsort (vector_0, ht->ht_fill, sizeof (void *), compare); return vector_0; } /* Round a given number up to the nearest power of 2. */ static unsigned long round_up_2 (unsigned long n) { n |= (n >> 1); n |= (n >> 2); n |= (n >> 4); n |= (n >> 8); n |= (n >> 16); #if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295 /* We only need this on systems where unsigned long is >32 bits. */ n |= (n >> 32); #endif return n + 1; } kbuild-2695/src/kmk/subproc.bat0000644000000000000000000000170712247157306015163 0ustar rootroot@echo off rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, rem 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . cd w32\subproc set MAKE=%2 set MAKEFILE=%1 if x%2 == x set MAKE=nmake %MAKE% /f %MAKEFILE% cd ..\.. kbuild-2695/src/kmk/implicit.c0000644000000000000000000010213312247157306014767 0ustar rootroot/* Implicit rule searching for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "filedef.h" #include "rule.h" #include "dep.h" #include "debug.h" #include "variable.h" #include "job.h" /* struct child, used inside commands.h */ #include "commands.h" /* set_file_variables */ static int pattern_search (struct file *file, int archive, unsigned int depth, unsigned int recursions); /* For a FILE which has no commands specified, try to figure out some from the implicit pattern rules. Returns 1 if a suitable implicit rule was found, after modifying FILE to contain the appropriate commands and deps, or returns 0 if no implicit rule was found. */ int try_implicit_rule (struct file *file, unsigned int depth) { DBF (DB_IMPLICIT, _("Looking for an implicit rule for `%s'.\n")); /* The order of these searches was previously reversed. My logic now is that since the non-archive search uses more information in the target (the archive search omits the archive name), it is more specific and should come first. */ if (pattern_search (file, 0, depth, 0)) return 1; #ifndef NO_ARCHIVES /* If this is an archive member reference, use just the archive member name to search for implicit rules. */ if (ar_name (file->name)) { DBF (DB_IMPLICIT, _("Looking for archive-member implicit rule for `%s'.\n")); if (pattern_search (file, 1, depth, 0)) return 1; } #endif return 0; } /* Scans the BUFFER for the next word with whitespace as a separator. Returns the pointer to the beginning of the word. LENGTH hold the length of the word. */ static const char * get_next_word (const char *buffer, unsigned int *length) { const char *p = buffer, *beg; char c; /* Skip any leading whitespace. */ while (isblank ((unsigned char)*p)) ++p; beg = p; c = *(p++); if (c == '\0') { if (length) /* bird: shut up gcc. */ *length = 0; return 0; } /* We already found the first value of "c", above. */ while (1) { char closeparen; int count; switch (c) { case '\0': case ' ': case '\t': goto done_word; case '$': c = *(p++); if (c == '$') break; /* This is a variable reference, so read it to the matching close paren. */ if (c == '(') closeparen = ')'; else if (c == '{') closeparen = '}'; else /* This is a single-letter variable reference. */ break; for (count = 0; *p != '\0'; ++p) { if (*p == c) ++count; else if (*p == closeparen && --count < 0) { ++p; break; } } break; case '|': goto done; default: break; } c = *(p++); } done_word: --p; done: if (length) *length = p - beg; return beg; } /* This structure stores information about the expanded prerequisites for a pattern rule. NAME is always set to the strcache'd name of the prereq. FILE and PATTERN will be set for intermediate files only. IGNORE_MTIME is copied from the prerequisite we expanded. */ struct patdeps { const char *name; const char *pattern; struct file *file; unsigned int ignore_mtime : 1; }; /* This structure stores information about pattern rules that we need to try. */ struct tryrule { struct rule *rule; /* Index of the target in this rule that matched the file. */ unsigned int matches; /* Stem length for this match. */ unsigned int stemlen; /* Definition order of this rule. Used to implement stable sort.*/ unsigned int order; /* Nonzero if the LASTSLASH logic was used in matching this rule. */ char checked_lastslash; }; int stemlen_compare (const void *v1, const void *v2) { const struct tryrule *r1 = v1; const struct tryrule *r2 = v2; int r = r1->stemlen - r2->stemlen; return r != 0 ? r : (int)(r1->order - r2->order); } /* Search the pattern rules for a rule with an existing dependency to make FILE. If a rule is found, the appropriate commands and deps are put in FILE and 1 is returned. If not, 0 is returned. If ARCHIVE is nonzero, FILE->name is of the form "LIB(MEMBER)". A rule for "(MEMBER)" will be searched for, and "(MEMBER)" will not be chopped up into directory and filename parts. If an intermediate file is found by pattern search, the intermediate file is set up as a target by the recursive call and is also made a dependency of FILE. DEPTH is used for debugging messages. */ static int pattern_search (struct file *file, int archive, unsigned int depth, unsigned int recursions) { /* Filename we are searching for a rule for. */ const char *filename = archive ? strchr (file->name, '(') : file->name; /* Length of FILENAME. */ unsigned int namelen = strlen (filename); /* The last slash in FILENAME (or nil if there is none). */ const char *lastslash; /* This is a file-object used as an argument in recursive calls. It never contains any data except during a recursive call. */ struct file *int_file = 0; /* List of dependencies found recursively. */ struct patdeps *deplist = xmalloc (max_pattern_deps * sizeof (struct patdeps)); struct patdeps *pat = deplist; /* All the prerequisites actually found for a rule, after expansion. */ struct dep *deps; /* Names of possible dependencies are constructed in this buffer. */ char *depname = alloca (namelen + max_pattern_dep_length); /* The start and length of the stem of FILENAME for the current rule. */ const char *stem = 0; unsigned int stemlen = 0; unsigned int fullstemlen = 0; /* Buffer in which we store all the rules that are possibly applicable. */ struct tryrule *tryrules = xmalloc (num_pattern_rules * max_pattern_targets * sizeof (struct tryrule)); /* Number of valid elements in TRYRULES. */ unsigned int nrules; /* The index in TRYRULES of the rule we found. */ unsigned int foundrule; /* Nonzero if should consider intermediate files as dependencies. */ int intermed_ok; /* Nonzero if we have initialized file variables for this target. */ int file_vars_initialized = 0; /* Nonzero if we have matched a pattern-rule target that is not just `%'. */ int specific_rule_matched = 0; struct dep dep_simple; unsigned int ri; /* uninit checks OK */ struct rule *rule; char *pathdir = NULL; unsigned long pathlen; PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */ #ifndef NO_ARCHIVES if (archive || ar_name (filename)) lastslash = 0; else #endif { /* Set LASTSLASH to point at the last slash in FILENAME but not counting any slash at the end. (foo/bar/ counts as bar/ in directory foo/, not empty in directory foo/bar/.) */ #ifdef VMS lastslash = strrchr (filename, ']'); if (lastslash == 0) lastslash = strrchr (filename, ':'); #else lastslash = strrchr (filename, '/'); #ifdef HAVE_DOS_PATHS /* Handle backslashes (possibly mixed with forward slashes) and the case of "d:file". */ { char *bslash = strrchr (filename, '\\'); if (lastslash == 0 || bslash > lastslash) lastslash = bslash; if (lastslash == 0 && filename[0] && filename[1] == ':') lastslash = filename + 1; } #endif #endif if (lastslash != 0 && lastslash[1] == '\0') lastslash = 0; } pathlen = lastslash - filename + 1; /* First see which pattern rules match this target and may be considered. Put them in TRYRULES. */ nrules = 0; for (rule = pattern_rules; rule != 0; rule = rule->next) { unsigned int ti; /* If the pattern rule has deps but no commands, ignore it. Users cancel built-in rules by redefining them without commands. */ if (rule->deps != 0 && rule->cmds == 0) continue; /* If this rule is in use by a parent pattern_search, don't use it here. */ if (rule->in_use) { DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n"))); continue; } for (ti = 0; ti < rule->num; ++ti) { const char *target = rule->targets[ti]; const char *suffix = rule->suffixes[ti]; int check_lastslash; /* Rules that can match any filename and are not terminal are ignored if we're recursing, so that they cannot be intermediate files. */ if (recursions > 0 && target[1] == '\0' && !rule->terminal) continue; if (rule->lens[ti] > namelen) /* It can't possibly match. */ continue; /* From the lengths of the filename and the pattern parts, find the stem: the part of the filename that matches the %. */ stem = filename + (suffix - target - 1); stemlen = namelen - rule->lens[ti] + 1; /* Set CHECK_LASTSLASH if FILENAME contains a directory prefix and the target pattern does not contain a slash. */ check_lastslash = 0; if (lastslash) { #ifdef VMS check_lastslash = (strchr (target, ']') == 0 && strchr (target, ':') == 0); #else check_lastslash = strchr (target, '/') == 0; #ifdef HAVE_DOS_PATHS /* Didn't find it yet: check for DOS-type directories. */ if (check_lastslash) { char *b = strchr (target, '\\'); check_lastslash = !(b || (target[0] && target[1] == ':')); } #endif #endif } if (check_lastslash) { /* If so, don't include the directory prefix in STEM here. */ if (pathlen > stemlen) continue; stemlen -= pathlen; stem += pathlen; } /* Check that the rule pattern matches the text before the stem. */ if (check_lastslash) { if (stem > (lastslash + 1) && !strneq (target, lastslash + 1, stem - lastslash - 1)) continue; } else if (stem > filename && !strneq (target, filename, stem - filename)) continue; /* Check that the rule pattern matches the text after the stem. We could test simply use streq, but this way we compare the first two characters immediately. This saves time in the very common case where the first character matches because it is a period. */ if (*suffix != stem[stemlen] || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1]))) continue; /* Record if we match a rule that not all filenames will match. */ if (target[1] != '\0') specific_rule_matched = 1; /* A rule with no dependencies and no commands exists solely to set specific_rule_matched when it matches. Don't try to use it. */ if (rule->deps == 0 && rule->cmds == 0) continue; /* Record this rule in TRYRULES and the index of the matching target in MATCHES. If several targets of the same rule match, that rule will be in TRYRULES more than once. */ tryrules[nrules].rule = rule; tryrules[nrules].matches = ti; tryrules[nrules].stemlen = stemlen + (check_lastslash ? pathlen : 0); tryrules[nrules].order = nrules; tryrules[nrules].checked_lastslash = check_lastslash; ++nrules; } } /* Bail out early if we haven't found any rules. */ if (nrules == 0) goto done; /* Sort the rules to place matches with the shortest stem first. This way the most specific rules will be tried first. */ if (nrules > 1) qsort (tryrules, nrules, sizeof (struct tryrule), stemlen_compare); /* If we have found a matching rule that won't match all filenames, retroactively reject any non-"terminal" rules that do always match. */ if (specific_rule_matched) for (ri = 0; ri < nrules; ++ri) if (!tryrules[ri].rule->terminal) { unsigned int j; for (j = 0; j < tryrules[ri].rule->num; ++j) if (tryrules[ri].rule->targets[j][1] == '\0') { tryrules[ri].rule = 0; break; } } /* Try each rule once without intermediate files, then once with them. */ for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok) { pat = deplist; /* Try each pattern rule till we find one that applies. If it does, expand its dependencies (as substituted) and chain them in DEPS. */ for (ri = 0; ri < nrules; ri++) { struct dep *dep; int check_lastslash; unsigned int failed = 0; int file_variables_set = 0; unsigned int deps_found = 0; /* NPTR points to the part of the prereq we haven't processed. */ const char *nptr = 0; const char *dir = NULL; int order_only = 0; unsigned int matches; rule = tryrules[ri].rule; /* RULE is nil when we discover that a rule, already placed in TRYRULES, should not be applied. */ if (rule == 0) continue; /* Reject any terminal rules if we're looking to make intermediate files. */ if (intermed_ok && rule->terminal) continue; /* From the lengths of the filename and the matching pattern parts, find the stem: the part of the filename that matches the %. */ matches = tryrules[ri].matches; stem = filename + (rule->suffixes[matches] - rule->targets[matches]) - 1; stemlen = (namelen - rule->lens[matches]) + 1; check_lastslash = tryrules[ri].checked_lastslash; if (check_lastslash) { stem += pathlen; stemlen -= pathlen; /* We need to add the directory prefix, so set it up. */ if (! pathdir) { pathdir = alloca (pathlen + 1); memcpy (pathdir, filename, pathlen); pathdir[pathlen] = '\0'; } dir = pathdir; } DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"), (int) stemlen, stem)); strncpy (stem_str, stem, stemlen); stem_str[stemlen] = '\0'; /* If there are no prerequisites, then this rule matches. */ if (rule->deps == 0) break; /* Temporary assign STEM to file->stem (needed to set file variables below). */ file->stem = stem_str; /* Mark this rule as in use so a recursive pattern_search won't try to use it. */ rule->in_use = 1; /* Try each prerequisite; see if it exists or can be created. We'll build a list of prereq info in DEPLIST. Due to 2nd expansion we may have to process multiple prereqs for a single dep entry. */ pat = deplist; dep = rule->deps; nptr = dep_name (dep); while (1) { struct dep *dl, *d; char *p; /* If we're out of name to parse, start the next prereq. */ if (! nptr) { dep = dep->next; if (dep == 0) break; nptr = dep_name (dep); } /* If we don't need a second expansion, just replace the %. */ if (! dep->need_2nd_expansion) { dep_simple = *dep; dep_simple.next = 0; p = strchr (nptr, '%'); if (p == 0) dep_simple.name = nptr; else { char *o = depname; if (check_lastslash) { memcpy (o, filename, pathlen); o += pathlen; } memcpy (o, nptr, p - nptr); o += p - nptr; memcpy (o, stem_str, stemlen); o += stemlen; strcpy (o, p + 1); dep_simple.name = strcache_add (depname); } dl = &dep_simple; /* We've used up this dep, so next time get a new one. */ nptr = 0; ++deps_found; } /* We have to perform second expansion on this prereq. In an ideal world we would take the dependency line, substitute the stem, re-expand the whole line and chop it into individual prerequisites. Unfortunately this won't work because of the "check_lastslash" twist. Instead, we will have to go word by word, taking $()'s into account. For each word we will substitute the stem, re-expand, chop it up, and, if check_lastslash != 0, add the directory part to each resulting prerequisite. */ else { int add_dir = 0; unsigned int len; nptr = get_next_word (nptr, &len); if (nptr == 0) continue; /* See this is a transition to order-only prereqs. */ if (! order_only && len == 1 && nptr[0] == '|') { order_only = 1; nptr += len; continue; } /* If the dependency name has %, substitute the stem. If we just replace % with the stem value then later, when we do the 2nd expansion, we will re-expand this stem value again. This is not good if you have certain characters in your stem (like $). Instead, we will replace % with $* and allow the second expansion to take care of it for us. This way (since $* is a simple variable) there won't be additional re-expansion of the stem. */ p = lindex (nptr, nptr + len, '%'); if (p == 0) { memcpy (depname, nptr, len); depname[len] = '\0'; } else { unsigned int i = p - nptr; memcpy (depname, nptr, i); memcpy (depname + i, "$*", 2); memcpy (depname + i + 2, p + 1, len - i - 1); depname[len + 2 - 1] = '\0'; if (check_lastslash) add_dir = 1; } /* Initialize and set file variables if we haven't already done so. */ if (!file_vars_initialized) { initialize_file_variables (file, 0); #if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE) set_file_variables (file, 0 /* real call */); #else set_file_variables (file); #endif file_vars_initialized = 1; } /* Update the stem value in $* for this rule. */ else if (!file_variables_set) { define_variable_for_file ( "*", 1, file->stem, o_automatic, 0, file); file_variables_set = 1; } /* Perform the 2nd expansion. */ p = variable_expand_for_file (depname, file); /* Parse the expanded string. */ dl = PARSE_FILE_SEQ (&p, struct dep, order_only ? '\0' : '|', add_dir ? dir : NULL, 0); for (d = dl; d != NULL; d = d->next) { ++deps_found; if (order_only) d->ignore_mtime = 1; } /* Set up for the next word. */ nptr += len; } /* If there are more than max_pattern_deps prerequisites (due to 2nd expansion), reset it and realloc the arrays. */ if (deps_found > max_pattern_deps) { unsigned int l = pat - deplist; deplist = xrealloc (deplist, deps_found * sizeof (struct patdeps)); pat = deplist + l; max_pattern_deps = deps_found; } /* Go through the nameseq and handle each as a prereq name. */ for (d = dl; d != 0; d = d->next) { struct dep *expl_d; int is_rule = d->name == dep_name (dep); if (file_impossible_p (d->name)) { /* If this prereq has already been ruled "impossible", then the rule fails. Don't bother trying it on the second pass either since we know that will fail. */ DBS (DB_IMPLICIT, (is_rule ? _("Rejecting impossible rule prerequisite `%s'.\n") : _("Rejecting impossible implicit prerequisite `%s'.\n"), d->name)); tryrules[ri].rule = 0; failed = 1; break; } memset (pat, '\0', sizeof (struct patdeps)); pat->ignore_mtime = d->ignore_mtime; DBS (DB_IMPLICIT, (is_rule ? _("Trying rule prerequisite `%s'.\n") : _("Trying implicit prerequisite `%s'.\n"), d->name)); /* If this prereq is also explicitly mentioned for FILE, skip all tests below since it must be built no matter which implicit rule we choose. */ for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next) if (streq (dep_name (expl_d), d->name)) break; if (expl_d != 0) { (pat++)->name = d->name; continue; } /* The DEP->changed flag says that this dependency resides in a nonexistent directory. So we normally can skip looking for the file. However, if CHECK_LASTSLASH is set, then the dependency file we are actually looking for is in a different directory (the one gotten by prepending FILENAME's directory), so it might actually exist. */ /* @@ dep->changed check is disabled. */ if (lookup_file (d->name) != 0 /*|| ((!dep->changed || check_lastslash) && */ || file_exists_p (d->name)) { (pat++)->name = d->name; continue; } /* This code, given FILENAME = "lib/foo.o", dependency name "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c". */ { const char *vname = vpath_search (d->name, 0, NULL, NULL); if (vname) { DBS (DB_IMPLICIT, (_("Found prerequisite `%s' as VPATH `%s'\n"), d->name, vname)); (pat++)->name = d->name; continue; } } /* We could not find the file in any place we should look. Try to make this dependency as an intermediate file, but only on the second pass. */ if (intermed_ok) { DBS (DB_IMPLICIT, (_("Looking for a rule with intermediate file `%s'.\n"), d->name)); if (int_file == 0) int_file = alloca (sizeof (struct file)); memset (int_file, '\0', sizeof (struct file)); int_file->name = d->name; if (pattern_search (int_file, 0, depth + 1, recursions + 1)) { pat->pattern = int_file->name; int_file->name = d->name; pat->file = int_file; (pat++)->name = d->name; int_file = 0; continue; } /* If we have tried to find P as an intermediate file and failed, mark that name as impossible so we won't go through the search again later. */ if (int_file->variables) free_variable_set (int_file->variables); if (int_file->pat_variables) free_variable_set (int_file->pat_variables); file_impossible (d->name); } /* A dependency of this rule does not exist. Therefore, this rule fails. */ failed = 1; break; } /* Free the ns chain. */ if (dl != &dep_simple) free_dep_chain (dl); if (failed) break; } /* Reset the stem in FILE. */ file->stem = 0; /* This rule is no longer `in use' for recursive searches. */ rule->in_use = 0; if (! failed) /* This pattern rule does apply. Stop looking for one. */ break; /* This pattern rule does not apply. If some of its dependencies succeeded, free the data structure describing them. */ /* free_idep_chain (deps); */ deps = 0; } /* If we found an applicable rule without intermediate files, don't try with them. */ if (ri < nrules) break; rule = 0; } /* RULE is nil if the loop went through the list but everything failed. */ if (rule == 0) goto done; foundrule = ri; /* If we are recursing, store the pattern that matched FILENAME in FILE->name for use in upper levels. */ if (recursions > 0) /* Kludge-o-matic */ file->name = rule->targets[tryrules[foundrule].matches]; /* DEPLIST lists the prerequisites for the rule we found. This includes the intermediate files, if any. Convert them into entries on the deps-chain of FILE. */ while (pat-- > deplist) { struct dep *dep; const char *s; if (pat->file != 0) { /* If we need to use an intermediate file, make sure it is entered as a target, with the info that was found for it in the recursive pattern_search call. We know that the intermediate file did not already exist as a target; therefore we can assume that the deps and cmds of F below are null before we change them. */ struct file *imf = pat->file; struct file *f = lookup_file (imf->name); /* We don't want to delete an intermediate file that happened to be a prerequisite of some (other) target. Mark it as precious. */ if (f != 0) f->precious = 1; else f = enter_file (imf->name); f->deps = imf->deps; f->cmds = imf->cmds; f->stem = imf->stem; f->variables = imf->variables; f->pat_variables = imf->pat_variables; f->pat_searched = imf->pat_searched; f->also_make = imf->also_make; f->is_target = 1; f->intermediate = 1; f->tried_implicit = 1; imf = lookup_file (pat->pattern); if (imf != 0 && imf->precious) f->precious = 1; for (dep = f->deps; dep != 0; dep = dep->next) { dep->file = enter_file (dep->name); dep->name = 0; dep->file->tried_implicit |= dep->changed; } } dep = alloc_dep (); dep->ignore_mtime = pat->ignore_mtime; s = strcache_add (pat->name); if (recursions) dep->name = s; else { dep->file = lookup_file (s); if (dep->file == 0) dep->file = enter_file (s); } if (pat->file == 0 && tryrules[foundrule].rule->terminal) { /* If the file actually existed (was not an intermediate file), and the rule that found it was a terminal one, then we want to mark the found file so that it will not have implicit rule search done for it. If we are not entering a `struct file' for it now, we indicate this with the `changed' flag. */ if (dep->file == 0) dep->changed = 1; else dep->file->tried_implicit = 1; } dep->next = file->deps; file->deps = dep; } if (!tryrules[foundrule].checked_lastslash) { /* Always allocate new storage, since STEM might be on the stack for an intermediate file. */ file->stem = strcache_add_len (stem, stemlen); fullstemlen = stemlen; } else { int dirlen = (lastslash + 1) - filename; char *sp; /* We want to prepend the directory from the original FILENAME onto the stem. */ fullstemlen = dirlen + stemlen; sp = alloca (fullstemlen + 1); memcpy (sp, filename, dirlen); memcpy (sp + dirlen, stem, stemlen); sp[fullstemlen] = '\0'; #ifndef CONFIG_WITH_VALUE_LENGTH file->stem = strcache_add (sp); #else file->stem = strcache_add_len (sp, fullstemlen); #endif } file->cmds = rule->cmds; file->is_target = 1; /* Set precious flag. */ { struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]); if (f && f->precious) file->precious = 1; } /* If this rule builds other targets, too, put the others into FILE's `also_make' member. */ if (rule->num > 1) for (ri = 0; ri < rule->num; ++ri) if (ri != tryrules[foundrule].matches) { char *nm = alloca (rule->lens[ri] + fullstemlen + 1); char *p = nm; struct file *f; struct dep *new = alloc_dep (); /* GKM FIMXE: handle '|' here too */ memcpy (p, rule->targets[ri], rule->suffixes[ri] - rule->targets[ri] - 1); p += rule->suffixes[ri] - rule->targets[ri] - 1; memcpy (p, file->stem, fullstemlen); p += fullstemlen; memcpy (p, rule->suffixes[ri], rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1); new->name = strcache_add (nm); new->file = enter_file (new->name); new->next = file->also_make; /* Set precious flag. */ f = lookup_file (rule->targets[ri]); if (f && f->precious) new->file->precious = 1; /* Set the is_target flag so that this file is not treated as intermediate by the pattern rule search algorithm and file_exists_p cannot pick it up yet. */ new->file->is_target = 1; file->also_make = new; } done: free (tryrules); free (deplist); return rule != 0; } kbuild-2695/src/kmk/testcase-math.kmk0000644000000000000000000000651612247157306016267 0ustar rootroot# $Id: testcase-math.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the math functions. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifneq ($(not 1),) $(error The 'not' function is missing) endif ifneq ($(eq 1,1),1) $(error The 'eq' function is missing) endif ASSERT_TRUE = $(if $(not $(1)),$(error failure: '$(1)' isn't true)) ASSERT_FALSE = $(if $(1) ,$(error failure: '$(1)' isn't false)) $(call ASSERT_TRUE, $(int-eq 0x0, 0)) $(call ASSERT_FALSE,$(int-eq 1, 0)) $(call ASSERT_FALSE,$(int-eq 1123123123, 9898787987)) $(call ASSERT_TRUE, $(int-eq 1234567890, 1234567890)) $(call ASSERT_TRUE, $(int-eq 0x1c, 28)) $(call ASSERT_TRUE, $(int-eq 1c, 28)) $(call ASSERT_TRUE, $(int-ne 0x123, -0x123)) $(call ASSERT_TRUE, $(int-ne 123, -0x123)) $(call ASSERT_FALSE,$(int-ne 0x100, 256)) $(call ASSERT_FALSE,$(int-ne 0x0, 0)) $(call ASSERT_FALSE,$(int-ne 0x1c, 28)) $(call ASSERT_TRUE, $(int-le 0, 0)) $(call ASSERT_TRUE, $(int-le -0, 0)) $(call ASSERT_FALSE,$(int-le 5, 1)) $(call ASSERT_FALSE,$(int-lt 5, 1)) $(call ASSERT_FALSE,$(int-lt 5, 5)) $(call ASSERT_TRUE, $(int-lt 9, 10)) $(call ASSERT_TRUE, $(int-lt -9, -8)) $(call ASSERT_TRUE, $(int-ge 0, 0)) $(call ASSERT_TRUE, $(int-ge -0, 0)) $(call ASSERT_TRUE, $(int-ge 1, 0)) $(call ASSERT_TRUE, $(int-ge -55, -55)) $(call ASSERT_TRUE, $(int-ge 512, 400)) $(call ASSERT_TRUE, $(int-ge -18, -19)) $(call ASSERT_FALSE,$(int-ge -19, -18)) $(call ASSERT_FALSE,$(int-ge 15, 20)) $(call ASSERT_FALSE,$(int-gt 15, 20)) $(call ASSERT_FALSE,$(int-gt 15, 15)) $(call ASSERT_TRUE, $(int-gt 20, 15)) ASSERT2 = $(if $(not $(int-eq $(1),$(2))),$(error failure: '$(1)' -ne '$(2)')) $(call ASSERT2,$(int-add 1, 1),0x2) $(call ASSERT2,$(int-add 1, 1, 1, 1, 1, 1, 1),7) $(call ASSERT2,$(int-add 1, -1),0) $(call ASSERT2,$(int-sub 1, -1),2) $(call ASSERT2,$(int-sub 1, 5),-4) $(call ASSERT2,$(int-mul 0x10, 0x20),0x200) $(call ASSERT2,$(int-mul 0x20, 0x10),0x200) $(call ASSERT2,$(int-mul 4, 7),28) $(call ASSERT2,$(int-mul 2, 2, 2, 2, 2, 4, 1, 1, 1, 1),128) $(call ASSERT2,$(int-div 0x1000, 0x100),0x10) $(call ASSERT2,$(int-div 999, 10),99) $(call ASSERT2,$(int-div 4096, 4,2,2,2,2),64) #$(call ASSERT2,$(int-div 0x1230023213, 0),0x0) $(call ASSERT2,$(int-mod 19, 10),9) $(call ASSERT2,$(int-mod 9, 10),9) $(call ASSERT2,$(int-mod 30, 10),0) $(call ASSERT2,$(int-not 0),-1) $(call ASSERT2,$(int-and 1, 1),1) $(call ASSERT2,$(int-and 0x123123214, 0xfff),0x214) $(call ASSERT2,$(int-and 0x123123214, 0xf0f, 0xf),4) $(call ASSERT2,$(int-or 1, 1, 1, 2, 2),3) $(call ASSERT2,$(int-xor 1, 1, 2, 2),0) $(call ASSERT2,$(int-xor 1, 2, 4),7) all_recursive: $(ECHO) The math works. 6 * 7 = $(int-mul 6,7) kbuild-2695/src/kmk/commands.h0000644000000000000000000000524612247157307014773 0ustar rootroot/* Definition of data structures describing shell commands for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Structure that gives the commands to make a file and information about where these commands came from. */ struct commands { struct floc fileinfo; /* Where commands were defined. */ char *commands; /* Commands text. */ unsigned int ncommand_lines;/* Number of command lines. */ char **command_lines; /* Commands chopped up into lines. */ #ifdef CONFIG_WITH_COMMANDS_FUNC short *lines_flags; /* One set of flag bits for each line. */ #else char *lines_flags; /* One set of flag bits for each line. */ #endif int any_recurse; /* Nonzero if any `lines_recurse' elt has */ /* the COMMANDS_RECURSE bit set. */ #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS int refs; /* References. */ #endif }; /* Bits in `lines_flags'. */ #define COMMANDS_RECURSE 1 /* Recurses: + or $(MAKE). */ #define COMMANDS_SILENT 2 /* Silent: @. */ #define COMMANDS_NOERROR 4 /* No errors: -. */ #ifdef CONFIG_WITH_EXTENDED_NOTPARALLEL # define COMMANDS_NOTPARALLEL 32 /* kmk: The commands must be executed alone. */ # define COMMANDS_NO_COMMANDS 64 /* kmk: No commands. */ #endif #ifdef CONFIG_WITH_KMK_BUILTIN # define COMMANDS_KMK_BUILTIN 128 /* kmk: kmk builtin command. */ #endif #ifdef CONFIG_WITH_COMMANDS_FUNC # define COMMAND_GETTER_SKIP_IT 256 /* $(commands target) skips this: % */ #endif void execute_file_commands (struct file *file); void print_commands (const struct commands *cmds); void delete_child_targets (struct child *child); void chop_commands (struct commands *cmds); #if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE) void set_file_variables (struct file *file, int called_early); #else void set_file_variables (struct file *file); #endif #ifdef CONFIG_WITH_LAZY_DEPS_VARS struct dep *create_uniqute_deps_chain (struct dep *deps); #endif kbuild-2695/src/kmk/README.DOS.template0000644000000000000000000003711012247157306016131 0ustar rootrootPort of GNU Make to 32-bit protected mode on MSDOS and MS-Windows. Builds with DJGPP v2 port of GNU C/C++ compiler and utilities. New (since 3.74) DOS-specific features: 1. Supports long filenames when run from DOS box on Windows 9x. 2. Supports both stock DOS COMMAND.COM and Unix-style shells (details in ``Notes'' below). 3. Supports DOS drive letters in dependencies and pattern rules. 4. Better support for DOS-style backslashes in pathnames (but see ``Notes'' below). 5. The $(shell) built-in can run arbitrary complex commands, including pipes and redirection, even when COMMAND.COM is your shell. 6. Can be built without floating-point code (see below). 7. Supports signals in child programs and restores the original directory if the child was interrupted. 8. Can be built without (a previous version of) Make. 9. The build process requires only standard tools. (Optional targets like "install:" and "clean:" still need additional programs, though, see below.) 10. Beginning with v3.78, the test suite works in the DJGPP environment (requires Perl and auxiliary tools; see below). To install a binary distribution: Simply unzip the makNNNb.zip file (where NNN is the version number) preserving the directory structure (-d switch if you use PKUNZIP). If you are installing Make on Windows 9X or Windows 2000, use an unzip program that supports long filenames in zip files. After unzipping, make sure the directory with make.exe is on your PATH, and that's all you need to use Make. To build from sources: 1. Unzip the archive, preserving the directory structure (-d switch if you use PKUNZIP). If you build Make on Windows 9X or Windows 2000, use an unzip program that supports long filenames in zip files. If you are unpacking an official GNU source distribution, use either DJTAR (which is part of the DJGPP development environment), or the DJGPP port of GNU Tar. 2. Invoke the `configure.bat' batch file. If you are building Make in-place, i.e. in the same directory where its sources are kept, just type "configure.bat" and press [Enter]. Otherwise, you need to supply the path to the source directory as an argument to the batch file, like this: c:\djgpp\gnu\make-%VERSION%\configure.bat c:/djgpp/gnu/make-%VERSION% Note the forward slashes in the source path argument: you MUST use them here. 3. If configure.bat doesn't find a working Make, it will suggest to use the `dosbuild.bat' batch file to build Make. Either do as it suggests or install another Make program (a pre-compiled binary should be available from the usual DJGPP sites) and rerun configure.bat. 4. If you will need to run Make on machines without an FPU, you might consider building a version of Make which doesn't issue floating-point instructions (they don't help much on MSDOS anyway). To this end, edit the Makefile created by configure.bat and add -DNO_FLOAT to the value of CPPFLAGS. 5. Invoke Make. If you are building from outside of the source directory, you need to tell Make where the sources are, like this: make srcdir=c:/djgpp/gnu/make-%VERSION% (configure.bat will tell you this when it finishes). You MUST use a full, not relative, name of the source directory here, or else Make might fail. 6. After Make finishes, if you have a Unix-style shell installed, you can use the `install' target to install the package. You will also need GNU Fileutils and GNU Sed for this (they should be available from the DJGPP sites). By default, GNU make will install into your DJGPP installation area. If you wish to use a different directory, override the DESTDIR variable when invoking "make install", like this: make install DESTDIR=c:/other/dir This causes the make executable to be placed in c:/other/dir/bin, the man pages in c:/other/dir/man, etc. Without a Unix-style shell, you will have to install programs and the docs manually. Copy make.exe to a directory on your PATH, make.i* info files to your Info directory, and update the file `dir' in your Info directory by adding the following item to the main menu: * Make: (make.info). The GNU make utility. If you have the `install-info' program (from the GNU Texinfo package), it will do that for you if you invoke it like this: install-info --info-dir=c:/djgpp/info c:/djgpp/info/make.info (If your Info directory is other than C:\DJGPP\INFO, change this command accordingly.) 7. The `clean' targets also require Unix-style shell, and GNU Sed and `rm' programs (the latter from Fileutils). 8. To run the test suite, type "make check". This requires a Unix shell (I used the DJGPP port of Bash 2.03), Perl, Sed, Fileutils and Sh-utils. Notes: ----- 1. The shell issue. This is probably the most significant improvement, first introduced in the port of GNU Make 3.75. The original behavior of GNU Make is to invoke commands directly, as long as they don't include characters special to the shell or internal shell commands, because that is faster. When shell features like redirection or filename wildcards are involved, Make calls the shell. This port supports both DOS shells (the stock COMMAND.COM and its 4DOS/NDOS replacements), and Unix-style shells (tested with the venerable Stewartson's `ms_sh' 2.3 and the DJGPP port of `bash' by Daisuke Aoyama ). When the $SHELL variable points to a Unix-style shell, Make works just like you'd expect on Unix, calling the shell for any command that involves characters special to the shell or internal shell commands. The only difference is that, since there is no standard way to pass command lines longer than the infamous DOS 126-character limit, this port of Make writes the command line to a temporary disk file and then invokes the shell on that file. If $SHELL points to a DOS-style shell, however, Make will not call it automatically, as it does with Unix shells. Stock COMMAND.COM is too dumb and would unnecessarily limit the functionality of Make. For example, you would not be able to use long command lines in commands that use redirection or pipes. Therefore, when presented with a DOS shell, this port of Make will emulate most of the shell functionality, like redirection and pipes, and shall only call the shell when a batch file or a command internal to the shell is invoked. (Even when a command is an internal shell command, Make will first search the $PATH for it, so that if a Makefile calls `mkdir', you can install, say, a port of GNU `mkdir' and have it called in that case.) The key to all this is the extended functionality of `spawn' and `system' functions from the DJGPP library; this port just calls `system' where it would invoke the shell on Unix. The most important aspect of these functions is that they use a special mechanism to pass long (up to 16KB) command lines to DJGPP programs. In addition, `system' emulates some internal commands, like `cd' (so that you can now use forward slashes with it, and can also change the drive if the directory is on another drive). Another aspect worth mentioning is that you can call Unix shell scripts directly, provided that the shell whose name is mentioned on the first line of the script is installed anywhere along the $PATH. It is impossible to tell here everything about these functions; refer to the DJGPP library reference for more details. The $(shell) built-in is implemented in this port by calling `popen'. Since `popen' calls `system', the above considerations are valid for $(shell) as well. In particular, you can put arbitrary complex commands, including pipes and redirection, inside $(shell), which is in many cases a valid substitute for the Unix-style command substitution (`command`) feature. 2. "SHELL=/bin/sh" -- or is it? Many Unix Makefiles include a line which sets the SHELL, for those versions of Make which don't have this as the default. Since many DOS systems don't have `sh' installed (in fact, most of them don't even have a `/bin' directory), this port takes such directives with a grain of salt. It will only honor such a directive if the basename of the shell name (like `sh' in the above example) can indeed be found in the directory that is mentioned in the SHELL= line (`/bin' in the above example), or in the current working directory, or anywhere on the $PATH (in that order). If the basename doesn't include a filename extension, Make will look for any known extension that indicates an executable file (.exe, .com, .bat, .btm, .sh, and even .sed and .pl). If any such file is found, then $SHELL will be defined to the exact pathname of that file, and that shell will hence be used for the rest of processing. But if the named shell is *not* found, the line which sets it will be effectively ignored, leaving the value of $SHELL as it was before. Since a lot of decisions that this port makes depend on the gender of the shell, I feel it doesn't make any sense to tailor Make's behavior to a shell which is nowhere to be found. Note that the above special handling of "SHELL=" only happens for Makefiles; if you set $SHELL in the environment or on the Make command line, you are expected to give the complete pathname of the shell, including the filename extension. The default value of $SHELL is computed as on Unix (see the Make manual for details), except that if $SHELL is not defined in the environment, $COMSPEC is used. Also, if an environment variable named $MAKESHELL is defined, it takes precedence over both $COMSPEC and $SHELL. Note that, unlike Unix, $SHELL in the environment *is* used to set the shell (since on MSDOS, it's unlikely that the interactive shell will not be suitable for Makefile processing). The bottom line is that you can now write Makefiles where some of the targets require a real (i.e. Unix-like) shell, which will nevertheless work when such shell is not available (provided, of course, that the commands which should always work, don't require such a shell). More important, you can convert Unix Makefiles to MSDOS and leave the line which sets the shell intact, so that people who do have Unixy shell could use it for targets which aren't converted to DOS (like `install' and `uninstall', for example). 3. Default directories. GNU Make knows about standard directories where it searches for library and include files mentioned in the Makefile. Since MSDOS machines don't have standard places for these, this port will search ${DJDIR}/lib and ${DJDIR}/include respectively. $DJDIR is defined automatically by the DJGPP startup code as the root of the DJGPP installation tree (unless you've tampered with the DJGPP.ENV file). This should provide reasonable default values, unless you moved parts of DJGPP to other directories. 4. Letter-case in filenames. If you run Make on Windows 9x, you should be aware of the letter-case issue. Make is internally case-sensitive, but all file operations are case-insensitive on Windows 9x, so e.g. files `FAQ', `faq' and `Faq' all refer to the same file, as far as Windows is concerned. The underlying DJGPP C library functions honor the letter-case of the filenames they get from the OS, except that by default, they down-case 8+3 DOS filenames which are stored in upper case in the directory and would break many Makefiles otherwise. (The details of which filenames are converted to lower case are explained in the DJGPP libc docs, under the `_preserve_fncase' and `_lfn_gen_short_fname' functions, but as a thumb rule, any filename that is stored in upper case in the directory, is a valid DOS 8+3 filename and doesn't include characters invalid on MSDOS FAT filesystems, will be automatically down-cased.) User reports that I have indicate that this default behavior is generally what you'd expect; however, your input is most welcome. In any case, if you hit a situation where you must force Make to get the 8+3 DOS filenames in upper case, set FNCASE=y in the environment or in the Makefile. 5. DOS-style pathnames. There are a lot of places throughout the program sources which make implicit assumptions about the pathname syntax. In particular, the directories are assumed to be separated by `/', and any pathname which doesn't begin with a `/' is assumed to be relative to the current directory. This port attempts to support DOS-style pathnames which might include the drive letter and use backslashes instead of forward slashes. However, this support is not complete; I feel that pursuing this support too far might break some more important features, particularly if you use a Unix-style shell (where a backslash is a quote character). I only consider support of backslashes desirable because some Makefiles invoke non-DJGPP programs which don't understand forward slashes. A notable example of such programs is the standard programs which come with MSDOS. Otherwise, you are advised to stay away from backslashes whenever possible. In particular, filename globbing won't work on pathnames with backslashes, because the GNU `glob' library doesn't support them (backslash is special in filename wildcards, and I didn't want to break that). One feature which *does* work with backslashes is the filename- related built-in functions such as $(dir), $(notdir), etc. Drive letters in pathnames are also fully supported. Bug reports: ----------- Bugs that are clearly related to the MSDOS/DJGPP port should be reported first on the comp.os.msdos.djgpp news group (if you cannot post to Usenet groups, write to the DJGPP mailing list, , which is an email gateway into the above news group). For other bugs, please follow the procedure explained in the "Bugs" chapter of the Info docs. If you don't have an Info reader, look up that chapter in the `make.i1' file with any text browser/editor. Enjoy, Eli Zaretskii ------------------------------------------------------------------------------- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/vpath.c0000644000000000000000000004344212247157307014307 0ustar rootroot/* Implementation of pattern-matching file search paths for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "filedef.h" #include "variable.h" #ifdef WINDOWS32 #include "pathstuff.h" #endif /* Structure used to represent a selective VPATH searchpath. */ struct vpath { struct vpath *next; /* Pointer to next struct in the linked list. */ const char *pattern;/* The pattern to match. */ const char *percent;/* Pointer into `pattern' where the `%' is. */ unsigned int patlen;/* Length of the pattern. */ const char **searchpath; /* Null-terminated list of directories. */ unsigned int maxlen;/* Maximum length of any entry in the list. */ }; /* Linked-list of all selective VPATHs. */ static struct vpath *vpaths; /* Structure for the general VPATH given in the variable. */ static struct vpath *general_vpath; /* Structure for GPATH given in the variable. */ static struct vpath *gpaths; /* Reverse the chain of selective VPATH lists so they will be searched in the order given in the makefiles and construct the list from the VPATH variable. */ void build_vpath_lists () { register struct vpath *new = 0; register struct vpath *old, *nexto; register char *p; #ifdef CONFIG_WITH_OPTIMIZATION_HACKS char expr[64]; #endif /* Reverse the chain. */ for (old = vpaths; old != 0; old = nexto) { nexto = old->next; old->next = new; new = old; } vpaths = new; /* If there is a VPATH variable with a nonnull value, construct the general VPATH list from it. We use variable_expand rather than just calling lookup_variable so that it will be recursively expanded. */ { /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; #ifdef CONFIG_WITH_OPTIMIZATION_HACKS p = variable_expand (strcpy (expr, "$(strip $(VPATH))")); #else p = variable_expand ("$(strip $(VPATH))"); #endif warn_undefined_variables_flag = save; } if (*p != '\0') { /* Save the list of vpaths. */ struct vpath *save_vpaths = vpaths; char gp[] = "%"; /* Empty `vpaths' so the new one will have no next, and `vpaths' will still be nil if P contains no existing directories. */ vpaths = 0; /* Parse P. */ construct_vpath_list (gp, p); /* Store the created path as the general path, and restore the old list of vpaths. */ general_vpath = vpaths; vpaths = save_vpaths; } /* If there is a GPATH variable with a nonnull value, construct the GPATH list from it. We use variable_expand rather than just calling lookup_variable so that it will be recursively expanded. */ { /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; #ifdef CONFIG_WITH_OPTIMIZATION_HACKS p = variable_expand (strcpy (expr, "$(strip $(GPATH))")); #else p = variable_expand ("$(strip $(GPATH))"); #endif warn_undefined_variables_flag = save; } if (*p != '\0') { /* Save the list of vpaths. */ struct vpath *save_vpaths = vpaths; char gp[] = "%"; /* Empty `vpaths' so the new one will have no next, and `vpaths' will still be nil if P contains no existing directories. */ vpaths = 0; /* Parse P. */ construct_vpath_list (gp, p); /* Store the created path as the GPATH, and restore the old list of vpaths. */ gpaths = vpaths; vpaths = save_vpaths; } } /* Construct the VPATH listing for the PATTERN and DIRPATH given. This function is called to generate selective VPATH lists and also for the general VPATH list (which is in fact just a selective VPATH that is applied to everything). The returned pointer is either put in the linked list of all selective VPATH lists or in the GENERAL_VPATH variable. If DIRPATH is nil, remove all previous listings with the same pattern. If PATTERN is nil, remove all VPATH listings. Existing and readable directories that are not "." given in the DIRPATH separated by the path element separator (defined in make.h) are loaded into the directory hash table if they are not there already and put in the VPATH searchpath for the given pattern with trailing slashes stripped off if present (and if the directory is not the root, "/"). The length of the longest entry in the list is put in the structure as well. The new entry will be at the head of the VPATHS chain. */ void construct_vpath_list (char *pattern, char *dirpath) { unsigned int elem; char *p; const char **vpath; unsigned int maxvpath; unsigned int maxelem; const char *percent = NULL; if (pattern != 0) percent = find_percent (pattern); if (dirpath == 0) { /* Remove matching listings. */ struct vpath *path, *lastpath; lastpath = 0; path = vpaths; while (path != 0) { struct vpath *next = path->next; if (pattern == 0 || (((percent == 0 && path->percent == 0) || (percent - pattern == path->percent - path->pattern)) && streq (pattern, path->pattern))) { /* Remove it from the linked list. */ if (lastpath == 0) vpaths = path->next; else lastpath->next = next; /* Free its unused storage. */ /* MSVC erroneously warns without a cast here. */ free ((void *)path->searchpath); free (path); } else lastpath = path; path = next; } return; } #ifdef WINDOWS32 convert_vpath_to_windows32(dirpath, ';'); #endif /* Skip over any initial separators and blanks. */ while (*dirpath == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*dirpath)) ++dirpath; /* Figure out the maximum number of VPATH entries and put it in MAXELEM. We start with 2, one before the first separator and one nil (the list terminator) and increment our estimated number for each separator or blank we find. */ maxelem = 2; p = dirpath; while (*p != '\0') if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) ++maxelem; vpath = xmalloc (maxelem * sizeof (const char *)); maxvpath = 0; elem = 0; p = dirpath; while (*p != '\0') { char *v; unsigned int len; /* Find the end of this entry. */ v = p; while (*p != '\0' #if defined(HAVE_DOS_PATHS) && (PATH_SEPARATOR_CHAR == ':') /* Platforms whose PATH_SEPARATOR_CHAR is ':' and which also define HAVE_DOS_PATHS would like us to recognize colons after the drive letter in the likes of "D:/foo/bar:C:/xyzzy". */ && (*p != PATH_SEPARATOR_CHAR || (p == v + 1 && (p[1] == '/' || p[1] == '\\'))) #else && *p != PATH_SEPARATOR_CHAR #endif && !isblank ((unsigned char)*p)) ++p; len = p - v; /* Make sure there's no trailing slash, but still allow "/" as a directory. */ #if defined(__MSDOS__) || defined(__EMX__) || defined(HAVE_DOS_PATHS) /* We need also to leave alone a trailing slash in "d:/". */ if (len > 3 || (len > 1 && v[1] != ':')) #endif if (len > 1 && p[-1] == '/') --len; /* Put the directory on the vpath list. */ if (len > 1 || *v != '.') { vpath[elem++] = dir_name (strcache_add_len (v, len)); if (len > maxvpath) maxvpath = len; } /* Skip over separators and blanks between entries. */ while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) ++p; } if (elem > 0) { struct vpath *path; /* ELEM is now incremented one element past the last entry, to where the nil-pointer terminator goes. Usually this is maxelem - 1. If not, shrink down. */ if (elem < (maxelem - 1)) vpath = (const char **)xrealloc (vpath, (elem+1) * sizeof (const char *)); /* Put the nil-pointer terminator on the end of the VPATH list. */ vpath[elem] = NULL; /* Construct the vpath structure and put it into the linked list. */ path = xmalloc (sizeof (struct vpath)); path->searchpath = vpath; path->maxlen = maxvpath; path->next = vpaths; vpaths = path; /* Set up the members. */ path->pattern = strcache_add (pattern); path->patlen = strlen (pattern); path->percent = percent ? path->pattern + (percent - pattern) : 0; } else /* There were no entries, so free whatever space we allocated. */ /* MSVC erroneously warns without a cast here. */ free ((void *)vpath); } /* Search the GPATH list for a pathname string that matches the one passed in. If it is found, return 1. Otherwise we return 0. */ int gpath_search (const char *file, unsigned int len) { const char **gp; if (gpaths && (len <= gpaths->maxlen)) for (gp = gpaths->searchpath; *gp != NULL; ++gp) if (strneq (*gp, file, len) && (*gp)[len] == '\0') return 1; return 0; } /* Search the given VPATH list for a directory where the name pointed to by FILE exists. If it is found, we return a cached name of the existing file and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no stat call was done). Also set the matching directory index in PATH_INDEX if it is not NULL. Otherwise we return NULL. */ static const char * selective_vpath_search (struct vpath *path, const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* path_index) { int not_target; char *name; const char *n; const char *filename; const char **vpath = path->searchpath; unsigned int maxvpath = path->maxlen; unsigned int i; unsigned int flen, vlen, name_dplen; int exists = 0; /* Find out if *FILE is a target. If and only if it is NOT a target, we will accept prospective files that don't exist but are mentioned in a makefile. */ { struct file *f = lookup_file (file); not_target = f == 0 || !f->is_target; } flen = strlen (file); /* Split *FILE into a directory prefix and a name-within-directory. NAME_DPLEN gets the length of the prefix; FILENAME gets the pointer to the name-within-directory and FLEN is its length. */ n = strrchr (file, '/'); #ifdef HAVE_DOS_PATHS /* We need the rightmost slash or backslash. */ { const char *bslash = strrchr(file, '\\'); if (!n || bslash > n) n = bslash; } #endif name_dplen = n != 0 ? n - file : 0; filename = name_dplen > 0 ? n + 1 : file; if (name_dplen > 0) flen -= name_dplen + 1; /* Get enough space for the biggest VPATH entry, a slash, the directory prefix that came with FILE, another slash (although this one may not always be necessary), the filename, and a null terminator. */ name = alloca (maxvpath + 1 + name_dplen + 1 + flen + 1); /* Try each VPATH entry. */ for (i = 0; vpath[i] != 0; ++i) { int exists_in_cache = 0; char *p; p = name; /* Put the next VPATH entry into NAME at P and increment P past it. */ vlen = strlen (vpath[i]); memcpy (p, vpath[i], vlen); p += vlen; /* Add the directory prefix already in *FILE. */ if (name_dplen > 0) { #ifndef VMS *p++ = '/'; #endif memcpy (p, file, name_dplen); p += name_dplen; } #ifdef HAVE_DOS_PATHS /* Cause the next if to treat backslash and slash alike. */ if (p != name && p[-1] == '\\' ) p[-1] = '/'; #endif /* Now add the name-within-directory at the end of NAME. */ #ifndef VMS if (p != name && p[-1] != '/') { *p = '/'; memcpy (p + 1, filename, flen + 1); } else #endif memcpy (p, filename, flen + 1); /* Check if the file is mentioned in a makefile. If *FILE is not a target, that is enough for us to decide this file exists. If *FILE is a target, then the file must be mentioned in the makefile also as a target to be chosen. The restriction that *FILE must not be a target for a makefile-mentioned file to be chosen was added by an inadequately commented change in July 1990; I am not sure off hand what problem it fixes. In December 1993 I loosened this restriction to allow a file to be chosen if it is mentioned as a target in a makefile. This seem logical. Special handling for -W / -o: make sure we preserve the special values here. Actually this whole thing is a little bogus: I think we should ditch the name/hname thing and look into the renamed capability that already exists for files: that is, have a new struct file* entry for the VPATH-found file, and set the renamed field if we use it. */ { struct file *f = lookup_file (name); if (f != 0) { exists = not_target || f->is_target; if (exists && mtime_ptr && (f->last_mtime == OLD_MTIME || f->last_mtime == NEW_MTIME)) { *mtime_ptr = f->last_mtime; mtime_ptr = 0; } } } if (!exists) { /* That file wasn't mentioned in the makefile. See if it actually exists. */ #ifdef VMS exists_in_cache = exists = dir_file_exists_p (vpath[i], filename); #else /* Clobber a null into the name at the last slash. Now NAME is the name of the directory to look in. */ *p = '\0'; /* We know the directory is in the hash table now because either construct_vpath_list or the code just above put it there. Does the file we seek exist in it? */ exists_in_cache = exists = dir_file_exists_p (name, filename); #endif } if (exists) { /* The file is in the directory cache. Now check that it actually exists in the filesystem. The cache may be out of date. When vpath thinks a file exists, but stat fails for it, confusion results in the higher levels. */ struct stat st; #ifndef VMS /* Put the slash back in NAME. */ *p = '/'; #endif if (exists_in_cache) /* Makefile-mentioned file need not exist. */ { int e; EINTRLOOP (e, stat (name, &st)); /* Does it really exist? */ if (e != 0) { exists = 0; continue; } /* Store the modtime into *MTIME_PTR for the caller. */ if (mtime_ptr != 0) { *mtime_ptr = FILE_TIMESTAMP_STAT_MODTIME (name, st); mtime_ptr = 0; } } /* We have found a file. If we get here and mtime_ptr hasn't been set, record UNKNOWN_MTIME to indicate this. */ if (mtime_ptr != 0) *mtime_ptr = UNKNOWN_MTIME; /* Store the name we found and return it. */ if (path_index) *path_index = i; return strcache_add_len (name, (p + 1 - name) + flen); } } return 0; } /* Search the VPATH list whose pattern matches FILE for a directory where FILE exists. If it is found, return the cached name of an existing file, and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no stat call was done). Also set the matching directory index in VPATH_INDEX and PATH_INDEX if they are not NULL. Otherwise we return 0. */ const char * vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* vpath_index, unsigned int* path_index) { struct vpath *v; /* If there are no VPATH entries or FILENAME starts at the root, there is nothing we can do. */ if (file[0] == '/' #ifdef HAVE_DOS_PATHS || file[0] == '\\' || file[1] == ':' #endif || (vpaths == 0 && general_vpath == 0)) return 0; if (vpath_index) { *vpath_index = 0; *path_index = 0; } for (v = vpaths; v != 0; v = v->next) { if (pattern_matches (v->pattern, v->percent, file)) { const char *p = selective_vpath_search ( v, file, mtime_ptr, path_index); if (p) return p; } if (vpath_index) ++*vpath_index; } if (general_vpath != 0) { const char *p = selective_vpath_search ( general_vpath, file, mtime_ptr, path_index); if (p) return p; } return 0; } /* Print the data base of VPATH search paths. */ void print_vpath_data_base (void) { unsigned int nvpaths; struct vpath *v; puts (_("\n# VPATH Search Paths\n")); nvpaths = 0; for (v = vpaths; v != 0; v = v->next) { register unsigned int i; ++nvpaths; printf ("vpath %s ", v->pattern); for (i = 0; v->searchpath[i] != 0; ++i) printf ("%s%c", v->searchpath[i], v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); } if (vpaths == 0) puts (_("# No `vpath' search paths.")); else printf (_("\n# %u `vpath' search paths.\n"), nvpaths); if (general_vpath == 0) puts (_("\n# No general (`VPATH' variable) search path.")); else { const char **path = general_vpath->searchpath; unsigned int i; fputs (_("\n# General (`VPATH' variable) search path:\n# "), stdout); for (i = 0; path[i] != 0; ++i) printf ("%s%c", path[i], path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); } } kbuild-2695/src/kmk/rule.c0000644000000000000000000003510512247157307014131 0ustar rootroot/* Pattern and suffix rule internals for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include #include "dep.h" #include "filedef.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" static void freerule (struct rule *rule, struct rule *lastrule); /* Chain of all pattern rules. */ struct rule *pattern_rules; /* Pointer to last rule in the chain, so we can add onto the end. */ struct rule *last_pattern_rule; /* Number of rules in the chain. */ unsigned int num_pattern_rules; /* Maximum number of target patterns of any pattern rule. */ unsigned int max_pattern_targets; /* Maximum number of dependencies of any pattern rule. */ unsigned int max_pattern_deps; /* Maximum length of the name of a dependencies of any pattern rule. */ unsigned int max_pattern_dep_length; /* Pointer to structure for the file .SUFFIXES whose dependencies are the suffixes to be searched. */ struct file *suffix_file; /* Maximum length of a suffix. */ unsigned int maxsuffix; /* Compute the maximum dependency length and maximum number of dependencies of all implicit rules. Also sets the subdir flag for a rule when appropriate, possibly removing the rule completely when appropriate. */ void count_implicit_rule_limits (void) { char *name; int namelen; struct rule *rule, *lastrule; num_pattern_rules = max_pattern_targets = max_pattern_deps = 0; max_pattern_dep_length = 0; name = 0; namelen = 0; rule = pattern_rules; lastrule = 0; while (rule != 0) { unsigned int ndeps = 0; struct dep *dep; struct rule *next = rule->next; ++num_pattern_rules; if (rule->num > max_pattern_targets) max_pattern_targets = rule->num; for (dep = rule->deps; dep != 0; dep = dep->next) { const char *dname = dep_name (dep); unsigned int len = strlen (dname); #ifdef VMS const char *p = strrchr (dname, ']'); const char *p2; if (p == 0) p = strrchr (dname, ':'); p2 = p != 0 ? strchr (dname, '%') : 0; #else const char *p = strrchr (dname, '/'); const char *p2 = p != 0 ? strchr (dname, '%') : 0; #endif ndeps++; if (len > max_pattern_dep_length) max_pattern_dep_length = len; if (p != 0 && p2 > p) { /* There is a slash before the % in the dep name. Extract the directory name. */ if (p == dname) ++p; if (p - dname > namelen) { namelen = p - dname; name = xrealloc (name, namelen + 1); } memcpy (name, dname, p - dname); name[p - dname] = '\0'; /* In the deps of an implicit rule the `changed' flag actually indicates that the dependency is in a nonexistent subdirectory. */ dep->changed = !dir_file_exists_p (name, ""); } else /* This dependency does not reside in a subdirectory. */ dep->changed = 0; } if (ndeps > max_pattern_deps) max_pattern_deps = ndeps; lastrule = rule; rule = next; } if (name != 0) free (name); } /* Create a pattern rule from a suffix rule. TARGET is the target suffix; SOURCE is the source suffix. CMDS are the commands. If TARGET is nil, it means the target pattern should be `(%.o)'. If SOURCE is nil, it means there should be no deps. */ static void convert_suffix_rule (const char *target, const char *source, struct commands *cmds) { const char **names, **percents; struct dep *deps; names = xmalloc (sizeof (const char *)); percents = xmalloc (sizeof (const char *)); if (target == 0) { /* Special case: TARGET being nil means we are defining a `.X.a' suffix rule; the target pattern is always `(%.o)'. */ #ifdef VMS *names = strcache_add_len ("(%.obj)", 7); #else *names = strcache_add_len ("(%.o)", 5); #endif *percents = *names + 1; } else { /* Construct the target name. */ unsigned int len = strlen (target); char *p = alloca (1 + len + 1); p[0] = '%'; memcpy (p + 1, target, len + 1); *names = strcache_add_len (p, len + 1); *percents = *names; } if (source == 0) deps = 0; else { /* Construct the dependency name. */ unsigned int len = strlen (source); char *p = alloca (1 + len + 1); p[0] = '%'; memcpy (p + 1, source, len + 1); deps = alloc_dep (); deps->name = strcache_add_len (p, len + 1); } create_pattern_rule (names, percents, 1, 0, deps, cmds, 0); } /* Convert old-style suffix rules to pattern rules. All rules for the suffixes on the .SUFFIXES list are converted and added to the chain of pattern rules. */ void convert_to_pattern (void) { struct dep *d, *d2; char *rulename; /* We will compute every potential suffix rule (.x.y) from the list of suffixes in the .SUFFIXES target's dependencies and see if it exists. First find the longest of the suffixes. */ maxsuffix = 0; for (d = suffix_file->deps; d != 0; d = d->next) { unsigned int l = strlen (dep_name (d)); if (l > maxsuffix) maxsuffix = l; } /* Space to construct the suffix rule target name. */ rulename = alloca ((maxsuffix * 2) + 1); for (d = suffix_file->deps; d != 0; d = d->next) { unsigned int slen; /* Make a rule that is just the suffix, with no deps or commands. This rule exists solely to disqualify match-anything rules. */ convert_suffix_rule (dep_name (d), 0, 0); if (d->file->cmds != 0) /* Record a pattern for this suffix's null-suffix rule. */ convert_suffix_rule ("", dep_name (d), d->file->cmds); /* Add every other suffix to this one and see if it exists as a two-suffix rule. */ slen = strlen (dep_name (d)); memcpy (rulename, dep_name (d), slen); for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next) { struct file *f; unsigned int s2len; s2len = strlen (dep_name (d2)); /* Can't build something from itself. */ if (slen == s2len && streq (dep_name (d), dep_name (d2))) continue; memcpy (rulename + slen, dep_name (d2), s2len + 1); f = lookup_file (rulename); if (f == 0 || f->cmds == 0) continue; if (s2len == 2 && rulename[slen] == '.' && rulename[slen + 1] == 'a') /* A suffix rule `.X.a:' generates the pattern rule `(%.o): %.X'. It also generates a normal `%.a: %.X' rule below. */ convert_suffix_rule (NULL, /* Indicates `(%.o)'. */ dep_name (d), f->cmds); /* The suffix rule `.X.Y:' is converted to the pattern rule `%.Y: %.X'. */ convert_suffix_rule (dep_name (d2), dep_name (d), f->cmds); } } } /* Install the pattern rule RULE (whose fields have been filled in) at the end of the list (so that any rules previously defined will take precedence). If this rule duplicates a previous one (identical target and dependencies), the old one is replaced if OVERRIDE is nonzero, otherwise this new one is thrown out. When an old rule is replaced, the new one is put at the end of the list. Return nonzero if RULE is used; zero if not. */ static int new_pattern_rule (struct rule *rule, int override) { struct rule *r, *lastrule; unsigned int i, j; rule->in_use = 0; rule->terminal = 0; rule->next = 0; /* Search for an identical rule. */ lastrule = 0; for (r = pattern_rules; r != 0; lastrule = r, r = r->next) for (i = 0; i < rule->num; ++i) { for (j = 0; j < r->num; ++j) if (!streq (rule->targets[i], r->targets[j])) break; /* If all the targets matched... */ if (j == r->num) { struct dep *d, *d2; for (d = rule->deps, d2 = r->deps; d != 0 && d2 != 0; d = d->next, d2 = d2->next) if (!streq (dep_name (d), dep_name (d2))) break; if (d == 0 && d2 == 0) { /* All the dependencies matched. */ if (override) { /* Remove the old rule. */ freerule (r, lastrule); /* Install the new one. */ if (pattern_rules == 0) pattern_rules = rule; else last_pattern_rule->next = rule; last_pattern_rule = rule; /* We got one. Stop looking. */ goto matched; } else { /* The old rule stays intact. Destroy the new one. */ freerule (rule, (struct rule *) 0); return 0; } } } } matched:; if (r == 0) { /* There was no rule to replace. */ if (pattern_rules == 0) pattern_rules = rule; else last_pattern_rule->next = rule; last_pattern_rule = rule; } return 1; } /* Install an implicit pattern rule based on the three text strings in the structure P points to. These strings come from one of the arrays of default implicit pattern rules. TERMINAL specifies what the `terminal' field of the rule should be. */ void install_pattern_rule (struct pspec *p, int terminal) { struct rule *r; char *ptr; r = xmalloc (sizeof (struct rule)); r->num = 1; r->targets = xmalloc (sizeof (const char *)); r->suffixes = xmalloc (sizeof (const char *)); r->lens = xmalloc (sizeof (unsigned int)); r->lens[0] = strlen (p->target); r->targets[0] = p->target; r->suffixes[0] = find_percent_cached (&r->targets[0]); assert (r->suffixes[0] != NULL); ++r->suffixes[0]; ptr = p->dep; r->deps = PARSE_FILE_SEQ (&ptr, struct dep, '\0', NULL, 0); if (new_pattern_rule (r, 0)) { r->terminal = terminal; #ifndef CONFIG_WITH_ALLOC_CACHES r->cmds = xmalloc (sizeof (struct commands)); #else r->cmds = alloccache_alloc (&commands_cache); #endif r->cmds->fileinfo.filenm = 0; r->cmds->fileinfo.lineno = 0; /* These will all be string literals, but we malloc space for them anyway because somebody might want to free them later. */ r->cmds->commands = xstrdup (p->commands); r->cmds->command_lines = 0; #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS r->cmds->refs = 1000; #endif } } /* Free all the storage used in RULE and take it out of the pattern_rules chain. LASTRULE is the rule whose next pointer points to RULE. */ static void freerule (struct rule *rule, struct rule *lastrule) { struct rule *next = rule->next; free_dep_chain (rule->deps); /* MSVC erroneously warns without a cast here. */ free ((void *)rule->targets); free ((void *)rule->suffixes); free (rule->lens); /* We can't free the storage for the commands because there are ways that they could be in more than one place: * If the commands came from a suffix rule, they could also be in the `struct file's for other suffix rules or plain targets given on the same makefile line. * If two suffixes that together make a two-suffix rule were each given twice in the .SUFFIXES list, and in the proper order, two identical pattern rules would be created and the second one would be discarded here, but both would contain the same `struct commands' pointer from the `struct file' for the suffix rule. */ free (rule); if (pattern_rules == rule) if (lastrule != 0) abort (); else pattern_rules = next; else if (lastrule != 0) lastrule->next = next; if (last_pattern_rule == rule) last_pattern_rule = lastrule; } /* Create a new pattern rule with the targets in the nil-terminated array TARGETS. TARGET_PERCENTS is an array of pointers to the % in each element of TARGETS. N is the number of items in the array (not counting the nil element). The new rule has dependencies DEPS and commands from COMMANDS. It is a terminal rule if TERMINAL is nonzero. This rule overrides identical rules with different commands if OVERRIDE is nonzero. The storage for TARGETS and its elements and TARGET_PERCENTS is used and must not be freed until the rule is destroyed. */ void create_pattern_rule (const char **targets, const char **target_percents, unsigned int n, int terminal, struct dep *deps, struct commands *commands, int override) { unsigned int i; struct rule *r = xmalloc (sizeof (struct rule)); r->num = n; r->cmds = commands; r->deps = deps; r->targets = targets; r->suffixes = target_percents; r->lens = xmalloc (n * sizeof (unsigned int)); for (i = 0; i < n; ++i) { r->lens[i] = strlen (targets[i]); assert (r->suffixes[i] != NULL); ++r->suffixes[i]; } if (new_pattern_rule (r, override)) r->terminal = terminal; #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS if (commands != NULL) commands->refs = 1000; #endif } /* Print the data base of rules. */ static void /* Useful to call from gdb. */ print_rule (struct rule *r) { unsigned int i; for (i = 0; i < r->num; ++i) { fputs (r->targets[i], stdout); putchar ((i + 1 == r->num) ? ':' : ' '); } if (r->terminal) putchar (':'); print_prereqs (r->deps); if (r->cmds != 0) print_commands (r->cmds); } void print_rule_data_base (void) { unsigned int rules, terminal; struct rule *r; puts (_("\n# Implicit Rules")); rules = terminal = 0; for (r = pattern_rules; r != 0; r = r->next) { ++rules; putchar ('\n'); print_rule (r); if (r->terminal) ++terminal; } if (rules == 0) puts (_("\n# No implicit rules.")); else { printf (_("\n# %u implicit rules, %u"), rules, terminal); #ifndef NO_FLOAT printf (" (%.1f%%)", (double) terminal / (double) rules * 100.0); #else { int f = (terminal * 1000 + 5) / rules; printf (" (%d.%d%%)", f/10, f%10); } #endif puts (_(" terminal.")); } if (num_pattern_rules != rules) { /* This can happen if a fatal error was detected while reading the makefiles and thus count_implicit_rule_limits wasn't called yet. */ if (num_pattern_rules != 0) fatal (NILF, _("BUG: num_pattern_rules is wrong! %u != %u"), num_pattern_rules, rules); } } kbuild-2695/src/kmk/make.10000644000000000000000000002400312247157306014007 0ustar rootroot.TH MAKE 1 "22 August 1989" "GNU" "LOCAL USER COMMANDS" .SH NAME make \- GNU make utility to maintain groups of programs .SH SYNOPSIS .B "make " [ .B \-f .I makefile ] [ options ] ... [ targets ] ... .SH WARNING This man page is an extract of the documentation of GNU .IR make . It is updated only occasionally, because the GNU project does not use nroff. For complete, current documentation, refer to the Info file .B make.info which is made from the Texinfo source file .BR make.texi . .SH DESCRIPTION .LP The purpose of the .I make utility is to determine automatically which pieces of a large program need to be recompiled, and issue the commands to recompile them. The manual describes the GNU implementation of .IR make , which was written by Richard Stallman and Roland McGrath, and is currently maintained by Paul Smith. Our examples show C programs, since they are most common, but you can use .I make with any programming language whose compiler can be run with a shell command. In fact, .I make is not limited to programs. You can use it to describe any task where some files must be updated automatically from others whenever the others change. .LP To prepare to use .IR make , you must write a file called the .I makefile that describes the relationships among files in your program, and the states the commands for updating each file. In a program, typically the executable file is updated from object files, which are in turn made by compiling source files. .LP Once a suitable makefile exists, each time you change some source files, this simple shell command: .sp 1 .RS .B make .RE .sp 1 suffices to perform all necessary recompilations. The .I make program uses the makefile data base and the last-modification times of the files to decide which of the files need to be updated. For each of those files, it issues the commands recorded in the data base. .LP .I make executes commands in the .I makefile to update one or more target .IR names , where .I name is typically a program. If no .B \-f option is present, .I make will look for the makefiles .IR GNUmakefile , .IR makefile , and .IR Makefile , in that order. .LP Normally you should call your makefile either .I makefile or .IR Makefile . (We recommend .I Makefile because it appears prominently near the beginning of a directory listing, right near other important files such as .IR README .) The first name checked, .IR GNUmakefile , is not recommended for most makefiles. You should use this name if you have a makefile that is specific to GNU .IR make , and will not be understood by other versions of .IR make . If .I makefile is `\-', the standard input is read. .LP .I make updates a target if it depends on prerequisite files that have been modified since the target was last modified, or if the target does not exist. .SH OPTIONS .sp 1 .TP 0.5i .BR \-b , " \-m" These options are ignored for compatibility with other versions of .IR make . .TP 0.5i .BR \-B , " \-\-always\-make" Unconditionally make all targets. .TP 0.5i \fB\-C\fR \fIdir\fR, \fB\-\-directory\fR=\fIdir\fR Change to directory .I dir before reading the makefiles or doing anything else. If multiple .B \-C options are specified, each is interpreted relative to the previous one: .BR "\-C " / .BR "\-C " etc is equivalent to .BR "\-C " /etc. This is typically used with recursive invocations of .IR make . .TP 0.5i .B \-d Print debugging information in addition to normal processing. The debugging information says which files are being considered for remaking, which file-times are being compared and with what results, which files actually need to be remade, which implicit rules are considered and which are applied---everything interesting about how .I make decides what to do. .TP 0.5i .BI \-\-debug "[=FLAGS]" Print debugging information in addition to normal processing. If the .I FLAGS are omitted, then the behavior is the same as if .B \-d was specified. .I FLAGS may be .I a for all debugging output (same as using .BR \-d ), .I b for basic debugging, .I v for more verbose basic debugging, .I i for showing implicit rules, .I j for details on invocation of commands, and .I m for debugging while remaking makefiles. .TP 0.5i .BR \-e , " \-\-environment\-overrides" Give variables taken from the environment precedence over variables from makefiles. .TP 0.5i \fB\-f\fR \fIfile\fR, \fB\-\-file\fR=\fIfile\fR, \fB\-\-makefile\fR=\fIFILE\fR Use .I file as a makefile. .TP 0.5i .BR \-i , " \-\-ignore\-errors" Ignore all errors in commands executed to remake files. .TP 0.5i \fB\-I\fR \fIdir\fR, \fB\-\-include\-dir\fR=\fIdir\fR Specifies a directory .I dir to search for included makefiles. If several .B \-I options are used to specify several directories, the directories are searched in the order specified. Unlike the arguments to other flags of .IR make , directories given with .B \-I flags may come directly after the flag: .BI \-I dir is allowed, as well as .BI "\-I " dir. This syntax is allowed for compatibility with the C preprocessor's .B \-I flag. .TP 0.5i \fB\-j\fR [\fIjobs\fR], \fB\-\-jobs\fR[=\fIjobs\fR] Specifies the number of .I jobs (commands) to run simultaneously. If there is more than one .B \-j option, the last one is effective. If the .B \-j option is given without an argument, .IR make will not limit the number of jobs that can run simultaneously. .TP 0.5i .BR \-k , " \-\-keep\-going" Continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same. .TP 0.5i \fB\-l\fR [\fIload\fR], \fB\-\-load\-average\fR[=\fIload\fR] Specifies that no new jobs (commands) should be started if there are others jobs running and the load average is at least .I load (a floating-point number). With no argument, removes a previous load limit. .TP 0.5i .BR \-L , " \-\-check\-symlink\-times" Use the latest mtime between symlinks and target. .TP 0.5i .BR \-n , " \-\-just\-print" , " \-\-dry\-run" , " \-\-recon" Print the commands that would be executed, but do not execute them (except in certain circumstances). .TP 0.5i \fB\-o\fR \fIfile\fR, \fB\-\-old\-file\fR=\fIfile\fR, \fB\-\-assume\-old\fR=\fIfile\fR Do not remake the file .I file even if it is older than its dependencies, and do not remake anything on account of changes in .IR file . Essentially the file is treated as very old and its rules are ignored. .TP 0.5i .BR \-p , " \-\-print\-data\-base" Print the data base (rules and variable values) that results from reading the makefiles; then execute as usual or as otherwise specified. This also prints the version information given by the .B \-v switch (see below). To print the data base without trying to remake any files, use .B make .B \-p .BI \-f /dev/null. .TP 0.5i .BR \-q , " \-\-question" ``Question mode''. Do not run any commands, or print anything; just return an exit status that is zero if the specified targets are already up to date, nonzero otherwise. .TP 0.5i .BR \-r , " \-\-no\-builtin\-rules" Eliminate use of the built\-in implicit rules. Also clear out the default list of suffixes for suffix rules. .TP 0.5i .BR \-R , " \-\-no\-builtin\-variables" Don't define any built\-in variables. .TP 0.5i .BR \-s , " \-\-silent" , " \-\-quiet" Silent operation; do not print the commands as they are executed. .TP 0.5i .BR \-S , " \-\-no\-keep\-going" , " \-\-stop" Cancel the effect of the .B \-k option. This is never necessary except in a recursive .I make where .B \-k might be inherited from the top-level .I make via MAKEFLAGS or if you set .B \-k in MAKEFLAGS in your environment. .TP 0.5i .BR \-t , " \-\-touch" Touch files (mark them up to date without really changing them) instead of running their commands. This is used to pretend that the commands were done, in order to fool future invocations of .IR make . .TP 0.5i .BR \-v , " \-\-version" Print the version of the .I make program plus a copyright, a list of authors and a notice that there is no warranty. .TP 0.5i .BR \-w , " \-\-print\-directory" Print a message containing the working directory before and after other processing. This may be useful for tracking down errors from complicated nests of recursive .I make commands. .TP 0.5i .B \-\-no\-print\-directory Turn off .BR \-w , even if it was turned on implicitly. .TP 0.5i \fB\-W\fR \fIfile\fR, \fB\-\-what\-if\fR=\fIfile\fR, \fB\-\-new\-file\fR=\fIfile\fR, \fB\-\-assume\-new\fR=\fIfile\fR Pretend that the target .I file has just been modified. When used with the .B \-n flag, this shows you what would happen if you were to modify that file. Without .BR \-n , it is almost the same as running a .I touch command on the given file before running .IR make , except that the modification time is changed only in the imagination of .IR make . .TP 0.5i .B \-\-warn\-undefined\-variables Warn when an undefined variable is referenced. .SH "EXIT STATUS" GNU .I make exits with a status of zero if all makefiles were successfully parsed and no targets that were built failed. A status of one will be returned if the .B \-q flag was used and .I make determines that a target needs to be rebuilt. A status of two will be returned if any errors were encountered. .SH "SEE ALSO" .I "The GNU Make Manual" .SH BUGS See the chapter `Problems and Bugs' in .IR "The GNU Make Manual" . .SH AUTHOR This manual page contributed by Dennis Morse of Stanford University. It has been reworked by Roland McGrath. Further updates contributed by Mike Frysinger. .SH "COPYRIGHT" Copyright (C) 1992, 1993, 1996, 1999, 2007 Free Software Foundation, Inc. This file is part of GNU .IR make . .LP GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. .LP GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. .LP You should have received a copy of the GNU General Public License along with this program. If not, see .IR http://www.gnu.org/licenses/ . kbuild-2695/src/kmk/kbuild.h0000644000000000000000000000423212247157306014435 0ustar rootroot/* $Id: kbuild.h 2549 2011-11-09 01:22:04Z bird $ */ /** @file * kBuild specific make functionality. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifndef ___kBuild_h #define ___kBuild_h char *func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName); char *func_kbuild_object_base(char *o, char **argv, const char *pszFuncName); char *func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName); char *func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName); char *func_kbuild_source_one(char *o, char **argv, const char *pszFuncName); char *func_kbuild_expand_template(char *o, char **argv, const char *pszFuncName); void init_kbuild(int argc, char **argv); const char *get_kbuild_path(void); const char *get_kbuild_bin_path(void); const char *get_default_kbuild_shell(void); struct kbuild_eval_data; extern struct kbuild_eval_data *g_pTopKbDef; struct variable_set *get_top_kbuild_variable_set(void); char *kbuild_prefix_variable(const char *pszName, unsigned int *pcchName); int eval_kbuild_define(struct kbuild_eval_data **kdata, const struct floc *flocp, const char *word, unsigned int wlen, const char *line, const char *eos, int ignoring); int eval_kbuild_endef(struct kbuild_eval_data **kdata, const struct floc *flocp, const char *word, unsigned int wlen, const char *line, const char *eos, int ignoring); void print_kbuild_data_base(void); void print_kbuild_define_stats(void); #endif kbuild-2695/src/kmk/Makefile.ami0000644000000000000000000002411612247157306015222 0ustar rootroot# -*-Makefile-*- for GNU make on Amiga # # NOTE: If you have no `make' program at all to process this makefile, run # `build.sh' instead. # # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # # Makefile for GNU Make # CC = sc RM = delete CFLAGS = CPPFLAGS = LDFLAGS = # Define these for your system as follows: # -DNO_ARCHIVES To disable `ar' archive support. # -DNO_FLOAT To avoid using floating-point numbers. # -DENUM_BITFIELDS If the compiler isn't GCC but groks enum foo:2. # Some compilers apparently accept this # without complaint but produce losing code, # so beware. # NeXT 1.0a uses an old version of GCC, which required -D__inline=inline. # See also `config.h'. defines = # Which flavor of remote job execution support to use. # The code is found in `remote-$(REMOTE).c'. REMOTE = stub # If you are using the GNU C library, or have the GNU getopt functions in # your C library, you can comment these out. GETOPT = getopt.o getopt1.o GETOPT_SRC = $(srcdir)getopt.c $(srcdir)getopt1.c $(srcdir)getopt.h # If you are using the GNU C library, or have the GNU glob functions in # your C library, you can comment this out. GNU make uses special hooks # into the glob functions to be more efficient (by using make's directory # cache for globbing), so you must use the GNU functions even if your # system's C library has the 1003.2 glob functions already. Also, the glob # functions in the AIX and HPUX C libraries are said to be buggy. GLOB = glob/glob.lib # If your system doesn't have alloca, or the one provided is bad, define this. ALLOCA = alloca.o ALLOCA_SRC = $(srcdir)alloca.c # If your system needs extra libraries loaded in, define them here. # System V probably need -lPW for alloca. HP-UX 7.0's alloca in # libPW.a is broken on HP9000s300 and HP9000s400 machines. Use # alloca.c instead on those machines. LOADLIBES = # Any extra object files your system needs. extras = amiga.o # Common prefix for machine-independent installed files. prefix = # Common prefix for machine-dependent installed files. exec_prefix = # Directory to install `make' in. bindir = sc:c # Directory to find libraries in for `-lXXX'. libdir = lib: # Directory to search by default for included makefiles. includedir = include: # Directory to install the Info files in. infodir = doc: # Directory to install the man page in. mandir = t: # Number to put on the man page filename. manext = 1 # Prefix to put on installed `make' binary file name. binprefix = # Prefix to put on installed `make' man page file name. manprefix = $(binprefix) # Whether or not make needs to be installed setgid. # The value should be either `true' or `false'. # On many systems, the getloadavg function (used to implement the `-l' # switch) will not work unless make is installed setgid kmem. install_setgid = false # Install make setgid to this group so it can read /dev/kmem. group = sys # Program to install `make'. INSTALL_PROGRAM = copy # Program to install the man page. INSTALL_DATA = copy # Generic install program. INSTALL = copy # Program to format Texinfo source into Info files. MAKEINFO = makeinfo # Program to format Texinfo source into DVI files. TEXI2DVI = texi2dvi # Programs to make tags files. ETAGS = etags -w CTAGS = ctags -w objs = commands.o job.o dir.o file.o misc.o main.o read.o remake.o \ rule.o implicit.o default.o variable.o expand.o function.o \ vpath.o version.o ar.o arscan.o signame.o strcache.o hash.o \ remote-$(REMOTE).o $(GETOPT) $(ALLOCA) $(extras) srcs = $(srcdir)commands.c $(srcdir)job.c $(srcdir)dir.c \ $(srcdir)file.c $(srcdir)getloadavg.c $(srcdir)misc.c \ $(srcdir)main.c $(srcdir)read.c $(srcdir)remake.c \ $(srcdir)rule.c $(srcdir)implicit.c $(srcdir)default.c \ $(srcdir)variable.c $(srcdir)expand.c $(srcdir)function.c \ $(srcdir)vpath.c $(srcdir)version.c $(srcdir)hash.c \ $(srcdir)remote-$(REMOTE).c \ $(srcdir)ar.c $(srcdir)arscan.c $(srcdir)strcache.c \ $(srcdir)signame.c $(srcdir)signame.h $(GETOPT_SRC) \ $(srcdir)commands.h $(srcdir)dep.h $(srcdir)filedep.h \ $(srcdir)job.h $(srcdir)make.h $(srcdir)rule.h \ $(srcdir)variable.h $(ALLOCA_SRC) $(srcdir)config.h.in .SUFFIXES: .SUFFIXES: .o .c .h .ps .dvi .info .texinfo all: make info: make.info dvi: make.dvi # Some makes apparently use .PHONY as the default goal if it is before `all'. .PHONY: all check info dvi make.info: make.texinfo $(MAKEINFO) -I$(srcdir) $(srcdir)make.texinfo -o make.info make.dvi: make.texinfo $(TEXI2DVI) $(srcdir)make.texinfo make.ps: make.dvi dvi2ps make.dvi > make.ps make: $(objs) $(GLOB) $(CC) Link $(LDFLAGS) $(objs) Lib $(GLOB) $(LOADLIBES) To make.new -delete make rename make.new make TMPFILE = t:Make$$ $(GLOB): cd glob @@\ $(MAKE) -$(MAKEFLAGS) -f Makefile # -I. is needed to find config.h in the build directory. OUTPUT_OPTION = .c.o: $(CC) $(defines) IDir "" IDir glob \ $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) # For some losing Unix makes. SHELL = /bin/sh #@SET_MAKE@ glob/libglob.a: FORCE config.h cd glob; $(MAKE) libglob.a FORCE: tagsrcs = $(srcs) $(srcdir)remote-*.c .PHONY: install installdirs install: installdirs \ $(bindir)$(binprefix)make $(infodir)make.info \ $(mandir)$(manprefix)make.$(manext) installdirs: $(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(infodir) $(mandir) $(bindir)$(binprefix)make: make $(INSTALL_PROGRAM) make $@.new @if $(install_setgid); then \ if chgrp $(group) $@.new && chmod g+s $@.new; then \ echo "chgrp $(group) $@.new && chmod g+s $@.new"; \ else \ echo "$@ needs to be owned by group $(group) and setgid;"; \ echo "otherwise the \`-l' option will probably not work."; \ echo "You may need special privileges to install $@."; \ fi; \ else true; fi # Some systems can't deal with renaming onto a running binary. -$(RM) $@.old -mv $@ $@.old mv $@.new $@ $(infodir)make.info: make.info if [ -r ./make.info ]; then dir=.; else dir=$(srcdir); fi; \ for file in $${dir}/make.info*; do \ name="`basename $$file`"; \ $(INSTALL_DATA) $$file \ `echo $@ | sed "s,make.info\$$,$$name,"`; \ done # Run install-info only if it exists. # Use `if' instead of just prepending `-' to the # line so we notice real errors from install-info. # We use `$(SHELL) -c' because some shells do not # fail gracefully when there is an unknown command. if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \ if [ -r ./make.info ]; then dir=.; else dir=$(srcdir); fi; \ install-info --infodir=$(infodir) $$dir/make.info; \ else true; fi $(mandir)$(manprefix)make.$(manext): make.man $(INSTALL_DATA) $(srcdir)make.man $@ loadavg: loadavg.c config.h $(CC) $(defines) -DTEST -I. -I$(srcdir) $(CFLAGS) $(LDFLAGS) \ loadavg.c $(LOADLIBES) -o $@ # We copy getloadavg.c into a different file rather than compiling it # directly because some compilers clobber getloadavg.o in the process. loadavg.c: getloadavg.c ln $(srcdir)getloadavg.c loadavg.c || \ cp $(srcdir)getloadavg.c loadavg.c check-loadavg: loadavg @echo The system uptime program believes the load average to be: -uptime @echo The GNU load average checking code believes: ./loadavg check: check-loadavg .PHONY: clean realclean distclean mostlyclean clean: glob-clean -$(RM) make loadavg "#?.o" core make.dvi distclean: clean glob-realclean -$(RM) Makefile config.h config.status build.sh -$(RM) config.log config.cache -$(RM) TAGS tags -$(RM) make.?? make.??s make.log make.toc make.*aux -$(RM) loadavg.c realclean: distclean -$(RM) make.info* mostlyclean: clean .PHONY: glob-clean glob-realclean glob-clean glob-realclean: cd glob @@\ $(MAKE) $@ # This tells versions [3.59,3.63) of GNU make not to export all variables. .NOEXPORT: # The automatically generated dependencies below may omit config.h # because it is included with ``#include '' rather than # ``#include "config.h"''. So we add the explicit dependency to make sure. $(objs): config.h # Automatically generated dependencies will be put at the end of the file. # Automatically generated dependencies. commands.o: commands.c make.h dep.h filedef.h variable.h job.h \ commands.h job.o: job.c make.h job.h filedef.h commands.h variable.h dir.o: dir.c make.h file.o: file.c make.h dep.h filedef.h job.h commands.h variable.h misc.o: misc.c make.h dep.h main.o: main.c make.h dep.h filedef.h variable.h job.h commands.h \ getopt.h read.o: read.c make.h dep.h filedef.h job.h commands.h variable.h \ glob/glob.h remake.o: remake.c make.h filedef.h job.h commands.h dep.h rule.o: rule.c make.h dep.h filedef.h job.h commands.h variable.h \ rule.h implicit.o: implicit.c make.h rule.h dep.h filedef.h default.o: default.c make.h rule.h dep.h filedef.h job.h commands.h \ variable.h variable.o: variable.c make.h dep.h filedef.h job.h commands.h \ variable.h expand.o: expand.c make.h filedef.h job.h commands.h variable.h function.o: function.c make.h filedef.h variable.h dep.h job.h \ commands.h amiga.h vpath.o: vpath.c make.h filedef.h variable.h strcache.o: strcache.c make.h hash.h version.o: version.c ar.o: ar.c make.h filedef.h dep.h arscan.o: arscan.c make.h signame.o: signame.c signame.h remote-stub.o: remote-stub.c make.h filedef.h job.h commands.h getopt.o: getopt.c getopt1.o : getopt1.c getopt.h getloadavg.o: getloadavg.c amiga.o: amiga.c make.h variable.h amiga.h kbuild-2695/src/kmk/NMakefile.template0000644000000000000000000000764412247157306016414 0ustar rootroot# -*-Makefile-*- to build GNU make with nmake # # NOTE: If you have no 'make' program at all to process this makefile, # run 'build_w32.bat' instead. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . LINK = link CC = cl MAKE = nmake OUTDIR=. MAKEFILE=NMakefile SUBPROC_MAKEFILE=NMakefile CFLAGS_any = /nologo /MT /W4 /GX /Zi /YX /I . /I glob /I w32/include /D WIN32 /D WINDOWS32 /D _CONSOLE /D HAVE_CONFIG_H CFLAGS_debug = $(CFLAGS_any) /Od /D DEBUG /D _DEBUG /FR.\WinDebug/ /Fp.\WinDebug/make.pch /Fo.\WinDebug/ /Fd.\WinDebug/make.pdb CFLAGS_release = $(CFLAGS_any) /O2 /D NDEBUG /FR.\WinRel/ /Fp.\WinRel/make.pch /Fo.\WinRel/ LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\ /INCREMENTAL:no /PDB:WinDebug/make.pdb /OUT:WinDebug/make.exe /DEBUG LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\ /INCREMENTAL:no /OUT:WinRel/make.exe all: config.h subproc Release Debug # # Make sure we build the subproc library first. It has it's own # makefile. To be portable to Windows 95, we put the instructions # on how to build the library into a batch file. On NT, we could # simply have done foo && bar && dog, but this doesn't port. # subproc: w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib: w32/subproc/misc.c w32/subproc/sub_proc.c w32/subproc/w32err.c subproc.bat $(SUBPROC_MAKEFILE) $(MAKE) if exist WinDebug\make.exe erase WinDebug\make.exe if exist WinRel\make.exe erase WinRel\make.exe config.h: config.h.W32 copy $? $@ Release: $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_release)" CFLAGS="$(CFLAGS_release)" OUTDIR=WinRel WinRel/make.exe Debug: $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_debug)" CFLAGS="$(CFLAGS_debug)" OUTDIR=WinDebug WinDebug/make.exe clean: if exist WinDebug\nul rmdir /s /q WinDebug if exist WinRel\nul rmdir /s /q WinRel if exist w32\subproc\WinDebug\nul rmdir /s /q w32\subproc\WinDebug if exist w32\subproc\WinRel\nul rmdir /s /q w32\subproc\WinRel if exist config.h erase config.h erase *.pdb $(OUTDIR): if not exist .\$@\nul mkdir .\$@ LIBS = kernel32.lib user32.lib advapi32.lib OBJS = \ $(OUTDIR)/ar.obj \ $(OUTDIR)/arscan.obj \ $(OUTDIR)/commands.obj \ $(OUTDIR)/default.obj \ $(OUTDIR)/dir.obj \ $(OUTDIR)/expand.obj \ $(OUTDIR)/file.obj \ $(OUTDIR)/function.obj \ $(OUTDIR)/getloadavg.obj \ $(OUTDIR)/getopt.obj \ $(OUTDIR)/getopt1.obj \ $(OUTDIR)/hash.obj \ $(OUTDIR)/implicit.obj \ $(OUTDIR)/job.obj \ $(OUTDIR)/main.obj \ $(OUTDIR)/misc.obj \ $(OUTDIR)/read.obj \ $(OUTDIR)/remake.obj \ $(OUTDIR)/remote-stub.obj \ $(OUTDIR)/rule.obj \ $(OUTDIR)/signame.obj \ $(OUTDIR)/strcache.obj \ $(OUTDIR)/variable.obj \ $(OUTDIR)/version.obj \ $(OUTDIR)/vpath.obj \ $(OUTDIR)/glob.obj \ $(OUTDIR)/fnmatch.obj \ $(OUTDIR)/dirent.obj \ $(OUTDIR)/pathstuff.obj $(OUTDIR)/make.exe: $(OUTDIR) $(OBJS) $(LINK) @<< $(LDFLAGS) $(LIBS) $(OBJS) << .c{$(OUTDIR)}.obj: $(CC) $(CFLAGS) /c $< $(OUTDIR)/glob.obj : glob/glob.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/fnmatch.obj : glob/fnmatch.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/dirent.obj : w32/compat/dirent.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/pathstuff.obj : w32/pathstuff.c $(CC) $(CFLAGS) /c $? kbuild-2695/src/kmk/alloca.c0000644000000000000000000003362712247157306014423 0ustar rootroot/* alloca.c -- allocate automatically reclaimed memory (Mostly) portable public-domain implementation -- D A Gwyn This implementation of the PWB library alloca function, which is used to allocate space off the run-time stack so that it is automatically reclaimed upon procedure exit, was inspired by discussions with J. Q. Johnson of Cornell. J.Otto Tennant contributed the Cray support. There are some preprocessor constants that can be defined when compiling for your specific system, for improved efficiency; however, the defaults should be okay. The general concept of this implementation is to keep track of all alloca-allocated blocks, and reclaim any that are found to be deeper in the stack than the current invocation. This heuristic does not reclaim storage as soon as it becomes invalid, but it will do so eventually. As a special case, alloca(0) reclaims storage without allocating any. It is a good idea to use alloca(0) in your main control loop, etc. to force garbage collection. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef emacs #include "blockinput.h" #endif /* If compiling with GCC 2, this file's not needed. */ #if !defined (__GNUC__) || __GNUC__ < 2 /* If someone has defined alloca as a macro, there must be some other way alloca is supposed to work. */ #ifndef alloca #ifdef emacs #ifdef static /* actually, only want this if static is defined as "" -- this is for usg, in which emacs must undefine static in order to make unexec workable */ #ifndef STACK_DIRECTION you lose -- must know STACK_DIRECTION at compile-time #endif /* STACK_DIRECTION undefined */ #endif /* static */ #endif /* emacs */ /* If your stack is a linked list of frames, you have to provide an "address metric" ADDRESS_FUNCTION macro. */ #if defined (CRAY) && defined (CRAY_STACKSEG_END) long i00afunc (); #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) #else #define ADDRESS_FUNCTION(arg) &(arg) #endif #if __STDC__ typedef void *pointer; #else typedef char *pointer; #endif #ifndef NULL #define NULL 0 #endif /* Different portions of Emacs need to call different versions of malloc. The Emacs executable needs alloca to call xmalloc, because ordinary malloc isn't protected from input signals. On the other hand, the utilities in lib-src need alloca to call malloc; some of them are very simple, and don't have an xmalloc routine. Non-Emacs programs expect this to call use xmalloc. Callers below should use malloc. */ #ifndef emacs #define malloc xmalloc #endif extern pointer malloc (); /* Define STACK_DIRECTION if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #ifndef STACK_DIRECTION #define STACK_DIRECTION 0 /* Direction unknown. */ #endif #if STACK_DIRECTION != 0 #define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ #else /* STACK_DIRECTION == 0; need run-time code. */ static int stack_dir; /* 1 or -1 once known. */ #define STACK_DIR stack_dir static void find_stack_direction (void) { static char *addr = NULL; /* Address of first `dummy', once known. */ auto char dummy; /* To get stack address. */ if (addr == NULL) { /* Initial entry. */ addr = ADDRESS_FUNCTION (dummy); find_stack_direction (); /* Recurse once. */ } else { /* Second entry. */ if (ADDRESS_FUNCTION (dummy) > addr) stack_dir = 1; /* Stack grew upward. */ else stack_dir = -1; /* Stack grew downward. */ } } #endif /* STACK_DIRECTION == 0 */ /* An "alloca header" is used to: (a) chain together all alloca'ed blocks; (b) keep track of stack depth. It is very important that sizeof(header) agree with malloc alignment chunk size. The following default should work okay. */ #ifndef ALIGN_SIZE #define ALIGN_SIZE sizeof(double) #endif typedef union hdr { char align[ALIGN_SIZE]; /* To force sizeof(header). */ struct { union hdr *next; /* For chaining headers. */ char *deep; /* For stack depth measure. */ } h; } header; static header *last_alloca_header = NULL; /* -> last alloca header. */ /* Return a pointer to at least SIZE bytes of storage, which will be automatically reclaimed upon exit from the procedure that called alloca. Originally, this space was supposed to be taken from the current stack frame of the caller, but that method cannot be made to work for some implementations of C, for example under Gould's UTX/32. */ pointer alloca (unsigned size) { auto char probe; /* Probes stack depth: */ register char *depth = ADDRESS_FUNCTION (probe); #if STACK_DIRECTION == 0 if (STACK_DIR == 0) /* Unknown growth direction. */ find_stack_direction (); #endif /* Reclaim garbage, defined as all alloca'd storage that was allocated from deeper in the stack than currently. */ { register header *hp; /* Traverses linked list. */ #ifdef emacs BLOCK_INPUT; #endif for (hp = last_alloca_header; hp != NULL;) if ((STACK_DIR > 0 && hp->h.deep > depth) || (STACK_DIR < 0 && hp->h.deep < depth)) { register header *np = hp->h.next; free ((pointer) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ last_alloca_header = hp; /* -> last valid storage. */ #ifdef emacs UNBLOCK_INPUT; #endif } if (size == 0) return NULL; /* No allocation required. */ /* Allocate combined header + user data storage. */ { register pointer new = malloc (sizeof (header) + size); /* Address of header. */ if (new == 0) abort(); ((header *) new)->h.next = last_alloca_header; ((header *) new)->h.deep = depth; last_alloca_header = (header *) new; /* User storage begins just after header. */ return (pointer) ((char *) new + sizeof (header)); } } #if defined (CRAY) && defined (CRAY_STACKSEG_END) #ifdef DEBUG_I00AFUNC #include #endif #ifndef CRAY_STACK #define CRAY_STACK #ifndef CRAY2 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ struct stack_control_header { long shgrow:32; /* Number of times stack has grown. */ long shaseg:32; /* Size of increments to stack. */ long shhwm:32; /* High water mark of stack. */ long shsize:32; /* Current size of stack (all segments). */ }; /* The stack segment linkage control information occurs at the high-address end of a stack segment. (The stack grows from low addresses to high addresses.) The initial part of the stack segment linkage control information is 0200 (octal) words. This provides for register storage for the routine which overflows the stack. */ struct stack_segment_linkage { long ss[0200]; /* 0200 overflow words. */ long sssize:32; /* Number of words in this segment. */ long ssbase:32; /* Offset to stack base. */ long:32; long sspseg:32; /* Offset to linkage control of previous segment of stack. */ long:32; long sstcpt:32; /* Pointer to task common address block. */ long sscsnm; /* Private control structure number for microtasking. */ long ssusr1; /* Reserved for user. */ long ssusr2; /* Reserved for user. */ long sstpid; /* Process ID for pid based multi-tasking. */ long ssgvup; /* Pointer to multitasking thread giveup. */ long sscray[7]; /* Reserved for Cray Research. */ long ssa0; long ssa1; long ssa2; long ssa3; long ssa4; long ssa5; long ssa6; long ssa7; long sss0; long sss1; long sss2; long sss3; long sss4; long sss5; long sss6; long sss7; }; #else /* CRAY2 */ /* The following structure defines the vector of words returned by the STKSTAT library routine. */ struct stk_stat { long now; /* Current total stack size. */ long maxc; /* Amount of contiguous space which would be required to satisfy the maximum stack demand to date. */ long high_water; /* Stack high-water mark. */ long overflows; /* Number of stack overflow ($STKOFEN) calls. */ long hits; /* Number of internal buffer hits. */ long extends; /* Number of block extensions. */ long stko_mallocs; /* Block allocations by $STKOFEN. */ long underflows; /* Number of stack underflow calls ($STKRETN). */ long stko_free; /* Number of deallocations by $STKRETN. */ long stkm_free; /* Number of deallocations by $STKMRET. */ long segments; /* Current number of stack segments. */ long maxs; /* Maximum number of stack segments so far. */ long pad_size; /* Stack pad size. */ long current_address; /* Current stack segment address. */ long current_size; /* Current stack segment size. This number is actually corrupted by STKSTAT to include the fifteen word trailer area. */ long initial_address; /* Address of initial segment. */ long initial_size; /* Size of initial segment. */ }; /* The following structure describes the data structure which trails any stack segment. I think that the description in 'asdef' is out of date. I only describe the parts that I am sure about. */ struct stk_trailer { long this_address; /* Address of this block. */ long this_size; /* Size of this block (does not include this trailer). */ long unknown2; long unknown3; long link; /* Address of trailer block of previous segment. */ long unknown5; long unknown6; long unknown7; long unknown8; long unknown9; long unknown10; long unknown11; long unknown12; long unknown13; long unknown14; }; #endif /* CRAY2 */ #endif /* not CRAY_STACK */ #ifdef CRAY2 /* Determine a "stack measure" for an arbitrary ADDRESS. I doubt that "lint" will like this much. */ static long i00afunc (long *address) { struct stk_stat status; struct stk_trailer *trailer; long *block, size; long result = 0; /* We want to iterate through all of the segments. The first step is to get the stack status structure. We could do this more quickly and more directly, perhaps, by referencing the $LM00 common block, but I know that this works. */ STKSTAT (&status); /* Set up the iteration. */ trailer = (struct stk_trailer *) (status.current_address + status.current_size - 15); /* There must be at least one stack segment. Therefore it is a fatal error if "trailer" is null. */ if (trailer == 0) abort (); /* Discard segments that do not contain our argument address. */ while (trailer != 0) { block = (long *) trailer->this_address; size = trailer->this_size; if (block == 0 || size == 0) abort (); trailer = (struct stk_trailer *) trailer->link; if ((block <= address) && (address < (block + size))) break; } /* Set the result to the offset in this segment and add the sizes of all predecessor segments. */ result = address - block; if (trailer == 0) { return result; } do { if (trailer->this_size <= 0) abort (); result += trailer->this_size; trailer = (struct stk_trailer *) trailer->link; } while (trailer != 0); /* We are done. Note that if you present a bogus address (one not in any segment), you will get a different number back, formed from subtracting the address of the first block. This is probably not what you want. */ return (result); } #else /* not CRAY2 */ /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. Determine the number of the cell within the stack, given the address of the cell. The purpose of this routine is to linearize, in some sense, stack addresses for alloca. */ static long i00afunc (long address) { long stkl = 0; long size, pseg, this_segment, stack; long result = 0; struct stack_segment_linkage *ssptr; /* Register B67 contains the address of the end of the current stack segment. If you (as a subprogram) store your registers on the stack and find that you are past the contents of B67, you have overflowed the segment. B67 also points to the stack segment linkage control area, which is what we are really interested in. */ stkl = CRAY_STACKSEG_END (); ssptr = (struct stack_segment_linkage *) stkl; /* If one subtracts 'size' from the end of the segment, one has the address of the first word of the segment. If this is not the first segment, 'pseg' will be nonzero. */ pseg = ssptr->sspseg; size = ssptr->sssize; this_segment = stkl - size; /* It is possible that calling this routine itself caused a stack overflow. Discard stack segments which do not contain the target address. */ while (!(this_segment <= address && address <= stkl)) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); #endif if (pseg == 0) break; stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; this_segment = stkl - size; } result = address - this_segment; /* If you subtract pseg from the current end of the stack, you get the address of the previous stack segment's end. This seems a little convoluted to me, but I'll bet you save a cycle somewhere. */ while (pseg != 0) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o\n", pseg, size); #endif stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; result += size; } return (result); } #endif /* not CRAY2 */ #endif /* CRAY */ #endif /* no alloca */ #endif /* not GCC version 2 */ kbuild-2695/src/kmk/read.c0000644000000000000000000034204212247157306014075 0ustar rootroot/* Reading and parsing of makefiles for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include #include #include "dep.h" #include "filedef.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" #include "debug.h" #include "hash.h" #ifdef KMK # include "kbuild.h" #endif #ifndef WINDOWS32 #ifndef _AMIGA #ifndef VMS #include #else struct passwd *getpwnam (char *name); #endif #endif #endif /* !WINDOWS32 */ /* A 'struct ebuffer' controls the origin of the makefile we are currently eval'ing. */ struct ebuffer { char *buffer; /* Start of the current line in the buffer. */ char *bufnext; /* Start of the next line in the buffer. */ char *bufstart; /* Start of the entire buffer. */ #ifdef CONFIG_WITH_VALUE_LENGTH char *eol; /* End of the current line in the buffer. */ #endif unsigned int size; /* Malloc'd size of buffer. */ FILE *fp; /* File, or NULL if this is an internal buffer. */ struct floc floc; /* Info on the file in fp (if any). */ }; /* Track the modifiers we can have on variable assignments */ struct vmodifiers { unsigned int assign_v:1; unsigned int define_v:1; unsigned int undefine_v:1; unsigned int export_v:1; unsigned int override_v:1; unsigned int private_v:1; }; /* Types of "words" that can be read in a makefile. */ enum make_word_type { w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon, w_varassign }; /* A `struct conditionals' contains the information describing all the active conditionals in a makefile. The global variable `conditionals' contains the conditionals information for the current makefile. It is initialized from the static structure `toplevel_conditionals' and is later changed to new structures for included makefiles. */ struct conditionals { unsigned int if_cmds; /* Depth of conditional nesting. */ unsigned int allocated; /* Elts allocated in following arrays. */ char *ignoring; /* Are we ignoring or interpreting? 0=interpreting, 1=not yet interpreted, 2=already interpreted */ char *seen_else; /* Have we already seen an `else'? */ #ifdef KMK char ignoring_first[8]; char seen_else_first[8]; #endif }; #ifdef KMK static struct conditionals toplevel_conditionals = { 0, sizeof (toplevel_conditionals.ignoring_first), &toplevel_conditionals.ignoring_first[0], &toplevel_conditionals.seen_else_first[0], "", "" }; #else /* !KMK */ static struct conditionals toplevel_conditionals; #endif /* !KMK */ static struct conditionals *conditionals = &toplevel_conditionals; /* Default directories to search for include files in */ static const char *default_include_directories[] = { #ifndef KMK #if defined(WINDOWS32) && !defined(INCLUDEDIR) /* This completely up to the user when they install MSVC or other packages. This is defined as a placeholder. */ # define INCLUDEDIR "." #endif # ifdef INCLUDEDIR /* bird */ INCLUDEDIR, # else /* bird */ ".", /* bird */ # endif /* bird */ #ifndef _AMIGA "/usr/gnu/include", "/usr/local/include", "/usr/include", #endif #endif /* !KMK */ 0 }; /* List of directories to search for include files in */ static const char **include_directories; /* Maximum length of an element of the above. */ static unsigned int max_incl_len; /* The filename and pointer to line number of the makefile currently being read in. */ const struct floc *reading_file = 0; /* The chain of makefiles read by read_makefile. */ static struct dep *read_makefiles = 0; static int eval_makefile (const char *filename, int flags); static void eval (struct ebuffer *buffer, int flags); static long readline (struct ebuffer *ebuf); static void do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf); static struct variable *do_define (char *name IF_WITH_VALUE_LENGTH_PARAM(char *eos), enum variable_origin origin, struct ebuffer *ebuf); #ifndef CONFIG_WITH_VALUE_LENGTH static int conditional_line (char *line, int len, const struct floc *flocp); #else static int conditional_line (char *line, char *eol, int len, const struct floc *flocp); #endif static void record_files (struct nameseq *filenames, const char *pattern, const char *pattern_percent, char *depstr, unsigned int cmds_started, char *commands, unsigned int commands_idx, int two_colon, const struct floc *flocp); static void record_target_var (struct nameseq *filenames, char *defn, enum variable_origin origin, struct vmodifiers *vmod, const struct floc *flocp); static enum make_word_type get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length); #ifndef CONFIG_WITH_VALUE_LENGTH static void remove_comments (char *line); static char *find_char_unquote (char *string, int stop1, int stop2, int blank, int ignorevars); #else /* CONFIG_WITH_VALUE_LENGTH */ __inline static char *remove_comments (char *line, char *eol); __inline static char *find_char_unquote_0 (char *string, int stop1, char **eosp); static char * find_char_unquote_2 (char *string, int stop1, int stop2, int blank, int ignorevars, unsigned int string_len); MY_INLINE char * find_char_unquote (char *string, int stop1, int stop2, int blank, int ignorevars) { if (!stop2 && !blank && !ignorevars) { char *p = strchr (string, stop1); if (!p) return NULL; if (p <= string || p[-1] != '\\') return p; /* fall back on find_char_unquote_2 */ } return find_char_unquote_2 (string, stop1, stop2, blank, ignorevars, 0); } #endif /* CONFIG_WITH_VALUE_LENGTH */ /* Compare a word, both length and contents. P must point to the word to be tested, and WLEN must be the length. */ #define word1eq(s) (wlen == sizeof(s)-1 && strneq (s, p, sizeof(s)-1)) /* Read in all the makefiles and return the chain of their names. */ struct dep * read_all_makefiles (const char **makefiles) { unsigned int num_makefiles = 0; /* Create *_LIST variables, to hold the makefiles, targets, and variables we will be reading. */ define_variable_cname ("MAKEFILE_LIST", "", o_file, 0); DB (DB_BASIC, (_("Reading makefiles...\n"))); /* If there's a non-null variable MAKEFILES, its value is a list of files to read first thing. But don't let it prevent reading the default makefiles and don't let the default goal come from there. */ { char *value; char *name, *p; unsigned int length; { /* Turn off --warn-undefined-variables while we expand MAKEFILES. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; #ifndef CONFIG_WITH_VALUE_LENGTH value = allocated_variable_expand ("$(MAKEFILES)"); #else value = allocated_variable_expand_2 (STRING_SIZE_TUPLE("$(MAKEFILES)"), NULL); #endif warn_undefined_variables_flag = save; } /* Set NAME to the start of next token and LENGTH to its length. MAKEFILES is updated for finding remaining tokens. */ p = value; while ((name = find_next_token ((const char **)&p, &length)) != 0) { if (*p != '\0') *p++ = '\0'; eval_makefile (name, RM_NO_DEFAULT_GOAL|RM_INCLUDED|RM_DONTCARE); } free (value); } /* Read makefiles specified with -f switches. */ if (makefiles != 0) while (*makefiles != 0) { struct dep *tail = read_makefiles; register struct dep *d; if (! eval_makefile (*makefiles, 0)) perror_with_name ("", *makefiles); /* Find the right element of read_makefiles. */ d = read_makefiles; while (d->next != tail) d = d->next; /* Use the storage read_makefile allocates. */ *makefiles = dep_name (d); ++num_makefiles; ++makefiles; } /* If there were no -f switches, try the default names. */ if (num_makefiles == 0) { static char *default_makefiles[] = #ifdef VMS /* all lower case since readdir() (the vms version) 'lowercasifies' */ # ifdef KMK { "makefile.kmk", "makefile.vms", "gnumakefile.", "makefile.", 0 }; # else { "makefile.vms", "gnumakefile.", "makefile.", 0 }; # endif #else #ifdef _AMIGA /* what's the deal here? no dots? */ # ifdef KMK { "Makefile.kmk", "makefile.kmk", "GNUmakefile", "Makefile", "SMakefile", 0 }; # else { "GNUmakefile", "Makefile", "SMakefile", 0 }; # endif #else /* !Amiga && !VMS */ # ifdef KMK { "Makefile.kmk", "makefile.kmk", "GNUmakefile", "makefile", "Makefile", 0 }; # else { "GNUmakefile", "makefile", "Makefile", 0 }; # endif #endif /* AMIGA */ #endif /* VMS */ register char **p = default_makefiles; while (*p != 0 && !file_exists_p (*p)) ++p; if (*p != 0) { if (! eval_makefile (*p, 0)) perror_with_name ("", *p); } else { /* No default makefile was found. Add the default makefiles to the `read_makefiles' chain so they will be updated if possible. */ struct dep *tail = read_makefiles; /* Add them to the tail, after any MAKEFILES variable makefiles. */ while (tail != 0 && tail->next != 0) tail = tail->next; for (p = default_makefiles; *p != 0; ++p) { struct dep *d = alloc_dep (); d->file = enter_file (strcache_add (*p)); d->dontcare = 1; /* Tell update_goal_chain to bail out as soon as this file is made, and main not to die if we can't make this file. */ d->changed = RM_DONTCARE; if (tail == 0) read_makefiles = d; else tail->next = d; tail = d; } if (tail != 0) tail->next = 0; } } return read_makefiles; } /* Install a new conditional and return the previous one. */ static struct conditionals * install_conditionals (struct conditionals *new) { struct conditionals *save = conditionals; #ifndef KMK memset (new, '\0', sizeof (*new)); #else /* KMK */ new->if_cmds = 0; new->allocated = sizeof (new->ignoring_first); new->ignoring = new->ignoring_first; new->seen_else = new->seen_else_first; #endif /* KMK */ conditionals = new; return save; } /* Free the current conditionals and reinstate a saved one. */ static void restore_conditionals (struct conditionals *saved) { /* Free any space allocated by conditional_line. */ #ifdef KMK if (conditionals->allocated > sizeof (conditionals->ignoring_first)) #endif { if (conditionals->ignoring) free (conditionals->ignoring); if (conditionals->seen_else) free (conditionals->seen_else); } /* Restore state. */ conditionals = saved; } static int eval_makefile (const char *filename, int flags) { struct dep *deps; struct ebuffer ebuf; const struct floc *curfile; char *expanded = 0; int makefile_errno; filename = strcache_add (filename); ebuf.floc.filenm = filename; ebuf.floc.lineno = 1; if (ISDB (DB_VERBOSE)) { printf (_("Reading makefile `%s'"), filename); if (flags & RM_NO_DEFAULT_GOAL) printf (_(" (no default goal)")); if (flags & RM_INCLUDED) printf (_(" (search path)")); if (flags & RM_DONTCARE) printf (_(" (don't care)")); if (flags & RM_NO_TILDE) printf (_(" (no ~ expansion)")); puts ("..."); } /* First, get a stream to read. */ /* Expand ~ in FILENAME unless it came from `include', in which case it was already done. */ if (!(flags & RM_NO_TILDE) && filename[0] == '~') { expanded = tilde_expand (filename); if (expanded != 0) filename = expanded; } ebuf.fp = fopen (filename, "r"); /* Save the error code so we print the right message later. */ makefile_errno = errno; /* If the makefile wasn't found and it's either a makefile from the `MAKEFILES' variable or an included makefile, search the included makefile search path for this makefile. */ if (ebuf.fp == 0 && (flags & RM_INCLUDED) && *filename != '/') { unsigned int i; for (i = 0; include_directories[i] != 0; ++i) { const char *included = concat (3, include_directories[i], "/", filename); ebuf.fp = fopen (included, "r"); if (ebuf.fp) { filename = strcache_add (included); break; } } } /* Add FILENAME to the chain of read makefiles. */ deps = alloc_dep (); deps->next = read_makefiles; read_makefiles = deps; #ifndef CONFIG_WITH_STRCACHE2 deps->file = lookup_file (filename); #else deps->file = lookup_file_cached (filename); #endif if (deps->file == 0) deps->file = enter_file (filename); filename = deps->file->name; deps->changed = flags; if (flags & RM_DONTCARE) deps->dontcare = 1; if (expanded) free (expanded); /* If the makefile can't be found at all, give up entirely. */ if (ebuf.fp == 0) { /* If we did some searching, errno has the error from the last attempt, rather from FILENAME itself. Restore it in case the caller wants to use it in a message. */ errno = makefile_errno; return 0; } /* Set close-on-exec to avoid leaking the makefile to children, such as $(shell ...). */ #ifdef HAVE_FILENO CLOSE_ON_EXEC (fileno (ebuf.fp)); #endif /* Add this makefile to the list. */ do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file, f_append, 0); #ifdef KMK /* Buffer the entire file or at least 256KB (footer.kmk) of it. */ { void *stream_buf = NULL; struct stat st; if (!fstat (fileno (ebuf.fp), &st)) { int stream_buf_size = 256*1024; if (st.st_size < stream_buf_size) { if (st.st_size) stream_buf_size = (st.st_size + 0xfff) & ~0xfff; else stream_buf_size = 0x1000; } stream_buf = xmalloc (stream_buf_size); setvbuf (ebuf.fp, stream_buf, _IOFBF, stream_buf_size); } #endif /* Evaluate the makefile */ ebuf.size = 200; ebuf.buffer = ebuf.bufnext = ebuf.bufstart = xmalloc (ebuf.size); #ifdef CONFIG_WITH_VALUE_LENGTH ebuf.eol = NULL; #endif curfile = reading_file; reading_file = &ebuf.floc; eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL)); reading_file = curfile; fclose (ebuf.fp); #ifdef KMK if (stream_buf) free (stream_buf); } #endif free (ebuf.bufstart); alloca (0); return 1; } void #ifndef CONFIG_WITH_VALUE_LENGTH eval_buffer (char *buffer) #else eval_buffer (char *buffer, char *eos) #endif { struct ebuffer ebuf; struct conditionals *saved; struct conditionals new; const struct floc *curfile; /* Evaluate the buffer */ #ifndef CONFIG_WITH_VALUE_LENGTH ebuf.size = strlen (buffer); #else ebuf.size = eos - buffer; ebuf.eol = eos; assert(strchr(buffer, '\0') == eos); #endif ebuf.buffer = ebuf.bufnext = ebuf.bufstart = buffer; ebuf.fp = NULL; if (reading_file) ebuf.floc = *reading_file; else ebuf.floc.filenm = NULL; curfile = reading_file; reading_file = &ebuf.floc; saved = install_conditionals (&new); eval (&ebuf, 1); restore_conditionals (saved); reading_file = curfile; alloca (0); } /* Check LINE to see if it's a variable assignment or undefine. It might use one of the modifiers "export", "override", "private", or it might be one of the conditional tokens like "ifdef", "include", etc. If it's not a variable assignment or undefine, VMOD.V_ASSIGN is 0. Returns LINE. Returns a pointer to the first non-modifier character, and sets VMOD based on the modifiers found if any, plus V_ASSIGN is 1. */ static char * parse_var_assignment (const char *line, struct vmodifiers *vmod) { const char *p; memset (vmod, '\0', sizeof (*vmod)); /* Find the start of the next token. If there isn't one we're done. */ line = next_token (line); if (*line == '\0') return (char *)line; p = line; while (1) { int wlen; const char *p2; enum variable_flavor flavor; p2 = parse_variable_definition (p, &flavor); /* If this is a variable assignment, we're done. */ if (p2) break; /* It's not a variable; see if it's a modifier. */ p2 = end_of_token (p); wlen = p2 - p; if (word1eq ("export")) vmod->export_v = 1; else if (word1eq ("override")) vmod->override_v = 1; else if (word1eq ("private")) vmod->private_v = 1; else if (word1eq ("define")) { /* We can't have modifiers after 'define' */ vmod->define_v = 1; p = next_token (p2); break; } else if (word1eq ("undefine")) { /* We can't have modifiers after 'undefine' */ vmod->undefine_v = 1; p = next_token (p2); break; } else /* Not a variable or modifier: this is not a variable assignment. */ return (char *)line; /* It was a modifier. Try the next word. */ p = next_token (p2); if (*p == '\0') return (char *)line; } /* Found a variable assignment or undefine. */ vmod->assign_v = 1; return (char *)p; } /* Read file FILENAME as a makefile and add its contents to the data base. SET_DEFAULT is true if we are allowed to set the default goal. */ static void eval (struct ebuffer *ebuf, int set_default) { char *collapsed = 0; unsigned int collapsed_length = 0; unsigned int commands_len = 200; char *commands; unsigned int commands_idx = 0; unsigned int cmds_started, tgts_started; int ignoring = 0, in_ignored_define = 0; int no_targets = 0; /* Set when reading a rule without targets. */ struct nameseq *filenames = 0; char *depstr = 0; long nlines = 0; int two_colon = 0; const char *pattern = 0; const char *pattern_percent; struct floc *fstart; struct floc fi; #ifdef CONFIG_WITH_VALUE_LENGTH unsigned int tmp_len; #endif #ifdef KMK struct kbuild_eval_data *kdata = 0; int krc; #endif #define record_waiting_files() \ do \ { \ if (filenames != 0) \ { \ fi.lineno = tgts_started; \ record_files (filenames, pattern, pattern_percent, depstr, \ cmds_started, commands, commands_idx, two_colon, \ &fi); \ filenames = 0; \ } \ commands_idx = 0; \ no_targets = 0; \ pattern = 0; \ } while (0) pattern_percent = 0; cmds_started = tgts_started = 1; fstart = &ebuf->floc; fi.filenm = ebuf->floc.filenm; /* Loop over lines in the file. The strategy is to accumulate target names in FILENAMES, dependencies in DEPS and commands in COMMANDS. These are used to define a rule when the start of the next rule (or eof) is encountered. When you see a "continue" in the loop below, that means we are moving on to the next line _without_ ending any rule that we happen to be working with at the moment. If you see a "goto rule_complete", then the statement we just parsed also finishes the previous rule. */ commands = xmalloc (200); while (1) { unsigned int linelen; #ifdef CONFIG_WITH_VALUE_LENGTH char *eol; #endif char *line; unsigned int wlen; char *p; char *p2; struct vmodifiers vmod; /* At the top of this loop, we are starting a brand new line. */ /* Grab the next line to be evaluated */ ebuf->floc.lineno += nlines; nlines = readline (ebuf); /* If there is nothing left to eval, we're done. */ if (nlines < 0) break; /* If this line is empty, skip it. */ line = ebuf->buffer; if (line[0] == '\0') continue; #ifndef CONFIG_WITH_VALUE_LENGTH linelen = strlen (line); #else linelen = ebuf->eol - line; assert (strlen (line) == linelen); #endif /* Check for a shell command line first. If it is not one, we can stop treating tab specially. */ if (line[0] == cmd_prefix) { if (no_targets) /* Ignore the commands in a rule with no targets. */ continue; /* If there is no preceding rule line, don't treat this line as a command, even though it begins with a recipe prefix. SunOS 4 make appears to behave this way. */ if (filenames != 0) { if (ignoring) /* Yep, this is a shell command, and we don't care. */ continue; /* Append this command line to the line being accumulated. Strip command prefix chars that appear after newlines. */ if (commands_idx == 0) cmds_started = ebuf->floc.lineno; if (linelen + commands_idx > commands_len) { commands_len = (linelen + commands_idx) * 2; commands = xrealloc (commands, commands_len); } p = &commands[commands_idx]; p2 = line + 1; while (--linelen) { ++commands_idx; *(p++) = *p2; if (p2[0] == '\n' && p2[1] == cmd_prefix) { ++p2; --linelen; } ++p2; } *p = '\n'; ++commands_idx; continue; } } /* This line is not a shell command line. Don't worry about whitespace. Get more space if we need it; we don't need to preserve the current contents of the buffer. */ if (collapsed_length < linelen+1) { collapsed_length = linelen+1; if (collapsed) free (collapsed); /* Don't need xrealloc: we don't need to preserve the content. */ collapsed = xmalloc (collapsed_length); } #ifndef CONFIG_WITH_VALUE_LENGTH strcpy (collapsed, line); /* Collapse continuation lines. */ collapse_continuations (collapsed); remove_comments (collapsed); #else memcpy (collapsed, line, linelen + 1); /* Collapse continuation lines. */ eol = collapse_continuations (collapsed, linelen); assert (strchr (collapsed, '\0') == eol); eol = remove_comments (collapsed, eol); assert (strchr (collapsed, '\0') == eol); #endif /* Get rid if starting space (including formfeed, vtab, etc.) */ p = collapsed; while (isspace ((unsigned char)*p)) ++p; /* See if this is a variable assignment. We need to do this early, to allow variables with names like 'ifdef', 'export', 'private', etc. */ p = parse_var_assignment(p, &vmod); if (vmod.assign_v) { struct variable *v; enum variable_origin origin = vmod.override_v ? o_override : o_file; /* If we're ignoring then we're done now. */ if (ignoring) { if (vmod.define_v) in_ignored_define = 1; continue; } if (vmod.undefine_v) { do_undefine (p, origin, ebuf); /* This line has been dealt with. */ goto rule_complete; } else if (vmod.define_v) v = do_define (p IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, ebuf); else v = try_variable_definition (fstart, p IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, 0); assert (v != NULL); if (vmod.export_v) v->export = v_export; if (vmod.private_v) v->private_var = 1; /* This line has been dealt with. */ goto rule_complete; } /* If this line is completely empty, ignore it. */ if (*p == '\0') continue; p2 = end_of_token (p); wlen = p2 - p; p2 = next_token (p2); /* If we're in an ignored define, skip this line (but maybe get out). */ if (in_ignored_define) { /* See if this is an endef line (plus optional comment). */ if (word1eq ("endef") && (*p2 == '\0' || *p2 == '#')) in_ignored_define = 0; continue; } /* Check for conditional state changes. */ { #ifndef CONFIG_WITH_VALUE_LENGTH int i = conditional_line (p, wlen, fstart); #else int i = conditional_line (p, eol, wlen, fstart); #endif if (i != -2) { if (i == -1) fatal (fstart, _("invalid syntax in conditional")); ignoring = i; continue; } } /* Nothing to see here... move along. */ if (ignoring) continue; #ifdef CONFIG_WITH_LOCAL_VARIABLES if (word1eq ("local")) { if (*p2 == '\0') error (fstart, _("empty `local' directive")); if (strneq (p2, "define", 6) && (isblank ((unsigned char)p2[6]) || p2[6] == '\0')) { if (ignoring) in_ignored_define = 1; else { p2 = next_token (p2 + 6); if (*p2 == '\0') fatal (fstart, _("empty variable name")); /* Let the variable name be the whole rest of the line, with trailing blanks stripped (comments have already been removed), so it could be a complex variable/function reference that might contain blanks. */ p = strchr (p2, '\0'); while (isblank ((unsigned char)p[-1])) --p; do_define (p2 IF_WITH_VALUE_LENGTH_PARAM(p), o_local, ebuf); } } else if (!ignoring && !try_variable_definition (fstart, p2 IF_WITH_VALUE_LENGTH_PARAM(eol), o_local, 0)) error (fstart, _("invalid `local' directive")); continue; } #endif /* CONFIG_WITH_LOCAL_VARIABLES */ #ifdef KMK /* Check for the kBuild language extensions. */ if ( wlen >= sizeof("kBuild-define") - 1 && strneq (p, "kBuild-define", sizeof("kBuild-define") - 1)) krc = eval_kbuild_define (&kdata, fstart, p, wlen, p2, eol, ignoring); else if ( wlen >= sizeof("kBuild-endef") - 1 && strneq (p, "kBuild-endef", sizeof("kBuild-endef") - 1)) krc = eval_kbuild_endef (&kdata, fstart, p, wlen, p2, eol, ignoring); else krc = 42; if (krc != 42) { if (krc != 0) error (fstart, _("krc=%d"), krc); continue; } #endif /* KMK */ /* Manage the "export" keyword used outside of variable assignment as well as "unexport". */ if (word1eq ("export") || word1eq ("unexport")) { int exporting = *p == 'u' ? 0 : 1; /* (un)export by itself causes everything to be (un)exported. */ if (*p2 == '\0') export_all_variables = exporting; else { unsigned int l; const char *cp; char *ap; /* Expand the line so we can use indirect and constructed variable names in an (un)export command. */ #ifndef CONFIG_WITH_VALUE_LENGTH cp = ap = allocated_variable_expand (p2); #else unsigned int buf_len; cp = ap = allocated_variable_expand_3 (p2, eol - p2, NULL, &buf_len); #endif for (p = find_next_token (&cp, &l); p != 0; p = find_next_token (&cp, &l)) { struct variable *v = lookup_variable (p, l); if (v == 0) v = define_variable_loc (p, l, "", o_file, 0, fstart); v->export = exporting ? v_export : v_noexport; } #ifndef CONFIG_WITH_VALUE_LENGTH free (ap); #else recycle_variable_buffer (ap, buf_len); #endif } goto rule_complete; } /* Handle the special syntax for vpath. */ if (word1eq ("vpath")) { const char *cp; char *vpat; unsigned int l; cp = variable_expand (p2); p = find_next_token (&cp, &l); if (p != 0) { vpat = xstrndup (p, l); p = find_next_token (&cp, &l); /* No searchpath means remove all previous selective VPATH's with the same pattern. */ } else /* No pattern means remove all previous selective VPATH's. */ vpat = 0; construct_vpath_list (vpat, p); if (vpat != 0) free (vpat); goto rule_complete; } #ifdef CONFIG_WITH_INCLUDEDEP assert (strchr (p2, '\0') == eol); if (word1eq ("includedep") || word1eq ("includedep-queue") || word1eq ("includedep-flush")) { /* We have found an `includedep' line specifying one or more dep files to be read at this point. This include variation does no globbing and do not support multiple names. It's trying to save time by being dead simple as well as ignoring errors. */ enum incdep_op op = p[wlen - 1] == 'p' ? incdep_read_it : p[wlen - 1] == 'e' ? incdep_queue : incdep_flush; char *free_me = NULL; unsigned int buf_len; char *name = p2; if (memchr (name, '$', eol - name)) { unsigned int name_len; free_me = name = allocated_variable_expand_3 (name, eol - name, &name_len, &buf_len); eol = name + name_len; while (isspace ((unsigned char)*name)) ++name; } while (eol > name && isspace ((unsigned char)eol[-1])) --eol; *eol = '\0'; eval_include_dep (name, fstart, op); if (free_me) recycle_variable_buffer (free_me, buf_len); goto rule_complete; } #endif /* CONFIG_WITH_INCLUDEDEP */ /* Handle include and variants. */ if (word1eq ("include") || word1eq ("-include") || word1eq ("sinclude")) { /* We have found an `include' line specifying a nested makefile to be read at this point. */ struct conditionals *save; struct conditionals new_conditionals; struct nameseq *files; /* "-include" (vs "include") says no error if the file does not exist. "sinclude" is an alias for this from SGI. */ int noerror = (p[0] != 'i'); #ifndef CONFIG_WITH_VALUE_LENGTH p = allocated_variable_expand (p2); #else unsigned int buf_len; p = allocated_variable_expand_3 (p2, eol - p2, NULL, &buf_len); #endif /* If no filenames, it's a no-op. */ if (*p == '\0') { #ifndef CONFIG_WITH_VALUE_LENGTH free (p); #else recycle_variable_buffer (p, buf_len); #endif continue; } /* Parse the list of file names. Don't expand archive references! */ p2 = p; files = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, PARSEFS_NOAR); #ifndef CONFIG_WITH_VALUE_LENGTH free (p); #else recycle_variable_buffer (p, buf_len); #endif /* Save the state of conditionals and start the included makefile with a clean slate. */ save = install_conditionals (&new_conditionals); /* Record the rules that are waiting so they will determine the default goal before those in the included makefile. */ record_waiting_files (); /* Read each included makefile. */ while (files != 0) { struct nameseq *next = files->next; const char *name = files->name; int r; free_ns (files); files = next; r = eval_makefile (name, (RM_INCLUDED | RM_NO_TILDE | (noerror ? RM_DONTCARE : 0) | (set_default ? 0 : RM_NO_DEFAULT_GOAL))); if (!r && !noerror) error (fstart, "%s: %s", name, strerror (errno)); } /* Restore conditional state. */ restore_conditionals (save); goto rule_complete; } /* This line starts with a tab but was not caught above because there was no preceding target, and the line might have been usable as a variable definition. But now we know it is definitely lossage. */ if (line[0] == cmd_prefix) fatal(fstart, _("recipe commences before first target")); /* This line describes some target files. This is complicated by the existence of target-specific variables, because we can't expand the entire line until we know if we have one or not. So we expand the line word by word until we find the first `:', then check to see if it's a target-specific variable. In this algorithm, `lb_next' will point to the beginning of the unexpanded parts of the input buffer, while `p2' points to the parts of the expanded buffer we haven't searched yet. */ { enum make_word_type wtype; char *cmdleft, *semip, *lb_next; unsigned int plen = 0; char *colonp; const char *end, *beg; /* Helpers for whitespace stripping. */ /* Record the previous rule. */ record_waiting_files (); tgts_started = fstart->lineno; /* Search the line for an unquoted ; that is not after an unquoted #. */ #ifndef CONFIG_WITH_VALUE_LENGTH cmdleft = find_char_unquote (line, ';', '#', 0, 1); #else cmdleft = find_char_unquote_2 (line, ';', '#', 0, 1, ebuf->eol - line); #endif if (cmdleft != 0 && *cmdleft == '#') { /* We found a comment before a semicolon. */ *cmdleft = '\0'; cmdleft = 0; } else if (cmdleft != 0) /* Found one. Cut the line short there before expanding it. */ *(cmdleft++) = '\0'; semip = cmdleft; #ifndef CONFIG_WITH_VALUE_LENGTH collapse_continuations (line); #else collapse_continuations (line, strlen (line)); /**@todo fix this */ #endif /* We can't expand the entire line, since if it's a per-target variable we don't want to expand it. So, walk from the beginning, expanding as we go, and looking for "interesting" chars. The first word is always expandable. */ wtype = get_next_mword(line, NULL, &lb_next, &wlen); switch (wtype) { case w_eol: if (cmdleft != 0) fatal(fstart, _("missing rule before recipe")); /* This line contained something but turned out to be nothing but whitespace (a comment?). */ continue; case w_colon: case w_dcolon: /* We accept and ignore rules without targets for compatibility with SunOS 4 make. */ no_targets = 1; continue; default: break; } #ifndef CONFIG_WITH_VALUE_LENGTH p2 = variable_expand_string(NULL, lb_next, wlen); #else p2 = variable_expand_string_2 (NULL, lb_next, wlen, &eol); assert (strchr (p2, '\0') == eol); #endif while (1) { lb_next += wlen; if (cmdleft == 0) { /* Look for a semicolon in the expanded line. */ #ifndef CONFIG_WITH_VALUE_LENGTH cmdleft = find_char_unquote (p2, ';', 0, 0, 0); #else cmdleft = find_char_unquote_0 (p2, ';', &eol); #endif if (cmdleft != 0) { unsigned long p2_off = p2 - variable_buffer; unsigned long cmd_off = cmdleft - variable_buffer; #ifndef CONFIG_WITH_VALUE_LENGTH char *pend = p2 + strlen(p2); #endif /* Append any remnants of lb, then cut the line short at the semicolon. */ *cmdleft = '\0'; /* One school of thought says that you shouldn't expand here, but merely copy, since now you're beyond a ";" and into a command script. However, the old parser expanded the whole line, so we continue that for backwards-compatiblity. Also, it wouldn't be entirely consistent, since we do an unconditional expand below once we know we don't have a target-specific variable. */ #ifndef CONFIG_WITH_VALUE_LENGTH (void)variable_expand_string(pend, lb_next, (long)-1); lb_next += strlen(lb_next); #else tmp_len = strlen (lb_next); variable_expand_string_2 (eol, lb_next, tmp_len, &eol); lb_next += tmp_len; #endif p2 = variable_buffer + p2_off; cmdleft = variable_buffer + cmd_off + 1; } } #ifndef CONFIG_WITH_VALUE_LENGTH colonp = find_char_unquote(p2, ':', 0, 0, 0); #else colonp = find_char_unquote_0 (p2, ':', &eol); #endif #ifdef HAVE_DOS_PATHS /* The drive spec brain-damage strikes again... */ /* Note that the only separators of targets in this context are whitespace and a left paren. If others are possible, they should be added to the string in the call to index. */ while (colonp && (colonp[1] == '/' || colonp[1] == '\\') && colonp > p2 && isalpha ((unsigned char)colonp[-1]) && (colonp == p2 + 1 || strchr (" \t(", colonp[-2]) != 0)) # ifndef CONFIG_WITH_VALUE_LENGTH colonp = find_char_unquote(colonp + 1, ':', 0, 0, 0); # else colonp = find_char_unquote_0 (colonp + 1, ':', &eol); # endif #endif if (colonp != 0) break; wtype = get_next_mword(lb_next, NULL, &lb_next, &wlen); if (wtype == w_eol) break; #ifndef CONFIG_WITH_VALUE_LENGTH p2 += strlen(p2); *(p2++) = ' '; p2 = variable_expand_string(p2, lb_next, wlen); #else *(eol++) = ' '; p2 = variable_expand_string_2 (eol, lb_next, wlen, &eol); #endif /* We don't need to worry about cmdleft here, because if it was found in the variable_buffer the entire buffer has already been expanded... we'll never get here. */ } p2 = next_token (variable_buffer); /* If the word we're looking at is EOL, see if there's _anything_ on the line. If not, a variable expanded to nothing, so ignore it. If so, we can't parse this line so punt. */ if (wtype == w_eol) { if (*p2 != '\0') /* There's no need to be ivory-tower about this: check for one of the most common bugs found in makefiles... */ fatal (fstart, _("missing separator%s"), (cmd_prefix == '\t' && !strneq(line, " ", 8)) ? "" : _(" (did you mean TAB instead of 8 spaces?)")); continue; } /* Make the colon the end-of-string so we know where to stop looking for targets. */ *colonp = '\0'; filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0); *p2 = ':'; if (!filenames) { /* We accept and ignore rules without targets for compatibility with SunOS 4 make. */ no_targets = 1; continue; } /* This should never be possible; we handled it above. */ assert (*p2 != '\0'); ++p2; /* Is this a one-colon or two-colon entry? */ two_colon = *p2 == ':'; if (two_colon) p2++; /* Test to see if it's a target-specific variable. Copy the rest of the buffer over, possibly temporarily (we'll expand it later if it's not a target-specific variable). PLEN saves the length of the unparsed section of p2, for later. */ if (*lb_next != '\0') { unsigned int l = p2 - variable_buffer; plen = strlen (p2); variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1); p2 = variable_buffer + l; } p2 = parse_var_assignment (p2, &vmod); if (vmod.assign_v) { /* If there was a semicolon found, add it back, plus anything after it. */ if (semip) { unsigned int l = p - variable_buffer; *(--semip) = ';'; #ifndef CONFIG_WITH_VALUE_LENGTH collapse_continuations (semip); #else collapse_continuations (semip, strlen(semip)); /** @todo fix this */ #endif variable_buffer_output (p2 + strlen (p2), semip, strlen (semip)+1); p = variable_buffer + l; } record_target_var (filenames, p2, vmod.override_v ? o_override : o_file, &vmod, fstart); filenames = 0; continue; } /* This is a normal target, _not_ a target-specific variable. Unquote any = in the dependency list. */ find_char_unquote (lb_next, '=', 0, 0, 0); /* We have some targets, so don't ignore the following commands. */ no_targets = 0; /* Expand the dependencies, etc. */ if (*lb_next != '\0') { unsigned int l = p2 - variable_buffer; #ifndef CONFIG_WITH_VALUE_LENGTH (void) variable_expand_string (p2 + plen, lb_next, (long)-1); #else char *eos; (void) variable_expand_string_2 (p2 + plen, lb_next, (long)-1, &eos); #endif p2 = variable_buffer + l; /* Look for a semicolon in the expanded line. */ if (cmdleft == 0) { #ifndef CONFIG_WITH_VALUE_LENGTH cmdleft = find_char_unquote (p2, ';', 0, 0, 0); #else cmdleft = find_char_unquote_0 (p2, ';', &eos); #endif if (cmdleft != 0) *(cmdleft++) = '\0'; } } /* Is this a static pattern rule: `target: %targ: %dep; ...'? */ p = strchr (p2, ':'); while (p != 0 && p[-1] == '\\') { char *q = &p[-1]; int backslash = 0; while (*q-- == '\\') backslash = !backslash; if (backslash) p = strchr (p + 1, ':'); else break; } #ifdef _AMIGA /* Here, the situation is quite complicated. Let's have a look at a couple of targets: install: dev:make dev:make: make dev:make:: xyz The rule is that it's only a target, if there are TWO :'s OR a space around the :. */ if (p && !(isspace ((unsigned char)p[1]) || !p[1] || isspace ((unsigned char)p[-1]))) p = 0; #endif #ifdef HAVE_DOS_PATHS { int check_again; do { check_again = 0; /* For DOS-style paths, skip a "C:\..." or a "C:/..." */ if (p != 0 && (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]) && (p == p2 + 1 || strchr (" \t:(", p[-2]) != 0)) { p = strchr (p + 1, ':'); check_again = 1; } } while (check_again); } #endif if (p != 0) { struct nameseq *target; target = PARSE_FILE_SEQ (&p2, struct nameseq, ':', NULL, PARSEFS_NOGLOB); ++p2; if (target == 0) fatal (fstart, _("missing target pattern")); else if (target->next != 0) fatal (fstart, _("multiple target patterns (target `%s')"), target->name); /* bird */ pattern_percent = find_percent_cached (&target->name); pattern = target->name; if (pattern_percent == 0) fatal (fstart, _("target pattern contains no `%%' (target `%s')"), target->name); /* bird */ free_ns (target); } else pattern = 0; /* Strip leading and trailing whitespaces. */ beg = p2; end = beg + strlen (beg) - 1; strip_whitespace (&beg, &end); /* Put all the prerequisites here; they'll be parsed later. */ if (beg <= end && *beg != '\0') depstr = xstrndup (beg, end - beg + 1); else depstr = 0; commands_idx = 0; if (cmdleft != 0) { /* Semicolon means rest of line is a command. */ unsigned int l = strlen (cmdleft); cmds_started = fstart->lineno; /* Add this command line to the buffer. */ if (l + 2 > commands_len) { commands_len = (l + 2) * 2; commands = xrealloc (commands, commands_len); } memcpy (commands, cmdleft, l); commands_idx += l; commands[commands_idx++] = '\n'; } /* Determine if this target should be made default. We used to do this in record_files() but because of the delayed target recording and because preprocessor directives are legal in target's commands it is too late. Consider this fragment for example: foo: ifeq ($(.DEFAULT_GOAL),foo) ... endif Because the target is not recorded until after ifeq directive is evaluated the .DEFAULT_GOAL does not contain foo yet as one would expect. Because of this we have to move the logic here. */ if (set_default && default_goal_var->value[0] == '\0') { const char *name; struct dep *d; struct nameseq *t = filenames; for (; t != 0; t = t->next) { int reject = 0; name = t->name; /* We have nothing to do if this is an implicit rule. */ if (strchr (name, '%') != 0) break; /* See if this target's name does not start with a `.', unless it contains a slash. */ if (*name == '.' && strchr (name, '/') == 0 #ifdef HAVE_DOS_PATHS && strchr (name, '\\') == 0 #endif ) continue; /* If this file is a suffix, don't let it be the default goal file. */ for (d = suffix_file->deps; d != 0; d = d->next) { register struct dep *d2; if (*dep_name (d) != '.' && streq (name, dep_name (d))) { reject = 1; break; } for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next) { #ifndef CONFIG_WITH_STRCACHE2 unsigned int l = strlen (dep_name (d2)); #else unsigned int l = strcache2_get_len (&file_strcache, dep_name (d2)); #endif if (!strneq (name, dep_name (d2), l)) continue; if (streq (name + l, dep_name (d))) { reject = 1; break; } } if (reject) break; } if (!reject) { define_variable_global (".DEFAULT_GOAL", 13, t->name, o_file, 0, NILF); break; } } } continue; } /* We get here except in the case that we just read a rule line. Record now the last rule we read, so following spurious commands are properly diagnosed. */ rule_complete: record_waiting_files (); } #undef word1eq if (conditionals->if_cmds) fatal (fstart, _("missing `endif'")); #ifdef KMK if (kdata != NULL) fatal (fstart, _("missing `kBuild-endef-*'")); #endif /* At eof, record the last rule. */ record_waiting_files (); if (collapsed) free (collapsed); free (commands); } /* Remove comments from LINE. This is done by copying the text at LINE onto itself. */ #ifndef CONFIG_WITH_VALUE_LENGTH static void remove_comments (char *line) { char *comment; comment = find_char_unquote (line, '#', 0, 0, 0); if (comment != 0) /* Cut off the line at the #. */ *comment = '\0'; } #else /* CONFIG_WITH_VALUE_LENGTH */ __inline static char * remove_comments (char *line, char *eol) { unsigned int string_len = eol - line; register int ch; char *p; /* Hope for simple (no comments). */ p = memchr (line, '#', string_len); if (!p) return eol; /* Found potential comment, enter the slow route. */ for (;;) { if (p > line && p[-1] == '\\') { /* Search for more backslashes. */ int i = -2; while (&p[i] >= line && p[i] == '\\') --i; ++i; /* The number of backslashes is now -I. Copy P over itself to swallow half of them. */ memmove (&p[i], &p[i/2], (string_len - (p - line)) - (i/2) + 1); p += i/2; if (i % 2 == 0) { /* All the backslashes quoted each other; the STOPCHAR was unquoted. */ *p = '\0'; return p; } /* The '#' was quoted by a backslash. Look for another. */ } else { /* No backslash in sight. */ *p = '\0'; return p; } /* lazy, string_len isn't correct so do it the slow way. */ while ((ch = *p) != '#') { if (ch == '\0') return p; ++p; } } /* won't ever get here. */ } #endif /* CONFIG_WITH_VALUE_LENGTH */ /* Execute a `undefine' directive. The undefine line has already been read, and NAME is the name of the variable to be undefined. */ static void do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf) { char *p, *var; /* Expand the variable name and find the beginning (NAME) and end. */ var = allocated_variable_expand (name); name = next_token (var); if (*name == '\0') fatal (&ebuf->floc, _("empty variable name")); p = name + strlen (name) - 1; while (p > name && isblank ((unsigned char)*p)) --p; p[1] = '\0'; undefine_variable_global (name, p - name + 1, origin); free (var); } /* Execute a `define' directive. The first line has already been read, and NAME is the name of the variable to be defined. The following lines remain to be read. */ static struct variable * do_define (char *name IF_WITH_VALUE_LENGTH_PARAM(char *eos), enum variable_origin origin, struct ebuffer *ebuf) { struct variable *v; enum variable_flavor flavor; struct floc defstart; int nlevels = 1; unsigned int length = 100; char *definition = xmalloc (length); unsigned int idx = 0; char *p, *var; defstart = ebuf->floc; p = parse_variable_definition (name, &flavor); if (p == NULL) /* No assignment token, so assume recursive. */ flavor = f_recursive; else { if (*(next_token (p)) != '\0') error (&defstart, _("extraneous text after `define' directive")); /* Chop the string before the assignment token to get the name. */ p[flavor == f_recursive ? -1 : -2] = '\0'; } /* Expand the variable name and find the beginning (NAME) and end. */ var = allocated_variable_expand (name); name = next_token (var); if (*name == '\0') fatal (&defstart, _("empty variable name")); p = name + strlen (name) - 1; while (p > name && isblank ((unsigned char)*p)) --p; p[1] = '\0'; /* Now read the value of the variable. */ while (1) { unsigned int len; char *line; long nlines = readline (ebuf); /* If there is nothing left to be eval'd, there's no 'endef'!! */ if (nlines < 0) fatal (&defstart, _("missing `endef', unterminated `define'")); ebuf->floc.lineno += nlines; line = ebuf->buffer; #ifndef CONFIG_WITH_VALUE_LENGTH collapse_continuations (line); #else ebuf->eol = collapse_continuations (line, ebuf->eol - line); #endif /* If the line doesn't begin with a tab, test to see if it introduces another define, or ends one. Stop if we find an 'endef' */ if (line[0] != cmd_prefix) { p = next_token (line); #ifndef CONFIG_WITH_VALUE_LENGTH len = strlen (p); #else len = ebuf->eol - p; assert (len == strlen (p)); #endif /* If this is another 'define', increment the level count. */ if ((len == 6 || (len > 6 && isblank ((unsigned char)p[6]))) && strneq (p, "define", 6)) ++nlevels; /* If this is an 'endef', decrement the count. If it's now 0, we've found the last one. */ else if ((len == 5 || (len > 5 && isblank ((unsigned char)p[5]))) && strneq (p, "endef", 5)) { p += 5; #ifndef CONFIG_WITH_VALUE_LENGTH remove_comments (p); #else ebuf->eol = remove_comments (p, ebuf->eol); #endif if (*(next_token (p)) != '\0') error (&ebuf->floc, _("extraneous text after `endef' directive")); if (--nlevels == 0) break; } } /* Add this line to the variable definition. */ #ifndef CONFIG_WITH_VALUE_LENGTH len = strlen (line); #else len = ebuf->eol - line; assert (len == strlen (line)); #endif if (idx + len + 1 > length) { length = (idx + len) * 2; definition = xrealloc (definition, length + 1); } memcpy (&definition[idx], line, len); idx += len; /* Separate lines with a newline. */ definition[idx++] = '\n'; } /* We've got what we need; define the variable. */ if (idx == 0) definition[0] = '\0'; else definition[idx - 1] = '\0'; v = do_variable_definition (&defstart, name, definition, origin, flavor, 0); free (definition); free (var); return (v); } /* Interpret conditional commands "ifdef", "ifndef", "ifeq", "ifneq", "if1of", "ifn1of", "else" and "endif". LINE is the input line, with the command as its first word. FILENAME and LINENO are the filename and line number in the current makefile. They are used for error messages. Value is -2 if the line is not a conditional at all, -1 if the line is an invalid conditional, 0 if following text should be interpreted, 1 if following text should be ignored. */ static int #ifndef CONFIG_WITH_VALUE_LENGTH conditional_line (char *line, int len, const struct floc *flocp) #else conditional_line (char *line, char *eol, int len, const struct floc *flocp) #endif { char *cmdname; enum { c_ifdef, c_ifndef, c_ifeq, c_ifneq, #ifdef CONFIG_WITH_SET_CONDITIONALS c_if1of, c_ifn1of, #endif #ifdef CONFIG_WITH_IF_CONDITIONALS c_ifcond, #endif c_else, c_endif } cmdtype; unsigned int i; unsigned int o; #ifdef CONFIG_WITH_VALUE_LENGTH assert (strchr (line, '\0') == eol); #endif /* Compare a word, both length and contents. */ #define word1eq(s) (len == sizeof(s)-1 && strneq (s, line, sizeof(s)-1)) #define chkword(s, t) if (word1eq (s)) { cmdtype = (t); cmdname = (s); } /* Make sure this line is a conditional. */ chkword ("ifdef", c_ifdef) else chkword ("ifndef", c_ifndef) else chkword ("ifeq", c_ifeq) else chkword ("ifneq", c_ifneq) #ifdef CONFIG_WITH_SET_CONDITIONALS else chkword ("if1of", c_if1of) else chkword ("ifn1of", c_ifn1of) #endif #ifdef CONFIG_WITH_IF_CONDITIONALS else chkword ("if", c_ifcond) #endif else chkword ("else", c_else) else chkword ("endif", c_endif) else return -2; /* Found one: skip past it and any whitespace after it. */ line = next_token (line + len); #define EXTRANEOUS() error (flocp, _("Extraneous text after `%s' directive"), cmdname) /* An 'endif' cannot contain extra text, and reduces the if-depth by 1 */ if (cmdtype == c_endif) { if (*line != '\0') EXTRANEOUS (); if (!conditionals->if_cmds) fatal (flocp, _("extraneous `%s'"), cmdname); --conditionals->if_cmds; goto DONE; } /* An 'else' statement can either be simple, or it can have another conditional after it. */ if (cmdtype == c_else) { const char *p; if (!conditionals->if_cmds) fatal (flocp, _("extraneous `%s'"), cmdname); o = conditionals->if_cmds - 1; if (conditionals->seen_else[o]) fatal (flocp, _("only one `else' per conditional")); /* Change the state of ignorance. */ switch (conditionals->ignoring[o]) { case 0: /* We've just been interpreting. Never do it again. */ conditionals->ignoring[o] = 2; break; case 1: /* We've never interpreted yet. Maybe this time! */ conditionals->ignoring[o] = 0; break; } /* It's a simple 'else'. */ if (*line == '\0') { conditionals->seen_else[o] = 1; goto DONE; } /* The 'else' has extra text. That text must be another conditional and cannot be an 'else' or 'endif'. */ /* Find the length of the next word. */ for (p = line+1; *p != '\0' && !isspace ((unsigned char)*p); ++p) ; len = p - line; /* If it's 'else' or 'endif' or an illegal conditional, fail. */ if (word1eq("else") || word1eq("endif") #ifndef CONFIG_WITH_VALUE_LENGTH || conditional_line (line, len, flocp) < 0) #else || conditional_line (line, eol, len, flocp) < 0) #endif EXTRANEOUS (); else { /* conditional_line() created a new level of conditional. Raise it back to this level. */ if (conditionals->ignoring[o] < 2) conditionals->ignoring[o] = conditionals->ignoring[o+1]; --conditionals->if_cmds; } goto DONE; } #ifndef KMK if (conditionals->allocated == 0) { conditionals->allocated = 5; conditionals->ignoring = xmalloc (conditionals->allocated); conditionals->seen_else = xmalloc (conditionals->allocated); } #endif o = conditionals->if_cmds++; if (conditionals->if_cmds > conditionals->allocated) { #ifdef KMK if (conditionals->allocated <= sizeof (conditionals->ignoring_first)) { assert (conditionals->allocated == sizeof (conditionals->ignoring_first)); conditionals->allocated += 16; conditionals->ignoring = xmalloc (conditionals->allocated); memcpy (conditionals->ignoring, conditionals->ignoring_first, sizeof (conditionals->ignoring_first)); conditionals->seen_else = xmalloc (conditionals->allocated); memcpy (conditionals->seen_else, conditionals->seen_else_first, sizeof (conditionals->seen_else_first)); } else { conditionals->allocated *= 2; #else /* !KMK */ conditionals->allocated += 5; #endif /* !KMK */ conditionals->ignoring = xrealloc (conditionals->ignoring, conditionals->allocated); conditionals->seen_else = xrealloc (conditionals->seen_else, conditionals->allocated); #ifdef KMK } #endif } /* Record that we have seen an `if...' but no `else' so far. */ conditionals->seen_else[o] = 0; /* Search through the stack to see if we're already ignoring. */ for (i = 0; i < o; ++i) if (conditionals->ignoring[i]) { /* We are already ignoring, so just push a level to match the next "else" or "endif", and keep ignoring. We don't want to expand variables in the condition. */ conditionals->ignoring[o] = 1; return 1; } if (cmdtype == c_ifdef || cmdtype == c_ifndef) { char *var; struct variable *v; char *p; /* Expand the thing we're looking up, so we can use indirect and constructed variable names. */ #ifndef CONFIG_WITH_VALUE_LENGTH var = allocated_variable_expand (line); #else var = variable_expand_string_2 (NULL, line, eol - line, &p); #endif /* Make sure there's only one variable name to test. */ p = end_of_token (var); i = p - var; p = next_token (p); if (*p != '\0') return -1; var[i] = '\0'; v = lookup_variable (var, i); conditionals->ignoring[o] = ((v != 0 && *v->value != '\0') == (cmdtype == c_ifndef)); #ifndef CONFIG_WITH_VALUE_LENGTH free (var); #endif } #ifdef CONFIG_WITH_IF_CONDITIONALS else if (cmdtype == c_ifcond) { int rval = expr_eval_if_conditionals (line, flocp); if (rval == -1) return rval; conditionals->ignoring[o] = rval; } #endif else { #ifdef CONFIG_WITH_SET_CONDITIONALS /* "ifeq", "ifneq", "if1of" or "ifn1of". */ #else /* "ifeq" or "ifneq". */ #endif char *s1, *s2; unsigned int l; char termin = *line == '(' ? ',' : *line; #ifdef CONFIG_WITH_VALUE_LENGTH char *s1_end, *s2_end; #endif if (termin != ',' && termin != '"' && termin != '\'') return -1; s1 = ++line; /* Find the end of the first string. */ if (termin == ',') { int count = 0; for (; *line != '\0'; ++line) if (*line == '(') ++count; else if (*line == ')') --count; else if (*line == ',' && count <= 0) break; } else while (*line != '\0' && *line != termin) ++line; if (*line == '\0') return -1; if (termin == ',') { /* Strip blanks after the first string. */ char *p = line++; while (isblank ((unsigned char)p[-1])) --p; *p = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH l = p - s1; #endif } else { #ifdef CONFIG_WITH_VALUE_LENGTH l = line - s1; #endif *line++ = '\0'; } #ifndef CONFIG_WITH_VALUE_LENGTH s2 = variable_expand (s1); /* We must allocate a new copy of the expanded string because variable_expand re-uses the same buffer. */ l = strlen (s2); s1 = alloca (l + 1); memcpy (s1, s2, l + 1); #else s1 = variable_expand_string_2 (NULL, s1, l, &s1_end); #endif if (termin != ',') /* Find the start of the second string. */ line = next_token (line); termin = termin == ',' ? ')' : *line; if (termin != ')' && termin != '"' && termin != '\'') return -1; /* Find the end of the second string. */ if (termin == ')') { int count = 0; s2 = next_token (line); for (line = s2; *line != '\0'; ++line) { if (*line == '(') ++count; else if (*line == ')') { if (count <= 0) break; else --count; } } } else { ++line; s2 = line; while (*line != '\0' && *line != termin) ++line; } if (*line == '\0') return -1; *line = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH l = line - s2; #endif line = next_token (++line); if (*line != '\0') EXTRANEOUS (); #ifndef CONFIG_WITH_VALUE_LENGTH s2 = variable_expand (s2); #else s2 = variable_expand_string_2 (s1_end + 1, s2, l, &s2_end); if (s2 != s1_end + 1) s1 += s2 - s1_end - 1; /* the variable buffer was reallocated */ #endif #ifdef CONFIG_WITH_SET_CONDITIONALS if (cmdtype == c_if1of || cmdtype == c_ifn1of) { const char *s1_cur; unsigned int s1_len; const char *s1_iterator = s1; conditionals->ignoring[o] = (cmdtype == c_if1of); /* if not found */ while ((s1_cur = find_next_token (&s1_iterator, &s1_len)) != 0) { const char *s2_cur; unsigned int s2_len; const char *s2_iterator = s2; while ((s2_cur = find_next_token (&s2_iterator, &s2_len)) != 0) if (s2_len == s1_len && strneq (s2_cur, s1_cur, s1_len) ) { conditionals->ignoring[o] = (cmdtype != c_if1of); /* found */ break; } } } else conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq)); #else conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq)); #endif } DONE: /* Search through the stack to see if we're ignoring. */ for (i = 0; i < conditionals->if_cmds; ++i) if (conditionals->ignoring[i]) return 1; return 0; } /* Record target-specific variable values for files FILENAMES. TWO_COLON is nonzero if a double colon was used. The links of FILENAMES are freed, and so are any names in it that are not incorporated into other data structures. If the target is a pattern, add the variable to the pattern-specific variable value list. */ static void record_target_var (struct nameseq *filenames, char *defn, enum variable_origin origin, struct vmodifiers *vmod, const struct floc *flocp) { struct nameseq *nextf; struct variable_set_list *global; global = current_variable_set_list; /* If the variable is an append version, store that but treat it as a normal recursive variable. */ for (; filenames != 0; filenames = nextf) { struct variable *v; const char *name = filenames->name; const char *fname; const char *percent; struct pattern_var *p; nextf = filenames->next; free_ns (filenames); /* If it's a pattern target, then add it to the pattern-specific variable list. */ percent = find_percent_cached (&name); if (percent) { /* Get a reference for this pattern-specific variable struct. */ p = create_pattern_var (name, percent); p->variable.fileinfo = *flocp; /* I don't think this can fail since we already determined it was a variable definition. */ v = assign_variable_definition (&p->variable, defn IF_WITH_VALUE_LENGTH_PARAM(NULL)); assert (v != 0); v->origin = origin; if (v->flavor == f_simple) v->value = allocated_variable_expand (v->value); else v->value = xstrdup (v->value); fname = p->target; } else { struct file *f; /* Get a file reference for this file, and initialize it. We don't want to just call enter_file() because that allocates a new entry if the file is a double-colon, which we don't want in this situation. */ #ifndef CONFIG_WITH_STRCACHE2 f = lookup_file (name); if (!f) f = enter_file (strcache_add (name)); #else /* CONFIG_WITH_STRCACHE2 */ /* XXX: this is probably already a cached string. */ fname = strcache_add (name); f = lookup_file_cached (fname); if (!f) f = enter_file (fname); #endif /* CONFIG_WITH_STRCACHE2 */ else if (f->double_colon) f = f->double_colon; initialize_file_variables (f, 1); fname = f->name; current_variable_set_list = f->variables; v = try_variable_definition (flocp, defn IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, 1); if (!v) fatal (flocp, _("Malformed target-specific variable definition")); current_variable_set_list = global; } /* Set up the variable to be *-specific. */ v->per_target = 1; v->private_var = vmod->private_v; v->export = vmod->export_v ? v_export : v_default; /* If it's not an override, check to see if there was a command-line setting. If so, reset the value. */ if (v->origin != o_override) { struct variable *gv; #ifndef CONFIG_WITH_STRCACHE2 int len = strlen(v->name); #else int len = !percent ? strcache2_get_len (&variable_strcache, v->name) : strlen(v->name); #endif gv = lookup_variable (v->name, len); if (gv && (gv->origin == o_env_override || gv->origin == o_command)) { #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE assert (!v->rdonly_val); /* paranoia */ #endif if (v->value != 0) free (v->value); #ifndef CONFIG_WITH_VALUE_LENGTH v->value = xstrdup (gv->value); #else v->value = xstrndup (gv->value, gv->value_length); v->value_length = gv->value_length; #endif v->origin = gv->origin; v->recursive = gv->recursive; v->append = 0; } } } } /* Record a description line for files FILENAMES, with dependencies DEPS, commands to execute described by COMMANDS and COMMANDS_IDX, coming from FILENAME:COMMANDS_STARTED. TWO_COLON is nonzero if a double colon was used. If not nil, PATTERN is the `%' pattern to make this a static pattern rule, and PATTERN_PERCENT is a pointer to the `%' within it. The links of FILENAMES are freed, and so are any names in it that are not incorporated into other data structures. */ static void record_files (struct nameseq *filenames, const char *pattern, const char *pattern_percent, char *depstr, unsigned int cmds_started, char *commands, unsigned int commands_idx, int two_colon, const struct floc *flocp) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET struct file *prev_file = 0; enum multitarget_mode { m_unsettled, m_no, m_yes, m_yes_maybe } multi_mode = !two_colon && !pattern ? m_unsettled : m_no; #endif struct commands *cmds; struct dep *deps; const char *implicit_percent; const char *name; /* If we've already snapped deps, that means we're in an eval being resolved after the makefiles have been read in. We can't add more rules at this time, since they won't get snapped and we'll get core dumps. See Savannah bug # 12124. */ if (snapped_deps) fatal (flocp, _("prerequisites cannot be defined in recipes")); /* Determine if this is a pattern rule or not. */ name = filenames->name; implicit_percent = find_percent_cached (&name); /* If there's a recipe, set up a struct for it. */ if (commands_idx > 0) { #ifndef CONFIG_WITH_ALLOC_CACHES cmds = xmalloc (sizeof (struct commands)); #else cmds = alloccache_alloc (&commands_cache); #endif cmds->fileinfo.filenm = flocp->filenm; cmds->fileinfo.lineno = cmds_started; cmds->commands = xstrndup (commands, commands_idx); cmds->command_lines = 0; #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS cmds->refs = 0; #endif } else cmds = 0; /* If there's a prereq string then parse it--unless it's eligible for 2nd expansion: if so, snap_deps() will do it. */ if (depstr == 0) deps = 0; else if (second_expansion && strchr (depstr, '$')) { deps = alloc_dep (); deps->name = depstr; deps->need_2nd_expansion = 1; deps->staticpattern = pattern != 0; } else { deps = split_prereqs (depstr); free (depstr); /* We'll enter static pattern prereqs later when we have the stem. We don't want to enter pattern rules at all so that we don't think that they ought to exist (make manual "Implicit Rule Search Algorithm", item 5c). */ if (! pattern && ! implicit_percent) deps = enter_prereqs (deps, NULL); } /* For implicit rules, _all_ the targets must have a pattern. That means we can test the first one to see if we're working with an implicit rule; if so we handle it specially. */ if (implicit_percent) { struct nameseq *nextf; const char **targets, **target_pats; unsigned int c; if (pattern != 0) fatal (flocp, _("mixed implicit and static pattern rules")); /* Count the targets to create an array of target names. We already have the first one. */ nextf = filenames->next; free_ns (filenames); filenames = nextf; for (c = 1; nextf; ++c, nextf = nextf->next) ; targets = xmalloc (c * sizeof (const char *)); target_pats = xmalloc (c * sizeof (const char *)); targets[0] = name; target_pats[0] = implicit_percent; c = 1; while (filenames) { name = filenames->name; implicit_percent = find_percent_cached (&name); if (implicit_percent == 0) fatal (flocp, _("mixed implicit and normal rules")); targets[c] = name; target_pats[c] = implicit_percent; ++c; nextf = filenames->next; free_ns (filenames); filenames = nextf; } create_pattern_rule (targets, target_pats, c, two_colon, deps, cmds, 1); return; } /* Walk through each target and create it in the database. We already set up the first target, above. */ while (1) { struct nameseq *nextf = filenames->next; struct file *f; struct dep *this = 0; free_ns (filenames); /* Check for special targets. Do it here instead of, say, snap_deps() so that we can immediately use the value. */ if (streq (name, ".POSIX")) { posix_pedantic = 1; define_variable_cname (".SHELLFLAGS", "-ec", o_default, 0); } else if (streq (name, ".SECONDEXPANSION")) second_expansion = 1; #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION else if (streq (name, ".SECONDTARGETEXPANSION")) second_target_expansion = 1; #endif #if !defined(WINDOWS32) && !defined (__MSDOS__) && !defined (__EMX__) else if (streq (name, ".ONESHELL")) one_shell = 1; #endif #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* Check for the explicit multitarget mode operators. For this to be identified as an explicit multiple target rule, the first + or +| operator *must* appear between the first two files. If not found as the 2nd file or if found as the 1st file, the rule will be rejected as a potential multiple first target rule. For the subsequent files the operator is only required to switch between maybe and non-maybe mode: `primary + 2nd 3rd +| 4th-maybe + 5th-for-sure: deps; cmds' The whole idea of the maybe-updated files is this: timestamp +| maybe.h: src1.c src2.c grep goes-into-maybe.h $* > timestamp cmp timestamp maybe.h || cp -f timestamp maybe.h This is implemented in remake.c where we don't consider the mtime of the maybe-updated targets. */ if (multi_mode != m_no && name[0] == '+' && (name[1] == '\0' || (name[1] == '|' && name[2] == '\0'))) { if (!prev_file) multi_mode = m_no; /* first */ else { if (multi_mode == m_unsettled) { prev_file->multi_head = prev_file; /* Only the primary file needs the dependencies. */ if (deps) { free_dep_chain (deps); deps = NULL; } } multi_mode = name[1] == '\0' ? m_yes : m_yes_maybe; goto l_next; } } else if (multi_mode == m_unsettled && prev_file) multi_mode = m_no; #endif /* If this is a static pattern rule: `targets: target%pattern: prereq%pattern; recipe', make sure the pattern matches this target name. */ if (pattern && !pattern_matches (pattern, pattern_percent, name)) error (flocp, _("target `%s' doesn't match the target pattern"), name); else if (deps) /* If there are multiple targets, copy the chain DEPS for all but the last one. It is not safe for the same deps to go in more than one place in the database. */ this = nextf != 0 ? copy_dep_chain (deps) : deps; /* Find or create an entry in the file database for this target. */ if (!two_colon) { /* Single-colon. Combine this rule with the file's existing record, if any. */ #ifndef KMK f = enter_file (strcache_add (name)); #else /* KMK - the name is already in the cache, don't waste time. */ f = enter_file (name); #endif if (f->double_colon) fatal (flocp, _("target file `%s' has both : and :: entries"), f->name); /* If CMDS == F->CMDS, this target was listed in this rule more than once. Just give a warning since this is harmless. */ if (cmds != 0 && cmds == f->cmds) error (flocp, _("target `%s' given more than once in the same rule."), f->name); /* Check for two single-colon entries both with commands. Check is_target so that we don't lose on files such as .c.o whose commands were preinitialized. */ else if (cmds != 0 && f->cmds != 0 && f->is_target) { error (&cmds->fileinfo, _("warning: overriding recipe for target `%s'"), f->name); error (&f->cmds->fileinfo, _("warning: ignoring old recipe for target `%s'"), f->name); } /* Defining .DEFAULT with no deps or cmds clears it. */ if (f == default_file && this == 0 && cmds == 0) f->cmds = 0; if (cmds != 0) f->cmds = cmds; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* If this is an explicit multi target rule, add it to the target chain and set the multi_maybe flag according to the current mode. */ if (multi_mode >= m_yes) { f->multi_maybe = multi_mode == m_yes_maybe; prev_file->multi_next = f; assert (prev_file->multi_head != 0); f->multi_head = prev_file->multi_head; if (f == suffix_file) error (flocp, _(".SUFFIXES encountered in an explicit multi target rule")); } prev_file = f; #endif /* Defining .SUFFIXES with no dependencies clears out the list of suffixes. */ if (f == suffix_file && this == 0) { free_dep_chain (f->deps); f->deps = 0; } } else { /* Double-colon. Make a new record even if there already is one. */ #ifndef CONFIG_WITH_STRCACHE2 f = lookup_file (name); #else /* CONFIG_WITH_STRCACHE2 - the name is already in the cache, don't waste time. */ f = lookup_file_cached (name); #endif /* CONFIG_WITH_STRCACHE2 */ /* Check for both : and :: rules. Check is_target so we don't lose on default suffix rules or makefiles. */ if (f != 0 && f->is_target && !f->double_colon) fatal (flocp, _("target file `%s' has both : and :: entries"), f->name); #ifndef KMK f = enter_file (strcache_add (name)); #else /* KMK - the name is already in the cache, don't waste time. */ f = enter_file (name); #endif /* If there was an existing entry and it was a double-colon entry, enter_file will have returned a new one, making it the prev pointer of the old one, and setting its double_colon pointer to the first one. */ if (f->double_colon == 0) /* This is the first entry for this name, so we must set its double_colon pointer to itself. */ f->double_colon = f; f->cmds = cmds; } f->is_target = 1; /* If this is a static pattern rule, set the stem to the part of its name that matched the `%' in the pattern, so you can use $* in the commands. If we didn't do it before, enter the prereqs now. */ if (pattern) { static const char *percent = "%"; char *buffer = variable_expand (""); const size_t buffer_offset = buffer - variable_buffer; /* bird */ char *o = patsubst_expand_pat (buffer, name, pattern, percent, pattern_percent+1, percent+1); buffer = variable_buffer + buffer_offset; /* bird - variable_buffer may have been reallocated. */ f->stem = strcache_add_len (buffer, o - buffer); if (this) { if (! this->need_2nd_expansion) this = enter_prereqs (this, f->stem); else this->stem = f->stem; } } /* Add the dependencies to this file entry. */ if (this != 0) { /* Add the file's old deps and the new ones in THIS together. */ if (f->deps == 0) f->deps = this; else if (cmds != 0) { struct dep *d = this; /* If this rule has commands, put these deps first. */ while (d->next != 0) d = d->next; d->next = f->deps; f->deps = this; } else { struct dep *d = f->deps; /* A rule without commands: put its prereqs at the end. */ while (d->next != 0) d = d->next; d->next = this; } } name = f->name; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET l_next: #endif /* All done! Set up for the next one. */ if (nextf == 0) break; filenames = nextf; /* Reduce escaped percents. If there are any unescaped it's an error */ name = filenames->name; if (find_percent_cached (&name)) fatal (flocp, _("mixed implicit and normal rules")); } } /* Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero). Backslashes quote STOPCHAR, blanks if BLANK is nonzero, and backslash. Quoting backslashes are removed from STRING by compacting it into itself. Returns a pointer to the first unquoted STOPCHAR if there is one, or nil if there are none. STOPCHARs inside variable references are ignored if IGNOREVARS is true. STOPCHAR _cannot_ be '$' if IGNOREVARS is true. */ #ifndef CONFIG_WITH_VALUE_LENGTH static char * find_char_unquote (char *string, int stop1, int stop2, int blank, int ignorevars) #else static char * find_char_unquote_2 (char *string, int stop1, int stop2, int blank, int ignorevars, unsigned int string_len) #endif { #ifndef CONFIG_WITH_VALUE_LENGTH unsigned int string_len = 0; #endif char *p = string; register int ch; /* bird: 'optimiziations' */ #ifdef CONFIG_WITH_VALUE_LENGTH assert (string_len == 0 || string_len == strlen (string)); #endif if (ignorevars) ignorevars = '$'; while (1) { if (stop2 && blank) while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1 && ch != stop2 && ! isblank ((unsigned char) ch)) ++p; else if (stop2) while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1 && ch != stop2) ++p; else if (blank) while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1 && ! isblank ((unsigned char) ch)) ++p; else while ((ch = *p) != '\0' && ch != ignorevars && ch != stop1) ++p; if (ch == '\0') break; /* If we stopped due to a variable reference, skip over its contents. */ if (ch == ignorevars) { char openparen = p[1]; p += 2; /* Skip the contents of a non-quoted, multi-char variable ref. */ if (openparen == '(' || openparen == '{') { unsigned int pcount = 1; char closeparen = (openparen == '(' ? ')' : '}'); while ((ch = *p)) { if (ch == openparen) ++pcount; else if (ch == closeparen) if (--pcount == 0) { ++p; break; } ++p; } } /* Skipped the variable reference: look for STOPCHARS again. */ continue; } if (p > string && p[-1] == '\\') { /* Search for more backslashes. */ int i = -2; while (&p[i] >= string && p[i] == '\\') --i; ++i; /* Only compute the length if really needed. */ if (string_len == 0) string_len = strlen (string); /* The number of backslashes is now -I. Copy P over itself to swallow half of them. */ memmove (&p[i], &p[i/2], (string_len - (p - string)) - (i/2) + 1); p += i/2; if (i % 2 == 0) /* All the backslashes quoted each other; the STOPCHAR was unquoted. */ return p; /* The STOPCHAR was quoted by a backslash. Look for another. */ } else /* No backslash in sight. */ return p; } /* Never hit a STOPCHAR or blank (with BLANK nonzero). */ return 0; } #ifdef CONFIG_WITH_VALUE_LENGTH /* Special case version of find_char_unquote that only takes stop1. This is so common that it makes a lot of sense to specialize this. */ __inline static char * find_char_unquote_0 (char *string, int stop1, char **eosp) { unsigned int string_len = *eosp - string; char *p = (char *)memchr (string, stop1, string_len); assert (strlen (string) == string_len); if (!p) return NULL; if (p <= string || p[-1] != '\\') return p; p = find_char_unquote_2 (string, stop1, 0, 0, 0, string_len); *eosp = memchr (string, '\0', string_len); return p; } #endif /* Search PATTERN for an unquoted % and handle quoting. */ char * find_percent (char *pattern) { return find_char_unquote (pattern, '%', 0, 0, 0); } /* Search STRING for an unquoted % and handle quoting. Returns a pointer to the % or NULL if no % was found. This version is used with strings in the string cache: if there's a need to modify the string a new version will be added to the string cache and *STRING will be set to that. */ const char * find_percent_cached (const char **string) { const char *p = *string; char *new = 0; int slen = 0; /* If the first char is a % return now. This lets us avoid extra tests inside the loop. */ if (*p == '%') return p; while (1) { while (*p != '\0' && *p != '%') ++p; if (*p == '\0') break; /* See if this % is escaped with a backslash; if not we're done. */ if (p[-1] != '\\') break; { /* Search for more backslashes. */ char *pv; int i = -2; while (&p[i] >= *string && p[i] == '\\') --i; ++i; /* At this point we know we'll need to allocate a new string. Make a copy if we haven't yet done so. */ if (! new) { slen = strlen (*string); new = alloca (slen + 1); memcpy (new, *string, slen + 1); p = new + (p - *string); *string = new; } /* At this point *string, p, and new all point into the same string. Get a non-const version of p so we can modify new. */ pv = new + (p - *string); /* The number of backslashes is now -I. Copy P over itself to swallow half of them. */ memmove (&pv[i], &pv[i/2], (slen - (pv - new)) - (i/2) + 1); p += i/2; /* If the backslashes quoted each other; the % was unquoted. */ if (i % 2 == 0) break; } } /* If we had to change STRING, add it to the strcache. */ if (new) { *string = strcache_add (*string); p = *string + (p - new); } /* If we didn't find a %, return NULL. Otherwise return a ptr to it. */ return (*p == '\0') ? NULL : p; } /* Find the next line of text in an eval buffer, combining continuation lines into one line. Return the number of actual lines read (> 1 if continuation lines). Returns -1 if there's nothing left in the buffer. After this function, ebuf->buffer points to the first character of the line we just found. */ /* Read a line of text from a STRING. Since we aren't really reading from a file, don't bother with linenumbers. */ static unsigned long readstring (struct ebuffer *ebuf) { char *eol; #ifdef CONFIG_WITH_VALUE_LENGTH char *end; #endif /* If there is nothing left in this buffer, return 0. */ if (ebuf->bufnext >= ebuf->bufstart + ebuf->size) return -1; /* Set up a new starting point for the buffer, and find the end of the next logical line (taking into account backslash/newline pairs). */ eol = ebuf->buffer = ebuf->bufnext; #ifdef CONFIG_WITH_VALUE_LENGTH end = ebuf->bufstart + ebuf->size; #endif while (1) { int backslash = 0; const char *bol = eol; const char *p; /* Find the next newline. At EOS, stop. */ #ifndef CONFIG_WITH_VALUE_LENGTH p = eol = strchr (eol , '\n'); #else p = (char *)memchr (eol, '\n', end - eol); assert (!memchr (eol, '\0', p != 0 ? p - eol : end - eol)); eol = (char *)p; #endif if (!eol) { ebuf->bufnext = ebuf->bufstart + ebuf->size + 1; #ifdef CONFIG_WITH_VALUE_LENGTH ebuf->eol = end; #endif return 0; } /* Found a newline; if it's escaped continue; else we're done. */ while (p > bol && *(--p) == '\\') backslash = !backslash; if (!backslash) break; ++eol; } /* Overwrite the newline char. */ *eol = '\0'; ebuf->bufnext = eol+1; #ifdef CONFIG_WITH_VALUE_LENGTH ebuf->eol = eol; #endif return 0; } static long readline (struct ebuffer *ebuf) { char *p; char *end; char *start; long nlines = 0; /* The behaviors between string and stream buffers are different enough to warrant different functions. Do the Right Thing. */ if (!ebuf->fp) return readstring (ebuf); /* When reading from a file, we always start over at the beginning of the buffer for each new line. */ p = start = ebuf->bufstart; end = p + ebuf->size; *p = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH ebuf->eol = p; #endif while (fgets (p, end - p, ebuf->fp) != 0) { char *p2; unsigned long len; int backslash; len = strlen (p); if (len == 0) { /* This only happens when the first thing on the line is a '\0'. It is a pretty hopeless case, but (wonder of wonders) Athena lossage strikes again! (xmkmf puts NULs in its makefiles.) There is nothing really to be done; we synthesize a newline so the following line doesn't appear to be part of this line. */ error (&ebuf->floc, _("warning: NUL character seen; rest of line ignored")); p[0] = '\n'; len = 1; } /* Jump past the text we just read. */ p += len; /* If the last char isn't a newline, the whole line didn't fit into the buffer. Get some more buffer and try again. */ if (p[-1] != '\n') goto more_buffer; /* We got a newline, so add one to the count of lines. */ ++nlines; #if !defined(WINDOWS32) && !defined(__MSDOS__) && !defined(__EMX__) /* Check to see if the line was really ended with CRLF; if so ignore the CR. */ if ((p - start) > 1 && p[-2] == '\r') { --p; p[-1] = '\n'; } #endif backslash = 0; for (p2 = p - 2; p2 >= start; --p2) { if (*p2 != '\\') break; backslash = !backslash; } if (!backslash) { p[-1] = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH ebuf->eol = p - 1; #endif break; } /* It was a backslash/newline combo. If we have more space, read another line. */ if (end - p >= 80) { #ifdef CONFIG_WITH_VALUE_LENGTH ebuf->eol = p; #endif continue; } /* We need more space at the end of our buffer, so realloc it. Make sure to preserve the current offset of p. */ more_buffer: { unsigned long off = p - start; ebuf->size *= 2; start = ebuf->buffer = ebuf->bufstart = xrealloc (start, ebuf->size); p = start + off; end = start + ebuf->size; *p = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH ebuf->eol = p; #endif } } if (ferror (ebuf->fp)) pfatal_with_name (ebuf->floc.filenm); /* If we found some lines, return how many. If we didn't, but we did find _something_, that indicates we read the last line of a file with no final newline; return 1. If we read nothing, we're at EOF; return -1. */ return nlines ? nlines : p == ebuf->bufstart ? -1 : 1; } /* Parse the next "makefile word" from the input buffer, and return info about it. A "makefile word" is one of: w_bogus Should never happen w_eol End of input w_static A static word; cannot be expanded w_variable A word containing one or more variables/functions w_colon A colon w_dcolon A double-colon w_semicolon A semicolon w_varassign A variable assignment operator (=, :=, +=, >=, or ?=) Note that this function is only used when reading certain parts of the makefile. Don't use it where special rules hold sway (RHS of a variable, in a command list, etc.) */ static enum make_word_type get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length) { enum make_word_type wtype = w_bogus; char *p = buffer, *beg; char c; /* Skip any leading whitespace. */ while (isblank ((unsigned char)*p)) ++p; beg = p; c = *(p++); switch (c) { case '\0': wtype = w_eol; break; case ';': wtype = w_semicolon; break; case '=': wtype = w_varassign; break; case ':': wtype = w_colon; switch (*p) { case ':': ++p; wtype = w_dcolon; break; case '=': ++p; wtype = w_varassign; break; } break; case '+': case '?': #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT case '>': #endif if (*p == '=') { ++p; wtype = w_varassign; break; } default: if (delim && strchr (delim, c)) wtype = w_static; break; } /* Did we find something? If so, return now. */ if (wtype != w_bogus) goto done; /* This is some non-operator word. A word consists of the longest string of characters that doesn't contain whitespace, one of [:=#], or [?+]=, or one of the chars in the DELIM string. */ /* We start out assuming a static word; if we see a variable we'll adjust our assumptions then. */ wtype = w_static; /* We already found the first value of "c", above. */ while (1) { char closeparen; int count; switch (c) { case '\0': case ' ': case '\t': case '=': goto done_word; case ':': #ifdef HAVE_DOS_PATHS /* A word CAN include a colon in its drive spec. The drive spec is allowed either at the beginning of a word, or as part of the archive member name, like in "libfoo.a(d:/foo/bar.o)". */ if (!(p - beg >= 2 && (*p == '/' || *p == '\\') && isalpha ((unsigned char)p[-2]) && (p - beg == 2 || p[-3] == '('))) #endif goto done_word; case '$': c = *(p++); if (c == '$') break; /* This is a variable reference, so note that it's expandable. Then read it to the matching close paren. */ wtype = w_variable; if (c == '(') closeparen = ')'; else if (c == '{') closeparen = '}'; else /* This is a single-letter variable reference. */ break; for (count=0; *p != '\0'; ++p) { if (*p == c) ++count; else if (*p == closeparen && --count < 0) { ++p; break; } } break; case '?': case '+': #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT case '>': #endif if (*p == '=') goto done_word; break; case '\\': switch (*p) { case ':': case ';': case '=': case '\\': ++p; break; } break; default: if (delim && strchr (delim, c)) goto done_word; break; } c = *(p++); } done_word: --p; done: if (startp) *startp = beg; if (length) *length = p - beg; return wtype; } /* Construct the list of include directories from the arguments and the default list. */ void construct_include_path (const char **arg_dirs) { #ifdef VAXC /* just don't ask ... */ stat_t stbuf; #else struct stat stbuf; #endif const char **dirs; const char **cpp; unsigned int idx; /* Compute the number of pointers we need in the table. */ idx = sizeof (default_include_directories) / sizeof (const char *); if (arg_dirs) for (cpp = arg_dirs; *cpp != 0; ++cpp) ++idx; #ifdef __MSDOS__ /* Add one for $DJDIR. */ ++idx; #endif #ifdef KMK /* Add one for the kBuild directory. */ ++idx; #endif dirs = xmalloc (idx * sizeof (const char *)); idx = 0; max_incl_len = 0; /* First consider any dirs specified with -I switches. Ignore any that don't exist. Remember the maximum string length. */ if (arg_dirs) while (*arg_dirs != 0) { const char *dir = *(arg_dirs++); char *expanded = 0; int e; if (dir[0] == '~') { expanded = tilde_expand (dir); if (expanded != 0) dir = expanded; } EINTRLOOP (e, stat (dir, &stbuf)); if (e == 0 && S_ISDIR (stbuf.st_mode)) { unsigned int len = strlen (dir); /* If dir name is written with trailing slashes, discard them. */ while (len > 1 && dir[len - 1] == '/') --len; if (len > max_incl_len) max_incl_len = len; dirs[idx++] = strcache_add_len (dir, len); } if (expanded) free (expanded); } /* Now add the standard default dirs at the end. */ #ifdef __MSDOS__ { /* The environment variable $DJDIR holds the root of the DJGPP directory tree; add ${DJDIR}/include. */ struct variable *djdir = lookup_variable ("DJDIR", 5); if (djdir) { unsigned int len = strlen (djdir->value) + 8; char *defdir = alloca (len + 1); strcat (strcpy (defdir, djdir->value), "/include"); dirs[idx++] = strcache_add (defdir); if (len > max_incl_len) max_incl_len = len; } } #endif #ifdef KMK /* Add $(KBUILD_PATH). */ { size_t len = strlen (get_kbuild_path ()); dirs[idx++] = strcache_add_len (get_kbuild_path (), len); if (len > max_incl_len) max_incl_len = len; } #endif for (cpp = default_include_directories; *cpp != 0; ++cpp) { int e; EINTRLOOP (e, stat (*cpp, &stbuf)); if (e == 0 && S_ISDIR (stbuf.st_mode)) { unsigned int len = strlen (*cpp); /* If dir name is written with trailing slashes, discard them. */ while (len > 1 && (*cpp)[len - 1] == '/') --len; if (len > max_incl_len) max_incl_len = len; dirs[idx++] = strcache_add_len (*cpp, len); } } dirs[idx] = 0; /* Now add each dir to the .INCLUDE_DIRS variable. */ for (cpp = dirs; *cpp != 0; ++cpp) do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp, o_default, f_append, 0); include_directories = dirs; } /* Expand ~ or ~USER at the beginning of NAME. Return a newly malloc'd string or 0. */ char * tilde_expand (const char *name) { #ifndef VMS if (name[1] == '/' || name[1] == '\0') { extern char *getenv (); char *home_dir; int is_variable; { /* Turn off --warn-undefined-variables while we expand HOME. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; #ifndef CONFIG_WITH_VALUE_LENGTH home_dir = allocated_variable_expand ("$(HOME)"); #else home_dir = allocated_variable_expand_2 (STRING_SIZE_TUPLE("$(HOME)"), NULL); #endif warn_undefined_variables_flag = save; } is_variable = home_dir[0] != '\0'; if (!is_variable) { free (home_dir); home_dir = getenv ("HOME"); } # if !defined(_AMIGA) && !defined(WINDOWS32) if (home_dir == 0 || home_dir[0] == '\0') { extern char *getlogin (); char *logname = getlogin (); home_dir = 0; if (logname != 0) { struct passwd *p = getpwnam (logname); if (p != 0) home_dir = p->pw_dir; } } # endif /* !AMIGA && !WINDOWS32 */ if (home_dir != 0) { char *new = xstrdup (concat (2, home_dir, name + 1)); if (is_variable) free (home_dir); return new; } } # if !defined(_AMIGA) && !defined(WINDOWS32) else { struct passwd *pwent; char *userend = strchr (name + 1, '/'); if (userend != 0) *userend = '\0'; pwent = getpwnam (name + 1); if (pwent != 0) { if (userend == 0) return xstrdup (pwent->pw_dir); else return xstrdup (concat (3, pwent->pw_dir, "/", userend + 1)); } else if (userend != 0) *userend = '/'; } # endif /* !AMIGA && !WINDOWS32 */ #endif /* !VMS */ return 0; } /* Parse a string into a sequence of filenames represented as a chain of struct nameseq's and return that chain. Optionally expand the strings via glob(). The string is passed as STRINGP, the address of a string pointer. The string pointer is updated to point at the first character not parsed, which either is a null char or equals STOPCHAR. SIZE is how big to construct chain elements. This is useful if we want them actually to be other structures that have room for additional info. PREFIX, if non-null, is added to the beginning of each filename. FLAGS allows one or more of the following bitflags to be set: PARSEFS_NOSTRIP - Do no strip './'s off the beginning PARSEFS_NOAR - Do not check filenames for archive references PARSEFS_NOGLOB - Do not expand globbing characters PARSEFS_EXISTS - Only return globbed files that actually exist (cannot also set NOGLOB) PARSEFS_NOCACHE - Do not add filenames to the strcache (caller frees) */ void * parse_file_seq (char **stringp, unsigned int size, int stopchar, const char *prefix, int flags IF_WITH_ALLOC_CACHES_PARAM(struct alloccache *alloc_cache) ) { extern void dir_setup_glob (glob_t *glob); /* tmp points to tmpbuf after the prefix, if any. tp is the end of the buffer. */ static char *tmpbuf = NULL; static int tmpbuf_len = 0; int cachep = (! (flags & PARSEFS_NOCACHE)); struct nameseq *new = 0; struct nameseq **newp = &new; #ifndef CONFIG_WITH_ALLOC_CACHES #define NEWELT(_n) do { \ const char *__n = (_n); \ *newp = xcalloc (size); \ (*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \ newp = &(*newp)->next; \ } while(0) #else # define NEWELT(_n) do { \ const char *__n = (_n); \ *newp = alloccache_calloc (alloc_cache); \ (*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \ newp = &(*newp)->next; \ } while(0) #endif char *p; glob_t gl; char *tp; #ifdef VMS # define VMS_COMMA ',' #else # define VMS_COMMA 0 #endif if (size < sizeof (struct nameseq)) size = sizeof (struct nameseq); if (! (flags & PARSEFS_NOGLOB)) dir_setup_glob (&gl); /* Get enough temporary space to construct the largest possible target. */ { int l = strlen (*stringp) + 1; if (l > tmpbuf_len) { tmpbuf = xrealloc (tmpbuf, l); tmpbuf_len = l; } } tp = tmpbuf; /* Parse STRING. P will always point to the end of the parsed content. */ p = *stringp; while (1) { const char *name; const char **nlist = 0; char *tildep = 0; #ifndef NO_ARCHIVES char *arname = 0; char *memname = 0; #endif char *s; int nlen; int i; /* Skip whitespace; at the end of the string or STOPCHAR we're done. */ p = next_token (p); if (*p == '\0' || *p == stopchar) break; /* There are names left, so find the end of the next name. Throughout this iteration S points to the start. */ s = p; p = find_char_unquote (p, stopchar, VMS_COMMA, 1, 0); #ifdef VMS /* convert comma separated list to space separated */ if (p && *p == ',') *p =' '; #endif #ifdef _AMIGA if (stopchar == ':' && p && *p == ':' && !(isspace ((unsigned char)p[1]) || !p[1] || isspace ((unsigned char)p[-1]))) p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0); #endif #ifdef HAVE_DOS_PATHS /* For DOS paths, skip a "C:\..." or a "C:/..." until we find the first colon which isn't followed by a slash or a backslash. Note that tokens separated by spaces should be treated as separate tokens since make doesn't allow path names with spaces */ if (stopchar == ':') while (p != 0 && !isspace ((unsigned char)*p) && (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1])) p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0); #endif if (p == 0) p = s + strlen (s); /* Strip leading "this directory" references. */ if (! (flags & PARSEFS_NOSTRIP)) #ifdef VMS /* Skip leading `[]'s. */ while (p - s > 2 && s[0] == '[' && s[1] == ']') #else /* Skip leading `./'s. */ while (p - s > 2 && s[0] == '.' && s[1] == '/') #endif { /* Skip "./" and all following slashes. */ s += 2; while (*s == '/') ++s; } /* Extract the filename just found, and skip it. Set NAME to the string, and NLEN to its length. */ if (s == p) { /* The name was stripped to empty ("./"). */ #if defined(VMS) continue; #elif defined(_AMIGA) /* PDS-- This cannot be right!! */ tp[0] = '\0'; nlen = 0; #else tp[0] = '.'; tp[1] = '/'; tp[2] = '\0'; nlen = 2; #endif } else { #ifdef VMS /* VMS filenames can have a ':' in them but they have to be '\'ed but we need * to remove this '\' before we can use the filename. * xstrdup called because S may be read-only string constant. */ char *n = tp; while (s < p) { if (s[0] == '\\' && s[1] == ':') ++s; *(n++) = *(s++); } n[0] = '\0'; nlen = strlen (tp); #else nlen = p - s; memcpy (tp, s, nlen); tp[nlen] = '\0'; #endif } /* At this point, TP points to the element and NLEN is its length. */ #ifndef NO_ARCHIVES /* If this is the start of an archive group that isn't complete, set up to add the archive prefix for future files. A file list like: "libf.a(x.o y.o z.o)" needs to be expanded as: "libf.a(x.o) libf.a(y.o) libf.a(z.o)" TP == TMP means we're not already in an archive group. Ignore something starting with `(', as that cannot actually be an archive-member reference (and treating it as such results in an empty file name, which causes much lossage). Also if it ends in ")" then it's a complete reference so we don't need to treat it specially. Finally, note that archive groups must end with ')' as the last character, so ensure there's some word ending like that before considering this an archive group. */ if (! (flags & PARSEFS_NOAR) && tp == tmpbuf && tp[0] != '(' && tp[nlen-1] != ')') { char *n = strchr (tp, '('); if (n) { /* This looks like the first element in an open archive group. A valid group MUST have ')' as the last character. */ const char *e = p + nlen; do { e = next_token (e); /* Find the end of this word. We don't want to unquote and we don't care about quoting since we're looking for the last char in the word. */ while (*e != '\0' && *e != stopchar && *e != VMS_COMMA && ! isblank ((unsigned char) *e)) ++e; if (e[-1] == ')') { /* Found the end, so this is the first element in an open archive group. It looks like "lib(mem". Reset TP past the open paren. */ nlen -= (n + 1) - tp; tp = n + 1; /* If we have just "lib(", part of something like "lib( a b)", go to the next item. */ if (! nlen) continue; /* We can stop looking now. */ break; } } while (*e != '\0'); } } /* If we are inside an archive group, make sure it has an end. */ if (tp > tmpbuf) { if (tp[nlen-1] == ')') { /* This is the natural end; reset TP. */ tp = tmpbuf; /* This is just ")", something like "lib(a b )": skip it. */ if (nlen == 1) continue; } else { /* Not the end, so add a "fake" end. */ tp[nlen++] = ')'; tp[nlen] = '\0'; } } #endif /* If we're not globbing we're done: add it to the end of the chain. Go to the next item in the string. */ if (flags & PARSEFS_NOGLOB) { NEWELT (concat (2, prefix, tp)); continue; } /* If we get here we know we're doing glob expansion. TP is a string in tmpbuf. NLEN is no longer used. We may need to do more work: after this NAME will be set. */ name = tp; /* Expand tilde if applicable. */ if (tp[0] == '~') { tildep = tilde_expand (tp); if (tildep != 0) name = tildep; } #ifndef NO_ARCHIVES /* If NAME is an archive member reference replace it with the archive file name, and save the member name in MEMNAME. We will glob on the archive name and then reattach MEMNAME later. */ if (! (flags & PARSEFS_NOAR) && ar_name (name)) { ar_parse_name (name, &arname, &memname); name = arname; } #endif /* !NO_ARCHIVES */ switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl)) { case GLOB_NOSPACE: fatal (NILF, _("virtual memory exhausted")); case 0: /* Success. */ i = gl.gl_pathc; nlist = (const char **)gl.gl_pathv; break; case GLOB_NOMATCH: /* If we want only existing items, skip this one. */ if (flags & PARSEFS_EXISTS) { i = 0; break; } /* FALLTHROUGH */ default: /* By default keep this name. */ i = 1; nlist = &name; break; } /* For each matched element, add it to the list. */ while (i-- > 0) #ifndef NO_ARCHIVES if (memname != 0) { /* Try to glob on MEMNAME within the archive. */ struct nameseq *found = ar_glob (nlist[i], memname, size); if (! found) /* No matches. Use MEMNAME as-is. */ NEWELT (concat (5, prefix, nlist[i], "(", memname, ")")); else { /* We got a chain of items. Attach them. */ (*newp)->next = found; /* Find and set the new end. Massage names if necessary. */ while (1) { if (! cachep) found->name = xstrdup (concat (2, prefix, name)); else if (prefix) found->name = strcache_add (concat (2, prefix, name)); if (found->next == 0) break; found = found->next; } newp = &found->next; } } else #endif /* !NO_ARCHIVES */ NEWELT (concat (2, prefix, nlist[i])); globfree (&gl); #ifndef NO_ARCHIVES if (arname) free (arname); #endif if (tildep) free (tildep); } *stringp = p; return new; } kbuild-2695/src/kmk/dir.c0000644000000000000000000011174412247157306013743 0ustar rootroot/* Directory hashing for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "hash.h" #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) # ifdef VMS /* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */ const char *vmsify (const char *name, int type); # endif #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif # ifdef HAVE_VMSDIR_H # include "vmsdir.h" # endif /* HAVE_VMSDIR_H */ #endif /* bird: FreeBSD + smbfs -> readdir() + EBADF */ #ifdef __FreeBSD__ # include #endif /* bird: end */ #ifdef CONFIG_WITH_STRCACHE2 # include #endif /* In GNU systems, defines this macro for us. */ #ifdef _D_NAMLEN # undef NAMLEN # define NAMLEN(d) _D_NAMLEN(d) #endif #if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__) /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ # define REAL_DIR_ENTRY(dp) 1 # define FAKE_DIR_ENTRY(dp) #else # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) # define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1) #endif /* POSIX */ #ifdef __MSDOS__ #include #include /* If it's MSDOS that doesn't have _USE_LFN, disable LFN support. */ #ifndef _USE_LFN #define _USE_LFN 0 #endif static const char * dosify (const char *filename) { static char dos_filename[14]; char *df; int i; if (filename == 0 || _USE_LFN) return filename; /* FIXME: what about filenames which violate 8+3 constraints, like "config.h.in", or ".emacs"? */ if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0) return filename; df = dos_filename; /* First, transform the name part. */ for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i) *df++ = tolower ((unsigned char)*filename++); /* Now skip to the next dot. */ while (*filename != '\0' && *filename != '.') ++filename; if (*filename != '\0') { *df++ = *filename++; for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i) *df++ = tolower ((unsigned char)*filename++); } /* Look for more dots. */ while (*filename != '\0' && *filename != '.') ++filename; if (*filename == '.') return filename; *df = 0; return dos_filename; } #endif /* __MSDOS__ */ #ifdef WINDOWS32 #include "pathstuff.h" #endif #ifdef _AMIGA #include #endif #ifdef HAVE_CASE_INSENSITIVE_FS static const char * downcase (const char *filename) { static PATH_VAR (new_filename); char *df; if (filename == 0) return 0; df = new_filename; while (*filename != '\0') { *df++ = tolower ((unsigned char)*filename); ++filename; } *df = 0; return new_filename; } #endif /* HAVE_CASE_INSENSITIVE_FS */ #ifdef VMS static int vms_hash (const char *name) { int h = 0; int g; while (*name) { unsigned char uc = *name; #ifdef HAVE_CASE_INSENSITIVE_FS h = (h << 4) + (isupper (uc) ? tolower (uc) : uc); #else h = (h << 4) + uc; #endif name++; g = h & 0xf0000000; if (g) { h = h ^ (g >> 24); h = h ^ g; } } return h; } /* fake stat entry for a directory */ static int vmsstat_dir (const char *name, struct stat *st) { char *s; int h; DIR *dir; dir = opendir (name); if (dir == 0) return -1; closedir (dir); s = strchr (name, ':'); /* find device */ if (s) { /* to keep the compiler happy we said "const char *name", now we cheat */ *s++ = 0; st->st_dev = (char *)vms_hash (name); h = vms_hash (s); *(s-1) = ':'; } else { st->st_dev = 0; h = vms_hash (name); } st->st_ino[0] = h & 0xff; st->st_ino[1] = h & 0xff00; st->st_ino[2] = h >> 16; return 0; } #endif /* VMS */ /* Hash table of directories. */ #ifndef DIRECTORY_BUCKETS #ifdef KMK # define DIRECTORY_BUCKETS 4096 # else # define DIRECTORY_BUCKETS 199 # endif #endif struct directory_contents { dev_t dev; /* Device and inode numbers of this dir. */ #ifdef WINDOWS32 /* Inode means nothing on WINDOWS32. Even file key information is * unreliable because it is random per file open and undefined for remote * filesystems. The most unique attribute I can come up with is the fully * qualified name of the directory. Beware though, this is also * unreliable. I'm open to suggestion on a better way to emulate inode. */ # ifndef CONFIG_WITH_STRCACHE2 char *path_key; # else char const *path_key; /* strcache'ed */ # endif int ctime; int mtime; /* controls check for stale directory cache */ int fs_flags; /* FS_FAT, FS_NTFS, ... */ # define FS_FAT 0x1 # define FS_NTFS 0x2 # define FS_UNKNOWN 0x4 #else # ifdef VMS ino_t ino[3]; # else ino_t ino; # endif #endif /* WINDOWS32 */ struct hash_table dirfiles; /* Files in this directory. */ DIR *dirstream; /* Stream reading this directory. */ }; static unsigned long directory_contents_hash_1 (const void *key_0) { const struct directory_contents *key = key_0; unsigned long hash; #ifdef WINDOWS32 # ifndef CONFIG_WITH_STRCACHE2 hash = 0; ISTRING_HASH_1 (key->path_key, hash); # else /* CONFIG_WITH_STRCACHE2 */ hash = strcache2_calc_ptr_hash (&file_strcache, key->path_key); # endif /* CONFIG_WITH_STRCACHE2 */ hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime; #else # ifdef VMS hash = (((unsigned int) key->dev << 4) ^ ((unsigned int) key->ino[0] + (unsigned int) key->ino[1] + (unsigned int) key->ino[2])); # else hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino; # endif #endif /* WINDOWS32 */ return hash; } static unsigned long directory_contents_hash_2 (const void *key_0) { const struct directory_contents *key = key_0; unsigned long hash; #ifdef WINDOWS32 # ifndef CONFIG_WITH_STRCACHE2 hash = 0; ISTRING_HASH_2 (key->path_key, hash); # else /* CONFIG_WITH_STRCACHE2 */ hash = strcache2_get_hash (&file_strcache, key->path_key); # endif /* CONFIG_WITH_STRCACHE2 */ hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime; #else # ifdef VMS hash = (((unsigned int) key->dev << 4) ^ ~((unsigned int) key->ino[0] + (unsigned int) key->ino[1] + (unsigned int) key->ino[2])); # else hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino; # endif #endif /* WINDOWS32 */ return hash; } /* Sometimes it's OK to use subtraction to get this value: result = X - Y; But, if we're not sure of the type of X and Y they may be too large for an int (on a 64-bit system for example). So, use ?: instead. See Savannah bug #15534. NOTE! This macro has side-effects! */ #define MAKECMP(_x,_y) ((_x)<(_y)?-1:((_x)==(_y)?0:1)) static int directory_contents_hash_cmp (const void *xv, const void *yv) { const struct directory_contents *x = xv; const struct directory_contents *y = yv; int result; #ifdef WINDOWS32 # ifndef CONFIG_WITH_STRCACHE2 ISTRING_COMPARE (x->path_key, y->path_key, result); if (result) return result; # else /* CONFIG_WITH_STRCACHE2 */ if (x->path_key != y->path_key) return -1; # endif /* CONFIG_WITH_STRCACHE2 */ result = MAKECMP(x->ctime, y->ctime); if (result) return result; #else # ifdef VMS result = MAKECMP(x->ino[0], y->ino[0]); if (result) return result; result = MAKECMP(x->ino[1], y->ino[1]); if (result) return result; result = MAKECMP(x->ino[2], y->ino[2]); if (result) return result; # else result = MAKECMP(x->ino, y->ino); if (result) return result; # endif #endif /* WINDOWS32 */ return MAKECMP(x->dev, y->dev); } /* Table of directory contents hashed by device and inode number. */ static struct hash_table directory_contents; #ifdef CONFIG_WITH_ALLOC_CACHES /* Allocation cache for directory contents. */ struct alloccache directory_contents_cache; #endif struct directory { const char *name; /* Name of the directory. */ /* The directory's contents. This data may be shared by several entries in the hash table, which refer to the same directory (identified uniquely by `dev' and `ino') under different names. */ struct directory_contents *contents; }; #ifndef CONFIG_WITH_STRCACHE2 static unsigned long directory_hash_1 (const void *key) { return_ISTRING_HASH_1 (((const struct directory *) key)->name); } static unsigned long directory_hash_2 (const void *key) { return_ISTRING_HASH_2 (((const struct directory *) key)->name); } static int directory_hash_cmp (const void *x, const void *y) { return_ISTRING_COMPARE (((const struct directory *) x)->name, ((const struct directory *) y)->name); } #endif /* !CONFIG_WITH_STRCACHE2 */ /* Table of directories hashed by name. */ static struct hash_table directories; #ifdef CONFIG_WITH_ALLOC_CACHES /* Allocation cache for directories. */ struct alloccache directories_cache; #endif /* Never have more than this many directories open at once. */ #define MAX_OPEN_DIRECTORIES 10 static unsigned int open_directories = 0; /* Hash table of files in each directory. */ struct dirfile { const char *name; /* Name of the file. */ short length; short impossible; /* This file is impossible. */ }; #ifndef CONFIG_WITH_STRCACHE2 static unsigned long dirfile_hash_1 (const void *key) { return_ISTRING_HASH_1 (((struct dirfile const *) key)->name); } static unsigned long dirfile_hash_2 (const void *key) { return_ISTRING_HASH_2 (((struct dirfile const *) key)->name); } static int dirfile_hash_cmp (const void *xv, const void *yv) { const struct dirfile *x = xv; const struct dirfile *y = yv; int result = x->length - y->length; if (result) return result; return_ISTRING_COMPARE (x->name, y->name); } #endif /* !CONFIG_WITH_STRCACHE2 */ #ifndef DIRFILE_BUCKETS #define DIRFILE_BUCKETS 107 #endif #ifdef CONFIG_WITH_ALLOC_CACHES /* Allocation cache for dirfiles. */ struct alloccache dirfile_cache; #endif static int dir_contents_file_exists_p (struct directory_contents *dir, const char *filename); static struct directory *find_directory (const char *name); /* Find the directory named NAME and return its `struct directory'. */ static struct directory * find_directory (const char *name) { const char *p; struct directory *dir; struct directory **dir_slot; struct directory dir_key; int r; #ifdef WINDOWS32 char* w32_path; char fs_label[BUFSIZ]; char fs_type[BUFSIZ]; unsigned long fs_serno; unsigned long fs_flags; unsigned long fs_len; #endif #ifdef VMS if ((*name == '.') && (*(name+1) == 0)) name = "[]"; else name = vmsify (name,1); #endif #ifndef CONFIG_WITH_STRCACHE2 dir_key.name = name; dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key); #else p = name + strlen (name); # if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) dir_key.name = strcache_add_len (downcase(name), p - name); # else dir_key.name = strcache_add_len (name, p - name); # endif dir_slot = (struct directory **) hash_find_slot_strcached (&directories, &dir_key); #endif dir = *dir_slot; if (HASH_VACANT (dir)) { struct stat st; /* The directory was not found. Create a new entry for it. */ #ifndef CONFIG_WITH_STRCACHE2 p = name + strlen (name); #endif #ifndef CONFIG_WITH_ALLOC_CACHES dir = xmalloc (sizeof (struct directory)); #else dir = alloccache_alloc (&directories_cache); #endif #ifndef CONFIG_WITH_STRCACHE2 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) dir->name = strcache_add_len (downcase(name), p - name); #else dir->name = strcache_add_len (name, p - name); #endif #else /* CONFIG_WITH_STRCACHE2 */ dir->name = dir_key.name; #endif /* CONFIG_WITH_STRCACHE2 */ hash_insert_at (&directories, dir, dir_slot); /* The directory is not in the name hash table. Find its device and inode numbers, and look it up by them. */ #ifdef VMS r = vmsstat_dir (name, &st); #elif defined(WINDOWS32) { char tem[MAXPATHLEN], *tstart, *tend; /* Remove any trailing slashes. Windows32 stat fails even on valid directories if they end in a slash. */ memcpy (tem, name, p - name + 1); tstart = tem; if (tstart[1] == ':') tstart += 2; for (tend = tem + (p - name - 1); tend > tstart && (*tend == '/' || *tend == '\\'); tend--) *tend = '\0'; r = stat (tem, &st); } #else EINTRLOOP (r, stat (name, &st)); #endif if (r < 0) { /* Couldn't stat the directory. Mark this by setting the `contents' member to a nil pointer. */ dir->contents = 0; } else { /* Search the contents hash table; device and inode are the key. */ struct directory_contents *dc; struct directory_contents **dc_slot; struct directory_contents dc_key; dc_key.dev = st.st_dev; #ifdef WINDOWS32 # ifndef CONFIG_WITH_STRCACHE2 dc_key.path_key = w32_path = w32ify (name, 1); # else /* CONFIG_WITH_STRCACHE2 */ w32_path = w32ify (name, 1); dc_key.path_key = strcache_add (w32_path); # endif /* CONFIG_WITH_STRCACHE2 */ dc_key.ctime = st.st_ctime; #else # ifdef VMS dc_key.ino[0] = st.st_ino[0]; dc_key.ino[1] = st.st_ino[1]; dc_key.ino[2] = st.st_ino[2]; # else dc_key.ino = st.st_ino; # endif #endif dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key); dc = *dc_slot; if (HASH_VACANT (dc)) { /* Nope; this really is a directory we haven't seen before. */ #ifndef CONFIG_WITH_ALLOC_CACHES dc = (struct directory_contents *) xmalloc (sizeof (struct directory_contents)); #else dc = (struct directory_contents *) alloccache_alloc (&directory_contents_cache); #endif /* Enter it in the contents hash table. */ dc->dev = st.st_dev; #ifdef WINDOWS32 # ifndef CONFIG_WITH_STRCACHE2 dc->path_key = xstrdup (w32_path); # else /* CONFIG_WITH_STRCACHE2 */ dc->path_key = dc_key.path_key; # endif /* CONFIG_WITH_STRCACHE2 */ dc->ctime = st.st_ctime; dc->mtime = st.st_mtime; /* * NTFS is the only WINDOWS32 filesystem that bumps mtime * on a directory when files are added/deleted from * a directory. */ w32_path[3] = '\0'; if (GetVolumeInformation(w32_path, fs_label, sizeof (fs_label), &fs_serno, &fs_len, &fs_flags, fs_type, sizeof (fs_type)) == FALSE) dc->fs_flags = FS_UNKNOWN; else if (!strcmp(fs_type, "FAT")) dc->fs_flags = FS_FAT; else if (!strcmp(fs_type, "NTFS")) dc->fs_flags = FS_NTFS; else dc->fs_flags = FS_UNKNOWN; #else # ifdef VMS dc->ino[0] = st.st_ino[0]; dc->ino[1] = st.st_ino[1]; dc->ino[2] = st.st_ino[2]; # else dc->ino = st.st_ino; # endif #endif /* WINDOWS32 */ hash_insert_at (&directory_contents, dc, dc_slot); ENULLLOOP (dc->dirstream, opendir (name)); if (dc->dirstream == 0) /* Couldn't open the directory. Mark this by setting the `files' member to a nil pointer. */ dc->dirfiles.ht_vec = 0; else { #ifdef KMK int buckets = st.st_nlink * 2; if (buckets < DIRFILE_BUCKETS) buckets = DIRFILE_BUCKETS; hash_init_strcached (&dc->dirfiles, buckets, &file_strcache, offsetof (struct dirfile, name)); #else # ifndef CONFIG_WITH_STRCACHE2 hash_init (&dc->dirfiles, DIRFILE_BUCKETS, dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); # else /* CONFIG_WITH_STRCACHE2 */ hash_init_strcached (&dc->dirfiles, DIRFILE_BUCKETS, &file_strcache, offsetof (struct dirfile, name)); # endif /* CONFIG_WITH_STRCACHE2 */ #endif /* Keep track of how many directories are open. */ ++open_directories; if (open_directories == MAX_OPEN_DIRECTORIES) /* We have too many directories open already. Read the entire directory and then close it. */ dir_contents_file_exists_p (dc, 0); } } /* Point the name-hashed entry for DIR at its contents data. */ dir->contents = dc; } } return dir; } /* Return 1 if the name FILENAME is entered in DIR's hash table. FILENAME must contain no slashes. */ static int dir_contents_file_exists_p (struct directory_contents *dir, const char *filename) { unsigned int hash; struct dirfile *df; struct dirent *d; #ifdef WINDOWS32 struct stat st; int rehash = 0; #endif if (dir == 0 || dir->dirfiles.ht_vec == 0) /* The directory could not be stat'd or opened. */ return 0; #ifdef __MSDOS__ filename = dosify (filename); #endif #ifdef HAVE_CASE_INSENSITIVE_FS filename = downcase (filename); #endif #ifdef __EMX__ if (filename != 0) _fnlwr (filename); /* lower case for FAT drives */ #endif #ifdef VMS filename = vmsify (filename,0); #endif hash = 0; if (filename != 0) { struct dirfile dirfile_key; if (*filename == '\0') { /* Checking if the directory exists. */ return 1; } #ifndef CONFIG_WITH_STRCACHE2 dirfile_key.name = filename; dirfile_key.length = strlen (filename); df = hash_find_item (&dir->dirfiles, &dirfile_key); #else /* CONFIG_WITH_STRCACHE2 */ dirfile_key.length = strlen (filename); dirfile_key.name = filename = strcache_add_len (filename, dirfile_key.length); df = hash_find_item_strcached (&dir->dirfiles, &dirfile_key); #endif /* CONFIG_WITH_STRCACHE2 */ if (df) return !df->impossible; } /* The file was not found in the hashed list. Try to read the directory further. */ if (dir->dirstream == 0) { #ifdef WINDOWS32 /* * Check to see if directory has changed since last read. FAT * filesystems force a rehash always as mtime does not change * on directories (ugh!). */ if (dir->path_key) { if ((dir->fs_flags & FS_FAT) != 0) { dir->mtime = time ((time_t *) 0); rehash = 1; } else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime) { /* reset date stamp to show most recent re-process. */ dir->mtime = st.st_mtime; rehash = 1; } /* If it has been already read in, all done. */ if (!rehash) return 0; /* make sure directory can still be opened; if not return. */ dir->dirstream = opendir (dir->path_key); if (!dir->dirstream) return 0; } else #endif /* The directory has been all read in. */ return 0; } while (1) { /* Enter the file in the hash table. */ unsigned int len; struct dirfile dirfile_key; struct dirfile **dirfile_slot; ENULLLOOP (d, readdir (dir->dirstream)); if (d == 0) { /* bird: Workaround for smbfs mounts returning EBADF at the end of the search. To exactly determin the cause here, I should probably do some smbfs tracing, but for now just ignoring the EBADF on seems to work. (The smb server is 64-bit vista, btw.) */ #if defined (__FreeBSD__) struct statfs stfs; int saved_errno = errno; errno = 0; if (saved_errno == EBADF && !fstatfs (dirfd (dir->dirstream), &stfs) && !(stfs.f_flags & MNT_LOCAL) && !strcmp(stfs.f_fstypename, "smbfs")) { /*fprintf (stderr, "EBADF on remote fs! dirfd=%d errno=%d\n", dirfd (dir->dirstream), errno);*/ saved_errno = 0; } errno = saved_errno; #endif /* bird: end */ if (errno) fatal (NILF, "INTERNAL: readdir(%p): %s (filename=%s)\n", (void *)dir, strerror (errno), filename); break; } #if defined(VMS) && defined(HAVE_DIRENT_H) /* In VMS we get file versions too, which have to be stripped off */ { char *p = strrchr (d->d_name, ';'); if (p) *p = '\0'; } #endif if (!REAL_DIR_ENTRY (d)) continue; len = NAMLEN (d); #ifndef CONFIG_WITH_STRCACHE2 dirfile_key.name = d->d_name; dirfile_key.length = len; dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key); #else # if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) dirfile_key.name = strcache_add_len (downcase(d->d_name), len); # else dirfile_key.name = strcache_add_len (d->d_name, len); # endif dirfile_key.length = len; dirfile_slot = (struct dirfile **) hash_find_slot_strcached (&dir->dirfiles, &dirfile_key); #endif #ifdef WINDOWS32 /* * If re-reading a directory, don't cache files that have * already been discovered. */ if (! rehash || HASH_VACANT (*dirfile_slot)) #endif { #ifndef CONFIG_WITH_ALLOC_CACHES df = xmalloc (sizeof (struct dirfile)); #else df = alloccache_alloc (&dirfile_cache); #endif #ifndef CONFIG_WITH_STRCACHE2 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) df->name = strcache_add_len (downcase(d->d_name), len); #else df->name = strcache_add_len (d->d_name, len); #endif #else /* CONFIG_WITH_STRCACHE2 */ df->name = dirfile_key.name; #endif /* CONFIG_WITH_STRCACHE2 */ df->length = len; df->impossible = 0; hash_insert_at (&dir->dirfiles, df, dirfile_slot); } /* Check if the name matches the one we're searching for. */ #ifndef CONFIG_WITH_STRCACHE2 if (filename != 0 && patheq (d->d_name, filename)) #else if (filename != 0 && dirfile_key.name == filename) #endif return 1; } /* If the directory has been completely read in, close the stream and reset the pointer to nil. */ if (d == 0) { --open_directories; closedir (dir->dirstream); dir->dirstream = 0; } return 0; } /* Return 1 if the name FILENAME in directory DIRNAME is entered in the dir hash table. FILENAME must contain no slashes. */ int dir_file_exists_p (const char *dirname, const char *filename) { return dir_contents_file_exists_p (find_directory (dirname)->contents, filename); } /* Return 1 if the file named NAME exists. */ int file_exists_p (const char *name) { const char *dirend; const char *dirname; const char *slash; #ifndef NO_ARCHIVES if (ar_name (name)) return ar_member_date (name) != (time_t) -1; #endif #ifdef VMS dirend = strrchr (name, ']'); if (dirend == 0) dirend = strrchr (name, ':'); if (dirend == 0) return dir_file_exists_p ("[]", name); #else /* !VMS */ dirend = strrchr (name, '/'); #ifdef HAVE_DOS_PATHS /* Forward and backslashes might be mixed. We need the rightmost one. */ { const char *bslash = strrchr(name, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && name[0] && name[1] == ':') dirend = name + 1; } #endif /* HAVE_DOS_PATHS */ if (dirend == 0) #ifndef _AMIGA return dir_file_exists_p (".", name); #else /* !VMS && !AMIGA */ return dir_file_exists_p ("", name); #endif /* AMIGA */ #endif /* VMS */ slash = dirend; if (dirend == name) dirname = "/"; else { char *p; #ifdef HAVE_DOS_PATHS /* d:/ and d: are *very* different... */ if (dirend < name + 3 && name[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++; #endif p = alloca (dirend - name + 1); memcpy (p, name, dirend - name); p[dirend - name] = '\0'; dirname = p; } return dir_file_exists_p (dirname, slash + 1); } /* Mark FILENAME as `impossible' for `file_impossible_p'. This means an attempt has been made to search for FILENAME as an intermediate file, and it has failed. */ void file_impossible (const char *filename) { const char *dirend; const char *p = filename; struct directory *dir; struct dirfile *new; #ifdef VMS dirend = strrchr (p, ']'); if (dirend == 0) dirend = strrchr (p, ':'); dirend++; if (dirend == (char *)1) dir = find_directory ("[]"); #else dirend = strrchr (p, '/'); # ifdef HAVE_DOS_PATHS /* Forward and backslashes might be mixed. We need the rightmost one. */ { const char *bslash = strrchr(p, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && p[0] && p[1] == ':') dirend = p + 1; } # endif /* HAVE_DOS_PATHS */ if (dirend == 0) # ifdef _AMIGA dir = find_directory (""); # else /* !VMS && !AMIGA */ dir = find_directory ("."); # endif /* AMIGA */ #endif /* VMS */ else { const char *dirname; const char *slash = dirend; if (dirend == p) dirname = "/"; else { char *cp; #ifdef HAVE_DOS_PATHS /* d:/ and d: are *very* different... */ if (dirend < p + 3 && p[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++; #endif cp = alloca (dirend - p + 1); memcpy (cp, p, dirend - p); cp[dirend - p] = '\0'; dirname = cp; } dir = find_directory (dirname); filename = p = slash + 1; } if (dir->contents == 0) /* The directory could not be stat'd. We allocate a contents structure for it, but leave it out of the contents hash table. */ #ifndef CONFIG_WITH_ALLOC_CACHES dir->contents = xcalloc (sizeof (struct directory_contents)); #else dir->contents = alloccache_calloc (&directory_contents_cache); #endif if (dir->contents->dirfiles.ht_vec == 0) { #ifndef CONFIG_WITH_STRCACHE2 hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS, dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); #else /* CONFIG_WITH_STRCACHE2 */ hash_init_strcached (&dir->contents->dirfiles, DIRFILE_BUCKETS, &file_strcache, offsetof (struct dirfile, name)); #endif /* CONFIG_WITH_STRCACHE2 */ } /* Make a new entry and put it in the table. */ #ifndef CONFIG_WITH_ALLOC_CACHES new = xmalloc (sizeof (struct dirfile)); #else new = alloccache_alloc (&dirfile_cache); #endif new->length = strlen (filename); #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) new->name = strcache_add_len (downcase(filename), new->length); #else new->name = strcache_add_len (filename, new->length); #endif new->impossible = 1; #ifndef CONFIG_WITH_STRCACHE2 hash_insert (&dir->contents->dirfiles, new); #else /* CONFIG_WITH_STRCACHE2 */ hash_insert_strcached (&dir->contents->dirfiles, new); #endif /* CONFIG_WITH_STRCACHE2 */ } /* Return nonzero if FILENAME has been marked impossible. */ int file_impossible_p (const char *filename) { const char *dirend; const char *p = filename; struct directory_contents *dir; struct dirfile *dirfile; struct dirfile dirfile_key; #ifdef VMS dirend = strrchr (filename, ']'); if (dirend == 0) dir = find_directory ("[]")->contents; #else dirend = strrchr (filename, '/'); #ifdef HAVE_DOS_PATHS /* Forward and backslashes might be mixed. We need the rightmost one. */ { const char *bslash = strrchr(filename, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && filename[0] && filename[1] == ':') dirend = filename + 1; } #endif /* HAVE_DOS_PATHS */ if (dirend == 0) #ifdef _AMIGA dir = find_directory ("")->contents; #else /* !VMS && !AMIGA */ dir = find_directory (".")->contents; #endif /* AMIGA */ #endif /* VMS */ else { const char *dirname; const char *slash = dirend; if (dirend == filename) dirname = "/"; else { char *cp; #ifdef HAVE_DOS_PATHS /* d:/ and d: are *very* different... */ if (dirend < filename + 3 && filename[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++; #endif cp = alloca (dirend - filename + 1); memcpy (cp, p, dirend - p); cp[dirend - p] = '\0'; dirname = cp; } dir = find_directory (dirname)->contents; p = filename = slash + 1; } if (dir == 0 || dir->dirfiles.ht_vec == 0) /* There are no files entered for this directory. */ return 0; #ifdef __MSDOS__ filename = dosify (p); #endif #ifdef HAVE_CASE_INSENSITIVE_FS filename = downcase (p); #endif #ifdef VMS filename = vmsify (p, 1); #endif #ifndef CONFIG_WITH_STRCACHE2 dirfile_key.name = filename; dirfile_key.length = strlen (filename); dirfile = hash_find_item (&dir->dirfiles, &dirfile_key); #else dirfile_key.length = strlen (filename); dirfile_key.name = strcache_add_len (filename, dirfile_key.length); dirfile = hash_find_item_strcached (&dir->dirfiles, &dirfile_key); #endif if (dirfile) return dirfile->impossible; return 0; } /* Return the already allocated name in the directory hash table that matches DIR. */ const char * dir_name (const char *dir) { return find_directory (dir)->name; } /* Print the data base of directories. */ void print_dir_data_base (void) { unsigned int files; unsigned int impossible; struct directory **dir_slot; struct directory **dir_end; puts (_("\n# Directories\n")); files = impossible = 0; dir_slot = (struct directory **) directories.ht_vec; dir_end = dir_slot + directories.ht_size; for ( ; dir_slot < dir_end; dir_slot++) { struct directory *dir = *dir_slot; if (! HASH_VACANT (dir)) { if (dir->contents == 0) printf (_("# %s: could not be stat'd.\n"), dir->name); else if (dir->contents->dirfiles.ht_vec == 0) { #ifdef WINDOWS32 printf (_("# %s (key %s, mtime %d): could not be opened.\n"), dir->name, dir->contents->path_key,dir->contents->mtime); #else /* WINDOWS32 */ #ifdef VMS printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"), dir->name, dir->contents->dev, dir->contents->ino[0], dir->contents->ino[1], dir->contents->ino[2]); #else printf (_("# %s (device %ld, inode %ld): could not be opened.\n"), dir->name, (long int) dir->contents->dev, (long int) dir->contents->ino); #endif #endif /* WINDOWS32 */ } else { unsigned int f = 0; unsigned int im = 0; struct dirfile **files_slot; struct dirfile **files_end; files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec; files_end = files_slot + dir->contents->dirfiles.ht_size; for ( ; files_slot < files_end; files_slot++) { struct dirfile *df = *files_slot; if (! HASH_VACANT (df)) { if (df->impossible) ++im; else ++f; } } #ifdef WINDOWS32 printf (_("# %s (key %s, mtime %d): "), dir->name, dir->contents->path_key, dir->contents->mtime); #else /* WINDOWS32 */ #ifdef VMS printf (_("# %s (device %d, inode [%d,%d,%d]): "), dir->name, dir->contents->dev, dir->contents->ino[0], dir->contents->ino[1], dir->contents->ino[2]); #else printf (_("# %s (device %ld, inode %ld): "), dir->name, (long)dir->contents->dev, (long)dir->contents->ino); #endif #endif /* WINDOWS32 */ if (f == 0) fputs (_("No"), stdout); else printf ("%u", f); fputs (_(" files, "), stdout); if (im == 0) fputs (_("no"), stdout); else printf ("%u", im); fputs (_(" impossibilities"), stdout); if (dir->contents->dirstream == 0) puts ("."); else puts (_(" so far.")); files += f; impossible += im; #ifdef KMK fputs ("# ", stdout); hash_print_stats (&dir->contents->dirfiles, stdout); fputs ("\n", stdout); #endif } } } fputs ("\n# ", stdout); if (files == 0) fputs (_("No"), stdout); else printf ("%u", files); fputs (_(" files, "), stdout); if (impossible == 0) fputs (_("no"), stdout); else printf ("%u", impossible); printf (_(" impossibilities in %lu directories.\n"), directories.ht_fill); #ifdef KMK fputs ("# directories: ", stdout); hash_print_stats (&directories, stdout); fputs ("\n# directory_contents: ", stdout); hash_print_stats (&directory_contents, stdout); fputs ("\n", stdout); #endif } /* Hooks for globbing. */ #include /* Structure describing state of iterating through a directory hash table. */ struct dirstream { struct directory_contents *contents; /* The directory being read. */ struct dirfile **dirfile_slot; /* Current slot in table. */ }; /* Forward declarations. */ static __ptr_t open_dirstream (const char *); static struct dirent *read_dirstream (__ptr_t); static __ptr_t open_dirstream (const char *directory) { struct dirstream *new; struct directory *dir = find_directory (directory); if (dir->contents == 0 || dir->contents->dirfiles.ht_vec == 0) /* DIR->contents is nil if the directory could not be stat'd. DIR->contents->dirfiles is nil if it could not be opened. */ return 0; /* Read all the contents of the directory now. There is no benefit in being lazy, since glob will want to see every file anyway. */ dir_contents_file_exists_p (dir->contents, 0); new = xmalloc (sizeof (struct dirstream)); new->contents = dir->contents; new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec; return (__ptr_t) new; } static struct dirent * read_dirstream (__ptr_t stream) { static char *buf; static unsigned int bufsz; struct dirstream *const ds = (struct dirstream *) stream; struct directory_contents *dc = ds->contents; struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size; while (ds->dirfile_slot < dirfile_end) { struct dirfile *df = *ds->dirfile_slot++; if (! HASH_VACANT (df) && !df->impossible) { /* The glob interface wants a `struct dirent', so mock one up. */ struct dirent *d; unsigned int len = df->length + 1; unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len; if (sz > bufsz) { bufsz *= 2; if (sz > bufsz) bufsz = sz; buf = xrealloc (buf, bufsz); } d = (struct dirent *) buf; #ifdef __MINGW32__ # if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \ __MINGW32_MINOR_VERSION == 0) d->d_name = xmalloc(len); # endif #endif FAKE_DIR_ENTRY (d); #ifdef _DIRENT_HAVE_D_NAMLEN d->d_namlen = len - 1; #endif #ifdef _DIRENT_HAVE_D_TYPE d->d_type = DT_UNKNOWN; #endif memcpy (d->d_name, df->name, len); return d; } } return 0; } static void ansi_free (void *p) { if (p) free(p); } /* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a * macro for stat64(). If stat is a macro, make a local wrapper function to * invoke it. */ #ifndef stat # ifndef VMS int stat (const char *path, struct stat *sbuf); # endif # define local_stat stat #else static int local_stat (const char *path, struct stat *buf) { int e; EINTRLOOP (e, stat (path, buf)); return e; } #endif void dir_setup_glob (glob_t *gl) { gl->gl_opendir = open_dirstream; gl->gl_readdir = read_dirstream; gl->gl_closedir = ansi_free; gl->gl_stat = local_stat; #ifdef __EMX__ /* The FreeBSD implementation actually uses gl_lstat!! */ gl->gl_lstat = local_stat; #endif /* We don't bother setting gl_lstat, since glob never calls it. The slot is only there for compatibility with 4.4 BSD. */ } void hash_init_directories (void) { #ifndef CONFIG_WITH_STRCACHE2 hash_init (&directories, DIRECTORY_BUCKETS, directory_hash_1, directory_hash_2, directory_hash_cmp); #else /* CONFIG_WITH_STRCACHE2 */ hash_init_strcached (&directories, DIRECTORY_BUCKETS, &file_strcache, offsetof (struct directory, name)); #endif /* CONFIG_WITH_STRCACHE2 */ hash_init (&directory_contents, DIRECTORY_BUCKETS, directory_contents_hash_1, directory_contents_hash_2, directory_contents_hash_cmp); #ifdef CONFIG_WITH_ALLOC_CACHES alloccache_init (&directories_cache, sizeof (struct directory), "directories", NULL, NULL); alloccache_init (&directory_contents_cache, sizeof (struct directory_contents), "directory_contents", NULL, NULL); alloccache_init (&dirfile_cache, sizeof (struct dirfile), "dirfile", NULL, NULL); #endif /* CONFIG_WITH_ALLOC_CACHES */ } kbuild-2695/src/kmk/config.h.haiku0000644000000000000000000003133712247157307015537 0ustar rootroot/* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using `getloadavg.c'. */ #define C_GETLOADAVG 1 /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 1 /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ #define HAVE_CLOCK_GETTIME 1 /* Define to 1 if you have the declaration of `bsd_signal', and to 0 if you don't. */ #define HAVE_DECL_BSD_SIGNAL 0 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you don't. */ #define HAVE_DECL__SYS_SIGLIST 0 /* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you don't. */ #define HAVE_DECL___SYS_SIGLIST 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Use platform specific coding */ /* #undef HAVE_DOS_PATHS */ /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 /* Define to 1 if you have the `fileno' function. */ #define HAVE_FILENO 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getgroups' function. */ #define HAVE_GETGROUPS 1 /* Define to 1 if you have the `gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the `gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the `getloadavg' function. */ /* #undef HAVE_GETLOADAVG */ /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have a standard gettimeofday function */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the `kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the `lstat' function. */ #define HAVE_LSTAT 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the `pipe' function. */ #define HAVE_PIPE 1 /* Define to 1 if you have the `pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the `readlink' function. */ #define HAVE_READLINK 1 /* Define to 1 if you have the `realpath' function. */ #define HAVE_REALPATH 1 /* Define to 1 if defines the SA_RESTART constant. */ #define HAVE_SA_RESTART 1 /* Define to 1 if you have the `setegid' function. */ #define HAVE_SETEGID 1 /* Define to 1 if you have the `seteuid' function. */ #define HAVE_SETEUID 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1 /* Define to 1 if you have the `setregid' function. */ #define HAVE_SETREGID 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setrlimit' function. */ #define HAVE_SETRLIMIT 1 /* Define to 1 if you have the `setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if you have the `sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the `socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strcmpi' function. */ /* #undef HAVE_STRCMPI */ /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `stricmp' function. */ /* #undef HAVE_STRICMP */ /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strncasecmp' function. */ #define HAVE_STRNCASECMP 1 /* Define to 1 if you have the `strncmpi' function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the `strndup' function. */ #define HAVE_STRNDUP 1 /* Define to 1 if you have the `strnicmp' function. */ /* #undef HAVE_STRNICMP */ /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if `n_un.n_name' is a member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_DIR_H */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the \`union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VARARGS_H */ /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the `wait3' function. */ /* #undef HAVE_WAIT3 */ /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Build host information. (not used by kmk) */ #define MAKE_HOST "i586-pc-haiku" /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 /* Define to 1 to enable symbolic link timestamp checking. */ #define MAKE_SYMLINKS 1 /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define to 1 if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of package */ #define PACKAGE "make" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the home page for this package. */ #define PACKAGE_URL "http://www.gnu.org/software/make/" /* Define to the version of this package. */ #define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "get" /* Define to 1 if the SCCS 'get' command understands the '-G' option. */ /* #undef SCCS_GET_MINUS_G */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ #define ST_MTIM_NSEC tv_nsec /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS 1 #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # define _TANDEM_SOURCE 1 #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # define __EXTENSIONS__ 1 #endif /* Version number of package */ #define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `int' if doesn't define. */ /* #undef gid_t */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define to `int' if doesn't define. */ /* #undef uid_t */ /* Define uintmax_t if not defined in or . */ /* #undef uintmax_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ #include "inlined_memchr.h" kbuild-2695/src/kmk/testcase-if1of.kmk0000644000000000000000000000327612247157306016342 0ustar rootroot# $Id: testcase-if1of.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the if1of and ifn1of conditionals. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk # the basics. if1of (asdf,asdf) else $(error busted) endif ifn1of (asdf,asdf) $(error busted) endif # larger sets. if1of (1,2 3 4 5 6 7 8 9 0) $(error busted) endif if1of (1,12 3 4 5 6 7 8 9 0) $(error busted) endif if1of (1,2 31 4 5 6 7 8 9 0) $(error busted) endif ifn1of (1,1 2 3 4 5 6 7 8 9 0) $(error busted) endif ifn1of (8,1 2 3 4 5 6 7 8 9 0) $(error busted) endif ifn1of (asdf,asdf) $(error busted) endif ifn1of (asdf,asdf asdf) $(error busted) endif # any in set 1 match any in set 2. if1of (1 3 5 7 9, 2 4 6 8) $(error busted) endif ifn1of (1 2 3 4 5, 2 4 6 8) $(error busted) endif # real life. ifn1of (win linux, linux) $(error busted) endif ifn1of (win.x86, win.amd64 linux.x86 darwin.x86 win.x86 os2.x86) $(error busted) endif all_recursive: $(ECHO) "if1of and ifn1of work fine" kbuild-2695/src/kmk/prepare_w32.bat0000644000000000000000000000050512247157307015633 0ustar rootroot@echo off @echo Windows32 CVS build preparation of config.h.W32 and NMakefile. if not exist config.h.W32 copy config.h.W32.template config.h.W32 if not exist config.h copy config.h.W32 config.h if not exist NMakefile copy NMakefile.template NMakefile @echo Preparation complete. Run build_w32.bat to compile and link. kbuild-2695/src/kmk/misc.c0000644000000000000000000010445612247157307014123 0ustar rootroot/* Miscellaneous generic support functions for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "dep.h" #include "debug.h" #if defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_ALLOC_CACHES) # include #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH # ifdef __APPLE__ # include # endif # if defined(__GLIBC__) || defined(HAVE_MALLINFO) # include # endif #endif #if defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_PRINT_TIME_SWITCH) # ifdef WINDOWS32 # include # endif #endif /* All bcopy calls in this file can be replaced by memcpy and save a tick or two. */ #ifdef CONFIG_WITH_OPTIMIZATION_HACKS # undef bcopy # if defined(__GNUC__) && defined(CONFIG_WITH_OPTIMIZATION_HACKS) # define bcopy(src, dst, size) __builtin_memcpy ((dst), (src), (size)) # else # define bcopy(src, dst, size) memcpy ((dst), (src), (size)) # endif #endif /* Variadic functions. We go through contortions to allow proper function prototypes for both ANSI and pre-ANSI C compilers, and also for those which support stdarg.h vs. varargs.h, and finally those which have vfprintf(), etc. and those who have _doprnt... or nothing. This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and VA_END macros used here since we have multiple print functions. */ #if USE_VARIADIC # if HAVE_STDARG_H # include # define VA_START(args, lastarg) va_start(args, lastarg) # else # include # define VA_START(args, lastarg) va_start(args) # endif # if HAVE_VPRINTF # define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args)) # else # define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp)) # endif # define VA_END(args) va_end(args) #else /* We can't use any variadic interface! */ # define va_alist a1, a2, a3, a4, a5, a6, a7, a8 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; # define VA_START(args, lastarg) # define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist) # define VA_END(args) #endif /* Compare strings *S1 and *S2. Return negative if the first is less, positive if it is greater, zero if they are equal. */ int alpha_compare (const void *v1, const void *v2) { const char *s1 = *((char **)v1); const char *s2 = *((char **)v2); if (*s1 != *s2) return *s1 - *s2; return strcmp (s1, s2); } /* Discard each backslash-newline combination from LINE. Backslash-backslash-newline combinations become backslash-newlines. This is done by copying the text at LINE into itself. */ #ifndef CONFIG_WITH_VALUE_LENGTH void collapse_continuations (char *line) #else char * collapse_continuations (char *line, unsigned int linelen) #endif { register char *in, *out, *p; register int backslash; register unsigned int bs_write; #ifndef CONFIG_WITH_VALUE_LENGTH in = strchr (line, '\n'); if (in == 0) return; #else assert (strlen (line) == linelen); in = memchr (line, '\n', linelen); if (in == 0) return line + linelen; if (in == line || in[-1] != '\\') { do { unsigned int off_in = in - line; if (off_in == linelen) return in; in = memchr (in + 1, '\n', linelen - off_in - 1); if (in == 0) return line + linelen; } while (in[-1] != '\\'); } #endif out = in; while (out > line && out[-1] == '\\') --out; while (*in != '\0') { /* BS_WRITE gets the number of quoted backslashes at the end just before IN, and BACKSLASH gets nonzero if the next character is quoted. */ backslash = 0; bs_write = 0; for (p = in - 1; p >= line && *p == '\\'; --p) { if (backslash) ++bs_write; backslash = !backslash; /* It should be impossible to go back this far without exiting, but if we do, we can't get the right answer. */ if (in == out - 1) abort (); } /* Output the appropriate number of backslashes. */ while (bs_write-- > 0) *out++ = '\\'; /* Skip the newline. */ ++in; /* If the newline is escaped, discard following whitespace leaving just one space. POSIX requires that each backslash/newline/following whitespace sequence be reduced to a single space. */ if (backslash) { in = next_token (in); /* Removing this loop will fix Savannah bug #16670: do we want to? */ while (out > line && isblank ((unsigned char)out[-1])) --out; *out++ = ' '; } else /* If the newline isn't quoted, put it in the output. */ *out++ = '\n'; /* Now copy the following line to the output. Stop when we find backslashes followed by a newline. */ while (*in != '\0') if (*in == '\\') { p = in + 1; while (*p == '\\') ++p; if (*p == '\n') { in = p; break; } while (in < p) *out++ = *in++; } else *out++ = *in++; } *out = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH assert (strchr (line, '\0') == out); return out; #endif } /* Print N spaces (used in debug for target-depth). */ void print_spaces (unsigned int n) { while (n-- > 0) putchar (' '); } /* Return a string whose contents concatenate the NUM strings provided This string lives in static, re-used memory. */ const char * #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H concat (unsigned int num, ...) #else concat (num, va_alist) unsigned int num; va_dcl #endif { static unsigned int rlen = 0; static char *result = NULL; unsigned int ri = 0; /* bird: must be unsigned */ #if USE_VARIADIC va_list args; #endif VA_START (args, num); while (num-- > 0) { const char *s = va_arg (args, const char *); unsigned int l = s ? strlen (s) : 0; if (l == 0) continue; if (ri + l > rlen) { rlen = ((rlen ? rlen : 60) + l) * 2; result = xrealloc (result, rlen); } memcpy (result + ri, s, l); ri += l; } VA_END (args); /* Get some more memory if we don't have enough space for the terminating '\0'. */ if (ri == rlen) { rlen = (rlen ? rlen : 60) * 2; result = xrealloc (result, rlen); } result[ri] = '\0'; return result; } /* Print a message on stdout. */ void #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H message (int prefix, const char *fmt, ...) #else message (prefix, fmt, va_alist) int prefix; const char *fmt; va_dcl #endif { #if USE_VARIADIC va_list args; #endif log_working_directory (1); if (fmt != 0) { if (prefix) { if (makelevel == 0) printf ("%s: ", program); else printf ("%s[%u]: ", program, makelevel); } VA_START (args, fmt); VA_PRINTF (stdout, fmt, args); VA_END (args); putchar ('\n'); } fflush (stdout); } /* Print an error message. */ void #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H error (const struct floc *flocp, const char *fmt, ...) #else error (flocp, fmt, va_alist) const struct floc *flocp; const char *fmt; va_dcl #endif { #if USE_VARIADIC va_list args; #endif log_working_directory (1); if (flocp && flocp->filenm) fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno); else if (makelevel == 0) fprintf (stderr, "%s: ", program); else fprintf (stderr, "%s[%u]: ", program, makelevel); VA_START(args, fmt); VA_PRINTF (stderr, fmt, args); VA_END (args); putc ('\n', stderr); fflush (stderr); } /* Print an error message and exit. */ void #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H fatal (const struct floc *flocp, const char *fmt, ...) #else fatal (flocp, fmt, va_alist) const struct floc *flocp; const char *fmt; va_dcl #endif { #if USE_VARIADIC va_list args; #endif log_working_directory (1); if (flocp && flocp->filenm) fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno); else if (makelevel == 0) fprintf (stderr, "%s: *** ", program); else fprintf (stderr, "%s[%u]: *** ", program, makelevel); VA_START(args, fmt); VA_PRINTF (stderr, fmt, args); VA_END (args); fputs (_(". Stop.\n"), stderr); die (2); } #ifndef HAVE_STRERROR #undef strerror char * strerror (int errnum) { extern int errno, sys_nerr; #ifndef __DECC extern char *sys_errlist[]; #endif static char buf[] = "Unknown error 12345678901234567890"; if (errno < sys_nerr) return sys_errlist[errnum]; sprintf (buf, _("Unknown error %d"), errnum); return buf; } #endif /* Print an error message from errno. */ void perror_with_name (const char *str, const char *name) { error (NILF, _("%s%s: %s"), str, name, strerror (errno)); } /* Print an error message from errno and exit. */ void pfatal_with_name (const char *name) { fatal (NILF, _("%s: %s"), name, strerror (errno)); /* NOTREACHED */ } /* Like malloc but get fatal error if memory is exhausted. */ /* Don't bother if we're using dmalloc; it provides these for us. */ #if !defined(HAVE_DMALLOC_H) && !defined(ELECTRIC_HEAP) /* bird */ #undef xmalloc #undef xcalloc #undef xrealloc #undef xstrdup void * xmalloc (unsigned int size) { /* Make sure we don't allocate 0, for pre-ISO implementations. */ void *result = malloc (size ? size : 1); if (result == 0) fatal (NILF, _("virtual memory exhausted")); #ifdef CONFIG_WITH_MAKE_STATS make_stats_allocations++; if (make_expensive_statistics) make_stats_allocated += SIZE_OF_HEAP_BLOCK (result); else make_stats_allocated += size; #endif return result; } void * xcalloc (unsigned int size) { /* Make sure we don't allocate 0, for pre-ISO implementations. */ void *result = calloc (size ? size : 1, 1); if (result == 0) fatal (NILF, _("virtual memory exhausted")); return result; } void * xrealloc (void *ptr, unsigned int size) { void *result; #ifdef CONFIG_WITH_MAKE_STATS if (make_expensive_statistics && ptr != NULL) make_stats_allocated -= SIZE_OF_HEAP_BLOCK (ptr); if (ptr) make_stats_reallocations++; else make_stats_allocations++; #endif /* Some older implementations of realloc() don't conform to ISO. */ if (! size) size = 1; result = ptr ? realloc (ptr, size) : malloc (size); if (result == 0) fatal (NILF, _("virtual memory exhausted")); #ifdef CONFIG_WITH_MAKE_STATS if (make_expensive_statistics) make_stats_allocated += SIZE_OF_HEAP_BLOCK (result); else make_stats_allocated += size; #endif return result; } char * xstrdup (const char *ptr) { char *result; #ifdef HAVE_STRDUP result = strdup (ptr); #else result = malloc (strlen (ptr) + 1); #endif if (result == 0) fatal (NILF, _("virtual memory exhausted")); #ifdef CONFIG_WITH_MAKE_STATS make_stats_allocations++; if (make_expensive_statistics) make_stats_allocated += SIZE_OF_HEAP_BLOCK (result); else make_stats_allocated += strlen (ptr) + 1; #endif #ifdef HAVE_STRDUP return result; #else return strcpy (result, ptr); #endif } #endif /* HAVE_DMALLOC_H */ char * xstrndup (const char *str, unsigned int length) { char *result; #if defined(HAVE_STRNDUP) && !defined(KMK) result = strndup (str, length); if (result == 0) fatal (NILF, _("virtual memory exhausted")); #else result = xmalloc (length + 1); if (length > 0) strncpy (result, str, length); result[length] = '\0'; #endif return result; } #ifndef CONFIG_WITH_OPTIMIZATION_HACKS /* This is really a reimplemntation of memchr, only slower. It's been replaced by a macro in the header file. */ /* Limited INDEX: Search through the string STRING, which ends at LIMIT, for the character C. Returns a pointer to the first occurrence, or nil if none is found. Like INDEX except that the string searched ends where specified instead of at the first null. */ char * lindex (const char *s, const char *limit, int c) { while (s < limit) if (*s++ == c) return (char *)(s - 1); return 0; } #endif /* CONFIG_WITH_OPTIMIZATION_HACKS */ /* Return the address of the first whitespace or null in the string S. */ char * end_of_token (const char *s) { #ifdef KMK for (;;) { unsigned char ch0, ch1, ch2, ch3; ch0 = *s; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0))) return (char *)s; ch1 = s[1]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1))) return (char *)s + 1; ch2 = s[2]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2))) return (char *)s + 2; ch3 = s[3]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3))) return (char *)s + 3; s += 4; } #else while (*s != '\0' && !isblank ((unsigned char)*s)) ++s; return (char *)s; #endif } #ifdef WINDOWS32 /* * Same as end_of_token, but take into account a stop character */ char * end_of_token_w32 (const char *s, char stopchar) { const char *p = s; int backslash = 0; while (*p != '\0' && *p != stopchar && (backslash || !isblank ((unsigned char)*p))) { if (*p++ == '\\') { backslash = !backslash; while (*p == '\\') { backslash = !backslash; ++p; } } else backslash = 0; } return (char *)p; } #endif /* Return the address of the first nonwhitespace or null in the string S. */ char * next_token (const char *s) { #ifdef KMK for (;;) { unsigned char ch0, ch1, ch2, ch3; ch0 = *s; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0))) return (char *)s; ch1 = s[1]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1))) return (char *)s + 1; ch2 = s[2]; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2))) return (char *)s + 2; ch3 = s[3]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3))) return (char *)s + 3; s += 4; } #else /* !KMK */ while (isblank ((unsigned char)*s)) ++s; return (char *)s; #endif /* !KMK */ } /* Find the next token in PTR; return the address of it, and store the length of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end of the token, so this function can be called repeatedly in a loop. */ char * find_next_token (const char **ptr, unsigned int *lengthptr) { #ifdef KMK const char *p = *ptr; const char *e; /* skip blanks */ # if 0 /* a moderate version */ for (;; p++) { unsigned char ch = *p; if (!MY_IS_BLANK(ch)) { if (!ch) return NULL; break; } } # else /* (too) big unroll */ for (;; p += 4) { unsigned char ch0, ch1, ch2, ch3; ch0 = *p; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch0))) { if (!ch0) return NULL; break; } ch1 = p[1]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch1))) { if (!ch1) return NULL; p += 1; break; } ch2 = p[2]; if (MY_PREDICT_FALSE(!MY_IS_BLANK(ch2))) { if (!ch2) return NULL; p += 2; break; } ch3 = p[3]; if (MY_PREDICT_TRUE(!MY_IS_BLANK(ch3))) { if (!ch3) return NULL; p += 3; break; } } # endif /* skip ahead until EOS or blanks. */ # if 0 /* a moderate version */ for (e = p + 1; ; e++) { unsigned char ch = *e; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch))) break; } # else /* (too) big unroll */ for (e = p + 1; ; e += 4) { unsigned char ch0, ch1, ch2, ch3; ch0 = *e; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch0))) break; ch1 = e[1]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch1))) { e += 1; break; } ch2 = e[2]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch2))) { e += 2; break; } ch3 = e[3]; if (MY_PREDICT_FALSE(MY_IS_BLANK_OR_EOS(ch3))) { e += 3; break; } } # endif *ptr = e; if (lengthptr != 0) *lengthptr = e - p; return (char *)p; #else const char *p = next_token (*ptr); if (*p == '\0') return 0; *ptr = end_of_token (p); if (lengthptr != 0) *lengthptr = *ptr - p; return (char *)p; #endif } #ifdef KMK /* Same as find_next_token with two exception: - The string ends at EOS or '\0'. - We keep track of $() and ${}, allowing functions to be used. */ char * find_next_token_eos (const char **ptr, const char *eos, unsigned int *lengthptr) { const char *p = *ptr; const char *e; int level = 0; /* skip blanks */ for (; p != eos; p++) { unsigned char ch = *p; if (!MY_IS_BLANK(ch)) { if (!ch) return NULL; break; } } if (p == eos) return NULL; /* skip ahead until EOS or blanks. */ for (e = p; e != eos; e++) { unsigned char ch = *e; if (MY_IS_BLANK_OR_EOS(ch)) { if (!ch || level == 0) break; } else if (ch == '$') { if (&e[1] != eos && (e[1] == '(' || e[1] == '{')) { level++; e++; } } else if ((ch == ')' || ch == '}') && level > 0) level--; } *ptr = e; if (lengthptr != 0) *lengthptr = e - p; return (char *)p; } #endif /* KMK */ /* Copy a chain of `struct dep'. For 2nd expansion deps, dup the name. */ struct dep * copy_dep_chain (const struct dep *d) { struct dep *firstnew = 0; struct dep *lastnew = 0; while (d != 0) { #ifndef CONFIG_WITH_ALLOC_CACHES struct dep *c = xmalloc (sizeof (struct dep)); #else struct dep *c = alloccache_alloc(&dep_cache); #endif memcpy (c, d, sizeof (struct dep)); /** @todo KMK: Check if we need this duplication! */ if (c->need_2nd_expansion) c->name = xstrdup (c->name); c->next = 0; if (firstnew == 0) firstnew = lastnew = c; else lastnew = lastnew->next = c; d = d->next; } return firstnew; } /* Free a chain of 'struct dep'. */ void free_dep_chain (struct dep *d) { while (d != 0) { struct dep *df = d; d = d->next; free_dep (df); } } /* Free a chain of struct nameseq. For struct dep chains use free_dep_chain. */ void free_ns_chain (struct nameseq *ns) { while (ns != 0) { struct nameseq *t = ns; ns = ns->next; #ifndef CONFIG_WITH_ALLOC_CACHES free (t); #else alloccache_free (&nameseq_cache, t); #endif } } #if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI /* If we don't have strcasecmp() (from POSIX), or anything that can substitute for it, define our own version. */ int strcasecmp (const char *s1, const char *s2) { while (1) { int c1 = (int) *(s1++); int c2 = (int) *(s2++); if (isalpha (c1)) c1 = tolower (c1); if (isalpha (c2)) c2 = tolower (c2); if (c1 != '\0' && c1 == c2) continue; return (c1 - c2); } } #endif #if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI /* If we don't have strncasecmp() (from POSIX), or anything that can substitute for it, define our own version. */ int strncasecmp (const char *s1, const char *s2, int n) { while (n-- > 0) { int c1 = (int) *(s1++); int c2 = (int) *(s2++); if (isalpha (c1)) c1 = tolower (c1); if (isalpha (c2)) c2 = tolower (c2); if (c1 != '\0' && c1 == c2) continue; return (c1 - c2); } return 0; } #endif #ifdef GETLOADAVG_PRIVILEGED #ifdef POSIX /* Hopefully if a system says it's POSIX.1 and has the setuid and setgid functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2, for example) which claim to be POSIX.1 also have the BSD setreuid and setregid functions, but they don't work as in BSD and only the POSIX.1 way works. */ #undef HAVE_SETREUID #undef HAVE_SETREGID #else /* Not POSIX. */ /* Some POSIX.1 systems have the seteuid and setegid functions. In a POSIX-like system, they are the best thing to use. However, some non-POSIX systems have them too but they do not work in the POSIX style and we must use setreuid and setregid instead. */ #undef HAVE_SETEUID #undef HAVE_SETEGID #endif /* POSIX. */ #ifndef HAVE_UNISTD_H extern int getuid (), getgid (), geteuid (), getegid (); extern int setuid (), setgid (); #ifdef HAVE_SETEUID extern int seteuid (); #else #ifdef HAVE_SETREUID extern int setreuid (); #endif /* Have setreuid. */ #endif /* Have seteuid. */ #ifdef HAVE_SETEGID extern int setegid (); #else #ifdef HAVE_SETREGID extern int setregid (); #endif /* Have setregid. */ #endif /* Have setegid. */ #endif /* No . */ /* Keep track of the user and group IDs for user- and make- access. */ static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1; #define access_inited (user_uid != -1) static enum { make, user } current_access; /* Under -d, write a message describing the current IDs. */ static void log_access (const char *flavor) { if (! ISDB (DB_JOBS)) return; /* All the other debugging messages go to stdout, but we write this one to stderr because it might be run in a child fork whose stdout is piped. */ fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"), flavor, (unsigned long) geteuid (), (unsigned long) getuid (), (unsigned long) getegid (), (unsigned long) getgid ()); fflush (stderr); } static void init_access (void) { #ifndef VMS user_uid = getuid (); user_gid = getgid (); make_uid = geteuid (); make_gid = getegid (); /* Do these ever fail? */ if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1) pfatal_with_name ("get{e}[gu]id"); log_access (_("Initialized access")); current_access = make; #endif } #endif /* GETLOADAVG_PRIVILEGED */ /* Give the process appropriate permissions for access to user data (i.e., to stat files, or to spawn a child process). */ void user_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) init_access (); if (current_access == user) return; /* We are in "make access" mode. This means that the effective user and group IDs are those of make (if it was installed setuid or setgid). We now want to set the effective user and group IDs to the real IDs, which are the IDs of the process that exec'd make. */ #ifdef HAVE_SETEUID /* Modern systems have the seteuid/setegid calls which set only the effective IDs, which is ideal. */ if (seteuid (user_uid) < 0) pfatal_with_name ("user_access: seteuid"); #else /* Not HAVE_SETEUID. */ #ifndef HAVE_SETREUID /* System V has only the setuid/setgid calls to set user/group IDs. There is an effective ID, which can be set by setuid/setgid. It can be set (unless you are root) only to either what it already is (returned by geteuid/getegid, now in make_uid/make_gid), the real ID (return by getuid/getgid, now in user_uid/user_gid), or the saved set ID (what the effective ID was before this set-ID executable (make) was exec'd). */ if (setuid (user_uid) < 0) pfatal_with_name ("user_access: setuid"); #else /* HAVE_SETREUID. */ /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs. They may be set to themselves or each other. So you have two alternatives at any one time. If you use setuid/setgid, the effective will be set to the real, leaving only one alternative. Using setreuid/setregid, however, you can toggle between your two alternatives by swapping the values in a single setreuid or setregid call. */ if (setreuid (make_uid, user_uid) < 0) pfatal_with_name ("user_access: setreuid"); #endif /* Not HAVE_SETREUID. */ #endif /* HAVE_SETEUID. */ #ifdef HAVE_SETEGID if (setegid (user_gid) < 0) pfatal_with_name ("user_access: setegid"); #else #ifndef HAVE_SETREGID if (setgid (user_gid) < 0) pfatal_with_name ("user_access: setgid"); #else if (setregid (make_gid, user_gid) < 0) pfatal_with_name ("user_access: setregid"); #endif #endif current_access = user; log_access (_("User access")); #endif /* GETLOADAVG_PRIVILEGED */ } /* Give the process appropriate permissions for access to make data (i.e., the load average). */ void make_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) init_access (); if (current_access == make) return; /* See comments in user_access, above. */ #ifdef HAVE_SETEUID if (seteuid (make_uid) < 0) pfatal_with_name ("make_access: seteuid"); #else #ifndef HAVE_SETREUID if (setuid (make_uid) < 0) pfatal_with_name ("make_access: setuid"); #else if (setreuid (user_uid, make_uid) < 0) pfatal_with_name ("make_access: setreuid"); #endif #endif #ifdef HAVE_SETEGID if (setegid (make_gid) < 0) pfatal_with_name ("make_access: setegid"); #else #ifndef HAVE_SETREGID if (setgid (make_gid) < 0) pfatal_with_name ("make_access: setgid"); #else if (setregid (user_gid, make_gid) < 0) pfatal_with_name ("make_access: setregid"); #endif #endif current_access = make; log_access (_("Make access")); #endif /* GETLOADAVG_PRIVILEGED */ } /* Give the process appropriate permissions for a child process. This is like user_access, but you can't get back to make_access. */ void child_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) abort (); /* Set both the real and effective UID and GID to the user's. They cannot be changed back to make's. */ #ifndef HAVE_SETREUID if (setuid (user_uid) < 0) pfatal_with_name ("child_access: setuid"); #else if (setreuid (user_uid, user_uid) < 0) pfatal_with_name ("child_access: setreuid"); #endif #ifndef HAVE_SETREGID if (setgid (user_gid) < 0) pfatal_with_name ("child_access: setgid"); #else if (setregid (user_gid, user_gid) < 0) pfatal_with_name ("child_access: setregid"); #endif log_access (_("Child access")); #endif /* GETLOADAVG_PRIVILEGED */ } #ifdef NEED_GET_PATH_MAX unsigned int get_path_max (void) { static unsigned int value; if (value == 0) { long int x = pathconf ("/", _PC_PATH_MAX); if (x > 0) value = x; else return MAXPATHLEN; } return value; } #endif /* This code is stolen from gnulib. If/when we abandon the requirement to work with K&R compilers, we can remove this (and perhaps other parts of GNU make!) and migrate to using gnulib directly. This is called only through atexit(), which means die() has already been invoked. So, call exit() here directly. Apparently that works...? */ /* Close standard output, exiting with status 'exit_failure' on failure. If a program writes *anything* to stdout, that program should close stdout and make sure that it succeeds before exiting. Otherwise, suppose that you go to the extreme of checking the return status of every function that does an explicit write to stdout. The last printf can succeed in writing to the internal stream buffer, and yet the fclose(stdout) could still fail (due e.g., to a disk full error) when it tries to write out that buffered data. Thus, you would be left with an incomplete output file and the offending program would exit successfully. Even calling fflush is not always sufficient, since some file systems (NFS and CODA) buffer written/flushed data until an actual close call. Besides, it's wasteful to check the return value from every call that writes to stdout -- just let the internal stream state record the failure. That's what the ferror test is checking below. It's important to detect such failures and exit nonzero because many tools (most notably `make' and other build-management systems) depend on being able to detect failure in other tools via their exit status. */ void close_stdout (void) { int prev_fail = ferror (stdout); int fclose_fail = fclose (stdout); if (prev_fail || fclose_fail) { if (fclose_fail) error (NILF, _("write error: %s"), strerror (errno)); else error (NILF, _("write error")); exit (EXIT_FAILURE); } } #ifdef CONFIG_WITH_PRINT_STATS_SWITCH /* Print heap statistics if supported by the platform. */ void print_heap_stats (void) { /* Darwin / Mac OS X */ # ifdef __APPLE__ malloc_statistics_t s; malloc_zone_statistics (NULL, &s); printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"), (unsigned)s.size_in_use, (unsigned)s.blocks_in_use, (unsigned)(s.size_in_use / s.blocks_in_use)); printf (_("# %u bytes max in use (high water mark)\n"), (unsigned)s.max_size_in_use); printf (_("# %u bytes reserved, %u bytes free (estimate)\n"), (unsigned)s.size_allocated, (unsigned)(s.size_allocated - s.size_in_use)); # endif /* __APPLE__ */ /* MSC / Windows */ # ifdef _MSC_VER unsigned int blocks_used = 0; unsigned int bytes_used = 0; unsigned int blocks_avail = 0; unsigned int bytes_avail = 0; _HEAPINFO hinfo; memset (&hinfo, '\0', sizeof (hinfo)); while (_heapwalk(&hinfo) == _HEAPOK) { if (hinfo._useflag == _USEDENTRY) { blocks_used++; bytes_used += hinfo._size; } else { blocks_avail++; bytes_avail += hinfo._size; } } printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"), bytes_used, blocks_used, bytes_used / blocks_used); printf (_("# %u bytes avail, in %u blocks, avg %u bytes/block\n"), bytes_avail, blocks_avail, bytes_avail / blocks_avail); # endif /* _MSC_VER */ /* Darwin Libc sources indicates that something like this may be found in GLIBC, however, it's not in any current one... */ # if 0 /* ??? */ struct mstats m; m = mstats(); printf (_("\n# CRT Heap: %zu blocks / %zu bytes in use, %zu blocks / %zu bytes free\n"), m.chunks_used, m.bytes_used, m.chunks_free, m.bytes_free); printf (_("# %zu bytes reserved\n"), m.bytes_total); # endif /* ??? */ /* XVID2/XPG mallinfo (displayed per GLIBC documentation). */ # if defined(__GLIBC__) || defined(HAVE_MALLINFO) struct mallinfo m; m = mallinfo(); printf (_("\n# CRT Heap: %d bytes in use, %d bytes free\n"), m.uordblks, m.fordblks); printf (_("# # free chunks=%d, # fastbin blocks=%d\n"), m.ordblks, m.smblks); printf (_("# # mapped regions=%d, space in mapped regions=%d\n"), m.hblks, m.hblkhd); printf (_("# non-mapped space allocated from system=%d\n"), m.arena); printf (_("# maximum total allocated space=%d\n"), m.usmblks); printf (_("# top-most releasable space=%d\n"), m.keepcost); # endif /* __GLIBC__ || HAVE_MALLINFO */ # ifdef CONFIG_WITH_MAKE_STATS printf(_("# %lu malloc calls, %lu realloc calls\n"), make_stats_allocations, make_stats_reallocations); printf(_("# %lu MBs alloc sum, not counting freed, add pinch of salt\n"), /* XXX: better wording */ make_stats_allocated / (1024*1024)); # endif /* XXX: windows */ } #endif /* CONFIG_WITH_PRINT_STATS_SWITCH */ #ifdef CONFIG_WITH_PRINT_TIME_SWITCH /* Get a nanosecond timestamp, from a monotonic time source if possible. Returns -1 after calling error() on failure. */ big_int nano_timestamp (void) { big_int ts; #if defined (WINDOWS32) static int s_state = -1; static LARGE_INTEGER s_freq; if (s_state == -1) s_state = QueryPerformanceFrequency (&s_freq); if (s_state) { LARGE_INTEGER pc; if (!QueryPerformanceCounter (&pc)) { s_state = 0; return nano_timestamp (); } ts = (big_int)((long double)pc.QuadPart / (long double)s_freq.QuadPart * 1000000000); } else { /* fall back to low resolution system time. */ LARGE_INTEGER bigint; FILETIME ft = {0,0}; GetSystemTimeAsFileTime (&ft); bigint.u.LowPart = ft.dwLowDateTime; bigint.u.HighPart = ft.dwLowDateTime; ts = bigint.QuadPart * 100; } #elif HAVE_GETTIMEOFDAY /* FIXME: Linux and others have the realtime clock_* api, detect and use it. */ struct timeval tv; if (!gettimeofday (&tv, NULL)) ts = (big_int)tv.tv_sec * 1000000000 + tv.tv_usec * 1000; else { error (NILF, _("gettimeofday failed")); ts = -1; } #else # error "PORTME" #endif return ts; } /* Formats the elapsed time (nano seconds) in the manner easiest to read, with millisecond percision for larger numbers. */ int format_elapsed_nano (char *buf, size_t size, big_int ts) { unsigned sz; if (ts < 1000) sz = sprintf (buf, "%uns", (unsigned)ts); else if (ts < 100000) sz = sprintf (buf, "%u.%03uus", (unsigned)(ts / 1000), (unsigned)(ts % 1000)); else { ts /= 1000; if (ts < 1000) sz = sprintf (buf, "%uus", (unsigned)ts); else if (ts < 100000) sz = sprintf (buf, "%u.%03ums", (unsigned)(ts / 1000), (unsigned)(ts % 1000)); else { ts /= 1000; if (ts < BIG_INT_C(60000)) sz = sprintf (buf, "%u.%03us", (unsigned)(ts / 1000), (unsigned)(ts % 1000)); else sz = sprintf (buf, "%um%u.%03us", (unsigned)( ts / BIG_INT_C(60000)), (unsigned)((ts % BIG_INT_C(60000)) / 1000), (unsigned)((ts % BIG_INT_C(60000)) % 1000)); } } if (sz >= size) fatal (NILF, _("format_elapsed_nano buffer overflow: %u written, %lu buffer"), sz, (unsigned long)size); return sz; } #endif /* CONFIG_WITH_PRINT_TIME_SWITCH */ kbuild-2695/src/kmk/testcase-includedep.kmk0000644000000000000000000000474512247157306017454 0ustar rootroot# $Id: testcase-includedep.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the includedep directive. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifdef testcase-includedep-sub.kmk $(error testcase-includedep-sub.kmk is defined at the start of the testcase.) endif foo = testcase-includedep-sub includedep $(foo).kmk ifneq ($(testcase-includedep-sub.kmk),included) $(error The first test failed.) endif testcase-includedep-sub.kmk := ifdef testcase-includedep-sub.kmk $(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.) endif foo = includedep includedep testcase-$(foo)-sub.kmk ifneq ($(testcase-includedep-sub.kmk),included) $(error The second test failed.) endif testcase-includedep-sub.kmk := ifdef testcase-includedep-sub.kmk $(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.) endif foo = kmk includedep testcase-includedep-sub.$(foo) ifneq ($(testcase-includedep-sub.kmk),included) $(error The thrid test failed.) endif testcase-includedep-sub.kmk := ifdef testcase-includedep-sub.kmk $(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.) endif includedep testcase-includedep-sub.kmk ifneq ($(testcase-includedep-sub.kmk),included) $(error The forth test failed.) endif testcase-includedep-sub.kmk := ifdef testcase-includedep-sub.kmk $(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.) endif foo = asdf includedep testcase-$(foo)-sub.kmk ifeq ($(testcase-includedep-sub.kmk),included) $(error The fifth test failed.) endif testcase-includedep-sub.kmk := ifdef testcase-includedep-sub.kmk $(error testcase-includedep-sub.kmk is persistent and does not want to be undefed.) endif all_recursive: $(ECHO) "includedep works fine" kbuild-2695/src/kmk/readme.vms0000644000000000000000000003744212247157307015010 0ustar rootrootThis is the VMS version of GNU Make, updated by Hartmut Becker Changes are based on GNU make 3.82. This version was built and tested on OpenVMS V7.3 (VAX), V7.3-2 (Alpha) and V8.3-1H1 (I64). Build instructions Make a 1st version $ @makefile.com ! ignore any compiler and/or linker warning $ rena make.exe 1st-make.exe Use the 1st version to generate a 2nd version $ mc sys$disk:[]1st-make clean $ mc sys$disk:[]1st-make Verify your 2nd version $ rena make.exe 2nd-make.exe $ mc sys$disk:[]2nd-make clean $ mc sys$disk:[]2nd-make Changes (3.81.90) Michael Gehre (at VISTEC-SEMI dot COM) supplied a fix for a problem with timestamps of object modules in OLBs. The timestamps were not correctly adjusted to GMT based time, if the local VMS time was using a daylight saving algorithm and if daylight saving was switched off. John Eisenbraun (at HP dot COM) supplied fixes and and an enhancement to append output redirection in action lines. Rework of ctrl+c and ctrl+y handling. Fix a problem with cached strings, which showed on case-insensitive file systems. Build fixes for const-ified code in VMS specific sources. Build notes: - Try to avoid HP C V7.2-001, which has an incompatible change how __STDC__ is defined. This results at least in compile time warnings. - On V8.3-1H1, if you press Ctrl+C you may see a traceback, starting with %SYSTEM-F-CONTROLC, operation completed under CTRL/C %TRACE-F-TRACEBACK, symbolic stack dump follows image module routine line rel PC abs PC DECC$SHR C$SIGNAL gsignal 27991 0000000000001180 FFFFFFFF84AB2DA0 DECC$SHR C$SIGNAL raise 28048 0000000000001280 FFFFFFFF84AB2EA0 DECC$SHR C$SIGPENDING decc$$deliver_signals 12475 0000000000000890 FFFFFFFF84C13690 ... This looks like an incompatibility to the Alpha and VAX behavior, so it looks like a problem in I64 VMS version(s). - There is no clean build on VAX. In the environment I tested, I had to use GNU make's alloca which produced a couple of compile time warnings. It seems too much effort to work on a clean build on VAX. A note on appending the redirected output. With this change, a simple mechanism is implemented to make ">>" work in action lines. In VMS there is no simple feature like ">>" to have DCL command or program output redirected and appended to a file. GNU make for VMS already implements the redirection of output. If such a redirection is detected, an ">" on the action line, GNU make creates a DCL command procedure to execute the action and to redirect its output. Based on that, now ">>" is also recognized and a similar but different command procedure is created to implement the append. The main idea here is to create a temporary file which collects the output and which is appended to the wanted output file. Then the temporary file is deleted. This is all done in the command procedure to keep changes in make small and simple. This obviously has some limitations but it seems good enough compared with the current ">" implementation. (And in my opinion, redirection is not really what GNU make has to do.) With this approach, it may happen that the temporary file is not yet appended and is left in SYS$SCRATCH. The temporary file names look like "CMDxxxxx.". Any time the created command procedure can not complete, this happens. Pressing Ctrl+Y to abort make is one case. In case of Ctrl+Y the associated command procedure is left in SYS$SCRATCH as well. Its name is CMDxxxxx.COM. Change in the Ctrl+Y handling Ctrl+Y was: The CtrlY handler called $forcex for the current child. Ctrl+Y changed: The CtrlY handler uses $delprc to delete all children. This way also actions with DCL commands will be stopped. As before Ctrl+Y then sends SIGQUIT to itself, which is handled in common code. Change in deleteing temporary command files Temporary command files were deleted in the main line, after returning from the vms child termination handler. If Ctrl+C was pressed, the handler is called but did not return to main line. Now, temporary command files are deleted in the vms child termination handler. That deletes the them even if a Ctrl+C was pressed. The behavior of pressing Ctrl+C is not changed. It still has only an effect, after the current action is terminated. If that doesn't happen or takes too long, Ctrl+Y should be used instead. Changes (3.80) . In default.c define variable ARCH as IA64 for VMS on Itanium systems. . In makefile.vms avoid name collision for glob and globfree. In newer version of the VMS CRTL there are glob and globfree implemented. Compiling and linking may result in %ILINK-W-MULDEFLNKG, symbol DECC$GLOBFREE has subsequent linkage definition in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1 %ILINK-W-MULDEF, symbol DECC$GLOBFREE multiply defined in module DECC$SHR file SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1 linker messages (and similar for DECC$GLOB). The messages just say, that globfree is a known CRTL whose name was mapped by the compiler to DECC$GLOBFREE. This is done in glob.c as well, so this name is defined twice. One possible solution is to use the VMS versions of glob and globfree. However, then the build environment needs to figure out if there is a new CRTL supporting these or not. This adds complexity. Even more, these functions return VMS file specifications, which is not expected by the other make sources. There is a switch at run time (a VMS logical DECC$GLOB_UNIX_STYLE), which can be set to get Unix style names. This may conflict with other software. The recommended solution for this is to set this switch just prior to calling main: in an initialization routine. This adds more complexity and more VMS specific code. It is easier to tell the compiler NOT to map the routine names with a simple change in makefile.vms. Some notes on case sensitive names in rules and on the disk. In the VMS template for CONFIG.H case sensitive rules can be enabled with defining WANT_CASE_SENSITIVE_TARGETS. For recent version of VMS there is a case sensitive file system: ODS5. To make use of that, additionally un-defining the HAVE_CASE_INSENSITIVE_FS is required. As these are C macros, different versions of make need to be built to have any case sensitivity for VMS working. Unfortunately, for ODS5 disks that's not all. - Usually DCL upcases command line tokens (except strings) and usually the file system is case blind (similar to how Windows systems work) $ set proc/parse=extended/case=sensitive preserves lower and UPPER on the command line and (for this process and all sub-processes) enables case sensitivity in the file system - Usually the CRTL tries to reverse what DCL did with command line tokens, it lowercases all tokens (except strings) $ define DECC$ARGV_PARSE_STYLE enable passes (the now preserved) lower and UPPER from the command line to main() - Usually the CRTL upcases the arguments to open() and friends $ define DECC$EFS_CASE_PRESERVE enable preserves the names as is. It is important to know that not all VMS tools are ready for case sensitivity. With this setup some tools may not work as expected. The setup should not blindly be applied for all users in default login procedures. Example? The poor coding gives a compiler message, showing that there are different files: $ dir Directory ODS5DISK[HB] A.c;1 B.c;1 c.c;1 X.c;1 x.c;1 Total of 5 files. $ ods5make x.obj cc /obj=x.obj x.c foo(){lowercase_x();} ......^ %CC-I-IMPLICITFUNC, In this statement, the identifier "lowercase_x" is implicitly declared as a function. at line number 1 in file ODS5DISK[HB]x.c;1 $ mc SYS$SYSDEVICE:[HARTMUT.MAKE_3_80P]ods5make X.obj cc /obj=X.obj X.c foo() {UPPERCASE_X();} .......^ %CC-I-IMPLICITFUNC, In this statement, the identifier "UPPERCASE_X" is implicitly declared as a function. at line number 1 in file ODS5DISK[HB]X.c;1 $ dir Directory ODS5DISK[HB] A.c;1 B.c;1 c.c;1 X.c;1 x.c;1 X.obj;1 x.obj;1 Total of 7 files. $ This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com. It is based on the specific version 3.77k and on 3.78.1. 3.77k was done by Klaus Kämpf , the code was based on the VMS port of GNU Make 3.60 by Mike Moretti. It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and tested on OpenVMS/Alpha V7.2, OpenVMS/VAX 7.1 and 5.5-2. Different versions of DECC were used. VAXC was tried: it fails; but it doesn't seem worth to get it working. There are still some PTRMISMATCH warnings during the compile. Although perl is working on VMS the test scripts don't work. The function $shell is still missing. There is a known bug in some of the VMS CRTLs. It is in the shipped versions of VMS V7.2 and V7.2-1 and in the currently (October 1999) available ECOs for VMS V7.1 and newer versions. It is fixed in versions shipped with newer VMS versions and all ECO kits after October 1999. It only shows up during the daylight saving time period (DST): stat() returns a modification time 1 hour ahead. This results in GNU make warning messages. For a just created source you will see: $ gmake x.exe gmake.exe;1: *** Warning: File `x.c' has modification time in the future (940582863 > 940579269) cc /obj=x.obj x.c link x.obj /exe=x.exe gmake.exe;1: *** Warning: Clock skew detected. Your build may be incomplete. New in 3.78.1: Fix a problem with automatically remaking makefiles. GNU make uses an execve to restart itself after a successful remake of the makefile. On UNIX systems execve replaces the running program with a new one and resets all signal handling to the default. On VMS execve creates a child process, signal and exit handlers of the parent are still active, and, unfortunately, corrupt the exit code from the child. Fix in job.c: ignore SIGCHLD. Added some switches to reflect latest features of DECC. Modifications in makefile.vms. Set some definitions to reflect latest features of DECC. Modifications in config.h-vms (which is copied to config.h). Added extern strcmpi declaration to avoid 'implicitly declared' messages. Modification in make.h. Default rule for C++, conditionals for gcc (GCC_IS_NATIVE) or DEC/Digital/ Compaq c/c++ compilers. Modifications in default.c. Usage of opendir() and friends, suppress file version. Modifications in dir.c. Added VMS specific code to handle ctrl+c and ctrl+y to abort make. Modifications in job.c. Added support to have case sensitive targets and dependencies but to still use case blind file names. This is especially useful for Java makefiles on VMS: .SUFFIXES : .SUFFIXES : .class .java .java.class : javac "$< HelloWorld.class : HelloWorld.java A new macro WANT_CASE_SENSITIVE_TARGETS in config.h-vms was introduced. It needs to be enabled to get this feature; default is disabled. The macro HAVE_CASE_INSENSITIVE_FS must not be touched: it is still enabled. Modifications in file.c and config.h-vms. Bootstrap make to start building make is still makefile.com, but make needs to be re-made with a make to make a correct version: ignore all possible warnings, delete all objects, rename make.exe to a different name and run it. Made some minor modifications to the bootstrap build makefile.com. This is the VMS port of GNU Make. It is based on the VMS port of GNU Make 3.60 by Mike Moretti. This port was done by Klaus Kämpf There is first-level support available from proGIS Software, Germany. Visit their web-site at http://www.progis.de to get information about other vms software and forthcoming updates to gnu make. New for 3.77: /bin/sh style I/O redirection is supported. You can now write lines like mcr sys$disk:[]program.exe < input.txt > output.txt &> error.txt Makefile variables are looked up in the current environment. You can set symbols or logicals in DCL and evaluate them in the Makefile via $(). Variables defined in the Makefile override VMS symbols/logicals ! Functions for file names are working now. See the GNU Make manual for $(dir ...) and $(wildcard ...). Unix-style and VMS-style names are supported as arguments. The default rules are set up for GNU C. Building an executable from a single source file is as easy as 'make file.exe'. The variable $(ARCH) is predefined as ALPHA or VAX resp. Makefiles for different VMS systems can now be written by checking $(ARCH) as in ifeq ($(ARCH),ALPHA) $(ECHO) "On the Alpha" else $(ECHO) "On the VAX" endif Command lines of excessive length are correctly broken and written to a batch file in sys$scratch for later execution. There's no limit to the lengths of commands (and no need for .opt files :-) any more. Empty commands are handled correctly and don't end in a new DCL process. New for 3.76: John W. Eaton has updated the VMS port to support libraries and VPATH. To build Make, simply type @makefile. This should compile all the necessary files and link Make. There is also a file called makefile.vms. If you already have GNU Make built you can just use Make with this makefile to rebuild. Here are some notes about GNU Make for VMS: The cd command is supported if it's called as $(CD). This invokes the 'builtin_cd' command which changes the directory. Calling 'set def' doesn't do the trick, since a sub-shell is spawned for this command, the directory is changed *in this sub-shell* and the sub-shell ends. Libraries are not supported. They were in GNU Make 3.60 but somehow I didn't care porting the code. If there is enough interest, I'll do it at some later time. The variable $^ separates files with commas instead of spaces (It's the natural thing to do for VMS). See defaults.c for VMS default suffixes and my definitions for default rules and variables. The shell function is not implemented yet. Load average routines haven't been implemented for VMS yet. The default include directory for including other makefiles is SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use SYS$LIBRARY: instead; maybe it wouldn't work that way). The default makefiles make looks for are: makefile.vms, gnumakefile, makefile., and gnumakefile. . The stat() function and handling of time stamps in VMS is broken, so I replaced it with a hack in vmsfunctions.c. I will provide a full rewrite somewhere in the future. Be warned, the time resolution inside make is less than what vms provides. This might be a problem on the faster Alphas. You can use a : in a filename only if you preceed it with a backslash ('\'). E.g.- hobbes\:[bogas.files] Make ignores success, informational, or warning errors (-S-, -I-, or -W-). But it will stop on -E- and -F- errors. (unless you do something to override this in your makefile, or whatever). Remote stuff isn't implemented yet. Multiple line DCL commands, such as "if" statements, must be put inside command files. You can run a command file by using \@. VMS changes made for 3.74.3 Lots of default settings are adapted for VMS. See default.c. Long command lines are now converted to command files. Comma (',') as a separator is now allowed. See makefile.vms for an example. ------------------------------------------------------------------------------- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/kmkbuiltin/0000755000000000000000000000000012247157307015163 5ustar rootrootkbuild-2695/src/kmk/kmkbuiltin/cat.c0000644000000000000000000001756112247157307016110 0ustar rootroot/*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kevin Fall. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #endif #ifndef lint #if 0 static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; #endif #endif /* not lint */ #if 0 #include __FBSDID("$FreeBSD: src/bin/cat/cat.c,v 1.32 2005/01/10 08:39:20 imp Exp $"); #else #define NO_UDOM_SUPPORT /* kmk */ #endif #include "config.h" #ifndef _MSC_VER # include #endif #include #ifndef NO_UDOM_SUPPORT # include # include # include #endif #include #include "err.h" #include #include #include #include #include #include #include #include "getopt.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #include "kmkbuiltin.h" int bflag, eflag, nflag, sflag, tflag, vflag; /*int rval;*/ const char *filename; static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int usage(FILE *); static int scanfiles(char *argv[], int cooked); static int cook_cat(FILE *); static int raw_cat(int); #ifndef NO_UDOM_SUPPORT static int udom_open(const char *path, int flags); #endif int kmk_builtin_cat(int argc, char *argv[], char **envp) { int ch, rc; /* kmk: reinitialize globals */ bflag = eflag = nflag = sflag = tflag = vflag = 0; filename = NULL; /* kmk: reset getopt and set progname */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ #ifdef kmk_builtin_cat /* kmk did this already. */ setlocale(LC_CTYPE, ""); #endif while ((ch = getopt_long(argc, argv, "benstuv", long_options, NULL)) != -1) switch (ch) { case 'b': bflag = nflag = 1; /* -b implies -n */ break; case 'e': eflag = vflag = 1; /* -e implies -v */ break; case 'n': nflag = 1; break; case 's': sflag = 1; break; case 't': tflag = vflag = 1; /* -t implies -v */ break; case 'u': setbuf(stdout, NULL); break; case 'v': vflag = 1; break; case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); default: return usage(stderr); } argv += optind; if (bflag || eflag || nflag || sflag || tflag || vflag) rc = scanfiles(argv, 1); else rc = scanfiles(argv, 0); #ifdef kmk_builtin_cat /* only in the external program. */ if (fclose(stdout)) return err(1, "stdout"); #endif return rc; } static int usage(FILE *fp) { fprintf(fp, "usage: %s [-benstuv] [file ...]\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname); return 1; } static int scanfiles(char *argv[], int cooked) { int i = 0; char *path; FILE *fp; int rc2 = 0; int rc = 0; while ((path = argv[i]) != NULL || i == 0) { int fd; if (path == NULL || strcmp(path, "-") == 0) { filename = "stdin"; fd = STDIN_FILENO; } else { filename = path; fd = open(path, O_RDONLY); #ifndef NO_UDOM_SUPPORT if (fd < 0 && errno == EOPNOTSUPP) fd = udom_open(path, O_RDONLY); #endif } if (fd < 0) { warn("%s", path); rc2 = 1; /* non fatal */ } else if (cooked) { if (fd == STDIN_FILENO) rc = cook_cat(stdin); else { fp = fdopen(fd, "r"); rc = cook_cat(fp); fclose(fp); } } else { rc = raw_cat(fd); if (fd != STDIN_FILENO) close(fd); } if (rc || path == NULL) break; ++i; } return !rc ? rc2 : rc; } static int cook_cat(FILE *fp) { int ch, gobble, line, prev; int rc = 0; /* Reset EOF condition on stdin. */ if (fp == stdin && feof(stdin)) clearerr(stdin); line = gobble = 0; for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { if (prev == '\n') { if (sflag) { if (ch == '\n') { if (gobble) continue; gobble = 1; } else gobble = 0; } if (nflag && (!bflag || ch != '\n')) { (void)fprintf(stdout, "%6d\t", ++line); if (ferror(stdout)) break; } } if (ch == '\n') { if (eflag && putchar('$') == EOF) break; } else if (ch == '\t') { if (tflag) { if (putchar('^') == EOF || putchar('I') == EOF) break; continue; } } else if (vflag) { if (!isascii(ch) && !isprint(ch)) { if (putchar('M') == EOF || putchar('-') == EOF) break; ch = toascii(ch); } if (iscntrl(ch)) { if (putchar('^') == EOF || putchar(ch == '\177' ? '?' : ch | 0100) == EOF) break; continue; } } if (putchar(ch) == EOF) break; } if (ferror(fp)) { warn("%s", filename); rc = 1; clearerr(fp); } if (ferror(stdout)) return err(1, "stdout"); return rc; } static int raw_cat(int rfd) { int off, wfd; ssize_t nr, nw; static size_t bsize; static char *buf = NULL; struct stat sbuf; wfd = fileno(stdout); if (buf == NULL) { if (fstat(wfd, &sbuf)) return err(1, "%s", filename); #ifdef _MSC_VER bsize = 1024; #else bsize = MAX(sbuf.st_blksize, 1024); #endif if ((buf = malloc(bsize)) == NULL) return err(1, "buffer"); } while ((nr = read(rfd, buf, bsize)) > 0) for (off = 0; nr; nr -= nw, off += nw) if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) return err(1, "stdout"); if (nr < 0) { warn("%s", filename); return 1; } return 0; } #ifndef NO_UDOM_SUPPORT static int udom_open(const char *path, int flags) { struct sockaddr_un sou; int fd; unsigned int len; bzero(&sou, sizeof(sou)); /* * Construct the unix domain socket address and attempt to connect */ fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd >= 0) { sou.sun_family = AF_UNIX; if ((len = strlcpy(sou.sun_path, path, sizeof(sou.sun_path))) >= sizeof(sou.sun_path)) { errno = ENAMETOOLONG; return (-1); } len = offsetof(struct sockaddr_un, sun_path[len+1]); if (connect(fd, (void *)&sou, len) < 0) { close(fd); fd = -1; } } /* * handle the open flags by shutting down appropriate directions */ if (fd >= 0) { switch(flags & O_ACCMODE) { case O_RDONLY: if (shutdown(fd, SHUT_WR) == -1) warn(NULL); break; case O_WRONLY: if (shutdown(fd, SHUT_RD) == -1) warn(NULL); break; default: break; } } return(fd); } #endif kbuild-2695/src/kmk/kmkbuiltin/mscfakes.h0000644000000000000000000001072712247157307017137 0ustar rootroot/* $Id: mscfakes.h 2592 2012-06-17 22:50:38Z bird $ */ /** @file * Unix fakes for MSC. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifndef ___mscfakes_h #define ___mscfakes_h #ifdef _MSC_VER #include #include #include #include #include #include "getopt.h" /* Note: Duplicated it config.h.win */ #include #include #include #if defined(MSC_DO_64_BIT_IO) && _MSC_VER >= 1400 /* We want 64-bit file lengths here when possible. */ # define off_t __int64 # undef stat # define stat _stat64 # define fstat _fstat64 # define lseek _lseeki64 #else # ifndef STAT_REDEFINED_ALREADY # define STAT_REDEFINED_ALREADY # undef stat # define stat(_path, _st) bird_w32_stat(_path, _st) extern int bird_w32_stat(const char *, struct stat *); # endif #endif #ifndef S_ISDIR # define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) #endif #ifndef S_ISREG # define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) #endif #define S_ISLNK(m) 0 #define S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC) #define S_IXUSR _S_IEXEC #define S_IWUSR _S_IWRITE #define S_IRUSR _S_IREAD #define S_IRWXG 0000070 #define S_IRGRP 0000040 #define S_IWGRP 0000020 #define S_IXGRP 0000010 #define S_IRWXO 0000007 #define S_IROTH 0000004 #define S_IWOTH 0000002 #define S_IXOTH 0000001 #define S_ISUID 0004000 #define S_ISGID 0002000 #define ALLPERMS 0000777 #undef PATH_MAX #define PATH_MAX _MAX_PATH #undef MAXPATHLEN #define MAXPATHLEN _MAX_PATH #define EX_OK 0 #define EX_OSERR 1 #define EX_NOUSER 1 #define EX_USAGE 1 #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 #define F_OK 0 #define X_OK 1 #define W_OK 2 #define R_OK 4 #define EFTYPE EINVAL #define _PATH_DEVNULL "/dev/null" #ifndef MAX # define MAX(a,b) ((a) >= (b) ? (a) : (b)) #endif typedef int mode_t; typedef unsigned short nlink_t; #if 0 /* found in config.h */ typedef unsigned short uid_t; typedef unsigned short gid_t; #endif typedef long ssize_t; typedef unsigned long u_long; typedef unsigned int u_int; typedef unsigned short u_short; #ifndef timerisset struct timeval { long tv_sec; long tv_usec; }; #endif struct iovec { char *iov_base; size_t iov_len; }; typedef __int64 intmax_t; #if 0 /* found in config.h */ typedef unsigned __int64 uintmax_t; #endif #define chown(path, uid, gid) 0 /** @todo implement fchmod! */ char *dirname(char *path); #define fsync(fd) 0 #define fchown(fd,uid,gid) 0 #define fchmod(fd, mode) 0 /** @todo implement fchmod! */ #define geteuid() 0 #define getegid() 0 #define lstat(path, s) stat(path, s) int lchmod(const char *path, mode_t mode); int msc_chmod(const char *path, mode_t mode); #define chmod msc_chmod #define lchown(path, uid, gid) chown(path, uid, gid) #define lutimes(path, tvs) utimes(path, tvs) int link(const char *pszDst, const char *pszLink); int mkdir_msc(const char *path, mode_t mode); #define mkdir(path, mode) mkdir_msc(path, mode) #define mkfifo(path, mode) -1 #define mknod(path, mode, devno) -1 int mkstemp(char *temp); #define readlink(link, buf, size) -1 #define reallocf(old, size) realloc(old, size) int rmdir_msc(const char *path); #define rmdir(path) rmdir_msc(path) intmax_t strtoimax(const char *nptr, char **endptr, int base); uintmax_t strtoumax(const char *nptr, char **endptr, int base); #define strtoll(a,b,c) strtoimax(a,b,c) #define strtoull(a,b,c) strtoumax(a,b,c) int asprintf(char **strp, const char *fmt, ...); int vasprintf(char **strp, const char *fmt, va_list ap); #if _MSC_VER < 1400 int snprintf(char *buf, size_t size, const char *fmt, ...); #else #define snprintf _snprintf #endif int symlink(const char *pszDst, const char *pszLink); int utimes(const char *pszPath, const struct timeval *paTimes); int writev(int fd, const struct iovec *vector, int count); #endif /* _MSC_VER */ #endif kbuild-2695/src/kmk/kmkbuiltin/cp.c0000644000000000000000000005051012247157307015732 0ustar rootroot/* * Copyright (c) 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * David Hitz of Auspex Systems Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1988, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)cp.c 8.2 (Berkeley) 4/1/94"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/bin/cp/cp.c,v 1.50 2004/04/06 20:06:44 markm Exp $"); #endif /* * Cp copies source files to target files. * * The global PATH_T structure "to" always contains the path to the * current target file. Since fts(3) does not change directories, * this path can be either absolute or dot-relative. * * The basic algorithm is to initialize "to" and use fts(3) to traverse * the file hierarchy rooted in the argument list. A trivial case is the * case of 'cp file1 file2'. The more interesting case is the case of * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the * path (relative to the root of the traversal) is appended to dir (stored * in "to") to form the final target path. */ #include "config.h" #include #include #include "err.h" #include #include #include #include #include #include #include #include #include "getopt.h" #include "k/kDefs.h" #ifdef _MSC_VER # include "mscfakes.h" #endif #include "cp_extern.h" #include "kmkbuiltin.h" #include "kbuild_protection.h" #if defined(_MSC_VER) || defined(__gnu_linux__) || defined(__linux__) extern char *strlcpy(char *, const char *, size_t); #endif #ifndef S_IFWHT #define S_IFWHT 0 #define S_ISWHT(s) 0 #define undelete(s) (-1) #endif #ifndef S_ISTXT #ifdef S_ISVTX #define S_ISTXT S_ISVTX #else #define S_ISTXT 0 #endif #endif /* !S_ISTXT */ #ifndef __unused # define __unused #endif #if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 # define IS_SLASH(ch) ((ch) == '/' || (ch) == '\\') #else # define IS_SLASH(ch) ((ch) == '/') #endif #define STRIP_TRAILING_SLASH(p) { \ while ((p).p_end > (p).p_path + 1 && IS_SLASH((p).p_end[-1])) \ *--(p).p_end = 0; \ } /* have wrappers for globals in cp_extern! */ static KBUILDPROTECTION g_ProtData; const char *cp_argv0; static char emptystring[] = ""; PATH_T to = { to.p_path, emptystring, "" }; int fflag, iflag, nflag, pflag, vflag; static int Rflag, rflag; volatile sig_atomic_t info; static int cp_ignore_non_existing, cp_changed_only; enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; enum cp_arg { CP_OPT_HELP = 261, CP_OPT_VERSION, CP_OPT_IGNORE_NON_EXISTING, CP_OPT_CHANGED, CP_OPT_DISABLE_PROTECTION, CP_OPT_ENABLE_PROTECTION, CP_OPT_ENABLE_FULL_PROTECTION, CP_OPT_DISABLE_FULL_PROTECTION, CP_OPT_PROTECTION_DEPTH }; static struct option long_options[] = { { "help", no_argument, 0, CP_OPT_HELP }, { "version", no_argument, 0, CP_OPT_VERSION }, { "ignore-non-existing", no_argument, 0, CP_OPT_IGNORE_NON_EXISTING }, { "changed", no_argument, 0, CP_OPT_CHANGED }, { "disable-protection", no_argument, 0, CP_OPT_DISABLE_PROTECTION }, { "enable-protection", no_argument, 0, CP_OPT_ENABLE_PROTECTION }, { "enable-full-protection", no_argument, 0, CP_OPT_ENABLE_FULL_PROTECTION }, { "disable-full-protection", no_argument, 0, CP_OPT_DISABLE_FULL_PROTECTION }, { "protection-depth", required_argument, 0, CP_OPT_PROTECTION_DEPTH }, { 0, 0, 0, 0 }, }; static int copy(char *[], enum op, int); static int mastercmp(const FTSENT **, const FTSENT **); #ifdef SIGINFO static void siginfo(int __unused); #endif static int usage(FILE *); int kmk_builtin_cp(int argc, char *argv[], char **envp) { struct stat to_stat, tmp_stat; enum op type; int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash, rc; char *target; /* init globals */ cp_argv0 = argv[0]; to.p_end = to.p_path; to.target_end = emptystring; memset(to.p_path, 0, sizeof(to.p_path)); fflag = iflag = nflag = pflag = vflag = Rflag = rflag = 0; info = 0; cp_ignore_non_existing = cp_changed_only = 0; kBuildProtectionInit(&g_ProtData); /* reset getopt and set progname. */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ Hflag = Lflag = Pflag = 0; while ((ch = getopt_long(argc, argv, "HLPRfinprv", long_options, NULL)) != -1) switch (ch) { case 'H': Hflag = 1; Lflag = Pflag = 0; break; case 'L': Lflag = 1; Hflag = Pflag = 0; break; case 'P': Pflag = 1; Hflag = Lflag = 0; break; case 'R': Rflag = 1; break; case 'f': fflag = 1; iflag = nflag = 0; break; case 'i': iflag = 1; fflag = nflag = 0; break; case 'n': nflag = 1; fflag = iflag = 0; break; case 'p': pflag = 1; break; #if 0 /* only one -R */ case 'r': rflag = 1; break; #endif case 'v': vflag = 1; break; case CP_OPT_HELP: usage(stdout); kBuildProtectionTerm(&g_ProtData); return 0; case CP_OPT_VERSION: kBuildProtectionTerm(&g_ProtData); return kbuild_version(argv[0]); case CP_OPT_IGNORE_NON_EXISTING: cp_ignore_non_existing = 1; break; case CP_OPT_CHANGED: cp_changed_only = 1; break; case CP_OPT_DISABLE_PROTECTION: kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case CP_OPT_ENABLE_PROTECTION: kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case CP_OPT_ENABLE_FULL_PROTECTION: kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case CP_OPT_DISABLE_FULL_PROTECTION: kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case CP_OPT_PROTECTION_DEPTH: if (kBuildProtectionSetDepth(&g_ProtData, optarg)) { kBuildProtectionTerm(&g_ProtData); return 1; } break; default: kBuildProtectionTerm(&g_ProtData); return usage(stderr); } argc -= optind; argv += optind; if (argc < 2) { kBuildProtectionTerm(&g_ProtData); return usage(stderr); } fts_options = FTS_NOCHDIR | FTS_PHYSICAL; if (rflag) { if (Rflag) { kBuildProtectionTerm(&g_ProtData); return errx(1, "the -R and -r options may not be specified together."); } if (Hflag || Lflag || Pflag) errx(1, "the -H, -L, and -P options may not be specified with the -r option."); fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } if (Rflag) { if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } } else { fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL | FTS_COMFOLLOW; } #ifdef SIGINFO (void)signal(SIGINFO, siginfo); #endif /* Save the target base in "to". */ target = argv[--argc]; if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) { kBuildProtectionTerm(&g_ProtData); return errx(1, "%s: name too long", target); } to.p_end = to.p_path + strlen(to.p_path); if (to.p_path == to.p_end) { *to.p_end++ = '.'; *to.p_end = 0; } have_trailing_slash = IS_SLASH(to.p_end[-1]); if (have_trailing_slash) STRIP_TRAILING_SLASH(to); to.target_end = to.p_end; /* Set end of argument list for fts(3). */ argv[argc] = NULL; /* * Cp has two distinct cases: * * cp [-R] source target * cp [-R] source1 ... sourceN directory * * In both cases, source can be either a file or a directory. * * In (1), the target becomes a copy of the source. That is, if the * source is a file, the target will be a file, and likewise for * directories. * * In (2), the real target is not directory, but "directory/source". */ r = stat(to.p_path, &to_stat); if (r == -1 && errno != ENOENT) { kBuildProtectionTerm(&g_ProtData); return err(1, "stat: %s", to.p_path); } if (r == -1 || !S_ISDIR(to_stat.st_mode)) { /* * Case (1). Target is not a directory. */ if (argc > 1) { kBuildProtectionTerm(&g_ProtData); return usage(stderr); } /* * Need to detect the case: * cp -R dir foo * Where dir is a directory and foo does not exist, where * we want pathname concatenations turned on but not for * the initial mkdir(). */ if (r == -1) { if (rflag || (Rflag && (Lflag || Hflag))) stat(*argv, &tmp_stat); else lstat(*argv, &tmp_stat); if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag)) type = DIR_TO_DNE; else type = FILE_TO_FILE; } else type = FILE_TO_FILE; if (have_trailing_slash && type == FILE_TO_FILE) { kBuildProtectionTerm(&g_ProtData); if (r == -1) return errx(1, "directory %s does not exist", to.p_path); else return errx(1, "%s is not a directory", to.p_path); } } else /* * Case (2). Target is a directory. */ type = FILE_TO_DIR; /* Finally, check that the "to" directory isn't protected. */ rc = 1; if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_CP_") && !kBuildProtectionEnforce(&g_ProtData, Rflag || rflag ? KBUILDPROTECTIONTYPE_RECURSIVE : KBUILDPROTECTIONTYPE_FULL, to.p_path)) { rc = copy(argv, type, fts_options); } kBuildProtectionTerm(&g_ProtData); return rc; } static int copy(char *argv[], enum op type, int fts_options) { struct stat to_stat; FTS *ftsp; FTSENT *curr; int base = 0, dne, badcp, rval; size_t nlen; char *p, *target_mid; mode_t mask, mode; /* * Keep an inverted copy of the umask, for use in correcting * permissions on created directories when not using -p. */ mask = ~umask(0777); umask(~mask); if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL) return err(1, "fts_open"); for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) { int copied = 0; switch (curr->fts_info) { case FTS_NS: if ( cp_ignore_non_existing && curr->fts_errno == ENOENT) { if (vflag) { warnx("fts: %s: %s", curr->fts_path, strerror(curr->fts_errno)); } continue; } case FTS_DNR: case FTS_ERR: warnx("fts: %s: %s", curr->fts_path, strerror(curr->fts_errno)); badcp = rval = 1; continue; case FTS_DC: /* Warn, continue. */ warnx("%s: directory causes a cycle", curr->fts_path); badcp = rval = 1; continue; default: ; } /* * If we are in case (2) or (3) above, we need to append the * source name to the target name. */ if (type != FILE_TO_FILE) { /* * Need to remember the roots of traversals to create * correct pathnames. If there's a directory being * copied to a non-existent directory, e.g. * cp -R a/dir noexist * the resulting path name should be noexist/foo, not * noexist/dir/foo (where foo is a file in dir), which * is the case where the target exists. * * Also, check for "..". This is for correct path * concatenation for paths ending in "..", e.g. * cp -R .. /tmp * Paths ending in ".." are changed to ".". This is * tricky, but seems the easiest way to fix the problem. * * XXX * Since the first level MUST be FTS_ROOTLEVEL, base * is always initialized. */ if (curr->fts_level == FTS_ROOTLEVEL) { if (type != DIR_TO_DNE) { p = strrchr(curr->fts_path, '/'); #if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 if (strrchr(curr->fts_path, '\\') > p) p = strrchr(curr->fts_path, '\\'); #endif base = (p == NULL) ? 0 : (int)(p - curr->fts_path + 1); if (!strcmp(&curr->fts_path[base], "..")) base += 1; } else base = curr->fts_pathlen; } p = &curr->fts_path[base]; nlen = curr->fts_pathlen - base; target_mid = to.target_end; if (!IS_SLASH(*p) && !IS_SLASH(target_mid[-1])) *target_mid++ = '/'; *target_mid = 0; if (target_mid - to.p_path + nlen >= PATH_MAX) { warnx("%s%s: name too long (not copied)", to.p_path, p); badcp = rval = 1; continue; } (void)strncat(target_mid, p, nlen); to.p_end = target_mid + nlen; *to.p_end = 0; STRIP_TRAILING_SLASH(to); } if (curr->fts_info == FTS_DP) { /* * We are nearly finished with this directory. If we * didn't actually copy it, or otherwise don't need to * change its attributes, then we are done. */ if (!curr->fts_number) continue; /* * If -p is in effect, set all the attributes. * Otherwise, set the correct permissions, limited * by the umask. Optimise by avoiding a chmod() * if possible (which is usually the case if we * made the directory). Note that mkdir() does not * honour setuid, setgid and sticky bits, but we * normally want to preserve them on directories. */ if (pflag) { if (setfile(curr->fts_statp, -1)) rval = 1; } else { mode = curr->fts_statp->st_mode; if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) || ((mode | S_IRWXU) & mask) != (mode & mask)) if (chmod(to.p_path, mode & mask) != 0){ warn("chmod: %s", to.p_path); rval = 1; } } continue; } /* Not an error but need to remember it happened */ if (stat(to.p_path, &to_stat) == -1) dne = 1; else { if (to_stat.st_dev == curr->fts_statp->st_dev && to_stat.st_dev != 0 && to_stat.st_ino == curr->fts_statp->st_ino && to_stat.st_ino != 0) { warnx("%s and %s are identical (not copied).", to.p_path, curr->fts_path); badcp = rval = 1; if (S_ISDIR(curr->fts_statp->st_mode)) (void)fts_set(ftsp, curr, FTS_SKIP); continue; } if (!S_ISDIR(curr->fts_statp->st_mode) && S_ISDIR(to_stat.st_mode)) { warnx("cannot overwrite directory %s with " "non-directory %s", to.p_path, curr->fts_path); badcp = rval = 1; continue; } dne = 0; } switch (curr->fts_statp->st_mode & S_IFMT) { #ifdef S_IFLNK case S_IFLNK: /* Catch special case of a non-dangling symlink */ if ((fts_options & FTS_LOGICAL) || ((fts_options & FTS_COMFOLLOW) && curr->fts_level == 0)) { if (copy_file(curr, dne, cp_changed_only, &copied)) badcp = rval = 1; } else { if (copy_link(curr, !dne)) badcp = rval = 1; } break; #endif case S_IFDIR: if (!Rflag && !rflag) { warnx("%s is a directory (not copied).", curr->fts_path); (void)fts_set(ftsp, curr, FTS_SKIP); badcp = rval = 1; break; } /* * If the directory doesn't exist, create the new * one with the from file mode plus owner RWX bits, * modified by the umask. Trade-off between being * able to write the directory (if from directory is * 555) and not causing a permissions race. If the * umask blocks owner writes, we fail.. */ if (dne) { if (mkdir(to.p_path, curr->fts_statp->st_mode | S_IRWXU) < 0) return err(1, "mkdir: %s", to.p_path); } else if (!S_ISDIR(to_stat.st_mode)) { errno = ENOTDIR; return err(1, "to-mode: %s", to.p_path); } /* * Arrange to correct directory attributes later * (in the post-order phase) if this is a new * directory, or if the -p flag is in effect. */ curr->fts_number = pflag || dne; break; #ifdef S_IFBLK case S_IFBLK: #endif case S_IFCHR: if (Rflag) { if (copy_special(curr->fts_statp, !dne)) badcp = rval = 1; } else { if (copy_file(curr, dne, cp_changed_only, &copied)) badcp = rval = 1; } break; #ifdef S_IFIFO case S_IFIFO: #endif if (Rflag) { if (copy_fifo(curr->fts_statp, !dne)) badcp = rval = 1; } else { if (copy_file(curr, dne, cp_changed_only, &copied)) badcp = rval = 1; } break; default: if (copy_file(curr, dne, cp_changed_only, &copied)) badcp = rval = 1; break; } if (vflag && !badcp) (void)printf(copied ? "%s -> %s\n" : "%s matches %s - not copied\n", curr->fts_path, to.p_path); } if (errno) return err(1, "fts_read"); return (rval); } /* * mastercmp -- * The comparison function for the copy order. The order is to copy * non-directory files before directory files. The reason for this * is because files tend to be in the same cylinder group as their * parent directory, whereas directories tend not to be. Copying the * files first reduces seeking. */ static int mastercmp(const FTSENT **a, const FTSENT **b) { int a_info, b_info; a_info = (*a)->fts_info; if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR) return (0); b_info = (*b)->fts_info; if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR) return (0); if (a_info == FTS_D) return (-1); if (b_info == FTS_D) return (1); return (0); } #ifdef SIGINFO static void siginfo(int sig __unused) { info = 1; } #endif static int usage(FILE *fp) { fprintf(fp, "usage: %s [options] src target\n" " or: %s [options] src1 ... srcN directory\n" " or: %s --help\n" " or: %s --version\n" "\n" "Options:\n" " -R Recursive copy.\n" " -H Follow symbolic links on the commandline. Only valid with -R.\n" " -L Follow all symbolic links. Only valid with -R.\n" " -P Do not follow symbolic links. Default. Only valid with -R\n" " -f Force. Overrides -i and -n.\n" " -i Iteractive. Overrides -n and -f.\n" " -n Don't overwrite any files. Overrides -i and -f.\n" " --ignore-non-existing\n" " Don't fail if the specified source file doesn't exist.\n" " --changed\n" " Only copy if changed (i.e. compare first).\n" " --disable-protection\n" " Will disable the protection file protection applied with -R.\n" " --enable-protection\n" " Will enable the protection file protection applied with -R.\n" " --enable-full-protection\n" " Will enable the protection file protection for all operations.\n" " --disable-full-protection\n" " Will disable the protection file protection for all operations.\n" " --protection-depth\n" " Number or path indicating the file protection depth. Default: %d\n" "\n" "Environment:\n" " KMK_CP_DISABLE_PROTECTION\n" " Same as --disable-protection. Overrides command line.\n" " KMK_CP_ENABLE_PROTECTION\n" " Same as --enable-protection. Overrides everyone else.\n" " KMK_CP_ENABLE_FULL_PROTECTION\n" " Same as --enable-full-protection. Overrides everyone else.\n" " KMK_CP_DISABLE_FULL_PROTECTION\n" " Same as --disable-full-protection. Overrides command line.\n" " KMK_CP_PROTECTION_DEPTH\n" " Same as --protection-depth. Overrides command line.\n" "\n" "The file protection of the top %d layers of the file hierarchy is there\n" "to try prevent makefiles from doing bad things to your system. This\n" "protection is not bulletproof, but should help prevent you from shooting\n" "yourself in the foot.\n" , g_progname, g_progname, g_progname, g_progname, kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth()); return 1; } kbuild-2695/src/kmk/kmkbuiltin/printf.c0000644000000000000000000004021612247157307016634 0ustar rootroot/* $NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*#include #ifndef lint #if !defined(BUILTIN) && !defined(SHELL) __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"); #endif #endif #ifndef lint #if 0 static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95"; #else __RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $"); #endif #endif*/ /* not lint */ #if !defined(kmk_builtin_printf) && !defined(BUILTIN) && !defined(SHELL) # include "../make.h" # include "../filedef.h" # include "../variable.h" #else # include "config.h" #endif #include #include #include "err.h" #include #include #include #include #include #include #include #include #include #include "getopt.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #include "../kmkbuiltin.h" #ifdef __GNUC__ #define ESCAPE '\e' #else #define ESCAPE 033 #endif static size_t b_length; static char *b_fmt; static int rval; static char **gargv; #if !defined(kmk_builtin_printf) && !defined(BUILTIN) && !defined(SHELL) static char *g_o = NULL; #endif static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int common_printf(int argc, char *argv[]); static void conv_escape_str(char *, void (*)(int)); static char *conv_escape(char *, char *); static char *conv_expand(const char *); static int getchr(void); static double getdouble(void); static int getwidth(void); static intmax_t getintmax(void); static uintmax_t getuintmax(void); static char *getstr(void); static char *mklong(const char *, int); static void check_conversion(const char *, const char *); static int usage(FILE *); static void b_count(int); static void b_output(int); static int wrap_putchar(int ch); static int wrap_printf(const char *, ...); #ifdef BUILTIN /* csh builtin */ #define kmk_builtin_printf progprintf #endif #ifdef SHELL /* sh (aka ash) builtin */ #define kmk_builtin_printf printfcmd #include "../../bin/sh/bltin/bltin.h" #endif /* SHELL */ #define PF(f, func) { \ if (fieldwidth != -1) { \ if (precision != -1) \ (void)wrap_printf(f, fieldwidth, precision, func); \ else \ (void)wrap_printf(f, fieldwidth, func); \ } else if (precision != -1) \ (void)wrap_printf(f, precision, func); \ else \ (void)wrap_printf(f, func); \ } #define APF(cpp, f, func) { \ if (fieldwidth != -1) { \ if (precision != -1) \ (void)asprintf(cpp, f, fieldwidth, precision, func); \ else \ (void)asprintf(cpp, f, fieldwidth, func); \ } else if (precision != -1) \ (void)asprintf(cpp, f, precision, func); \ else \ (void)asprintf(cpp, f, func); \ } int kmk_builtin_printf(int argc, char *argv[], char **envp) { int rc; int ch; /* kmk: reset getopt and set progname */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ #if !defined(SHELL) && !defined(BUILTIN) && !defined(kmk_builtin_printf) /* kmk did this already. */ (void)setlocale (LC_ALL, ""); #endif while ((ch = getopt_long(argc, argv, "", long_options, NULL)) != -1) { switch (ch) { case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(stderr); } } argc -= optind; argv += optind; if (argc < 1) { return usage(stderr); } rc = common_printf(argc, argv); return rc; } #ifndef kmk_builtin_printf /* entry point used by function.c $(printf ..,..). */ char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname) { int rc; int argc; for (argc = 0; argv[argc] != NULL; argc++) /* nothing */; g_o = o; rc = common_printf(argc, argv); o = g_o; g_o = NULL; (void)funcname; if (rc != 0) fatal (NILF, _("$(%s): failure rc=%d\n"), funcname, rc); return o; } #endif static int common_printf(int argc, char *argv[]) { char *fmt, *start; int fieldwidth, precision; char nextch; char *format; int ch; /* kmk: reinitialize globals */ b_length = 0; b_fmt = NULL; rval = 0; gargv = NULL; format = *argv; gargv = ++argv; #define SKIP1 "#-+ 0" #define SKIP2 "*0123456789" do { /* * Basic algorithm is to scan the format string for conversion * specifications -- once one is found, find out if the field * width or precision is a '*'; if it is, gather up value. * Note, format strings are reused as necessary to use up the * provided arguments, arguments of zero/null string are * provided to use up the format string. */ /* find next format specification */ for (fmt = format; (ch = *fmt++) != '\0';) { if (ch == '\\') { char c_ch; fmt = conv_escape(fmt, &c_ch); wrap_putchar(c_ch); continue; } if (ch != '%' || (*fmt == '%' && ++fmt)) { (void)wrap_putchar(ch); continue; } /* Ok - we've found a format specification, Save its address for a later printf(). */ start = fmt - 1; /* skip to field width */ fmt += strspn(fmt, SKIP1); fieldwidth = *fmt == '*' ? getwidth() : -1; /* skip to possible '.', get following precision */ fmt += strspn(fmt, SKIP2); if (*fmt == '.') ++fmt; precision = *fmt == '*' ? getwidth() : -1; fmt += strspn(fmt, SKIP2); ch = *fmt; if (!ch) { warnx("missing format character"); return (1); } /* null terminate format string to we can use it as an argument to printf. */ nextch = fmt[1]; fmt[1] = 0; switch (ch) { case 'B': { const char *p = conv_expand(getstr()); *fmt = 's'; PF(start, p); break; } case 'b': { /* There has to be a better way to do this, * but the string we generate might have * embedded nulls. */ static char *a, *t; char *cp = getstr(); /* Free on entry in case shell longjumped out */ if (a != NULL) free(a); a = NULL; if (t != NULL) free(t); t = NULL; /* Count number of bytes we want to output */ b_length = 0; conv_escape_str(cp, b_count); t = malloc(b_length + 1); if (t == NULL) break; memset(t, 'x', b_length); t[b_length] = 0; /* Get printf to calculate the lengths */ *fmt = 's'; APF(&a, start, t); b_fmt = a; /* Output leading spaces and data bytes */ conv_escape_str(cp, b_output); /* Add any trailing spaces */ wrap_printf("%s", b_fmt); break; } case 'c': { char p = getchr(); PF(start, p); break; } case 's': { char *p = getstr(); PF(start, p); break; } case 'd': case 'i': { intmax_t p = getintmax(); char *f = mklong(start, ch); PF(f, p); break; } case 'o': case 'u': case 'x': case 'X': { uintmax_t p = getuintmax(); char *f = mklong(start, ch); PF(f, p); break; } case 'e': case 'E': case 'f': case 'g': case 'G': { double p = getdouble(); PF(start, p); break; } default: warnx("%s: invalid directive", start); return 1; } *fmt++ = ch; *fmt = nextch; /* escape if a \c was encountered */ if (rval & 0x100) return rval & ~0x100; } } while (gargv != argv && *gargv); return rval; } /* helper functions for conv_escape_str */ static void /*ARGSUSED*/ b_count(int ch) { b_length++; (void)ch; } /* Output one converted character for every 'x' in the 'format' */ static void b_output(int ch) { for (;;) { switch (*b_fmt++) { case 0: b_fmt--; return; case ' ': wrap_putchar(' '); break; default: wrap_putchar(ch); return; } } } static int wrap_putchar(int ch) { #ifndef kmk_builtin_printf if (g_o) { char sz[2]; sz[0] = ch; sz[1] = '\0'; g_o = variable_buffer_output(g_o, sz, 1); return ch; } #endif return putchar(ch); } static int wrap_printf(const char * fmt, ...) { int rc; va_list va; #ifndef kmk_builtin_printf if (g_o) { char *str; va_start(va, fmt); rc = vasprintf(&str, fmt, va); va_end(va); if (rc >= 0) { g_o = variable_buffer_output(g_o, str, rc); free(str); } return rc; } #endif va_start(va, fmt); rc = vprintf(fmt, va); va_end(va); return rc; } /* * Print SysV echo(1) style escape string * Halts processing string if a \c escape is encountered. */ static void conv_escape_str(char *str, void (*do_putchar)(int)) { int value; int ch; char c; while ((ch = *str++) != '\0') { if (ch != '\\') { do_putchar(ch); continue; } ch = *str++; if (ch == 'c') { /* \c as in SYSV echo - abort all processing.... */ rval |= 0x100; break; } /* * %b string octal constants are not like those in C. * They start with a \0, and are followed by 0, 1, 2, * or 3 octal digits. */ if (ch == '0') { int octnum = 0, i; for (i = 0; i < 3; i++) { if (!isdigit((unsigned char)*str) || *str > '7') break; octnum = (octnum << 3) | (*str++ - '0'); } do_putchar(octnum); continue; } /* \[M][^|-]C as defined by vis(3) */ if (ch == 'M' && *str == '-') { do_putchar(0200 | str[1]); str += 2; continue; } if (ch == 'M' && *str == '^') { str++; value = 0200; ch = '^'; } else value = 0; if (ch == '^') { ch = *str++; if (ch == '?') value |= 0177; else value |= ch & 037; do_putchar(value); continue; } /* Finally test for sequences valid in the format string */ str = conv_escape(str - 1, &c); do_putchar(c); } } /* * Print "standard" escape characters */ static char * conv_escape(char *str, char *conv_ch) { int value; int ch; char num_buf[4], *num_end; ch = *str++; switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': num_buf[0] = ch; ch = str[0]; num_buf[1] = ch; num_buf[2] = ch ? str[1] : 0; num_buf[3] = 0; value = strtoul(num_buf, &num_end, 8); str += num_end - (num_buf + 1); break; case 'x': /* Hexadecimal character constants are not required to be supported (by SuS v1) because there is no consistent way to detect the end of the constant. Supporting 2 byte constants is a compromise. */ ch = str[0]; num_buf[0] = ch; num_buf[1] = ch ? str[1] : 0; num_buf[2] = 0; value = strtoul(num_buf, &num_end, 16); str += num_end - num_buf; break; case '\\': value = '\\'; break; /* backslash */ case '\'': value = '\''; break; /* single quote */ case '"': value = '"'; break; /* double quote */ case 'a': value = '\a'; break; /* alert */ case 'b': value = '\b'; break; /* backspace */ case 'e': value = ESCAPE; break; /* escape */ case 'f': value = '\f'; break; /* form-feed */ case 'n': value = '\n'; break; /* newline */ case 'r': value = '\r'; break; /* carriage-return */ case 't': value = '\t'; break; /* tab */ case 'v': value = '\v'; break; /* vertical-tab */ default: warnx("unknown escape sequence `\\%c'", ch); rval = 1; value = ch; break; } *conv_ch = value; return str; } /* expand a string so that everything is printable */ static char * conv_expand(const char *str) { static char *conv_str; static char no_memory[] = ""; char *cp; int ch; if (conv_str) free(conv_str); /* get a buffer that is definitely large enough.... */ conv_str = malloc(4 * strlen(str) + 1); if (!conv_str) return no_memory; cp = conv_str; while ((ch = *(const unsigned char *)str++) != '\0') { switch (ch) { /* Use C escapes for expected control characters */ case '\\': ch = '\\'; break; /* backslash */ case '\'': ch = '\''; break; /* single quote */ case '"': ch = '"'; break; /* double quote */ case '\a': ch = 'a'; break; /* alert */ case '\b': ch = 'b'; break; /* backspace */ case ESCAPE: ch = 'e'; break; /* escape */ case '\f': ch = 'f'; break; /* form-feed */ case '\n': ch = 'n'; break; /* newline */ case '\r': ch = 'r'; break; /* carriage-return */ case '\t': ch = 't'; break; /* tab */ case '\v': ch = 'v'; break; /* vertical-tab */ default: /* Copy anything printable */ if (isprint(ch)) { *cp++ = ch; continue; } /* Use vis(3) encodings for the rest */ *cp++ = '\\'; if (ch & 0200) { *cp++ = 'M'; ch &= ~0200; } if (ch == 0177) { *cp++ = '^'; *cp++ = '?'; continue; } if (ch < 040) { *cp++ = '^'; *cp++ = ch | 0100; continue; } *cp++ = '-'; *cp++ = ch; continue; } *cp++ = '\\'; *cp++ = ch; } *cp = 0; return conv_str; } static char * mklong(const char *str, int ch) { static char copy[64]; size_t len; len = strlen(str) - 1; if (len > sizeof(copy) - 5) { warnx("format %s too complex\n", str); len = 4; } (void)memmove(copy, str, len); #ifndef _MSC_VER copy[len++] = 'j'; #else copy[len++] = 'I'; copy[len++] = '6'; copy[len++] = '4'; #endif copy[len++] = ch; copy[len] = '\0'; return copy; } static int getchr(void) { if (!*gargv) return 0; return (int)**gargv++; } static char * getstr(void) { static char empty[] = ""; if (!*gargv) return empty; return *gargv++; } static int getwidth(void) { long val; char *s, *ep; s = *gargv; if (!*gargv) return (0); gargv++; errno = 0; val = strtoul(s, &ep, 0); check_conversion(s, ep); /* Arbitrarily 'restrict' field widths to 1Mbyte */ if (val < 0 || val > 1 << 20) { warnx("%s: invalid field width", s); return 0; } return val; } static intmax_t getintmax(void) { intmax_t val; char *cp, *ep; cp = *gargv; if (cp == NULL) return 0; gargv++; if (*cp == '\"' || *cp == '\'') return *(cp+1); errno = 0; val = strtoimax(cp, &ep, 0); check_conversion(cp, ep); return val; } static uintmax_t getuintmax(void) { uintmax_t val; char *cp, *ep; cp = *gargv; if (cp == NULL) return 0; gargv++; if (*cp == '\"' || *cp == '\'') return *(cp + 1); /* strtoumax won't error -ve values */ while (isspace(*(unsigned char *)cp)) cp++; if (*cp == '-') { warnx("%s: expected positive numeric value", cp); rval = 1; return 0; } errno = 0; val = strtoumax(cp, &ep, 0); check_conversion(cp, ep); return val; } static double getdouble(void) { double val; char *ep; if (!*gargv) return (0.0); if (**gargv == '\"' || **gargv == '\'') return (double) *((*gargv++)+1); errno = 0; val = strtod(*gargv, &ep); check_conversion(*gargv++, ep); return val; } static void check_conversion(const char *s, const char *ep) { if (*ep) { if (ep == s) warnx("%s: expected numeric value", s); else warnx("%s: not completely converted", s); rval = 1; } else if (errno == ERANGE) { warnx("%s: %s", s, strerror(ERANGE)); rval = 1; } } static int usage(FILE *pf) { fprintf(pf, "usage: %s format [arg ...]\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname); return 1; } kbuild-2695/src/kmk/kmkbuiltin/kDepObj.c0000644000000000000000000011433712247157307016656 0ustar rootroot/* $Id: kDepObj.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * kDepObj - Extract dependency information from an object file. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #if !defined(_MSC_VER) # include #else # include #endif #include "../../lib/k/kDefs.h" #include "../../lib/k/kTypes.h" #include "../../lib/k/kLdrFmts/pe.h" #include "../../lib/kDep.h" #include "kmkbuiltin.h" /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /*#define DEBUG*/ #define DEBUG #ifdef DEBUG # define dprintf(a) printf a # define dump(pb, cb, offBase) depHexDump(pb,cb,offBase) #else # define dprintf(a) do {} while (0) # define dump(pb, cb, offBase) do {} while (0) #endif /** @name OMF defines * @{ */ #define KDEPOMF_THEADR 0x80 #define KDEPOMF_LHEADR 0x82 #define KDEPOMF_COMENT 0x88 #define KDEPOMF_CMTCLS_DEPENDENCY 0xe9 #define KDEPOMF_CMTCLS_DBGTYPE 0xa1 #define KDEPOMF_LINNUM 0x94 #define KDEPOMF_LINNUM32 0x95 /** @} */ /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ /** @name OMF Structures * @{ */ #pragma pack(1) /** OMF record header. */ typedef struct KDEPOMFHDR { /** The record type. */ KU8 bType; /** The size of the record, excluding this header. */ KU16 cbRec; } KDEPOMFHDR; typedef KDEPOMFHDR *PKDEPOMFHDR; typedef const KDEPOMFHDR *PCKDEPOMFHDR; /** OMF string. */ typedef struct KDEPOMFSTR { KU8 cch; char ach[1]; } KDEPOMFSTR; typedef KDEPOMFSTR *PKDEPOMFSTR; typedef const KDEPOMFSTR *PCKDEPOMFSTR; /** THEADR/LHEADR. */ typedef struct KDEPOMFTHEADR { KDEPOMFHDR Hdr; KDEPOMFSTR Name; } KDEPOMFTHEADR; typedef KDEPOMFTHEADR *PKDEPOMFTHEADR; typedef const KDEPOMFTHEADR *PCKDEPOMFTHEADR; /** Dependency File. */ typedef struct KDEPOMFDEPFILE { KDEPOMFHDR Hdr; KU8 fType; KU8 bClass; KU16 wDosTime; KU16 wDosDate; KDEPOMFSTR Name; } KDEPOMFDEPFILE; typedef KDEPOMFDEPFILE *PKDEPOMFDEPFILE; typedef const KDEPOMFDEPFILE *PCKDEPOMFDEPFILE; #pragma pack() /** @} */ /** @name COFF Structures * @{ */ #pragma pack(1) typedef struct KDEPCVSYMHDR { /** The record size minus the size field. */ KU16 cb; /** The record type. */ KU16 uType; } KDEPCVSYMHDR; typedef KDEPCVSYMHDR *PKDEPCVSYMHDR; typedef const KDEPCVSYMHDR *PCKDEPCVSYMHDR; /** @name Selection of KDEPCVSYMHDR::uType values. * @{ */ #define K_CV8_S_MSTOOL KU16_C(0x1116) /** @} */ typedef struct KDEPCV8SYMHDR { /** The record type. */ KU32 uType; /** The record size minus the size field. */ KU32 cb; } KDEPCV8SYMHDR; typedef KDEPCV8SYMHDR *PKDEPCV8SYMHDR; typedef const KDEPCV8SYMHDR *PCKDEPCV8SYMHDR; /** @name Known KDEPCV8SYMHDR::uType Values. * @{ */ #define K_CV8_SYMBOL_INFO KU32_C(0x000000f1) #define K_CV8_LINE_NUMBERS KU32_C(0x000000f2) #define K_CV8_STRING_TABLE KU32_C(0x000000f3) #define K_CV8_SOURCE_FILES KU32_C(0x000000f4) #define K_CV8_COMDAT_XXXXX KU32_C(0x000000f5) /**< no idea about the format... */ /** @} */ #pragma pack() /** @} */ /******************************************************************************* * Global Variables * *******************************************************************************/ /** the executable name. */ static const char *argv0 = ""; static const char *g_pszFile = NULL; /** * Prints an error message. * * @returns rc. * @param rc The return code, for making one line return statements. * @param pszFormat The message format string. * @param ... Format arguments. * @todo Promote this to kDep.c. */ static int kDepErr(int rc, const char *pszFormat, ...) { va_list va; const char *psz; const char *pszName = argv0; fflush(stdout); /* The message prefix. */ while ((psz = strpbrk(pszName, "/\\:")) != NULL) pszName = psz + 1; if (g_pszFile) fprintf(stderr, "%s: %s: error: ", pszName, g_pszFile); else fprintf(stderr, "%s: error: ", pszName); /* The message. */ va_start(va, pszFormat); vfprintf(stderr, pszFormat, va); va_end(va); return rc; } /** * Gets an index from the data. * * @returns The index, KU16_MAX on buffer underflow. * @param puData The current data stream position (in/out). * @param pcbLeft Number of bytes left (in/out). */ static KU16 kDepObjOMFGetIndex(KPCUINT *puData, KU16 *pcbLeft) { KU16 u16; if (*pcbLeft >= 1 && *pcbLeft != KU16_MAX) { *pcbLeft -= 1; u16 = *puData->pb++; if (u16 & KU16_C(0x80)) { if (*pcbLeft >= 1) { *pcbLeft -= 1; u16 = ((u16 & KU16_C(0x7f)) << 8) | *puData->pb++; } else u16 = KU16_MAX; } } else u16 = KU16_MAX; return u16; } /** * Parses the OMF file. * * @returns 0 on success, 1 on failure, 2 if no dependencies was found. * @param pbFile The start of the file. * @param cbFile The file size. */ int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile) { PCKDEPOMFHDR pHdr = (PCKDEPOMFHDR)pbFile; KSIZE cbLeft = cbFile; char uDbgType = 0; /* H or C */ KU8 uDbgVer = KU8_MAX; KU32 iSrc = 0; KU32 iMaybeSrc = 0; KU8 uLinNumType = KU8_MAX; KU16 cLinNums = 0; KU32 cLinFiles = 0; KU32 iLinFile = 0; /* * Iterate thru the records until we hit the end or an invalid one. */ while ( cbLeft >= sizeof(*pHdr) && cbLeft >= pHdr->cbRec + sizeof(*pHdr)) { KPCUINT uData; uData.pv = pHdr + 1; /* process selected record types. */ dprintf(("%#07" KUPTR_PRI ": %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec)); switch (pHdr->bType) { /* * The T/L Header contains the source name. When emitting CodeView 4 * and earlier (like masm and watcom does), all includes used by the * line number tables have their own THEADR record. */ case KDEPOMF_THEADR: case KDEPOMF_LHEADR: { PCKDEPOMFTHEADR pTHeadr = (PCKDEPOMFTHEADR)pHdr; if (1 + pTHeadr->Name.cch + 1 != pHdr->cbRec) return kDepErr(1, "%#07x - Bad %cHEADR record, length mismatch.\n", (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L'); if ( ( pTHeadr->Name.cch > 2 && pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == '.' && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'o' || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'O')) || ( pTHeadr->Name.cch > 4 && pTHeadr->Name.ach[pTHeadr->Name.cch - 4] == '.' && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'o' || pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'O') && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'b' || pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'B') && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'j' || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'J')) ) dprintf(("%cHEADR: %.*s [ignored]\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach)); else { dprintf(("%cHEADR: %.*s\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach)); depAdd(pTHeadr->Name.ach, pTHeadr->Name.cch); iMaybeSrc++; } uLinNumType = KU8_MAX; break; } case KDEPOMF_COMENT: { KU8 uClass; if (pHdr->cbRec < 2 + 1) return kDepErr(1, "%#07x - Bad COMMENT record, too small.\n", (const KU8*)pHdr - pbFile); if (uData.pb[0] & 0x3f) return kDepErr(1, "%#07x - Bad COMMENT record, reserved flags set.\n", (const KU8*)pHdr - pbFile); uClass = uData.pb[1]; uData.pb += 2; switch (uClass) { /* * Borland dependency file comment (famously used by wmake and Watcom). */ case KDEPOMF_CMTCLS_DEPENDENCY: { PCKDEPOMFDEPFILE pDep = (PCKDEPOMFDEPFILE)pHdr; if (K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1 != pHdr->cbRec + sizeof(*pHdr)) { /* Empty record indicates the end of the dependency files, no need to go on. */ if (pHdr->cbRec == 2 + 1) return 0; return kDepErr(1, "%#07lx - Bad DEPENDENCY FILE record, length mismatch. (%u/%u)\n", (long)((const KU8 *)pHdr - pbFile), K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1, (unsigned)(pHdr->cbRec + sizeof(*pHdr))); } depAdd(pDep->Name.ach, pDep->Name.cch); iSrc++; break; } /* * Pick up the debug type so we can parse the LINNUM records. */ case KDEPOMF_CMTCLS_DBGTYPE: if (pHdr->cbRec < 2 + 3 + 1) break; /* ignore, Borland used this for something else apparently. */ if ( !(uData.pb[1] == 'C' && uData.pb[2] == 'V') && !(uData.pb[1] == 'H' && uData.pb[2] == 'L')) { dprintf(("Unknown debug type: %c%c (%u)\n", uData.pb[1], uData.pb[2], uData.pb[0])); break; } uDbgType = uData.pb[1]; uDbgVer = uData.pb[0]; dprintf(("Debug Type %s ver %u\n", uDbgType == 'H' ? "HLL" : "CodeView", uDbgVer)); break; } break; /* COMENT */ } /* * LINNUM + THEADR == sigar. */ case KDEPOMF_LINNUM: if (uDbgType == 'C') iMaybeSrc |= KU32_C(0x80000000); dprintf(("LINNUM:\n")); break; /* * The HLL v4 and v6 file names table will include all files when present, which * is perfect for generating dependencies. */ case KDEPOMF_LINNUM32: if ( uDbgType == 'H' && uDbgVer >= 3 && uDbgVer <= 6) { /* skip two indexes (group & segment) */ KU16 cbRecLeft = pHdr->cbRec - 1; KU16 uGrp = kDepObjOMFGetIndex(&uData, &cbRecLeft); KU16 uSeg = kDepObjOMFGetIndex(&uData, &cbRecLeft); if (uSeg == KU16_MAX) return kDepErr(1, "%#07lx - Bad LINNUM32 record\n", (long)((const KU8 *)pHdr - pbFile)); if (uLinNumType == KU8_MAX) { static const char * const s_apsz[5] = { "source file", "listing file", "source & listing file", "file names table", "path table" }; KU16 uLine; KU8 uReserved; KU16 uSeg2; KU32 cbLinNames; if (cbRecLeft < 2+1+1+2+2+4) return kDepErr(1, "%#07lx - Bad LINNUM32 record, too short\n", (long)((const KU8 *)pHdr - pbFile)); cbRecLeft -= 2+1+1+2+2+4; uLine = *uData.pu16++; uLinNumType = *uData.pu8++; uReserved = *uData.pu8++; cLinNums = *uData.pu16++; uSeg2 = *uData.pu16++; cbLinNames = *uData.pu32++; dprintf(("LINNUM32: uGrp=%#x uSeg=%#x uSeg2=%#x uLine=%#x (MBZ) uReserved=%#x\n", uGrp, uSeg, uSeg2, uLine, uReserved)); dprintf(("LINNUM32: cLinNums=%#x (%u) cbLinNames=%#x (%u) uLinNumType=%#x (%s)\n", cLinNums, cLinNums, cbLinNames, cbLinNames, uLinNumType, uLinNumType < K_ELEMENTS(s_apsz) ? s_apsz[uLinNumType] : "??")); if (uLine != 0) return kDepErr(1, "%#07lx - Bad LINNUM32 record, line %#x (MBZ)\n", (long)((const KU8 *)pHdr - pbFile), uLine); cLinFiles = iLinFile = KU32_MAX; if ( uLinNumType == 3 /* file names table */ || uLinNumType == 4 /* path table */) cLinNums = 0; /* no line numbers */ else if (uLinNumType > 4) return kDepErr(1, "%#07lx - Bad LINNUM32 record, type %#x unknown\n", (long)((const KU8 *)pHdr - pbFile), uLinNumType); } else dprintf(("LINNUM32: uGrp=%#x uSeg=%#x\n", uGrp, uSeg)); /* Skip file numbers (we parse them to follow the stream correctly). */ if (uLinNumType != 3 && uLinNumType != 4) { static const unsigned s_acbTypes[3] = { 2+2+4, 4+4+4, 2+2+4+4+4 }; unsigned cbEntry = s_acbTypes[uLinNumType]; while (cLinNums && cbRecLeft) { if (cbRecLeft < cbEntry) return kDepErr(1, "%#07lx - Bad LINNUM32 record, incomplete line entry\n", (long)((const KU8 *)pHdr - pbFile)); switch (uLinNumType) { case 0: /* source file */ dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI " at %#010" KX32_PRI "\n", uData.pu16[0], uData.pu16[1], uData.pu32[1])); break; case 1: /* listing file */ dprintf((" Line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n", uData.pu32[0], uData.pu32[1], uData.pu32[2])); break; case 2: /* source & listing file */ dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI ", listning line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n", uData.pu16[0], uData.pu16[1], uData.pu32[1], uData.pu32[2], uData.pu32[3])); break; } uData.pb += cbEntry; cbRecLeft -= cbEntry; cLinNums--; } /* If at end of the announced line number entiries, we may find a file names table here (who is actually emitting this?). */ if (!cLinNums) { uLinNumType = cbRecLeft > 0 ? 3 : KU8_MAX; dprintf(("End-of-line-numbers; uLinNumType=%u cbRecLeft=%#x\n", uLinNumType, cbRecLeft)); } } if (uLinNumType == 3 || uLinNumType == 4) { /* Read the file/path table header (first time only). */ if (cLinFiles == KU32_MAX && iLinFile == KU32_MAX) { KU32 iFirstCol; KU32 cCols; if (cbRecLeft < 4+4+4) return kDepErr(1, "%#07lx - Bad LINNUM32 record, incomplete file/path table header\n", (long)((const KU8 *)pHdr - pbFile)); cbRecLeft -= 4+4+4; iFirstCol = *uData.pu32++; cCols = *uData.pu32++; cLinFiles = *uData.pu32++; dprintf(("%s table header: cLinFiles=%#" KX32_PRI " (%" KU32_PRI ") iFirstCol=%" KU32_PRI " cCols=%" KU32_PRI"\n", uLinNumType == 3 ? "file names" : "path", cLinFiles, cLinFiles, iFirstCol, cCols)); if (cLinFiles == KU32_MAX) return kDepErr(1, "%#07lx - Bad LINNUM32 record, too many file/path table entries.\n", (long)((const KU8 *)pHdr - pbFile)); iLinFile = 0; } /* Parse the file names / path table. */ while (iLinFile < cLinFiles && cbRecLeft) { int cbName = *uData.pb++; if (cbRecLeft < 1 + cbName) return kDepErr(1, "%#07lx - Bad LINNUM32 record, file/path table entry too long.\n", (long)((const KU8 *)pHdr - pbFile)); iLinFile++; dprintf(("#%" KU32_PRI": %.*s\n", iLinFile, cbName, uData.pch)); if (uLinNumType == 3) { depAdd(uData.pch, cbName); iSrc++; } cbRecLeft -= 1 + cbName; uData.pb += cbName; } /* The end? */ if (iLinFile == cLinFiles) { uLinNumType = KU8_MAX; dprintf(("End-of-file/path-table; cbRecLeft=%#x\n", cbRecLeft)); } } } else dprintf(("LINNUM32: Unknown or unsupported format\n")); break; } /* advance */ cbLeft -= pHdr->cbRec + sizeof(*pHdr); pHdr = (PCKDEPOMFHDR)((const KU8 *)(pHdr + 1) + pHdr->cbRec); } if (cbLeft) return kDepErr(1, "%#07x - Unexpected EOF. cbLeft=%#x\n", (const KU8*)pHdr - pbFile, cbLeft); if (iSrc == 0 && iMaybeSrc <= 1) { dprintf(("kDepObjOMFParse: No cylindrical smoking thing: iSrc=0 iMaybeSrc=%#" KX32_PRI"\n", iMaybeSrc)); return 2; } dprintf(("kDepObjOMFParse: iSrc=%" KU32_PRI " iMaybeSrc=%#" KX32_PRI "\n", iSrc, iMaybeSrc)); return 0; } /** * Checks if this file is an OMF file or not. * * @returns K_TRUE if it's OMF, K_FALSE otherwise. * * @param pb The start of the file. * @param cb The file size. */ KBOOL kDepObjOMFTest(const KU8 *pbFile, KSIZE cbFile) { PCKDEPOMFTHEADR pHdr = (PCKDEPOMFTHEADR)pbFile; if (cbFile <= sizeof(*pHdr)) return K_FALSE; if ( pHdr->Hdr.bType != KDEPOMF_THEADR && pHdr->Hdr.bType != KDEPOMF_LHEADR) return K_FALSE; if (pHdr->Hdr.cbRec + sizeof(pHdr->Hdr) >= cbFile) return K_FALSE; if (pHdr->Hdr.cbRec != 1 + pHdr->Name.cch + 1) return K_FALSE; return K_TRUE; } /** * Parses a CodeView 8 symbol section. * * @returns 0 on success, 1 on failure, 2 if no dependencies was found. * @param pbSyms Pointer to the start of the symbol section. * @param cbSyms Size of the symbol section. */ int kDepObjCOFFParseCV8SymbolSection(const KU8 *pbSyms, KSIZE cbSyms) { char const * pchStrTab = NULL; KU32 cbStrTab = 0; KPCUINT uSrcFiles = {0}; KU32 cbSrcFiles = 0; KU32 off = 4; KU32 iSrc = 0; if (cbSyms < 16) return 1; /* * The parsing loop. */ while (off < cbSyms) { PCKDEPCV8SYMHDR pHdr = (PCKDEPCV8SYMHDR)(pbSyms + off); KPCUINT uData; KU32 cbData; uData.pv = pHdr + 1; if (off + sizeof(*pHdr) >= cbSyms) { fprintf(stderr, "%s: CV symbol table entry at %08" KX32_PRI " is too long; cbSyms=%#" KSIZE_PRI "\n", argv0, off, cbSyms); return 1; /* FIXME */ } cbData = pHdr->cb; if (off + cbData + sizeof(*pHdr) > cbSyms) { fprintf(stderr, "%s: CV symbol table entry at %08" KX32_PRI " is too long; cbData=%#" KX32_PRI " cbSyms=%#" KSIZE_PRI "\n", argv0, off, cbData, cbSyms); return 1; /* FIXME */ } /* If the size is 0, assume it covers the rest of the section. VC++ 2003 has been observed doing thing. */ if (!cbData) cbData = cbSyms - off; switch (pHdr->uType) { case K_CV8_SYMBOL_INFO: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Symbol Info\n", off, cbData)); /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_LINE_NUMBERS: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Line numbers\n", off, cbData)); /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_STRING_TABLE: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": String table\n", off, cbData)); if (pchStrTab) fprintf(stderr, "%s: warning: Found yet another string table!\n", argv0); pchStrTab = uData.pch; cbStrTab = cbData; /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_SOURCE_FILES: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Source files\n", off, cbData)); if (uSrcFiles.pb) fprintf(stderr, "%s: warning: Found yet another source files table!\n", argv0); uSrcFiles = uData; cbSrcFiles = cbData; /*dump(uData.pb, cbData, 0);*/ break; case K_CV8_COMDAT_XXXXX: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": 0xf5 Unknown COMDAT stuff\n", off, cbData)); /*dump(uData.pb, cbData, 0);*/ break; default: dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Unknown type %#" KX32_PRI "\n", off, cbData, pHdr->uType)); dump(uData.pb, cbData, 0); break; } /* next */ cbData = (cbData + 3) & ~KU32_C(3); off += cbData + sizeof(*pHdr); } /* * Did we find any source files and strings? */ if (!pchStrTab || !uSrcFiles.pv) { dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: pchStrTab=%p uSrcFiles.pv=%p\n", pchStrTab, uSrcFiles.pv)); return 2; } /* * Iterate the source file table. */ off = 0; while (off < cbSrcFiles) { KU32 offFile; const char *pszFile; KSIZE cchFile; KU16 u16Type; KPCUINT uSrc; KU32 cbSrc; /* * Validate and parse the entry (variable length record are fun). */ if (off + 8 > cbSrcFiles) { fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KX32_PRI "\n", argv0, off, cbSrcFiles); return 1; } uSrc.pb = uSrcFiles.pb + off; u16Type = uSrc.pu16[2]; cbSrc = u16Type == 0x0110 ? 6 + 16 + 2 : 6 + 2; if (off + cbSrc > cbSrcFiles) { fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KX32_PRI "\n", argv0, off, cbSrc, cbSrcFiles); return 1; } offFile = *uSrc.pu32; if (offFile > cbStrTab) { fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is out side the string table; offFile=%#" KX32_PRI " cbStrTab=%#" KX32_PRI "\n", argv0, off, offFile, cbStrTab); return 1; } pszFile = pchStrTab + offFile; cchFile = strlen(pszFile); if (cchFile == 0) { fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " has an empty file name; offFile=%#x" KX32_PRI "\n", argv0, off, offFile); return 1; } /* * Display the result and add it to the dependency database. */ depAdd(pszFile, cchFile); if (u16Type == 0x0110) dprintf(("#%03" KU32_PRI ": {todo-md5-todo} '%s'\n", iSrc, pszFile)); else dprintf(("#%03" KU32_PRI ": type=%#06" KX16_PRI " '%s'\n", iSrc, u16Type, pszFile)); /* next */ iSrc++; off += cbSrc; } if (iSrc == 0) { dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: iSrc=0\n")); return 2; } dprintf(("kDepObjCOFFParseCV8SymbolSection: iSrc=%" KU32_PRI "\n", iSrc)); return 0; } /** * Parses the OMF file. * * @returns 0 on success, 1 on failure, 2 if no dependencies was found. * @param pbFile The start of the file. * @param cbFile The file size. */ int kDepObjCOFFParse(const KU8 *pbFile, KSIZE cbFile) { IMAGE_FILE_HEADER const *pFileHdr = (IMAGE_FILE_HEADER const *)pbFile; IMAGE_SECTION_HEADER const *paSHdrs = (IMAGE_SECTION_HEADER const *)((KU8 const *)(pFileHdr + 1) + pFileHdr->SizeOfOptionalHeader); unsigned cSHdrs = pFileHdr->NumberOfSections; unsigned iSHdr; KPCUINT u; int rcRet = 2; int rc; printf("COFF file!\n"); for (iSHdr = 0; iSHdr < cSHdrs; iSHdr++) { if ( !memcmp(paSHdrs[iSHdr].Name, ".debug$S", sizeof(".debug$S") - 1) && paSHdrs[iSHdr].SizeOfRawData > 4) { u.pb = pbFile + paSHdrs[iSHdr].PointerToRawData; dprintf(("CV symbol table: version=%x\n", *u.pu32)); if (*u.pu32 == 0x000000004) rc = kDepObjCOFFParseCV8SymbolSection(u.pb, paSHdrs[iSHdr].SizeOfRawData); else rc = 2; dprintf(("rc=%d\n", rc)); if (rcRet == 2) rcRet = rc; if (rcRet != 2) return rc; } printf("#%d: %.8s\n", iSHdr, paSHdrs[iSHdr].Name); } return rcRet; } /** * Checks if this file is a COFF file or not. * * @returns K_TRUE if it's COFF, K_FALSE otherwise. * * @param pb The start of the file. * @param cb The file size. */ KBOOL kDepObjCOFFTest(const KU8 *pbFile, KSIZE cbFile) { IMAGE_FILE_HEADER const *pFileHdr = (IMAGE_FILE_HEADER const *)pbFile; IMAGE_SECTION_HEADER const *paSHdrs = (IMAGE_SECTION_HEADER const *)((KU8 const *)(pFileHdr + 1) + pFileHdr->SizeOfOptionalHeader); unsigned cSHdrs = pFileHdr->NumberOfSections; unsigned iSHdr; KSIZE cbHdrs = (const KU8 *)&paSHdrs[cSHdrs] - (const KU8 *)pbFile; if (cbFile <= sizeof(*pFileHdr)) return K_FALSE; if ( pFileHdr->Machine != IMAGE_FILE_MACHINE_I386 && pFileHdr->Machine != IMAGE_FILE_MACHINE_AMD64) return K_FALSE; if (pFileHdr->SizeOfOptionalHeader != 0) return K_FALSE; /* COFF files doesn't have an optional header */ if ( pFileHdr->NumberOfSections <= 1 || pFileHdr->NumberOfSections > cbFile) return K_FALSE; if (cbHdrs >= cbFile) return K_FALSE; if ( pFileHdr->PointerToSymbolTable != 0 && ( pFileHdr->PointerToSymbolTable < cbHdrs || pFileHdr->PointerToSymbolTable > cbFile)) return K_FALSE; if ( pFileHdr->PointerToSymbolTable == 0 && pFileHdr->NumberOfSymbols != 0) return K_FALSE; if ( pFileHdr->Characteristics & ( IMAGE_FILE_DLL | IMAGE_FILE_SYSTEM | IMAGE_FILE_UP_SYSTEM_ONLY | IMAGE_FILE_NET_RUN_FROM_SWAP | IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED)) return K_FALSE; for (iSHdr = 0; iSHdr < cSHdrs; iSHdr++) { if ( paSHdrs[iSHdr].PointerToRawData != 0 && ( paSHdrs[iSHdr].PointerToRawData < cbHdrs || paSHdrs[iSHdr].PointerToRawData >= cbFile || paSHdrs[iSHdr].PointerToRawData + paSHdrs[iSHdr].SizeOfRawData > cbFile)) return K_FALSE; if ( paSHdrs[iSHdr].PointerToRelocations != 0 && ( paSHdrs[iSHdr].PointerToRelocations < cbHdrs || paSHdrs[iSHdr].PointerToRelocations >= cbFile || paSHdrs[iSHdr].PointerToRelocations + paSHdrs[iSHdr].NumberOfRelocations * 10 > cbFile)) /* IMAGE_RELOCATION */ return K_FALSE; if ( paSHdrs[iSHdr].PointerToLinenumbers != 0 && ( paSHdrs[iSHdr].PointerToLinenumbers < cbHdrs || paSHdrs[iSHdr].PointerToLinenumbers >= cbFile || paSHdrs[iSHdr].PointerToLinenumbers + paSHdrs[iSHdr].NumberOfLinenumbers * 6 > cbFile)) /* IMAGE_LINENUMBER */ return K_FALSE; } return K_TRUE; } /** * Read the file into memory and parse it. */ static int kDepObjProcessFile(FILE *pInput) { size_t cbFile; KU8 *pbFile; void *pvOpaque; int rc = 0; /* * Read the file into memory. */ pbFile = (KU8 *)depReadFileIntoMemory(pInput, &cbFile, &pvOpaque); if (!pbFile) return 1; /* * See if it's an OMF file, then process it. */ if (kDepObjOMFTest(pbFile, cbFile)) rc = kDepObjOMFParse(pbFile, cbFile); else if (kDepObjCOFFTest(pbFile, cbFile)) rc = kDepObjCOFFParse(pbFile, cbFile); else { fprintf(stderr, "%s: error: Doesn't recognize the header of the OMF file.\n", argv0); rc = 1; } depFreeFileMemory(pbFile, pvOpaque); return rc; } static void usage(const char *a_argv0) { printf("usage: %s -o -t [-fqs] \n" " or: %s --help\n" " or: %s --version\n", a_argv0, a_argv0, a_argv0); } int kmk_builtin_kDepObj(int argc, char *argv[], char **envp) { int i; /* Arguments. */ FILE *pOutput = NULL; const char *pszOutput = NULL; FILE *pInput = NULL; const char *pszTarget = NULL; int fStubs = 0; int fFixCase = 0; /* Argument parsing. */ int fInput = 0; /* set when we've found input argument. */ int fQuiet = 0; argv0 = argv[0]; /* * Parse arguments. */ if (argc <= 1) { usage(argv[0]); return 1; } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { const char *psz = &argv[i][1]; if (*psz == '-') { if (!strcmp(psz, "-quiet")) psz = "q"; else if (!strcmp(psz, "-help")) psz = "?"; else if (!strcmp(psz, "-version")) psz = "V"; } switch (*psz) { /* * Output file. */ case 'o': { pszOutput = &argv[i][2]; if (pOutput) { fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]); return 1; } if (!*pszOutput) { if (++i >= argc) { fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", argv[0]); return 1; } pszOutput = argv[i]; } if (pszOutput[0] == '-' && !pszOutput[1]) pOutput = stdout; else pOutput = fopen(pszOutput, "w"); if (!pOutput) { fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput); return 1; } break; } /* * Target name. */ case 't': { if (pszTarget) { fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]); return 1; } pszTarget = &argv[i][2]; if (!*pszTarget) { if (++i >= argc) { fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", argv[0]); return 1; } pszTarget = argv[i]; } break; } /* * Fix case. */ case 'f': { fFixCase = 1; break; } /* * Quiet. */ case 'q': { fQuiet = 1; break; } /* * Generate stubs. */ case 's': { fStubs = 1; break; } /* * The mandatory version & help. */ case '?': usage(argv[0]); return 0; case 'V': case 'v': return kbuild_version(argv[0]); /* * Invalid argument. */ default: fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]); usage(argv[0]); return 1; } } else { pInput = fopen(argv[i], "rb"); if (!pInput) { fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]); return 1; } fInput = 1; } /* * End of the line? */ if (fInput) { if (++i < argc) { fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]); return 1; } break; } } /* * Got all we require? */ if (!pInput) { fprintf(stderr, "%s: syntax error: No input!\n", argv[0]); return 1; } if (!pOutput) { fprintf(stderr, "%s: syntax error: No output!\n", argv[0]); return 1; } if (!pszTarget) { fprintf(stderr, "%s: syntax error: No target!\n", argv[0]); return 1; } /* * Do the parsing. */ i = kDepObjProcessFile(pInput); fclose(pInput); /* * Write the dependecy file. */ if (!i) { depOptimize(fFixCase, fQuiet); fprintf(pOutput, "%s:", pszTarget); depPrint(pOutput); if (fStubs) depPrintStubs(pOutput); } /* * Close the output, delete output on failure. */ if (!i && ferror(pOutput)) { i = 1; fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput); } fclose(pOutput); if (i) { if (unlink(pszOutput)) fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput); } depCleanup(); return i; } kbuild-2695/src/kmk/kmkbuiltin/sleep.c0000644000000000000000000001221712247157306016441 0ustar rootroot/* $Id: sleep.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * kmk_sleep - suspend execution for an interval of time. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #if defined(_MSC_VER) # include #else # include # include #endif #include "../kmkbuiltin.h" static const char *name(const char *pszName) { const char *psz = strrchr(pszName, '/'); #if defined(_MSC_VER) || defined(__OS2__) const char *psz2 = strrchr(pszName, '\\'); if (!psz2) psz2 = strrchr(pszName, ':'); if (psz2 && (!psz || psz2 > psz)) psz = psz2; #endif return psz ? psz + 1 : pszName; } static int usage(FILE *pOut, const char *argv0) { argv0 = name(argv0); fprintf(pOut, "usage: %s [s]\n" " or: %s ms\n" " or: %s m\n" " or: %s h\n" " or: %s d\n" " or: %s --help\n" " or: %s --version\n" "\n" "Only integer values are accepted.\n" , argv0, argv0, argv0, argv0, argv0, argv0, argv0); return 1; } int kmk_builtin_sleep(int argc, char **argv, char **envp) { long cMsToSleep; long lTmp; unsigned long ulFactor; char *pszInterval; char *pszSuff; /* * Parse arguments. */ if (argc != 2) return usage(stderr, argv[0]); /* help request */ if ( !strcmp(argv[1], "-h") || !strcmp(argv[1], "-?") || !strcmp(argv[1], "-H") || !strcmp(argv[1], "--help")) { usage(stdout, argv[0]); return 0; } /* version request */ if ( !strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { printf("kmk_sleep - kBuild version %d.%d.%d (r%u)\n" "Copyright (c) 2008-2009 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; } /* * Try convert the argument to a time period. * Allow spaces before, between and after the different parts. */ pszInterval = argv[1]; while (isspace(*pszInterval)) pszInterval++; cMsToSleep = strtol(pszInterval, &pszSuff, 0); if (pszSuff == pszInterval) { fprintf(stderr, "%s: malformed interval '%s'!\n", name(argv[0]), pszInterval); return 1; } while (isspace(*pszSuff)) pszSuff++; if (!*pszSuff) ulFactor = 1000; /* s */ else { /* find the suffix length and check that it's only white space following it. */ int cchSuff; int i = 1; while (pszSuff[i] && !isspace(pszSuff[i])) i++; cchSuff = i; while (pszSuff[i]) { if (!isspace(pszSuff[i])) { fprintf(stderr, "%s: malformed interval '%s'!\n", name(argv[0]), pszInterval); return 1; } i++; } if (cchSuff == 2 && !strncmp (pszSuff, "ms", 2)) ulFactor = 1; else if (cchSuff == 1 && *pszSuff == 's') ulFactor = 1000; else if (cchSuff == 1 && *pszSuff == 'm') ulFactor = 60*1000; else if (cchSuff == 1 && *pszSuff == 'h') ulFactor = 60*60*1000; else if (cchSuff == 1 && *pszSuff == 'd') ulFactor = 24*60*60*1000; else { fprintf(stderr, "%s: unknown suffix '%.*s'!\n", name(argv[0]), cchSuff, pszSuff); return 1; } } lTmp = cMsToSleep; cMsToSleep *= ulFactor; if ((cMsToSleep / ulFactor) != (unsigned long)lTmp) { fprintf(stderr, "%s: time interval overflow!\n", name(argv[0])); return 1; } /* * Do the actual sleeping. */ if (cMsToSleep > 0) { #if defined(_MSC_VER) Sleep(cMsToSleep); #else if (cMsToSleep) { struct timespec TimeSpec; TimeSpec.tv_nsec = (cMsToSleep % 1000) * 1000000; TimeSpec.tv_sec = cMsToSleep / 1000; nanosleep(&TimeSpec, NULL); } #endif } return 0; } kbuild-2695/src/kmk/kmkbuiltin/ln.c0000644000000000000000000001530612247157306015744 0ustar rootroot/*- * Copyright (c) 1987, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1987, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/bin/ln/ln.c,v 1.33 2005/02/09 17:37:37 ru Exp $"); #endif /* no $id */ #include "config.h" #ifndef _MSC_VER # include #endif #include #include "err.h" #include #include #include #include #include #include #include "getopt.h" #ifdef _MSC_VER # include "mscfakes.h" #endif #include "kmkbuiltin.h" static int fflag; /* Unlink existing files. */ static int hflag; /* Check new name for symlink first. */ static int iflag; /* Interactive mode. */ static int sflag; /* Symbolic, not hard, link. */ static int vflag; /* Verbose output. */ /* System link call. */ static int (*linkf)(const char *, const char *); static char linkch; static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int linkit(const char *, const char *, int); static int usage(FILE *); int kmk_builtin_ln(int argc, char *argv[], char **envp) { struct stat sb; char *sourcedir; int ch, exitval; /* initialize globals. */ fflag = hflag = iflag = sflag = vflag = 0; linkch = 0; linkf = NULL; /* kmk: reset getopt() and set program name. */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ while ((ch = getopt_long(argc, argv, "fhinsv", long_options, NULL)) != -1) switch (ch) { case 'f': fflag = 1; iflag = 0; break; case 'h': case 'n': hflag = 1; break; case 'i': iflag = 1; fflag = 0; break; case 's': sflag = 1; break; case 'v': vflag = 1; break; case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(stderr); } argv += optind; argc -= optind; linkf = sflag ? symlink : link; linkch = sflag ? '-' : '='; switch(argc) { case 0: return usage(stderr); /* NOTREACHED */ case 1: /* ln target */ return linkit(argv[0], ".", 1); case 2: /* ln target source */ return linkit(argv[0], argv[1], 0); default: ; } /* ln target1 target2 directory */ sourcedir = argv[argc - 1]; if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) { /* * We were asked not to follow symlinks, but found one at * the target--simulate "not a directory" error */ errno = ENOTDIR; return err(1, "st_mode: %s", sourcedir); } if (stat(sourcedir, &sb)) return err(1, "stat: %s", sourcedir); if (!S_ISDIR(sb.st_mode)) return usage(stderr); for (exitval = 0; *argv != sourcedir; ++argv) exitval |= linkit(*argv, sourcedir, 1); return exitval; } static int linkit(const char *target, const char *source, int isdir) { struct stat sb; const char *p; int ch, exists, first; char path[PATH_MAX]; if (!sflag) { /* If target doesn't exist, quit now. */ if (stat(target, &sb)) { warn("stat: %s", target); return (1); } /* Only symbolic links to directories. */ if (S_ISDIR(sb.st_mode)) { errno = EISDIR; warn("st_mode: %s", target); return (1); } } /* * If the source is a directory (and not a symlink if hflag), * append the target's name. */ if (isdir || (lstat(source, &sb) == 0 && S_ISDIR(sb.st_mode)) || (!hflag && stat(source, &sb) == 0 && S_ISDIR(sb.st_mode))) { #if defined(_MSC_VER) || defined(__OS2__) char *p2 = strrchr(target, '\\'); p = strrchr(target, '/'); if (p2 != NULL && (p == NULL || p2 > p)) p = p2; if (p == NULL) #else if ((p = strrchr(target, '/')) == NULL) #endif p = target; else ++p; if (snprintf(path, sizeof(path), "%s/%s", source, p) >= (ssize_t)sizeof(path)) { errno = ENAMETOOLONG; warn("snprintf: %s", target); return (1); } source = path; } exists = !lstat(source, &sb); /* * If the file exists, then unlink it forcibly if -f was specified * and interactively if -i was specified. */ if (fflag && exists) { if (unlink(source)) { warn("unlink: %s", source); return (1); } } else if (iflag && exists) { fflush(stdout); fprintf(stderr, "replace %s? ", source); first = ch = getchar(); while(ch != '\n' && ch != EOF) ch = getchar(); if (first != 'y' && first != 'Y') { fprintf(stderr, "not replaced\n"); return (1); } if (unlink(source)) { warn("unlink: %s", source); return (1); } } /* Attempt the link. */ if ((*linkf)(target, source)) { warn("%s: %s", linkf == link ? "link" : "symlink", source); return (1); } if (vflag) (void)printf("%s %c> %s\n", source, linkch, target); return (0); } static int usage(FILE *pf) { fprintf(pf, "usage: %s [-fhinsv] source_file [target_file]\n" " or: %s [-fhinsv] source_file ... target_dir\n" " or: %s source_file target_file\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname, g_progname, g_progname); return 1; } kbuild-2695/src/kmk/kmkbuiltin/test.c0000644000000000000000000004705612247157306016321 0ustar rootroot/* $NetBSD: test.c,v 1.33 2007/06/24 18:54:58 christos Exp $ */ /* * test(1); version 7-like -- author Erik Baalbergen * modified by Eric Gisin to be used as built-in. * modified by Arnold Robbins to add SVR3 compatibility * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). * modified by J.T. Conklin for NetBSD. * * This program is in the Public Domain. */ /*#include #ifndef lint __RCSID("$NetBSD: test.c,v 1.33 2007/06/24 18:54:58 christos Exp $"); #endif*/ #include "config.h" #include #include #include #include "err.h" #include #include #include #include #include #ifdef _MSC_VER # include # include # include # include "mscfakes.h" #else # include #endif #include #include #include "kmkbuiltin.h" #ifndef __arraycount # define __arraycount(a) ( sizeof(a) / sizeof(a[0]) ) #endif /* test(1) accepts the following grammar: oexpr ::= aexpr | aexpr "-o" oexpr ; aexpr ::= nexpr | nexpr "-a" aexpr ; nexpr ::= primary | "!" primary primary ::= unary-operator operand | operand binary-operator operand | operand | "(" oexpr ")" ; unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| "-nt"|"-ot"|"-ef"; operand ::= */ enum token { EOI, FILRD, FILWR, FILEX, FILEXIST, FILREG, FILDIR, FILCDEV, FILBDEV, FILFIFO, FILSOCK, FILSYM, FILGZ, FILTT, FILSUID, FILSGID, FILSTCK, FILNT, FILOT, FILEQ, FILUID, FILGID, STREZ, STRNZ, STREQ, STRNE, STRLT, STRGT, INTEQ, INTNE, INTGE, INTGT, INTLE, INTLT, UNOT, BAND, BOR, LPAREN, RPAREN, OPERAND }; enum token_types { UNOP, BINOP, BUNOP, BBINOP, PAREN }; struct t_op { const char *op_text; short op_num, op_type; }; static const struct t_op cop[] = { {"!", UNOT, BUNOP}, {"(", LPAREN, PAREN}, {")", RPAREN, PAREN}, {"<", STRLT, BINOP}, {"=", STREQ, BINOP}, {">", STRGT, BINOP}, }; static const struct t_op cop2[] = { {"!=", STRNE, BINOP}, }; static const struct t_op mop3[] = { {"ef", FILEQ, BINOP}, {"eq", INTEQ, BINOP}, {"ge", INTGE, BINOP}, {"gt", INTGT, BINOP}, {"le", INTLE, BINOP}, {"lt", INTLT, BINOP}, {"ne", INTNE, BINOP}, {"nt", FILNT, BINOP}, {"ot", FILOT, BINOP}, }; static const struct t_op mop2[] = { {"G", FILGID, UNOP}, {"L", FILSYM, UNOP}, {"O", FILUID, UNOP}, {"S", FILSOCK,UNOP}, {"a", BAND, BBINOP}, {"b", FILBDEV,UNOP}, {"c", FILCDEV,UNOP}, {"d", FILDIR, UNOP}, {"e", FILEXIST,UNOP}, {"f", FILREG, UNOP}, {"g", FILSGID,UNOP}, {"h", FILSYM, UNOP}, /* for backwards compat */ {"k", FILSTCK,UNOP}, {"n", STRNZ, UNOP}, {"o", BOR, BBINOP}, {"p", FILFIFO,UNOP}, {"r", FILRD, UNOP}, {"s", FILGZ, UNOP}, {"t", FILTT, UNOP}, {"u", FILSUID,UNOP}, {"w", FILWR, UNOP}, {"x", FILEX, UNOP}, {"z", STREZ, UNOP}, }; static char **t_wp; static struct t_op const *t_wp_op; static int syntax(const char *, const char *); static int oexpr(enum token); static int aexpr(enum token); static int nexpr(enum token); static int primary(enum token); static int binop(void); static int test_access(struct stat *, mode_t); static int filstat(char *, enum token); static enum token t_lex(char *); static int isoperand(void); static int getn(const char *); static int newerf(const char *, const char *); static int olderf(const char *, const char *); static int equalf(const char *, const char *); static int usage(const char *); #if !defined(kmk_builtin_test) || defined(ELECTRIC_HEAP) extern void *xmalloc(unsigned int); #else extern void *xmalloc(unsigned int sz) { void *p = malloc(sz); if (!p) { fprintf(stderr, "%s: malloc(%u) failed\n", g_progname, sz); exit(1); } return p; } #endif int kmk_builtin_test(int argc, char **argv, char **envp, char ***ppapszArgvSpawn) { int res; char **argv_spawn; int i; g_progname = argv[0]; /* look for the '--', '--help' and '--version'. */ argv_spawn = NULL; for (i = 1; i < argc; i++) { if ( argv[i][0] == '-' && argv[i][1] == '-') { if (argv[i][2] == '\0') { argc = i; argv[i] = NULL; /* skip blank arguments (happens inside kmk) */ while (argv[++i]) { const char *psz = argv[i]; while (isspace(*psz)) psz++; if (*psz) break; } argv_spawn = &argv[i]; break; } if (!strcmp(argv[i], "--help")) return usage(argv[0]); if (!strcmp(argv[i], "--version")) return kbuild_version(argv[0]); } } /* are we '['? then check for ']'. */ if (strcmp(g_progname, "[") == 0) { /** @todo should skip the path in g_progname */ if (strcmp(argv[--argc], "]")) return errx(1, "missing ]"); argv[argc] = NULL; } /* evaluate the expression */ if (argc < 2) res = 1; else { t_wp = &argv[1]; res = oexpr(t_lex(*t_wp)); if (res != -42 && *t_wp != NULL && *++t_wp != NULL) res = syntax(*t_wp, "unexpected operator"); if (res == -42) return 1; /* don't mix syntax errors with the argv_spawn ignore */ res = !res; } /* anything to execute on success? */ if (argv_spawn) { if (res != 0 || !argv_spawn[0]) res = 0; /* ignored */ else { #ifdef kmk_builtin_test /* try exec the specified process */ # if defined(_MSC_VER) res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn); if (res == -1) res = err(1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[0]); # else execvp(argv_spawn[0], argv_spawn); res = err(1, "execvp(%s,..)", argv_spawn[0]); # endif #else /* in kmk */ /* let job.c spawn the process, make a job.c style argv_spawn copy. */ char *buf, *cur, **argv_new; size_t sz = 0; int argc_new = 0; while (argv_spawn[argc_new]) { size_t len = strlen(argv_spawn[argc_new]) + 1; sz += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1); argc_new++; } argv_new = xmalloc((argc_new + 1) * sizeof(char *)); buf = cur = xmalloc(sz); for (i = 0; i < argc_new; i++) { size_t len = strlen(argv_spawn[i]) + 1; argv_new[i] = memcpy(cur, argv_spawn[i], len); cur += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1); } argv_new[i] = NULL; *ppapszArgvSpawn = argv_new; res = 0; #endif /* in kmk */ } } return res; } static int syntax(const char *op, const char *msg) { if (op && *op) errx(1, "%s: %s", op, msg); else errx(1, "%s", msg); return -42; } static int oexpr(enum token n) { int res; res = aexpr(n); if (res == -42 || *t_wp == NULL) return res; if (t_lex(*++t_wp) == BOR) { int res2 = oexpr(t_lex(*++t_wp)); return res2 != -42 ? res2 || res : res2; } t_wp--; return res; } static int aexpr(enum token n) { int res; res = nexpr(n); if (res == -42 || *t_wp == NULL) return res; if (t_lex(*++t_wp) == BAND) { int res2 = aexpr(t_lex(*++t_wp)); return res2 != -42 ? res2 && res : res2; } t_wp--; return res; } static int nexpr(enum token n) { if (n == UNOT) { int res = nexpr(t_lex(*++t_wp)); return res != -42 ? !res : res; } return primary(n); } static int primary(enum token n) { enum token nn; int res; if (n == EOI) return 0; /* missing expression */ if (n == LPAREN) { if ((nn = t_lex(*++t_wp)) == RPAREN) return 0; /* missing expression */ res = oexpr(nn); if (res != -42 && t_lex(*++t_wp) != RPAREN) return syntax(NULL, "closing paren expected"); return res; } if (t_wp_op && t_wp_op->op_type == UNOP) { /* unary expression */ if (*++t_wp == NULL) return syntax(t_wp_op->op_text, "argument expected"); switch (n) { case STREZ: return strlen(*t_wp) == 0; case STRNZ: return strlen(*t_wp) != 0; case FILTT: return isatty(getn(*t_wp)); default: return filstat(*t_wp, n); } } if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { return binop(); } return strlen(*t_wp) > 0; } static int binop(void) { const char *opnd1, *opnd2; struct t_op const *op; opnd1 = *t_wp; (void) t_lex(*++t_wp); op = t_wp_op; if ((opnd2 = *++t_wp) == NULL) return syntax(op->op_text, "argument expected"); switch (op->op_num) { case STREQ: return strcmp(opnd1, opnd2) == 0; case STRNE: return strcmp(opnd1, opnd2) != 0; case STRLT: return strcmp(opnd1, opnd2) < 0; case STRGT: return strcmp(opnd1, opnd2) > 0; case INTEQ: return getn(opnd1) == getn(opnd2); case INTNE: return getn(opnd1) != getn(opnd2); case INTGE: return getn(opnd1) >= getn(opnd2); case INTGT: return getn(opnd1) > getn(opnd2); case INTLE: return getn(opnd1) <= getn(opnd2); case INTLT: return getn(opnd1) < getn(opnd2); case FILNT: return newerf(opnd1, opnd2); case FILOT: return olderf(opnd1, opnd2); case FILEQ: return equalf(opnd1, opnd2); default: abort(); /* NOTREACHED */ #ifdef _MSC_VER return -42; #endif } } /* * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits, * not use access(): * * True shall indicate only that the write flag is on. The file is not * writable on a read-only file system even if this test indicates true. * * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only: * * True shall indicate that permission to read from file will be granted, * as defined in "File Read, Write, and Creation". * * and that section says: * * When a file is to be read or written, the file shall be opened with an * access mode corresponding to the operation to be performed. If file * access permissions deny access, the requested operation shall fail. * * and of course access permissions are described as one might expect: * * * If a process has the appropriate privilege: * * * If read, write, or directory search permission is requested, * access shall be granted. * * * If execute permission is requested, access shall be granted if * execute permission is granted to at least one user by the file * permission bits or by an alternate access control mechanism; * otherwise, access shall be denied. * * * Otherwise: * * * The file permission bits of a file contain read, write, and * execute/search permissions for the file owner class, file group * class, and file other class. * * * Access shall be granted if an alternate access control mechanism * is not enabled and the requested access permission bit is set for * the class (file owner class, file group class, or file other class) * to which the process belongs, or if an alternate access control * mechanism is enabled and it allows the requested access; otherwise, * access shall be denied. * * and when I first read this I thought: surely we can't go about using * open(O_WRONLY) to try this test! However the POSIX 1003.1-2001 Rationale * section for test does in fact say: * * On historical BSD systems, test -w directory always returned false * because test tried to open the directory for writing, which always * fails. * * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX * System III, and thus presumably also for BSD up to and including 4.3. * * Secondly I remembered why using open() and/or access() are bogus. They * don't work right for detecting read and write permissions bits when called * by root. * * Interestingly the 'test' in 4.4BSD was closer to correct (as per * 1003.2-1992) and it was implemented efficiently with stat() instead of * open(). * * This was apparently broken in NetBSD around about 1994/06/30 when the old * 4.4BSD implementation was replaced with a (arguably much better coded) * implementation derived from pdksh. * * Note that modern pdksh is yet different again, but still not correct, at * least not w.r.t. 1003.2-1992. * * As I think more about it and read more of the related IEEE docs I don't like * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all. I very * much prefer the original wording in 1003.2-1992. It is much more useful, * and so that's what I've implemented. * * (Note that a strictly conforming implementation of 1003.1-2001 is in fact * totally useless for the case in question since its 'test -w' and 'test -r' * can never fail for root for any existing files, i.e. files for which 'test * -e' succeeds.) * * The rationale for 1003.1-2001 suggests that the wording was "clarified" in * 1003.1-2001 to align with the 1003.2b draft. 1003.2b Draft 12 (July 1999), * which is the latest copy I have, does carry the same suggested wording as is * in 1003.1-2001, with its rationale saying: * * This change is a clarification and is the result of interpretation * request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992. * * That interpretation can be found here: * * http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html * * Not terribly helpful, unfortunately. I wonder who that fence sitter was. * * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the * PASC interpretation and appear to be gone against at least one widely used * implementation (namely 4.4BSD). The problem is that for file access by root * this means that if test '-r' and '-w' are to behave as if open() were called * then there's no way for a shell script running as root to check if a file * has certain access bits set other than by the grotty means of interpreting * the output of 'ls -l'. This was widely considered to be a bug in V7's * "test" and is, I believe, one of the reasons why direct use of access() was * avoided in some more recent implementations! * * I have always interpreted '-r' to match '-w' and '-x' as per the original * wording in 1003.2-1992, not the other way around. I think 1003.2b goes much * too far the wrong way without any valid rationale and that it's best if we * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of * open() since we already know very well how it will work -- existance of the * file is all that matters to open() for root. * * Unfortunately the SVID is no help at all (which is, I guess, partly why * we're in this mess in the first place :-). * * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use * access(name, 2) even though it also goes to much greater lengths for '-x' * matching the 1003.2-1992 definition (which is no doubt where that definition * came from). * * The ksh93 implementation uses access() for '-r' and '-w' if * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root. * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b). */ static int test_access(struct stat *sp, mode_t stmode) { #ifdef _MSC_VER /* just pretend to be root for now. */ stmode = (stmode << 6) | (stmode << 3) | stmode; return !!(sp->st_mode & stmode); #else gid_t *groups; register int n; uid_t euid; int maxgroups; /* * I suppose we could use access() if not running as root and if we are * running with ((euid == uid) && (egid == gid)), but we've already * done the stat() so we might as well just test the permissions * directly instead of asking the kernel to do it.... */ euid = geteuid(); if (euid == 0) /* any bit is good enough */ stmode = (stmode << 6) | (stmode << 3) | stmode; else if (sp->st_uid == euid) stmode <<= 6; else if (sp->st_gid == getegid()) stmode <<= 3; else { /* XXX stolen almost verbatim from ksh93.... */ /* on some systems you can be in several groups */ if ((maxgroups = getgroups(0, NULL)) <= 0) maxgroups = NGROUPS_MAX; /* pre-POSIX system? */ groups = xmalloc((maxgroups + 1) * sizeof(gid_t)); n = getgroups(maxgroups, groups); while (--n >= 0) { if (groups[n] == sp->st_gid) { stmode <<= 3; break; } } free(groups); } return !!(sp->st_mode & stmode); #endif } static int filstat(char *nm, enum token mode) { struct stat s; if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) return 0; switch (mode) { case FILRD: return test_access(&s, S_IROTH); case FILWR: return test_access(&s, S_IWOTH); case FILEX: return test_access(&s, S_IXOTH); case FILEXIST: return 1; /* the successful lstat()/stat() is good enough */ case FILREG: return S_ISREG(s.st_mode); case FILDIR: return S_ISDIR(s.st_mode); case FILCDEV: #ifdef S_ISCHR return S_ISCHR(s.st_mode); #else return 0; #endif case FILBDEV: #ifdef S_ISBLK return S_ISBLK(s.st_mode); #else return 0; #endif case FILFIFO: #ifdef S_ISFIFO return S_ISFIFO(s.st_mode); #else return 0; #endif case FILSOCK: #ifdef S_ISSOCK return S_ISSOCK(s.st_mode); #else return 0; #endif case FILSYM: #ifdef S_ISLNK return S_ISLNK(s.st_mode); #else return 0; #endif case FILSUID: return (s.st_mode & S_ISUID) != 0; case FILSGID: return (s.st_mode & S_ISGID) != 0; case FILSTCK: #ifdef S_ISVTX return (s.st_mode & S_ISVTX) != 0; #else return 0; #endif case FILGZ: return s.st_size > (off_t)0; case FILUID: return s.st_uid == geteuid(); case FILGID: return s.st_gid == getegid(); default: return 1; } } #define VTOC(x) (const unsigned char *)((const struct t_op *)x)->op_text static int compare1(const void *va, const void *vb) { const unsigned char *a = va; const unsigned char *b = VTOC(vb); return a[0] - b[0]; } static int compare2(const void *va, const void *vb) { const unsigned char *a = va; const unsigned char *b = VTOC(vb); int z = a[0] - b[0]; return z ? z : (a[1] - b[1]); } static struct t_op const * findop(const char *s) { if (s[0] == '-') { if (s[1] == '\0') return NULL; if (s[2] == '\0') return bsearch(s + 1, mop2, __arraycount(mop2), sizeof(*mop2), compare1); else if (s[3] != '\0') return NULL; else return bsearch(s + 1, mop3, __arraycount(mop3), sizeof(*mop3), compare2); } else { if (s[1] == '\0') return bsearch(s, cop, __arraycount(cop), sizeof(*cop), compare1); else if (strcmp(s, cop2[0].op_text) == 0) return cop2; else return NULL; } } static enum token t_lex(char *s) { struct t_op const *op; if (s == NULL) { t_wp_op = NULL; return EOI; } if ((op = findop(s)) != NULL) { if (!((op->op_type == UNOP && isoperand()) || (op->op_num == LPAREN && *(t_wp+1) == 0))) { t_wp_op = op; return op->op_num; } } t_wp_op = NULL; return OPERAND; } static int isoperand(void) { struct t_op const *op; char *s, *t; if ((s = *(t_wp+1)) == 0) return 1; if ((t = *(t_wp+2)) == 0) return 0; if ((op = findop(s)) != NULL) return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); return 0; } /* atoi with error detection */ static int getn(const char *s) { char *p; long r; errno = 0; r = strtol(s, &p, 10); if (errno != 0) return errx(-42, "%s: out of range", s); while (isspace((unsigned char)*p)) p++; if (*p) return errx(-42, "%s: bad number", s); return (int) r; } static int newerf(const char *f1, const char *f2) { struct stat b1, b2; return (stat(f1, &b1) == 0 && stat(f2, &b2) == 0 && b1.st_mtime > b2.st_mtime); } static int olderf(const char *f1, const char *f2) { struct stat b1, b2; return (stat(f1, &b1) == 0 && stat(f2, &b2) == 0 && b1.st_mtime < b2.st_mtime); } static int equalf(const char *f1, const char *f2) { struct stat b1, b2; return (stat(f1, &b1) == 0 && stat(f2, &b2) == 0 && b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino); } static int usage(const char *argv0) { fprintf(stdout, "usage: %s expression [-- [args]]\n", argv0); return 0; /* only used in --help. */ } kbuild-2695/src/kmk/kmkbuiltin/kDepIDB.c0000644000000000000000000006164312247157307016543 0ustar rootroot/* $Id: kDepIDB.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * kDepIDB - Extract dependency information from a MS Visual C++ .idb file. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #if !defined(_MSC_VER) # include #else # include #endif #include "../../lib/k/kDefs.h" #include "../../lib/k/kTypes.h" #include "../../lib/kDep.h" #include "kmkbuiltin.h" /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /*#define DEBUG*/ #ifdef DEBUG # define dprintf(a) printf a # define dump(pb, cb, offBase) depHexDump(pb,cb,offBase) #else # define dprintf(a) do {} while (0) # define dump(pb, cb, offBase) do {} while (0) #endif /******************************************************************************* * Global Variables * *******************************************************************************/ /** the executable name. */ static const char *argv0 = ""; /** * Scans a stream (chunk of data really) for dependencies. * * @returns 0 on success. * @returns !0 on failure. * @param pbStream The stream bits. * @param cbStream The size of the stream. * @param pszPrefix The dependency prefix. * @param cchPrefix The size of the prefix. */ static int ScanStream(KU8 *pbStream, size_t cbStream, const char *pszPrefix, size_t cchPrefix) { const KU8 *pbCur = pbStream; size_t cbLeft = cbStream; register char chFirst = *pszPrefix; while (cbLeft > cchPrefix + 2) { if ( *pbCur != chFirst || memcmp(pbCur, pszPrefix, cchPrefix)) { pbCur++; cbLeft--; } else { size_t cchDep; pbCur += cchPrefix; cchDep = strlen((const char *)pbCur); depAdd((const char *)pbCur, cchDep); dprintf(("%05x: '%s'\n", pbCur - pbStream, pbCur)); pbCur += cchDep; cbLeft -= cchDep + cchPrefix; } } return 0; } /*///////////////////////////////////////////////////////////////////////////// // // // P D B 7 . 0 // // /////////////////////////////////////////////////////////////////////////////*/ /** A PDB 7.0 Page number. */ typedef KU32 PDB70PAGE; /** Pointer to a PDB 7.0 Page number. */ typedef PDB70PAGE *PPDB70PAGE; /** * A PDB 7.0 stream. */ typedef struct PDB70STREAM { /** The size of the stream. */ KU32 cbStream; } PDB70STREAM, *PPDB70STREAM; /** The PDB 7.00 signature. */ #define PDB_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\x1A" "DS\0\0" /** * The PDB 7.0 header. */ typedef struct PDB70HDR { /** The signature string. */ KU8 szSignature[sizeof(PDB_SIGNATURE_700)]; /** The page size. */ KU32 cbPage; /** The start page. */ PDB70PAGE iStartPage; /** The number of pages in the file. */ PDB70PAGE cPages; /** The root stream directory. */ KU32 cbRoot; /** Unknown function, always 0. */ KU32 u32Reserved; /** The page index of the root page table. */ PDB70PAGE iRootPages; } PDB70HDR, *PPDB70HDR; /** * The PDB 7.0 root directory. */ typedef struct PDB70ROOT { /** The number of streams */ KU32 cStreams; /** Array of streams. */ PDB70STREAM aStreams[1]; /* KU32 aiPages[] */ } PDB70ROOT, *PPDB70ROOT; /** * The PDB 7.0 name stream (#1) header. */ typedef struct PDB70NAMES { /** The structure version. */ KU32 Version; /** Timestamp. */ KU32 TimeStamp; /** Unknown. */ KU32 Unknown1; /** GUID. */ KU32 u32Guid[4]; /** The size of the following name table. */ KU32 cbNames; /** The name table. */ char szzNames[1]; } PDB70NAMES, *PPDB70NAMES; /** The version / magic of the names structure. */ #define PDB70NAMES_VERSION 20000404 static int Pdb70ValidateHeader(PPDB70HDR pHdr, size_t cbFile) { if (pHdr->cbPage * pHdr->cPages != cbFile) { fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0); return 1; } if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0) { fprintf(stderr, "%s: error: Bad PDB 2.0 header - iStartPage=%u cPages=%u.\n", argv0, pHdr->iStartPage, pHdr->cPages); return 1; } if (pHdr->iRootPages >= pHdr->cPages && pHdr->iRootPages <= 0) { fprintf(stderr, "%s: error: Bad PDB 2.0 header - iRootPages=%u cPage=%u.\n", argv0, pHdr->iStartPage, pHdr->cPages); return 1; } return 0; } #ifdef DEBUG static size_t Pdb70Align(PPDB70HDR pHdr, size_t cb) { if (cb == ~(KU32)0 || !cb) return 0; return ((cb + pHdr->cbPage - 1) / pHdr->cbPage) * pHdr->cbPage; } #endif /* DEBUG */ static size_t Pdb70Pages(PPDB70HDR pHdr, size_t cb) { if (cb == ~(KU32)0 || !cb) return 0; return (cb + pHdr->cbPage - 1) / pHdr->cbPage; } static void *Pdb70AllocAndRead(PPDB70HDR pHdr, size_t cb, PPDB70PAGE paiPageMap) { const size_t cbPage = pHdr->cbPage; size_t cPages = Pdb70Pages(pHdr, cb); KU8 *pbBuf = malloc(cPages * cbPage + 1); if (pbBuf) { size_t iPage = 0; while (iPage < cPages) { size_t off = paiPageMap[iPage]; if (off < pHdr->cPages) { off *= cbPage; memcpy(pbBuf + iPage * cbPage, (KU8 *)pHdr + off, cbPage); dump(pbBuf + iPage * cbPage, iPage + 1 < cPages ? cbPage : cb % cbPage, off); } else { fprintf(stderr, "%s: warning: Invalid page index %u (max %u)!\n", argv0, (unsigned)off, pHdr->cPages); memset(pbBuf + iPage * cbPage, 0, cbPage); } iPage++; } pbBuf[cPages * cbPage] = '\0'; } else fprintf(stderr, "%s: error: failed to allocate %lu bytes\n", argv0, (unsigned long)(cPages * cbPage + 1)); return pbBuf; } static PPDB70ROOT Pdb70AllocAndReadRoot(PPDB70HDR pHdr) { /* * The tricky bit here is to find the right length. Really? * (Todo: Check if we can just use the stream #0 size..) */ PPDB70PAGE piPageMap = (KU32 *)((KU8 *)pHdr + pHdr->iRootPages * pHdr->cbPage); PPDB70ROOT pRoot = Pdb70AllocAndRead(pHdr, pHdr->cbRoot, piPageMap); if (pRoot) { #if 1 /* This stuff is probably unnecessary: */ /* size = stream header + array of stream. */ size_t cb = K_OFFSETOF(PDB70ROOT, aStreams[pRoot->cStreams]); free(pRoot); pRoot = Pdb70AllocAndRead(pHdr, cb, piPageMap); if (pRoot) { /* size += page tables. */ unsigned iStream = pRoot->cStreams; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) cb += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB70PAGE); free(pRoot); pRoot = Pdb70AllocAndRead(pHdr, cb, piPageMap); if (pRoot) { /* validate? */ return pRoot; } } #else /* validate? */ return pRoot; #endif } return NULL; } static void *Pdb70AllocAndReadStream(PPDB70HDR pHdr, PPDB70ROOT pRoot, unsigned iStream, size_t *pcbStream) { const size_t cbStream = pRoot->aStreams[iStream].cbStream; PPDB70PAGE paiPageMap; if ( iStream >= pRoot->cStreams || cbStream == ~(KU32)0) { fprintf(stderr, "%s: error: Invalid stream %d\n", argv0, iStream); return NULL; } paiPageMap = (PPDB70PAGE)&pRoot->aStreams[pRoot->cStreams]; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) paiPageMap += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream); if (pcbStream) *pcbStream = cbStream; return Pdb70AllocAndRead(pHdr, cbStream, paiPageMap); } static int Pdb70Process(KU8 *pbFile, size_t cbFile) { PPDB70HDR pHdr = (PPDB70HDR)pbFile; PPDB70ROOT pRoot; PPDB70NAMES pNames; size_t cbStream = 0; unsigned fDone = 0; unsigned iStream; int rc = 0; dprintf(("pdb70\n")); /* * Validate the header and read the root stream. */ if (Pdb70ValidateHeader(pHdr, cbFile)) return 1; pRoot = Pdb70AllocAndReadRoot(pHdr); if (!pRoot) return 1; /* * The names we want are usually all found in the 'Names' stream, that is #1. */ dprintf(("Reading the names stream....\n")); pNames = Pdb70AllocAndReadStream(pHdr, pRoot, 1, &cbStream); if (pNames) { dprintf(("Names: Version=%u cbNames=%u (%#x)\n", pNames->Version, pNames->cbNames, pNames->cbNames)); if ( pNames->Version == PDB70NAMES_VERSION && pNames->cbNames > 32 && pNames->cbNames + K_OFFSETOF(PDB70NAMES, szzNames) <= pRoot->aStreams[1].cbStream) { /* * Iterate the names and add the /mr/inversedeps/ ones to the dependency list. */ const char *psz = &pNames->szzNames[0]; size_t cb = pNames->cbNames; size_t off = 0; dprintf(("0x0000 #0: %6d bytes [root / toc]\n", pRoot->aStreams[0].cbStream)); for (iStream = 1; cb > 0; iStream++) { int fAdded = 0; size_t cch = strlen(psz); if ( cch >= sizeof("/mr/inversedeps/") && !memcmp(psz, "/mr/inversedeps/", sizeof("/mr/inversedeps/") - 1)) { depAdd(psz + sizeof("/mr/inversedeps/") - 1, cch - (sizeof("/mr/inversedeps/") - 1)); fAdded = 1; } dprintf(("%#06x #%d: %6d bytes %s%s\n", off, iStream, iStream < pRoot->cStreams ? pRoot->aStreams[iStream].cbStream : -1, psz, fAdded ? " [dep]" : "")); (void)fAdded; /* next */ if (cch >= cb) { dprintf(("warning! cch=%d cb=%d\n", cch, cb)); cch = cb - 1; } cb -= cch + 1; psz += cch + 1; off += cch + 1; } rc = 0; fDone = 1; } else dprintf(("Unknown version or bad size: Version=%u cbNames=%d cbStream=%d\n", pNames->Version, pNames->cbNames, cbStream)); free(pNames); } if (!fDone) { /* * Iterate the streams in the root and scan their content for * dependencies. */ rc = 0; for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++) { KU8 *pbStream; if ( pRoot->aStreams[iStream].cbStream == ~(KU32)0 || !pRoot->aStreams[iStream].cbStream) continue; dprintf(("Stream #%d: %#x bytes (%#x aligned)\n", iStream, pRoot->aStreams[iStream].cbStream, Pdb70Align(pHdr, pRoot->aStreams[iStream].cbStream))); pbStream = (KU8 *)Pdb70AllocAndReadStream(pHdr, pRoot, iStream, &cbStream); if (pbStream) { rc = ScanStream(pbStream, cbStream, "/mr/inversedeps/", sizeof("/mr/inversedeps/") - 1); free(pbStream); } else rc = 1; } } free(pRoot); return rc; } /*///////////////////////////////////////////////////////////////////////////// // // // P D B 2 . 0 // // /////////////////////////////////////////////////////////////////////////////*/ /** A PDB 2.0 Page number. */ typedef KU16 PDB20PAGE; /** Pointer to a PDB 2.0 Page number. */ typedef PDB20PAGE *PPDB20PAGE; /** * A PDB 2.0 stream. */ typedef struct PDB20STREAM { /** The size of the stream. */ KU32 cbStream; /** Some unknown value. */ KU32 u32Unknown; } PDB20STREAM, *PPDB20STREAM; /** The PDB 2.00 signature. */ #define PDB_SIGNATURE_200 "Microsoft C/C++ program database 2.00\r\n\x1A" "JG\0" /** * The PDB 2.0 header. */ typedef struct PDB20HDR { /** The signature string. */ KU8 szSignature[sizeof(PDB_SIGNATURE_200)]; /** The page size. */ KU32 cbPage; /** The start page - whatever that is... */ PDB20PAGE iStartPage; /** The number of pages in the file. */ PDB20PAGE cPages; /** The root stream directory. */ PDB20STREAM RootStream; /** The root page table. */ PDB20PAGE aiRootPageMap[1]; } PDB20HDR, *PPDB20HDR; /** * The PDB 2.0 root directory. */ typedef struct PDB20ROOT { /** The number of streams */ KU16 cStreams; /** Reserved or high part of cStreams. */ KU16 u16Reserved; /** Array of streams. */ PDB20STREAM aStreams[1]; } PDB20ROOT, *PPDB20ROOT; static int Pdb20ValidateHeader(PPDB20HDR pHdr, size_t cbFile) { if (pHdr->cbPage * pHdr->cPages != cbFile) { fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0); return 1; } if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0) { fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0); return 1; } return 0; } static size_t Pdb20Pages(PPDB20HDR pHdr, size_t cb) { if (cb == ~(KU32)0 || !cb) return 0; return (cb + pHdr->cbPage - 1) / pHdr->cbPage; } static void *Pdb20AllocAndRead(PPDB20HDR pHdr, size_t cb, PPDB20PAGE paiPageMap) { size_t cPages = Pdb20Pages(pHdr, cb); KU8 *pbBuf = malloc(cPages * pHdr->cbPage + 1); if (pbBuf) { size_t iPage = 0; while (iPage < cPages) { size_t off = paiPageMap[iPage]; off *= pHdr->cbPage; memcpy(pbBuf + iPage * pHdr->cbPage, (KU8 *)pHdr + off, pHdr->cbPage); iPage++; } pbBuf[cPages * pHdr->cbPage] = '\0'; } else fprintf(stderr, "%s: error: failed to allocate %lu bytes\n", argv0, (unsigned long)(cPages * pHdr->cbPage + 1)); return pbBuf; } static PPDB20ROOT Pdb20AllocAndReadRoot(PPDB20HDR pHdr) { /* * The tricky bit here is to find the right length. * (Todo: Check if we can just use the stream size..) */ PPDB20ROOT pRoot = Pdb20AllocAndRead(pHdr, sizeof(*pRoot), &pHdr->aiRootPageMap[0]); if (pRoot) { /* size = stream header + array of stream. */ size_t cb = K_OFFSETOF(PDB20ROOT, aStreams[pRoot->cStreams]); free(pRoot); pRoot = Pdb20AllocAndRead(pHdr, cb, &pHdr->aiRootPageMap[0]); if (pRoot) { /* size += page tables. */ unsigned iStream = pRoot->cStreams; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) cb += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB20PAGE); free(pRoot); pRoot = Pdb20AllocAndRead(pHdr, cb, &pHdr->aiRootPageMap[0]); if (pRoot) { /* validate? */ return pRoot; } } } return NULL; } static void *Pdb20AllocAndReadStream(PPDB20HDR pHdr, PPDB20ROOT pRoot, unsigned iStream, size_t *pcbStream) { size_t cbStream = pRoot->aStreams[iStream].cbStream; PPDB20PAGE paiPageMap; if ( iStream >= pRoot->cStreams || cbStream == ~(KU32)0) { fprintf(stderr, "%s: error: Invalid stream %d\n", argv0, iStream); return NULL; } paiPageMap = (PPDB20PAGE)&pRoot->aStreams[pRoot->cStreams]; while (iStream-- > 0) if (pRoot->aStreams[iStream].cbStream != ~(KU32)0) paiPageMap += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream); if (pcbStream) *pcbStream = cbStream; return Pdb20AllocAndRead(pHdr, cbStream, paiPageMap); } static int Pdb20Process(KU8 *pbFile, size_t cbFile) { PPDB20HDR pHdr = (PPDB20HDR)pbFile; PPDB20ROOT pRoot; unsigned iStream; int rc = 0; /* * Validate the header and read the root stream. */ if (Pdb20ValidateHeader(pHdr, cbFile)) return 1; pRoot = Pdb20AllocAndReadRoot(pHdr); if (!pRoot) return 1; /* * Iterate the streams in the root and scan their content for * dependencies. */ rc = 0; for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++) { KU8 *pbStream; if (pRoot->aStreams[iStream].cbStream == ~(KU32)0) continue; pbStream = (KU8 *)Pdb20AllocAndReadStream(pHdr, pRoot, iStream, NULL); if (pbStream) { rc = ScanStream(pbStream, pRoot->aStreams[iStream].cbStream, "/ipm/header/", sizeof("/ipm/header/") - 1); free(pbStream); } else rc = 1; } free(pRoot); return rc; } /** * Make an attempt at parsing a Visual C++ IDB file. */ static int ProcessIDB(FILE *pInput) { size_t cbFile; KU8 *pbFile; void *pvOpaque; int rc = 0; /* * Read the file into memory. */ pbFile = (KU8 *)depReadFileIntoMemory(pInput, &cbFile, &pvOpaque); if (!pbFile) return 1; /* * Figure out which parser to use. */ if (!memcmp(pbFile, PDB_SIGNATURE_700, sizeof(PDB_SIGNATURE_700))) rc = Pdb70Process(pbFile, cbFile); else if (!memcmp(pbFile, PDB_SIGNATURE_200, sizeof(PDB_SIGNATURE_200))) rc = Pdb20Process(pbFile, cbFile); else { fprintf(stderr, "%s: error: Doesn't recognize the header of the Visual C++ IDB file.\n", argv0); rc = 1; } depFreeFileMemory(pbFile, pvOpaque); return rc; } static void usage(const char *a_argv0) { printf("usage: %s -o -t [-fqs] \n" " or: %s --help\n" " or: %s --version\n", a_argv0, a_argv0, a_argv0); } int kmk_builtin_kDepIDB(int argc, char *argv[], char **envp) { int i; /* Arguments. */ FILE *pOutput = NULL; const char *pszOutput = NULL; FILE *pInput = NULL; const char *pszTarget = NULL; int fStubs = 0; int fFixCase = 0; /* Argument parsing. */ int fInput = 0; /* set when we've found input argument. */ int fQuiet = 0; argv0 = argv[0]; /* * Parse arguments. */ if (argc <= 1) { usage(argv[0]); return 1; } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { const char *psz = &argv[i][1]; if (*psz == '-') { if (!strcmp(psz, "-quiet")) psz = "q"; else if (!strcmp(psz, "-help")) psz = "?"; else if (!strcmp(psz, "-version")) psz = "V"; } switch (*psz) { /* * Output file. */ case 'o': { pszOutput = &argv[i][2]; if (pOutput) { fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]); return 1; } if (!*pszOutput) { if (++i >= argc) { fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", argv[0]); return 1; } pszOutput = argv[i]; } if (pszOutput[0] == '-' && !pszOutput[1]) pOutput = stdout; else pOutput = fopen(pszOutput, "w"); if (!pOutput) { fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput); return 1; } break; } /* * Target name. */ case 't': { if (pszTarget) { fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]); return 1; } pszTarget = &argv[i][2]; if (!*pszTarget) { if (++i >= argc) { fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", argv[0]); return 1; } pszTarget = argv[i]; } break; } /* * Fix case. */ case 'f': { fFixCase = 1; break; } /* * Quiet. */ case 'q': { fQuiet = 1; break; } /* * Generate stubs. */ case 's': { fStubs = 1; break; } /* * The mandatory version & help. */ case '?': usage(argv[0]); return 0; case 'V': case 'v': return kbuild_version(argv[0]); /* * Invalid argument. */ default: fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]); usage(argv[0]); return 1; } } else { pInput = fopen(argv[i], "rb"); if (!pInput) { fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]); return 1; } fInput = 1; } /* * End of the line? */ if (fInput) { if (++i < argc) { fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]); return 1; } break; } } /* * Got all we require? */ if (!pInput) { fprintf(stderr, "%s: syntax error: No input!\n", argv[0]); return 1; } if (!pOutput) { fprintf(stderr, "%s: syntax error: No output!\n", argv[0]); return 1; } if (!pszTarget) { fprintf(stderr, "%s: syntax error: No target!\n", argv[0]); return 1; } /* * Do the parsing. */ i = ProcessIDB(pInput); fclose(pInput); /* * Write the dependecy file. */ if (!i) { depOptimize(fFixCase, fQuiet); fprintf(pOutput, "%s:", pszTarget); depPrint(pOutput); if (fStubs) depPrintStubs(pOutput); } /* * Close the output, delete output on failure. */ if (!i && ferror(pOutput)) { i = 1; fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput); } fclose(pOutput); if (i) { if (unlink(pszOutput)) fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput); } depCleanup(); return i; } kbuild-2695/src/kmk/kmkbuiltin/redirect.c0000644000000000000000000005225212247157307017136 0ustar rootroot/* $Id: redirect.c 2684 2013-06-19 11:01:48Z bird $ */ /** @file * kmk_redirect - Do simple program <-> file redirection (++). */ /* * Copyright (c) 2007-2012 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #if defined(_MSC_VER) # include # include # include #else # include #endif #ifdef __OS2__ # define INCL_BASE # include # ifndef LIBPATHSTRICT # define LIBPATHSTRICT 3 # endif #endif #if defined(_MSC_VER) /** * Replaces arguments in need of quoting. * * This will "leak" the original and/or the replacement string, depending on * how you look at it. * * For details on how MSC parses the command line, see "Parsing C Command-Line * Arguments": http://msdn.microsoft.com/en-us/library/a1y7w461.aspx * * @param argc The argument count. * @param argv The argument vector. */ static void quoteArguments(int argc, char **argv) { int i; for (i = 0; i < argc; i++) { const char *pszOrg = argv[i]; size_t cchOrg = strlen(pszOrg); const char *pszQuotes = (const char *)memchr(pszOrg, '"', cchOrg); if ( pszQuotes || cchOrg == 0 || memchr(pszOrg, '&', cchOrg) || memchr(pszOrg, '>', cchOrg) || memchr(pszOrg, '<', cchOrg) || memchr(pszOrg, '|', cchOrg) || memchr(pszOrg, '%', cchOrg) ) { char ch; int fComplicated = pszQuotes || (cchOrg > 0 && pszOrg[cchOrg - 1] == '\\'); size_t cchNew = fComplicated ? cchOrg * 2 + 2 : cchOrg + 2; char *pszNew = (char *)malloc(cchNew + 1); argv[i] = pszNew; *pszNew++ = '"'; if (fComplicated) { while ((ch = *pszOrg++) != '\0') { if (ch == '"') { *pszNew++ = '\\'; *pszNew++ = '"'; } else if (ch == '\\') { /* Backslashes are a bit complicated, they depends on whether a quotation mark follows them or not. They only require escaping if one does. */ unsigned cSlashes = 1; while ((ch = *pszOrg) == '\\') { pszOrg++; cSlashes++; } if (ch == '"' || ch == '\0') /* We put a " at the EOS. */ { while (cSlashes-- > 0) { *pszNew++ = '\\'; *pszNew++ = '\\'; } } else while (cSlashes-- > 0) *pszNew++ = '\\'; } else *pszNew++ = ch; } } else { memcpy(pszNew, pszOrg, cchOrg); pszNew += cchOrg; } *pszNew++ = '"'; *pszNew = '\0'; } } /*for (i = 0; i < argc; i++) printf("argv[%u]=%s;;\n", i, argv[i]); */ } #endif /* _MSC_VER */ #ifdef _MSC_VER /** Used by safeCloseFd. */ static void __cdecl ignore_invalid_parameter(const wchar_t *a, const wchar_t *b, const wchar_t *c, unsigned d, uintptr_t e) { } #endif /** * Safely works around MS CRT's pedantic close() function. * * @param fd The file handle. */ static void safeCloseFd(int fd) { #ifdef _MSC_VER _invalid_parameter_handler pfnOld = _get_invalid_parameter_handler(); _set_invalid_parameter_handler(ignore_invalid_parameter); close(fd); _set_invalid_parameter_handler(pfnOld); #else close(fd); #endif } static const char *name(const char *pszName) { const char *psz = strrchr(pszName, '/'); #if defined(_MSC_VER) || defined(__OS2__) const char *psz2 = strrchr(pszName, '\\'); if (!psz2) psz2 = strrchr(pszName, ':'); if (psz2 && (!psz || psz2 > psz)) psz = psz2; #endif return psz ? psz + 1 : pszName; } static int usage(FILE *pOut, const char *argv0) { fprintf(pOut, "usage: %s [-[rwa+tb] ] [-c] [-Z] [-E ] [-C ] -- [args]\n" " or: %s --help\n" " or: %s --version\n" "\n" "The rwa+tb is like for fopen, if not specified it defaults to w+.\n" "The is either a number or an alias for the standard handles:\n" " i = stdin\n" " o = stdout\n" " e = stderr\n" "\n" "The -c switch will close the specified file descriptor.\n" "\n" "The -Z switch zaps the environment.\n" "\n" "The -E switch is for making changes to the environment in a putenv\n" "fashion.\n" "\n" "The -C switch is for changing the current directory. This takes immediate\n" "effect, so be careful where you put it.\n" "\n" "This command was originally just a quick hack to avoid invoking the shell\n" "on Windows (cygwin) where forking is very expensive and has exhibited\n" "stability issues on SMP machines. It has since grown into something like\n" "/usr/bin/env on steroids.\n" , argv0, argv0, argv0); return 1; } int main(int argc, char **argv, char **envp) { int i; #if defined(_MSC_VER) intptr_t rc; #endif FILE *pStdErr = stderr; FILE *pStdOut = stdout; /* * Parse arguments. */ if (argc <= 1) return usage(pStdErr, name(argv[0])); for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { int fd; int fdOpened; int fOpen; char *psz = &argv[i][1]; if (*psz == '-') { /* '--' ? */ if (!psz[1]) { i++; break; } /* convert to short. */ if (!strcmp(psz, "-help")) psz = "h"; else if (!strcmp(psz, "-version")) psz = "V"; else if (!strcmp(psz, "-env")) psz = "E"; else if (!strcmp(psz, "-chdir")) psz = "C"; else if (!strcmp(psz, "-zap-env")) psz = "Z"; else if (!strcmp(psz, "-close")) psz = "c"; } /* * Deal with the obligatory help and version switches first. */ if (*psz == 'h') { usage(pStdOut, name(argv[0])); return 0; } if (*psz == 'V') { printf("kmk_redirect - kBuild version %d.%d.%d (r%u)\n" "Copyright (C) 2007-2012 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; } /* * Environment switch? */ if (*psz == 'E') { psz++; if (*psz == ':' || *psz == '=') psz++; else { if (i + 1 >= argc) { fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]); return 1; } psz = argv[++i]; } #ifdef __OS2__ if ( !strncmp(psz, "BEGINLIBPATH=", sizeof("BEGINLIBPATH=") - 1) || !strncmp(psz, "ENDLIBPATH=", sizeof("ENDLIBPATH=") - 1) || !strncmp(psz, "LIBPATHSTRICT=", sizeof("LIBPATHSTRICT=") - 1)) { ULONG ulVar = *psz == 'B' ? BEGIN_LIBPATH : *psz == 'E' ? END_LIBPATH : LIBPATHSTRICT; const char *pszVal = strchr(psz, '=') + 1; APIRET rc = DosSetExtLIBPATH(pszVal, ulVar); if (rc) { fprintf(pStdErr, "%s: error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu\n", name(argv[0]), pszVal, pszVal - psz - 1, psz, ulVar, rc); return 1; } } else #endif /* __OS2__ */ if (putenv(psz)) { fprintf(pStdErr, "%s: error: putenv(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno)); return 1; } continue; } /* * Change directory switch? */ if (*psz == 'C') { psz++; if (*psz == ':' || *psz == '=') psz++; else { if (i + 1 >= argc) { fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]); return 1; } psz = argv[++i]; } if (!chdir(psz)) continue; #ifdef _MSC_VER { /* drop trailing slash if any. */ size_t cch = strlen(psz); if ( cch > 2 && (psz[cch - 1] == '/' || psz[cch - 1] == '\\') && psz[cch - 1] != ':') { int rc2; char *pszCopy = strdup(psz); do pszCopy[--cch] = '\0'; while ( cch > 2 && (pszCopy[cch - 1] == '/' || pszCopy[cch - 1] == '\\') && pszCopy[cch - 1] != ':'); rc2 = chdir(pszCopy); free(pszCopy); if (!rc2) continue; } } #endif fprintf(pStdErr, "%s: error: chdir(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno)); return 1; } /* * Zap environment switch? * This is a bit of a hack. */ if (*psz == 'Z') { unsigned j = 0; while (envp[j] != NULL) j++; while (j-- > 0) { char *pszEqual = strchr(envp[j], '='); char *pszCopy; if (pszEqual) *pszEqual = '\0'; pszCopy = strdup(envp[j]); if (pszEqual) *pszEqual = '='; #if defined(_MSC_VER) || defined(__OS2__) putenv(pszCopy); #else unsetenv(pszCopy); #endif free(pszCopy); } continue; } /* * Close the specified file descriptor (no stderr/out/in aliases). */ if (*psz == 'c') { psz++; if (!*psz) { i++; if (i >= argc) { fprintf(pStdErr, "%s: syntax error: missing filename argument.\n", name(argv[0])); return 1; } psz = argv[i]; } fd = (int)strtol(psz, &psz, 0); if (!fd || *psz) { fprintf(pStdErr, "%s: error: failed to convert '%s' to a number\n", name(argv[0]), argv[i]); return 1; } if (fd < 0) { fprintf(pStdErr, "%s: error: negative fd %d (%s)\n", name(argv[0]), fd, argv[i]); return 1; } /** @todo deal with stderr */ safeCloseFd(fd); continue; } /* * Parse a file descriptor argument. */ /* mode */ switch (*psz) { case 'r': psz++; if (*psz == '+') { fOpen = O_RDWR; psz++; } else fOpen = O_RDONLY; break; case 'w': psz++; if (*psz == '+') { psz++; fOpen = O_RDWR | O_CREAT | O_TRUNC; } else fOpen = O_WRONLY | O_CREAT | O_TRUNC; break; case 'a': psz++; if (*psz == '+') { psz++; fOpen = O_RDWR | O_CREAT | O_APPEND; } else fOpen = O_WRONLY | O_CREAT | O_APPEND; break; case 'i': /* make sure stdin is read-only. */ fOpen = O_RDONLY; break; case '+': fprintf(pStdErr, "%s: syntax error: Unexpected '+' in '%s'\n", name(argv[0]), argv[i]); return 1; default: fOpen = O_RDWR | O_CREAT | O_TRUNC; break; } /* binary / text modifiers */ switch (*psz) { case 'b': #ifdef O_BINARY fOpen |= O_BINARY; #endif psz++; break; case 't': #ifdef O_TEXT fOpen |= O_TEXT; #endif psz++; break; default: #ifdef O_BINARY fOpen |= O_BINARY; #endif break; } /* convert to file descriptor number */ switch (*psz) { case 'i': fd = 0; psz++; break; case 'o': fd = 1; psz++; break; case 'e': fd = 2; psz++; break; case '0': if (!psz[1]) { fd = 0; psz++; break; } case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': fd = (int)strtol(psz, &psz, 0); if (!fd) { fprintf(pStdErr, "%s: error: failed to convert '%s' to a number\n", name(argv[0]), argv[i]); return 1; } if (fd < 0) { fprintf(pStdErr, "%s: error: negative fd %d (%s)\n", name(argv[0]), fd, argv[i]); return 1; } break; /* * Invalid argument. */ default: fprintf(pStdErr, "%s: error: failed to convert '%s' ('%s') to a file descriptor\n", name(argv[0]), psz, argv[i]); return 1; } /* * Check for the filename. */ if (*psz) { if (*psz != ':' && *psz != '=') { fprintf(pStdErr, "%s: syntax error: characters following the file descriptor: '%s' ('%s')\n", name(argv[0]), psz, argv[i]); return 1; } psz++; } else { i++; if (i >= argc) { fprintf(pStdErr, "%s: syntax error: missing filename argument.\n", name(argv[0])); return 1; } psz = argv[i]; } /* * Setup the redirection. */ if (fd == fileno(pStdErr)) { /* * Move stderr to a new location, making it close on exec. * If pStdOut has already teamed up with pStdErr, update it too. */ FILE *pNew; fdOpened = dup(fileno(pStdErr)); if (fdOpened == -1) { fprintf(pStdErr, "%s: error: failed to dup stderr (%d): %s\n", name(argv[0]), fileno(pStdErr), strerror(errno)); return 1; } #ifdef _MSC_VER /** @todo figure out how to make the handle close-on-exec. We'll simply close it for now. * SetHandleInformation + set FNOINHERIT in CRT. */ #else if (fcntl(fdOpened, F_SETFD, FD_CLOEXEC) == -1) { fprintf(pStdErr, "%s: error: failed to make stderr (%d) close-on-exec: %s\n", name(argv[0]), fdOpened, strerror(errno)); return 1; } #endif pNew = fdopen(fdOpened, "w"); if (!pNew) { fprintf(pStdErr, "%s: error: failed to fdopen the new stderr (%d): %s\n", name(argv[0]), fdOpened, strerror(errno)); return 1; } if (pStdOut == pStdErr) pStdOut = pNew; pStdErr = pNew; } else if (fd == 1 && pStdOut != pStdErr) pStdOut = pStdErr; /* * Close and open the new file descriptor. */ safeCloseFd(fd); #if defined(_MSC_VER) if (!strcmp(psz, "/dev/null")) psz = (char *)"nul"; #endif fdOpened = open(psz, fOpen, 0666); if (fdOpened == -1) { fprintf(pStdErr, "%s: error: failed to open '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno)); return 1; } if (fdOpened != fd) { /* move it (dup2 returns 0 on MSC). */ if (dup2(fdOpened, fd) == -1) { fprintf(pStdErr, "%s: error: failed to dup '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno)); return 1; } close(fdOpened); } } else { fprintf(pStdErr, "%s: syntax error: Invalid argument '%s'.\n", name(argv[0]), argv[i]); return usage(pStdErr, name(argv[0])); } } /* * Make sure there's something to execute. */ if (i >= argc) { fprintf(pStdErr, "%s: syntax error: nothing to execute!\n", name(argv[0])); return usage(pStdErr, name(argv[0])); } #if defined(_MSC_VER) if (fileno(pStdErr) != 2) /* no close-on-exec flag on windows */ { fclose(pStdErr); pStdErr = NULL; } /* MSC is a PITA since it refuses to quote the arguments... */ quoteArguments(argc - i, &argv[i]); rc = _spawnvp(_P_WAIT, argv[i], &argv[i]); if (rc == -1 && pStdErr) { fprintf(pStdErr, "%s: error: _spawnvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno)); rc = 1; } return rc; #else execvp(argv[i], &argv[i]); fprintf(pStdErr, "%s: error: _execvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno)); return 1; #endif } kbuild-2695/src/kmk/kmkbuiltin/openbsd.c0000644000000000000000000000310412247157306016756 0ustar rootroot/* $Id: openbsd.c 2421 2010-10-17 21:27:53Z bird $ */ /** @file * Missing BSD functions in OpenBSD. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include int lchmod(const char *path, mode_t mode) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return chmod(path, mode); } int lutimes(const char *path, const struct timeval *tvs) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return utimes(path, tvs); } kbuild-2695/src/kmk/kmkbuiltin/cp_extern.h0000644000000000000000000000465612247157307017336 0ustar rootroot/*- * Copyright (c) 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)extern.h 8.2 (Berkeley) 4/1/94 * $FreeBSD: src/bin/cp/extern.h,v 1.19 2004/04/06 20:06:44 markm Exp $ */ typedef struct { char *p_end; /* pointer to NULL at end of path */ char *target_end; /* pointer to end of target base */ char p_path[PATH_MAX]; /* pointer to the start of a path */ } PATH_T; #define argv0 cp_argv0 #define to cp_to #define fflag cp_fflag #define iflag cp_iflag #define nflag cp_nflag #define pflag cp_pflag #define vflag cp_vflag #define info cp_info #define usage cp_usage #define setfile cp_setfile extern const char *argv0; extern PATH_T to; extern int fflag, iflag, nflag, pflag, vflag; extern volatile sig_atomic_t info; int copy_fifo(struct stat *, int); int copy_file(const FTSENT *, int, int, int *); int copy_link(const FTSENT *, int); int copy_special(struct stat *, int); int setfile(struct stat *, int); kbuild-2695/src/kmk/kmkbuiltin/haikufakes.c0000644000000000000000000000276412247157306017452 0ustar rootroot/* $Id: haikufakes.c 2546 2011-10-01 19:49:54Z bird $ */ /** @file * Fake Unix/BSD stuff for Haiku. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include "haikufakes.h" int haiku_lchmod(const char *pszPath, mode_t mode) { /* * Weed out symbolic links. */ struct stat s; if ( !lstat(pszPath, &s) && S_ISLNK(s.st_mode)) { errno = -ENOSYS; return -1; } return chmod(pszPath, mode); } kbuild-2695/src/kmk/kmkbuiltin/cmp_util.c0000644000000000000000000003544312247157307017154 0ustar rootroot/* $NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $ */ /* $NetBSD: misc.c,v 1.11 2007/08/22 16:59:19 christos Exp $ */ /* $NetBSD: regular.c,v 1.20 2006/06/03 21:47:55 christos Exp $ */ /* $NetBSD: special.c,v 1.12 2007/08/21 14:09:54 christos Exp $ */ /* * Copyright (c) 1987, 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n");*/ #include "config.h" #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) /** @todo more mmap capable OSes. */ # define CMP_USE_MMAP # include # include #endif #include #include #include #include #include #ifndef _MSC_VER # include # ifndef O_BINARY # define O_BINARY 0 # endif #else # define MSC_DO_64_BIT_IO # include "mscfakes.h" #endif #include "err.h" #include "cmp_extern.h" static int errmsg(const char *file, off_t byte, off_t line, int lflag) { if (lflag) #ifdef _MSC_VER return err(ERR_EXIT, "%s: char %I64d, line %lld", file, (__int64)byte, (long long)line); #else return err(ERR_EXIT, "%s: char %lld, line %lld", file, (long long)byte, (long long)line); #endif return err(ERR_EXIT, "%s", file); } static int eofmsg(const char *file, off_t byte, off_t line, int sflag, int lflag) { if (!sflag) { if (!lflag) warnx("EOF on %s", file); else { #ifdef _MSC_VER if (line > 0) warnx("EOF on %s: char %I64d, line %I64d", file, (__int64)byte, (__int64)line); else warnx("EOF on %s: char %I64d", file, (__int64)byte); #else if (line > 0) warnx("EOF on %s: char %lld, line %lld", file, (long long)byte, (long long)line); else warnx("EOF on %s: char %lld", file, (long long)byte); #endif } } return DIFF_EXIT; } static int diffmsg(const char *file1, const char *file2, off_t byte, off_t line, int sflag) { if (!sflag) #ifdef _MSC_VER printf("%s %s differ: char %I64d, line %I64d\n", file1, file2, (__int64)byte, (__int64)line); #else printf("%s %s differ: char %lld, line %lld\n", file1, file2, (long long)byte, (long long)line); #endif return DIFF_EXIT; } /** * Compares two files, where one or both are non-regular ones. */ static int c_special(int fd1, const char *file1, off_t skip1, int fd2, const char *file2, off_t skip2, int lflag, int sflag) { int fd1dup, fd2dup; FILE *fp1; int rc; /* duplicate because fdopen+fclose will otherwise close the handle. */ fd1dup = dup(fd1); if (fd1 < 0) return err(ERR_EXIT, "%s", file1); fp1 = fdopen(fd1dup, "rb"); if (!fp1) fp1 = fdopen(fd1dup, "r"); if (!fp1) { err(ERR_EXIT, "%s", file1); close(fd1dup); return ERR_EXIT; } fd2dup = dup(fd2); if (fd2dup >= 0) { FILE *fp2 = fdopen(fd2dup, "rb"); if (!fp2) fp2 = fdopen(fd2dup, "r"); if (fp2) { off_t byte; off_t line; int ch1 = 0; int ch2 = 0; /* skipping ahead */ rc = OK_EXIT; for (byte = line = 1; skip1--; byte++) { ch1 = getc(fp1); if (ch1 == EOF) break; if (ch1 == '\n') line++; } for (byte = line = 1; skip2--; byte++) { ch2 = getc(fp2); if (ch2 == EOF) break; if (ch2 == '\n') line++; } if (ch2 != EOF && ch1 != EOF) { /* compare byte by byte */ for (byte = line = 1;; ++byte) { ch1 = getc(fp1); ch2 = getc(fp2); if (ch1 == EOF || ch2 == EOF) break; if (ch1 != ch2) { if (!lflag) { rc = diffmsg(file1, file2, byte, line, sflag); break; } rc = DIFF_EXIT; #ifdef _MSC_VER printf("%6i64d %3o %3o\n", (__int64)byte, ch1, ch2); #else printf("%6lld %3o %3o\n", (long long)byte, ch1, ch2); #endif } if (ch1 == '\n') ++line; } } /* Check for errors and length differences (EOF). */ if (ferror(fp1) && rc != ERR_EXIT) rc = errmsg(file1, byte, line, lflag); if (ferror(fp2) && rc != ERR_EXIT) rc = errmsg(file2, byte, line, lflag); if (rc == OK_EXIT) { if (feof(fp1)) { if (!feof(fp2)) rc = eofmsg(file1, byte, line, sflag, lflag); } else if (feof(fp2)) rc = eofmsg(file2, byte, line, sflag, lflag); } fclose(fp2); } else { rc = err(ERR_EXIT, "%s", file2); close(fd2dup); } } else rc = err(ERR_EXIT, "%s", file2); fclose(fp1); return rc; } #ifdef CMP_USE_MMAP /** * Compare two files using mmap. */ static int c_regular(int fd1, const char *file1, off_t skip1, off_t len1, int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag) { unsigned char ch, *p1, *p2, *b1, *b2; off_t byte, length, line; int dfound; size_t blk_sz, blk_cnt; if (sflag && len1 != len2) return DIFF_EXIT; if (skip1 > len1) return eofmsg(file1, len1 + 1, 0, sflag, lflag); len1 -= skip1; if (skip2 > len2) return eofmsg(file2, len2 + 1, 0, sflag, lflag); len2 -= skip2; byte = line = 1; dfound = 0; length = len1 <= len2 ? len1 : len2; for (blk_sz = 1024 * 1024; length != 0; length -= blk_sz) { if (blk_sz > length) blk_sz = length; b1 = p1 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd1, skip1); if (p1 == MAP_FAILED) goto l_mmap_failed; b2 = p2 = mmap(NULL, blk_sz, PROT_READ, MAP_FILE | MAP_SHARED, fd2, skip2); if (p2 == MAP_FAILED) { munmap(p1, blk_sz); goto l_mmap_failed; } blk_cnt = blk_sz; for (; blk_cnt--; ++p1, ++p2, ++byte) { if ((ch = *p1) != *p2) { if (!lflag) { munmap(b1, blk_sz); munmap(b2, blk_sz); return diffmsg(file1, file2, byte, line, sflag); } dfound = 1; #ifdef _MSC_VER printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2); #else printf("%6lld %3o %3o\n", (long long)byte, ch, *p2); #endif } if (ch == '\n') ++line; } munmap(p1 - blk_sz, blk_sz); munmap(p2 - blk_sz, blk_sz); skip1 += blk_sz; skip2 += blk_sz; } if (len1 != len2) return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag); if (dfound) return DIFF_EXIT; return OK_EXIT; l_mmap_failed: return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag); } #else /* non-mmap c_regular: */ /** * Compare two files without mmaping them. */ static int c_regular(int fd1, const char *file1, off_t skip1, off_t len1, int fd2, const char *file2, off_t skip2, off_t len2, int sflag, int lflag) { unsigned char ch, *p1, *p2, *b1 = 0, *b2 = 0; off_t byte, length, line, bytes_read; int dfound; size_t blk_sz, blk_cnt; if (sflag && len1 != len2) return DIFF_EXIT; if (skip1 > len1) return eofmsg(file1, len1 + 1, 0, sflag, lflag); len1 -= skip1; if (skip2 > len2) return eofmsg(file2, len2 + 1, 0, sflag, lflag); len2 -= skip2; if (skip1 && lseek(fd1, skip1, SEEK_SET) < 0) goto l_special; if (skip2 && lseek(fd2, skip2, SEEK_SET) < 0) { if (skip1 && lseek(fd1, 0, SEEK_SET) < 0) return err(1, "seek failed"); goto l_special; } #define CMP_BUF_SIZE (128*1024) b1 = malloc(CMP_BUF_SIZE); b2 = malloc(CMP_BUF_SIZE); if (!b1 || !b2) goto l_malloc_failed; byte = line = 1; dfound = 0; length = len1; if (length > len2) length = len2; for (blk_sz = CMP_BUF_SIZE; length != 0; length -= blk_sz) { if ((off_t)blk_sz > length) blk_sz = length; bytes_read = read(fd1, b1, blk_sz); if (bytes_read != (off_t)blk_sz) goto l_read_error; bytes_read = read(fd2, b2, blk_sz); if (bytes_read != (off_t)blk_sz) goto l_read_error; blk_cnt = blk_sz; p1 = b1; p2 = b2; for (; blk_cnt--; ++p1, ++p2, ++byte) { if ((ch = *p1) != *p2) { if (!lflag) { free(b1); free(b2); return diffmsg(file1, file2, byte, line, sflag); } dfound = 1; #ifdef _MSC_VER printf("%6I64d %3o %3o\n", (__int64)byte, ch, *p2); #else printf("%6lld %3o %3o\n", (long long)byte, ch, *p2); #endif } if (ch == '\n') ++line; } skip1 += blk_sz; skip2 += blk_sz; } if (len1 != len2) return eofmsg(len1 > len2 ? file2 : file1, byte, line, sflag, lflag); if (dfound) return DIFF_EXIT; return OK_EXIT; l_read_error: if ( lseek(fd1, 0, SEEK_SET) < 0 || lseek(fd2, 0, SEEK_SET) < 0) { err(1, "seek failed"); free(b1); free(b2); return 1; } l_malloc_failed: free(b1); free(b2); l_special: return c_special(fd1, file1, skip1, fd2, file2, skip2, lflag, sflag); } #endif /* non-mmap c_regular */ /** * Compares two open files. */ int cmp_fd_and_fd_ex(int fd1, const char *file1, off_t skip1, int fd2, const char *file2, off_t skip2, int sflag, int lflag, int special) { struct stat st1, st2; int rc; if (fstat(fd1, &st1)) return err(ERR_EXIT, "%s", file1); if (fstat(fd2, &st2)) return err(ERR_EXIT, "%s", file2); if ( !S_ISREG(st1.st_mode) || !S_ISREG(st2.st_mode) || special) rc = c_special(fd1, file1, skip1, fd2, file2, skip2, sflag, lflag); else rc = c_regular(fd1, file1, skip1, st1.st_size, fd2, file2, skip2, st2.st_size, sflag, lflag); return rc; } /** * Compares two open files. */ int cmp_fd_and_fd(int fd1, const char *file1, int fd2, const char *file2, int sflag, int lflag, int special) { return cmp_fd_and_fd_ex(fd1, file1, 0, fd2, file2, 0, sflag, lflag, special); } /** * Compares an open file with another that isn't open yet. */ int cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special) { int rc; int fd2; if (!strcmp(file2, "-")) { fd2 = 0 /* stdin */; special = 1; file2 = "stdin"; } else fd2 = open(file2, O_RDONLY | O_BINARY, 0); if (fd2 >= 0) { rc = cmp_fd_and_fd_ex(fd1, file1, skip1, fd2, file2, skip2, sflag, lflag, special); close(fd2); } else { if (!sflag) warn("%s", file2); rc = ERR_EXIT; } return rc; } /** * Compares an open file with another that isn't open yet. */ int cmp_fd_and_file(int fd1, const char *file1, const char *file2, int sflag, int lflag, int special) { return cmp_fd_and_file_ex(fd1, file1, 0, file2, 0, sflag, lflag, special); } /** * Opens and compare two files. */ int cmp_file_and_file_ex(const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special) { int fd1; int rc; if (lflag && sflag) return errx(ERR_EXIT, "only one of -l and -s may be specified"); if (!strcmp(file1, "-")) { if (!strcmp(file2, "-")) return errx(ERR_EXIT, "standard input may only be specified once"); file1 = "stdin"; fd1 = 1; special = 1; } else fd1 = open(file1, O_RDONLY | O_BINARY, 0); if (fd1 >= 0) { rc = cmp_fd_and_file_ex(fd1, file1, skip1, file2, skip2, sflag, lflag, special); close(fd1); } else { if (!sflag) warn("%s", file1); rc = ERR_EXIT; } return rc; } /** * Opens and compare two files. */ int cmp_file_and_file(const char *file1, const char *file2, int sflag, int lflag, int special) { return cmp_file_and_file_ex(file1, 0, file2, 0, sflag, lflag, special); } kbuild-2695/src/kmk/kmkbuiltin/Makefile.kup0000644000000000000000000000000012247157306017406 0ustar rootrootkbuild-2695/src/kmk/kmkbuiltin/rm.c0000644000000000000000000004560612247157306015757 0ustar rootroot/*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94"; #endif /* not lint */ #include /*__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.47 2004/04/06 20:06:50 markm Exp $");*/ #endif #include "config.h" #include #if !defined(_MSC_VER) && !defined(__HAIKU__) # include # include #endif #include "err.h" #include #include #include #include #include #include #include #include #ifndef __HAIKU__ # include #endif #include #include #include "getopt.h" #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #if defined(__OS2__) || defined(_MSC_VER) # include # include #endif #include "kmkbuiltin.h" #include "kbuild_protection.h" #if defined(__EMX__) || defined(_MSC_VER) # define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' ) # define HAVE_DOS_PATHS 1 # define DEFAULT_PROTECTION_DEPTH 1 #else # define IS_SLASH(ch) ( (ch) == '/' ) # undef HAVE_DOS_PATHS # define DEFAULT_PROTECTION_DEPTH 2 #endif #ifdef __EMX__ #undef S_IFWHT #undef S_ISWHT #endif #ifndef S_IFWHT #define S_IFWHT 0 #define S_ISWHT(s) 0 #define undelete(s) (-1) #endif extern void bsd_strmode(mode_t mode, char *p); static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok; static uid_t uid; static char *argv0; static KBUILDPROTECTION g_ProtData; static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { "disable-protection", no_argument, 0, 263 }, { "enable-protection", no_argument, 0, 264 }, { "enable-full-protection", no_argument, 0, 265 }, { "disable-full-protection", no_argument, 0, 266 }, { "protection-depth", required_argument, 0, 267 }, { 0, 0, 0, 0 }, }; static int check(char *, char *, struct stat *); static void checkdot(char **); static int rm_file(char **); static int rm_overwrite(char *, struct stat *); static int rm_tree(char **); static int usage(FILE *); #if 1 #define CUR_LINE_H2(x) "[line " #x "]" #define CUR_LINE_H1(x) CUR_LINE_H2(x) #define CUR_LINE() CUR_LINE_H1(__LINE__) #else # define CUR_LINE() #endif /* * rm -- * This rm is different from historic rm's, but is expected to match * POSIX 1003.2 behavior. The most visible difference is that -f * has two specific effects now, ignore non-existent files and force * file removal. */ int kmk_builtin_rm(int argc, char *argv[], char **envp) { int ch, rflag; /* reinitialize globals */ argv0 = argv[0]; dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0; uid = 0; kBuildProtectionInit(&g_ProtData); /* kmk: reset getopt and set program name. */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ Pflag = rflag = 0; while ((ch = getopt_long(argc, argv, "dfiPRvW", long_options, NULL)) != -1) switch(ch) { case 'd': dflag = 1; break; case 'f': fflag = 1; iflag = 0; break; case 'i': fflag = 0; iflag = 1; break; case 'P': Pflag = 1; break; case 'R': #if 0 case 'r': /* Compatibility. */ #endif rflag = 1; break; case 'v': vflag = 1; break; #ifdef FTS_WHITEOUT case 'W': Wflag = 1; break; #endif case 261: kBuildProtectionTerm(&g_ProtData); usage(stdout); return 0; case 262: kBuildProtectionTerm(&g_ProtData); return kbuild_version(argv[0]); case 263: kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case 264: kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); break; case 265: kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case 266: kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL); break; case 267: if (kBuildProtectionSetDepth(&g_ProtData, optarg)) { kBuildProtectionTerm(&g_ProtData); return 1; } break; case '?': default: kBuildProtectionTerm(&g_ProtData); return usage(stderr); } argc -= optind; argv += optind; if (argc < 1) { kBuildProtectionTerm(&g_ProtData); if (fflag) return (0); return usage(stderr); } if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_RM_")) { checkdot(argv); uid = geteuid(); if (*argv) { stdin_ok = isatty(STDIN_FILENO); if (rflag) eval |= rm_tree(argv); else eval |= rm_file(argv); } } else { eval = 1; } kBuildProtectionTerm(&g_ProtData); return eval; } static int rm_tree(char **argv) { FTS *fts; FTSENT *p; int needstat; int flags; int rval; /* * Check up front before anything is deleted. This will not catch * everything, but we'll check the individual items later. */ int i; for (i = 0; argv[i]; i++) { if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) { return 1; } } /* * Remove a file hierarchy. If forcing removal (-f), or interactive * (-i) or can't ask anyway (stdin_ok), don't stat the file. */ needstat = !uid || (!fflag && !iflag && stdin_ok); /* * If the -i option is specified, the user can skip on the pre-order * visit. The fts_number field flags skipped directories. */ #define SKIPPED 1 flags = FTS_PHYSICAL; if (!needstat) flags |= FTS_NOSTAT; #ifdef FTS_WHITEOUT if (Wflag) flags |= FTS_WHITEOUT; #endif if (!(fts = fts_open(argv, flags, NULL))) { return err(1, "fts_open"); } while ((p = fts_read(fts)) != NULL) { const char *operation = "chflags"; switch (p->fts_info) { case FTS_DNR: if (!fflag || p->fts_errno != ENOENT) { fprintf(stderr, "fts: %s: %s: %s" CUR_LINE() "\n", argv0, p->fts_path, strerror(p->fts_errno)); eval = 1; } continue; case FTS_ERR: fts_close(fts); return errx(1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno)); case FTS_NS: /* * Assume that since fts_read() couldn't stat the * file, it can't be unlinked. */ if (!needstat) break; if (!fflag || p->fts_errno != ENOENT) { fprintf(stderr, "fts: %s: %s: %s " CUR_LINE() "\n", argv0, p->fts_path, strerror(p->fts_errno)); eval = 1; } continue; case FTS_D: /* Pre-order: give user chance to skip. */ if (!fflag && !check(p->fts_path, p->fts_accpath, p->fts_statp)) { (void)fts_set(fts, p, FTS_SKIP); p->fts_number = SKIPPED; } #ifdef UF_APPEND else if (!uid && (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && chflags(p->fts_accpath, p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0) goto err; #endif continue; case FTS_DP: /* Post-order: see if user skipped. */ if (p->fts_number == SKIPPED) continue; break; default: if (!fflag && !check(p->fts_path, p->fts_accpath, p->fts_statp)) continue; } /* * Protect against deleting root files and directories. */ if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) { fts_close(fts); return 1; } rval = 0; #ifdef UF_APPEND if (!uid && (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE))) rval = chflags(p->fts_accpath, p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)); #endif if (rval == 0) { /* * If we can't read or search the directory, may still be * able to remove it. Don't print out the un{read,search}able * message unless the remove fails. */ switch (p->fts_info) { case FTS_DP: case FTS_DNR: rval = rmdir(p->fts_accpath); if (rval == 0 || (fflag && errno == ENOENT)) { if (rval == 0 && vflag) (void)printf("%s\n", p->fts_path); continue; } operation = "mkdir"; break; #ifdef FTS_W case FTS_W: rval = undelete(p->fts_accpath); if (rval == 0 && (fflag && errno == ENOENT)) { if (vflag) (void)printf("%s\n", p->fts_path); continue; } operation = "undelete"; break; #endif case FTS_NS: /* * Assume that since fts_read() couldn't stat * the file, it can't be unlinked. */ if (fflag) continue; /* FALLTHROUGH */ default: if (Pflag) if (!rm_overwrite(p->fts_accpath, NULL)) continue; rval = unlink(p->fts_accpath); #ifdef _MSC_VER if (rval != 0) { chmod(p->fts_accpath, 0777); rval = unlink(p->fts_accpath); } #endif if (rval == 0 || (fflag && errno == ENOENT)) { if (rval == 0 && vflag) (void)printf("%s\n", p->fts_path); continue; } operation = "unlink"; break; } } #ifdef UF_APPEND err: #endif fprintf(stderr, "%s: %s: %s: %s " CUR_LINE() "\n", operation, argv0, p->fts_path, strerror(errno)); eval = 1; } if (errno) { fprintf(stderr, "%s: fts_read: %s " CUR_LINE() "\n", argv0, strerror(errno)); eval = 1; } fts_close(fts); return eval; } static int rm_file(char **argv) { struct stat sb; int rval; char *f; /* * Check up front before anything is deleted. */ int i; for (i = 0; argv[i]; i++) { if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i])) return 1; } /* * Remove a file. POSIX 1003.2 states that, by default, attempting * to remove a directory is an error, so must always stat the file. */ while ((f = *argv++) != NULL) { const char *operation = "?"; /* Assume if can't stat the file, can't unlink it. */ if (lstat(f, &sb)) { #ifdef FTS_WHITEOUT if (Wflag) { sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR; } else { #else { #endif if (!fflag || errno != ENOENT) { fprintf(stderr, "lstat: %s: %s: %s " CUR_LINE() "\n", argv0, f, strerror(errno)); eval = 1; } continue; } #ifdef FTS_WHITEOUT } else if (Wflag) { fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(EEXIST)); eval = 1; continue; #endif } if (S_ISDIR(sb.st_mode) && !dflag) { fprintf(stderr, "%s: %s: is a directory\n", argv0, f); eval = 1; continue; } if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb)) continue; rval = 0; #ifdef UF_APPEND if (!uid && (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE))) rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE)); #endif if (rval == 0) { if (S_ISWHT(sb.st_mode)) { rval = undelete(f); operation = "undelete"; } else if (S_ISDIR(sb.st_mode)) { rval = rmdir(f); operation = "rmdir"; } else { if (Pflag) if (!rm_overwrite(f, &sb)) continue; rval = unlink(f); #ifdef _MSC_VER if (rval != 0) { chmod(f, 0777); rval = unlink(f); } #endif operation = "unlink"; } } if (rval && (!fflag || errno != ENOENT)) { fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, f, strerror(errno)); eval = 1; } if (vflag && rval == 0) (void)printf("%s\n", f); } return eval; } /* * rm_overwrite -- * Overwrite the file 3 times with varying bit patterns. * * XXX * This is a cheap way to *really* delete files. Note that only regular * files are deleted, directories (and therefore names) will remain. * Also, this assumes a fixed-block file system (like FFS, or a V7 or a * System V file system). In a logging file system, you'll have to have * kernel support. */ static int rm_overwrite(char *file, struct stat *sbp) { struct stat sb; #ifdef HAVE_FSTATFS struct statfs fsb; #endif off_t len; int bsize, fd, wlen; char *buf = NULL; const char *operation = "lstat"; fd = -1; if (sbp == NULL) { if (lstat(file, &sb)) goto err; sbp = &sb; } if (!S_ISREG(sbp->st_mode)) return (1); operation = "open"; if ((fd = open(file, O_WRONLY, 0)) == -1) goto err; #ifdef HAVE_FSTATFS if (fstatfs(fd, &fsb) == -1) goto err; bsize = MAX(fsb.f_iosize, 1024); #elif defined(HAVE_ST_BLKSIZE) bsize = MAX(sb.st_blksize, 1024); #else bsize = 1024; #endif if ((buf = malloc(bsize)) == NULL) exit(err(1, "%s: malloc", file)); #define PASS(byte) { \ operation = "write"; \ memset(buf, byte, bsize); \ for (len = sbp->st_size; len > 0; len -= wlen) { \ wlen = len < bsize ? len : bsize; \ if (write(fd, buf, wlen) != wlen) \ goto err; \ } \ } PASS(0xff); operation = "fsync/lseek"; if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) goto err; PASS(0x00); operation = "fsync/lseek"; if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) goto err; PASS(0xff); if (!fsync(fd) && !close(fd)) { free(buf); return (1); } operation = "fsync/close"; err: eval = 1; if (buf) free(buf); if (fd != -1) close(fd); fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, file, strerror(errno)); return (0); } static int check(char *path, char *name, struct stat *sp) { int ch, first; char modep[15], *flagsp; /* Check -i first. */ if (iflag) (void)fprintf(stderr, "remove %s? ", path); else { /* * If it's not a symbolic link and it's unwritable and we're * talking to a terminal, ask. Symbolic links are excluded * because their permissions are meaningless. Check stdin_ok * first because we may not have stat'ed the file. * Also skip this check if the -P option was specified because * we will not be able to overwrite file contents and will * barf later. */ if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag || (!access(name, W_OK) && #ifdef SF_APPEND !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid)) #else 1) #endif ) return (1); bsd_strmode(sp->st_mode, modep); #ifdef SF_APPEND if ((flagsp = fflagstostr(sp->st_flags)) == NULL) exit(err(1, "fflagstostr")); (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ", modep + 1, modep[9] == ' ' ? "" : " ", user_from_uid(sp->st_uid, 0), group_from_gid(sp->st_gid, 0), *flagsp ? flagsp : "", *flagsp ? " " : "", path); free(flagsp); #else (void)flagsp; (void)fprintf(stderr, "override %s%s %d/%d for %s? ", modep + 1, modep[9] == ' ' ? "" : " ", sp->st_uid, sp->st_gid, path); #endif } (void)fflush(stderr); first = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); return (first == 'y' || first == 'Y'); } #define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2]))) static void checkdot(char **argv) { char *p, **save, **t; int complained; complained = 0; for (t = argv; *t;) { #ifdef HAVE_DOS_PATHS const char *tmp = p = *t; while (*tmp) { switch (*tmp) { case '/': case '\\': case ':': p = (char *)tmp + 1; break; } tmp++; } #else if ((p = strrchr(*t, '/')) != NULL) ++p; else p = *t; #endif if (ISDOT(p)) { if (!complained++) fprintf(stderr, "%s: \".\" and \"..\" may not be removed\n", argv0); eval = 1; for (save = t; (t[0] = t[1]) != NULL; ++t) continue; t = save; } else ++t; } } static int usage(FILE *pf) { fprintf(pf, "usage: %s [options] file ...\n" " or: %s --help\n" " or: %s --version\n" "\n" "Options:\n" " -f\n" " Attempt to remove files without prompting, regardless of the file\n" " permission. Ignore non-existing files. Overrides previous -i's.\n" " -i\n" " Prompt for each file. Always.\n" " -d\n" " Attempt to remove directories as well as other kinds of files.\n" " -P\n" " Overwrite regular files before deleting; three passes: ff,0,ff\n" " -R\n" " Attempt to remove the file hierachy rooted in each file argument.\n" " This option implies -d and file protection.\n" " -v\n" " Be verbose, show files as they are removed.\n" " -W\n" " Undelete without files.\n" " --disable-protection\n" " Will disable the protection file protection applied with -R.\n" " --enable-protection\n" " Will enable the protection file protection applied with -R.\n" " --enable-full-protection\n" " Will enable the protection file protection for all operations.\n" " --disable-full-protection\n" " Will disable the protection file protection for all operations.\n" " --protection-depth\n" " Number or path indicating the file protection depth. Default: %d\n" "\n" "Environment:\n" " KMK_RM_DISABLE_PROTECTION\n" " Same as --disable-protection. Overrides command line.\n" " KMK_RM_ENABLE_PROTECTION\n" " Same as --enable-protection. Overrides everyone else.\n" " KMK_RM_ENABLE_FULL_PROTECTION\n" " Same as --enable-full-protection. Overrides everyone else.\n" " KMK_RM_DISABLE_FULL_PROTECTION\n" " Same as --disable-full-protection. Overrides command line.\n" " KMK_RM_PROTECTION_DEPTH\n" " Same as --protection-depth. Overrides command line.\n" "\n" "The file protection of the top %d layers of the file hierarchy is there\n" "to try prevent makefiles from doing bad things to your system. This\n" "protection is not bulletproof, but should help prevent you from shooting\n" "yourself in the foot.\n" , g_progname, g_progname, g_progname, kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth()); return EX_USAGE; } kbuild-2695/src/kmk/kmkbuiltin/rmdir.c0000644000000000000000000001250612247157307016450 0ustar rootroot/*- * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1992, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)rmdir.c 8.3 (Berkeley) 4/2/94"; #endif /* not lint */ #endif #if 0 #include __FBSDID("$FreeBSD: src/bin/rmdir/rmdir.c,v 1.20 2005/01/26 06:51:28 ssouhlal Exp $"); #endif #include "config.h" #include "err.h" #include #include #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #include "getopt.h" #include "kmkbuiltin.h" #ifdef _MSC_VER # include "mscfakes.h" #endif static int rm_path(char *); static int usage(FILE *); static int pflag; static int vflag; static int ignore_fail_on_non_empty; static int ignore_fail_on_not_exist; static struct option long_options[] = { { "help", no_argument, 0, 262 }, { "ignore-fail-on-non-empty", no_argument, 0, 260 }, { "ignore-fail-on-not-exist", no_argument, 0, 261 }, { "parents", no_argument, 0, 'p' }, { "verbose", no_argument, 0, 'v' }, { "version", no_argument, 0, 263 }, { 0, 0, 0, 0 }, }; int kmk_builtin_rmdir(int argc, char *argv[], char **envp) { int ch, errors; /* reinitialize globals */ ignore_fail_on_not_exist = ignore_fail_on_non_empty = vflag = pflag = 0; /* kmk: reset getopt and set progname */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ while ((ch = getopt_long(argc, argv, "pv", long_options, NULL)) != -1) switch(ch) { case 'p': pflag = 1; break; case 'v': vflag = 1; break; case 260: ignore_fail_on_non_empty = 1; break; case 261: ignore_fail_on_not_exist = 1; break; case 262: usage(stdout); return 0; case 263: return kbuild_version(argv[0]); case '?': default: return usage(stderr); } argc -= optind; argv += optind; if (argc == 0) return /*usage(stderr)*/0; for (errors = 0; *argv; argv++) { if (rmdir(*argv) < 0) { if ( (!ignore_fail_on_non_empty || (errno != ENOTEMPTY && errno != EPERM && errno != EACCES && errno != EINVAL && errno != EEXIST)) && (!ignore_fail_on_not_exist || errno != ENOENT)) { warn("rmdir: %s", *argv); errors = 1; continue; } if (!ignore_fail_on_not_exist || errno != ENOENT) continue; /* (only ignored doesn't exist errors fall thru) */ } else if (vflag) { printf("%s\n", *argv); } if (pflag) errors |= rm_path(*argv); } return errors; } static int rm_path(char *path) { char *p; const size_t len = strlen(path); p = alloca(len + 1); path = memcpy(p, path, len + 1); #if defined(_MSC_VER) || defined(__EMX__) p = strchr(path, '\\'); while (p) { *p++ = '/'; p = strchr(p, '\\'); } #endif p = path + len; while (--p > path && *p == '/') ; *++p = '\0'; while ((p = strrchr(path, '/')) != NULL) { /* Delete trailing slashes. */ while (--p >= path && *p == '/') ; *++p = '\0'; if (p == path) break; #if defined(_MSC_VER) || defined(__EMX__) if (p[-1] == ':' && p - 2 == path) break; #endif if (rmdir(path) < 0) { if (ignore_fail_on_non_empty && (errno == ENOTEMPTY || errno == EPERM || errno == EACCES || errno == EINVAL || errno == EEXIST)) break; if (!ignore_fail_on_not_exist || errno != ENOENT) { warn("rmdir: %s", path); return (1); } } if (vflag) printf("%s\n", path); } return (0); } static int usage(FILE *pf) { (void)fprintf(pf, "usage: %s [-pv --ignore-fail-on-non-empty --ignore-fail-on-not-exist] directory ...\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname); return 1; } kbuild-2695/src/kmk/kmkbuiltin/mscfakes.c0000644000000000000000000003647112247157307017136 0ustar rootroot/* $Id: mscfakes.c 2645 2012-09-09 02:29:23Z bird $ */ /** @file * Fake Unix stuff for MSC. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include #include #include #include "err.h" #include "mscfakes.h" #define timeval windows_timeval #include #undef timeval /** * Makes corrections to a directory path that ends with a trailing slash. * * @returns temporary buffer to free. * @param ppszPath The path pointer. This is updated when necessary. * @param pfMustBeDir This is set if it must be a directory, otherwise it's cleared. */ static char * msc_fix_path(const char **ppszPath, int *pfMustBeDir) { const char *pszPath = *ppszPath; const char *psz; char *pszNew; *pfMustBeDir = 0; /* * Skip any compusory trailing slashes */ if (pszPath[0] == '/' || pszPath[0] == '\\') { if ( (pszPath[1] == '/' || pszPath[1] == '\\') && pszPath[2] != '/' && pszPath[2] != '\\') /* unc */ pszPath += 2; else /* root slash(es) */ pszPath++; } else if ( isalpha(pszPath[0]) && pszPath[1] == ':') { if (pszPath[2] == '/' || pszPath[2] == '\\') /* drive w/ slash */ pszPath += 3; else /* drive relative path. */ pszPath += 2; } /* else: relative path, no skipping necessary. */ /* * Any trailing slashes to drop off? */ psz = strchr(pszPath, '\0'); if (pszPath <= psz) return NULL; if ( psz[-1] != '/' || psz[-1] != '\\') return NULL; /* figure how many, make a copy and strip them off. */ while ( psz > pszPath && ( psz[-1] == '/' || psz[-1] == '\\')) psz--; pszNew = strdup(pszPath); pszNew[psz - pszPath] = '\0'; *pfMustBeDir = 1; *ppszPath = pszNew; /* use this one */ return pszNew; } static int msc_set_errno(DWORD dwErr) { switch (dwErr) { default: case ERROR_INVALID_FUNCTION: errno = EINVAL; break; case ERROR_FILE_NOT_FOUND: errno = ENOENT; break; case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_TOO_MANY_OPEN_FILES: errno = EMFILE; break; case ERROR_ACCESS_DENIED: errno = EACCES; break; case ERROR_INVALID_HANDLE: errno = EBADF; break; case ERROR_ARENA_TRASHED: errno = ENOMEM; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; case ERROR_INVALID_BLOCK: errno = ENOMEM; break; case ERROR_BAD_ENVIRONMENT: errno = E2BIG; break; case ERROR_BAD_FORMAT: errno = ENOEXEC; break; case ERROR_INVALID_ACCESS: errno = EINVAL; break; case ERROR_INVALID_DATA: errno = EINVAL; break; case ERROR_INVALID_DRIVE: errno = ENOENT; break; case ERROR_CURRENT_DIRECTORY: errno = EACCES; break; case ERROR_NOT_SAME_DEVICE: errno = EXDEV; break; case ERROR_NO_MORE_FILES: errno = ENOENT; break; case ERROR_LOCK_VIOLATION: errno = EACCES; break; case ERROR_BAD_NETPATH: errno = ENOENT; break; case ERROR_NETWORK_ACCESS_DENIED: errno = EACCES; break; case ERROR_BAD_NET_NAME: errno = ENOENT; break; case ERROR_FILE_EXISTS: errno = EEXIST; break; case ERROR_CANNOT_MAKE: errno = EACCES; break; case ERROR_FAIL_I24: errno = EACCES; break; case ERROR_INVALID_PARAMETER: errno = EINVAL; break; case ERROR_NO_PROC_SLOTS: errno = EAGAIN; break; case ERROR_DRIVE_LOCKED: errno = EACCES; break; case ERROR_BROKEN_PIPE: errno = EPIPE; break; case ERROR_DISK_FULL: errno = ENOSPC; break; case ERROR_INVALID_TARGET_HANDLE: errno = EBADF; break; case ERROR_WAIT_NO_CHILDREN: errno = ECHILD; break; case ERROR_CHILD_NOT_COMPLETE: errno = ECHILD; break; case ERROR_DIRECT_ACCESS_HANDLE: errno = EBADF; break; case ERROR_NEGATIVE_SEEK: errno = EINVAL; break; case ERROR_SEEK_ON_DEVICE: errno = EACCES; break; case ERROR_DIR_NOT_EMPTY: errno = ENOTEMPTY; break; case ERROR_NOT_LOCKED: errno = EACCES; break; case ERROR_BAD_PATHNAME: errno = ENOENT; break; case ERROR_MAX_THRDS_REACHED: errno = EAGAIN; break; case ERROR_LOCK_FAILED: errno = EACCES; break; case ERROR_ALREADY_EXISTS: errno = EEXIST; break; case ERROR_FILENAME_EXCED_RANGE: errno = ENOENT; break; case ERROR_NESTING_NOT_ALLOWED: errno = EAGAIN; break; #ifdef EMLINK case ERROR_TOO_MANY_LINKS: errno = EMLINK; break; #endif } return -1; } char *dirname(char *path) { /** @todo later */ return path; } int lchmod(const char *pszPath, mode_t mode) { int rc = 0; int fMustBeDir; char *pszPathFree = msc_fix_path(&pszPath, &fMustBeDir); /* * Get the current attributes */ DWORD fAttr = GetFileAttributes(pszPath); if (fAttr == INVALID_FILE_ATTRIBUTES) rc = msc_set_errno(GetLastError()); else if (fMustBeDir & !(fAttr & FILE_ATTRIBUTE_DIRECTORY)) { errno = ENOTDIR; rc = -1; } else { /* * Modify the attributes and try set them. */ if (mode & _S_IWRITE) fAttr &= ~FILE_ATTRIBUTE_READONLY; else fAttr |= FILE_ATTRIBUTE_READONLY; if (!SetFileAttributes(pszPath, fAttr)) rc = msc_set_errno(GetLastError()); } if (pszPathFree) { int saved_errno = errno; free(pszPathFree); errno = saved_errno; } return rc; } int msc_chmod(const char *pszPath, mode_t mode) { int rc = 0; int fMustBeDir; char *pszPathFree = msc_fix_path(&pszPath, &fMustBeDir); /* * Get the current attributes. */ DWORD fAttr = GetFileAttributes(pszPath); if (fAttr == INVALID_FILE_ATTRIBUTES) rc = msc_set_errno(GetLastError()); else if (fMustBeDir & !(fAttr & FILE_ATTRIBUTE_DIRECTORY)) { errno = ENOTDIR; rc = -1; } else if (fAttr & FILE_ATTRIBUTE_REPARSE_POINT) { errno = ENOSYS; /** @todo resolve symbolic link / rewrite to NtSetInformationFile. */ rc = -1; } else { /* * Modify the attributes and try set them. */ if (mode & _S_IWRITE) fAttr &= ~FILE_ATTRIBUTE_READONLY; else fAttr |= FILE_ATTRIBUTE_READONLY; if (!SetFileAttributes(pszPath, fAttr)) rc = msc_set_errno(GetLastError()); } if (pszPathFree) { int saved_errno = errno; free(pszPathFree); errno = saved_errno; } return rc; } typedef BOOL (WINAPI *PFNCREATEHARDLINKA)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); int link(const char *pszDst, const char *pszLink) { static PFNCREATEHARDLINKA s_pfnCreateHardLinkA = NULL; static int s_fTried = FALSE; /* The API was introduced in Windows 2000, so resolve it dynamically. */ if (!s_pfnCreateHardLinkA) { if (!s_fTried) { HMODULE hmod = LoadLibrary("KERNEL32.DLL"); if (hmod) *(FARPROC *)&s_pfnCreateHardLinkA = GetProcAddress(hmod, "CreateHardLinkA"); s_fTried = TRUE; } if (!s_pfnCreateHardLinkA) { errno = ENOSYS; return -1; } } if (s_pfnCreateHardLinkA(pszLink, pszDst, NULL)) return 0; return msc_set_errno(GetLastError()); } int mkdir_msc(const char *path, mode_t mode) { int rc = (mkdir)(path); if (rc) { size_t len = strlen(path); if (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\')) { char *str = strdup(path); while (len > 0 && (str[len - 1] == '/' || str[len - 1] == '\\')) str[--len] = '\0'; rc = (mkdir)(str); free(str); } } return rc; } int rmdir_msc(const char *path) { int rc = (rmdir)(path); if (rc) { size_t len = strlen(path); if (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\')) { char *str = strdup(path); while (len > 0 && (str[len - 1] == '/' || str[len - 1] == '\\')) str[--len] = '\0'; rc = (rmdir)(str); free(str); } } return rc; } static int doname(char *pszX, char *pszEnd) { static char s_szChars[] = "Xabcdefghijklmnopqrstuwvxyz1234567890"; int rc = 0; do { char ch; pszEnd++; ch = *(strchr(s_szChars, *pszEnd) + 1); if (ch) { *pszEnd = ch; return 0; } *pszEnd = 'a'; } while (pszEnd != pszX); return 1; } int mkstemp(char *temp) { char *pszX = strchr(temp, 'X'); char *pszEnd = strchr(pszX, '\0'); int cTries = 1000; while (--cTries > 0) { int fd; if (doname(pszX, pszEnd)) return -1; fd = open(temp, _O_EXCL | _O_CREAT | _O_BINARY | _O_RDWR, 0777); if (fd >= 0) return fd; } return -1; } /** Unix to DOS. */ static char *fix_slashes(char *psz) { char *pszRet = psz; for (; *psz; psz++) if (*psz == '/') *psz = '\\'; return pszRet; } /** Calcs the SYMBOLIC_LINK_FLAG_DIRECTORY flag for CreatesymbolcLink. */ static DWORD is_directory(const char *pszPath, const char *pszRelativeTo) { size_t cchPath = strlen(pszPath); struct stat st; if (cchPath > 0 && pszPath[cchPath - 1] == '\\' || pszPath[cchPath - 1] == '/') return 1; /* SYMBOLIC_LINK_FLAG_DIRECTORY */ if (stat(pszPath, &st)) { size_t cchRelativeTo = strlen(pszRelativeTo); char *psz = malloc(cchPath + cchRelativeTo + 4); memcpy(psz, pszRelativeTo, cchRelativeTo); memcpy(psz + cchRelativeTo, "\\", 1); memcpy(psz + cchRelativeTo + 1, pszPath, cchPath + 1); if (stat(pszPath, &st)) st.st_mode = _S_IFREG; free(psz); } return (st.st_mode & _S_IFMT) == _S_IFDIR ? 1 : 0; } int symlink(const char *pszDst, const char *pszLink) { static BOOLEAN (WINAPI *s_pfnCreateSymbolicLinkA)(LPCSTR, LPCSTR, DWORD) = 0; static BOOL s_fTried = FALSE; if (!s_fTried) { HMODULE hmod = LoadLibrary("KERNEL32.DLL"); if (hmod) *(FARPROC *)&s_pfnCreateSymbolicLinkA = GetProcAddress(hmod, "CreateSymbolicLinkA"); s_fTried = TRUE; } if (s_pfnCreateSymbolicLinkA) { char *pszDstCopy = fix_slashes(strdup(pszDst)); char *pszLinkCopy = fix_slashes(strdup(pszLink)); BOOLEAN fRc = s_pfnCreateSymbolicLinkA(pszLinkCopy, pszDstCopy, is_directory(pszDstCopy, pszLinkCopy)); DWORD err = GetLastError(); free(pszDstCopy); free(pszLinkCopy); if (fRc) return 0; switch (err) { case ERROR_NOT_SUPPORTED: errno = ENOSYS; break; case ERROR_ALREADY_EXISTS: case ERROR_FILE_EXISTS: errno = EEXIST; break; case ERROR_DIRECTORY: errno = ENOTDIR; break; case ERROR_ACCESS_DENIED: case ERROR_PRIVILEGE_NOT_HELD: errno = EPERM; break; default: errno = EINVAL; break; } return -1; } errno = ENOSYS; err(1, "symlink() is not implemented on windows!"); return -1; } #if _MSC_VER < 1400 int snprintf(char *buf, size_t size, const char *fmt, ...) { int cch; va_list args; va_start(args, fmt); cch = vsprintf(buf, fmt, args); va_end(args); return cch; } #endif int utimes(const char *pszPath, const struct timeval *paTimes) { /** @todo implement me! */ return 0; } int writev(int fd, const struct iovec *vector, int count) { int size = 0; int i; for (i = 0; i < count; i++) { int cb = (int)write(fd, vector[i].iov_base, (int)vector[i].iov_len); if (cb < 0) return -1; size += cb; } return size; } intmax_t strtoimax(const char *nptr, char **endptr, int base) { if (*nptr != '-') return _strtoui64(nptr, endptr, base); return -(intmax_t)_strtoui64(nptr + 1, endptr, base); } uintmax_t strtoumax(const char *nptr, char **endptr, int base) { return _strtoui64(nptr, endptr, base); } int asprintf(char **strp, const char *fmt, ...) { int rc; va_list va; va_start(va, fmt); rc = vasprintf(strp, fmt, va); va_end(va); return rc; } int vasprintf(char **strp, const char *fmt, va_list va) { int rc; char *psz; size_t cb = 1024; *strp = NULL; for (;;) { va_list va2; psz = malloc(cb); if (!psz) return -1; #ifdef va_copy va_copy(va2, va); rc = snprintf(psz, cb, fmt, va2); va_end(vaCopy); #else va2 = va; rc = snprintf(psz, cb, fmt, va2); #endif if (rc < 0 || (size_t)rc < cb) break; cb *= 2; free(psz); } *strp = psz; return rc; } /* * Workaround for directory names with trailing slashes. */ #undef stat int bird_w32_stat(const char *path, struct stat *st) { int rc = stat(path, st); if ( rc != 0 && errno == ENOENT && *path != '\0') { char *slash = strchr(path, '\0') - 1; if (*slash == '/' || *slash == '\\') { size_t len_path = slash - path + 1; char *tmp = alloca(len_path + 4); memcpy(tmp, path, len_path); tmp[len_path] = '.'; tmp[len_path + 1] = '\0'; errno = 0; rc = stat(tmp, st); if ( rc == 0 && !S_ISDIR(st->st_mode)) { errno = ENOTDIR; rc = -1; } } } #ifdef KMK_PRF { int err = errno; fprintf(stderr, "stat(%s,) -> %d/%d\n", path, rc, errno); errno = err; } #endif return rc; } kbuild-2695/src/kmk/kmkbuiltin/mv.c0000644000000000000000000003037612247157307015762 0ustar rootroot/*- * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Ken Smith of The State University of New York at Buffalo. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1989, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)mv.c 8.2 (Berkeley) 4/2/94"; #endif /* not lint */ #endif #if 0 #include __FBSDID("$FreeBSD: src/bin/mv/mv.c,v 1.46 2005/09/05 04:36:08 csjp Exp $"); #endif #include "config.h" #include #ifndef _MSC_VER # ifdef CROSS_DEVICE_MOVE # include # endif # include # include # include # ifndef __HAIKU__ # include # endif #endif #include #include "err.h" #include #include #include #include #include #include #include #include #include #ifndef __HAIKU__ # include #endif #include #include "getopt.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #include "kmkbuiltin.h" static int fflg, iflg, nflg, vflg; static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int do_move(char *, char *); #ifdef CROSS_DEVICE_MOVE static int fastcopy(char *, char *, struct stat *); static int copy(char *, char *); #endif static int usage(FILE *); extern void bsd_strmode(mode_t mode, char *p); #if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__) # ifdef __OS2__ static # endif const char *user_from_uid(uid_t id, int x) { static char s_buf[64]; sprintf(s_buf, "%ld", (long int)id); (void)x; return s_buf; } # ifdef __OS2__ static # endif const char *group_from_gid(gid_t id, int x) { static char s_buf[64]; sprintf(s_buf, "%ld", (long int)id); (void)x; return s_buf; } #endif /* 'not in libc' */ int kmk_builtin_mv(int argc, char *argv[], char **envp) { size_t baselen, len; int rval; char *p, *endp; struct stat sb; int ch; char path[PATH_MAX]; /* kmk: reinitialize globals */ fflg = iflg = nflg = vflg = 0; /* kmk: reset getopt and set progname */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ while ((ch = getopt_long(argc, argv, "finv", long_options, NULL)) != -1) switch (ch) { case 'i': iflg = 1; fflg = nflg = 0; break; case 'f': fflg = 1; iflg = nflg = 0; break; case 'n': nflg = 1; fflg = iflg = 0; break; case 'v': vflg = 1; break; case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); default: return usage(stderr); } argc -= optind; argv += optind; if (argc < 2) return usage(stderr); /* * If the stat on the target fails or the target isn't a directory, * try the move. More than 2 arguments is an error in this case. */ if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) { if (argc > 2) return usage(stderr); return do_move(argv[0], argv[1]); } /* It's a directory, move each file into it. */ if (strlen(argv[argc - 1]) > sizeof(path) - 1) return errx(1, "%s: destination pathname too long", *argv); (void)strcpy(path, argv[argc - 1]); baselen = strlen(path); endp = &path[baselen]; #if defined(_MSC_VER) || defined(__EMX__) if (!baselen || (*(endp - 1) != '/' && *(endp - 1) != '\\' && *(endp - 1) != ':')) { #else if (!baselen || *(endp - 1) != '/') { #endif *endp++ = '/'; ++baselen; } for (rval = 0; --argc; ++argv) { /* * Find the last component of the source pathname. It * may have trailing slashes. */ p = *argv + strlen(*argv); #if defined(_MSC_VER) || defined(__EMX__) while (p != *argv && (p[-1] == '/' || p[-1] == '\\')) --p; while (p != *argv && p[-1] != '/' && p[-1] != '/' && p[-1] != ':') --p; #else while (p != *argv && p[-1] == '/') --p; while (p != *argv && p[-1] != '/') --p; #endif if ((baselen + (len = strlen(p))) >= PATH_MAX) { warnx("%s: destination pathname too long", *argv); rval = 1; } else { memmove(endp, p, (size_t)len + 1); if (do_move(*argv, path)) rval = 1; } } return rval; } static int do_move(char *from, char *to) { struct stat sb; int ask, ch, first; char modep[15]; /* * Check access. If interactive and file exists, ask user if it * should be replaced. Otherwise if file exists but isn't writable * make sure the user wants to clobber it. */ if (!fflg && !access(to, F_OK)) { /* prompt only if source exist */ if (lstat(from, &sb) == -1) { warn("%s", from); return (1); } #define YESNO "(y/n [n]) " ask = 0; if (nflg) { if (vflg) printf("%s not overwritten\n", to); return (0); } else if (iflg) { (void)fprintf(stderr, "overwrite %s? %s", to, YESNO); ask = 1; } else if (access(to, W_OK) && !stat(to, &sb)) { bsd_strmode(sb.st_mode, modep); (void)fprintf(stderr, "override %s%s%s/%s for %s? %s", modep + 1, modep[9] == ' ' ? "" : " ", user_from_uid((unsigned long)sb.st_uid, 0), group_from_gid((unsigned long)sb.st_gid, 0), to, YESNO); ask = 1; } if (ask) { first = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (first != 'y' && first != 'Y') { (void)fprintf(stderr, "not overwritten\n"); return (0); } } } if (!rename(from, to)) { if (vflg) printf("%s -> %s\n", from, to); return (0); } #ifdef _MSC_VER if (errno == EEXIST) { remove(to); if (!rename(from, to)) { if (vflg) printf("%s -> %s\n", from, to); return (0); } } #endif if (errno == EXDEV) { #ifndef CROSS_DEVICE_MOVE warnx("cannot move `%s' to a different device: `%s'", from, to); return (1); #else struct statfs sfs; char path[PATH_MAX]; /* * If the source is a symbolic link and is on another * filesystem, it can be recreated at the destination. */ if (lstat(from, &sb) == -1) { warn("%s", from); return (1); } if (!S_ISLNK(sb.st_mode)) { /* Can't mv(1) a mount point. */ if (realpath(from, path) == NULL) { warnx("cannot resolve %s: %s", from, path); return (1); } if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname)) { warnx("cannot rename a mount point"); return (1); } } #endif } else { warn("rename %s to %s", from, to); return (1); } #ifdef CROSS_DEVICE_MOVE /* * If rename fails because we're trying to cross devices, and * it's a regular file, do the copy internally; otherwise, use * cp and rm. */ if (lstat(from, &sb)) { warn("%s", from); return (1); } return (S_ISREG(sb.st_mode) ? fastcopy(from, to, &sb) : copy(from, to)); #endif } #ifdef CROSS_DEVICE_MOVE int static fastcopy(char *from, char *to, struct stat *sbp) { struct timeval tval[2]; static u_int blen; static char *bp; mode_t oldmode; int nread, from_fd, to_fd; acl_t acl; if ((from_fd = open(from, O_RDONLY, 0)) < 0) { warn("%s", from); return (1); } if (blen < sbp->st_blksize) { if (bp != NULL) free(bp); if ((bp = malloc((size_t)sbp->st_blksize)) == NULL) { blen = 0; warnx("malloc failed"); return (1); } blen = sbp->st_blksize; } while ((to_fd = open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) { if (errno == EEXIST && unlink(to) == 0) continue; warn("%s", to); (void)close(from_fd); return (1); } while ((nread = read(from_fd, bp, (size_t)blen)) > 0) if (write(to_fd, bp, (size_t)nread) != nread) { warn("%s", to); goto err; } if (nread < 0) { warn("%s", from); err: if (unlink(to)) warn("%s: remove", to); (void)close(from_fd); (void)close(to_fd); return (1); } oldmode = sbp->st_mode & ALLPERMS; if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) { warn("%s: set owner/group (was: %lu/%lu)", to, (u_long)sbp->st_uid, (u_long)sbp->st_gid); if (oldmode & (S_ISUID | S_ISGID)) { warnx( "%s: owner/group changed; clearing suid/sgid (mode was 0%03o)", to, oldmode); sbp->st_mode &= ~(S_ISUID | S_ISGID); } } /* * POSIX 1003.2c states that if _POSIX_ACL_EXTENDED is in effect * for dest_file, then it's ACLs shall reflect the ACLs of the * source_file. */ if (fpathconf(to_fd, _PC_ACL_EXTENDED) == 1 && fpathconf(from_fd, _PC_ACL_EXTENDED) == 1) { acl = acl_get_fd(from_fd); if (acl == NULL) warn("failed to get acl entries while setting %s", from); else if (acl_set_fd(to_fd, acl) < 0) warn("failed to set acl entries for %s", to); } (void)close(from_fd); if (fchmod(to_fd, sbp->st_mode)) warn("%s: set mode (was: 0%03o)", to, oldmode); /* * XXX * NFS doesn't support chflags; ignore errors unless there's reason * to believe we're losing bits. (Note, this still won't be right * if the server supports flags and we were trying to *remove* flags * on a file that we copied, i.e., that we didn't create.) */ errno = 0; if (fchflags(to_fd, (u_long)sbp->st_flags)) if (errno != EOPNOTSUPP || sbp->st_flags != 0) warn("%s: set flags (was: 0%07o)", to, sbp->st_flags); tval[0].tv_sec = sbp->st_atime; tval[1].tv_sec = sbp->st_mtime; tval[0].tv_usec = tval[1].tv_usec = 0; if (utimes(to, tval)) warn("%s: set times", to); if (close(to_fd)) { warn("%s", to); return (1); } if (unlink(from)) { warn("%s: remove", from); return (1); } if (vflg) printf("%s -> %s\n", from, to); return (0); } int copy(char *from, char *to) { int pid, status; if ((pid = fork()) == 0) { execl(_PATH_CP, "mv", vflg ? "-PRpv" : "-PRp", "--", from, to, (char *)NULL); warn("%s", _PATH_CP); _exit(1); } if (waitpid(pid, &status, 0) == -1) { warn("%s: waitpid", _PATH_CP); return (1); } if (!WIFEXITED(status)) { warnx("%s: did not terminate normally", _PATH_CP); return (1); } if (WEXITSTATUS(status)) { warnx("%s: terminated with %d (non-zero) status", _PATH_CP, WEXITSTATUS(status)); return (1); } if (!(pid = vfork())) { execl(_PATH_RM, "mv", "-rf", "--", from, (char *)NULL); warn("%s", _PATH_RM); _exit(1); } if (waitpid(pid, &status, 0) == -1) { warn("%s: waitpid", _PATH_RM); return (1); } if (!WIFEXITED(status)) { warnx("%s: did not terminate normally", _PATH_RM); return (1); } if (WEXITSTATUS(status)) { warnx("%s: terminated with %d (non-zero) status", _PATH_RM, WEXITSTATUS(status)); return (1); } return (0); } #endif /* CROSS_DEVICE_MOVE */ static int usage(FILE *pf) { fprintf(pf, "usage: %s [-f | -i | -n] [-v] source target\n" " or: %s [-f | -i | -n] [-v] source ... directory\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname, g_progname); return EX_USAGE; } kbuild-2695/src/kmk/kmkbuiltin/kbuild_version.c0000644000000000000000000000344612247157306020354 0ustar rootroot/* $Id: kbuild_version.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * kbuild_version(), helper function. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include "kmkbuiltin.h" #include #include /** * Prints the kBuild version message and returns 0. * * @returns 0 * @param argv0 The argv0. */ int kbuild_version(const char *argv0) { const char *tmp; /* skip the path */ for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:")) argv0 = tmp + 1; /* find the end, ignoring extenions */ tmp = strrchr(argv0, '.'); if (!tmp) tmp = strchr(argv0, '\0'); printf("%.*s - kBuild version %d.%d.%d (r%u)\n", (int)(tmp - argv0), argv0, KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; } kbuild-2695/src/kmk/kmkbuiltin/chmod.c0000644000000000000000000001553312247157307016430 0ustar rootroot/*- * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1989, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)chmod.c 8.8 (Berkeley) 4/1/94"; #endif /* not lint */ #endif /*#include */ /*__FBSDID("$FreeBSD: src/bin/chmod/chmod.c,v 1.33 2005/01/10 08:39:20 imp Exp $");*/ #include "config.h" #include #include #include "err.h" #include #include #include #include #include #include #ifndef _MSC_VER # include #else # include "mscfakes.h" #endif #ifdef __sun__ # include "solfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #include "getopt.h" #include "kmkbuiltin.h" extern void * bsd_setmode(const char *p); extern mode_t bsd_getmode(const void *bbox, mode_t omode); extern void bsd_strmode(mode_t mode, char *p); #if (defined(__APPLE__) && !defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) || defined(__OpenBSD__) extern int lchmod(const char *, mode_t); #endif static int usage(FILE *); static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; int kmk_builtin_chmod(int argc, char *argv[], char **envp) { FTS *ftsp; FTSENT *p; mode_t *set; int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval; int vflag; char *mode; mode_t newmode; int (*change_mode)(const char *, mode_t); /* kmk: reset getopt and set progname */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ set = NULL; Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; while ((ch = getopt_long(argc, argv, "HLPRXfghorstuvwx", long_options, NULL)) != -1) switch (ch) { case 'H': Hflag = 1; Lflag = 0; break; case 'L': Lflag = 1; Hflag = 0; break; case 'P': Hflag = Lflag = 0; break; case 'R': Rflag = 1; break; case 'f': fflag = 1; break; case 'h': /* * In System V (and probably POSIX.2) the -h option * causes chmod to change the mode of the symbolic * link. 4.4BSD's symbolic links didn't have modes, * so it was an undocumented noop. In FreeBSD 3.0, * lchmod(2) is introduced and this option does real * work. */ hflag = 1; break; /* * XXX * "-[rwx]" are valid mode commands. If they are the entire * argument, getopt has moved past them, so decrement optind. * Regardless, we're done argument processing. */ case 'g': case 'o': case 'r': case 's': case 't': case 'u': case 'w': case 'X': case 'x': if (argv[optind - 1][0] == '-' && argv[optind - 1][1] == ch && argv[optind - 1][2] == '\0') --optind; goto done; case 'v': vflag++; break; case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(stderr); } done: argv += optind; argc -= optind; if (argc < 2) return usage(stderr); if (Rflag) { fts_options = FTS_PHYSICAL; if (hflag) return errx(1, "the -R and -h options may not be specified together."); if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } } else fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL; if (hflag) change_mode = lchmod; else change_mode = chmod; mode = *argv; if ((set = bsd_setmode(mode)) == NULL) return errx(1, "invalid file mode: %s", mode); if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) return err(1, "fts_open"); for (rval = 0; (p = fts_read(ftsp)) != NULL;) { switch (p->fts_info) { case FTS_D: /* Change it at FTS_DP. */ if (!Rflag) fts_set(ftsp, p, FTS_SKIP); continue; case FTS_DNR: /* Warn, chmod, continue. */ warnx("fts: %s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; break; case FTS_ERR: /* Warn, continue. */ case FTS_NS: warnx("fts: %s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; continue; case FTS_SL: /* Ignore. */ case FTS_SLNONE: /* * The only symlinks that end up here are ones that * don't point to anything and ones that we found * doing a physical walk. */ if (!hflag) continue; /* else */ /* FALLTHROUGH */ default: break; } newmode = bsd_getmode(set, p->fts_statp->st_mode); if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS)) continue; if ((*change_mode)(p->fts_accpath, newmode) && !fflag) { warn("%schmod: %s", hflag ? "l" : "", p->fts_path); rval = 1; } else { if (vflag) { (void)printf("%s", p->fts_path); if (vflag > 1) { char m1[12], m2[12]; bsd_strmode(p->fts_statp->st_mode, m1); bsd_strmode((p->fts_statp->st_mode & S_IFMT) | newmode, m2); (void)printf(": 0%o [%s] -> 0%o [%s]", (unsigned int)p->fts_statp->st_mode, m1, (unsigned int)((p->fts_statp->st_mode & S_IFMT) | newmode), m2); } (void)printf("\n"); } } } if (errno) rval = err(1, "fts_read"); free(set); fts_close(ftsp); return rval; } int usage(FILE *out) { (void)fprintf(out, "usage: %s [-fhv] [-R [-H | -L | -P]] mode file ...\n" " or: %s --version\n" " or: %s --help\n", g_progname, g_progname, g_progname); return 1; } kbuild-2695/src/kmk/kmkbuiltin/append.c0000644000000000000000000001636112247157306016604 0ustar rootroot/* $Id: append.c 2466 2011-07-12 09:52:39Z bird $ */ /** @file * kMk Builtin command - append text to file. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #ifndef kmk_builtin_append # include "make.h" # include "filedef.h" # include "variable.h" #else # include "config.h" #endif #include #include #ifdef HAVE_ALLOCA_H # include #endif #include "err.h" #include "kmkbuiltin.h" /** * Prints the usage and return 1. */ static int usage(FILE *pf) { fprintf(pf, "usage: %s [-dcnNtv] file [string ...]\n" " or: %s --version\n" " or: %s --help\n" "\n" "Options:\n" " -d Enclose the output in define ... endef, taking the name from\n" " the first argument following the file name.\n" " -c Output the command for specified target(s). [builtin only]\n" " -n Insert a newline between the strings.\n" " -N Suppress the trailing newline.\n" " -t Truncate the file instead of appending\n" " -v Output the value(s) for specified variable(s). [builtin only]\n" , g_progname, g_progname, g_progname); return 1; } /** * Appends text to a textfile, creating the textfile if necessary. */ int kmk_builtin_append(int argc, char **argv, char **envp) { int i; int fFirst; int iFile; FILE *pFile; int fNewline = 0; int fNoTrailingNewline = 0; int fTruncate = 0; int fDefine = 0; int fVariables = 0; int fCommands = 0; g_progname = argv[0]; /* * Parse options. */ i = 1; while (i < argc && argv[i][0] == '-' && argv[i][1] != '\0' /* '-' is a file */ && strchr("-cdnNtv", argv[i][1]) /* valid option char */ ) { char *psz = &argv[i][1]; if (*psz != '-') { do { switch (*psz) { case 'c': if (fVariables) { errx(1, "Option '-c' clashes with '-v'."); return usage(stderr); } #ifndef kmk_builtin_append fCommands = 1; break; #else errx(1, "Option '-c' isn't supported in external mode."); return usage(stderr); #endif case 'd': if (fVariables) { errx(1, "Option '-d' must come before '-v'!"); return usage(stderr); } fDefine = 1; break; case 'n': fNewline = 1; break; case 'N': fNoTrailingNewline = 1; break; case 't': fTruncate = 1; break; case 'v': if (fCommands) { errx(1, "Option '-v' clashes with '-c'."); return usage(stderr); } #ifndef kmk_builtin_append fVariables = 1; break; #else errx(1, "Option '-v' isn't supported in external mode."); return usage(stderr); #endif default: errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]); return usage(stderr); } } while (*++psz); } else if (!strcmp(psz, "-help")) { usage(stdout); return 0; } else if (!strcmp(psz, "-version")) return kbuild_version(argv[0]); else break; i++; } if (i + fDefine >= argc) { if (i <= argc) errx(1, "missing filename!"); else errx(1, "missing define name!"); return usage(stderr); } /* * Open the output file. */ iFile = i; pFile = fopen(argv[i], fTruncate ? "w" : "a"); if (!pFile) return err(1, "failed to open '%s'", argv[i]); /* * Start define? */ if (fDefine) { i++; fprintf(pFile, "define %s\n", argv[i]); } /* * Append the argument strings to the file */ fFirst = 1; for (i++; i < argc; i++) { const char *psz = argv[i]; size_t cch = strlen(psz); if (!fFirst) fputc(fNewline ? '\n' : ' ', pFile); #ifndef kmk_builtin_append if (fCommands) { char *pszOldBuf; unsigned cchOldBuf; char *pchEnd; install_variable_buffer(&pszOldBuf, &cchOldBuf); pchEnd = func_commands(variable_buffer, &argv[i], "commands"); fwrite(variable_buffer, 1, pchEnd - variable_buffer, pFile); restore_variable_buffer(pszOldBuf, cchOldBuf); } else if (fVariables) { struct variable *pVar = lookup_variable(psz, cch); if (!pVar) continue; if ( pVar->recursive && memchr(pVar->value, '$', pVar->value_length)) { char *pszExpanded = allocated_variable_expand(pVar->value); fwrite(pszExpanded, 1, strlen(pszExpanded), pFile); free(pszExpanded); } else fwrite(pVar->value, 1, pVar->value_length, pFile); } else #endif fwrite(psz, 1, cch, pFile); fFirst = 0; } /* * End the define? */ if (fDefine) { if (fFirst) fwrite("\nendef", 1, sizeof("\nendef") - 1, pFile); else fwrite("endef", 1, sizeof("endef") - 1, pFile); } /* * Add the final newline (unless supressed) and close the file. */ if ( ( !fNoTrailingNewline && fputc('\n', pFile) == EOF) || ferror(pFile)) { fclose(pFile); return errx(1, "error writing to '%s'!", argv[iFile]); } if (fclose(pFile)) return err(1, "failed to fclose '%s'!", argv[iFile]); return 0; } kbuild-2695/src/kmk/kmkbuiltin/err.c0000644000000000000000000000427412247157306016125 0ustar rootroot/* $Id: err.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * Override err.h so we get the program name right. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include "err.h" /** The current program name. */ const char *g_progname = "kmk"; int err(int eval, const char *fmt, ...) { va_list args; int error = errno; fprintf(stderr, "%s: ", g_progname); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, ": %s\n", strerror(error)); return eval; } int errx(int eval, const char *fmt, ...) { va_list args; fprintf(stderr, "%s: ", g_progname); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n"); return eval; } void warn(const char *fmt, ...) { int error = errno; va_list args; fprintf(stderr, "%s: ", g_progname); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, ": %s\n", strerror(error)); } void warnx(const char *fmt, ...) { va_list args; fprintf(stderr, "%s: ", g_progname); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n"); } kbuild-2695/src/kmk/kmkbuiltin/osdep.c0000644000000000000000000000233012247157307016437 0ustar rootroot/* $Id: osdep.c 2656 2012-09-10 20:39:16Z bird $ */ /** @file * Include all the OS dependent bits when bootstrapping. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #include /** @todo replace this by proper configure.in tests. */ #if defined(_MSC_VER) # include "mscfakes.c" # include "fts.c" #elif defined(__sun__) # include "solfakes.c" # include "fts.c" #elif defined(__APPLE__) # include "darwin.c" #elif defined(__OpenBSD__) # include "openbsd.c" #elif defined(__HAIKU__) # include "haikufakes.c" #endif kbuild-2695/src/kmk/kmkbuiltin/setmode.c0000644000000000000000000002667212247157307017004 0ustar rootroot/* $NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $ */ /* * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Dave Borman at Cray Research, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*#include */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94"; #else __RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $"); #endif #endif /* LIBC_SCCS and not lint */ /*#include "namespace.h"*/ #include "config.h" #include #include #include #include #include #include #include #ifndef _MSC_VER #include #else #include "mscfakes.h" #endif #ifdef SETMODE_DEBUG #include #endif /*#ifdef __weak_alias __weak_alias(getmode,_getmode) __weak_alias(setmode,_setmode) #endif*/ #define SET_LEN 6 /* initial # of bitcmd struct to malloc */ #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */ typedef struct bitcmd { char cmd; char cmd2; mode_t bits; } BITCMD; #define CMD2_CLR 0x01 #define CMD2_SET 0x02 #define CMD2_GBITS 0x04 #define CMD2_OBITS 0x08 #define CMD2_UBITS 0x10 static BITCMD *addcmd(BITCMD *, int, int, int, u_int); static void compress_mode(BITCMD *); #ifdef SETMODE_DEBUG static void dumpmode(BITCMD *); #endif #ifndef _DIAGASSERT # define _DIAGASSERT assert #endif #ifndef S_ISTXT # ifdef S_ISVTX # define S_ISTXT S_ISVTX # else # define S_ISTXT 0 # endif #endif /* !S_ISTXT */ /* * Given the old mode and an array of bitcmd structures, apply the operations * described in the bitcmd structures to the old mode, and return the new mode. * Note that there is no '=' command; a strict assignment is just a '-' (clear * bits) followed by a '+' (set bits). */ mode_t bsd_getmode(bbox, omode) const void *bbox; mode_t omode; { const BITCMD *set; mode_t clrval, newmode, value; _DIAGASSERT(bbox != NULL); set = (const BITCMD *)bbox; newmode = omode; for (value = 0;; set++) switch(set->cmd) { /* * When copying the user, group or other bits around, we "know" * where the bits are in the mode so that we can do shifts to * copy them around. If we don't use shifts, it gets real * grundgy with lots of single bit checks and bit sets. */ case 'u': value = (newmode & S_IRWXU) >> 6; goto common; case 'g': value = (newmode & S_IRWXG) >> 3; goto common; case 'o': value = newmode & S_IRWXO; common: if (set->cmd2 & CMD2_CLR) { clrval = (set->cmd2 & CMD2_SET) ? S_IRWXO : value; if (set->cmd2 & CMD2_UBITS) newmode &= ~((clrval<<6) & set->bits); if (set->cmd2 & CMD2_GBITS) newmode &= ~((clrval<<3) & set->bits); if (set->cmd2 & CMD2_OBITS) newmode &= ~(clrval & set->bits); } if (set->cmd2 & CMD2_SET) { if (set->cmd2 & CMD2_UBITS) newmode |= (value<<6) & set->bits; if (set->cmd2 & CMD2_GBITS) newmode |= (value<<3) & set->bits; if (set->cmd2 & CMD2_OBITS) newmode |= value & set->bits; } break; case '+': newmode |= set->bits; break; case '-': newmode &= ~set->bits; break; case 'X': if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH)) newmode |= set->bits; break; case '\0': default: #ifdef SETMODE_DEBUG (void)printf("getmode:%04o -> %04o\n", omode, newmode); #endif return (newmode); } } #define ADDCMD(a, b, c, d) do { \ if (set >= endset) { \ BITCMD *newset; \ setlen += SET_LEN_INCR; \ newset = realloc(saveset, sizeof(BITCMD) * setlen); \ if (newset == NULL) { \ free(saveset); \ return (NULL); \ } \ set = newset + (set - saveset); \ saveset = newset; \ endset = newset + (setlen - 2); \ } \ set = addcmd(set, (a), (b), (c), (d)); \ } while (/*CONSTCOND*/0) #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) void * bsd_setmode(p) const char *p; { int perm, who; char op, *ep; BITCMD *set, *saveset, *endset; #ifndef _MSC_VER sigset_t signset, sigoset; #endif mode_t mask; int equalopdone = 0; /* pacify gcc */ int permXbits, setlen; if (!*p) return (NULL); /* * Get a copy of the mask for the permissions that are mask relative. * Flip the bits, we want what's not set. Since it's possible that * the caller is opening files inside a signal handler, protect them * as best we can. */ #ifndef _MSC_VER sigfillset(&signset); (void)sigprocmask(SIG_BLOCK, &signset, &sigoset); #endif (void)umask(mask = umask(0)); mask = ~mask; #ifndef _MSC_VER (void)sigprocmask(SIG_SETMASK, &sigoset, NULL); #endif setlen = SET_LEN + 2; if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL) return (NULL); saveset = set; endset = set + (setlen - 2); /* * If an absolute number, get it and return; disallow non-octal digits * or illegal bits. */ if (isdigit((unsigned char)*p)) { perm = (mode_t)strtol(p, &ep, 8); if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) { free(saveset); return (NULL); } ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask); set->cmd = 0; return (saveset); } /* * Build list of structures to set/clear/copy bits as described by * each clause of the symbolic mode. */ for (;;) { /* First, find out which bits might be modified. */ for (who = 0;; ++p) { switch (*p) { case 'a': who |= STANDARD_BITS; break; case 'u': who |= S_ISUID|S_IRWXU; break; case 'g': who |= S_ISGID|S_IRWXG; break; case 'o': who |= S_IRWXO; break; default: goto getop; } } getop: if ((op = *p++) != '+' && op != '-' && op != '=') { free(saveset); return (NULL); } if (op == '=') equalopdone = 0; who &= ~S_ISTXT; for (perm = 0, permXbits = 0;; ++p) { switch (*p) { case 'r': perm |= S_IRUSR|S_IRGRP|S_IROTH; break; case 's': /* * If specific bits where requested and * only "other" bits ignore set-id. */ if (who == 0 || (who & ~S_IRWXO)) perm |= S_ISUID|S_ISGID; break; case 't': /* * If specific bits where requested and * only "other" bits ignore set-id. */ if (who == 0 || (who & ~S_IRWXO)) { who |= S_ISTXT; perm |= S_ISTXT; } break; case 'w': perm |= S_IWUSR|S_IWGRP|S_IWOTH; break; case 'X': permXbits = S_IXUSR|S_IXGRP|S_IXOTH; break; case 'x': perm |= S_IXUSR|S_IXGRP|S_IXOTH; break; case 'u': case 'g': case 'o': /* * When ever we hit 'u', 'g', or 'o', we have * to flush out any partial mode that we have, * and then do the copying of the mode bits. */ if (perm) { ADDCMD(op, who, perm, mask); perm = 0; } if (op == '=') equalopdone = 1; if (op == '+' && permXbits) { ADDCMD('X', who, permXbits, mask); permXbits = 0; } ADDCMD(*p, who, op, mask); break; default: /* * Add any permissions that we haven't already * done. */ if (perm || (op == '=' && !equalopdone)) { if (op == '=') equalopdone = 1; ADDCMD(op, who, perm, mask); perm = 0; } if (permXbits) { ADDCMD('X', who, permXbits, mask); permXbits = 0; } goto apply; } } apply: if (!*p) break; if (*p != ',') goto getop; ++p; } set->cmd = 0; #ifdef SETMODE_DEBUG (void)printf("Before compress_mode()\n"); dumpmode(saveset); #endif compress_mode(saveset); #ifdef SETMODE_DEBUG (void)printf("After compress_mode()\n"); dumpmode(saveset); #endif return (saveset); } static BITCMD * addcmd(set, op, who, oparg, mask) BITCMD *set; int oparg, who; int op; u_int mask; { _DIAGASSERT(set != NULL); switch (op) { case '=': set->cmd = '-'; set->bits = who ? who : STANDARD_BITS; set++; op = '+'; /* FALLTHROUGH */ case '+': case '-': case 'X': set->cmd = op; set->bits = (who ? (mode_t)who : mask) & oparg; break; case 'u': case 'g': case 'o': set->cmd = op; if (who) { set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) | ((who & S_IRGRP) ? CMD2_GBITS : 0) | ((who & S_IROTH) ? CMD2_OBITS : 0); set->bits = (mode_t)~0; } else { set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS; set->bits = mask; } if (oparg == '+') set->cmd2 |= CMD2_SET; else if (oparg == '-') set->cmd2 |= CMD2_CLR; else if (oparg == '=') set->cmd2 |= CMD2_SET|CMD2_CLR; break; } return (set + 1); } #ifdef SETMODE_DEBUG static void dumpmode(set) BITCMD *set; { _DIAGASSERT(set != NULL); for (; set->cmd; ++set) (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n", set->cmd, set->bits, set->cmd2 ? " cmd2:" : "", set->cmd2 & CMD2_CLR ? " CLR" : "", set->cmd2 & CMD2_SET ? " SET" : "", set->cmd2 & CMD2_UBITS ? " UBITS" : "", set->cmd2 & CMD2_GBITS ? " GBITS" : "", set->cmd2 & CMD2_OBITS ? " OBITS" : ""); } #endif /* * Given an array of bitcmd structures, compress by compacting consecutive * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u', * 'g' and 'o' commands continue to be separate. They could probably be * compacted, but it's not worth the effort. */ static void compress_mode(set) BITCMD *set; { BITCMD *nset; int setbits, clrbits, Xbits, op; _DIAGASSERT(set != NULL); for (nset = set;;) { /* Copy over any 'u', 'g' and 'o' commands. */ while ((op = nset->cmd) != '+' && op != '-' && op != 'X') { *set++ = *nset++; if (!op) return; } for (setbits = clrbits = Xbits = 0;; nset++) { if ((op = nset->cmd) == '-') { clrbits |= nset->bits; setbits &= ~nset->bits; Xbits &= ~nset->bits; } else if (op == '+') { setbits |= nset->bits; clrbits &= ~nset->bits; Xbits &= ~nset->bits; } else if (op == 'X') Xbits |= nset->bits & ~setbits; else break; } if (clrbits) { set->cmd = '-'; set->cmd2 = 0; set->bits = clrbits; set++; } if (setbits) { set->cmd = '+'; set->cmd2 = 0; set->bits = setbits; set++; } if (Xbits) { set->cmd = 'X'; set->cmd2 = 0; set->bits = Xbits; set++; } } } kbuild-2695/src/kmk/kmkbuiltin/solfakes.c0000644000000000000000000000427512247157307017146 0ustar rootroot/* $Id: solfakes.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * Fake Unix stuff for Solaris. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #include "solfakes.h" int asprintf(char **strp, const char *fmt, ...) { int rc; va_list va; va_start(va, fmt); rc = vasprintf(strp, fmt, va); va_end(va); return rc; } int vasprintf(char **strp, const char *fmt, va_list va) { int rc; char *psz; size_t cb = 1024; *strp = NULL; for (;;) { va_list va2; psz = malloc(cb); if (!psz) return -1; #ifdef va_copy va_copy(va2, va); rc = snprintf(psz, cb, fmt, va2); va_end(va2); #else va2 = va; rc = snprintf(psz, cb, fmt, va2); #endif if (rc < 0 || (size_t)rc < cb) break; cb *= 2; free(psz); } *strp = psz; return rc; } int sol_lchmod(const char *pszPath, mode_t mode) { /* * Weed out symbolic links. */ struct stat s; if ( !lstat(pszPath, &s) && S_ISLNK(s.st_mode)) { errno = -ENOSYS; return -1; } return chmod(pszPath, mode); } kbuild-2695/src/kmk/kmkbuiltin/strmode.c0000644000000000000000000001021712247157307017005 0ustar rootroot/* $NetBSD: strmode.c,v 1.16 2004/06/20 22:20:15 jmc Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*#include */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94"; #else __RCSID("$NetBSD: strmode.c,v 1.16 2004/06/20 22:20:15 jmc Exp $"); #endif #endif /* LIBC_SCCS and not lint */ #include "config.h" /*#include "namespace.h"*/ #include #include #include #ifndef _MSC_VER #include #else #include "mscfakes.h" #endif #ifndef _DIAGASSERT #define _DIAGASSERT assert #endif void bsd_strmode(mode, p) mode_t mode; char *p; { _DIAGASSERT(p != NULL); /* print type */ switch (mode & S_IFMT) { case S_IFDIR: /* directory */ *p++ = 'd'; break; case S_IFCHR: /* character special */ *p++ = 'c'; break; #ifdef S_IFBLK case S_IFBLK: /* block special */ *p++ = 'b'; break; #endif case S_IFREG: /* regular */ #ifdef S_ARCH2 if ((mode & S_ARCH2) != 0) { *p++ = 'A'; } else if ((mode & S_ARCH1) != 0) { *p++ = 'a'; } else { #endif *p++ = '-'; #ifdef S_ARCH2 } #endif break; #ifdef S_IFLNK case S_IFLNK: /* symbolic link */ *p++ = 'l'; break; #endif #ifdef S_IFSOCK case S_IFSOCK: /* socket */ *p++ = 's'; break; #endif #ifdef S_IFIFO case S_IFIFO: /* fifo */ *p++ = 'p'; break; #endif #ifdef S_IFWHT case S_IFWHT: /* whiteout */ *p++ = 'w'; break; #endif #ifdef S_IFDOOR case S_IFDOOR: /* door */ *p++ = 'D'; break; #endif default: /* unknown */ *p++ = '?'; break; } /* usr */ if (mode & S_IRUSR) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWUSR) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXUSR | S_ISUID)) { case 0: *p++ = '-'; break; case S_IXUSR: *p++ = 'x'; break; case S_ISUID: *p++ = 'S'; break; case S_IXUSR | S_ISUID: *p++ = 's'; break; } /* group */ if (mode & S_IRGRP) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWGRP) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXGRP | S_ISGID)) { case 0: *p++ = '-'; break; case S_IXGRP: *p++ = 'x'; break; case S_ISGID: *p++ = 'S'; break; case S_IXGRP | S_ISGID: *p++ = 's'; break; } /* other */ if (mode & S_IROTH) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWOTH) *p++ = 'w'; else *p++ = '-'; #ifdef S_ISVTX switch (mode & (S_IXOTH | S_ISVTX)) { #else switch (mode & (S_IXOTH)) { #endif case 0: *p++ = '-'; break; case S_IXOTH: *p++ = 'x'; break; #ifdef S_ISVTX case S_ISVTX: *p++ = 'T'; break; case S_IXOTH | S_ISVTX: *p++ = 't'; break; #endif } *p++ = ' '; /* will be a '+' if ACL's implemented */ *p = '\0'; } kbuild-2695/src/kmk/kmkbuiltin/kbuild_protection.h0000644000000000000000000000405312247157307021056 0ustar rootroot/* $Id: kbuild_protection.h 2413 2010-09-11 17:43:04Z bird $ */ /** @file * Simple File Protection. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifndef ___kbuild_protection_h #define ___kbuild_protection_h /** * The different protection types. */ typedef enum { KBUILDPROTECTIONTYPE_FIRST = 0, KBUILDPROTECTIONTYPE_RECURSIVE = KBUILDPROTECTIONTYPE_FIRST, KBUILDPROTECTIONTYPE_FULL, KBUILDPROTECTIONTYPE_MAX } KBUILDPROTECTIONTYPE; /** * The instance data. * Don't touch. */ typedef struct KBUILDPROTECTION { unsigned int uMagic; unsigned int cProtectionDepth; unsigned char afTypes[KBUILDPROTECTIONTYPE_MAX]; } KBUILDPROTECTION; typedef KBUILDPROTECTION *PKBUILDPROTECTION; typedef const KBUILDPROTECTION *PCKBUILDPROTECTION; void kBuildProtectionInit(PKBUILDPROTECTION pThis); void kBuildProtectionTerm(PKBUILDPROTECTION pThis); int kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix); void kBuildProtectionEnable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType); void kBuildProtectionDisable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType); int kBuildProtectionSetDepth(PKBUILDPROTECTION pThis, const char *pszValue); int kBuildProtectionEnforce(PCKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType, const char *pszPath); int kBuildProtectionDefaultDepth(void); #endif kbuild-2695/src/kmk/kmkbuiltin/fts.c0000644000000000000000000010176212247157307016132 0ustar rootroot/* $NetBSD: __fts13.c,v 1.44 2005/01/19 00:59:48 mycroft Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif /*#include */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; #else __RCSID("$NetBSD: __fts13.c,v 1.44 2005/01/19 00:59:48 mycroft Exp $"); #endif #endif /* LIBC_SCCS and not lint */ #include "config.h" /*#include "namespace.h"*/ #ifndef _MSC_VER #include #endif #include #include #include #include #include #include "ftsfake.h" #include #include #include #ifdef HAVE_ALLOCA_H # include #endif #ifdef __sun__ # include "solfakes.h" # ifndef __XOPEN_OR_POSIX # define dirfd(dir) ((dir)->dd_fd) #else # define dirfd(dir) ((dir)->d_fd) #endif #endif #ifdef _MSC_VER # include "mscfakes.h" # define dirfd(dir) -1 #endif #if ! HAVE_NBTOOL_CONFIG_H # if !defined(__sun__) && !defined(__gnu_linux__) && !defined(__HAIKU__) # define HAVE_STRUCT_DIRENT_D_NAMLEN 1 # endif #endif #if 0 #ifdef __weak_alias #ifdef __LIBC12_SOURCE__ __weak_alias(fts_children,_fts_children) __weak_alias(fts_close,_fts_close) __weak_alias(fts_open,_fts_open) __weak_alias(fts_read,_fts_read) __weak_alias(fts_set,_fts_set) #endif /* __LIBC12_SOURCE__ */ #endif /* __weak_alias */ #endif #ifdef __LIBC12_SOURCE__ #define STAT stat12 #else #define STAT stat #endif #ifdef __LIBC12_SOURCE__ __warn_references(fts_children, "warning: reference to compatibility fts_children();" " include for correct reference") __warn_references(fts_close, "warning: reference to compatibility fts_close();" " include for correct reference") __warn_references(fts_open, "warning: reference to compatibility fts_open();" " include for correct reference") __warn_references(fts_read, "warning: reference to compatibility fts_read();" " include for correct reference") __warn_references(fts_set, "warning: reference to compatibility fts_set();" " include for correct reference") #endif static FTSENT *fts_alloc(FTS *, const char *, size_t); static FTSENT *fts_build(FTS *, int); static void fts_lfree(FTSENT *); static void fts_load(FTS *, FTSENT *); static size_t fts_maxarglen(char * const *); static size_t fts_pow2(size_t); static int fts_palloc(FTS *, size_t); static void fts_padjust(FTS *, FTSENT *); static FTSENT *fts_sort(FTS *, FTSENT *, size_t); static u_short fts_stat(FTS *, FTSENT *, int); static int fts_safe_changedir(const FTS *, const FTSENT *, int, const char *); #ifdef _MSC_VER #undef HAVE_STRUCT_DIRENT_D_NAMLEN #undef HAVE_FCHDIR #endif #if defined(__EMX__) || defined(_MSC_VER) # define NEED_STRRSLASH # define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' ) #else # define HAVE_FCHDIR # define IS_SLASH(ch) ( (ch) == '/' ) #endif #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) #define CLR(opt) (sp->fts_options &= ~(opt)) #define ISSET(opt) (sp->fts_options & (opt)) #define SET(opt) (sp->fts_options |= (opt)) #define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path)) #ifdef HAVE_FCHDIR #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) #else #define FCHDIR(sp, rdir) CHDIR(sp, rdir) #endif /* fts_build flags */ #define BCHILD 1 /* fts_children */ #define BNAMES 2 /* fts_children, names only */ #define BREAD 3 /* fts_read */ #ifndef DTF_HIDEW #undef FTS_WHITEOUT #endif #ifndef _DIAGASSERT #define _DIAGASSERT assert #endif FTS * fts_open(argv, options, compar) char * const *argv; int options; int (*compar)(const FTSENT **, const FTSENT **); { FTS *sp; FTSENT *p, *root; size_t nitems; FTSENT *parent, *tmp = NULL; /* pacify gcc */ size_t len; _DIAGASSERT(argv != NULL); /* Options check. */ if (options & ~FTS_OPTIONMASK) { errno = EINVAL; return (NULL); } /* Allocate/initialize the stream */ if ((sp = malloc((u_int)sizeof(FTS))) == NULL) return (NULL); memset(sp, 0, sizeof(FTS)); sp->fts_compar = compar; sp->fts_options = options; /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ if (ISSET(FTS_LOGICAL)) SET(FTS_NOCHDIR); /* * Start out with 1K of path space, and enough, in any case, * to hold the user's paths. */ if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN))) goto mem1; /* Allocate/initialize root's parent. */ if ((parent = fts_alloc(sp, "", 0)) == NULL) goto mem2; parent->fts_level = FTS_ROOTPARENTLEVEL; /* Allocate/initialize root(s). */ for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) { /* Don't allow zero-length paths. */ if ((len = strlen(*argv)) == 0) { errno = ENOENT; goto mem3; } if ((p = fts_alloc(sp, *argv, len)) == NULL) goto mem3; p->fts_level = FTS_ROOTLEVEL; p->fts_parent = parent; p->fts_accpath = p->fts_name; p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); /* Command-line "." and ".." are real directories. */ if (p->fts_info == FTS_DOT) p->fts_info = FTS_D; /* * If comparison routine supplied, traverse in sorted * order; otherwise traverse in the order specified. */ if (compar) { p->fts_link = root; root = p; } else { p->fts_link = NULL; if (root == NULL) tmp = root = p; else { tmp->fts_link = p; tmp = p; } } } if (compar && nitems > 1) root = fts_sort(sp, root, nitems); /* * Allocate a dummy pointer and make fts_read think that we've just * finished the node before the root(s); set p->fts_info to FTS_INIT * so that everything about the "current" node is ignored. */ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) goto mem3; sp->fts_cur->fts_link = root; sp->fts_cur->fts_info = FTS_INIT; /* * If using chdir(2), grab a file descriptor pointing to dot to insure * that we can get back here; this could be avoided for some paths, * but almost certainly not worth the effort. Slashes, symbolic links, * and ".." are all fairly nasty problems. Note, if we can't get the * descriptor we run anyway, just more slowly. */ if (!ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if ((sp->fts_rfd = open(".", O_RDONLY, 0)) == -1) SET(FTS_NOCHDIR); else if (fcntl(sp->fts_rfd, F_SETFD, FD_CLOEXEC) == -1) { close(sp->fts_rfd); SET(FTS_NOCHDIR); } #else if ((sp->fts_rdir = getcwd(NULL, 0)) != NULL) SET(FTS_NOCHDIR); #endif } return (sp); mem3: fts_lfree(root); free(parent); mem2: free(sp->fts_path); mem1: free(sp); return (NULL); } #ifdef NEED_STRRSLASH static char *strrslash(register char *psz) { register char ch; char *pszLast = NULL; for (; (ch = *psz); psz++) switch (ch) { case '/': case '\\': case ':': pszLast = psz; break; } return pszLast; } #endif static void fts_load(sp, p) FTS *sp; FTSENT *p; { size_t len; char *cp; _DIAGASSERT(sp != NULL); _DIAGASSERT(p != NULL); /* * Load the stream structure for the next traversal. Since we don't * actually enter the directory until after the preorder visit, set * the fts_accpath field specially so the chdir gets done to the right * place and the user can access the first node. From fts_open it's * known that the path will fit. */ len = p->fts_pathlen = p->fts_namelen; memmove(sp->fts_path, p->fts_name, len + 1); #ifdef NEED_STRRSLASH if ((cp = strrslash(p->fts_name)) && (cp != p->fts_name || cp[1])) { #else if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { #endif len = strlen(++cp); memmove(p->fts_name, cp, len + 1); p->fts_namelen = len; } p->fts_accpath = p->fts_path = sp->fts_path; sp->fts_dev = p->fts_dev; } int fts_close(sp) FTS *sp; { FTSENT *freep, *p; int saved_errno = 0; _DIAGASSERT(sp != NULL); /* * This still works if we haven't read anything -- the dummy structure * points to the root list, so we step through to the end of the root * list which has a valid parent pointer. */ if (sp->fts_cur) { #ifndef _MSC_VER if (ISSET(FTS_SYMFOLLOW)) (void)close(sp->fts_cur->fts_symfd); #endif for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { freep = p; p = p->fts_link ? p->fts_link : p->fts_parent; free(freep); } free(p); } /* Free up child linked list, sort array, path buffer. */ if (sp->fts_child) fts_lfree(sp->fts_child); if (sp->fts_array) free(sp->fts_array); free(sp->fts_path); /* Return to original directory, save errno if necessary. */ if (!ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if (fchdir(sp->fts_rfd)) saved_errno = errno; (void)close(sp->fts_rfd); #else if (chdir(sp->fts_rdir)) saved_errno = errno; free(sp->fts_rdir); sp->fts_rdir = NULL; #endif } /* Free up the stream pointer. */ free(sp); /* ISSET() is illegal after this, since the macro touches sp */ /* Set errno and return. */ if (saved_errno) { errno = saved_errno; return (-1); } return (0); } /* * Special case a root of "/" so that slashes aren't appended which would * cause paths to be written as "//foo". */ #define NAPPEND(p) \ (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \ IS_SLASH(p->fts_path[0]) ? 0 : p->fts_pathlen) FTSENT * fts_read(sp) FTS *sp; { FTSENT *p, *tmp; int instr; char *t; int saved_errno; _DIAGASSERT(sp != NULL); /* If finished or unrecoverable error, return NULL. */ if (sp->fts_cur == NULL || ISSET(FTS_STOP)) return (NULL); /* Set current node pointer. */ p = sp->fts_cur; /* Save and zero out user instructions. */ instr = p->fts_instr; p->fts_instr = FTS_NOINSTR; /* Any type of file may be re-visited; re-stat and re-turn. */ if (instr == FTS_AGAIN) { p->fts_info = fts_stat(sp, p, 0); return (p); } /* * Following a symlink -- SLNONE test allows application to see * SLNONE and recover. If indirecting through a symlink, have * keep a pointer to current location. If unable to get that * pointer, follow fails. */ if (instr == FTS_FOLLOW && (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if ((p->fts_symfd = open(".", O_RDONLY, 0)) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; close(p->fts_symfd); } else p->fts_flags |= FTS_SYMFOLLOW; #endif } return (p); } /* Directory in pre-order. */ if (p->fts_info == FTS_D) { /* If skipped or crossed mount point, do post-order visit. */ if (instr == FTS_SKIP || (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { #ifdef HAVE_FCHDIR if (p->fts_flags & FTS_SYMFOLLOW) (void)close(p->fts_symfd); #endif if (sp->fts_child) { fts_lfree(sp->fts_child); sp->fts_child = NULL; } p->fts_info = FTS_DP; return (p); } /* Rebuild if only read the names and now traversing. */ if (sp->fts_child && ISSET(FTS_NAMEONLY)) { CLR(FTS_NAMEONLY); fts_lfree(sp->fts_child); sp->fts_child = NULL; } /* * Cd to the subdirectory. * * If have already read and now fail to chdir, whack the list * to make the names come out right, and set the parent errno * so the application will eventually get an error condition. * Set the FTS_DONTCHDIR flag so that when we logically change * directories back to the parent we don't do a chdir. * * If haven't read do so. If the read fails, fts_build sets * FTS_STOP or the fts_info field of the node. */ if (sp->fts_child) { if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { p->fts_errno = errno; p->fts_flags |= FTS_DONTCHDIR; for (p = sp->fts_child; p; p = p->fts_link) p->fts_accpath = p->fts_parent->fts_accpath; } } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { if (ISSET(FTS_STOP)) return (NULL); return (p); } p = sp->fts_child; sp->fts_child = NULL; goto name; } /* Move to the next node on this level. */ next: tmp = p; if ((p = p->fts_link) != NULL) { free(tmp); /* * If reached the top, return to the original directory, and * load the paths for the next root. */ if (p->fts_level == FTS_ROOTLEVEL) { #ifdef HAVE_FCHDIR if (FCHDIR(sp, sp->fts_rfd)) { #else if (CHDIR(sp, sp->fts_rdir)) { #endif SET(FTS_STOP); return (NULL); } fts_load(sp, p); return (sp->fts_cur = p); } /* * User may have called fts_set on the node. If skipped, * ignore. If followed, get a file descriptor so we can * get back if necessary. */ if (p->fts_instr == FTS_SKIP) goto next; if (p->fts_instr == FTS_FOLLOW) { p->fts_info = fts_stat(sp, p, 1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { #ifdef HAVE_FCHDIR if ((p->fts_symfd = open(".", O_RDONLY, 0)) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; } else if (fcntl(p->fts_symfd, F_SETFD, FD_CLOEXEC) == -1) { p->fts_errno = errno; p->fts_info = FTS_ERR; close(p->fts_symfd); } else p->fts_flags |= FTS_SYMFOLLOW; #endif } p->fts_instr = FTS_NOINSTR; } name: t = sp->fts_path + NAPPEND(p->fts_parent); *t++ = '/'; memmove(t, p->fts_name, (size_t)(p->fts_namelen + 1)); return (sp->fts_cur = p); } /* Move up to the parent node. */ p = tmp->fts_parent; free(tmp); if (p->fts_level == FTS_ROOTPARENTLEVEL) { /* * Done; free everything up and set errno to 0 so the user * can distinguish between error and EOF. */ free(p); errno = 0; return (sp->fts_cur = NULL); } /* Nul terminate the pathname. */ sp->fts_path[p->fts_pathlen] = '\0'; /* * Return to the parent directory. If at a root node or came through * a symlink, go back through the file descriptor. Otherwise, cd up * one directory. */ if (p->fts_level == FTS_ROOTLEVEL) { #ifdef HAVE_FCHDIR if (FCHDIR(sp, sp->fts_rfd)) { #else if (CHDIR(sp, sp->fts_rdir)) { #endif SET(FTS_STOP); return (NULL); } #ifdef HAVE_FCHDIR } else if (p->fts_flags & FTS_SYMFOLLOW) { if (FCHDIR(sp, p->fts_symfd)) { saved_errno = errno; (void)close(p->fts_symfd); errno = saved_errno; SET(FTS_STOP); return (NULL); } (void)close(p->fts_symfd); #else (void)saved_errno; #endif } else if (!(p->fts_flags & FTS_DONTCHDIR) && fts_safe_changedir(sp, p->fts_parent, -1, "..")) { SET(FTS_STOP); return (NULL); } p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; return (sp->fts_cur = p); } /* * Fts_set takes the stream as an argument although it's not used in this * implementation; it would be necessary if anyone wanted to add global * semantics to fts using fts_set. An error return is allowed for similar * reasons. */ /* ARGSUSED */ int fts_set(sp, p, instr) FTS *sp; FTSENT *p; int instr; { _DIAGASSERT(sp != NULL); _DIAGASSERT(p != NULL); if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW && instr != FTS_NOINSTR && instr != FTS_SKIP) { errno = EINVAL; return (1); } p->fts_instr = instr; return (0); } FTSENT * fts_children(sp, instr) FTS *sp; int instr; { FTSENT *p; #ifdef HAVE_FCHDIR int fd; #else char *pszRoot; int rc; #endif _DIAGASSERT(sp != NULL); if (instr && instr != FTS_NAMEONLY) { errno = EINVAL; return (NULL); } /* Set current node pointer. */ p = sp->fts_cur; /* * Errno set to 0 so user can distinguish empty directory from * an error. */ errno = 0; /* Fatal errors stop here. */ if (ISSET(FTS_STOP)) return (NULL); /* Return logical hierarchy of user's arguments. */ if (p->fts_info == FTS_INIT) return (p->fts_link); /* * If not a directory being visited in pre-order, stop here. Could * allow FTS_DNR, assuming the user has fixed the problem, but the * same effect is available with FTS_AGAIN. */ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) return (NULL); /* Free up any previous child list. */ if (sp->fts_child) fts_lfree(sp->fts_child); if (instr == FTS_NAMEONLY) { SET(FTS_NAMEONLY); instr = BNAMES; } else instr = BCHILD; /* * If using chdir on a relative path and called BEFORE fts_read does * its chdir to the root of a traversal, we can lose -- we need to * chdir into the subdirectory, and we don't know where the current * directory is, so we can't get back so that the upcoming chdir by * fts_read will work. */ if (p->fts_level != FTS_ROOTLEVEL || IS_SLASH(p->fts_accpath[0]) || ISSET(FTS_NOCHDIR)) return (sp->fts_child = fts_build(sp, instr)); #ifdef HAVE_FCHDIR if ((fd = open(".", O_RDONLY, 0)) == -1) #else if ((pszRoot = getcwd(NULL, 0)) == NULL) #endif return (sp->fts_child = NULL); sp->fts_child = fts_build(sp, instr); #ifdef HAVE_FCHDIR if (fchdir(fd)) { (void)close(fd); return (NULL); } (void)close(fd); #else rc = chdir(pszRoot); free(pszRoot); if (rc) return (NULL); #endif return (sp->fts_child); } /* * This is the tricky part -- do not casually change *anything* in here. The * idea is to build the linked list of entries that are used by fts_children * and fts_read. There are lots of special cases. * * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is * set and it's a physical walk (so that symbolic links can't be directories), * we can do things quickly. First, if it's a 4.4BSD file system, the type * of the file is in the directory entry. Otherwise, we assume that the number * of subdirectories in a node is equal to the number of links to the parent. * The former skips all stat calls. The latter skips stat calls in any leaf * directories and for any files after the subdirectories in the directory have * been found, cutting the stat calls by about 2/3. */ static FTSENT * fts_build(sp, type) FTS *sp; int type; { struct dirent *dp; FTSENT *p, *head; size_t nitems; FTSENT *cur, *tail; DIR *dirp; int adjust, cderrno, descend, len, level, nlinks, saved_errno, nostat; size_t maxlen; #ifdef FTS_WHITEOUT int oflag; #endif char *cp = NULL; /* pacify gcc */ _DIAGASSERT(sp != NULL); /* Set current node pointer. */ cur = sp->fts_cur; /* * Open the directory for reading. If this fails, we're done. * If being called from fts_read, set the fts_info field. */ #if defined(FTS_WHITEOUT) && !defined(__OS2__) if (ISSET(FTS_WHITEOUT)) oflag = DTF_NODUP|DTF_REWIND; else oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; #else #define __opendir2(path, flag) opendir(path) #endif if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { if (type == BREAD) { cur->fts_info = FTS_DNR; cur->fts_errno = errno; } return (NULL); } /* * Nlinks is the number of possible entries of type directory in the * directory if we're cheating on stat calls, 0 if we're not doing * any stat calls at all, -1 if we're doing stats on everything. */ if (type == BNAMES) { nlinks = 0; nostat = 1; } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); nostat = 1; } else { nlinks = -1; nostat = 0; } #ifdef notdef (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); #endif /* * If we're going to need to stat anything or we want to descend * and stay in the directory, chdir. If this fails we keep going, * but set a flag so we don't chdir after the post-order visit. * We won't be able to stat anything, but we can still return the * names themselves. Note, that since fts_read won't be able to * chdir into the directory, it will have to return different path * names than before, i.e. "a/b" instead of "b". Since the node * has already been visited in pre-order, have to wait until the * post-order visit to return the error. There is a special case * here, if there was nothing to stat then it's not an error to * not be able to stat. This is all fairly nasty. If a program * needed sorted entries or stat information, they had better be * checking FTS_NS on the returned nodes. */ cderrno = 0; if (nlinks || type == BREAD) { #ifdef HAVE_FCHDIR if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { #else if (fts_safe_changedir(sp, cur, dirfd(dirp), cur->fts_accpath)) { #endif if (nlinks && type == BREAD) cur->fts_errno = errno; cur->fts_flags |= FTS_DONTCHDIR; descend = 0; cderrno = errno; } else descend = 1; } else descend = 0; /* * Figure out the max file name length that can be stored in the * current path -- the inner loop allocates more path as necessary. * We really wouldn't have to do the maxlen calculations here, we * could do them in fts_read before returning the path, but it's a * lot easier here since the length is part of the dirent structure. * * If not changing directories set a pointer so that can just append * each new name into the path. */ len = NAPPEND(cur); if (ISSET(FTS_NOCHDIR)) { cp = sp->fts_path + len; *cp++ = '/'; } len++; maxlen = sp->fts_pathlen - len; level = cur->fts_level + 1; /* Read the directory, attaching each entry to the `link' pointer. */ adjust = 0; for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)) != NULL;) { size_t dlen; if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) continue; #if HAVE_STRUCT_DIRENT_D_NAMLEN dlen = dp->d_namlen; #else dlen = strlen(dp->d_name); #endif if ((p = fts_alloc(sp, dp->d_name, dlen)) == NULL) goto mem1; if (dlen >= maxlen) { /* include space for NUL */ if (fts_palloc(sp, len + dlen + 1)) { /* * No more memory for path or structures. Save * errno, free up the current structure and the * structures already allocated. */ mem1: saved_errno = errno; if (p) free(p); fts_lfree(head); (void)closedir(dirp); errno = saved_errno; cur->fts_info = FTS_ERR; SET(FTS_STOP); return (NULL); } adjust = 1; if (ISSET(FTS_NOCHDIR)) cp = sp->fts_path + len; maxlen = sp->fts_pathlen - len; } p->fts_pathlen = len + dlen; p->fts_parent = sp->fts_cur; p->fts_level = level; #ifdef FTS_WHITEOUT if (dp->d_type == DT_WHT) p->fts_flags |= FTS_ISW; #endif if (cderrno) { if (nlinks) { p->fts_info = FTS_NS; p->fts_errno = cderrno; } else p->fts_info = FTS_NSOK; p->fts_accpath = cur->fts_accpath; } else if (nlinks == 0 #ifdef DT_DIR || (nostat && dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN) #endif ) { p->fts_accpath = ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; p->fts_info = FTS_NSOK; } else { /* Build a file name for fts_stat to stat. */ if (ISSET(FTS_NOCHDIR)) { p->fts_accpath = p->fts_path; memmove(cp, p->fts_name, (size_t)(p->fts_namelen + 1)); } else p->fts_accpath = p->fts_name; /* Stat it. */ p->fts_info = fts_stat(sp, p, 0); /* Decrement link count if applicable. */ if (nlinks > 0 && (p->fts_info == FTS_D || p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) --nlinks; } /* We walk in directory order so "ls -f" doesn't get upset. */ p->fts_link = NULL; if (head == NULL) head = tail = p; else { tail->fts_link = p; tail = p; } ++nitems; } (void)closedir(dirp); /* * If had to realloc the path, adjust the addresses for the rest * of the tree. */ if (adjust) fts_padjust(sp, head); /* * If not changing directories, reset the path back to original * state. */ if (ISSET(FTS_NOCHDIR)) { if (cp - 1 > sp->fts_path) --cp; *cp = '\0'; } /* * If descended after called from fts_children or after called from * fts_read and nothing found, get back. At the root level we use * the saved fd; if one of fts_open()'s arguments is a relative path * to an empty directory, we wind up here with no other way back. If * can't get back, we're done. */ if (descend && (type == BCHILD || !nitems) && (cur->fts_level == FTS_ROOTLEVEL ? #ifdef HAVE_FCHDIR FCHDIR(sp, sp->fts_rfd) : #else CHDIR(sp, sp->fts_rdir) : #endif fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { cur->fts_info = FTS_ERR; SET(FTS_STOP); return (NULL); } /* If didn't find anything, return NULL. */ if (!nitems) { if (type == BREAD) cur->fts_info = FTS_DP; return (NULL); } /* Sort the entries. */ if (sp->fts_compar && nitems > 1) head = fts_sort(sp, head, nitems); return (head); } static u_short fts_stat(sp, p, follow) FTS *sp; FTSENT *p; int follow; { FTSENT *t; dev_t dev; ino_t ino; struct STAT *sbp, sb; int saved_errno; _DIAGASSERT(sp != NULL); _DIAGASSERT(p != NULL); /* If user needs stat info, stat buffer already allocated. */ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; #ifdef FTS_WHITEOUT /* check for whiteout */ if (p->fts_flags & FTS_ISW) { if (sbp != &sb) { memset(sbp, '\0', sizeof (*sbp)); sbp->st_mode = S_IFWHT; } return (FTS_W); } #endif /* * If doing a logical walk, or application requested FTS_FOLLOW, do * a stat(2). If that fails, check for a non-existent symlink. If * fail, set the errno from the stat call. */ if (ISSET(FTS_LOGICAL) || follow) { if (stat(p->fts_accpath, sbp)) { saved_errno = errno; if (!lstat(p->fts_accpath, sbp)) { errno = 0; return (FTS_SLNONE); } p->fts_errno = saved_errno; goto err; } } else if (lstat(p->fts_accpath, sbp)) { p->fts_errno = errno; err: memset(sbp, 0, sizeof(struct STAT)); return (FTS_NS); } if (S_ISDIR(sbp->st_mode)) { /* * Set the device/inode. Used to find cycles and check for * crossing mount points. Also remember the link count, used * in fts_build to limit the number of stat calls. It is * understood that these fields are only referenced if fts_info * is set to FTS_D. */ dev = p->fts_dev = sbp->st_dev; ino = p->fts_ino = sbp->st_ino; p->fts_nlink = sbp->st_nlink; if (ISDOT(p->fts_name)) return (FTS_DOT); /* * Cycle detection is done by brute force when the directory * is first encountered. If the tree gets deep enough or the * number of symbolic links to directories is high enough, * something faster might be worthwhile. */ #ifdef _MSC_VER if (ino && dev) /** @todo ino emulation on windows... */ #endif for (t = p->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) if (ino == t->fts_ino && dev == t->fts_dev) { p->fts_cycle = t; return (FTS_DC); } return (FTS_D); } if (S_ISLNK(sbp->st_mode)) return (FTS_SL); if (S_ISREG(sbp->st_mode)) return (FTS_F); return (FTS_DEFAULT); } static FTSENT * fts_sort(sp, head, nitems) FTS *sp; FTSENT *head; size_t nitems; { FTSENT **ap, *p; _DIAGASSERT(sp != NULL); _DIAGASSERT(head != NULL); /* * Construct an array of pointers to the structures and call qsort(3). * Reassemble the array in the order returned by qsort. If unable to * sort for memory reasons, return the directory entries in their * current order. Allocate enough space for the current needs plus * 40 so don't realloc one entry at a time. */ if (nitems > sp->fts_nitems) { FTSENT **new; new = realloc(sp->fts_array, sizeof(FTSENT *) * (nitems + 40)); if (new == 0) return (head); sp->fts_array = new; sp->fts_nitems = nitems + 40; } for (ap = sp->fts_array, p = head; p; p = p->fts_link) *ap++ = p; qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), (int (*)(const void *, const void *))sp->fts_compar); for (head = *(ap = sp->fts_array); --nitems; ++ap) ap[0]->fts_link = ap[1]; ap[0]->fts_link = NULL; return (head); } static FTSENT * fts_alloc(sp, name, namelen) FTS *sp; const char *name; size_t namelen; { FTSENT *p; size_t len; _DIAGASSERT(sp != NULL); _DIAGASSERT(name != NULL); #if defined(ALIGNBYTES) && defined(ALIGN) /* * The file name is a variable length array and no stat structure is * necessary if the user has set the nostat bit. Allocate the FTSENT * structure, the file name and the stat structure in one chunk, but * be careful that the stat structure is reasonably aligned. Since the * fts_name field is declared to be of size 1, the fts_name pointer is * namelen + 2 before the first possible address of the stat structure. */ len = sizeof(FTSENT) + namelen; if (!ISSET(FTS_NOSTAT)) len += sizeof(struct STAT) + ALIGNBYTES; if ((p = malloc(len)) == NULL) return (NULL); if (!ISSET(FTS_NOSTAT)) p->fts_statp = (struct STAT *)ALIGN((u_long)(p->fts_name + namelen + 2)); #else (void)len; if ((p = malloc(sizeof(FTSENT) + namelen)) == NULL) return (NULL); if (!ISSET(FTS_NOSTAT)) if ((p->fts_statp = malloc(sizeof(struct STAT))) == NULL) { free(p); return (NULL); } #endif /* Copy the name plus the trailing NULL. */ memmove(p->fts_name, name, namelen + 1); p->fts_namelen = namelen; p->fts_path = sp->fts_path; p->fts_errno = 0; p->fts_flags = 0; p->fts_instr = FTS_NOINSTR; p->fts_number = 0; p->fts_pointer = NULL; return (p); } static void fts_lfree(head) FTSENT *head; { FTSENT *p; /* XXX: head may be NULL ? */ /* Free a linked list of structures. */ while ((p = head) != NULL) { head = head->fts_link; #if !defined(ALIGNBYTES) || !defined(ALIGN) if (p->fts_statp) free(p->fts_statp); #endif free(p); } } static size_t fts_pow2(x) size_t x; { x--; x |= x>>1; x |= x>>2; x |= x>>4; x |= x>>8; x |= x>>16; #if LONG_BIT > 32 x |= x>>32; #endif #if LONG_BIT > 64 x |= x>>64; #endif x++; return (x); } /* * Allow essentially unlimited paths; find, rm, ls should all work on any tree. * Most systems will allow creation of paths much longer than MAXPATHLEN, even * though the kernel won't resolve them. Round up the new size to a power of 2, * so we don't realloc the path 2 bytes at a time. */ static int fts_palloc(sp, size) FTS *sp; size_t size; { char *new; _DIAGASSERT(sp != NULL); #if 1 /* Protect against fts_pathlen overflow. */ if (size > USHRT_MAX + 1) { errno = ENOMEM; return (1); } #endif size = fts_pow2(size); new = realloc(sp->fts_path, size); if (new == 0) return (1); sp->fts_path = new; sp->fts_pathlen = size; return (0); } /* * When the path is realloc'd, have to fix all of the pointers in structures * already returned. */ static void fts_padjust(sp, head) FTS *sp; FTSENT *head; { FTSENT *p; char *addr; _DIAGASSERT(sp != NULL); #define ADJUST(p) do { \ if ((p)->fts_accpath != (p)->fts_name) \ (p)->fts_accpath = \ addr + ((p)->fts_accpath - (p)->fts_path); \ (p)->fts_path = addr; \ } while (/*CONSTCOND*/0) addr = sp->fts_path; /* Adjust the current set of children. */ for (p = sp->fts_child; p; p = p->fts_link) ADJUST(p); /* Adjust the rest of the tree, including the current level. */ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { ADJUST(p); p = p->fts_link ? p->fts_link : p->fts_parent; } } static size_t fts_maxarglen(argv) char * const *argv; { size_t len, max; _DIAGASSERT(argv != NULL); for (max = 0; *argv; ++argv) if ((len = strlen(*argv)) > max) max = len; return (max + 1); } /* * Change to dir specified by fd or p->fts_accpath without getting * tricked by someone changing the world out from underneath us. * Assumes p->fts_dev and p->fts_ino are filled in. */ static int fts_safe_changedir(sp, p, fd, path) const FTS *sp; const FTSENT *p; int fd; const char *path; { int oldfd = fd, ret = -1; struct STAT sb; if (ISSET(FTS_NOCHDIR)) return 0; #ifdef HAVE_FCHDIR if (oldfd < 0 && (fd = open(path, O_RDONLY)) == -1) return -1; if (fstat(fd, &sb) == -1) goto bail; #else if (stat(path, &sb)) goto bail; #endif if (sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev) { errno = ENOENT; goto bail; } #ifdef HAVE_FCHDIR ret = fchdir(fd); #else ret = chdir(path); #endif bail: #ifdef HAVE_FCHDIR if (oldfd < 0) { int save_errno = errno; (void)close(fd); errno = save_errno; } #endif return ret; } kbuild-2695/src/kmk/kmkbuiltin/darwin.c0000644000000000000000000000314312247157306016613 0ustar rootroot/* $Id: darwin.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * Missing BSD functions on Darwin / Mac OS X. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include int lchmod(const char *path, mode_t mode) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return chmod(path, mode); } int lutimes(const char *path, const struct timeval *tvs) { struct stat st; if (lstat(path, &st)) return -1; if (S_ISLNK(st.st_mode)) return 0; /* pretend success */ return utimes(path, tvs); } kbuild-2695/src/kmk/kmkbuiltin/md5sum.c0000644000000000000000000005540112247157307016546 0ustar rootroot/* $Id: md5sum.c 2414 2010-09-12 18:42:06Z bird $ */ /** @file * md5sum. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #ifdef _MSC_VER # include #else # include #endif #include #include "err.h" #include "kmkbuiltin.h" #include "../../lib/md5.h" /*#define MD5SUM_USE_STDIO*/ /** * Prints the usage and return 1. */ static int usage(FILE *pOut) { fprintf(pOut, "usage: md5sum [-bt] [-o list-file] file(s)\n" " or: md5sum [-btwq] -c list-file(s)\n" " or: md5sum [-btq] -C MD5 file\n" "\n" " -c, --check Check MD5 and files found in the specified list file(s).\n" " The default is to compute MD5 sums of the specified files\n" " and print them to stdout in list form.\n" " -C, --check-file This is followed by an MD5 sum and the file to check.\n" " -b, --binary Read files in binary mode. (default)\n" " -t, --text Read files in text mode.\n" " -p, --progress Show progress indicator on large files.\n" " -o, --output Name of the output list file. Useful with -p.\n" " -q, --status Be quiet.\n" " -w, --warn Ignored. Always warn, unless quiet.\n" " -h, --help This usage info.\n" " -v, --version Show version information and exit.\n" ); return 1; } /** * Makes a string out of the given digest. * * @param pDigest The MD5 digest. * @param pszDigest Where to put the digest string. Must be able to * hold at least 33 bytes. */ static void digest_to_string(unsigned char pDigest[16], char *pszDigest) { unsigned i; for (i = 0; i < 16; i++) { static char s_achDigits[17] = "0123456789abcdef"; pszDigest[i*2] = s_achDigits[(pDigest[i] >> 4)]; pszDigest[i*2 + 1] = s_achDigits[(pDigest[i] & 0xf)]; } pszDigest[i*2] = '\0'; } /** * Attempts to convert a string to a MD5 digest. * * @returns 0 on success, 1-based position of the failure first error. * @param pszDigest The string to interpret. * @param pDigest Where to put the MD5 digest. */ static int string_to_digest(const char *pszDigest, unsigned char pDigest[16]) { unsigned i; unsigned iBase = 1; /* skip blanks */ while ( *pszDigest == ' ' || *pszDigest == '\t' || *pszDigest == '\n' || *pszDigest == '\r') pszDigest++, iBase++; /* convert the digits. */ memset(pDigest, 0, 16); for (i = 0; i < 32; i++, pszDigest++) { int iDigit; if (*pszDigest >= '0' && *pszDigest <= '9') iDigit = *pszDigest - '0'; else if (*pszDigest >= 'a' && *pszDigest <= 'f') iDigit = *pszDigest - 'a' + 10; else if (*pszDigest >= 'A' && *pszDigest <= 'F') iDigit = *pszDigest - 'A' + 10; else return i + iBase; if (i & 1) pDigest[i >> 1] |= iDigit; else pDigest[i >> 1] |= iDigit << 4; } /* the rest of the string must now be blanks. */ while ( *pszDigest == ' ' || *pszDigest == '\t' || *pszDigest == '\n' || *pszDigest == '\r') pszDigest++, i++; return *pszDigest ? i + iBase : 0; } /** * Opens the specified file for md5 sum calculation. * * @returns Opaque pointer on success, NULL and errno on failure. * @param pszFilename The filename. * @param fText Whether text or binary mode should be used. */ static void *open_file(const char *pszFilename, unsigned fText) { #if defined(MD5SUM_USE_STDIO) FILE *pFile; errno = 0; pFile = fopen(pszFilename, fText ? "r" : "rb"); if (!pFile && errno == EINVAL && !fText) pFile = fopen(pszFilename, "r"); return pFile; #else int fd; int fFlags; /* figure out the appropriate flags. */ fFlags = O_RDONLY; #ifdef O_SEQUENTIAL fFlags |= _O_SEQUENTIAL; #elif defined(_O_SEQUENTIAL) fFlags |= _O_SEQUENTIAL; #endif #ifdef O_BINARY if (!fText) fFlags |= O_BINARY; #elif defined(_O_BINARY) if (!fText) fFlags |= _O_BINARY; #endif #ifdef O_TEXT if (fText) fFlags |= O_TEXT; #elif defined(O_TEXT) if (fText) fFlags |= _O_TEXT; #else (void)fText; #endif errno = 0; fd = open(pszFilename, fFlags, 0755); if (fd >= 0) { int *pFd = malloc(sizeof(*pFd)); if (pFd) { *pFd = fd; return pFd; } close(fd); errno = ENOMEM; } return NULL; #endif } /** * Closes a file opened by open_file. * * @param pvFile The opaque pointer returned by open_file. */ static void close_file(void *pvFile) { #if defined(MD5SUM_USE_STDIO) fclose((FILE *)pvFile); #else close(*(int *)pvFile); free(pvFile); #endif } /** * Reads from a file opened by open_file. * * @returns Number of bytes read on success. * 0 on EOF. * Negated errno on read error. * @param pvFile The opaque pointer returned by open_file. * @param pvBuf Where to put the number of read bytes. * @param cbBuf The max number of bytes to read. * Must be less than a INT_MAX. */ static int read_file(void *pvFile, void *pvBuf, size_t cbBuf) { #if defined(MD5SUM_USE_STDIO) int cb; errno = 0; cb = (int)fread(pvBuf, 1, cbBuf, (FILE *)pvFile); if (cb >= 0) return (int)cb; if (!errno) return -EINVAL; return -errno; #else int cb; errno = 0; cb = (int)read(*(int *)pvFile, pvBuf, (int)cbBuf); if (cb >= 0) return (int)cb; if (!errno) return -EINVAL; return -errno; #endif } /** * Gets the size of the file. * This is informational and not necessarily 100% accurate. * * @returns File size. * @param pvFile The opaque pointer returned by open_file */ static double size_file(void *pvFile) { #if defined(_MSC_VER) __int64 cb; # if defined(MD5SUM_USE_STDIO) cb = _filelengthi64(fileno((FILE *)pvFile)); # else cb = _filelengthi64(*(int *)pvFile); # endif if (cb >= 0) return (double)cb; #elif defined(MD5SUM_USE_STDIO) struct stat st; if (!fstat(fileno((FILE *)pvFile), &st)) return st.st_size; #else struct stat st; if (!fstat(*(int *)pvFile, &st)) return st.st_size; #endif return 1024; } /** * Calculates the md5sum of the sepecified file stream. * * @returns errno on failure, 0 on success. * @param pvFile The file stream. * @param pDigest Where to store the MD5 digest. * @param fProgress Whether to show a progress bar. */ static int calc_md5sum(void *pvFile, unsigned char pDigest[16], unsigned fProgress) { int cb; int rc = 0; char abBuf[32*1024]; struct MD5Context Ctx; unsigned uPercent = 0; double cbFile = 0.0; double off = 0.0; if (fProgress) { cbFile = size_file(pvFile); if (cbFile < 1024*1024) fProgress = 0; } MD5Init(&Ctx); for (;;) { /* process a chunk. */ cb = read_file(pvFile, abBuf, sizeof(abBuf)); if (cb > 0) MD5Update(&Ctx, (unsigned char *)&abBuf[0], cb); else if (!cb) break; else { rc = -cb; break; } /* update the progress indicator. */ if (fProgress) { unsigned uNewPercent; off += cb; uNewPercent = (unsigned)((off / cbFile) * 100); if (uNewPercent != uPercent) { if (uPercent) printf("\b\b\b\b"); printf("%3d%%", uNewPercent); fflush(stdout); uPercent = uNewPercent; } } } MD5Final(pDigest, &Ctx); if (fProgress) printf("\b\b\b\b \b\b\b\b"); return rc; } /** * Checks the if the specified digest matches the digest of the file stream. * * @returns 0 on match, -1 on mismatch, errno value (positive) on failure. * @param pvFile The file stream. * @param Digest The MD5 digest. * @param fProgress Whether to show an progress indicator on large files. */ static int check_md5sum(void *pvFile, unsigned char Digest[16], unsigned fProgress) { unsigned char DigestFile[16]; int rc; rc = calc_md5sum(pvFile, DigestFile, fProgress); if (!rc) rc = memcmp(Digest, DigestFile, 16) ? -1 : 0; return rc; } /** * Checks if the specified file matches the given MD5 digest. * * @returns 0 if it matches, 1 if it doesn't or an error occurs. * @param pszFilename The name of the file to check. * @param pszDigest The MD5 digest string. * @param fText Whether to open the file in text or binary mode. * @param fQuiet Whether to go about this in a quiet fashion or not. * @param fProgress Whether to show an progress indicator on large files. */ static int check_one_file(const char *pszFilename, const char *pszDigest, unsigned fText, unsigned fQuiet, unsigned fProgress) { unsigned char Digest[16]; int rc; rc = string_to_digest(pszDigest, Digest); if (!rc) { void *pvFile; pvFile = open_file(pszFilename, fText); if (pvFile) { if (!fQuiet) fprintf(stdout, "%s: ", pszFilename); rc = check_md5sum(pvFile, Digest, fProgress); close_file(pvFile); if (!fQuiet) { fprintf(stdout, "%s\n", !rc ? "OK" : rc < 0 ? "FAILURE" : "ERROR"); fflush(stdout); if (rc > 0) errx(1, "Error reading '%s': %s", pszFilename, strerror(rc)); } if (rc) rc = 1; } else { if (!fQuiet) errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } } else { errx(1, "Malformed MD5 digest '%s'!", pszDigest); errx(1, " %*s^", rc - 1, ""); rc = 1; } return rc; } /** * Checks the specified md5.lst file. * * @returns 0 if all checks out file, 1 if one or more fails or there are read errors. * @param pszFilename The name of the file. * @param fText The default mode, text or binary. Only used when fBinaryTextOpt is true. * @param fBinaryTextOpt Whether a -b or -t option was specified and should be used. * @param fQuiet Whether to be quiet. * @param fProgress Whether to show an progress indicator on large files. */ static int check_files(const char *pszFilename, int fText, int fBinaryTextOpt, int fQuiet, unsigned fProgress) { int rc = 0; FILE *pFile; /* * Try open the md5.lst file and process it line by line. */ pFile = fopen(pszFilename, "r"); if (pFile) { int iLine = 0; char szLine[8192]; while (fgets(szLine, sizeof(szLine), pFile)) { const char *pszDigest; int fLineText; char *psz; int rc2; iLine++; psz = szLine; /* leading blanks */ while (*psz == ' ' || *psz == '\t' || *psz == '\n') psz++; /* skip blank or comment lines. */ if (!*psz || *psz == '#' || *psz == ';' || *psz == '/') continue; /* remove the trailing newline. */ rc2 = (int)strlen(psz); if (psz[rc2 - 1] == '\n') psz[rc2 - (rc2 >= 2 && psz[rc2 - 2] == '\r' ? 2 : 1)] = '\0'; /* skip to the end of the digest and terminate it. */ pszDigest = psz; while (*psz != ' ' && *psz != '\t' && *psz) psz++; if (*psz) { *psz++ = '\0'; /* blanks */ while (*psz == ' ' || *psz == '\t' || *psz == '\n') psz++; /* check for binary asterix */ if (*psz != '*') fLineText = fBinaryTextOpt ? fText : 0; else { fLineText = 0; psz++; } if (*psz) { unsigned char Digest[16]; /* the rest is filename. */ pszFilename = psz; /* * Do the job. */ rc2 = string_to_digest(pszDigest, Digest); if (!rc2) { void *pvFile = open_file(pszFilename, fLineText); if (pvFile) { if (!fQuiet) fprintf(stdout, "%s: ", pszFilename); rc2 = check_md5sum(pvFile, Digest, fProgress); close_file(pvFile); if (!fQuiet) { fprintf(stdout, "%s\n", !rc2 ? "OK" : rc2 < 0 ? "FAILURE" : "ERROR"); fflush(stdout); if (rc2 > 0) errx(1, "Error reading '%s': %s", pszFilename, strerror(rc2)); } if (rc2) rc = 1; } else { if (!fQuiet) errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } } else if (!fQuiet) { errx(1, "%s (%d): Ignoring malformed digest '%s' (digest)", pszFilename, iLine, pszDigest); errx(1, "%s (%d): %*s^", pszFilename, iLine, rc2 - 1, ""); } } else if (!fQuiet) errx(1, "%s (%d): Ignoring malformed line!", pszFilename, iLine); } else if (!fQuiet) errx(1, "%s (%d): Ignoring malformed line!", pszFilename, iLine); } /* while more lines */ fclose(pFile); } else { errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } return rc; } /** * Calculates the MD5 sum for one file and prints it. * * @returns 0 on success, 1 on any kind of failure. * @param pszFilename The file to process. * @param fText The mode to open the file in. * @param fQuiet Whether to be quiet or verbose about errors. * @param fProgress Whether to show an progress indicator on large files. * @param pOutput Where to write the list. Progress is always written to stdout. */ static int md5sum_file(const char *pszFilename, unsigned fText, unsigned fQuiet, unsigned fProgress, FILE *pOutput) { int rc; void *pvFile; /* * Calcuate and print the MD5 sum for one file. */ pvFile = open_file(pszFilename, fText); if (pvFile) { unsigned char Digest[16]; if (fProgress && pOutput) fprintf(stdout, "%s: ", pszFilename); rc = calc_md5sum(pvFile, Digest, fProgress); close_file(pvFile); if (fProgress && pOutput) { size_t cch = strlen(pszFilename) + 2; while (cch-- > 0) fputc('\b', stdout); } if (!rc) { char szDigest[36]; digest_to_string(Digest, szDigest); if (pOutput) { fprintf(pOutput, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename); fflush(pOutput); } fprintf(stdout, "%s %s%s\n", szDigest, fText ? "" : "*", pszFilename); fflush(stdout); } else { if (!fQuiet) errx(1, "Failed to open '%s': %s", pszFilename, strerror(rc)); rc = 1; } } else { if (!fQuiet) errx(1, "Failed to open '%s': %s", pszFilename, strerror(errno)); rc = 1; } return rc; } /** * md5sum, calculates and checks the md5sum of files. * Somewhat similar to the GNU coreutil md5sum command. */ int kmk_builtin_md5sum(int argc, char **argv, char **envp) { int i; int rc = 0; int fText = 0; int fBinaryTextOpt = 0; int fQuiet = 0; int fChecking = 0; int fProgress = 0; int fNoMoreOptions = 0; const char *pszOutput = NULL; FILE *pOutput = NULL; g_progname = argv[0]; /* * Print usage if no arguments. */ if (argc <= 1) return usage(stderr); /* * Process the arguments, FIFO style. */ i = 1; while (i < argc) { char *psz = argv[i]; if (!fNoMoreOptions && psz[0] == '-' && psz[1] == '-' && !psz[2]) fNoMoreOptions = 1; else if (*psz == '-' && !fNoMoreOptions) { psz++; /* convert long options for gnu just for fun */ if (*psz == '-') { if (!strcmp(psz, "-binary")) psz = "b"; else if (!strcmp(psz, "-text")) psz = "t"; else if (!strcmp(psz, "-check")) psz = "c"; else if (!strcmp(psz, "-check-file")) psz = "C"; else if (!strcmp(psz, "-output")) psz = "o"; else if (!strcmp(psz, "-progress")) psz = "p"; else if (!strcmp(psz, "-status")) psz = "q"; else if (!strcmp(psz, "-warn")) psz = "w"; else if (!strcmp(psz, "-help")) psz = "h"; else if (!strcmp(psz, "-version")) psz = "v"; } /* short options */ do { switch (*psz) { case 'c': fChecking = 1; break; case 'b': fText = 0; fBinaryTextOpt = 1; break; case 't': fText = 1; fBinaryTextOpt = 1; break; case 'p': fProgress = 1; break; case 'q': fQuiet = 1; break; case 'w': /* ignored */ break; case 'h': usage(stdout); return 0; case 'v': return kbuild_version(argv[0]); /* * -C md5 file */ case 'C': { const char *pszFilename; const char *pszDigest; if (psz[1]) pszDigest = &psz[1]; else if (i + 1 < argc) pszDigest = argv[++i]; else { errx(1, "'-C' is missing the MD5 sum!"); return 1; } if (i + 1 < argc) pszFilename = argv[++i]; else { errx(1, "'-C' is missing the filename!"); return 1; } rc |= check_one_file(pszFilename, pszDigest, fText, fQuiet, fProgress && !fQuiet); psz = "\0"; break; } /* * Output file. */ case 'o': { if (fChecking) { errx(1, "'-o' cannot be used with -c or -C!"); return 1; } if (psz[1]) pszOutput = &psz[1]; else if (i + 1 < argc) pszOutput = argv[++i]; else { errx(1, "'-o' is missing the file name!"); return 1; } psz = "\0"; break; } default: errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]); return usage(stderr); } } while (*++psz); } else if (fChecking) rc |= check_files(argv[i], fText, fBinaryTextOpt, fQuiet, fProgress && !fQuiet); else { /* lazily open the output if specified. */ if (pszOutput) { if (pOutput) fclose(pOutput); pOutput = fopen(pszOutput, "w"); if (!pOutput) { rc = err(1, "fopen(\"%s\", \"w\") failed", pszOutput); break; } pszOutput = NULL; } rc |= md5sum_file(argv[i], fText, fQuiet, fProgress && !fQuiet, pOutput); } i++; } if (pOutput) fclose(pOutput); return rc; } kbuild-2695/src/kmk/kmkbuiltin/mkdir.c0000644000000000000000000001600012247157307016432 0ustar rootroot/* * Copyright (c) 1983, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1983, 1992, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) 1/25/94"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/bin/mkdir/mkdir.c,v 1.28 2004/04/06 20:06:48 markm Exp $"); #endif #include "config.h" #include #include #include "err.h" #include #ifndef _MSC_VER # include #endif #include #include #include #ifndef __HAIKU__ # include #endif #include #ifdef HAVE_ALLOCA_H # include #endif #include "getopt.h" #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef _MSC_VER # include # include "mscfakes.h" #endif #include "kmkbuiltin.h" static int vflag; static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; extern void * bsd_setmode(const char *p); extern mode_t bsd_getmode(const void *bbox, mode_t omode); static int build(char *, mode_t); static int usage(FILE *); int kmk_builtin_mkdir(int argc, char *argv[], char **envp) { int ch, exitval, success, pflag; mode_t omode, *set = (mode_t *)NULL; char *mode; omode = pflag = 0; mode = NULL; /* reinitialize globals */ vflag = 0; /* kmk: reset getopt and set progname */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ while ((ch = getopt_long(argc, argv, "m:pv", long_options, NULL)) != -1) switch(ch) { case 'm': mode = optarg; break; case 'p': pflag = 1; break; case 'v': vflag = 1; break; case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(stderr); } argc -= optind; argv += optind; if (argv[0] == NULL) return usage(stderr); if (mode == NULL) { omode = S_IRWXU | S_IRWXG | S_IRWXO; } else { if ((set = bsd_setmode(mode)) == NULL) return errx(1, "invalid file mode: %s", mode); omode = bsd_getmode(set, S_IRWXU | S_IRWXG | S_IRWXO); free(set); } for (exitval = 0; *argv != NULL; ++argv) { success = 1; if (pflag) { if (build(*argv, omode)) success = 0; } else if (mkdir(*argv, omode) < 0) { if (errno == ENOTDIR || errno == ENOENT) warn("mkdir: %s", dirname(*argv)); else warn("mkdir: %s", *argv); success = 0; } else if (vflag) (void)printf("%s\n", *argv); if (!success) exitval = 1; /* * The mkdir() and umask() calls both honor only the low * nine bits, so if you try to set a mode including the * sticky, setuid, setgid bits you lose them. Don't do * this unless the user has specifically requested a mode, * as chmod will (obviously) ignore the umask. */ if (success && mode != NULL && chmod(*argv, omode) == -1) { warn("chmod: %s", *argv); exitval = 1; } } return exitval; } static int build(char *path, mode_t omode) { struct stat sb; mode_t numask, oumask; int first, last, retval; char *p; const size_t len = strlen(path); p = alloca(len + 1); path = memcpy(p, path, len + 1); #if defined(_MSC_VER) || defined(__EMX__) /* correct slashes. */ p = strchr(path, '\\'); while (p) { *p++ = '/'; p = strchr(p, '\\'); } #endif p = path; oumask = 0; retval = 0; #if defined(_MSC_VER) || defined(__EMX__) if ( ( (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) && p[1] == ':') p += 2; /* skip the drive letter */ else if ( p[0] == '/' && p[1] == '/' && p[2] != '/') { /* UNC */ p += 2; while (*p && *p != '/') /* server */ p++; while (*p == '/') p++; while (*p && *p != '/') /* share */ p++; } #endif if (p[0] == '/') /* Skip leading '/'. */ ++p; for (first = 1, last = 0; !last ; ++p) { if (p[0] == '\0') last = 1; else if (p[0] != '/') continue; *p = '\0'; if (!last && p[1] == '\0') last = 1; if (first) { /* * POSIX 1003.2: * For each dir operand that does not name an existing * directory, effects equivalent to those cased by the * following command shall occcur: * * mkdir -p -m $(umask -S),u+wx $(dirname dir) && * mkdir [-m mode] dir * * We change the user's umask and then restore it, * instead of doing chmod's. */ oumask = umask(0); numask = oumask & ~(S_IWUSR | S_IXUSR); (void)umask(numask); first = 0; } if (last) (void)umask(oumask); if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) { if (errno == EEXIST || errno == EISDIR || errno == ENOSYS /* (solaris crap) */ || errno == EACCES /* (ditto) */) { if (stat(path, &sb) < 0) { warn("stat: %s", path); retval = 1; break; } else if (!S_ISDIR(sb.st_mode)) { if (last) errno = EEXIST; else errno = ENOTDIR; warn("st_mode: %s", path); retval = 1; break; } } else { warn("mkdir: %s", path); retval = 1; break; } } else if (vflag) printf("%s\n", path); if (!last) *p = '/'; } if (!first && !last) (void)umask(oumask); return (retval); } static int usage(FILE *pf) { fprintf(pf, "usage: %s [-pv] [-m mode] directory ...\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname); return EX_USAGE; } kbuild-2695/src/kmk/kmkbuiltin/solfakes.h0000644000000000000000000000257212247157307017151 0ustar rootroot/* $Id: solfakes.h 2413 2010-09-11 17:43:04Z bird $ */ /** @file * Unix fakes for Solaris. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifndef ___solfakes_h #define ___solfakes_h #ifdef __sun__ #include #include #include "getopt.h" #define _PATH_DEVNULL "/dev/null" #define ALLPERMS 0000777 #define lutimes(path, tvs) utimes(path, tvs) #define lchmod sol_lchmod #define MAX(a,b) ((a) >= (b) ? (a) : (b)) #ifndef USHRT_MAX # define USHRT_MAX 65535 #endif int vasprintf(char **strp, const char *fmt, va_list va); int asprintf(char **strp, const char *fmt, ...); int sol_lchmod(const char *pszPath, mode_t mode); #endif /* __sun__ */ #endif /* ___solfakes_h */ kbuild-2695/src/kmk/kmkbuiltin/cmp.c0000644000000000000000000001025412247157307016110 0ustar rootroot/* $NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $ */ /* * Copyright (c) 1987, 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"); static char sccsid[] = "@(#)cmp.c 8.3 (Berkeley) 4/2/94"; __RCSID("$NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $"); */ #include "config.h" #include #include "err.h" #include #include #include #include #include #ifndef _MSC_VER # include #else # define MSC_DO_64_BIT_IO /* for correct off_t */ # include "mscfakes.h" #endif #include "getopt.h" #include "kmkbuiltin.h" #include "cmp_extern.h" static const struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { 0, 0, 0, 0 }, }; static int usage(FILE *); int kmk_builtin_cmp(int argc, char *argv[], char **envp) { off_t skip1 = 0, skip2 = 0; int lflag = 0, sflag = 0; int ch; char *file1, *file2; #ifdef kmk_builtin_cmp setlocale(LC_ALL, ""); #endif /* reset getopt and set progname. */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ while ((ch = getopt_long(argc, argv, "ls", long_options, NULL)) != -1) { switch (ch) { case 'l': /* print all differences */ lflag = 1; break; case 's': /* silent run */ sflag = 1; break; case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); case '?': default: return usage(stderr); } } argv += optind; argc -= optind; if (argc < 2 || argc > 4) return usage(stderr); file1 = argv[0]; file2 = argv[1]; if (argc > 2) { char *ep; errno = 0; skip1 = strtoll(argv[2], &ep, 0); if (errno || ep == argv[2]) return errx(ERR_EXIT, "strtoll(%s,,) failed", argv[2]); if (argc == 4) { skip2 = strtoll(argv[3], &ep, 0); if (errno || ep == argv[3]) return errx(ERR_EXIT, "strtoll(%s,,) failed", argv[3]); } } return cmp_file_and_file_ex(file1, skip1, file2, skip2, sflag, lflag, 0); } static int usage(FILE *fp) { fprintf(fp, "usage: %s [-l | -s] file1 file2 [skip1 [skip2]]\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname); return ERR_EXIT; } kbuild-2695/src/kmk/kmkbuiltin/err.h0000644000000000000000000000211612247157307016124 0ustar rootroot/* $Id: err.h 2413 2010-09-11 17:43:04Z bird $ */ /** @file * Override err.h stuff so we get the program names right. */ /* * Copyright (c) 2005-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifndef ___err_h #define ___err_h extern const char *g_progname; int err(int eval, const char *fmt, ...); int errx(int eval, const char *fmt, ...); void warn(const char *fmt, ...); void warnx(const char *fmt, ...); #endif kbuild-2695/src/kmk/kmkbuiltin/strlcpy.c0000644000000000000000000000477312247157307017042 0ustar rootroot/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $"); #include //__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.7 2003/05/01 19:03:14 nectar Exp $"); #endif /* LIBC_SCCS and not lint */ #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } kbuild-2695/src/kmk/kmkbuiltin/haikufakes.h0000644000000000000000000000223012247157306017443 0ustar rootroot/* $Id: haikufakes.h 2656 2012-09-10 20:39:16Z bird $ */ /** @file * Unix/BSD fakes for Haiku. */ /* * Copyright (c) 2005-2012 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifndef ___haikufakes_h #define ___haikufakes_h #define EX_OK 0 #define EX_OSERR 1 #define EX_NOUSER 1 #define EX_USAGE 1 #define EX_TEMPFAIL 1 #define EX_SOFTWARE 1 #define lutimes(path, tvs) utimes(path, tvs) #define lchmod haiku_lchmod extern int haiku_lchmod(const char *pszPath, mode_t mode); #endif kbuild-2695/src/kmk/kmkbuiltin/ftsfake.h0000644000000000000000000001306012247157306016756 0ustar rootroot/* $NetBSD: fts.h,v 1.12 2005/02/03 04:39:32 perry Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fts.h 8.3 (Berkeley) 8/14/94 */ #ifndef _FTS_H_ #define _FTS_H_ #ifdef _MSC_VER # include "kmkbuiltin/mscfakes.h" #endif typedef struct { struct _ftsent *fts_cur; /* current node */ struct _ftsent *fts_child; /* linked list of children */ struct _ftsent **fts_array; /* sort array */ dev_t fts_dev; /* starting device # */ char *fts_path; /* path for this descent */ #if defined(_MSC_VER) || defined(__OS2__) char *fts_rdir; /* path of root */ #else int fts_rfd; /* fd for root */ #endif u_int fts_pathlen; /* sizeof(path) */ u_int fts_nitems; /* elements in the sort array */ int (*fts_compar) /* compare function */ (const struct _ftsent **, const struct _ftsent **); #define FTS_COMFOLLOW 0x001 /* follow command line symlinks */ #define FTS_LOGICAL 0x002 /* logical walk */ #define FTS_NOCHDIR 0x004 /* don't change directories */ #define FTS_NOSTAT 0x008 /* don't get stat info */ #define FTS_PHYSICAL 0x010 /* physical walk */ #define FTS_SEEDOT 0x020 /* return dot and dot-dot */ #define FTS_XDEV 0x040 /* don't cross devices */ #ifndef _MSC_VER #define FTS_WHITEOUT 0x080 /* return whiteout information */ #endif #define FTS_OPTIONMASK 0x0ff /* valid user option mask */ #define FTS_NAMEONLY 0x100 /* (private) child names only */ #define FTS_STOP 0x200 /* (private) unrecoverable error */ int fts_options; /* fts_open options, global flags */ } FTS; typedef struct _ftsent { struct _ftsent *fts_cycle; /* cycle node */ struct _ftsent *fts_parent; /* parent directory */ struct _ftsent *fts_link; /* next file in directory */ long fts_number; /* local numeric value */ void *fts_pointer; /* local address value */ char *fts_accpath; /* access path */ char *fts_path; /* root path */ int fts_errno; /* errno for this node */ #ifndef _MSC_VER int fts_symfd; /* fd for symlink */ #endif u_short fts_pathlen; /* strlen(fts_path) */ u_short fts_namelen; /* strlen(fts_name) */ ino_t fts_ino; /* inode */ dev_t fts_dev; /* device */ #ifdef __LIBC12_SOURCE__ u_int16_t fts_nlink; /* link count */ #else #ifndef _MSC_VER nlink_t fts_nlink; /* link count */ #else int fts_nlink; /* link count */ #endif #endif #define FTS_ROOTPARENTLEVEL -1 #define FTS_ROOTLEVEL 0 short fts_level; /* depth (-1 to N) */ #define FTS_D 1 /* preorder directory */ #define FTS_DC 2 /* directory that causes cycles */ #define FTS_DEFAULT 3 /* none of the above */ #define FTS_DNR 4 /* unreadable directory */ #define FTS_DOT 5 /* dot or dot-dot */ #define FTS_DP 6 /* postorder directory */ #define FTS_ERR 7 /* error; errno is set */ #define FTS_F 8 /* regular file */ #define FTS_INIT 9 /* initialized only */ #define FTS_NS 10 /* stat(2) failed */ #define FTS_NSOK 11 /* no stat(2) requested */ #define FTS_SL 12 /* symbolic link */ #define FTS_SLNONE 13 /* symbolic link without target */ #ifndef _MSC_VER #define FTS_W 14 /* whiteout object */ #endif u_short fts_info; /* user flags for FTSENT structure */ #define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ #define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ #ifndef _MSC_VER #define FTS_ISW 0x04 /* this is a whiteout object */ #endif u_short fts_flags; /* private flags for FTSENT structure */ #define FTS_AGAIN 1 /* read node again */ #define FTS_FOLLOW 2 /* follow symbolic link */ #define FTS_NOINSTR 3 /* no instructions */ #define FTS_SKIP 4 /* discard node */ u_short fts_instr; /* fts_set() instructions */ #ifdef __LIBC12_SOURCE__ struct stat12 *fts_statp; /* stat(2) information */ #else struct stat *fts_statp; /* stat(2) information */ #endif char fts_name[1]; /* file name */ } FTSENT; #ifdef __cplusplus extern "C" { #endif FTSENT *fts_children(FTS *, int); int fts_close(FTS *); FTS *fts_open(char * const *, int, int (*)(const FTSENT **, const FTSENT **)); FTSENT *fts_read(FTS *); int fts_set(FTS *, FTSENT *, int); #ifdef __cplusplus } #endif #endif /* !_FTS_H_ */ kbuild-2695/src/kmk/kmkbuiltin/cmp_extern.h0000644000000000000000000000505612247157307017506 0ustar rootroot/* $NetBSD: extern.h,v 1.7 2007/08/21 14:09:53 christos Exp $ */ /*- * Copyright (c) 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)extern.h 8.3 (Berkeley) 4/2/94 */ #define OK_EXIT 0 #define DIFF_EXIT 1 #define ERR_EXIT 2 /* error exit code */ int cmp_file_and_file(const char *file1, const char *file2, int sflag, int lflag, int special); int cmp_file_and_file_ex(const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special); int cmp_fd_and_file(int fd1, const char *file1, const char *file2, int sflag, int lflag, int special); int cmp_fd_and_file_ex(int fd1, const char *file1, off_t skip1, const char *file2, off_t skip2, int sflag, int lflag, int special); int cmp_fd_and_fd(int fd1, const char *file1, int fd2, const char *file2, int sflag, int lflag, int special); int cmp_fd_and_fd_ex(int fd1, const char *file1, off_t skip1, int fd2, const char *file2, off_t skip2, int sflag, int lflag, int special); kbuild-2695/src/kmk/kmkbuiltin/echo.c0000644000000000000000000001046012247157307016246 0ustar rootroot/* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93"; #endif /* not lint */ #include /*__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.17 2004/04/06 20:06:46 markm Exp $");*/ #endif #include "config.h" #include #ifndef _MSC_VER #include #endif #include #include #include #include #include #include #ifndef _MSC_VER #include #else #include "mscfakes.h" #endif #ifndef IOV_MAX #define IOV_MAX 1024 #endif /* * Report an error and exit. * Use it instead of err(3) to avoid linking-in stdio. */ static void errexit(const char *prog, const char *reason) { char *errstr = strerror(errno); write(STDERR_FILENO, prog, strlen(prog)); write(STDERR_FILENO, ": ", 2); write(STDERR_FILENO, reason, strlen(reason)); write(STDERR_FILENO, ": ", 2); write(STDERR_FILENO, errstr, strlen(errstr)); write(STDERR_FILENO, "\n", 1); } int kmk_builtin_echo(int argc, char *argv[]) { int nflag; /* if not set, output a trailing newline. */ int veclen; /* number of writev arguments. */ struct iovec *iov, *vp, *iovfree; /* Elements to write, current element. */ char space[] = " "; char newline[] = "\n"; char *progname = argv[0]; /* This utility may NOT do getopt(3) option parsing. */ if (*++argv && !strcmp(*argv, "-n")) { ++argv; --argc; nflag = 1; } else nflag = 0; veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0; if ((iovfree = vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) { errexit(progname, "malloc"); exit(1); } while (argv[0] != NULL) { size_t len; len = strlen(argv[0]); /* * If the next argument is NULL then this is this * the last argument, therefore we need to check * for a trailing \c. */ if (argv[1] == NULL) { /* is there room for a '\c' and is there one? */ if (len >= 2 && argv[0][len - 2] == '\\' && argv[0][len - 1] == 'c') { /* chop it and set the no-newline flag. */ len -= 2; nflag = 1; } } vp->iov_base = *argv; vp++->iov_len = len; if (*++argv) { vp->iov_base = space; vp++->iov_len = 1; } } if (!nflag) { veclen++; vp->iov_base = newline; vp++->iov_len = 1; } /* assert(veclen == (vp - iov)); */ while (veclen) { int nwrite; nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen; if (writev(STDOUT_FILENO, iov, nwrite) == -1) { errexit(progname, "write"); free(iovfree); return 1; } iov += nwrite; veclen -= nwrite; } free(iovfree); return 0; } kbuild-2695/src/kmk/kmkbuiltin/kbuild_protection.c0000644000000000000000000002571512247157307021061 0ustar rootroot/* $Id: kbuild_protection.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * Simple File Protection. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "config.h" #include #include #include #include #include #if defined(_MSC_VER) || defined(__OS2__) # include # include #else # include #endif #include "kbuild_protection.h" #include "err.h" /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ #define KBUILD_PROTECTION_MAGIC 0x00111100 #if defined(__EMX__) || defined(_MSC_VER) # define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' ) # define DEFAULT_PROTECTION_DEPTH 1 #else # define IS_SLASH(ch) ( (ch) == '/' ) # define DEFAULT_PROTECTION_DEPTH 2 #endif /** * Counts the components in the specified sub path. * This is a helper for count_path_components. * * etc = 1 * etc/ = 1 * etc/x11 = 2 * and so and and so forth. */ static int countSubPathComponents(const char *pszPath, int cDepth) { for (;;) { const char *pszEnd; size_t cch; /* skip slashes. */ while (IS_SLASH(*pszPath)) pszPath++; if (!*pszPath) break; /* find end of component. */ pszEnd = pszPath; while (!IS_SLASH(*pszEnd) && *pszEnd) pszEnd++; /* count it, checking for '..' and '.'. */ cch = pszEnd - pszPath; if (cch == 2 && pszPath[0] == '.' && pszPath[1] == '.') { if (cDepth > 0) cDepth--; } else if (cch != 1 || pszPath[0] != '.') cDepth++; /* advance */ if (!*pszEnd) break; pszPath = pszEnd + 1; } return cDepth; } /** * Parses the specified path counting the number of components * relative to root. * * We don't check symbolic links and such, just some simple and cheap * path parsing. * * @param pszPath The path to process. * * @returns 0 or higher on success. * On failure an error is printed, eval is set and -1 is returned. */ static int countPathComponents(const char *pszPath) { int cComponents = 0; /* * Deal with root, UNC, drive letter. */ #if defined(_MSC_VER) || defined(__OS2__) if (IS_SLASH(pszPath[0]) && IS_SLASH(pszPath[1]) && !IS_SLASH(pszPath[2])) { /* skip the root - UNC */ pszPath += 3; while (!IS_SLASH(*pszPath) && *pszPath) /* server name */ pszPath++; while (IS_SLASH(*pszPath)) pszPath++; while (!IS_SLASH(*pszPath) && *pszPath) /* share name */ pszPath++; while (IS_SLASH(*pszPath)) pszPath++; } else { unsigned uDriveLetter = (unsigned)toupper(pszPath[0]) - (unsigned)'A'; if (uDriveLetter <= (unsigned)('Z' - 'A') && pszPath[1] == ':') uDriveLetter++; /* A == 1 */ else uDriveLetter = 0; /* 0 == default */ if (!IS_SLASH(pszPath[uDriveLetter ? 2 : 0])) { /* * Relative path, must count cwd depth first. */ #ifdef __OS2__ /** @todo remove when ticket 194 has been fixed */ char *pszCwd = _getdcwd(uDriveLetter, NULL, PATH_MAX); #else char *pszCwd = _getdcwd(uDriveLetter, NULL, 0); #endif char *pszTmp = pszCwd; if (!pszTmp) { err(1, "_getdcwd"); return -1; } if (IS_SLASH(pszTmp[0]) && IS_SLASH(pszTmp[1])) { /* skip the root - UNC */ pszTmp += 2; while (!IS_SLASH(*pszTmp) && *pszTmp) /* server name */ pszTmp++; while (IS_SLASH(*pszTmp)) pszTmp++; while (!IS_SLASH(*pszTmp) && *pszTmp) /* share name */ pszTmp++; } else { /* skip the drive letter and while we're at it, the root slash too. */ pszTmp += 1 + (pszTmp[1] == ':'); } cComponents = countSubPathComponents(pszTmp, 0); free(pszCwd); } else { /* skip the drive letter and while we're at it, the root slash too. */ pszPath += uDriveLetter ? 3 : 1; } } #else /* !WIN && !OS2 */ if (!IS_SLASH(pszPath[0])) { /* * Relative path, must count cwd depth first. */ char szCwd[4096]; if (!getcwd(szCwd, sizeof(szCwd))) { err(1, "getcwd"); return -1; } cComponents = countSubPathComponents(szCwd, 0); } #endif /* !WIN && !OS2 */ /* * We're now past any UNC or drive letter crap, possibly positioned * at the root slash or at the start of a path component at the * given depth. Count the remainder. */ return countSubPathComponents(pszPath, cComponents); } /** * Initializes the instance data. * * @param pThis Pointer to the instance data. */ void kBuildProtectionInit(PKBUILDPROTECTION pThis) { pThis->uMagic = KBUILD_PROTECTION_MAGIC; pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] = 0; pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] = 1; pThis->cProtectionDepth = DEFAULT_PROTECTION_DEPTH; } /** * Destroys the instance data. * * @param pThis Pointer to the instance data. */ void kBuildProtectionTerm(PKBUILDPROTECTION pThis) { pThis->uMagic = 0; } void kBuildProtectionEnable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType) { assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC); assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST); pThis->afTypes[enmType] |= 1; } void kBuildProtectionDisable(PKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType) { assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC); assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST); pThis->afTypes[enmType] &= ~1U; } /** * Sets the protection depth according to the option argument. * * @param pszValue The value. * * @returns 0 on success, -1 and errx on failure. */ int kBuildProtectionSetDepth(PKBUILDPROTECTION pThis, const char *pszValue) { /* skip leading blanks, they don't count either way. */ while (isspace(*pszValue)) pszValue++; /* number or path? */ if (!isdigit(*pszValue) || strpbrk(pszValue, ":/\\")) pThis->cProtectionDepth = countPathComponents(pszValue); else { char *pszMore = 0; pThis->cProtectionDepth = strtol(pszValue, &pszMore, 0); if (pThis->cProtectionDepth != 0 && pszMore) { /* trailing space is harmless. */ while (isspace(*pszMore)) pszMore++; } if (!pThis->cProtectionDepth || pszValue == pszMore || *pszMore) return errx(1, "bogus protection depth: %s", pszValue); } if (pThis->cProtectionDepth < 1) return errx(1, "bogus protection depth: %s", pszValue); return 0; } /** * Scans the environment for option overrides. * * @param pThis Pointer to the instance data. * @param papszEnv The environment array. * @param pszPrefix The variable prefix. * * @returns 0 on success, -1 and err*() on failure. */ int kBuildProtectionScanEnv(PKBUILDPROTECTION pThis, char **papszEnv, const char *pszPrefix) { unsigned i; const size_t cchPrefix = strlen(pszPrefix); for (i = 0; papszEnv[i]; i++) { const char *pszVar = papszEnv[i]; if (!strncmp(pszVar, pszPrefix, cchPrefix)) { pszVar += cchPrefix; if (!strncmp(pszVar, "PROTECTION_DEPTH=", sizeof("PROTECTION_DEPTH=") - 1)) { const char *pszVal = pszVar + sizeof("PROTECTION_DEPTH=") - 1; if (kBuildProtectionSetDepth(pThis, pszVal)) return -1; } else if (!strncmp(pszVar, "DISABLE_PROTECTION=", sizeof("DISABLE_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] &= ~1U; else if (!strncmp(pszVar, "ENABLE_PROTECTION=", sizeof("ENABLE_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_RECURSIVE] |= 3; else if (!strncmp(pszVar, "DISABLE_FULL_PROTECTION=", sizeof("DISABLE_FULL_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] &= ~1U; else if (!strncmp(pszVar, "ENABLE_FULL_PROTECTION=", sizeof("ENABLE_FULL_PROTECTION=") - 1)) pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] |= 3; } } return 0; } /** * Protect the upper layers of the file system against accidental * or malicious deletetion attempt from within a makefile. * * @param pszPath The path to check. * @param required_depth The minimum number of components in the * path counting from the root. * * @returns 0 on success. * On failure an error is printed and -1 is returned. */ int kBuildProtectionEnforce(PCKBUILDPROTECTION pThis, KBUILDPROTECTIONTYPE enmType, const char *pszPath) { assert(pThis->uMagic == KBUILD_PROTECTION_MAGIC); assert(enmType < KBUILDPROTECTIONTYPE_MAX && enmType >= KBUILDPROTECTIONTYPE_FIRST); if ( (pThis->afTypes[enmType] & 3) || (pThis->afTypes[KBUILDPROTECTIONTYPE_FULL] & 3)) { /* * Count the path and compare it with the required depth. */ int cComponents = countPathComponents(pszPath); if (cComponents < 0) return -1; if ((unsigned int)cComponents <= pThis->cProtectionDepth) { errx(1, "%s: protected", pszPath); return -1; } } return 0; } /** * Retrieve the default path protection depth. * * @returns the default value. */ int kBuildProtectionDefaultDepth(void) { return DEFAULT_PROTECTION_DEPTH; } kbuild-2695/src/kmk/kmkbuiltin/cp_utils.c0000644000000000000000000002401112247157306017146 0ustar rootroot/*- * Copyright (c) 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94"; #include __FBSDID("$FreeBSD: src/bin/cp/utils.c,v 1.43 2004/04/06 20:06:44 markm Exp $"); #endif #endif /* not lint */ #define MSC_DO_64_BIT_IO #include "config.h" #ifndef _MSC_VER # include #endif #include #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED # include #endif #include "err.h" #include #include #include #include #include #include #include #ifndef __HAIKU__ # include #endif #include #ifdef __sun__ # include "solfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #else # include #endif #include "cp_extern.h" #include "cmp_extern.h" #define cp_pct(x,y) (int)(100.0 * (double)(x) / (double)(y)) #ifndef MAXBSIZE # define MAXBSIZE 0x20000 #endif #ifndef O_BINARY # define O_BINARY 0 #endif #ifndef S_ISVTX # define S_ISVTX 0 #endif int copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied) { static char buf[MAXBSIZE]; struct stat *fs; int ch, checkch, from_fd, rcount, rval, to_fd; ssize_t wcount; size_t wresid; size_t wtotal; char *bufp; #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED char *p; #endif *pcopied = 0; if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) { warn("open: %s", entp->fts_path); return (1); } fs = entp->fts_statp; /* * If the file exists and we're interactive, verify with the user. * If the file DNE, set the mode to be the from file, minus setuid * bits, modified by the umask; arguably wrong, but it makes copying * executables work right and it's been that way forever. (The * other choice is 666 or'ed with the execute bits on the from file * modified by the umask.) */ if (!dne) { /* compare the files first if requested */ if (changed_only) { if (cmp_fd_and_file(from_fd, entp->fts_path, to.p_path, 1 /* silent */, 0 /* lflag */, 0 /* special */) == OK_EXIT) { close(from_fd); return (0); } if (lseek(from_fd, 0, SEEK_SET) != 0) { close(from_fd); if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) { warn("open: %s", entp->fts_path); return (1); } } } #define YESNO "(y/n [n]) " if (nflag) { if (vflag) printf("%s not overwritten\n", to.p_path); return (0); } else if (iflag) { (void)fprintf(stderr, "overwrite %s? %s", to.p_path, YESNO); checkch = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (checkch != 'y' && checkch != 'Y') { (void)close(from_fd); (void)fprintf(stderr, "not overwritten\n"); return (1); } } if (fflag) { /* remove existing destination file name, * create a new file */ (void)unlink(to.p_path); to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, fs->st_mode & ~(S_ISUID | S_ISGID)); } else /* overwrite existing destination file name */ to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_BINARY, 0); } else to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, fs->st_mode & ~(S_ISUID | S_ISGID)); if (to_fd == -1) { warn("open: %s", to.p_path); (void)close(from_fd); return (1); } rval = 0; *pcopied = 1; /* * Mmap and write if less than 8M (the limit is so we don't totally * trash memory on big files. This is really a minor hack, but it * wins some CPU back. */ #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED if (S_ISREG(fs->st_mode) && fs->st_size > 0 && fs->st_size <= 8 * 1048576) { if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ, MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { warn("mmap: %s", entp->fts_path); rval = 1; } else { wtotal = 0; for (bufp = p, wresid = fs->st_size; ; bufp += wcount, wresid -= (size_t)wcount) { wcount = write(to_fd, bufp, wresid); wtotal += wcount; if (info) { info = 0; (void)fprintf(stderr, "%s -> %s %3d%%\n", entp->fts_path, to.p_path, cp_pct(wtotal, fs->st_size)); } if (wcount >= (ssize_t)wresid || wcount <= 0) break; } if (wcount != (ssize_t)wresid) { warn("write[%zd != %zu]: %s", wcount, wresid, to.p_path); rval = 1; } /* Some systems don't unmap on close(2). */ if (munmap(p, fs->st_size) < 0) { warn("munmap: %s", entp->fts_path); rval = 1; } } } else #endif { wtotal = 0; while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { for (bufp = buf, wresid = rcount; ; bufp += wcount, wresid -= wcount) { wcount = write(to_fd, bufp, wresid); wtotal += wcount; if (info) { info = 0; (void)fprintf(stderr, "%s -> %s %3d%%\n", entp->fts_path, to.p_path, cp_pct(wtotal, fs->st_size)); } if (wcount >= (ssize_t)wresid || wcount <= 0) break; } if (wcount != (ssize_t)wresid) { warn("write[%zd != %zu]: %s", wcount, wresid, to.p_path); rval = 1; break; } } if (rcount < 0) { warn("read: %s", entp->fts_path); rval = 1; } } /* * Don't remove the target even after an error. The target might * not be a regular file, or its attributes might be important, * or its contents might be irreplaceable. It would only be safe * to remove it if we created it and its length is 0. */ if (pflag && setfile(fs, to_fd)) rval = 1; (void)close(from_fd); if (close(to_fd)) { warn("close: %s", to.p_path); rval = 1; } return (rval); } int copy_link(const FTSENT *p, int exists) { int len; char llink[PATH_MAX]; if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) { warn("readlink: %s", p->fts_path); return (1); } llink[len] = '\0'; if (exists && unlink(to.p_path)) { warn("unlink: %s", to.p_path); return (1); } if (symlink(llink, to.p_path)) { warn("symlink: %s", llink); return (1); } return (pflag ? setfile(p->fts_statp, -1) : 0); } int copy_fifo(struct stat *from_stat, int exists) { if (exists && unlink(to.p_path)) { warn("unlink: %s", to.p_path); return (1); } if (mkfifo(to.p_path, from_stat->st_mode)) { warn("mkfifo: %s", to.p_path); return (1); } return (pflag ? setfile(from_stat, -1) : 0); } int copy_special(struct stat *from_stat, int exists) { if (exists && unlink(to.p_path)) { warn("unlink: %s", to.p_path); return (1); } if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) { warn("mknod: %s", to.p_path); return (1); } return (pflag ? setfile(from_stat, -1) : 0); } int setfile(struct stat *fs, int fd) { static struct timeval tv[2]; struct stat ts; int rval, gotstat, islink, fdval; rval = 0; fdval = fd != -1; islink = !fdval && S_ISLNK(fs->st_mode); fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; #ifdef HAVE_ST_TIMESPEC TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); #else tv[0].tv_sec = fs->st_atime; tv[1].tv_sec = fs->st_mtime; tv[0].tv_usec = tv[1].tv_usec = 0; #endif if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) { warn("%sutimes: %s", islink ? "l" : "", to.p_path); rval = 1; } if (fdval ? fstat(fd, &ts) : (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts))) gotstat = 0; else { gotstat = 1; ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; } /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) : chown(to.p_path, fs->st_uid, fs->st_gid))) { if (errno != EPERM) { warn("chown: %s", to.p_path); rval = 1; } fs->st_mode &= ~(S_ISUID | S_ISGID); } if (!gotstat || fs->st_mode != ts.st_mode) if (fdval ? fchmod(fd, fs->st_mode) : (islink ? lchmod(to.p_path, fs->st_mode) : chmod(to.p_path, fs->st_mode))) { warn("chmod: %s", to.p_path); rval = 1; } #ifdef HAVE_ST_FLAGS if (!gotstat || fs->st_flags != ts.st_flags) if (fdval ? fchflags(fd, fs->st_flags) : (islink ? (errno = ENOSYS) : chflags(to.p_path, fs->st_flags))) { warn("chflags: %s", to.p_path); rval = 1; } #endif return (rval); } kbuild-2695/src/kmk/kmkbuiltin/expr.c0000644000000000000000000002357412247157306016317 0ustar rootroot/* $OpenBSD: expr.c,v 1.17 2006/06/21 18:28:24 deraadt Exp $ */ /* $NetBSD: expr.c,v 1.3.6.1 1996/06/04 20:41:47 cgd Exp $ */ /* * Written by J.T. Conklin . * Public domain. */ #include "config.h" #include #include #include #include #include #ifdef KMK_WITH_REGEX #include #endif #include #include #ifdef HAVE_ALLOCA_H # include #endif #include "err.h" #include "getopt.h" #include "kmkbuiltin.h" static struct val *make_int(int); static struct val *make_str(char *); static void free_value(struct val *); static int is_integer(struct val *, int *); static int to_integer(struct val *); static void to_string(struct val *); static int is_zero_or_null(struct val *); static void nexttoken(int); static void error(void); static struct val *eval6(void); static struct val *eval5(void); static struct val *eval4(void); static struct val *eval3(void); static struct val *eval2(void); static struct val *eval1(void); static struct val *eval0(void); enum token { OR, AND, EQ, LT, GT, ADD, SUB, MUL, DIV, MOD, MATCH, RP, LP, NE, LE, GE, OPERAND, EOI }; struct val { enum { integer, string } type; union { char *s; int i; } u; }; static enum token token; static struct val *tokval; static char **av; static jmp_buf g_expr_jmp; static void **recorded_allocations; static int num_recorded_allocations; static void expr_mem_record_alloc(void *ptr) { if (!(num_recorded_allocations & 31)) { void *newtab = realloc(recorded_allocations, (num_recorded_allocations + 33) * sizeof(void *)); if (!newtab) longjmp(g_expr_jmp, err(3, NULL)); recorded_allocations = (void **)newtab; } recorded_allocations[num_recorded_allocations++] = ptr; } static void expr_mem_record_free(void *ptr) { int i = num_recorded_allocations; while (i-- > 0) if (recorded_allocations[i] == ptr) { num_recorded_allocations--; recorded_allocations[i] = recorded_allocations[num_recorded_allocations]; return; } assert(i >= 0); } static void expr_mem_init(void) { num_recorded_allocations = 0; recorded_allocations = NULL; } static void expr_mem_cleanup(void) { if (recorded_allocations) { while (num_recorded_allocations-- > 0) free(recorded_allocations[num_recorded_allocations]); free(recorded_allocations); recorded_allocations = NULL; } } static struct val * make_int(int i) { struct val *vp; vp = (struct val *) malloc(sizeof(*vp)); if (vp == NULL) longjmp(g_expr_jmp, err(3, NULL)); expr_mem_record_alloc(vp); vp->type = integer; vp->u.i = i; return vp; } static struct val * make_str(char *s) { struct val *vp; vp = (struct val *) malloc(sizeof(*vp)); if (vp == NULL || ((vp->u.s = strdup(s)) == NULL)) longjmp(g_expr_jmp, err(3, NULL)); expr_mem_record_alloc(vp->u.s); expr_mem_record_alloc(vp); vp->type = string; return vp; } static void free_value(struct val *vp) { if (vp->type == string) { expr_mem_record_free(vp->u.s); free(vp->u.s); } free(vp); expr_mem_record_free(vp); } /* determine if vp is an integer; if so, return it's value in *r */ static int is_integer(struct val *vp, int *r) { char *s; int neg; int i; if (vp->type == integer) { *r = vp->u.i; return 1; } /* * POSIX.2 defines an "integer" as an optional unary minus * followed by digits. */ s = vp->u.s; i = 0; neg = (*s == '-'); if (neg) s++; while (*s) { if (!isdigit(*s)) return 0; i *= 10; i += *s - '0'; s++; } if (neg) i *= -1; *r = i; return 1; } /* coerce to vp to an integer */ static int to_integer(struct val *vp) { int r; if (vp->type == integer) return 1; if (is_integer(vp, &r)) { expr_mem_record_free(vp->u.s); free(vp->u.s); vp->u.i = r; vp->type = integer; return 1; } return 0; } /* coerce to vp to an string */ static void to_string(struct val *vp) { char *tmp; if (vp->type == string) return; if (asprintf(&tmp, "%d", vp->u.i) == -1) longjmp(g_expr_jmp, err(3, NULL)); expr_mem_record_alloc(tmp); vp->type = string; vp->u.s = tmp; } static int is_zero_or_null(struct val *vp) { if (vp->type == integer) { return (vp->u.i == 0); } else { return (*vp->u.s == 0 || (to_integer(vp) && vp->u.i == 0)); } /* NOTREACHED */ } static void nexttoken(int pat) { char *p; if ((p = *av) == NULL) { token = EOI; return; } av++; if (pat == 0 && p[0] != '\0') { if (p[1] == '\0') { const char *x = "|&=<>+-*/%:()"; char *i; /* index */ if ((i = strchr(x, *p)) != NULL) { token = i - x; return; } } else if (p[1] == '=' && p[2] == '\0') { switch (*p) { case '<': token = LE; return; case '>': token = GE; return; case '!': token = NE; return; } } } tokval = make_str(p); token = OPERAND; return; } #ifdef __GNUC__ __attribute__((noreturn)) #endif static void error(void) { longjmp(g_expr_jmp, errx(2, "syntax error")); /* NOTREACHED */ } static struct val * eval6(void) { struct val *v; if (token == OPERAND) { nexttoken(0); return tokval; } else if (token == RP) { nexttoken(0); v = eval0(); if (token != LP) { error(); /* NOTREACHED */ } nexttoken(0); return v; } else { error(); } /* NOTREACHED */ } /* Parse and evaluate match (regex) expressions */ static struct val * eval5(void) { #ifdef KMK_WITH_REGEX regex_t rp; regmatch_t rm[2]; char errbuf[256]; int eval; struct val *r; struct val *v; #endif struct val *l; l = eval6(); while (token == MATCH) { #ifdef KMK_WITH_REGEX nexttoken(1); r = eval6(); /* coerce to both arguments to strings */ to_string(l); to_string(r); /* compile regular expression */ if ((eval = regcomp(&rp, r->u.s, 0)) != 0) { regerror(eval, &rp, errbuf, sizeof(errbuf)); longjmp(g_expr_jmp, errx(2, "%s", errbuf)); } /* compare string against pattern -- remember that patterns are anchored to the beginning of the line */ if (regexec(&rp, l->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { if (rm[1].rm_so >= 0) { *(l->u.s + rm[1].rm_eo) = '\0'; v = make_str(l->u.s + rm[1].rm_so); } else { v = make_int((int)(rm[0].rm_eo - rm[0].rm_so)); } } else { if (rp.re_nsub == 0) { v = make_int(0); } else { v = make_str(""); } } /* free arguments and pattern buffer */ free_value(l); free_value(r); regfree(&rp); l = v; #else longjmp(g_expr_jmp, errx(2, "regex not supported, sorry.")); #endif } return l; } /* Parse and evaluate multiplication and division expressions */ static struct val * eval4(void) { struct val *l, *r; enum token op; l = eval5(); while ((op = token) == MUL || op == DIV || op == MOD) { nexttoken(0); r = eval5(); if (!to_integer(l) || !to_integer(r)) { longjmp(g_expr_jmp, errx(2, "non-numeric argument")); } if (op == MUL) { l->u.i *= r->u.i; } else { if (r->u.i == 0) { longjmp(g_expr_jmp, errx(2, "division by zero")); } if (op == DIV) { l->u.i /= r->u.i; } else { l->u.i %= r->u.i; } } free_value(r); } return l; } /* Parse and evaluate addition and subtraction expressions */ static struct val * eval3(void) { struct val *l, *r; enum token op; l = eval4(); while ((op = token) == ADD || op == SUB) { nexttoken(0); r = eval4(); if (!to_integer(l) || !to_integer(r)) { longjmp(g_expr_jmp, errx(2, "non-numeric argument")); } if (op == ADD) { l->u.i += r->u.i; } else { l->u.i -= r->u.i; } free_value(r); } return l; } /* Parse and evaluate comparison expressions */ static struct val * eval2(void) { struct val *l, *r; enum token op; int v = 0, li, ri; l = eval3(); while ((op = token) == EQ || op == NE || op == LT || op == GT || op == LE || op == GE) { nexttoken(0); r = eval3(); if (is_integer(l, &li) && is_integer(r, &ri)) { switch (op) { case GT: v = (li > ri); break; case GE: v = (li >= ri); break; case LT: v = (li < ri); break; case LE: v = (li <= ri); break; case EQ: v = (li == ri); break; case NE: v = (li != ri); break; default: break; } } else { to_string(l); to_string(r); switch (op) { case GT: v = (strcoll(l->u.s, r->u.s) > 0); break; case GE: v = (strcoll(l->u.s, r->u.s) >= 0); break; case LT: v = (strcoll(l->u.s, r->u.s) < 0); break; case LE: v = (strcoll(l->u.s, r->u.s) <= 0); break; case EQ: v = (strcoll(l->u.s, r->u.s) == 0); break; case NE: v = (strcoll(l->u.s, r->u.s) != 0); break; default: break; } } free_value(l); free_value(r); l = make_int(v); } return l; } /* Parse and evaluate & expressions */ static struct val * eval1(void) { struct val *l, *r; l = eval2(); while (token == AND) { nexttoken(0); r = eval2(); if (is_zero_or_null(l) || is_zero_or_null(r)) { free_value(l); free_value(r); l = make_int(0); } else { free_value(r); } } return l; } /* Parse and evaluate | expressions */ static struct val * eval0(void) { struct val *l, *r; l = eval1(); while (token == OR) { nexttoken(0); r = eval1(); if (is_zero_or_null(l)) { free_value(l); l = r; } else { free_value(r); } } return l; } int kmk_builtin_expr(int argc, char *argv[], char **envp) { struct val *vp; int rval; /* re-init globals */ token = 0; tokval = 0; av = 0; expr_mem_init(); #ifdef kmk_builtin_expr /* kmk already does this. */ (void) setlocale(LC_ALL, ""); #endif if (argc > 1 && !strcmp(argv[1], "--")) argv++; av = argv + 1; rval = setjmp(g_expr_jmp); if (!rval) { nexttoken(0); vp = eval0(); if (token != EOI) { error(); /* NOTREACHED */ } if (vp->type == integer) printf("%d\n", vp->u.i); else printf("%s\n", vp->u.s); rval = is_zero_or_null(vp); } /* else: longjmp */ /* cleanup */ expr_mem_cleanup(); return rval; } kbuild-2695/src/kmk/kmkbuiltin/install.c0000644000000000000000000006657712247157306017021 0ustar rootroot/* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1987, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; #endif /* not lint */ #include __FBSDID("$FreeBSD: src/usr.bin/xinstall/xinstall.c,v 1.66 2005/01/25 14:34:57 ssouhlal Exp $"); #endif #include "config.h" #ifndef _MSC_VER # include # ifdef USE_MMAP # include # endif # ifndef __HAIKU__ # include # endif # include # include #endif /* !_MSC_VER */ #include #include #include "err.h" #include #include #include #include #include #include #include #include #ifndef __HAIKU__ # include #endif #include #if defined(__EMX__) || defined(_MSC_VER) # include #endif #include "getopt.h" #ifdef __sun__ # include "solfakes.h" #endif #ifdef _MSC_VER # include "mscfakes.h" #endif #ifdef __HAIKU__ # include "haikufakes.h" #endif #include "kmkbuiltin.h" extern void * bsd_setmode(const char *p); extern mode_t bsd_getmode(const void *bbox, mode_t omode); #ifndef __unused # define __unused #endif #ifndef MAXBSIZE # define MAXBSIZE 0x20000 #endif /* Bootstrap aid - this doesn't exist in most older releases */ #ifndef MAP_FAILED #define MAP_FAILED ((void *)-1) /* from */ #endif #define MAX_CMP_SIZE (16 * 1024 * 1024) #define DIRECTORY 0x01 /* Tell install it's a directory. */ #define SETFLAGS 0x02 /* Tell install to set flags. */ #define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND) #define BACKUP_SUFFIX ".old" #ifndef O_BINARY # define O_BINARY 0 #endif #ifndef EFTYPE # define EFTYPE EINVAL #endif #if defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__) # define IS_SLASH(ch) ((ch) == '/' || (ch) == '\\') #else # define IS_SLASH(ch) ((ch) == '/') #endif static gid_t gid; static uid_t uid; static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose, mode_given; static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; static const char *suffix = BACKUP_SUFFIX; static int ignore_perm_errors; static int hard_link_files_when_possible; static struct option long_options[] = { { "help", no_argument, 0, 261 }, { "version", no_argument, 0, 262 }, { "ignore-perm-errors", no_argument, 0, 263 }, { "no-ignore-perm-errors", no_argument, 0, 264 }, { "hard-link-files-when-possible", no_argument, 0, 265 }, { "no-hard-link-files-when-possible", no_argument, 0, 266 }, { 0, 0, 0, 0 }, }; static int copy(int, const char *, int, const char *, off_t); static int compare(int, const char *, size_t, int, const char *, size_t); static int create_newfile(const char *, int, struct stat *); static int create_tempfile(const char *, char *, size_t); static int install(const char *, const char *, u_long, u_int); static int install_dir(char *); static u_long numeric_id(const char *, const char *); static int strip(const char *); #ifdef USE_MMAP static int trymmap(int); #endif static int usage(FILE *); static char *last_slash(const char *); int kmk_builtin_install(int argc, char *argv[], char ** envp) { struct stat from_sb, to_sb; mode_t *set; u_long fset = 0; int ch, no_target; u_int iflags; char *flags; const char *group, *owner, *to_name; (void)envp; /* reinitialize globals */ mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; suffix = BACKUP_SUFFIX; gid = 0; uid = 0; dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = mode_given = 0; ignore_perm_errors = geteuid() != 0; hard_link_files_when_possible = 0; /* reset getopt and set progname. */ g_progname = argv[0]; opterr = 1; optarg = NULL; optopt = 0; optind = 0; /* init */ iflags = 0; group = owner = NULL; while ((ch = getopt_long(argc, argv, "B:bCcdf:g:Mm:o:pSsv", long_options, NULL)) != -1) switch(ch) { case 'B': suffix = optarg; /* FALLTHROUGH */ case 'b': dobackup = 1; break; case 'C': docompare = 1; break; case 'c': /* For backwards compatibility. */ break; case 'd': dodir = 1; break; case 'f': #ifdef UF_IMMUTABLE flags = optarg; if (strtofflags(&flags, &fset, NULL)) return errx(EX_USAGE, "%s: invalid flag", flags); iflags |= SETFLAGS; #else (void)flags; #endif break; case 'g': group = optarg; break; case 'M': nommap = 1; break; case 'm': if (!(set = bsd_setmode(optarg))) return errx(EX_USAGE, "invalid file mode: %s", optarg); mode = bsd_getmode(set, 0); free(set); mode_given = 1; break; case 'o': owner = optarg; break; case 'p': docompare = dopreserve = 1; break; case 'S': safecopy = 1; break; case 's': dostrip = 1; break; case 'v': verbose = 1; break; case 261: usage(stdout); return 0; case 262: return kbuild_version(argv[0]); case 263: ignore_perm_errors = 1; break; case 264: ignore_perm_errors = 0; break; case 265: hard_link_files_when_possible = 1; break; case 266: hard_link_files_when_possible = 0; break; case '?': default: return usage(stderr); } argc -= optind; argv += optind; /* some options make no sense when creating directories */ if (dostrip && dodir) { warnx("-d and -s may not be specified together"); return usage(stderr); } /* must have at least two arguments, except when creating directories */ if (argc == 0 || (argc == 1 && !dodir)) return usage(stderr); /* need to make a temp copy so we can compare stripped version */ if (docompare && dostrip) safecopy = 1; /* get group and owner id's */ if (group != NULL) { #ifndef _MSC_VER struct group *gp; if ((gp = getgrnam(group)) != NULL) gid = gp->gr_gid; else #endif { gid = (gid_t)numeric_id(group, "group"); if (gid == (gid_t)-1) return 1; } } else gid = (gid_t)-1; if (owner != NULL) { #ifndef _MSC_VER struct passwd *pp; if ((pp = getpwnam(owner)) != NULL) uid = pp->pw_uid; else #endif { uid = (uid_t)numeric_id(owner, "user"); if (uid == (uid_t)-1) return 1; } } else uid = (uid_t)-1; if (dodir) { for (; *argv != NULL; ++argv) { int rc = install_dir(*argv); if (rc) return rc; } return EX_OK; /* NOTREACHED */ } no_target = stat(to_name = argv[argc - 1], &to_sb); if (!no_target && S_ISDIR(to_sb.st_mode)) { for (; *argv != to_name; ++argv) { int rc = install(*argv, to_name, fset, iflags | DIRECTORY); if (rc) return rc; } return EX_OK; } /* can't do file1 file2 directory/file */ if (argc != 2) { warnx("wrong number or types of arguments"); return usage(stderr); } if (!no_target) { if (stat(*argv, &from_sb)) return err(EX_OSERR, "%s", *argv); if (!S_ISREG(to_sb.st_mode)) { errno = EFTYPE; return err(EX_OSERR, "%s", to_name); } if (to_sb.st_dev == from_sb.st_dev && to_sb.st_dev != 0 && to_sb.st_ino == from_sb.st_ino && to_sb.st_ino != 0 && !hard_link_files_when_possible) return errx(EX_USAGE, "%s and %s are the same file", *argv, to_name); } return install(*argv, to_name, fset, iflags); } static u_long numeric_id(const char *name, const char *type) { u_long val; char *ep; /* * XXX * We know that uid_t's and gid_t's are unsigned longs. */ errno = 0; val = strtoul(name, &ep, 10); if (errno) return err(-1, "%s", name); if (*ep != '\0') return errx(-1, "unknown %s %s", type, name); return (val); } /* * install -- * build a path name and install the file */ static int install(const char *from_name, const char *to_name, u_long fset, u_int flags) { struct stat from_sb, temp_sb, to_sb; struct timeval tvb[2]; int devnull, files_match, from_fd, serrno, target; int tempcopy, temp_fd, to_fd; char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN]; int rc = EX_OK; files_match = 0; from_fd = -1; to_fd = -1; temp_fd = -1; /* If try to install NULL file to a directory, fails. */ if (flags & DIRECTORY #if defined(__EMX__) || defined(_MSC_VER) || ( stricmp(from_name, _PATH_DEVNULL) && stricmp(from_name, "nul") # ifdef __EMX__ && stricmp(from_name, "/dev/nul") # endif ) #else || strcmp(from_name, _PATH_DEVNULL) #endif ) { if (stat(from_name, &from_sb)) return err(EX_OSERR, "%s", from_name); if (!S_ISREG(from_sb.st_mode)) { errno = EFTYPE; return err(EX_OSERR, "%s", from_name); } /* Build the target path. */ if (flags & DIRECTORY) { (void)snprintf(pathbuf, sizeof(pathbuf), "%s/%s", to_name, (p = last_slash(from_name)) ? ++p : from_name); to_name = pathbuf; } devnull = 0; } else { devnull = 1; } target = stat(to_name, &to_sb) == 0; /* Only install to regular files. */ if (target && !S_ISREG(to_sb.st_mode)) { errno = EFTYPE; warn("%s", to_name); return EX_OK; } /* Only copy safe if the target exists. */ tempcopy = safecopy && target; /* Try hard linking if wanted and possible. */ if (hard_link_files_when_possible) { #ifdef KBUILD_OS_OS2 const char *why_not = "not supported on OS/2"; #else const char *why_not = NULL; if (devnull) { why_not = "/dev/null"; } else if (dostrip) { why_not = "strip (-s)"; } else if (docompare) { why_not = "compare (-C)"; } else if (dobackup) { why_not = "backup (-b/-B)"; } else if (safecopy) { why_not = "safe copy (-S)"; } else if (lstat(from_name, &temp_sb)) { why_not = "lstat on source failed"; } else if (S_ISLNK(temp_sb.st_mode)) { why_not = "symlink"; } else if (!S_ISREG(temp_sb.st_mode)) { why_not = "not regular file"; # if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) } else if ((mode & S_IWUSR) != (from_sb.st_mode & S_IWUSR)) { # else } else if (mode != (from_sb.st_mode & ALLPERMS)) { # endif printf("install: warning: Not hard linking, mode differs: 0%03o, desires 0%03o\n" "install: src path '%s'\n" "install: dst path '%s'\n", (from_sb.st_mode & ALLPERMS), mode, from_name, to_name); why_not = NULL; } else if (uid != (uid_t)-1 && gid != from_sb.st_uid) { why_not = "uid mismatch"; } else if (gid != (gid_t)-1 && gid != from_sb.st_gid) { why_not = "gid mismatch"; } else { int rcLink = link(from_name, to_name); if (rcLink != 0 && errno == EEXIST) { unlink(to_name); rcLink = link(from_name, to_name); } if (rcLink == 0) { if (verbose) printf("install: %s -> %s (hardlinked)\n", from_name, to_name); goto l_done; } if (verbose) printf("install: hard linking '%s' to '%s' failed: %s\n", to_name, from_name, strerror(errno)); why_not = NULL; } #endif if (verbose && why_not) printf("install: not hard linking '%s' to '%s' because: %s\n", to_name, from_name, why_not); /* Can't hard link or we failed, continue as nothing happend. */ } if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY, 0)) < 0) return err(EX_OSERR, "%s", from_name); /* If we don't strip, we can compare first. */ if (docompare && !dostrip && target) { if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { rc = err(EX_OSERR, "%s", to_name); goto l_done; } if (devnull) files_match = to_sb.st_size == 0; else files_match = !(compare(from_fd, from_name, (size_t)from_sb.st_size, to_fd, to_name, (size_t)to_sb.st_size)); /* Close "to" file unless we match. */ if (!files_match) { (void)close(to_fd); to_fd = -1; } } if (!files_match) { if (tempcopy) { to_fd = create_tempfile(to_name, tempfile, sizeof(tempfile)); if (to_fd < 0) { rc = err(EX_OSERR, "%s", tempfile); goto l_done; } } else { if ((to_fd = create_newfile(to_name, target, &to_sb)) < 0) { rc = err(EX_OSERR, "%s", to_name); goto l_done; } if (verbose) (void)printf("install: %s -> %s\n", from_name, to_name); } if (!devnull) { rc = copy(from_fd, from_name, to_fd, tempcopy ? tempfile : to_name, from_sb.st_size); if (rc) goto l_done; } } if (dostrip) { #if defined(__EMX__) || defined(_MSC_VER) /* close before we strip. */ close(to_fd); to_fd = -1; #endif rc = strip(tempcopy ? tempfile : to_name); if (rc) goto l_done; /* * Re-open our fd on the target, in case we used a strip * that does not work in-place -- like GNU binutils strip. */ #if !defined(__EMX__) && !defined(_MSC_VER) close(to_fd); #endif to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY, 0); if (to_fd < 0) { rc = err(EX_OSERR, "stripping %s", to_name); goto l_done; } } /* * Compare the stripped temp file with the target. */ if (docompare && dostrip && target) { temp_fd = to_fd; /* Re-open to_fd using the real target name. */ if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { rc = err(EX_OSERR, "%s", to_name); goto l_done; } if (fstat(temp_fd, &temp_sb)) { serrno = errno; (void)unlink(tempfile); errno = serrno; rc = err(EX_OSERR, "%s", tempfile); goto l_done; } if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd, to_name, (size_t)to_sb.st_size) == 0) { /* * If target has more than one link we need to * replace it in order to snap the extra links. * Need to preserve target file times, though. */ #if !defined(_MSC_VER) && !defined(__EMX__) if (to_sb.st_nlink != 1) { tvb[0].tv_sec = to_sb.st_atime; tvb[0].tv_usec = 0; tvb[1].tv_sec = to_sb.st_mtime; tvb[1].tv_usec = 0; (void)utimes(tempfile, tvb); } else #endif { files_match = 1; (void)unlink(tempfile); } (void) close(temp_fd); temp_fd = -1; } } /* * Move the new file into place if doing a safe copy * and the files are different (or just not compared). */ if (tempcopy && !files_match) { #ifdef UF_IMMUTABLE /* Try to turn off the immutable bits. */ if (to_sb.st_flags & NOCHANGEBITS) (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS); #endif if (dobackup) { if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name, suffix) != strlen(to_name) + strlen(suffix)) { unlink(tempfile); rc = errx(EX_OSERR, "%s: backup filename too long", to_name); goto l_done; } if (verbose) (void)printf("install: %s -> %s\n", to_name, backup); if (rename(to_name, backup) < 0) { serrno = errno; unlink(tempfile); errno = serrno; rc = err(EX_OSERR, "rename: %s to %s", to_name, backup); goto l_done; } } if (verbose) (void)printf("install: %s -> %s\n", from_name, to_name); if (rename(tempfile, to_name) < 0) { serrno = errno; unlink(tempfile); errno = serrno; rc = err(EX_OSERR, "rename: %s to %s", tempfile, to_name); goto l_done; } /* Re-open to_fd so we aren't hosed by the rename(2). */ (void) close(to_fd); if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { rc = err(EX_OSERR, "%s", to_name); goto l_done; } } /* * Preserve the timestamp of the source file if necessary. */ if (dopreserve && !files_match && !devnull) { tvb[0].tv_sec = from_sb.st_atime; tvb[0].tv_usec = 0; tvb[1].tv_sec = from_sb.st_mtime; tvb[1].tv_usec = 0; (void)utimes(to_name, tvb); } if (fstat(to_fd, &to_sb) == -1) { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(EX_OSERR, "%s", to_name); goto l_done; } /* * Set owner, group, mode for target; do the chown first, * chown may lose the setuid bits. */ #ifdef UF_IMMUTABLE if ((gid != (gid_t)-1 && gid != to_sb.st_gid) || (uid != (uid_t)-1 && uid != to_sb.st_uid) || (mode != (to_sb.st_mode & ALLPERMS))) { /* Try to turn off the immutable bits. */ if (to_sb.st_flags & NOCHANGEBITS) (void)fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS); } #endif if ((gid != (gid_t)-1 && gid != to_sb.st_gid) || (uid != (uid_t)-1 && uid != to_sb.st_uid)) if (fchown(to_fd, uid, gid) == -1) { if (errno == EPERM && ignore_perm_errors) { warn("%s: ignoring chown uid=%d gid=%d failure", to_name, (int)uid, (int)gid); } else { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(EX_OSERR,"%s: chown/chgrp", to_name); goto l_done; } } if (mode != (to_sb.st_mode & ALLPERMS)) if (fchmod(to_fd, mode)) { serrno = errno; if (serrno == EPERM && ignore_perm_errors) { fchmod(to_fd, mode & (ALLPERMS & ~0007000)); errno = errno; warn("%s: ignoring chmod 0%o failure", to_name, (int)(mode & ALLPERMS)); } else { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(EX_OSERR, "%s: chmod", to_name); goto l_done; } } /* * If provided a set of flags, set them, otherwise, preserve the * flags, except for the dump flag. * NFS does not support flags. Ignore EOPNOTSUPP flags if we're just * trying to turn off UF_NODUMP. If we're trying to set real flags, * then warn if the the fs doesn't support it, otherwise fail. */ #ifdef UF_IMMUTABLE if (!devnull && (flags & SETFLAGS || (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) && fchflags(to_fd, flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { if (flags & SETFLAGS) { if (errno == EOPNOTSUPP) warn("%s: chflags", to_name); else { serrno = errno; (void)unlink(to_name); errno = serrno; rc = err(EX_OSERR, "%s: chflags", to_name); goto l_done; } } } #endif l_done: if (to_fd >= 0) (void)close(to_fd); if (temp_fd >= 0) (void)close(temp_fd); if (from_fd >= 0 && !devnull) (void)close(from_fd); return rc; } /* * compare -- * compare two files; non-zero means files differ */ static int compare(int from_fd, const char *from_name __unused, size_t from_len, int to_fd, const char *to_name __unused, size_t to_len) { char *p, *q; int rv; int done_compare; rv = 0; if (from_len != to_len) return 1; if (from_len <= MAX_CMP_SIZE) { #ifdef USE_MMAP done_compare = 0; if (trymmap(from_fd) && trymmap(to_fd)) { p = mmap(NULL, from_len, PROT_READ, MAP_SHARED, from_fd, (off_t)0); if (p == (char *)MAP_FAILED) goto out; q = mmap(NULL, from_len, PROT_READ, MAP_SHARED, to_fd, (off_t)0); if (q == (char *)MAP_FAILED) { munmap(p, from_len); goto out; } rv = memcmp(p, q, from_len); munmap(p, from_len); munmap(q, from_len); done_compare = 1; } out: #else (void)p; (void)q; done_compare = 0; #endif if (!done_compare) { char buf1[MAXBSIZE]; char buf2[MAXBSIZE]; int n1, n2; rv = 0; lseek(from_fd, 0, SEEK_SET); lseek(to_fd, 0, SEEK_SET); while (rv == 0) { n1 = read(from_fd, buf1, sizeof(buf1)); if (n1 == 0) break; /* EOF */ else if (n1 > 0) { n2 = read(to_fd, buf2, n1); if (n2 == n1) rv = memcmp(buf1, buf2, n1); else rv = 1; /* out of sync */ } else rv = 1; /* read failure */ } lseek(from_fd, 0, SEEK_SET); lseek(to_fd, 0, SEEK_SET); } } else rv = 1; /* don't bother in this case */ return rv; } /* * create_tempfile -- * create a temporary file based on path and open it */ int create_tempfile(const char *path, char *temp, size_t tsize) { char *p; (void)strncpy(temp, path, tsize); temp[tsize - 1] = '\0'; if ((p = last_slash(temp)) != NULL) p++; else p = temp; (void)strncpy(p, "INS@XXXX", &temp[tsize - 1] - p); temp[tsize - 1] = '\0'; return (mkstemp(temp)); } /* * create_newfile -- * create a new file, overwriting an existing one if necessary */ int create_newfile(const char *path, int target, struct stat *sbp) { char backup[MAXPATHLEN]; int saved_errno = 0; int newfd; if (target) { /* * Unlink now... avoid ETXTBSY errors later. Try to turn * off the append/immutable bits -- if we fail, go ahead, * it might work. */ #ifdef UF_IMMUTABLE if (sbp->st_flags & NOCHANGEBITS) (void)chflags(path, sbp->st_flags & ~NOCHANGEBITS); #endif if (dobackup) { if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", path, suffix) != strlen(path) + strlen(suffix)) { errx(EX_OSERR, "%s: backup filename too long", path); errno = ENAMETOOLONG; return -1; } (void)snprintf(backup, MAXPATHLEN, "%s%s", path, suffix); if (verbose) (void)printf("install: %s -> %s\n", path, backup); if (rename(path, backup) < 0) { err(EX_OSERR, "rename: %s to %s", path, backup); return -1; } } else if (unlink(path) < 0) saved_errno = errno; } newfd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR); if (newfd < 0 && saved_errno != 0) errno = saved_errno; return newfd; } /* * copy -- * copy from one file to another */ static int copy(int from_fd, const char *from_name, int to_fd, const char *to_name, off_t size) { int nr, nw; int serrno; char *p, buf[MAXBSIZE]; int done_copy; /* Rewind file descriptors. */ if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1) return err(EX_OSERR, "lseek: %s", from_name); if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1) return err(EX_OSERR, "lseek: %s", to_name); /* * Mmap and write if less than 8M (the limit is so we don't totally * trash memory on big files. This is really a minor hack, but it * wins some CPU back. */ done_copy = 0; #ifdef USE_MMAP if (size <= 8 * 1048576 && trymmap(from_fd) && (p = mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED, from_fd, (off_t)0)) != (char *)MAP_FAILED) { if ((nw = write(to_fd, p, size)) != size) { serrno = errno; (void)unlink(to_name); errno = nw > 0 ? EIO : serrno; err(EX_OSERR, "%s", to_name); } done_copy = 1; } #else (void)p; (void)size; #endif if (!done_copy) { while ((nr = read(from_fd, buf, sizeof(buf))) > 0) if ((nw = write(to_fd, buf, nr)) != nr) { serrno = errno; (void)unlink(to_name); errno = nw > 0 ? EIO : serrno; return err(EX_OSERR, "%s", to_name); } if (nr != 0) { serrno = errno; (void)unlink(to_name); errno = serrno; return err(EX_OSERR, "%s", from_name); } } return EX_OK; } /* * strip -- * use strip(1) to strip the target file */ static int strip(const char *to_name) { #if defined(__EMX__) || defined(_MSC_VER) const char *stripbin = getenv("STRIPBIN"); if (stripbin == NULL) stripbin = "strip"; return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL); #else const char *stripbin; int serrno, status; pid_t pid; pid = fork(); switch (pid) { case -1: serrno = errno; (void)unlink(to_name); errno = serrno; return err(EX_TEMPFAIL, "fork"); case 0: stripbin = getenv("STRIPBIN"); if (stripbin == NULL) stripbin = "strip"; execlp(stripbin, stripbin, to_name, (char *)NULL); err(EX_OSERR, "exec(%s)", stripbin); exit(EX_OSERR); default: if (waitpid(pid, &status, 0) == -1 || status) { serrno = errno; (void)unlink(to_name); errno = serrno; return err(EX_SOFTWARE, "waitpid"); /* NOTREACHED */ } } return 0; #endif } /* * install_dir -- * build directory heirarchy */ static int install_dir(char *path) { char *p; struct stat sb; int ch; for (p = path;; ++p) if ( !*p || ( p != path && IS_SLASH(*p) #if defined(_MSC_VER) /* stat("C:") fails (VC++ v10). Just skip it since it's unnecessary. */ && (p - path != 2 || p[-1] != ':') #endif )) { ch = *p; *p = '\0'; if (stat(path, &sb)) { if (errno != ENOENT || mkdir(path, 0755) < 0) { return err(EX_OSERR, "mkdir %s", path); /* NOTREACHED */ } else if (verbose) (void)printf("install: mkdir %s\n", path); } else if (!S_ISDIR(sb.st_mode)) return errx(EX_OSERR, "%s exists but is not a directory", path); if (!(*p = ch)) break; } if ((gid != (gid_t)-1 || uid != (uid_t)-1) && chown(path, uid, gid)) warn("chown %u:%u %s", uid, gid, path); if (chmod(path, mode)) warn("chmod %o %s", mode, path); return EX_OK; } /* * usage -- * print a usage message and die */ static int usage(FILE *pf) { fprintf(pf, "usage: %s [-bCcpSsv] [--[no-]hard-link-files-when-possible]\n" " [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n" " [-g group] [-m mode] [-o owner] file1 file2\n" " or: %s [-bCcpSsv] [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n" " [-g group] [-m mode] [-o owner] file1 ... fileN directory\n" " or: %s -d [-v] [-g group] [-m mode] [-o owner] directory ...\n" " or: %s --help\n" " or: %s --version\n", g_progname, g_progname, g_progname, g_progname, g_progname); return EX_USAGE; } #ifdef USE_MMAP /* * trymmap -- * return true (1) if mmap should be tried, false (0) if not. */ static int trymmap(int fd) { /* * The ifdef is for bootstrapping - f_fstypename doesn't exist in * pre-Lite2-merge systems. */ #ifdef MFSNAMELEN struct statfs stfs; if (nommap || fstatfs(fd, &stfs) != 0) return (0); if (strcmp(stfs.f_fstypename, "ufs") == 0 || strcmp(stfs.f_fstypename, "cd9660") == 0) return (1); #endif return (0); } #endif /* figures out where the last slash or colon is. */ static char * last_slash(const char *path) { #if defined(__WIN32__) || defined(__WIN64__) || defined(__OS2__) char *p = (char *)strrchr(path, '/'); if (p) { char *p2 = strrchr(p, '\\'); if (p2) p = p2; } else { p = (char *)strrchr(path, '\\'); if (!p && isalpha(path[0]) && path[1] == ':') p = (char *)&path[1]; } return p; #else return strrchr(path, '/'); #endif } kbuild-2695/src/kmk/INSTALL0000644000000000000000000002207112247157306014044 0ustar rootrootInstallation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PREFIX', the package will use PREFIX as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the `--target=TYPE' option to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc will cause the specified gcc to be used as the C compiler (unless it is overridden in the site shell script). `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. kbuild-2695/src/kmk/dosbuild.bat0000644000000000000000000000632412247157307015314 0ustar rootroot@echo off rem Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, rem 2008, 2009, 2010 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . echo Building Make for MSDOS rem Echo ON so they will see what is going on. @echo on gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g commands.c -o commands.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g job.c -o job.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g dir.c -o dir.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g file.c -o file.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g misc.c -o misc.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g main.c -o main.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -DINCLUDEDIR=\"c:/djgpp/include\" -O2 -g read.c -o read.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -DLIBDIR=\"c:/djgpp/lib\" -O2 -g remake.c -o remake.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g rule.c -o rule.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g implicit.c -o implicit.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g default.c -o default.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g variable.c -o variable.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g expand.c -o expand.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g function.c -o function.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g vpath.c -o vpath.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g hash.c -o hash.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g strcache.c -o strcache.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g version.c -o version.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g ar.c -o ar.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g arscan.c -o arscan.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g signame.c -o signame.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g remote-stub.c -o remote-stub.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt.c -o getopt.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt1.c -o getopt1.o @cd glob @if exist libglob.a del libglob.a gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g glob.c -o glob.o gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g fnmatch.c -o fnmatch.o ar rv libglob.a glob.o fnmatch.o @echo off cd .. echo commands.o > respf.$$$ for %%f in (job dir file misc main read remake rule implicit default variable) do echo %%f.o >> respf.$$$ for %%f in (expand function vpath hash strcache version ar arscan signame remote-stub getopt getopt1) do echo %%f.o >> respf.$$$ echo glob/libglob.a >> respf.$$$ @echo Linking... @echo on gcc -o make.new @respf.$$$ @if exist make.exe echo Make.exe is now built! @if not exist make.exe echo Make.exe build failed... @if exist make.exe del respf.$$$ kbuild-2695/src/kmk/alloccache.c0000644000000000000000000001700612247157306015237 0ustar rootroot/* $Id: alloccache.c 2633 2012-09-08 23:18:59Z bird $ */ /** @file * alloccache - Fixed sized allocation cache. * * The rational for using an allocation cache, is that it is way faster * than malloc+free on most systems. It may be more efficient as well, * depending on the way the heap implementes small allocations. Also, * with the incdep.c code being threaded, all heaps (except for MSC) * ran into severe lock contention issues since both the main thread * and the incdep worker thread was allocating a crazy amount of tiny * allocations (struct dep, struct nameseq, ++). * * Darwin also showed a significant amount of time spent just executing * free(), which is kind of silly. The alloccache helps a bit here too. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "make.h" #include "dep.h" #include "debug.h" #include #ifdef CONFIG_WITH_ALLOC_CACHES /* Free am item. This was not inlined because of aliasing issues arrising with GCC. It is also in a separate file for this reason (it used to be in misc.c but since free_dep_chain() was using it there, we ran the risk of it being inlined and gcc screwing up). */ void alloccache_free (struct alloccache *cache, void *item) { #ifndef CONFIG_WITH_ALLOCCACHE_DEBUG struct alloccache_free_ent *f = (struct alloccache_free_ent *)item; # if 0 /*ndef NDEBUG*/ struct alloccache_free_ent *c; unsigned int i = 0; for (c = cache->free_head; c != NULL; c = c->next, i++) MY_ASSERT_MSG (c != f && i < 0x10000000, ("i=%u total_count=%u\n", i, cache->total_count)); # endif f->next = cache->free_head; cache->free_head = f; MAKE_STATS(cache->free_count++;); #else free(item); #endif } /* Default allocator. */ static void * alloccache_default_grow_alloc(void *ignore, unsigned int size) { return xmalloc (size); } /* Worker for growing the cache. */ struct alloccache_free_ent * alloccache_alloc_grow (struct alloccache *cache) { #ifndef CONFIG_WITH_ALLOCCACHE_DEBUG void *item; unsigned int items = (64*1024 - 32) / cache->size; cache->free_start = cache->grow_alloc (cache->grow_arg, items * cache->size); cache->free_end = cache->free_start + items * cache->size; cache->total_count+= items; # ifndef NDEBUG /* skip the first item so the heap can detect free(). */ cache->total_count--; cache->free_start += cache->size; # endif item = cache->free_start; cache->free_start += cache->size; /* caller counts */ return (struct alloccache_free_ent *)item; #else return (struct alloccache_free_ent *)xmalloc(cache->size); #endif } /* List of alloc caches, for printing. */ static struct alloccache *alloccache_head = NULL; /* Initializes an alloc cache */ void alloccache_init (struct alloccache *cache, unsigned int size, const char *name, void *(*grow_alloc)(void *grow_arg, unsigned int size), void *grow_arg) { unsigned act_size; /* ensure OK alignment and min sizeof (struct alloccache_free_ent). */ if (size <= sizeof (struct alloccache_free_ent)) act_size = sizeof (struct alloccache_free_ent); else if (size <= 32) { act_size = 4; while (act_size < size) act_size <<= 1; } else act_size = (size + 31U) & ~(size_t)31; /* align the structure. */ cache->free_start = NULL; cache->free_end = NULL; cache->free_head = NULL; cache->size = act_size; cache->total_count = 0; cache->alloc_count = 0; cache->free_count = 0; cache->name = name; cache->grow_arg = grow_arg; cache->grow_alloc = grow_alloc ? grow_alloc : alloccache_default_grow_alloc; /* link it. */ cache->next = alloccache_head; alloccache_head = cache; } /* Terminate an alloc cache, free all the memory it contains. */ void alloccache_term (struct alloccache *cache, void (*term_free)(void *term_arg, void *ptr, unsigned int size), void *term_arg) { /*cache->size = 0;*/ (void)cache; (void)term_free; (void)term_arg; /* FIXME: Implement memory segment tracking and cleanup. */ } /* Joins to caches, unlinking the 2nd one. */ void alloccache_join (struct alloccache *cache, struct alloccache *eat) { assert (cache->size == eat->size); #if 0 /* probably a waste of time */ /* FIXME: Optimize joining, avoid all list walking. */ /* add the free list... */ if (eat->free_head) { unsigned int eat_in_use = eat->alloc_count - eat->free_count; unsigned int dst_in_use = cache->alloc_count - cache->free_count; if (!cache->free_head) cache->free_head = eat->free_head; else if (eat->total_count - eat_in_use < cache->total_count - dst_ins_use) { struct alloccache_free_ent *last = eat->free_head; while (last->next) last = last->next; last->next = cache->free_head; cache->free_head = eat->free_head; } else { struct alloccache_free_ent *last = cache->free_head; while (last->next) last = last->next; last->next = eat->free_head; } } /* ... and the free space. */ while (eat->free_start != eat->free_end) { struct alloccache_free_ent *f = (struct alloccache_free_ent *)eat->free_start; eat->free_start += eat->size; f->next = cache->free_head; cache->free_head = f; } /* and statistics */ cache->alloc_count += eat->alloc_count; cache->free_count += eat->free_count; #else /* and statistics */ cache->alloc_count += eat->alloc_count; cache->free_count += eat->free_count; #endif cache->total_count += eat->total_count; /* unlink and disable the eat cache */ if (alloccache_head == eat) alloccache_head = eat->next; else { struct alloccache *cur = alloccache_head; while (cur->next != eat) cur = cur->next; assert (cur && cur->next == eat); cur->next = eat->next; } eat->size = 0; eat->free_end = eat->free_start = NULL; eat->free_head = NULL; } /* Print one alloc cache. */ void alloccache_print (struct alloccache *cache) { printf (_("\n# Alloc Cache: %s\n" "# Items: size = %-3u total = %-6u"), cache->name, cache->size, cache->total_count); MAKE_STATS(printf (_(" in-use = %-6lu"), cache->alloc_count - cache->free_count);); MAKE_STATS(printf (_("\n# alloc calls = %-7lu free calls = %-7lu"), cache->alloc_count, cache->free_count);); printf ("\n"); } /* Print all alloc caches. */ void alloccache_print_all (void) { struct alloccache *cur; puts (""); for (cur = alloccache_head; cur; cur = cur->next) alloccache_print (cur); } #endif /* CONFIG_WITH_ALLOC_CACHES */ kbuild-2695/src/kmk/amiga.h0000644000000000000000000000160512247157306014242 0ustar rootroot/* Definitions for amiga specific things Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ int MyExecute (char ** argv); char * wildcard_expansion (char * wc, char * o); kbuild-2695/src/kmk/electric.h0000644000000000000000000000250612247157306014757 0ustar rootroot/* $Id: electric.h 2591 2012-06-17 20:45:31Z bird $ */ /** @file * A simple electric heap implementation, wrapper header. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifdef ELECTRIC_HEAP #include #ifdef WINDOWS32 # include #endif #include /* strdup */ void xfree (void *); void *xcalloc (unsigned int); void *xmalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); #define free(a) xfree(a) #define calloc(a,b) xcalloc((a) * (b)) #define malloc(a) xmalloc(a) #define realloc(a,b) xrealloc((a),(b)) #define strdup(a) xstrdup(a) #endif kbuild-2695/src/kmk/testcase-local.kmk0000644000000000000000000000552212247157307016425 0ustar rootroot# # local variables: # o The keyword will make sure the variable is defined in # current variable context instead of the global one. # o Local variables are readable by children but not writable, # writes goes to the globle space (a sideeffect / feature). # o Local variables hides global and parent variables. # # global variable. var_exists1 = 1 ## # A simple define that is $(eval)uated. define def_test1 # check that the existing variable is accessible. ifneq ($(var_exists1),1) $(error var_exists1=$(var_exists1) (def_test1/1)) endif # Quick check with a couple of local variables. local var_local1 = 2 ifneq ($(var_local1),2) $(error var_local1=$(var_local1) (def_test1/2)) endif local var_local2 = 3 ifneq ($(var_local2),3) $(error var_local2=$(var_local2) (def_test1/3)) endif # var_local1 and var_local2 should remain unchanged, var_local3 shouldn't exist. $(evalctx $(value def_test2)) ifneq ($(var_local1),2) $(error var_local1=$(var_local1) (def_test1/4)) endif ifneq ($(var_local2),3) $(error var_local2=$(var_local2) (def_test1/5)) endif ifneq ($(var_local3),) $(error var_local3=$(var_local3) (def_test1/6)) endif endef # def_test1 ## # Called by def_test1, this checks that the locals of def_test1 # are accessible and can be hidden by another local variable # or updated if assigned to. define def_test2 # check that the existing variables are accessible, including the def_test1 ones. ifneq ($(var_exists1),1) $(error var_exists1=$(var_exists1) (def_test2/1)) endif ifneq ($(var_local1),2) $(error var_local1=$(var_local1) (def_test2/2)) endif ifneq ($(var_local2),3) $(error var_local2=$(var_local2) (def_test2/3)) endif # Make a local var_local1 that hides the one in def_test1. local var_local1 = 20 ifneq ($(var_local1),20) $(error var_local1=$(var_local1) (def_test2/4)) endif # FEATURE: Update the var_local2 variable, this should be visible in the global space and not the local. var_local2 = 30 ifneq ($(var_local2),3) $(error var_local2=$(var_local2) (def_test2/5)) endif # create a new local variable that isn't accessible from def_test1. local var_local3 = 4 ifneq ($(var_local3),4) $(error var_local3=$(var_local3) (def_test2/6)) endif endef # def_test2 # # The test body # # None of the local variables should exist. ifneq ($(var_local1),) $(error var_local1=$(var_local1)) endif ifneq ($(var_local2),) $(error var_local2=$(var_local2)) endif ifneq ($(var_local3),) $(error var_local3=$(var_local3)) endif # Evaluate the function in a local context. $(evalctx $(value def_test1)) # FEATURE: see var_local2 = 30 in def_test2. ifneq ($(var_local2),30) $(error var_local2=$(var_local2)) endif # None of the other local variables should exist. ifneq ($(var_local1),) $(error var_local1=$(var_local1)) endif ifneq ($(var_local3),) $(error var_local3=$(var_local3)) endif # dummy all: echo local variables works. kbuild-2695/src/kmk/remote-stub.c0000644000000000000000000000565512247157307015437 0ustar rootroot/* Template for the remote job exportation interface to GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "filedef.h" #include "job.h" #include "commands.h" char *remote_description = 0; /* Call once at startup even if no commands are run. */ void remote_setup (void) { } /* Called before exit. */ void remote_cleanup (void) { } /* Return nonzero if the next job should be done remotely. */ int start_remote_job_p (int first_p UNUSED) { return 0; } /* Start a remote job running the command in ARGV, with environment from ENVP. It gets standard input from STDIN_FD. On failure, return nonzero. On success, return zero, and set *USED_STDIN to nonzero if it will actually use STDIN_FD, zero if not, set *ID_PTR to a unique identification, and set *IS_REMOTE to zero if the job is local, nonzero if it is remote (meaning *ID_PTR is a process ID). */ int start_remote_job (char **argv UNUSED, char **envp UNUSED, int stdin_fd UNUSED, int *is_remote UNUSED, int *id_ptr UNUSED, int *used_stdin UNUSED) { return -1; } /* Get the status of a dead remote child. Block waiting for one to die if BLOCK is nonzero. Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR to the termination signal or zero if it exited normally, and *COREDUMP_PTR nonzero if it dumped core. Return the ID of the child that died, 0 if we would have to block and !BLOCK, or < 0 if there were none. */ int remote_status (int *exit_code_ptr UNUSED, int *signal_ptr UNUSED, int *coredump_ptr UNUSED, int block UNUSED) { errno = ECHILD; return -1; } /* Block asynchronous notification of remote child death. If this notification is done by raising the child termination signal, do not block that signal. */ void block_remote_children (void) { return; } /* Restore asynchronous notification of remote child death. If this is done by raising the child termination signal, do not unblock that signal. */ void unblock_remote_children (void) { return; } /* Send signal SIG to child ID. Return 0 if successful, -1 if not. */ int remote_kill (int id UNUSED, int sig UNUSED) { return -1; } kbuild-2695/src/kmk/testcase-xargs.kmk0000644000000000000000000000404612247157306016456 0ustar rootroot# $Id: testcase-xargs.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the xargs function. # Requires manual inspection of the output. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifneq ($(not 1),) $(error The 'not' function is missing) endif ifneq ($(eq 1,1),1) $(error The 'eq' function is missing) endif ASSERT_TRUE = $(if $(not $(1)),$(error failure: '$(1)' isn't true)) ASSERT_FALSE = $(if $(1) ,$(error failure: '$(1)' isn't false)) # 94 bytes ONEARG = abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_xxxxxxxxxxxx ITERATIONS := 0 1 2 3 4 5 6 7 8 9 ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS))) ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS))) ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS))) ITERATIONS := $(foreach i, 0 1 2 3 4 5 6 7 8 9,$(addprefix $(i),$(ITERATIONS))) # add a 5 bytes sequence number and a space, then duplicate it 10000 times: # 100 bytes * 10000 = 1,000,000 bytes. REALLY_LONG := $(foreach i,$(ITERATIONS),$(i)$(ONEARG)) #$(call ASSERT_TRUE, $(xargs $(ECHO) 1:, $(ECHO) 2:, $(ECHO) 3:, asdf asdf asdf asdf asdf asdf asdf adf asdf asdf)) all_recursive: $(xargs @$(ECHO_EXT) 1:, @$(ECHO_EXT) 2:, @$(ECHO_EXT) 3:, $(REALLY_LONG)) $(ECHO) done kbuild-2695/src/kmk/make_msvc_net2003.vcproj0000644000000000000000000001613412247157306017363 0ustar rootroot kbuild-2695/src/kmk/build.template0000644000000000000000000000507412247157306015653 0ustar rootroot#!/bin/sh # Shell script to build GNU Make in the absence of any `make' program. # @configure_input@ # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # See Makefile.in for comments describing these variables. srcdir='@srcdir@' CC='@CC@' CFLAGS='@CFLAGS@' CPPFLAGS='@CPPFLAGS@' LDFLAGS='@LDFLAGS@' ALLOCA='@ALLOCA@' LOADLIBES='@LIBS@ @LIBINTL@' eval extras=\'@LIBOBJS@\' REMOTE='@REMOTE@' GLOBLIB='@GLOBLIB@' PATH_SEPARATOR='@PATH_SEPARATOR@' OBJEXT='@OBJEXT@' EXEEXT='@EXEEXT@' # Common prefix for machine-independent installed files. prefix='@prefix@' # Common prefix for machine-dependent installed files. exec_prefix=`eval echo @exec_prefix@` # Directory to find libraries in for `-lXXX'. libdir=${exec_prefix}/lib # Directory to search by default for included makefiles. includedir=${prefix}/include localedir=${prefix}/share/locale aliaspath=${localedir}${PATH_SEPARATOR}. defines="-DALIASPATH=\"${aliaspath}\" -DLOCALEDIR=\"${localedir}\" -DLIBDIR=\"${libdir}\" -DINCLUDEDIR=\"${includedir}\""' @DEFS@' # Exit as soon as any command fails. set -e # These are all the objects we need to link together. objs="%objs% remote-${REMOTE}.${OBJEXT} ${extras} ${ALLOCA}" if [ x"$GLOBLIB" != x ]; then objs="$objs %globobjs%" globinc=-I${srcdir}/glob fi # Compile the source files into those objects. for file in `echo ${objs} | sed 's/\.'${OBJEXT}'/.c/g'`; do echo compiling ${file}... $CC $defines $CPPFLAGS $CFLAGS \ -c -I. -I${srcdir} ${globinc} ${srcdir}/$file done # The object files were actually all put in the current directory. # Remove the source directory names from the list. srcobjs="$objs" objs= for obj in $srcobjs; do objs="$objs `basename $obj`" done # Link all the objects together. echo linking make... $CC $CFLAGS $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT} echo done mv -f makenew${EXEEXT} make${EXEEXT} kbuild-2695/src/kmk/Makefile.am0000644000000000000000000002136112247157307015051 0ustar rootroot# This is a -*-Makefile-*-, or close enough # # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . AUTOMAKE_OPTIONS = 1.8 dist-bzip2 check-news ACLOCAL_AMFLAGS = -I config MAKE_HOST = @MAKE_HOST@ # Only process if target is MS-Windows if WINDOWSENV MAYBE_W32 = w32 W32INC = -I $(top_srcdir)/w32/include W32LIB = -Lw32 -lw32 endif # we can safely drop doc and po when bootstrapping kmk. # SUBDIRS = glob config po doc $(MAYBE_W32) SUBDIRS = glob config $(MAYBE_W32) bin_PROGRAMS = kmk kmk_redirect if USE_CUSTOMS remote = remote-cstms.c else remote = remote-stub.c endif kmk_SOURCES = ar.c arscan.c commands.c default.c dir.c expand.c file.c \ function.c getopt.c getopt1.c implicit.c job.c main.c \ misc.c read.c remake.c $(remote) rule.c signame.c \ strcache.c variable.c version.c vpath.c hash.c \ \ expreval.c \ incdep.c \ strcache2.c \ alloccache.c \ kbuild.c \ kbuild-read.c \ electric.c \ ../lib/md5.c \ ../lib/kDep.c \ \ kmkbuiltin.c \ kmkbuiltin/append.c \ kmkbuiltin/cat.c \ kmkbuiltin/chmod.c \ kmkbuiltin/cmp.c \ kmkbuiltin/cmp_util.c \ kmkbuiltin/cp.c \ kmkbuiltin/cp_utils.c \ kmkbuiltin/echo.c \ kmkbuiltin/expr.c \ kmkbuiltin/install.c \ kmkbuiltin/kDepIDB.c \ kmkbuiltin/kDepObj.c \ kmkbuiltin/ln.c \ kmkbuiltin/md5sum.c \ kmkbuiltin/mkdir.c \ kmkbuiltin/mv.c \ kmkbuiltin/printf.c \ kmkbuiltin/rm.c \ kmkbuiltin/rmdir.c \ kmkbuiltin/sleep.c \ kmkbuiltin/test.c \ kmkbuiltin/err.c \ kmkbuiltin/fts.c \ kmkbuiltin/setmode.c \ kmkbuiltin/strmode.c \ kmkbuiltin/strlcpy.c \ kmkbuiltin/osdep.c \ kmkbuiltin/kbuild_protection.c \ kmkbuiltin/kbuild_version.c kmk_redirect_SOURCES = kmkbuiltin/redirect.c EXTRA_kmk_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c noinst_HEADERS = commands.h dep.h filedef.h job.h make.h rule.h variable.h \ debug.h getopt.h gettext.h hash.h #kmk_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@ kmk_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ # Only process if target is MS-Windows if WINDOWSENV kmk_LDADD += $(W32LIB) endif man_MANS = make.1 # org - DEFS = -DLOCALEDIR=\"$(localedir)\" -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\" @DEFS@ DEFS = \ -DNO_ARCHIVES \ -DEXPERIMENTAL \ -DCONFIG_WITH_TOUPPER_TOLOWER \ -DCONFIG_WITH_DEFINED \ -DCONFIG_WITH_EXPLICIT_MULTITARGET \ -DCONFIG_WITH_DOT_MUST_MAKE \ -DCONFIG_WITH_PREPEND_ASSIGNMENT \ -DCONFIG_WITH_LOCAL_VARIABLES \ -DCONFIG_WITH_2ND_TARGET_EXPANSION \ -DCONFIG_WITH_ALLOC_CACHES \ -DCONFIG_WITH_STRCACHE2 \ \ -DKMK \ -DKMK_HELPERS \ -DCONFIG_NO_DEFAULT_SUFFIXES \ -DCONFIG_NO_DEFAULT_PATTERN_RULES \ -DCONFIG_NO_DEFAULT_TERMINAL_RULES \ -DCONFIG_NO_DEFAULT_SUFFIX_RULES \ -DCONFIG_NO_DEFAULT_VARIABLES \ -DCONFIG_WITH_EXTENDED_NOTPARALLEL \ -DCONFIG_WITH_INCLUDEDEP \ -DCONFIG_WITHOUT_THREADS \ -DCONFIG_WITH_VALUE_LENGTH \ \ -DCONFIG_WITH_ABSPATHEX \ -DCONFIG_WITH_COMMANDS_FUNC \ -DCONFIG_WITH_DATE \ -DCONFIG_WITH_DEFINED_FUNCTIONS \ -DCONFIG_WITH_EVALPLUS \ -DCONFIG_WITH_FILE_SIZE \ -DCONFIG_WITH_LOOP_FUNCTIONS \ -DCONFIG_WITH_MATH \ -DCONFIG_WITH_NANOTS \ -DCONFIG_WITH_ROOT_FUNC \ -DCONFIG_WITH_RSORT \ -DCONFIG_WITH_STACK \ -DCONFIG_WITH_STRING_FUNCTIONS \ -DCONFIG_WITH_WHERE_FUNCTION \ -DCONFIG_WITH_WHICH \ -DCONFIG_WITH_XARGS \ \ -DCONFIG_WITH_COMPARE \ -DCONFIG_WITH_SET_CONDITIONALS \ -DCONFIG_WITH_IF_CONDITIONALS \ -DCONFIG_WITH_PRINTF \ -DCONFIG_WITH_MINIMAL_STATS \ -DCONFIG_PRETTY_COMMAND_PRINTING \ -DCONFIG_WITH_PRINT_STATS_SWITCH \ -DCONFIG_WITH_PRINT_TIME_SWITCH \ -DCONFIG_WITH_RDONLY_VARIABLE_VALUE \ -DCONFIG_WITH_LAZY_DEPS_VARS \ \ -DKBUILD_TYPE=\"$(KBUILD_TYPE)\" \ -DKBUILD_HOST=\"$(KBUILD_TARGET)\" \ -DKBUILD_HOST_ARCH=\"$(KBUILD_TARGET_ARCH)\" \ -DKBUILD_HOST_CPU=\"$(KBUILD_TARGET_CPU)\" \ \ -DKBUILD_SVN_REV=1 \ -DKBUILD_VERSION_MAJOR=0 \ -DKBUILD_VERSION_MINOR=1 \ -DKBUILD_VERSION_PATCH=9998 \ \ -DCONFIG_WITH_KMK_BUILTIN \ @DEFS@ AM_CPPFLAGS = $(GLOBINC) -I$(srcdir)/../lib # Only process if target is MS-Windows if WINDOWSENV AM_CPPFLAGS += $(W32INC) endif # Extra stuff to include in the distribution. EXTRA_DIST = README build.sh.in $(man_MANS) \ README.customs README.OS2 \ SCOPTIONS SMakefile \ README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h \ README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\ README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat \ make_msvc_net2003.sln make_msvc_net2003.vcproj \ readme.vms makefile.vms makefile.com config.h-vms \ vmsdir.h vmsfunctions.c vmsify.c # This is built during configure, but behind configure's back DISTCLEANFILES = build.sh # Forward targets html: cd doc && $(MAKE) $(AM_MAKEFLAGS) $@ .PHONY: html # --------------- Internationalization Section localedir = $(datadir)/locale # --------------- Local INSTALL Section # If necessary, change the gid of the app and turn on the setgid flag. # # Whether or not make needs to be installed setgid. # The value should be either `true' or `false'. # On many systems, the getloadavg function (used to implement the `-l' # switch) will not work unless make is installed setgid kmem. # inst_setgid = @NEED_SETGID@ # Install make setgid to this group so it can get the load average. # inst_group = @KMEM_GROUP@ install-exec-local: @if $(inst_setgid); then \ app=$(DESTDIR)$(bindir)/`echo $(bin_PROGRAMS)|sed '$(transform)'`; \ if chgrp $(inst_group) $$app && chmod g+s $$app; then \ echo "chgrp $(inst_group) $$app && chmod g+s $$app"; \ else \ echo "$$app needs to be owned by group $(inst_group) and setgid;"; \ echo "otherwise the \`-l' option will probably not work."; \ echo "You may need special privileges to complete the installation"; \ echo "of $$app."; \ fi; \ else true; fi # --------------- Local DIST Section # Install the w32 and tests subdirectories # dist-hook: (cd $(srcdir); \ sub=`find w32 tests -follow \( -name CVS -prune -o -name .cvsignore -o -name work -prune \) -o \( -name \*.orig -o -name \*.rej -o -name \*~ -prune \) -o -type f -print`; \ tar chf - $$sub) \ | (cd $(distdir); tar xfBp -) # --------------- Local CHECK Section check-local: check-regression check-loadavg @banner=" Regression PASSED: GNU Make $(VERSION) ($(MAKE_HOST)) built with $(CC) "; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes"; \ echo .PHONY: check-loadavg check-regression check-loadavg: loadavg$(EXEEXT) @echo The system uptime program believes the load average to be: -uptime @echo The GNU load average checking code thinks: -./loadavg$(EXEEXT) # The loadavg function is invoked during "make check" to test getloadavg. check_PROGRAMS = loadavg nodist_loadavg_SOURCES = getloadavg.c loadavg_CPPFLAGS = -DTEST loadavg_LDADD = @GETLOADAVG_LIBS@ # > check-regression # # Look for the make test suite, and run it if found and we can find perl. # If we're building outside the tree, we use symlinks to make a local copy of # the test suite. Unfortunately the test suite itself isn't localizable yet. # MAKETESTFLAGS = check-regression: @if test -f "$(srcdir)/tests/run_make_tests"; then \ if $(PERL) -v >/dev/null 2>&1; then \ case `cd $(srcdir); pwd` in `pwd`) : ;; \ *) test -d tests || mkdir tests; \ rm -f srctests; \ if ln -s "$(srcdir)/tests" srctests; then \ for f in run_make_tests run_make_tests.pl test_driver.pl scripts; do \ rm -f tests/$$f; ln -s ../srctests/$$f tests; \ done; fi ;; \ esac; \ echo "cd tests && $(PERL) ./run_make_tests.pl -make ../make$(EXEEXT) $(MAKETESTFLAGS)"; \ cd tests && $(PERL) ./run_make_tests.pl -make ../make$(EXEEXT) $(MAKETESTFLAGS); \ else \ echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \ fi; \ else \ echo "Can't find the GNU Make test suite ($(srcdir)/tests)."; \ fi # --------------- Maintainer's Section # Tell automake that I haven't forgotten about this file and it will be # created before we build a distribution (see maintMakefile in the CVS # distribution). README: @MAINT_MAKEFILE@ kbuild-2695/src/kmk/.purify0000644000000000000000000000112412247157306014326 0ustar rootroot# Solaris (2.5.1) has a couple if issues. # suppress plk malloc; setvbuf "libc*"; main "main.c" suppress umr kstat_read; kstat_chain_update; kstat_open; getloadavg suppress umr kstat_chain_update; kstat_open; getloadavg # The command line options stuff leaks a little bit. No big deal. # suppress mlk malloc; xmalloc "misc.c"; decode_env_switches "main.c" suppress plk malloc; xmalloc "misc.c"; decode_env_switches "main.c" suppress mlk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c" suppress plk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c" kbuild-2695/src/kmk/kbuild.c0000644000000000000000000030113312247157306014430 0ustar rootroot/* $Id: kbuild.c 2540 2011-08-02 20:13:24Z bird $ */ /** @file * kBuild specific make functionality. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /* No GNU coding style here! */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "make.h" #include "filedef.h" #include "variable.h" #include "dep.h" #include "debug.h" #ifdef WINDOWS32 # include "pathstuff.h" # include #endif #if defined(__APPLE__) # include #endif #if defined(__FreeBSD__) # include # include #endif #include "kbuild.h" #include /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** Helper for passing a string constant to kbuild_get_variable_n. */ #define ST(strconst) strconst, sizeof(strconst) - 1 #if 1 # define my_memcpy(dst, src, len) \ do { \ if (len > 8) \ memcpy(dst, src, len); \ else \ switch (len) \ { \ case 8: dst[7] = src[7]; \ case 7: dst[6] = src[6]; \ case 6: dst[5] = src[5]; \ case 5: dst[4] = src[4]; \ case 4: dst[3] = src[3]; \ case 3: dst[2] = src[2]; \ case 2: dst[1] = src[1]; \ case 1: dst[0] = src[0]; \ case 0: break; \ } \ } while (0) #elif defined(__GNUC__) # define my_memcpy __builtin_memcpy #elif defined(_MSC_VER) # pragma instrinic(memcpy) # define my_memcpy memcpy #endif /******************************************************************************* * Global Variables * *******************************************************************************/ /** The argv[0] passed to main. */ static const char *g_pszExeName; /** The initial working directory. */ static char *g_pszInitialCwd; /** * Initialize kBuild stuff. * * @param argc Number of arguments to main(). * @param argv The main() argument vector. */ void init_kbuild(int argc, char **argv) { int rc; PATH_VAR(szTmp); /* * Get the initial cwd for use in my_abspath. */ #ifdef WINDOWS32 if (getcwd_fs(szTmp, GET_PATH_MAX) != 0) #else if (getcwd(szTmp, GET_PATH_MAX) != 0) #endif g_pszInitialCwd = xstrdup(szTmp); else fatal(NILF, _("getcwd failed")); /* * Determin the executable name. */ rc = -1; #if defined(__APPLE__) { const char *pszImageName = _dyld_get_image_name(0); if (pszImageName) { size_t cchImageName = strlen(pszImageName); if (cchImageName < GET_PATH_MAX) { memcpy(szTmp, pszImageName, cchImageName + 1); rc = 0; } } } #elif defined(__FreeBSD__) rc = readlink("/proc/curproc/file", szTmp, GET_PATH_MAX - 1); if (rc < 0 || rc == GET_PATH_MAX - 1) { rc = -1; # if 0 /* doesn't work because l_name isn't always absolute, it's just argv0 from exec or something. */ /* /proc is optional, try rtdl. */ void *hExe = dlopen(NULL, 0); rc = -1; if (hExe) { struct link_map const *pLinkMap = 0; if (dlinfo(hExe, RTLD_DI_LINKMAP, &pLinkMap) == 0) { const char *pszImageName = pLinkMap->l_name; size_t cchImageName = strlen(pszImageName); if (cchImageName < GET_PATH_MAX) { memcpy(szTmp, pszImageName, cchImageName + 1); rc = 0; } } } # endif } else szTmp[rc] = '\0'; #elif defined(__gnu_linux__) || defined(__linux__) rc = readlink("/proc/self/exe", szTmp, GET_PATH_MAX - 1); if (rc < 0 || rc == GET_PATH_MAX - 1) rc = -1; else szTmp[rc] = '\0'; #elif defined(__OS2__) _execname(szTmp, GET_PATH_MAX); rc = 0; #elif defined(__sun__) { char szTmp2[64]; snprintf(szTmp2, sizeof(szTmp2), "/proc/%ld/path/a.out", (long)getpid()); rc = readlink(szTmp2, szTmp, GET_PATH_MAX - 1); if (rc < 0 || rc == GET_PATH_MAX - 1) rc = -1; else szTmp[rc] = '\0'; } #elif defined(WINDOWS32) if (GetModuleFileName(GetModuleHandle(NULL), szTmp, GET_PATH_MAX)) rc = 0; #endif #if !defined(__OS2__) && !defined(WINDOWS32) /* fallback, try use the path to locate the binary. */ if ( rc < 0 && access(argv[0], X_OK)) { size_t cchArgv0 = strlen(argv[0]); const char *pszPath = getenv("PATH"); char *pszCopy = xstrdup(pszPath ? pszPath : "."); char *psz = pszCopy; while (*psz) { size_t cch; char *pszEnd = strchr(psz, PATH_SEPARATOR_CHAR); if (!pszEnd) pszEnd = strchr(psz, '\0'); cch = pszEnd - psz; if (cch + cchArgv0 + 2 <= GET_PATH_MAX) { memcpy(szTmp, psz, cch); szTmp[cch] = '/'; memcpy(&szTmp[cch + 1], argv[0], cchArgv0 + 1); if (!access(szTmp, X_OK)) { rc = 0; break; } } /* next */ psz = pszEnd; while (*psz == PATH_SEPARATOR_CHAR) psz++; } free(pszCopy); } #endif if (rc < 0) g_pszExeName = argv[0]; else g_pszExeName = xstrdup(szTmp); (void)argc; } /** * Wrapper that ensures correct starting_directory. */ static char *my_abspath(const char *pszIn, char *pszOut) { char *pszSaved, *pszRet; pszSaved = starting_directory; starting_directory = g_pszInitialCwd; pszRet = abspath(pszIn, pszOut); starting_directory = pszSaved; return pszRet; } /** * Determin the KBUILD_PATH value. * * @returns Pointer to static a buffer containing the value (consider it read-only). */ const char *get_kbuild_path(void) { static const char *s_pszPath = NULL; if (!s_pszPath) { PATH_VAR(szTmpPath); const char *pszEnvVar = getenv("KBUILD_PATH"); if ( !pszEnvVar || !my_abspath(pszEnvVar, szTmpPath)) { pszEnvVar = getenv("PATH_KBUILD"); if ( !pszEnvVar || !my_abspath(pszEnvVar, szTmpPath)) { #ifdef KBUILD_PATH return s_pszPath = KBUILD_PATH; #else /* $(abspath $(KBUILD_BIN_PATH)/../..)*/ size_t cch = strlen(get_kbuild_bin_path()); char *pszTmp2 = alloca(cch + sizeof("/../..")); strcat(strcpy(pszTmp2, get_kbuild_bin_path()), "/../.."); if (!my_abspath(pszTmp2, szTmpPath)) fatal(NILF, _("failed to determin KBUILD_PATH")); #endif } } s_pszPath = xstrdup(szTmpPath); } return s_pszPath; } /** * Determin the KBUILD_BIN_PATH value. * * @returns Pointer to static a buffer containing the value (consider it read-only). */ const char *get_kbuild_bin_path(void) { static const char *s_pszPath = NULL; if (!s_pszPath) { PATH_VAR(szTmpPath); const char *pszEnvVar = getenv("KBUILD_BIN_PATH"); if ( !pszEnvVar || !my_abspath(pszEnvVar, szTmpPath)) { pszEnvVar = getenv("PATH_KBUILD_BIN"); if ( !pszEnvVar || !my_abspath(pszEnvVar, szTmpPath)) { #ifdef KBUILD_PATH return s_pszPath = KBUILD_BIN_PATH; #else /* $(abspath $(dir $(ARGV0)).) */ size_t cch = strlen(g_pszExeName); char *pszTmp2 = alloca(cch + sizeof(".")); char *pszSep = pszTmp2 + cch - 1; memcpy(pszTmp2, g_pszExeName, cch); # ifdef HAVE_DOS_PATHS while (pszSep >= pszTmp2 && *pszSep != '/' && *pszSep != '\\' && *pszSep != ':') # else while (pszSep >= pszTmp2 && *pszSep != '/') # endif pszSep--; if (pszSep >= pszTmp2) strcpy(pszSep + 1, "."); else strcpy(pszTmp2, "."); if (!my_abspath(pszTmp2, szTmpPath)) fatal(NILF, _("failed to determin KBUILD_BIN_PATH (pszTmp2=%s szTmpPath=%s)"), pszTmp2, szTmpPath); #endif /* !KBUILD_PATH */ } } s_pszPath = xstrdup(szTmpPath); } return s_pszPath; } /** * Determin the location of default kBuild shell. * * @returns Pointer to static a buffer containing the location (consider it read-only). */ const char *get_default_kbuild_shell(void) { static char *s_pszDefaultShell = NULL; if (!s_pszDefaultShell) { #if defined(__OS2__) || defined(_WIN32) || defined(WINDOWS32) static const char s_szShellName[] = "/kmk_ash.exe"; #else static const char s_szShellName[] = "/kmk_ash"; #endif const char *pszBin = get_kbuild_bin_path(); size_t cchBin = strlen(pszBin); s_pszDefaultShell = xmalloc(cchBin + sizeof(s_szShellName)); memcpy(s_pszDefaultShell, pszBin, cchBin); memcpy(&s_pszDefaultShell[cchBin], s_szShellName, sizeof(s_szShellName)); } return s_pszDefaultShell; } #ifdef KMK_HELPERS /** * Applies the specified default path to any relative paths in *ppsz. * * @param pDefPath The default path. * @param ppsz Pointer to the string pointer. If we expand anything, *ppsz * will be replaced and the caller is responsible for calling free() on it. * @param pcch IN: *pcch contains the current string length. * OUT: *pcch contains the new string length. * @param pcchAlloc *pcchAlloc contains the length allocated for the string. Can be NULL. * @param fCanFree Whether *ppsz should be freed when we replace it. */ static void kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, unsigned int *pcch, unsigned int *pcchAlloc, int fCanFree) { const char *pszIterator; const char *pszInCur; unsigned int cchInCur; unsigned int cRelativePaths; /* * The first pass, count the relative paths. */ cRelativePaths = 0; pszIterator = *ppsz; while ((pszInCur = find_next_token(&pszIterator, &cchInCur))) { /* is relative? */ #ifdef HAVE_DOS_PATHS if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':')) #else if (pszInCur[0] != '/') #endif cRelativePaths++; } /* * The second pass construct the new string. */ if (cRelativePaths) { const size_t cchOut = *pcch + cRelativePaths * (pDefPath->value_length + 1) + 1; char *pszOut = xmalloc(cchOut); char *pszOutCur = pszOut; const char *pszInNextCopy = *ppsz; cRelativePaths = 0; pszIterator = *ppsz; while ((pszInCur = find_next_token(&pszIterator, &cchInCur))) { /* is relative? */ #ifdef HAVE_DOS_PATHS if (pszInCur[0] != '/' && pszInCur[0] != '\\' && (cchInCur < 2 || pszInCur[1] != ':')) #else if (pszInCur[0] != '/') #endif { PATH_VAR(szAbsPathIn); PATH_VAR(szAbsPathOut); if (pDefPath->value_length + cchInCur + 1 >= GET_PATH_MAX) continue; /* Create the abspath input. */ memcpy(szAbsPathIn, pDefPath->value, pDefPath->value_length); szAbsPathIn[pDefPath->value_length] = '/'; memcpy(&szAbsPathIn[pDefPath->value_length + 1], pszInCur, cchInCur); szAbsPathIn[pDefPath->value_length + 1 + cchInCur] = '\0'; if (abspath(szAbsPathIn, szAbsPathOut) != NULL) { const size_t cchAbsPathOut = strlen(szAbsPathOut); assert(cchAbsPathOut <= pDefPath->value_length + 1 + cchInCur); /* copy leading input */ if (pszInCur != pszInNextCopy) { const size_t cchCopy = pszInCur - pszInNextCopy; memcpy(pszOutCur, pszInNextCopy, cchCopy); pszOutCur += cchCopy; } pszInNextCopy = pszInCur + cchInCur; /* copy out the abspath. */ memcpy(pszOutCur, szAbsPathOut, cchAbsPathOut); pszOutCur += cchAbsPathOut; } } } /* the final copy (includes the nil). */ cchInCur = *ppsz + *pcch - pszInNextCopy; memcpy(pszOutCur, pszInNextCopy, cchInCur); pszOutCur += cchInCur; *pszOutCur = '\0'; assert((size_t)(pszOutCur - pszOut) < cchOut); /* set return values */ if (fCanFree) free(*ppsz); *ppsz = pszOut; *pcch = pszOutCur - pszOut; if (pcchAlloc) *pcchAlloc = cchOut; } } /** * Gets a variable that must exist. * Will cause a fatal failure if the variable doesn't exist. * * @returns Pointer to the variable. * @param pszName The variable name. * @param cchName The name length. */ MY_INLINE struct variable * kbuild_get_variable_n(const char *pszName, size_t cchName) { struct variable *pVar = lookup_variable(pszName, cchName); if (!pVar) fatal(NILF, _("variable `%.*s' isn't defined!"), (int)cchName, pszName); if (pVar->recursive) fatal(NILF, _("variable `%.*s' is defined as `recursive' instead of `simple'!"), (int)cchName, pszName); MY_ASSERT_MSG(strlen(pVar->value) == pVar->value_length, ("%u != %u %.*s\n", pVar->value_length, (unsigned int)strlen(pVar->value), (int)cchName, pVar->name)); return pVar; } /** * Gets a variable that must exist and can be recursive. * Will cause a fatal failure if the variable doesn't exist. * * @returns Pointer to the variable. * @param pszName The variable name. */ static struct variable * kbuild_get_recursive_variable(const char *pszName) { struct variable *pVar = lookup_variable(pszName, strlen(pszName)); if (!pVar) fatal(NILF, _("variable `%s' isn't defined!"), pszName); MY_ASSERT_MSG(strlen(pVar->value) == pVar->value_length, ("%u != %u %s\n", pVar->value_length, (unsigned int)strlen(pVar->value), pVar->name)); return pVar; } /** * Gets a variable that doesn't have to exit, but if it does can be recursive. * * @returns Pointer to the variable. * NULL if not found. * @param pszName The variable name. Doesn't need to be terminated. * @param cchName The name length. */ static struct variable * kbuild_query_recursive_variable_n(const char *pszName, size_t cchName) { struct variable *pVar = lookup_variable(pszName, cchName); MY_ASSERT_MSG(!pVar || strlen(pVar->value) == pVar->value_length, ("%u != %u %.*s\n", pVar->value_length, (unsigned int)strlen(pVar->value), (int)cchName, pVar->name)); return pVar; } /** * Gets a variable that doesn't have to exit, but if it does can be recursive. * * @returns Pointer to the variable. * NULL if not found. * @param pszName The variable name. */ static struct variable * kbuild_query_recursive_variable(const char *pszName) { return kbuild_query_recursive_variable_n(pszName, strlen(pszName)); } /** * Converts the specified variable into a 'simple' one. * @returns pVar. * @param pVar The variable. */ static struct variable * kbuild_simplify_variable(struct variable *pVar) { if (memchr(pVar->value, '$', pVar->value_length)) { unsigned int value_len; char *pszExpanded = allocated_variable_expand_2(pVar->value, pVar->value_length, &value_len); #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (pVar->rdonly_val) pVar->rdonly_val = 0; else #endif free(pVar->value); assert(pVar->origin != o_automatic); pVar->value = pszExpanded; pVar->value_length = value_len; pVar->value_alloc_len = value_len + 1; } pVar->recursive = 0; return pVar; } /** * Looks up a variable. * The value_length field is valid upon successful return. * * @returns Pointer to the variable. NULL if not found. * @param pszName The variable name. * @param cchName The name length. */ MY_INLINE struct variable * kbuild_lookup_variable_n(const char *pszName, size_t cchName) { struct variable *pVar = lookup_variable(pszName, cchName); if (pVar) { MY_ASSERT_MSG(strlen(pVar->value) == pVar->value_length, ("%u != %u %.*s\n", pVar->value_length, (unsigned int)strlen(pVar->value), (int)cchName, pVar->name)); /* Make sure the variable is simple, convert it if necessary. */ if (pVar->recursive) kbuild_simplify_variable(pVar); } return pVar; } /** * Looks up a variable. * The value_length field is valid upon successful return. * * @returns Pointer to the variable. NULL if not found. * @param pszName The variable name. */ MY_INLINE struct variable * kbuild_lookup_variable(const char *pszName) { return kbuild_lookup_variable_n(pszName, strlen(pszName)); } /** * Looks up a variable and applies default a path to all relative paths. * The value_length field is valid upon successful return. * * @returns Pointer to the variable. NULL if not found. * @param pDefPath The default path. * @param pszName The variable name. * @param cchName The name length. */ MY_INLINE struct variable * kbuild_lookup_variable_defpath_n(struct variable *pDefPath, const char *pszName, size_t cchName) { struct variable *pVar = kbuild_lookup_variable_n(pszName, cchName); if (pVar && pDefPath) { assert(pVar->origin != o_automatic); #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE assert(!pVar->rdonly_val); #endif kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1); } return pVar; } /** * Looks up a variable and applies default a path to all relative paths. * The value_length field is valid upon successful return. * * @returns Pointer to the variable. NULL if not found. * @param pDefPath The default path. * @param pszName The variable name. */ MY_INLINE struct variable * kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName) { struct variable *pVar = kbuild_lookup_variable(pszName); if (pVar && pDefPath) { assert(pVar->origin != o_automatic); #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE assert(!pVar->rdonly_val); #endif kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1); } return pVar; } /** * Gets the first defined property variable. */ static struct variable * kbuild_first_prop(struct variable *pTarget, struct variable *pSource, struct variable *pTool, struct variable *pType, struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszPropF1, char cchPropF1, const char *pszPropF2, char cchPropF2, const char *pszVarName) { struct variable *pVar; size_t cchBuf; char *pszBuf; char *psz, *psz1, *psz2, *psz3, *psz4, *pszEnd; /* calc and allocate a too big name buffer. */ cchBuf = cchPropF2 + 1 + cchPropF1 + 1 + pTarget->value_length + 1 + pSource->value_length + 1 + (pTool ? pTool->value_length + 1 : 0) + pType->value_length + 1 + pBldTrg->value_length + 1 + pBldTrgArch->value_length + 1; pszBuf = xmalloc(cchBuf); #define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0) #define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0) #define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0) #define ADD_CH(ch) do { *psz++ = (ch); } while (0) /* * $(target)_$(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch) */ psz = pszBuf; ADD_VAR(pTarget); ADD_CH('_'); ADD_VAR(pSource); ADD_CH('_'); psz2 = psz; ADD_VAR(pType); ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* $(target)_$(source)_$(type)$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* $(target)_$(source)_$(type)$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); /* * $(target)_$(source)_$(propf2).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz = psz2; ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* $(target)_$(source)_$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* $(target)_$(source)_$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); } /* * $(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz = pszBuf; ADD_VAR(pSource); ADD_CH('_'); psz2 = psz; ADD_VAR(pType); ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* $(source)_$(type)$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* $(source)_$(type)$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); /* * $(source)_$(propf2).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz = psz2; ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* $(source)_$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* $(source)_$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); } } /* * $(target)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz = pszBuf; ADD_VAR(pTarget); ADD_CH('_'); psz2 = psz; ADD_VAR(pType); ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* $(target)_$(type)$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* $(target)_$(type)$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); /* $(target)_$(propf2).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz = psz2; ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); } /* $(target)_$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* $(target)_$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); } /* * TOOL_$(tool)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch) */ if (!pVar && pTool) { psz = pszBuf; ADD_CSTR("TOOL_"); ADD_VAR(pTool); ADD_CH('_'); psz2 = psz; ADD_VAR(pType); ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* TOOL_$(tool)_$(type)$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* TOOL_$(tool)_$(type)$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); /* TOOL_$(tool)_$(propf2).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz = psz2; ADD_STR(pszPropF2, cchPropF2); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* TOOL_$(tool)_$(propf2).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* TOOL_$(tool)_$(propf2) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); } } /* * $(type)$(propf1).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz = pszBuf; ADD_VAR(pType); ADD_STR(pszPropF1, cchPropF1); psz3 = psz; ADD_CH('.'); ADD_VAR(pBldTrg); psz4 = psz; ADD_CH('.'); ADD_VAR(pBldTrgArch); pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); /* $(type)$(propf1).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf); /* $(type)$(propf1) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf); /* * $(propf1).$(bld_trg).$(bld_trg_arch) */ if (!pVar) { psz1 = pszBuf + pType->value_length; pVar = kbuild_lookup_variable_n(psz1, psz - psz1); /* $(propf1).$(bld_trg) */ if (!pVar) pVar = kbuild_lookup_variable_n(psz1, psz4 - psz1); /* $(propf1) */ if (!pVar) pVar = kbuild_lookup_variable_n(pszPropF1, cchPropF1); } } free(pszBuf); #undef ADD_VAR #undef ADD_STR #undef ADD_CSTR #undef ADD_CH if (pVar) { /* strip it */ psz = pVar->value; pszEnd = psz + pVar->value_length; while (isblank((unsigned char)*psz)) psz++; while (pszEnd > psz && isblank((unsigned char)pszEnd[-1])) pszEnd--; if (pszEnd > psz) { char chSaved = *pszEnd; *pszEnd = '\0'; pVar = define_variable_vl(pszVarName, strlen(pszVarName), psz, pszEnd - psz, 1 /* duplicate */, o_local, 0 /* !recursive */); *pszEnd = chSaved; if (pVar) return pVar; } } return NULL; } /* _SOURCE_TOOL = $(strip $(firstword \ $($(target)_$(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(source)_$(type)TOOL.$(bld_trg)) \ $($(target)_$(source)_$(type)TOOL) \ $($(target)_$(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(source)_TOOL.$(bld_trg)) \ $($(target)_$(source)_TOOL) \ $($(source)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(source)_$(type)TOOL.$(bld_trg)) \ $($(source)_$(type)TOOL) \ $($(source)_TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(source)_TOOL.$(bld_trg)) \ $($(source)_TOOL) \ $($(target)_$(type)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(type)TOOL.$(bld_trg)) \ $($(target)_$(type)TOOL) \ $($(target)_TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(target)_TOOL.$(bld_trg)) \ $($(target)_TOOL) \ $($(type)TOOL.$(bld_trg).$(bld_trg_arch)) \ $($(type)TOOL.$(bld_trg)) \ $($(type)TOOL) \ $(TOOL.$(bld_trg).$(bld_trg_arch)) \ $(TOOL.$(bld_trg)) \ $(TOOL) )) */ static struct variable * kbuild_get_source_tool(struct variable *pTarget, struct variable *pSource, struct variable *pType, struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName) { struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch, "TOOL", sizeof("TOOL") - 1, "TOOL", sizeof("TOOL") - 1, pszVarName); if (!pVar) fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value); return pVar; } /* Implements _SOURCE_TOOL. */ char * func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName) { struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable_n(ST("target")), kbuild_get_variable_n(ST("source")), kbuild_get_variable_n(ST("type")), kbuild_get_variable_n(ST("bld_trg")), kbuild_get_variable_n(ST("bld_trg_arch")), argv[0]); if (pVar) o = variable_buffer_output(o, pVar->value, pVar->value_length); (void)pszFuncName; return o; } /* This has been extended a bit, it's now identical to _SOURCE_TOOL. $(firstword \ $($(target)_$(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\ $($(target)_$(source)_OBJSUFF.$(bld_trg))\ $($(target)_$(source)_OBJSUFF)\ $($(source)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\ $($(source)_OBJSUFF.$(bld_trg))\ $($(source)_OBJSUFF)\ $($(target)_OBJSUFF.$(bld_trg).$(bld_trg_arch))\ $($(target)_OBJSUFF.$(bld_trg))\ $($(target)_OBJSUFF)\ $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_$(type)OBJSUFF.$(bld_trg))\ $(TOOL_$(tool)_$(type)OBJSUFF)\ $(SUFF_OBJ)) */ static struct variable * kbuild_get_object_suffix(struct variable *pTarget, struct variable *pSource, struct variable *pTool, struct variable *pType, struct variable *pBldTrg, struct variable *pBldTrgArch, const char *pszVarName) { struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "SUFF_OBJ", sizeof("SUFF_OBJ") - 1, "OBJSUFF", sizeof("OBJSUFF") - 1, pszVarName); if (!pVar) fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value); return pVar; } /* */ char * func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName) { struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable_n(ST("target")), kbuild_get_variable_n(ST("source")), kbuild_get_variable_n(ST("tool")), kbuild_get_variable_n(ST("type")), kbuild_get_variable_n(ST("bld_trg")), kbuild_get_variable_n(ST("bld_trg_arch")), argv[0]); if (pVar) o = variable_buffer_output(o, pVar->value, pVar->value_length); (void)pszFuncName; return o; } /* ## Figure out where to put object files. # @param $1 source file # @param $2 normalized main target # @remark There are two major hacks here: # 1. Source files in the output directory are translated into a gen/ subdir. # 2. Catch anyone specifying $(PATH_SUB_CURRENT)/sourcefile.c. _OBJECT_BASE = $(PATH_TARGET)/$(2)/$(call no-root-slash,$(call no-drive,$(basename \ $(patsubst $(PATH_ROOT)/%,%,$(patsubst $(PATH_SUB_CURRENT)/%,%,$(patsubst $(PATH_TARGET)/$(2)/%,gen/%,$(1))))))) */ static struct variable * kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName) { struct variable *pPathTarget = kbuild_get_variable_n(ST("PATH_TARGET")); struct variable *pPathRoot = kbuild_get_variable_n(ST("PATH_ROOT")); struct variable *pPathSubCur = kbuild_get_variable_n(ST("PATH_SUB_CURRENT")); const char *pszSrcPrefix = NULL; size_t cchSrcPrefix = 0; size_t cchSrc = 0; const char *pszSrcEnd; char *pszSrc; char *pszResult; char *psz; char *pszDot; size_t cch; /* * Strip the source filename of any uncessary leading path and root specs. */ /* */ if ( pSource->value_length > pPathTarget->value_length && !strncmp(pSource->value, pPathTarget->value, pPathTarget->value_length)) { pszSrc = pSource->value + pPathTarget->value_length; pszSrcPrefix = "gen/"; cchSrcPrefix = sizeof("gen/") - 1; if ( *pszSrc == '/' && !strncmp(pszSrc + 1, pTarget->value, pTarget->value_length) && ( pszSrc[pTarget->value_length + 1] == '/' || pszSrc[pTarget->value_length + 1] == '\0')) pszSrc += 1 + pTarget->value_length; } else if ( pSource->value_length > pPathRoot->value_length && !strncmp(pSource->value, pPathRoot->value, pPathRoot->value_length)) { pszSrc = pSource->value + pPathRoot->value_length; if ( *pszSrc == '/' && !strncmp(pszSrc + 1, pPathSubCur->value, pPathSubCur->value_length) && ( pszSrc[pPathSubCur->value_length + 1] == '/' || pszSrc[pPathSubCur->value_length + 1] == '\0')) pszSrc += 1 + pPathSubCur->value_length; } else pszSrc = pSource->value; /* skip root specification */ #ifdef HAVE_DOS_PATHS if (isalpha(pszSrc[0]) && pszSrc[1] == ':') pszSrc += 2; #endif while (*pszSrc == '/' #ifdef HAVE_DOS_PATHS || *pszSrc == '\\' #endif ) pszSrc++; /* drop the source extension. */ pszSrcEnd = pSource->value + pSource->value_length; for (;;) { pszSrcEnd--; if ( pszSrcEnd <= pszSrc || *pszSrcEnd == '/' #ifdef HAVE_DOS_PATHS || *pszSrcEnd == '\\' || *pszSrcEnd == ':' #endif ) { pszSrcEnd = pSource->value + pSource->value_length; break; } if (*pszSrcEnd == '.') break; } /* * Assemble the string on the heap and define the objbase variable * which we then return. */ cchSrc = pszSrcEnd - pszSrc; cch = pPathTarget->value_length + 1 /* slash */ + pTarget->value_length + 1 /* slash */ + cchSrcPrefix + cchSrc + 1; psz = pszResult = xmalloc(cch); memcpy(psz, pPathTarget->value, pPathTarget->value_length); psz += pPathTarget->value_length; *psz++ = '/'; memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length; *psz++ = '/'; if (pszSrcPrefix) { memcpy(psz, pszSrcPrefix, cchSrcPrefix); psz += cchSrcPrefix; } pszDot = psz; memcpy(psz, pszSrc, cchSrc); psz += cchSrc; *psz = '\0'; /* convert '..' path elements in the source to 'dt'. */ while ((pszDot = memchr(pszDot, '.', psz - pszDot)) != NULL) { if ( pszDot[1] == '.' && ( pszDot == psz || pszDot[-1] == '/' #ifdef HAVE_DOS_PATHS || pszDot[-1] == '\\' || pszDot[-1] == ':' #endif ) && ( !pszDot[2] || pszDot[2] == '/' #ifdef HAVE_DOS_PATHS || pszDot[2] == '\\' || pszDot[2] == ':' #endif ) ) { *pszDot++ = 'd'; *pszDot++ = 't'; } else pszDot++; } /* * Define the variable in the current set and return it. */ return define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cch - 1, 0 /* use pszResult */, o_local, 0 /* !recursive */); } /* Implements _OBJECT_BASE. */ char * func_kbuild_object_base(char *o, char **argv, const char *pszFuncName) { struct variable *pVar = kbuild_get_object_base(kbuild_lookup_variable("target"), kbuild_lookup_variable("source"), argv[0]); if (pVar) o = variable_buffer_output(o, pVar->value, pVar->value_length); (void)pszFuncName; return o; } struct kbuild_sdks { char *apsz[4]; struct variable *pa; unsigned c; unsigned iGlobal; unsigned cGlobal; unsigned iTarget; unsigned cTarget; unsigned iSource; unsigned cSource; unsigned iTargetSource; unsigned cTargetSource; unsigned int cchMax; }; /* Fills in the SDK struct (remember to free it). */ static void kbuild_get_sdks(struct kbuild_sdks *pSdks, struct variable *pTarget, struct variable *pSource, struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch) { unsigned i; unsigned j; size_t cchTmp, cch; char *pszTmp; unsigned cchCur; char *pszCur; const char *pszIterator; /** @todo rewrite this to avoid sprintf and allocated_varaible_expand_2. */ /* basic init. */ pSdks->cchMax = 0; pSdks->pa = NULL; pSdks->c = 0; i = 0; /* determin required tmp variable name space. */ cchTmp = sizeof("$(__SDKS) $(__SDKS.) $(__SDKS.) $(__SDKS.) $(__SDKS..)") + (pTarget->value_length + pSource->value_length) * 5 + pBldType->value_length + pBldTrg->value_length + pBldTrgArch->value_length + pBldTrg->value_length + pBldTrgArch->value_length; pszTmp = alloca(cchTmp); /* the global sdks. */ pSdks->iGlobal = i; pSdks->cGlobal = 0; cch = sprintf(pszTmp, "$(SDKS) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s) $(SDKS.%s.%s)", pBldType->value, pBldTrg->value, pBldTrgArch->value, pBldTrg->value, pBldTrgArch->value); pszIterator = pSdks->apsz[0] = allocated_variable_expand_2(pszTmp, cch, NULL); while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0) pSdks->cGlobal++; i += pSdks->cGlobal; /* the target sdks.*/ pSdks->iTarget = i; pSdks->cTarget = 0; cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)", pTarget->value, pTarget->value, pBldType->value, pTarget->value, pBldTrg->value, pTarget->value, pBldTrgArch->value, pTarget->value, pBldTrg->value, pBldTrgArch->value); pszIterator = pSdks->apsz[1] = allocated_variable_expand_2(pszTmp, cch, NULL); while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0) pSdks->cTarget++; i += pSdks->cTarget; /* the source sdks.*/ pSdks->iSource = i; pSdks->cSource = 0; cch = sprintf(pszTmp, "$(%s_SDKS) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s) $(%s_SDKS.%s.%s)", pSource->value, pSource->value, pBldType->value, pSource->value, pBldTrg->value, pSource->value, pBldTrgArch->value, pSource->value, pBldTrg->value, pBldTrgArch->value); pszIterator = pSdks->apsz[2] = allocated_variable_expand_2(pszTmp, cch, NULL); while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0) pSdks->cSource++; i += pSdks->cSource; /* the target + source sdks. */ pSdks->iTargetSource = i; pSdks->cTargetSource = 0; cch = sprintf(pszTmp, "$(%s_%s_SDKS) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s) $(%s_%s_SDKS.%s.%s)", pTarget->value, pSource->value, pTarget->value, pSource->value, pBldType->value, pTarget->value, pSource->value, pBldTrg->value, pTarget->value, pSource->value, pBldTrgArch->value, pTarget->value, pSource->value, pBldTrg->value, pBldTrgArch->value); assert(cch < cchTmp); (void)cch; pszIterator = pSdks->apsz[3] = allocated_variable_expand_2(pszTmp, cch, NULL); while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0) pSdks->cTargetSource++; i += pSdks->cTargetSource; pSdks->c = i; if (!i) return; /* * Allocate the variable array and create the variables. */ pSdks->pa = (struct variable *)xmalloc(sizeof(pSdks->pa[0]) * i); memset(pSdks->pa, 0, sizeof(pSdks->pa[0]) * i); for (i = j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++) { pszIterator = pSdks->apsz[j]; while ((pszCur = find_next_token(&pszIterator, &cchCur)) != 0) { pSdks->pa[i].value = pszCur; pSdks->pa[i].value_length = cchCur; i++; } } assert(i == pSdks->c); /* terminate them (find_next_token won't work if we terminate them in the previous loop). */ while (i-- > 0) { pSdks->pa[i].value[pSdks->pa[i].value_length] = '\0'; /* calc the max variable length too. */ if (pSdks->cchMax < (unsigned int)pSdks->pa[i].value_length) pSdks->cchMax = pSdks->pa[i].value_length; } } /* releases resources allocated in the kbuild_get_sdks. */ static void kbuild_put_sdks(struct kbuild_sdks *pSdks) { unsigned j; for (j = 0; j < sizeof(pSdks->apsz) / sizeof(pSdks->apsz[0]); j++) free(pSdks->apsz[j]); free(pSdks->pa); } /* this kind of stuff: defs := $(kb-src-exp defs) $(TOOL_$(tool)_DEFS)\ $(TOOL_$(tool)_DEFS.$(bld_type))\ $(TOOL_$(tool)_DEFS.$(bld_trg))\ $(TOOL_$(tool)_DEFS.$(bld_trg_arch))\ $(TOOL_$(tool)_DEFS.$(bld_trg).$(bld_trg_arch))\ $(TOOL_$(tool)_DEFS.$(bld_trg_cpu))\ $(TOOL_$(tool)_$(type)DEFS)\ $(TOOL_$(tool)_$(type)DEFS.$(bld_type))\ $(foreach sdk, $(SDKS.$(bld_trg)) \ $(SDKS.$(bld_trg).$(bld_trg_arch)) \ $(SDKS.$(bld_type)) \ $(SDKS),\ $(SDK_$(sdk)_DEFS)\ $(SDK_$(sdk)_DEFS.$(bld_type))\ $(SDK_$(sdk)_DEFS.$(bld_trg))\ $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\ $(SDK_$(sdk)_$(type)DEFS)\ $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\ $(DEFS)\ $(DEFS.$(bld_type))\ $(DEFS.$(bld_trg))\ $(DEFS.$(bld_trg_arch))\ $(DEFS.$(bld_trg).$(bld_trg_arch))\ $(DEFS.$(bld_trg_cpu))\ $($(type)DEFS)\ $($(type)DEFS.$(bld_type))\ $($(type)DEFS.$(bld_trg))\ $($(type)DEFS.$(bld_trg_arch))\ $($(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $($(type)DEFS.$(bld_trg_cpu))\ $(foreach sdk, $($(target)_SDKS.$(bld_trg)) \ $($(target)_SDKS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_SDKS.$(bld_type)) \ $($(target)_SDKS),\ $(SDK_$(sdk)_DEFS)\ $(SDK_$(sdk)_DEFS.$(bld_type))\ $(SDK_$(sdk)_DEFS.$(bld_trg))\ $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\ $(SDK_$(sdk)_$(type)DEFS)\ $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\ $($(target)_DEFS)\ $($(target)_DEFS.$(bld_type))\ $($(target)_DEFS.$(bld_trg))\ $($(target)_DEFS.$(bld_trg_arch))\ $($(target)_DEFS.$(bld_trg).$(bld_trg_arch))\ $($(target)_DEFS.$(bld_trg_cpu))\ $($(target)_$(type)DEFS)\ $($(target)_$(type)DEFS.$(bld_type))\ $($(target)_$(type)DEFS.$(bld_trg))\ $($(target)_$(type)DEFS.$(bld_trg_arch))\ $($(target)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $($(target)_$(type)DEFS.$(bld_trg_cpu))\ $(foreach sdk, $($(source)_SDKS.$(bld_trg)) \ $($(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \ $($(source)_SDKS.$(bld_type)) \ $($(source)_SDKS),\ $(SDK_$(sdk)_DEFS)\ $(SDK_$(sdk)_DEFS.$(bld_type))\ $(SDK_$(sdk)_DEFS.$(bld_trg))\ $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\ $(SDK_$(sdk)_$(type)DEFS)\ $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\ $($(source)_DEFS)\ $($(source)_DEFS.$(bld_type))\ $($(source)_DEFS.$(bld_trg))\ $($(source)_DEFS.$(bld_trg_arch))\ $($(source)_DEFS.$(bld_trg).$(bld_trg_arch))\ $($(source)_DEFS.$(bld_trg_cpu))\ $($(source)_$(type)DEFS)\ $($(source)_$(type)DEFS.$(bld_type))\ $($(source)_$(type)DEFS.$(bld_trg))\ $($(source)_$(type)DEFS.$(bld_trg_arch))\ $($(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $($(source)_$(type)DEFS.$(bld_trg_cpu))\ $(foreach sdk, $($(target)_$(source)_SDKS.$(bld_trg)) \ $($(target)_$(source)_SDKS.$(bld_trg).$(bld_trg_arch)) \ $($(target)_$(source)_SDKS.$(bld_type)) \ $($(target)_$(source)_SDKS),\ $(SDK_$(sdk)_DEFS)\ $(SDK_$(sdk)_DEFS.$(bld_type))\ $(SDK_$(sdk)_DEFS.$(bld_trg))\ $(SDK_$(sdk)_DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_DEFS.$(bld_trg_cpu))\ $(SDK_$(sdk)_$(type)DEFS)\ $(SDK_$(sdk)_$(type)DEFS.$(bld_type))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $(SDK_$(sdk)_$(type)DEFS.$(bld_trg_cpu)))\ $($(target)_$(source)_DEFS)\ $($(target)_$(source)_DEFS.$(bld_type))\ $($(target)_$(source)_DEFS.$(bld_trg))\ $($(target)_$(source)_DEFS.$(bld_trg_arch))\ $($(target)_$(source)_DEFS.$(bld_trg).$(bld_trg_arch))\ $($(target)_$(source)_DEFS.$(bld_trg_cpu))\ $($(target)_$(source)_$(type)DEFS)\ $($(target)_$(source)_$(type)DEFS.$(bld_type))\ $($(target)_$(source)_$(type)DEFS.$(bld_trg))\ $($(target)_$(source)_$(type)DEFS.$(bld_trg_arch))\ $($(target)_$(source)_$(type)DEFS.$(bld_trg).$(bld_trg_arch))\ $($(target)_$(source)_$(type)DEFS.$(bld_trg_cpu)) */ static struct variable * kbuild_collect_source_prop(struct variable *pTarget, struct variable *pSource, struct variable *pTool, struct kbuild_sdks *pSdks, struct variable *pType, struct variable *pBldType, struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu, struct variable *pDefPath, const char *pszProp, size_t cchProp, const char *pszVarName, size_t cchVarName, int iDirection) { struct variable *pVar; unsigned iSdk, iSdkEnd; int cVars, iVar; size_t cchTotal, cchBuf; char *pszResult, *pszBuf, *psz, *psz2, *psz3; struct { struct variable *pVar; unsigned int cchExp; char *pszExp; } *paVars; assert(iDirection == 1 || iDirection == -1); /* * Calc and allocate a too big name buffer. */ cchBuf = cchProp + 1 + pTarget->value_length + 1 + pSource->value_length + 1 + pSdks->cchMax + 1 + (pTool ? pTool->value_length + 1 : 0) + pType->value_length + 1 + pBldTrg->value_length + 1 + pBldTrgArch->value_length + 1 + pBldTrgCpu->value_length + 1 + pBldType->value_length + 1; pszBuf = xmalloc(cchBuf); /* * Get the variables. * * The compiler will get a heart attack when it sees this code ... ;-) */ cVars = 12 * (pSdks->c + 5); paVars = alloca(cVars * sizeof(paVars[0])); iVar = 0; cchTotal = 0; #define ADD_VAR(pVar) do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0) #define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0) #define ADD_CSTR(pszStr) do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0) #define ADD_CH(ch) do { *psz++ = (ch); } while (0) #define DO_VAR_LOOKUP() \ do { \ pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf); \ if (pVar) \ { \ paVars[iVar].pVar = pVar; \ if ( !pVar->recursive \ || !memchr(pVar->value, '$', pVar->value_length)) \ { \ paVars[iVar].pszExp = pVar->value; \ paVars[iVar].cchExp = pVar->value_length; \ if (pDefPath && paVars[iVar].cchExp) \ kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL, 0); \ if (paVars[iVar].cchExp) \ { \ cchTotal += paVars[iVar].cchExp + 1; \ iVar++; \ } \ } \ else \ { \ paVars[iVar].pszExp = allocated_variable_expand_2(pVar->value, pVar->value_length, &paVars[iVar].cchExp); \ if (pDefPath && paVars[iVar].cchExp) \ kbuild_apply_defpath(pDefPath, &paVars[iVar].pszExp, &paVars[iVar].cchExp, NULL, 1); \ if (paVars[iVar].cchExp) \ { \ cchTotal += paVars[iVar].cchExp + 1; \ iVar++; \ } \ else \ free(paVars[iVar].pszExp); \ } \ } \ } while (0) #define DO_SINGLE_PSZ3_VARIATION() \ do { \ DO_VAR_LOOKUP(); \ \ ADD_CH('.'); \ psz3 = psz; \ ADD_VAR(pBldType); \ DO_VAR_LOOKUP(); \ \ psz = psz3; \ ADD_VAR(pBldTrg); \ DO_VAR_LOOKUP(); \ \ psz = psz3; \ ADD_VAR(pBldTrgArch); \ DO_VAR_LOOKUP(); \ \ psz = psz3; \ ADD_VAR(pBldTrg); \ ADD_CH('.'); \ ADD_VAR(pBldTrgArch); \ DO_VAR_LOOKUP(); \ \ psz = psz3; \ ADD_VAR(pBldTrgCpu); \ DO_VAR_LOOKUP(); \ } while (0) #define DO_DOUBLE_PSZ2_VARIATION() \ do { \ psz2 = psz; \ ADD_STR(pszProp, cchProp); \ DO_SINGLE_PSZ3_VARIATION(); \ \ /* add prop before type */ \ psz = psz2; \ ADD_VAR(pType); \ ADD_STR(pszProp, cchProp); \ DO_SINGLE_PSZ3_VARIATION(); \ } while (0) /* the tool (lowest priority). */ psz = pszBuf; ADD_CSTR("TOOL_"); ADD_VAR(pTool); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); /* the global sdks. */ iSdkEnd = iDirection == 1 ? pSdks->iGlobal + pSdks->cGlobal : pSdks->iGlobal - 1; for (iSdk = iDirection == 1 ? pSdks->iGlobal : pSdks->iGlobal + pSdks->cGlobal - 1; iSdk != iSdkEnd; iSdk += iDirection) { struct variable *pSdk = &pSdks->pa[iSdk]; psz = pszBuf; ADD_CSTR("SDK_"); ADD_VAR(pSdk); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); } /* the globals. */ psz = pszBuf; DO_DOUBLE_PSZ2_VARIATION(); /* the target sdks. */ iSdkEnd = iDirection == 1 ? pSdks->iTarget + pSdks->cTarget : pSdks->iTarget - 1; for (iSdk = iDirection == 1 ? pSdks->iTarget : pSdks->iTarget + pSdks->cTarget - 1; iSdk != iSdkEnd; iSdk += iDirection) { struct variable *pSdk = &pSdks->pa[iSdk]; psz = pszBuf; ADD_CSTR("SDK_"); ADD_VAR(pSdk); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); } /* the target. */ psz = pszBuf; ADD_VAR(pTarget); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); /* the source sdks. */ iSdkEnd = iDirection == 1 ? pSdks->iSource + pSdks->cSource : pSdks->iSource - 1; for (iSdk = iDirection == 1 ? pSdks->iSource : pSdks->iSource + pSdks->cSource - 1; iSdk != iSdkEnd; iSdk += iDirection) { struct variable *pSdk = &pSdks->pa[iSdk]; psz = pszBuf; ADD_CSTR("SDK_"); ADD_VAR(pSdk); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); } /* the source. */ psz = pszBuf; ADD_VAR(pSource); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); /* the target + source sdks. */ iSdkEnd = iDirection == 1 ? pSdks->iTargetSource + pSdks->cTargetSource : pSdks->iTargetSource - 1; for (iSdk = iDirection == 1 ? pSdks->iTargetSource : pSdks->iTargetSource + pSdks->cTargetSource - 1; iSdk != iSdkEnd; iSdk += iDirection) { struct variable *pSdk = &pSdks->pa[iSdk]; psz = pszBuf; ADD_CSTR("SDK_"); ADD_VAR(pSdk); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); } /* the target + source. */ psz = pszBuf; ADD_VAR(pTarget); ADD_CH('_'); ADD_VAR(pSource); ADD_CH('_'); DO_DOUBLE_PSZ2_VARIATION(); free(pszBuf); assert(iVar <= cVars); cVars = iVar; /* * Construct the result value. */ if (!cVars || !cchTotal) pVar = define_variable_vl(pszVarName, cchVarName, "", 0, 1 /* duplicate value */ , o_local, 0 /* !recursive */); else { psz = pszResult = xmalloc(cchTotal + 1); if (iDirection == 1) { for (iVar = 0; iVar < cVars; iVar++) { my_memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp); psz += paVars[iVar].cchExp; *psz++ = ' '; if (paVars[iVar].pszExp != paVars[iVar].pVar->value) free(paVars[iVar].pszExp); } } else { iVar = cVars; while (iVar-- > 0) { my_memcpy(psz, paVars[iVar].pszExp, paVars[iVar].cchExp); psz += paVars[iVar].cchExp; *psz++ = ' '; if (paVars[iVar].pszExp != paVars[iVar].pVar->value) free(paVars[iVar].pszExp); } } assert(psz != pszResult); assert(cchTotal == (size_t)(psz - pszResult)); psz[-1] = '\0'; cchTotal--; pVar = define_variable_vl(pszVarName, cchVarName, pszResult, cchTotal, 0 /* take pszResult */ , o_local, 0 /* !recursive */); } return pVar; #undef ADD_VAR #undef ADD_STR #undef ADD_CSTR #undef ADD_CH #undef DO_VAR_LOOKUP #undef DO_DOUBLE_PSZ2_VARIATION #undef DO_SINGLE_PSZ3_VARIATION } /* get a source property. */ char * func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName) { struct variable *pTarget = kbuild_get_variable_n(ST("target")); struct variable *pSource = kbuild_get_variable_n(ST("source")); struct variable *pDefPath = NULL; struct variable *pType = kbuild_get_variable_n(ST("type")); struct variable *pTool = kbuild_get_variable_n(ST("tool")); struct variable *pBldType = kbuild_get_variable_n(ST("bld_type")); struct variable *pBldTrg = kbuild_get_variable_n(ST("bld_trg")); struct variable *pBldTrgArch = kbuild_get_variable_n(ST("bld_trg_arch")); struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu")); struct variable *pVar; struct kbuild_sdks Sdks; int iDirection; if (!strcmp(argv[2], "left-to-right")) iDirection = 1; else if (!strcmp(argv[2], "right-to-left")) iDirection = -1; else fatal(NILF, _("incorrect direction argument `%s'!"), argv[2]); if (argv[3]) { const char *psz = argv[3]; while (isspace(*psz)) psz++; if (*psz) pDefPath = kbuild_get_variable_n(ST("defpath")); } kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch); pVar = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath, argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), iDirection); if (pVar) o = variable_buffer_output(o, pVar->value, pVar->value_length); kbuild_put_sdks(&Sdks); (void)pszFuncName; return o; } /* dep := $(obj)$(SUFF_DEP) obj := $(outbase)$(objsuff) dirdep := $(call DIRDEP,$(dir $(outbase))) PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase))) */ static struct variable * kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(struct variable *pTarget, struct variable *pSource, struct variable *pOutBase, struct variable *pObjSuff, const char *pszVarName, struct variable **ppDep, struct variable **ppDirDep) { struct variable *pDepSuff = kbuild_get_variable_n(ST("SUFF_DEP")); struct variable *pObj; size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1; char *pszResult = alloca(cch); char *pszName, *psz; /* * dep. */ psz = pszResult; memcpy(psz, pOutBase->value, pOutBase->value_length); psz += pOutBase->value_length; memcpy(psz, pObjSuff->value, pObjSuff->value_length); psz += pObjSuff->value_length; memcpy(psz, pDepSuff->value, pDepSuff->value_length + 1); *ppDep = define_variable_vl("dep", 3, pszResult, cch - 1, 1 /*dup*/, o_local, 0 /* !recursive */); /* * obj */ *psz = '\0'; pObj = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, psz - pszResult, 1/* dup */, o_local, 0 /* !recursive */); /* * PATH_$(target)_$(source) - this is global! */ /* calc variable name. */ cch = sizeof("PATH_")-1 + pTarget->value_length + sizeof("_")-1 + pSource->value_length; psz = pszName = alloca(cch + 1); memcpy(psz, "PATH_", sizeof("PATH_") - 1); psz += sizeof("PATH_") - 1; memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length; *psz++ = '_'; memcpy(psz, pSource->value, pSource->value_length + 1); /* strip off the filename. */ psz = pszResult + pOutBase->value_length; for (;;) { psz--; if (psz <= pszResult) fatal(NULL, "whut!?! no path? result=`%s'", pszResult); #ifdef HAVE_DOS_PATHS if (*psz == ':') { psz++; break; } #endif if ( *psz == '/' #ifdef HAVE_DOS_PATHS || *psz == '\\' #endif ) { while ( psz - 1 > pszResult && psz[-1] == '/' #ifdef HAVE_DOS_PATHS || psz[-1] == '\\' #endif ) psz--; #ifdef HAVE_DOS_PATHS if (psz == pszResult + 2 && pszResult[1] == ':') psz++; #endif break; } } *psz = '\0'; /* set global variable */ define_variable_vl_global(pszName, cch, pszResult, psz - pszResult, 1/*dup*/, o_file, 0 /* !recursive */, NILF); /* * dirdep */ if ( psz[-1] != '/' #ifdef HAVE_DOS_PATHS && psz[-1] != '\\' && psz[-1] != ':' #endif ) { *psz++ = '/'; *psz = '\0'; } *ppDirDep = define_variable_vl("dirdep", 6, pszResult, psz - pszResult, 1/*dup*/, o_local, 0 /* !recursive */); return pObj; } /* setup the base variables for def_target_source_c_cpp_asm_new: X := $(kb-src-tool tool) x := $(kb-obj-base outbase) x := $(kb-obj-suff objsuff) obj := $(outbase)$(objsuff) PATH_$(target)_$(source) := $(patsubst %/,%,$(dir $(outbase))) x := $(kb-src-prop DEFS,defs,left-to-right) x := $(kb-src-prop INCS,incs,right-to-left) x := $(kb-src-prop FLAGS,flags,right-to-left) x := $(kb-src-prop DEPS,deps,left-to-right) dirdep := $(call DIRDEP,$(dir $(outbase))) dep := $(obj)$(SUFF_DEP) */ char * func_kbuild_source_one(char *o, char **argv, const char *pszFuncName) { static int s_fNoCompileCmdsDepsDefined = -1; struct variable *pTarget = kbuild_get_variable_n(ST("target")); struct variable *pSource = kbuild_get_variable_n(ST("source")); struct variable *pDefPath = kbuild_get_variable_n(ST("defpath")); struct variable *pType = kbuild_get_variable_n(ST("type")); struct variable *pBldType = kbuild_get_variable_n(ST("bld_type")); struct variable *pBldTrg = kbuild_get_variable_n(ST("bld_trg")); struct variable *pBldTrgArch= kbuild_get_variable_n(ST("bld_trg_arch")); struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu")); struct variable *pTool = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool"); struct variable *pOutBase = kbuild_get_object_base(pTarget, pSource, "outbase"); struct variable *pObjSuff = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff"); struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe; struct variable *pObj = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep); int fInstallOldVars = 0; char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz; char *pszSavedVarBuf; unsigned cchSavedVarBuf; size_t cch; struct kbuild_sdks Sdks; int iVer; /* * argv[0] is the function version. Prior to r1792 (early 0.1.5) this * was undefined and footer.kmk always passed an empty string. * * Version 2, as implemented in r1797, will make use of the async * includedep queue feature. This means the files will be read by one or * more background threads, leaving the eval'ing to be done later on by * the main thread (in snap_deps). */ if (!argv[0][0]) iVer = 0; else switch (argv[0][0] | (argv[0][1] << 8)) { case '2': iVer = 2; break; case '3': iVer = 3; break; case '4': iVer = 4; break; case '5': iVer = 5; break; case '6': iVer = 6; break; case '7': iVer = 7; break; case '8': iVer = 8; break; case '9': iVer = 9; break; case '0': iVer = 0; break; case '1': iVer = 1; break; default: iVer = 0; psz = argv[0]; while (isblank((unsigned char)*psz)) psz++; if (*psz) iVer = atoi(psz); break; } /* * Gather properties. */ kbuild_get_sdks(&Sdks, pTarget, pSource, pBldType, pBldTrg, pBldTrgArch); if (pDefPath && !pDefPath->value_length) pDefPath = NULL; pDefs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL, ST("DEFS"), ST("defs"), 1/* left-to-right */); pIncs = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath, ST("INCS"), ST("incs"), -1/* right-to-left */); pFlags = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL, ST("FLAGS"), ST("flags"), 1/* left-to-right */); pDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath, ST("DEPS"), ST("deps"), 1/* left-to-right */); pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath, ST("ORDERDEPS"), ST("orderdeps"), 1/* left-to-right */); /* * If we've got a default path, we must expand the source now. * If we do this too early, "_property = stuff" won't work becuase * our 'source' value isn't what the user expects. */ if (pDefPath) { /** @todo assert(pSource->origin != o_automatic); We're changing 'source' * from the foreach loop! */ #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE assert(!pSource->rdonly_val); #endif kbuild_apply_defpath(pDefPath, &pSource->value, &pSource->value_length, &pSource->value_alloc_len, 1 /* can free */); } /* # dependencies ifndef NO_COMPILE_CMDS_DEPS _DEPFILES_INCLUDED += $(dep) $(if $(wildcard $(dep)),$(eval include $(dep))) endif */ if (s_fNoCompileCmdsDepsDefined == -1) s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable_n(ST("NO_COMPILE_CMDS_DEPS")) != NULL; if (!s_fNoCompileCmdsDepsDefined) { pVar = kbuild_query_recursive_variable_n("_DEPFILES_INCLUDED", sizeof("_DEPFILES_INCLUDED") - 1); if (pVar) { if (pVar->recursive) pVar = kbuild_simplify_variable(pVar); append_string_to_variable(pVar, pDep->value, pDep->value_length, 1 /* append */); } else define_variable_vl_global("_DEPFILES_INCLUDED", sizeof("_DEPFILES_INCLUDED") - 1, pDep->value, pDep->value_length, 1 /* duplicate_value */, o_file, 0 /* recursive */, NULL /* flocp */); eval_include_dep(pDep->value, NILF, iVer >= 2 ? incdep_queue : incdep_read_it); } /* # call the tool $(target)_$(source)_CMDS_ := $(TOOL_$(tool)_COMPILE_$(type)_CMDS) $(target)_$(source)_OUTPUT_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT) $(target)_$(source)_OUTPUT_MAYBE_ := $(TOOL_$(tool)_COMPILE_$(type)_OUTPUT_MAYBE) $(target)_$(source)_DEPEND_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPEND) $(deps) $(source) $(target)_$(source)_DEPORD_ := $(TOOL_$(tool)_COMPILE_$(type)_DEPORD) $(dirdep) */ /** @todo Make all these local variables, if someone needs the info later it * can be recalculated. (Ticket #80.) */ cch = sizeof("TOOL_") + pTool->value_length + sizeof("_COMPILE_") + pType->value_length + sizeof("_OUTPUT_MAYBE"); if (cch < pTarget->value_length + sizeof("$(_2_OBJS)")) cch = pTarget->value_length + sizeof("$(_2_OBJS)"); psz = pszSrcVar = alloca(cch); memcpy(psz, "TOOL_", sizeof("TOOL_") - 1); psz += sizeof("TOOL_") - 1; memcpy(psz, pTool->value, pTool->value_length); psz += pTool->value_length; memcpy(psz, "_COMPILE_", sizeof("_COMPILE_") - 1); psz += sizeof("_COMPILE_") - 1; memcpy(psz, pType->value, pType->value_length); psz += pType->value_length; pszSrc = psz; cch = pTarget->value_length + 1 + pSource->value_length + sizeof("_OUTPUT_MAYBE_"); psz = pszDstVar = alloca(cch); memcpy(psz, pTarget->value, pTarget->value_length); psz += pTarget->value_length; *psz++ = '_'; memcpy(psz, pSource->value, pSource->value_length); psz += pSource->value_length; pszDst = psz; memcpy(pszSrc, "_CMDS", sizeof("_CMDS")); memcpy(pszDst, "_CMDS_", sizeof("_CMDS_")); pVar = kbuild_get_recursive_variable(pszSrcVar); do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length, !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */); do_variable_definition_2(NILF, "kbsrc_cmds", pVar->value, pVar->value_length, !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */); memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT")); memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_")); pVar = kbuild_get_recursive_variable(pszSrcVar); pOutput = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length, !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */); pOutput = do_variable_definition_2(NILF, "kbsrc_output", pVar->value, pVar->value_length, !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */); memcpy(pszSrc, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE")); memcpy(pszDst, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_")); pVar = kbuild_query_recursive_variable(pszSrcVar); if (pVar) { pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length, !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */); pOutputMaybe = do_variable_definition_2(NILF, "kbsrc_output_maybe", pVar->value, pVar->value_length, !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */); } else { pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, "", 0, 1, 0, o_local, f_simple, 0 /* !target_var */); pOutputMaybe = do_variable_definition_2(NILF, "kbsrc_output_maybe", "", 0, 1, 0, o_local, f_simple, 0 /* !target_var */); } memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND")); memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_")); pVar = kbuild_get_recursive_variable(pszSrcVar); psz = pszVal = xmalloc(pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length + 1); memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length; *psz++ = ' '; memcpy(psz, pDeps->value, pDeps->value_length); psz += pDeps->value_length; *psz++ = ' '; memcpy(psz, pSource->value, pSource->value_length + 1); do_variable_definition_2(NILF, pszDstVar, pszVal, pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length, !pVar->recursive && !pDeps->recursive && !pSource->recursive, NULL, o_local, f_simple, 0 /* !target_var */); do_variable_definition_2(NILF, "kbsrc_depend", pszVal, pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length, !pVar->recursive && !pDeps->recursive && !pSource->recursive, pszVal, o_local, f_simple, 0 /* !target_var */); memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD")); memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_")); pVar = kbuild_get_recursive_variable(pszSrcVar); psz = pszVal = xmalloc(pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length + 1); memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length; *psz++ = ' '; memcpy(psz, pDirDep->value, pDirDep->value_length); psz += pDirDep->value_length; *psz++ = ' '; memcpy(psz, pOrderDeps->value, pOrderDeps->value_length + 1); do_variable_definition_2(NILF, pszDstVar, pszVal, pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length, !pVar->recursive && !pDirDep->recursive && !pOrderDeps->recursive, NULL, o_local, f_simple, 0 /* !target_var */); do_variable_definition_2(NILF, "kbsrc_depord", pszVal, pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length, !pVar->recursive && !pDirDep->recursive && !pOrderDeps->recursive, pszVal, o_local, f_simple, 0 /* !target_var */); /* _OUT_FILES += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_) */ pVar = kbuild_get_variable_n(ST("_OUT_FILES")); append_string_to_variable(pVar, pOutput->value, pOutput->value_length, 1 /* append */); if (pOutputMaybe->value_length) append_string_to_variable(pVar, pOutputMaybe->value, pOutputMaybe->value_length, 1 /* append */); /* $(target)_2_OBJS += $(obj) */ memcpy(pszDstVar + pTarget->value_length, "_2_OBJS", sizeof("_2_OBJS")); pVar = kbuild_query_recursive_variable_n(pszDstVar, pTarget->value_length + sizeof("_2_OBJS") - 1); fInstallOldVars |= iVer <= 2 && (!pVar || !pVar->value_length); if (pVar) { if (pVar->recursive) pVar = kbuild_simplify_variable(pVar); append_string_to_variable(pVar, pObj->value, pObj->value_length, 1 /* append */); } else define_variable_vl_global(pszDstVar, pTarget->value_length + sizeof("_2_OBJS") - 1, pObj->value, pObj->value_length, 1 /* duplicate_value */, o_file, 0 /* recursive */, NULL /* flocp */); /* * Install legacy variables. */ if (fInstallOldVars) { /* $(target)_OBJS_ = $($(target)_2_OBJS)*/ memcpy(pszDstVar + pTarget->value_length, "_OBJS_", sizeof("_OBJS_")); pszSrcVar[0] = '$'; pszSrcVar[1] = '('; memcpy(pszSrcVar + 2, pTarget->value, pTarget->value_length); psz = pszSrcVar + 2 + pTarget->value_length; memcpy(psz, "_2_OBJS)", sizeof("_2_OBJS)")); define_variable_vl_global(pszDstVar, pTarget->value_length + sizeof("_OBJS_") - 1, pszSrcVar, pTarget->value_length + sizeof("$(_2_OBJS)") - 1, 1 /* duplicate_value */, o_file, 1 /* recursive */, NULL /* flocp */); } /* $(eval $(def_target_source_rule)) */ pVar = kbuild_get_recursive_variable("def_target_source_rule"); pszVal = variable_expand_string_2 (o, pVar->value, pVar->value_length, &psz); assert(!((size_t)pszVal & 3)); install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf); eval_buffer(pszVal, psz); restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf); kbuild_put_sdks(&Sdks); (void)pszFuncName; *pszVal = '\0'; return pszVal; } /* ## Inherit one template property in a non-accumulative manner. # @param $(prop) Property name # @param $(target) Target name # @todo fix the precedence order for some properties. define def_inherit_template_one ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop) ifndef $(target)_$(prop) $(target)_$(prop) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg) ifndef $(target)_$(prop).$(bld_trg) $(target)_$(prop).$(bld_trg) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch) ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch) $(target)_$(prop).$(bld_trg).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch) ifndef $(target)_$(prop).$(bld_trg_arch) $(target)_$(prop).$(bld_trg_arch) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu) ifndef $(target)_$(prop).$(bld_trg_cpu) $(target)_$(prop).$(bld_trg_cpu) := $(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)) endif endif endef ## Inherit one template property in a non-accumulative manner, deferred expansion. # @param 1: $(prop) Property name # @param 2: $(target) Target name # @todo fix the precedence order for some properties. # @remark this define relies on double evaluation define def_inherit_template_one_deferred ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop) ifndef $(target)_$(prop) $(target)_$(prop) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg) ifndef $(target)_$(prop).$(bld_trg) $(target)_$(prop).$(bld_trg) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch) ifndef $(target)_$(prop).$(bld_trg).$(bld_trg_arch) $(target)_$(prop).$(bld_trg).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch) ifndef $(target)_$(prop).$(bld_trg_arch) $(target)_$(prop).$(bld_trg_arch) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)) endif endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu) ifndef $(target)_$(prop).$(bld_trg_cpu) $(target)_$(prop).$(bld_trg_cpu) = $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)) endif endif endef ## Inherit one acculumlative template property where the 'most significant' items are at the left end. # @param $(prop) Property name # @param $(target) Target name define def_inherit_template_one_accumulate_l ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop) ifeq ($$(flavor $(target)_$(prop)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop)) endif $(target)_$(prop) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE) ifeq ($$(flavor $(target)_$(prop).$(KBUILD_TYPE)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(KBUILD_TYPE)) endif $(target)_$(prop).$(KBUILD_TYPE) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg) ifeq ($$(flavor $(target)_$(prop).$(bld_trg)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg)) endif $(target)_$(prop).$(bld_trg) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch) ifeq ($$(flavor $(target)_$(prop).$(bld_trg).$(bld_trg_arch)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg).$(bld_trg_arch)) endif $(target)_$(prop).$(bld_trg).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu) ifeq ($$(flavor $(target)_$(prop).$(bld_trg_cpu)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_cpu)) endif $(target)_$(prop).$(bld_trg_cpu) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch) ifeq ($$(flavor $(target)_$(prop).$(bld_trg_arch)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_arch)) endif $(target)_$(prop).$(bld_trg_arch) += $$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)) endif endef ## Inherit one acculumlative template property where the 'most significant' items are at the right end. # @param $(prop) Property name # @param $(target) Target name define def_inherit_template_one_accumulate_r ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop) ifeq ($$(flavor $(target)_$(prop)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop)) endif $(target)_$(prop) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE) ifeq ($$(flavor $(target)_$(prop).$(KBUILD_TYPE)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(KBUILD_TYPE)) endif $(target)_$(prop).$(KBUILD_TYPE) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(KBUILD_TYPE)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg) ifeq ($$(flavor $(target)_$(prop).$(bld_trg)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg)) endif $(target)_$(prop).$(bld_trg) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch) ifeq ($$(flavor $(target)_$(prop).$(bld_trg).$(bld_trg_arch)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg).$(bld_trg_arch)) endif $(target)_$(prop).$(bld_trg).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg).$(bld_trg_arch)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu) ifeq ($$(flavor $(target)_$(prop).$(bld_trg_cpu)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_cpu)) endif $(target)_$(prop).$(bld_trg_cpu) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_cpu)) endif ifdef TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch) ifeq ($$(flavor $(target)_$(prop).$(bld_trg_arch)),simple) $$(evalcall2 def_simple_2_recursive,$(target)_$(prop).$(bld_trg_arch)) endif $(target)_$(prop).$(bld_trg_arch) <=$$(TEMPLATE_$($(target)_TEMPLATE)_$(prop).$(bld_trg_arch)) endif endef ## Inherit template properties for on target. # @param $(target) Target name. define def_inherit_template # sanity check. ifdef _$(target)_ALREADY_PROCESSED $(error kBuild: The target $(target) appears more than once in the target lists! Please correct the makefile(s)) endif _$(target)_ALREADY_PROCESSED := 1 # Inherit any default template. ifdef TEMPLATE ifeq ($($(target)_TEMPLATE),) $(eval $(target)_TEMPLATE:=$(TEMPLATE)) endif endif # Expand the template if specified. ifneq ($($(target)_TEMPLATE),) $(foreach prop,$(PROPS_SINGLE),$(evalval def_inherit_template_one)) $(foreach prop,$(PROPS_DEFERRED),$(eval $(def_inherit_template_one_deferred))) # exploits the 2 evaluation, so no value! $(foreach prop,$(PROPS_ACCUMULATE_L),$(eval $(def_inherit_template_one_accumulate_l))) # += works fine without value $(foreach prop,$(PROPS_ACCUMULATE_R),$(eval $(def_inherit_template_one_accumulate_r))) # use <= (kmk addition) endif endef Invoked like this: $(kb-exp-tmpl 1,$(_ALL_TARGET_TARGETS),$(KBUILD_TARGET),$(KBUILD_TARGET_ARCH),$(KBUILD_TARGET_CPU),$(KBUILD_TYPE)) */ char * func_kbuild_expand_template(char *o, char **argv, const char *pszFuncName) { const char *pszVersion = argv[0]; const char *pszBldTrg = argv[2]; const char *pszBldTrgArch = argv[3]; const char *pszBldTrgCpu = argv[4]; const char *pszBldType = argv[5]; size_t cchBldTrg = strlen(pszBldTrg); size_t cchBldTrgArch = strlen(pszBldTrgArch); size_t cchBldTrgCpu = strlen(pszBldTrgCpu); size_t cchBldType = strlen(pszBldType); size_t cchMaxBld = cchBldTrg + cchBldTrgArch + cchBldTrgCpu + cchBldType; /* too big, but so what. */ struct kbet_key { unsigned int cch; char *psz; } aKeys[6]; unsigned int const cKeys = 6; unsigned int iKey; struct variable *pDefTemplate; struct variable *pProps; struct kbet_prop { const char *pch; unsigned int cch; enum kbet_prop_enum { kPropSingle, kPropDeferred, kPropAccumulateL, kPropAccumulateR } enmType; } *paProps; unsigned int cProps; unsigned int iProp; size_t cchMaxProp; struct variable *pVarTrg; struct variable *pVarSrc; const char *pszIter; const char *pszTarget; unsigned int cchTarget; char *pszSrc = 0; char *pszSrcRef = 0; char *pszSrcBuf = 0; size_t cchSrcBuf = 0; char *pszTrg = 0; size_t cchTrg = 0; /* * Validate input. */ if (pszVersion[0] != '1' || pszVersion[1]) fatal(NULL, "%s: Unsupported version `%s'", pszFuncName, pszVersion); if (!cchBldTrg) fatal(NULL, "%s: missing bldtrg", pszFuncName); if (!cchBldTrgArch) fatal(NULL, "%s: missing bld_trg_arch", pszFuncName); if (!cchBldTrgCpu) fatal(NULL, "%s: missing bld_trg_cpu", pszFuncName); if (!cchBldType) fatal(NULL, "%s: missing bld_type", pszFuncName); /* * Prepare the keywords, prepending dots for quicker copying. * This allows for an inner loop when processing properties, saving code * at the expense of a few xmallocs. */ /* the first entry is empty. */ aKeys[0].cch = 0; aKeys[0].psz = NULL; /* .$(bld_type) */ aKeys[1].cch = cchBldType + 1; aKeys[1].psz = xmalloc (aKeys[1].cch + 1); aKeys[1].psz[0] = '.'; memcpy(aKeys[1].psz + 1, pszBldType, cchBldType + 1); /* .$(bld_trg) */ aKeys[2].cch = cchBldTrg + 1; aKeys[2].psz = xmalloc (aKeys[2].cch + 1); aKeys[2].psz[0] = '.'; memcpy(aKeys[2].psz + 1, pszBldTrg, cchBldTrg + 1); /* .$(bld_trg).$(bld_trg_arch) */ aKeys[3].cch = cchBldTrg + 1 + cchBldTrgArch + 1; aKeys[3].psz = xmalloc (aKeys[3].cch + 1); aKeys[3].psz[0] = '.'; memcpy(aKeys[3].psz + 1, pszBldTrg, cchBldTrg); aKeys[3].psz[1 + cchBldTrg] = '.'; memcpy(aKeys[3].psz + 1 + cchBldTrg + 1, pszBldTrgArch, cchBldTrgArch + 1); /* .$(bld_trg_cpu) */ aKeys[4].cch = cchBldTrgCpu + 1; aKeys[4].psz = xmalloc (aKeys[4].cch + 1); aKeys[4].psz[0] = '.'; memcpy(aKeys[4].psz + 1, pszBldTrgCpu, cchBldTrgCpu + 1); /* .$(bld_trg_arch) */ aKeys[5].cch = cchBldTrgArch + 1; aKeys[5].psz = xmalloc (aKeys[5].cch + 1); aKeys[5].psz[0] = '.'; memcpy(aKeys[5].psz + 1, pszBldTrgArch, cchBldTrgArch + 1); /* * Prepare the properties, folding them into an array. * This way we won't have to reparse them for each an every target, though * it comes at the expense of one or more heap calls. */ #define PROP_ALLOC_INC 128 iProp = 0; cProps = PROP_ALLOC_INC; paProps = xmalloc(sizeof(*pProps) * cProps); pProps = kbuild_get_variable_n(ST("PROPS_SINGLE")); pszIter = pProps->value; while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch))) { paProps[iProp].enmType = kPropSingle; if (++iProp >= cProps) { cProps += PROP_ALLOC_INC; paProps = xrealloc(paProps, sizeof(*paProps) * cProps); } } pProps = kbuild_get_variable_n(ST("PROPS_DEFERRED")); pszIter = pProps->value; while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch))) { paProps[iProp].enmType = kPropDeferred; if (++iProp >= cProps) { cProps += PROP_ALLOC_INC; paProps = xrealloc(paProps, sizeof(*paProps) * cProps); } } pProps = kbuild_get_variable_n(ST("PROPS_ACCUMULATE_L")); pszIter = pProps->value; while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch))) { paProps[iProp].enmType = kPropAccumulateL; if (++iProp >= cProps) { cProps += PROP_ALLOC_INC; paProps = xrealloc(paProps, sizeof(*paProps) * cProps); } } pProps = kbuild_get_variable_n(ST("PROPS_ACCUMULATE_R")); pszIter = pProps->value; while ((paProps[iProp].pch = find_next_token(&pszIter, &paProps[iProp].cch))) { paProps[iProp].enmType = kPropAccumulateR; if (++iProp >= cProps) { cProps += PROP_ALLOC_INC; paProps = xrealloc(paProps, sizeof(*paProps) * cProps); } } #undef PROP_ALLOC_INC cProps = iProp; /* find the max prop length. */ cchMaxProp = paProps[0].cch; while (--iProp > 0) if (paProps[iProp].cch > cchMaxProp) cchMaxProp = paProps[iProp].cch; /* * Query and prepare (strip) the default template * (given by the TEMPLATE variable). */ pDefTemplate = kbuild_lookup_variable_n(ST("TEMPLATE")); if (pDefTemplate) { if ( pDefTemplate->value_length && ( isspace(pDefTemplate->value[0]) || isspace(pDefTemplate->value[pDefTemplate->value_length - 1]))) { unsigned int off; if (pDefTemplate->rdonly_val) fatal(NULL, "%s: TEMPLATE is read-only", pszFuncName); /* head */ for (off = 0; isspace(pDefTemplate->value[off]); off++) /* nothing */; if (off) { pDefTemplate->value_length -= off; memmove(pDefTemplate->value, pDefTemplate->value + off, pDefTemplate->value_length + 1); } /* tail */ off = pDefTemplate->value_length; while (off > 0 && isspace(pDefTemplate->value[off - 1])) off--; pDefTemplate->value_length = off; pDefTemplate->value[off] = '\0'; } if (!pDefTemplate->value_length) pDefTemplate = NULL; } /* * Iterate the target list. */ pszIter = argv[1]; while ((pszTarget = find_next_token(&pszIter, &cchTarget))) { char *pszTrgProp, *pszSrcProp; char *pszTrgKey, *pszSrcKey; struct variable *pTmpl; const char *pszTmpl; size_t cchTmpl, cchMax; /* resize the target buffer. */ cchMax = cchTarget + cchMaxProp + cchMaxBld + 10; if (cchTrg < cchMax) { cchTrg = (cchMax + 31U) & ~(size_t)31; pszTrg = xrealloc(pszTrg, cchTrg); } /* * Query the TEMPLATE property, if not found or zero-length fall back on the default. */ memcpy(pszTrg, pszTarget, cchTarget); pszTrgProp = pszTrg + cchTarget; memcpy(pszTrgProp, "_TEMPLATE", sizeof("_TEMPLATE")); pszTrgProp++; /* after '_'. */ /** @todo Change this to a recursive lookup with simplification below. That * will allow target_TEMPLATE = $(NO_SUCH_TEMPLATE) instead of having * to use target_TEMPLATE = DUMMY */ pTmpl = kbuild_lookup_variable_n(pszTrg, cchTarget + sizeof("_TEMPLATE") - 1); if (!pTmpl || !pTmpl->value_length) { if (!pDefTemplate) continue; /* no template */ pszTmpl = pDefTemplate->value; cchTmpl = pDefTemplate->value_length; } else { pszTmpl = pTmpl->value; cchTmpl = pTmpl->value_length; while (isspace(*pszTmpl)) cchTmpl--, pszTmpl++; if (!cchTmpl) continue; /* no template */ } /* resize the source buffer. */ cchMax = sizeof("TEMPLATE_") + cchTmpl + cchMaxProp + cchMaxBld + 10 + sizeof(void *); if (cchSrcBuf < cchMax) { cchSrcBuf = (cchMax + 31U) & ~(size_t)31; pszSrcBuf = xrealloc(pszSrcBuf, cchSrcBuf); pszSrc = pszSrcBuf + sizeof(void *); assert(sizeof(void *) >= 2); pszSrcRef = pszSrc - 2; pszSrcRef[0] = '$'; pszSrcRef[1] = '('; } /* prepare the source buffer */ memcpy(pszSrc, "TEMPLATE_", sizeof("TEMPLATE_") - 1); pszSrcProp = pszSrc + sizeof("TEMPLATE_") - 1; memcpy(pszSrcProp, pszTmpl, cchTmpl); pszSrcProp += cchTmpl; *pszSrcProp++ = '_'; /* * Process properties. * Note! The single and deferred are handled in the same way now. */ #define BY_REF_LIMIT 64 /*(cchSrcVar * 4 > 64 ? cchSrcVar * 4 : 64)*/ for (iProp = 0; iProp < cProps; iProp++) { memcpy(pszTrgProp, paProps[iProp].pch, paProps[iProp].cch); pszTrgKey = pszTrgProp + paProps[iProp].cch; memcpy(pszSrcProp, paProps[iProp].pch, paProps[iProp].cch); pszSrcKey = pszSrcProp + paProps[iProp].cch; for (iKey = 0; iKey < cKeys; iKey++) { char *pszTrgEnd; size_t cchSrcVar; /* lookup source, skip ahead if it doesn't exist. */ memcpy(pszSrcKey, aKeys[iKey].psz, aKeys[iKey].cch); cchSrcVar = pszSrcKey - pszSrc + aKeys[iKey].cch; pszSrc[cchSrcVar] = '\0'; pVarSrc = kbuild_query_recursive_variable_n(pszSrc, cchSrcVar); if (!pVarSrc) continue; /* lookup target, skip ahead if it exists. */ memcpy(pszTrgKey, aKeys[iKey].psz, aKeys[iKey].cch); pszTrgEnd = pszTrgKey + aKeys[iKey].cch; *pszTrgEnd = '\0'; pVarTrg = kbuild_query_recursive_variable_n(pszTrg, pszTrgEnd - pszTrg); switch (paProps[iProp].enmType) { case kPropAccumulateL: case kPropAccumulateR: if (pVarTrg) { /* Append to existing variable. If the source is recursive, or we append by reference, we'll have to make sure the target is recusive as well. */ if ( !pVarTrg->recursive && ( pVarSrc->value_length >= BY_REF_LIMIT || pVarSrc->recursive)) pVarTrg->recursive = 1; if (pVarSrc->value_length < BY_REF_LIMIT) append_string_to_variable(pVarTrg, pVarSrc->value, pVarSrc->value_length, paProps[iProp].enmType == kPropAccumulateL /* append */); else { pszSrc[cchSrcVar] = ')'; pszSrc[cchSrcVar + 1] = '\0'; append_string_to_variable(pVarTrg, pszSrcRef, 2 + cchSrcVar + 1, paProps[iProp].enmType == kPropAccumulateL /* append */); } break; } /* else: the target variable doesn't exist, create it. */ /* fall thru */ case kPropSingle: case kPropDeferred: if (pVarTrg) continue; /* skip ahead if it already exists. */ /* copy the variable if its short, otherwise reference it. */ if (pVarSrc->value_length < BY_REF_LIMIT) define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg, pVarSrc->value, pVarSrc->value_length, 1 /* duplicate_value */, o_file, pVarSrc->recursive, NULL /* flocp */); else { pszSrc[cchSrcVar] = ')'; pszSrc[cchSrcVar + 1] = '\0'; define_variable_vl_global(pszTrg, pszTrgEnd - pszTrg, pszSrcRef, 2 + cchSrcVar + 1, 1 /* duplicate_value */, o_file, 1 /* recursive */, NULL /* flocp */); } break; } } /* foreach key */ } /* foreach prop */ #undef BY_REF_LIMIT } /* foreach target */ /* * Cleanup. */ free(pszSrcBuf); free(pszTrg); free(paProps); for (iKey = 1; iKey < cKeys; iKey++) free(aKeys[iKey].psz); return o; } #endif /* KMK_HELPERS */ kbuild-2695/src/kmk/Makefile.kmk0000644000000000000000000003322712247157306015241 0ustar rootroot# $Id: Makefile.kmk 2667 2012-11-25 19:52:26Z bird $ ## @file # Sub-makefile for kmk / GNU Make. # # # Copyright (c) 2004-2011 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # SUB_DEPTH = ../.. include $(KBUILD_PATH)/subheader.kmk # # Template for kmk and the kmk_* binaries in this makefile. # TEMPLATE_BIN-KMK = Template for src/gmake binaries TEMPLATE_BIN-KMK_EXTENDS = BIN-THREADED TEMPLATE_BIN-KMK_DEFS = \ HAVE_CONFIG_H \ $(TEMPLATE_BIN_DEFS) \ KBUILD_SVN_REV=$(KBUILD_SVN_REV) \ KBUILD_TYPE=\"$(KBUILD_TYPE)\" TEMPLATE_BIN-KMK_DEPS = \ $(kmk_0_OUTDIR)/config.h \ $(kmk_0_OUTDIR)/fts.h TEMPLATE_BIN-KMK_CLEAN = $(TEMPLATE_BIN-KMK_DEPS) TEMPLATE_BIN-KMK_DEPS.solaris = \ $(kmk_0_OUTDIR)/paths.h TEMPLATE_BIN-KMK_CLEAN.solaris = $(TEMPLATE_BIN-KMK_DEPS.solaris) TEMPLATE_BIN-KMK_DEPS.win = \ $(kmk_0_OUTDIR)/sysexits.h \ $(kmk_0_OUTDIR)/unistd.h \ $(kmk_0_OUTDIR)/paths.h \ $(kmk_0_OUTDIR)/grp.h \ $(kmk_0_OUTDIR)/pwd.h \ $(kmk_0_OUTDIR)/inttypes.h TEMPLATE_BIN-KMK_CFLAGS.win.amd64 = $(TEMPLATE_BIN-THREADED_CFLAGS.win.amd64) -wd4244 -wd4267 TEMPLATE_BIN-KMK_CLEAN.win = $(TEMPLATE_BIN-KMK_DEPS.win) TEMPLATE_BIN-KMK_INCS = $(kmk_0_OUTDIR) . $(TEMPLATE_BIN-THREADED_INCS) TEMPLATE_BIN-KMK_INCS.darwin = glob TEMPLATE_BIN-KMK_INCS.dragonfly = glob TEMPLATE_BIN-KMK_INCS.freebsd = glob TEMPLATE_BIN-KMK_INCS.haiku = glob TEMPLATE_BIN-KMK_INCS.openbsd = glob TEMPLATE_BIN-KMK_INCS.solaris = glob TEMPLATE_BIN-KMK_LIBS = $(TEMPLATE_BIN-THREADED_LIBS) $(kmkmissing_1_TARGET) $(LIB_KUTIL) ifdef ELECTRIC_HEAP # for electric heap (see electric.c) - windows only. ifeq ($(KBUILD_TARGET),win) TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN-THREADED_CFLAGS) /FI$(kmk_DEFPATH)/electric.h -DELECTRIC_HEAP=1 else TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN-THREADED_CFLAGS) -include $(kmk_DEFPATH)/electric.h -DELECTRIC_HEAP=1 endif endif # # A library containing the missing features needed by kmk and the # kmk_* binaries. Saves a bit of work later on. # LIBRARIES += kmkmissing kmkmissing_TEMPLATE = BIN-KMK kmkmissing_DEFS = KMK kmkmissing_NOINST = 1 kmkmissing_SOURCES = \ kmkbuiltin/err.c \ kmkbuiltin/fts.c \ kmkbuiltin/setmode.c \ kmkbuiltin/strmode.c \ kmkbuiltin/kbuild_version.c \ kmkbuiltin/kbuild_protection.c \ getopt.c \ getopt1.c \ electric.c kmkmissing_SOURCES.darwin = \ kmkbuiltin/darwin.c \ glob/glob.c \ glob/fnmatch.c kmkmissing_SOURCES.dragonfly = \ glob/glob.c \ glob/fnmatch.c kmkmissing_SOURCES.freebsd = \ glob/glob.c \ glob/fnmatch.c kmkmissing_SOURCES.haiku = \ kmkbuiltin/haikufakes.c \ glob/glob.c \ glob/fnmatch.c kmkmissing_SOURCES.linux += \ kmkbuiltin/strlcpy.c kmkmissing_SOURCES.openbsd = \ kmkbuiltin/openbsd.c \ glob/glob.c kmkmissing_SOURCES.solaris = \ kmkbuiltin/strlcpy.c \ kmkbuiltin/solfakes.c \ glob/glob.c \ glob/fnmatch.c kmkmissing_SOURCES.win += \ kmkbuiltin/strlcpy.c \ kmkbuiltin/mscfakes.c \ glob/glob.c \ glob/fnmatch.c \ getloadavg.c \ w32/subproc/misc.c \ w32/subproc/sub_proc.c \ w32/subproc/w32err.c \ w32/compat/dirent.c \ w32/pathstuff.c \ w32/imagecache.c # # kmk # PROGRAMS += kmk kmk_TEMPLATE = BIN-KMK kmk_DEFS = \ NO_ARCHIVES \ EXPERIMENTAL \ CONFIG_WITH_TOUPPER_TOLOWER \ CONFIG_WITH_DEFINED \ CONFIG_WITH_EXPLICIT_MULTITARGET \ CONFIG_WITH_DOT_MUST_MAKE \ CONFIG_WITH_PREPEND_ASSIGNMENT \ CONFIG_WITH_LOCAL_VARIABLES \ CONFIG_WITH_2ND_TARGET_EXPANSION \ CONFIG_WITH_ALLOC_CACHES \ CONFIG_WITH_STRCACHE2 \ \ KMK \ KMK_HELPERS \ CONFIG_NO_DEFAULT_SUFFIXES \ CONFIG_NO_DEFAULT_PATTERN_RULES \ CONFIG_NO_DEFAULT_TERMINAL_RULES \ CONFIG_NO_DEFAULT_SUFFIX_RULES \ CONFIG_NO_DEFAULT_VARIABLES \ \ CONFIG_WITH_ABSPATHEX \ CONFIG_WITH_COMMANDS_FUNC \ CONFIG_WITH_DATE \ CONFIG_WITH_DEFINED_FUNCTIONS \ CONFIG_WITH_EVALPLUS \ CONFIG_WITH_FILE_SIZE \ CONFIG_WITH_LOOP_FUNCTIONS \ CONFIG_WITH_MATH \ CONFIG_WITH_NANOTS \ CONFIG_WITH_ROOT_FUNC \ CONFIG_WITH_RSORT \ CONFIG_WITH_STACK \ CONFIG_WITH_STRING_FUNCTIONS \ CONFIG_WITH_WHERE_FUNCTION \ CONFIG_WITH_WHICH \ CONFIG_WITH_XARGS \ \ CONFIG_WITH_EXTENDED_NOTPARALLEL \ CONFIG_WITH_INCLUDEDEP \ CONFIG_WITH_VALUE_LENGTH \ CONFIG_WITH_COMPARE \ CONFIG_WITH_SET_CONDITIONALS \ CONFIG_WITH_IF_CONDITIONALS \ CONFIG_WITH_PRINTF \ CONFIG_WITH_MINIMAL_STATS \ \ CONFIG_PRETTY_COMMAND_PRINTING \ CONFIG_WITH_PRINT_STATS_SWITCH \ CONFIG_WITH_PRINT_TIME_SWITCH \ CONFIG_WITH_RDONLY_VARIABLE_VALUE \ CONFIG_WITH_LAZY_DEPS_VARS \ CONFIG_WITH_MEMORY_OPTIMIZATIONS \ \ KBUILD_HOST=\"$(KBUILD_TARGET)\" \ KBUILD_HOST_ARCH=\"$(KBUILD_TARGET_ARCH)\" \ KBUILD_HOST_CPU=\"$(KBUILD_TARGET_CPU)\" kmk_DEFS.x86 = CONFIG_WITH_OPTIMIZATION_HACKS kmk_DEFS.amd64 = CONFIG_WITH_OPTIMIZATION_HACKS kmk_DEFS.win = CONFIG_NEW_WIN32_CTRL_EVENT CONFIG_WITH_FAST_IS_SPACE kmk_DEFS.debug = CONFIG_WITH_MAKE_STATS kmk_SOURCES = \ main.c \ kbuild.c \ kbuild-read.c \ read.c \ expreval.c \ incdep.c \ hash.c \ strcache.c \ strcache2.c \ variable.c \ ar.c \ arscan.c \ commands.c \ default.c \ dir.c \ expand.c \ file.c \ function.c \ implicit.c \ job.c \ misc.c \ alloccache.c \ remake.c \ rule.c \ signame.c \ version.c \ vpath.c \ remote-stub.c kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS #kmk_LIBS.solaris = malloc #kmk_DEFS.solaris += HAVE_MALLINFO # # kmkbuiltin commands # kmk_DEFS += CONFIG_WITH_KMK_BUILTIN kmk_LIBS += $(LIB_KUTIL) $(LIB_KDEP) kmk_SOURCES += \ kmkbuiltin.c \ kmkbuiltin/append.c \ kmkbuiltin/cat.c \ kmkbuiltin/chmod.c \ kmkbuiltin/cmp.c \ kmkbuiltin/cmp_util.c \ kmkbuiltin/cp.c \ kmkbuiltin/cp_utils.c \ kmkbuiltin/echo.c \ kmkbuiltin/expr.c \ kmkbuiltin/install.c \ kmkbuiltin/kDepIDB.c \ kmkbuiltin/kDepObj.c \ kmkbuiltin/md5sum.c \ kmkbuiltin/mkdir.c \ kmkbuiltin/mv.c \ kmkbuiltin/ln.c \ kmkbuiltin/printf.c \ kmkbuiltin/rm.c \ kmkbuiltin/rmdir.c \ kmkbuiltin/sleep.c \ kmkbuiltin/test.c \ ## @todo kmkbuiltin/redirect.c ## Some profiling #kmk_SOURCES += kbuildprf.c #kmk_DEFS += open=prf_open read=prf_read lseek=prf_lseek close=prf_close ##kmk_DEFS += KMK_PRF=1 ##kmkmissing_DEFS += KMK_PRF=1 # # Standalone kmkbuiltin commands. # PROGRAMS += \ kmk_append \ kmk_cat \ kmk_chmod \ kmk_cp \ kmk_cmp \ kmk_echo \ kmk_expr \ kmk_md5sum \ kmk_mkdir \ kmk_mv \ kmk_install \ kmk_ln \ kmk_printf \ kmk_redirect \ kmk_rm \ kmk_rmdir \ kmk_sleep \ kmk_test \ kDepIDB \ kDepObj \ kmk_append_TEMPLATE = BIN-KMK kmk_append_DEFS = kmk_builtin_append=main kmk_append_INCS = . kmk_append_SOURCES = \ kmkbuiltin/append.c kmk_cat_TEMPLATE = BIN-KMK kmk_cat_DEFS = kmk_builtin_cat=main kmk_cat_SOURCES = \ kmkbuiltin/cat.c kmk_chmod_TEMPLATE = BIN-KMK kmk_chmod_DEFS = kmk_builtin_chmod=main kmk_chmod_SOURCES = \ kmkbuiltin/chmod.c kmk_cmp_TEMPLATE = BIN-KMK kmk_cmp_DEFS = kmk_builtin_cmp=main kmk_cmp_SOURCES = \ kmkbuiltin/cmp.c \ kmkbuiltin/cmp_util.c kmk_cp_TEMPLATE = BIN-KMK kmk_cp_DEFS = kmk_builtin_cp=main kmk_cp_SOURCES = \ kmkbuiltin/cp.c \ kmkbuiltin/cp_utils.c \ kmkbuiltin/cmp_util.c kmk_echo_TEMPLATE = BIN-KMK kmk_echo_DEFS = kmk_builtin_echo=main kmk_echo_SOURCES = \ kmkbuiltin/echo.c kmk_expr_TEMPLATE = BIN-KMK kmk_expr_DEFS = kmk_builtin_expr=main kmk_expr_SOURCES = \ kmkbuiltin/expr.c kmk_install_TEMPLATE = BIN-KMK kmk_install_DEFS = kmk_builtin_install=main kmk_install_SOURCES = \ kmkbuiltin/install.c kmk_ln_TEMPLATE = BIN-KMK kmk_ln_DEFS = kmk_builtin_ln=main kmk_ln_SOURCES = \ kmkbuiltin/ln.c kmk_mkdir_TEMPLATE = BIN-KMK kmk_mkdir_DEFS = kmk_builtin_mkdir=main kmk_mkdir_SOURCES = \ kmkbuiltin/mkdir.c kmk_md5sum_TEMPLATE = BIN-KMK kmk_md5sum_DEFS = kmk_builtin_md5sum=main kmk_md5sum_SOURCES = \ kmkbuiltin/md5sum.c kmk_md5sum_LIBS = $(LIB_KUTIL) kmk_mv_TEMPLATE = BIN-KMK kmk_mv_DEFS = kmk_builtin_mv=main kmk_mv_SOURCES = \ kmkbuiltin/mv.c kmk_printf_TEMPLATE = BIN-KMK kmk_printf_DEFS = kmk_builtin_printf=main kmk_printf_SOURCES = \ kmkbuiltin/printf.c kmk_rm_TEMPLATE = BIN-KMK kmk_rm_DEFS = kmk_builtin_rm=main kmk_rm_SOURCES = \ kmkbuiltin/rm.c kmk_redirect_TEMPLATE = BIN-KMK kmk_redirect_DEFS = kmk_builtin_redirect=main kmk_redirect_SOURCES = \ kmkbuiltin/redirect.c kmk_redirect_SOURCES.win = \ ../lib/startuphacks-win.c kmk_rmdir_TEMPLATE = BIN-KMK kmk_rmdir_DEFS = kmk_builtin_rmdir=main kmk_rmdir_SOURCES = \ kmkbuiltin/rmdir.c kmk_sleep_TEMPLATE = BIN-KMK kmk_sleep_DEFS = kmk_builtin_sleep=main kmk_sleep_SOURCES = \ kmkbuiltin/sleep.c kmk_test_TEMPLATE = BIN-KMK kmk_test_DEFS = kmk_builtin_test=main kmk_test_SOURCES = \ kmkbuiltin/test.c kDepIDB_TEMPLATE = BIN-KMK kDepIDB_DEFS = kmk_builtin_kDepIDB=main kDepIDB_INCS = . kDepIDB_LIBS = $(LIB_KDEP) kDepIDB_SOURCES = \ kmkbuiltin/kDepIDB.c kDepObj_TEMPLATE = BIN-KMK kDepObj_DEFS = kmk_builtin_kDepObj=main kDepObj_INCS = . kDepObj_LIBS = $(LIB_KDEP) kDepObj_SOURCES = \ kmkbuiltin/kDepObj.c # # kmk_gmake - almost plain GNU Make. # PROGRAMS += kmk_gmake kmk_gmake_TEMPLATE = BIN-KMK kmk_gmake_DEFS = \ HAVE_CONFIG_H \ CONFIG_WITH_TOUPPER_TOLOWER \ EXPERIMENTAL # NO_ARCHIVES kmk_gmake_SOURCES = \ main.c \ read.c \ hash.c \ strcache.c \ variable.c \ ar.c \ arscan.c \ commands.c \ default.c \ dir.c \ expand.c \ file.c \ function.c \ implicit.c \ job.c \ misc.c \ remake.c \ rule.c \ signame.c \ version.c \ vpath.c \ remote-stub.c # # kmk_fmake - Faster GNU Make. # ifeq ($(USER),bird) # for experimental purposes only. PROGRAMS += kmk_fgmake endif kmk_fgmake_TEMPLATE = BIN-KMK kmk_fgmake_DEFS = \ HAVE_CONFIG_H \ NO_ARCHIVES \ CONFIG_WITH_TOUPPER_TOLOWER \ EXPERIMENTAL \ \ CONFIG_WITH_ALLOC_CACHES \ CONFIG_WITH_LAZY_DEPS_VARS \ CONFIG_WITH_STRCACHE2 \ CONFIG_WITH_VALUE_LENGTH \ CONFIG_WITH_RDONLY_VARIABLE_VALUE # TODO ? # CONFIG_WITH_PRINT_STATS_SWITCH \ # CONFIG_WITH_EXTENDED_NOTPARALLEL \ kmk_fgmake_SOURCES = \ main.c \ read.c \ hash.c \ strcache.c \ strcache2.c \ variable.c \ ar.c \ arscan.c \ commands.c \ default.c \ dir.c \ expand.c \ file.c \ function.c \ implicit.c \ job.c \ misc.c \ alloccache.c \ remake.c \ rule.c \ signame.c \ version.c \ vpath.c \ remote-stub.c include $(FILE_KBUILD_SUB_FOOTER) # # Use checked in config.h instead of running ./Configure for it. # kmk_config.h.$(KBUILD_TARGET) := $(kmk_DEFPATH)/config.h.$(KBUILD_TARGET) $(kmk_0_OUTDIR)/config.h: $(kmk_config.h.$(KBUILD_TARGET)) $(MKDIR) -p $(dir $@) $(CP) $^ $@ # # Some missing headers. # $(kmk_0_OUTDIR)/fts.h: $(kmk_DEFPATH)/kmkbuiltin/ftsfake.h | $(call DIRDEP,$(kmk_0_OUTDIR)) $(CP) $^ $@ $(kmk_0_OUTDIR)/unistd.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/sysexits.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/inttypes.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/paths.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/pwd.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ $(kmk_0_OUTDIR)/grp.h: | $(call DIRDEP,$(kmk_0_OUTDIR)) $(ECHO_EXT) > $@ # # Some tests. # parallel: parallel_1 parallel_2 parallel_3 parallel_4 parallel_5 parallel_1 parallel_2 parallel_3 parallel_4 parallel_5: echo $@_start ; sleep 1; echo $@_done my_test: echo "1" echo "2" echo "3" echo "4" # # Shell execution tests. # test_shell: test_shell_quoting test_shell_double_quoting test_shell_newline # shell double and single quoting check (was busted on windows in 3.81). test_shell_quoting: $(ECHO_EXT) "double quoted sTrInG" $(ECHO_EXT) "double quoted sTrInG" | $(SED_EXT) -e "s/sTrInG/string/g" $(ECHO_EXT) 'single quoted sTrInG' | $(SED_EXT) -e 's/sTrInG/string/g' $(ECHO) "This string should not be printed with double quotes." $(ECHO) 'This string should not be printed with single quotes.' ( echo " #define PWD \"`pwd`\""; ) test_shell_double_quoting: $(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \ "s/foo/$@/" -e \ "s/foo/works/" \ -e "s/foo/\!/" test_shell_double_quoting2: $(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \ "s/foo/$@/" -e \ "s/foo/works/" \ -e\ "s/foo/\!/" # when using batch mode shell, the newline got escaped twice and spoiling everything. test_shell_newline: $(ECHO_EXT) "foo foo foo" | $(SED_EXT) -e \ 's/foo/$@/' -e \ 's/foo/works/' \ -e 's/foo/\!/' test_stack: $(MAKE) -f $(kmk_DEFPATH)/testcase-stack.kmk test_math: $(MAKE) -f $(kmk_DEFPATH)/testcase-math.kmk test_if1of: $(MAKE) -f $(kmk_DEFPATH)/testcase-if1of.kmk test_local: $(MAKE) -f $(kmk_DEFPATH)/testcase-local.kmk test_includedep: $(MAKE) -f $(kmk_DEFPATH)/testcase-includedep.kmk test_root: $(MAKE) -f $(kmk_DEFPATH)/testcase-root.kmk test_2ndtargetexp: $(MAKE) -f $(kmk_DEFPATH)/testcase-2ndtargetexp.kmk test_30_continued_on_failure_worker: this_executable_does_not_exist.exe echo "We shouldn't see this..." test_30_continued_on_failure: $(MAKE) -f $(MAKEFILE) test_30_continued_on_failure_worker; \ RC=$$?; \ if test $${RC} -ne 2; then \ echo "$@: FAILED - exit code $${RC} instead of 2."; \ exit 1; \ else \ echo "$@: SUCCESS"; \ fi test_lazy_deps_vars: $(MAKE) -C $(kmk_DEFPATH) -f testcase-lazy-deps-vars.kmk test_all: \ test_math \ test_stack \ test_shell \ test_if1of \ test_local \ test_root \ test_includedep \ test_2ndtargetexp \ test_30_continued_on_failure \ test_lazy_deps_vars kbuild-2695/src/kmk/configh.dos.template0000644000000000000000000000717112247157307016756 0ustar rootroot/* configh.dos -- hand-massaged config.h file for MS-DOS builds -*-C-*- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Include this header to make __DJGPP_MINOR__ available because DJGPP ports of GCC 4.3.0 and later no longer do it automatically. */ #include /* Many things are defined already by a system header. */ #include #if __DJGPP__ > 2 || __DJGPP_MINOR__ > 1 /* Define to 1 if `sys_siglist' is declared by or . */ # define SYS_SIGLIST_DECLARED 1 /* Define to 1 if the C library defines the variable `_sys_siglist'. */ # define HAVE_DECL_SYS_SIGLIST 1 #else /* Define NSIG. */ # define NSIG SIGMAX #endif /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 0 /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have the fdopen function. */ #define HAVE_FDOPEN 1 /* Define to 1 if you have the `getgroups' function. */ #define HAVE_GETGROUPS 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the mkstemp function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `setvbuf' function. */ #define HAVE_SETVBUF 1 #define SCCS_GET "get" /* Define to `unsigned long' or `unsigned long long' if doesn't define. */ #define uintmax_t unsigned long long /* Define the type of the first arg to select(). */ #define fd_set_size_t int /* Define to 1 if you have the select function. */ #define HAVE_SELECT 1 /* Define to 1 if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the vprintf library function. */ #undef HAVE_VPRINTF #define HAVE_VPRINTF 1 /* Define to 1 if you have the stricmp function. */ #define HAVE_STRICMP 1 /* Name of the package */ #define PACKAGE "%PACKAGE%" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-%PACKAGE%@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU %PACKAGE%" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "GNU %PACKAGE% %VERSION%" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "%PACKAGE%" /* Define to the version of this package. */ #define PACKAGE_VERSION "%VERSION%" /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 /* Version number of package */ #define VERSION "%VERSION%" /* Build host information. */ #define MAKE_HOST "i386-pc-msdosdjgpp" /* Grok DOS paths (drive specs and backslash path element separators) */ #define HAVE_DOS_PATHS kbuild-2695/src/kmk/signame.c0000644000000000000000000001546712247157307014616 0ustar rootroot/* Convert between signal names and numbers. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" /* If the system provides strsignal, we don't need it. */ #if !HAVE_STRSIGNAL /* If the system provides sys_siglist, we'll use that. Otherwise create our own. */ #if !HAVE_DECL_SYS_SIGLIST /* Some systems do not define NSIG in . */ #ifndef NSIG #ifdef _NSIG #define NSIG _NSIG #else #define NSIG 32 #endif #endif /* There is too much variation in Sys V signal numbers and names, so we must initialize them at runtime. */ static const char *undoc; static const char *sys_siglist[NSIG]; /* Table of abbreviations for signals. Note: A given number can appear more than once with different abbreviations. */ #define SIG_TABLE_SIZE (NSIG*2) typedef struct { int number; const char *abbrev; } num_abbrev; static num_abbrev sig_table[SIG_TABLE_SIZE]; /* Number of elements of sig_table used. */ static int sig_table_nelts = 0; /* Enter signal number NUMBER into the tables with ABBREV and NAME. */ static void init_sig (int number, const char *abbrev, const char *name) { /* If this value is ever greater than NSIG it seems like it'd be a bug in the system headers, but... better safe than sorry. We know, for example, that this isn't always true on VMS. */ if (number >= 0 && number < NSIG) sys_siglist[number] = name; if (sig_table_nelts < SIG_TABLE_SIZE) { sig_table[sig_table_nelts].number = number; sig_table[sig_table_nelts++].abbrev = abbrev; } } static int signame_init (void) { int i; undoc = xstrdup (_("unknown signal")); /* Initialize signal names. */ for (i = 0; i < NSIG; i++) sys_siglist[i] = undoc; /* Initialize signal names. */ #if defined (SIGHUP) init_sig (SIGHUP, "HUP", _("Hangup")); #endif #if defined (SIGINT) init_sig (SIGINT, "INT", _("Interrupt")); #endif #if defined (SIGQUIT) init_sig (SIGQUIT, "QUIT", _("Quit")); #endif #if defined (SIGILL) init_sig (SIGILL, "ILL", _("Illegal Instruction")); #endif #if defined (SIGTRAP) init_sig (SIGTRAP, "TRAP", _("Trace/breakpoint trap")); #endif /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't. */ #if defined (SIGABRT) init_sig (SIGABRT, "ABRT", _("Aborted")); #endif #if defined (SIGIOT) init_sig (SIGIOT, "IOT", _("IOT trap")); #endif #if defined (SIGEMT) init_sig (SIGEMT, "EMT", _("EMT trap")); #endif #if defined (SIGFPE) init_sig (SIGFPE, "FPE", _("Floating point exception")); #endif #if defined (SIGKILL) init_sig (SIGKILL, "KILL", _("Killed")); #endif #if defined (SIGBUS) init_sig (SIGBUS, "BUS", _("Bus error")); #endif #if defined (SIGSEGV) init_sig (SIGSEGV, "SEGV", _("Segmentation fault")); #endif #if defined (SIGSYS) init_sig (SIGSYS, "SYS", _("Bad system call")); #endif #if defined (SIGPIPE) init_sig (SIGPIPE, "PIPE", _("Broken pipe")); #endif #if defined (SIGALRM) init_sig (SIGALRM, "ALRM", _("Alarm clock")); #endif #if defined (SIGTERM) init_sig (SIGTERM, "TERM", _("Terminated")); #endif #if defined (SIGUSR1) init_sig (SIGUSR1, "USR1", _("User defined signal 1")); #endif #if defined (SIGUSR2) init_sig (SIGUSR2, "USR2", _("User defined signal 2")); #endif /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that is what is in POSIX.1. */ #if defined (SIGCHLD) init_sig (SIGCHLD, "CHLD", _("Child exited")); #endif #if defined (SIGCLD) init_sig (SIGCLD, "CLD", _("Child exited")); #endif #if defined (SIGPWR) init_sig (SIGPWR, "PWR", _("Power failure")); #endif #if defined (SIGTSTP) init_sig (SIGTSTP, "TSTP", _("Stopped")); #endif #if defined (SIGTTIN) init_sig (SIGTTIN, "TTIN", _("Stopped (tty input)")); #endif #if defined (SIGTTOU) init_sig (SIGTTOU, "TTOU", _("Stopped (tty output)")); #endif #if defined (SIGSTOP) init_sig (SIGSTOP, "STOP", _("Stopped (signal)")); #endif #if defined (SIGXCPU) init_sig (SIGXCPU, "XCPU", _("CPU time limit exceeded")); #endif #if defined (SIGXFSZ) init_sig (SIGXFSZ, "XFSZ", _("File size limit exceeded")); #endif #if defined (SIGVTALRM) init_sig (SIGVTALRM, "VTALRM", _("Virtual timer expired")); #endif #if defined (SIGPROF) init_sig (SIGPROF, "PROF", _("Profiling timer expired")); #endif #if defined (SIGWINCH) /* "Window size changed" might be more accurate, but even if that is all that it means now, perhaps in the future it will be extended to cover other kinds of window changes. */ init_sig (SIGWINCH, "WINCH", _("Window changed")); #endif #if defined (SIGCONT) init_sig (SIGCONT, "CONT", _("Continued")); #endif #if defined (SIGURG) init_sig (SIGURG, "URG", _("Urgent I/O condition")); #endif #if defined (SIGIO) /* "I/O pending" has also been suggested. A disadvantage is that signal only happens when the process has asked for it, not everytime I/O is pending. Another disadvantage is the confusion from giving it a different name than under Unix. */ init_sig (SIGIO, "IO", _("I/O possible")); #endif #if defined (SIGWIND) init_sig (SIGWIND, "WIND", _("SIGWIND")); #endif #if defined (SIGPHONE) init_sig (SIGPHONE, "PHONE", _("SIGPHONE")); #endif #if defined (SIGPOLL) init_sig (SIGPOLL, "POLL", _("I/O possible")); #endif #if defined (SIGLOST) init_sig (SIGLOST, "LOST", _("Resource lost")); #endif #if defined (SIGDANGER) init_sig (SIGDANGER, "DANGER", _("Danger signal")); #endif #if defined (SIGINFO) init_sig (SIGINFO, "INFO", _("Information request")); #endif #if defined (SIGNOFP) init_sig (SIGNOFP, "NOFP", _("Floating point co-processor not available")); #endif return 1; } #endif /* HAVE_DECL_SYS_SIGLIST */ char * strsignal (int sig) { static char buf[] = "Signal 12345678901234567890"; #if ! HAVE_DECL_SYS_SIGLIST # if HAVE_DECL__SYS_SIGLIST # define sys_siglist _sys_siglist # elif HAVE_DECL___SYS_SIGLIST # define sys_siglist __sys_siglist # else static char sig_initted = 0; if (!sig_initted) sig_initted = signame_init (); # endif #endif if (sig > 0 || sig < NSIG) return (char *) sys_siglist[sig]; sprintf (buf, "Signal %d", sig); return buf; } #endif /* HAVE_STRSIGNAL */ kbuild-2695/src/kmk/make_msvc_net2003.sln0000644000000000000000000000163312247157307016653 0ustar rootrootMicrosoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_msvc.net2003", "make_msvc_net2003.vcproj", "{E96B5060-3240-4723-91C9-E64F1C877A04}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.ActiveCfg = Debug|Win32 {E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.Build.0 = Debug|Win32 {E96B5060-3240-4723-91C9-E64F1C877A04}.Release.ActiveCfg = Release|Win32 {E96B5060-3240-4723-91C9-E64F1C877A04}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal kbuild-2695/src/kmk/doc/0000755000000000000000000000000012247157306013556 5ustar rootrootkbuild-2695/src/kmk/doc/Makefile.am0000644000000000000000000000226012247157306015612 0ustar rootroot# -*-Makefile-*-, or close enough # Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, # 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 3 of the License, or (at your option) any later # version. # # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . TEXI2HTML = texi2html TEXI2HTML_FLAGS = -split_chapter info_TEXINFOS = make.texi make_TEXINFOS = fdl.texi make-stds.texi CLEANFILES = make*.html ## ----------------------------- ## ## Other documentation formats. ## ## ----------------------------- ## html: make_1.html make_1.html: $(info_TEXINFOS) $(make_TEXINFOS) $(TEXI2HTML) $(TEXI2HTML_FLAGS) $(srcdir)/make.texi .PHONY: html kbuild-2695/src/kmk/README.Amiga0000644000000000000000000000527012247157306014712 0ustar rootrootShort: Port of GNU make with SAS/C (no ixemul.library required) Author: GNU, Amiga port by Aaron "Optimizer" Digulla Uploader: Aaron "Optimizer" Digulla (digulla@fh-konstanz.de) Type: dev/c This is a pure Amiga port of GNU make. It needs no extra libraries or anything. It has the following features (in addition to any features of GNU make): - Runs Amiga-Commands with SystemTags() (Execute) - Can run multi-line statements - Allows to use Device-Names in targets: c:make : make.o is ok. To distinguish between device-names and target : or ::, MAKE looks for spaces. If there are any around :, it's taken as a target delimiter, if there are none, it's taken as the name of a device. Note that "make:make.o" tries to create "make.o" on the device "make:". - Replaces @@ by a newline in any command line: if exists make @@\ delete make.bak quiet @@\ rename make make.bak @@\ endif @@\ $(CC) Link Make.o To make works. Note that the @@ must stand alone (ie. "make@@\" is illegal). Also be carefull that there is a space after the "\" (ie, at the beginning of the next line). - Can be made resident to save space and time - Amiga specific wildcards can be used in $(wildcard ...) BUGS: - The line dummy.h : src/*.c tries to make dummy.h from "src/*.c" (ie. no wildcard-expansion takes place). You have to use "$(wildcard src/*.c)" instead. COMPILING FROM SCRATCH ---------------------- To recompile, you need SAS/C 6.51. make itself is not neccessary, there is an smakefile. 1. Copy config.ami to config.h 2. If you use make to compie, copy Makefile.ami to Makefile and glob/Makefile.ami to glob/Makefile. Copy make into the current directory. 3. Run smake/make INSTALLATION Copy make somewhere in your search path (eg. sc:c or sc:bin). If you plan to use recursive makes, install make resident: Resident make Add ------------------------------------------------------------------------------- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/version.c0000644000000000000000000000240112247157307014640 0ustar rootroot/* Record version and build host architecture for GNU make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because make.h was found in $srcdir). */ #include #ifndef MAKE_HOST # define MAKE_HOST "unknown" #endif char *version_string = VERSION; char *make_host = MAKE_HOST; /* Local variables: version-control: never End: */ kbuild-2695/src/kmk/function.c0000644000000000000000000047466112247157307015025 0ustar rootroot/* Builtin function expansion for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "filedef.h" #include "variable.h" #include "dep.h" #include "job.h" #include "commands.h" #include "debug.h" #ifdef _AMIGA #include "amiga.h" #endif #ifdef WINDOWS32 /* bird */ # include "pathstuff.h" #endif #ifdef KMK_HELPERS # include "kbuild.h" #endif #ifdef CONFIG_WITH_PRINTF # include "kmkbuiltin.h" #endif #ifdef CONFIG_WITH_XARGS /* bird */ # ifdef HAVE_LIMITS_H # include # endif #endif #include /* bird */ #if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE) /* bird */ # include typedef big_int math_int; static char *math_int_to_variable_buffer (char *, math_int); static math_int math_int_from_string (const char *str); #endif #ifdef CONFIG_WITH_NANOTS /* bird */ # ifdef WINDOWS32 # include # endif #endif #ifdef __OS2__ # define CONFIG_WITH_OS2_LIBPATH 1 #endif #ifdef CONFIG_WITH_OS2_LIBPATH # define INCL_BASE # define INCL_ERRROS # include # define QHINF_EXEINFO 1 /* NE exeinfo. */ # define QHINF_READRSRCTBL 2 /* Reads from the resource table. */ # define QHINF_READFILE 3 /* Reads from the executable file. */ # define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */ # define QHINF_LIBPATH 5 /* Gets the entire libpath. */ # define QHINF_FIXENTRY 6 /* NE only */ # define QHINF_STE 7 /* NE only */ # define QHINF_MAPSEL 8 /* NE only */ extern APIRET APIENTRY DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction); #endif /* CONFIG_WITH_OS2_LIBPATH */ #ifdef KMK /** Checks if the @a_cch characters (bytes) in @a a_psz equals @a a_szConst. */ # define STR_N_EQUALS(a_psz, a_cch, a_szConst) \ ( (a_cch) == sizeof (a_szConst) - 1 && !strncmp ((a_psz), (a_szConst), sizeof (a_szConst) - 1) ) # ifdef _MSC_VER # include "kmkbuiltin/mscfakes.h" # endif #endif struct function_table_entry { const char *name; unsigned char len; unsigned char minimum_args; unsigned char maximum_args; char expand_args; char *(*func_ptr) (char *output, char **argv, const char *fname); }; static unsigned long function_table_entry_hash_1 (const void *keyv) { const struct function_table_entry *key = keyv; return_STRING_N_HASH_1 (key->name, key->len); } static unsigned long function_table_entry_hash_2 (const void *keyv) { const struct function_table_entry *key = keyv; return_STRING_N_HASH_2 (key->name, key->len); } static int function_table_entry_hash_cmp (const void *xv, const void *yv) { const struct function_table_entry *x = xv; const struct function_table_entry *y = yv; int result = x->len - y->len; if (result) return result; return_STRING_N_COMPARE (x->name, y->name, x->len); } static struct hash_table function_table; #ifdef CONFIG_WITH_MAKE_STATS long make_stats_allocations = 0; long make_stats_reallocations = 0; unsigned long make_stats_allocated = 0; unsigned long make_stats_ht_lookups = 0; unsigned long make_stats_ht_collisions = 0; #endif /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is the length of SUBST and RLEN is the length of REPLACE. If BY_WORD is nonzero, substitutions are done only on matches which are complete whitespace-delimited words. */ char * subst_expand (char *o, const char *text, const char *subst, const char *replace, unsigned int slen, unsigned int rlen, int by_word) { const char *t = text; const char *p; if (slen == 0 && !by_word) { /* The first occurrence of "" in any string is its end. */ o = variable_buffer_output (o, t, strlen (t)); if (rlen > 0) o = variable_buffer_output (o, replace, rlen); return o; } do { if (by_word && slen == 0) /* When matching by words, the empty string should match the end of each word, rather than the end of the whole text. */ p = end_of_token (next_token (t)); else { p = strstr (t, subst); if (p == 0) { /* No more matches. Output everything left on the end. */ o = variable_buffer_output (o, t, strlen (t)); return o; } } /* Output everything before this occurrence of the string to replace. */ if (p > t) o = variable_buffer_output (o, t, p - t); /* If we're substituting only by fully matched words, or only at the ends of words, check that this case qualifies. */ if (by_word && ((p > text && !isblank ((unsigned char)p[-1])) || (p[slen] != '\0' && !isblank ((unsigned char)p[slen])))) /* Struck out. Output the rest of the string that is no longer to be replaced. */ o = variable_buffer_output (o, subst, slen); else if (rlen > 0) /* Output the replacement string. */ o = variable_buffer_output (o, replace, rlen); /* Advance T past the string to be replaced. */ t = p + slen; } while (*t != '\0'); return o; } /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing strings matching PATTERN with REPLACE. If PATTERN_PERCENT is not nil, PATTERN has already been run through find_percent, and PATTERN_PERCENT is the result. If REPLACE_PERCENT is not nil, REPLACE has already been run through find_percent, and REPLACE_PERCENT is the result. Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the character _AFTER_ the %, not to the % itself. */ char * patsubst_expand_pat (char *o, const char *text, const char *pattern, const char *replace, const char *pattern_percent, const char *replace_percent) { unsigned int pattern_prepercent_len, pattern_postpercent_len; unsigned int replace_prepercent_len, replace_postpercent_len; const char *t; unsigned int len; int doneany = 0; /* Record the length of REPLACE before and after the % so we don't have to compute these lengths more than once. */ if (replace_percent) { replace_prepercent_len = replace_percent - replace - 1; replace_postpercent_len = strlen (replace_percent); } else { replace_prepercent_len = strlen (replace); replace_postpercent_len = 0; } if (!pattern_percent) /* With no % in the pattern, this is just a simple substitution. */ return subst_expand (o, text, pattern, replace, strlen (pattern), strlen (replace), 1); /* Record the length of PATTERN before and after the % so we don't have to compute it more than once. */ pattern_prepercent_len = pattern_percent - pattern - 1; pattern_postpercent_len = strlen (pattern_percent); while ((t = find_next_token (&text, &len)) != 0) { int fail = 0; /* Is it big enough to match? */ if (len < pattern_prepercent_len + pattern_postpercent_len) fail = 1; /* Does the prefix match? */ if (!fail && pattern_prepercent_len > 0 && (*t != *pattern || t[pattern_prepercent_len - 1] != pattern_percent[-2] || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1))) fail = 1; /* Does the suffix match? */ if (!fail && pattern_postpercent_len > 0 && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1] || t[len - pattern_postpercent_len] != *pattern_percent || !strneq (&t[len - pattern_postpercent_len], pattern_percent, pattern_postpercent_len - 1))) fail = 1; if (fail) /* It didn't match. Output the string. */ o = variable_buffer_output (o, t, len); else { /* It matched. Output the replacement. */ /* Output the part of the replacement before the %. */ o = variable_buffer_output (o, replace, replace_prepercent_len); if (replace_percent != 0) { /* Output the part of the matched string that matched the % in the pattern. */ o = variable_buffer_output (o, t + pattern_prepercent_len, len - (pattern_prepercent_len + pattern_postpercent_len)); /* Output the part of the replacement after the %. */ o = variable_buffer_output (o, replace_percent, replace_postpercent_len); } } /* Output a space, but not if the replacement is "". */ if (fail || replace_prepercent_len > 0 || (replace_percent != 0 && len + replace_postpercent_len > 0)) { o = variable_buffer_output (o, " ", 1); doneany = 1; } } #ifndef CONFIG_WITH_VALUE_LENGTH if (doneany) /* Kill the last space. */ --o; #else /* Kill the last space and make sure there is a terminator there so that strcache_add_len doesn't have to do a lot of exacty work when expand_deps sends the output its way. */ if (doneany) *--o = '\0'; else o = variable_buffer_output (o, "\0", 1) - 1; #endif return o; } /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing strings matching PATTERN with REPLACE. If PATTERN_PERCENT is not nil, PATTERN has already been run through find_percent, and PATTERN_PERCENT is the result. If REPLACE_PERCENT is not nil, REPLACE has already been run through find_percent, and REPLACE_PERCENT is the result. Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the character _AFTER_ the %, not to the % itself. */ char * patsubst_expand (char *o, const char *text, char *pattern, char *replace) { const char *pattern_percent = find_percent (pattern); const char *replace_percent = find_percent (replace); /* If there's a percent in the pattern or replacement skip it. */ if (replace_percent) ++replace_percent; if (pattern_percent) ++pattern_percent; return patsubst_expand_pat (o, text, pattern, replace, pattern_percent, replace_percent); } #if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH) /* Char map containing the valid function name characters. */ char func_char_map[256]; /* Do the hash table lookup. */ MY_INLINE const struct function_table_entry * lookup_function_in_hash_tab (const char *s, unsigned char len) { struct function_table_entry function_table_entry_key; function_table_entry_key.name = s; function_table_entry_key.len = len; return hash_find_item (&function_table, &function_table_entry_key); } /* Look up a function by name. */ MY_INLINE const struct function_table_entry * lookup_function (const char *s, unsigned int len) { unsigned char ch; # if 0 /* insane loop unroll */ if (len > MAX_FUNCTION_LENGTH) len = MAX_FUNCTION_LENGTH + 1; # define X(idx) \ if (!func_char_map[ch = s[idx]]) \ { \ if (isblank (ch)) \ return lookup_function_in_hash_tab (s, idx); \ return 0; \ } # define Z(idx) \ return lookup_function_in_hash_tab (s, idx); switch (len) { default: assert (0); case 0: return 0; case 1: return 0; case 2: X(0); X(1); Z(2); case 3: X(0); X(1); X(2); Z(3); case 4: X(0); X(1); X(2); X(3); Z(4); case 5: X(0); X(1); X(2); X(3); X(4); Z(5); case 6: X(0); X(1); X(2); X(3); X(4); X(5); Z(6); case 7: X(0); X(1); X(2); X(3); X(4); X(5); X(6); Z(7); case 8: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); Z(8); case 9: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); Z(9); case 10: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); Z(10); case 11: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); Z(11); case 12: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); Z(12); case 13: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); X(12); if ((ch = s[12]) == '\0' || isblank (ch)) return lookup_function_in_hash_tab (s, 12); return 0; } # undef Z # undef X # else /* normal loop */ const char *e = s; if (len > MAX_FUNCTION_LENGTH) len = MAX_FUNCTION_LENGTH; while (func_char_map[ch = *e]) { if (!len--) return 0; e++; } if (ch == '\0' || isblank (ch)) return lookup_function_in_hash_tab (s, e - s); return 0; # endif /* normal loop */ } #else /* original code */ /* Look up a function by name. */ static const struct function_table_entry * lookup_function (const char *s) { const char *e = s; while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-')) e++; if (*e == '\0' || isblank ((unsigned char) *e)) { struct function_table_entry function_table_entry_key; function_table_entry_key.name = s; function_table_entry_key.len = e - s; return hash_find_item (&function_table, &function_table_entry_key); } return 0; } #endif /* original code */ /* Return 1 if PATTERN matches STR, 0 if not. */ int pattern_matches (const char *pattern, const char *percent, const char *str) { unsigned int sfxlen, strlength; if (percent == 0) { unsigned int len = strlen (pattern) + 1; char *new_chars = alloca (len); memcpy (new_chars, pattern, len); percent = find_percent (new_chars); if (percent == 0) return streq (new_chars, str); pattern = new_chars; } sfxlen = strlen (percent + 1); strlength = strlen (str); if (strlength < (percent - pattern) + sfxlen || !strneq (pattern, str, percent - pattern)) return 0; return !strcmp (percent + 1, str + (strlength - sfxlen)); } /* Find the next comma or ENDPAREN (counting nested STARTPAREN and ENDPARENtheses), starting at PTR before END. Return a pointer to next character. If no next argument is found, return NULL. */ static char * find_next_argument (char startparen, char endparen, const char *ptr, const char *end) { int count = 0; for (; ptr < end; ++ptr) if (*ptr == startparen) ++count; else if (*ptr == endparen) { --count; if (count < 0) return NULL; } else if (*ptr == ',' && !count) return (char *)ptr; /* We didn't find anything. */ return NULL; } /* Glob-expand LINE. The returned pointer is only good until the next call to string_glob. */ static char * string_glob (char *line) { static char *result = 0; static unsigned int length; struct nameseq *chain; unsigned int idx; chain = PARSE_FILE_SEQ (&line, struct nameseq, '\0', NULL, /* We do not want parse_file_seq to strip `./'s. That would break examples like: $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS); if (result == 0) { length = 100; result = xmalloc (100); } idx = 0; while (chain != 0) { struct nameseq *next = chain->next; unsigned int len = strlen (chain->name); if (idx + len + 1 > length) { length += (len + 1) * 2; result = xrealloc (result, length); } memcpy (&result[idx], chain->name, len); idx += len; result[idx++] = ' '; /* Because we used PARSEFS_NOCACHE above, we have to free() NAME. */ free ((char *)chain->name); #ifndef CONFIG_WITH_ALLOC_CACHES free (chain); #else alloccache_free (&nameseq_cache, chain); #endif chain = next; } /* Kill the last space and terminate the string. */ if (idx == 0) result[0] = '\0'; else result[idx - 1] = '\0'; return result; } /* Builtin functions */ static char * func_patsubst (char *o, char **argv, const char *funcname UNUSED) { o = patsubst_expand (o, argv[2], argv[0], argv[1]); return o; } static char * func_join (char *o, char **argv, const char *funcname UNUSED) { int doneany = 0; /* Write each word of the first argument directly followed by the corresponding word of the second argument. If the two arguments have a different number of words, the excess words are just output separated by blanks. */ const char *tp; const char *pp; const char *list1_iterator = argv[0]; const char *list2_iterator = argv[1]; do { unsigned int len1, len2; tp = find_next_token (&list1_iterator, &len1); if (tp != 0) o = variable_buffer_output (o, tp, len1); pp = find_next_token (&list2_iterator, &len2); if (pp != 0) o = variable_buffer_output (o, pp, len2); if (tp != 0 || pp != 0) { o = variable_buffer_output (o, " ", 1); doneany = 1; } } while (tp != 0 || pp != 0); if (doneany) /* Kill the last blank. */ --o; return o; } static char * func_origin (char *o, char **argv, const char *funcname UNUSED) { /* Expand the argument. */ struct variable *v = lookup_variable (argv[0], strlen (argv[0])); if (v == 0) o = variable_buffer_output (o, "undefined", 9); else switch (v->origin) { default: case o_invalid: abort (); break; case o_default: o = variable_buffer_output (o, "default", 7); break; case o_env: o = variable_buffer_output (o, "environment", 11); break; case o_file: o = variable_buffer_output (o, "file", 4); break; case o_env_override: o = variable_buffer_output (o, "environment override", 20); break; case o_command: o = variable_buffer_output (o, "command line", 12); break; case o_override: o = variable_buffer_output (o, "override", 8); break; case o_automatic: o = variable_buffer_output (o, "automatic", 9); break; #ifdef CONFIG_WITH_LOCAL_VARIABLES case o_local: o = variable_buffer_output (o, "local", 5); break; #endif } return o; } static char * func_flavor (char *o, char **argv, const char *funcname UNUSED) { struct variable *v = lookup_variable (argv[0], strlen (argv[0])); if (v == 0) o = variable_buffer_output (o, "undefined", 9); else if (v->recursive) o = variable_buffer_output (o, "recursive", 9); else o = variable_buffer_output (o, "simple", 6); return o; } #ifdef CONFIG_WITH_WHERE_FUNCTION static char * func_where (char *o, char **argv, const char *funcname UNUSED) { struct variable *v = lookup_variable (argv[0], strlen (argv[0])); char buf[64]; if (v == 0) o = variable_buffer_output (o, "undefined", 9); else if (v->fileinfo.filenm) { o = variable_buffer_output (o, v->fileinfo.filenm, strlen(v->fileinfo.filenm)); sprintf (buf, ":%lu", v->fileinfo.lineno); o = variable_buffer_output (o, buf, strlen(buf)); } else o = variable_buffer_output (o, "no-location", 11); return o; } #endif /* CONFIG_WITH_WHERE_FUNCTION */ #ifdef VMS # define IS_PATHSEP(c) ((c) == ']') #else # ifdef HAVE_DOS_PATHS # define IS_PATHSEP(c) ((c) == '/' || (c) == '\\') # else # define IS_PATHSEP(c) ((c) == '/') # endif #endif static char * func_notdir_suffix (char *o, char **argv, const char *funcname) { /* Expand the argument. */ const char *list_iterator = argv[0]; const char *p2; int doneany =0; unsigned int len=0; int is_suffix = streq (funcname, "suffix"); int is_notdir = !is_suffix; while ((p2 = find_next_token (&list_iterator, &len)) != 0) { const char *p = p2 + len; while (p >= p2 && (!is_suffix || *p != '.')) { if (IS_PATHSEP (*p)) break; --p; } if (p >= p2) { if (is_notdir) ++p; else if (*p != '.') continue; o = variable_buffer_output (o, p, len - (p - p2)); } #ifdef HAVE_DOS_PATHS /* Handle the case of "d:foo/bar". */ else if (streq (funcname, "notdir") && p2[0] && p2[1] == ':') { p = p2 + 2; o = variable_buffer_output (o, p, len - (p - p2)); } #endif else if (is_notdir) o = variable_buffer_output (o, p2, len); if (is_notdir || p >= p2) { o = variable_buffer_output (o, " ", 1); doneany = 1; } } if (doneany) /* Kill last space. */ --o; return o; } static char * func_basename_dir (char *o, char **argv, const char *funcname) { /* Expand the argument. */ const char *p3 = argv[0]; const char *p2; int doneany=0; unsigned int len=0; int is_basename= streq (funcname, "basename"); int is_dir= !is_basename; while ((p2 = find_next_token (&p3, &len)) != 0) { const char *p = p2 + len; while (p >= p2 && (!is_basename || *p != '.')) { if (IS_PATHSEP (*p)) break; --p; } if (p >= p2 && (is_dir)) o = variable_buffer_output (o, p2, ++p - p2); else if (p >= p2 && (*p == '.')) o = variable_buffer_output (o, p2, p - p2); #ifdef HAVE_DOS_PATHS /* Handle the "d:foobar" case */ else if (p2[0] && p2[1] == ':' && is_dir) o = variable_buffer_output (o, p2, 2); #endif else if (is_dir) #ifdef VMS o = variable_buffer_output (o, "[]", 2); #else #ifndef _AMIGA o = variable_buffer_output (o, "./", 2); #else ; /* Just a nop... */ #endif /* AMIGA */ #endif /* !VMS */ else /* The entire name is the basename. */ o = variable_buffer_output (o, p2, len); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill last space. */ --o; return o; } #ifdef CONFIG_WITH_ROOT_FUNC /* $(root path) This is mainly for dealing with drive letters and UNC paths on Windows and OS/2. */ static char * func_root (char *o, char **argv, const char *funcname UNUSED) { const char *paths = argv[0] ? argv[0] : ""; int doneany = 0; const char *p; unsigned int len; while ((p = find_next_token (&paths, &len)) != 0) { const char *p2 = p; #ifdef HAVE_DOS_PATHS if ( len >= 2 && p2[1] == ':' && ( (p2[0] >= 'A' && p2[0] <= 'Z') || (p2[0] >= 'a' && p2[0] <= 'z'))) { p2 += 2; len -= 2; } else if (len >= 4 && IS_PATHSEP(p2[0]) && IS_PATHSEP(p2[1]) && !IS_PATHSEP(p2[2])) { /* Min recognized UNC: "//./" - find the next slash Typical root: "//srv/shr/" */ /* XXX: Check if //./ needs special handling. */ p2 += 3; len -= 3; while (len > 0 && !IS_PATHSEP(*p2)) p2++, len--; if (len && IS_PATHSEP(p2[0]) && (len == 1 || !IS_PATHSEP(p2[1]))) { p2++; len--; if (len) /* optional share */ while (len > 0 && !IS_PATHSEP(*p2)) p2++, len--; } else p2 = NULL; } else if (IS_PATHSEP(*p2)) { p2++; len--; } else p2 = NULL; #elif defined (VMS) || defined (AMGIA) /* XXX: VMS and AMGIA */ fatal (NILF, _("$(root ) is not implemented on this platform")); #else if (IS_PATHSEP(*p2)) { p2++; len--; } else p2 = NULL; #endif if (p2 != NULL) { /* Include all subsequent path separators. */ while (len > 0 && IS_PATHSEP(*p2)) p2++, len--; o = variable_buffer_output (o, p, p2 - p); o = variable_buffer_output (o, " ", 1); doneany = 1; } } if (doneany) /* Kill last space. */ --o; return o; } /* $(notroot path) This is mainly for dealing with drive letters and UNC paths on Windows and OS/2. */ static char * func_notroot (char *o, char **argv, const char *funcname UNUSED) { const char *paths = argv[0] ? argv[0] : ""; int doneany = 0; const char *p; unsigned int len; while ((p = find_next_token (&paths, &len)) != 0) { const char *p2 = p; #ifdef HAVE_DOS_PATHS if ( len >= 2 && p2[1] == ':' && ( (p2[0] >= 'A' && p2[0] <= 'Z') || (p2[0] >= 'a' && p2[0] <= 'z'))) { p2 += 2; len -= 2; } else if (len >= 4 && IS_PATHSEP(p2[0]) && IS_PATHSEP(p2[1]) && !IS_PATHSEP(p2[2])) { /* Min recognized UNC: "//./" - find the next slash Typical root: "//srv/shr/" */ /* XXX: Check if //./ needs special handling. */ unsigned int saved_len = len; p2 += 3; len -= 3; while (len > 0 && !IS_PATHSEP(*p2)) p2++, len--; if (len && IS_PATHSEP(p2[0]) && (len == 1 || !IS_PATHSEP(p2[1]))) { p2++; len--; if (len) /* optional share */ while (len > 0 && !IS_PATHSEP(*p2)) p2++, len--; } else { p2 = p; len = saved_len; } } #elif defined (VMS) || defined (AMGIA) /* XXX: VMS and AMGIA */ fatal (NILF, _("$(root ) is not implemented on this platform")); #endif /* Exclude all subsequent / leading path separators. */ while (len > 0 && IS_PATHSEP(*p2)) p2++, len--; if (len > 0) o = variable_buffer_output (o, p2, len); else o = variable_buffer_output (o, ".", 1); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill last space. */ --o; return o; } #endif /* CONFIG_WITH_ROOT_FUNC */ static char * func_addsuffix_addprefix (char *o, char **argv, const char *funcname) { int fixlen = strlen (argv[0]); const char *list_iterator = argv[1]; int is_addprefix = streq (funcname, "addprefix"); int is_addsuffix = !is_addprefix; int doneany = 0; const char *p; unsigned int len; while ((p = find_next_token (&list_iterator, &len)) != 0) { if (is_addprefix) o = variable_buffer_output (o, argv[0], fixlen); o = variable_buffer_output (o, p, len); if (is_addsuffix) o = variable_buffer_output (o, argv[0], fixlen); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill last space. */ --o; return o; } static char * func_subst (char *o, char **argv, const char *funcname UNUSED) { o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]), strlen (argv[1]), 0); return o; } #ifdef CONFIG_WITH_DEFINED_FUNCTIONS /* Used by func_firstdefined and func_lastdefined to parse the optional last argument. Returns 0 if the variable name is to be returned and 1 if it's the variable value value. */ static int parse_value_name_argument (const char *arg1, const char *funcname) { const char *end; int rc; if (arg1 == NULL) return 0; end = strchr (arg1, '\0'); strip_whitespace (&arg1, &end); if (!strncmp (arg1, "name", end - arg1)) rc = 0; else if (!strncmp (arg1, "value", end - arg1)) rc = 1; else #if 1 /* FIXME: later */ fatal (*expanding_var, _("second argument to `%s' function must be `name' or `value', not `%s'"), funcname, arg1); #else { /* check the expanded form */ char *exp = expand_argument (arg1, strchr (arg1, '\0')); arg1 = exp; end = strchr (arg1, '\0'); strip_whitespace (&arg1, &end); if (!strncmp (arg1, "name", end - arg1)) rc = 0; else if (!strncmp (arg1, "value", end - arg1)) rc = 1; else fatal (*expanding_var, _("second argument to `%s' function must be `name' or `value', not `%s'"), funcname, exp); free (exp); } #endif return rc; } /* Given a list of variable names (ARGV[0]), returned the first variable which is defined (i.e. value is not empty). ARGV[1] indicates whether to return the variable name or its value. */ static char * func_firstdefined (char *o, char **argv, const char *funcname) { unsigned int i; const char *words = argv[0]; /* Use a temp variable for find_next_token */ const char *p; int ret_value = parse_value_name_argument (argv[1], funcname); /* FIXME: Optimize by not expanding the arguments, but instead expand them one by one here. This will require a find_next_token variant which takes `$(' and `)' into account. */ while ((p = find_next_token (&words, &i)) != NULL) { struct variable *v = lookup_variable (p, i); if (v && v->value_length) { if (ret_value) variable_expand_string_2 (o, v->value, v->value_length, &o); else o = variable_buffer_output (o, p, i); break; } } return o; } /* Given a list of variable names (ARGV[0]), returned the last variable which is defined (i.e. value is not empty). ARGV[1] indicates whether to return the variable name or its value. */ static char * func_lastdefined (char *o, char **argv, const char *funcname) { struct variable *last_v = NULL; unsigned int i; const char *words = argv[0]; /* Use a temp variable for find_next_token */ const char *p; int ret_value = parse_value_name_argument (argv[1], funcname); /* FIXME: Optimize this. Walk from the end on unexpanded arguments. */ while ((p = find_next_token (&words, &i)) != NULL) { struct variable *v = lookup_variable (p, i); if (v && v->value_length) { last_v = v; break; } } if (last_v != NULL) { if (ret_value) variable_expand_string_2 (o, last_v->value, last_v->value_length, &o); else o = variable_buffer_output (o, last_v->name, last_v->length); } return o; } #endif /* CONFIG_WITH_DEFINED_FUNCTIONS */ static char * func_firstword (char *o, char **argv, const char *funcname UNUSED) { unsigned int i; const char *words = argv[0]; /* Use a temp variable for find_next_token */ const char *p = find_next_token (&words, &i); if (p != 0) o = variable_buffer_output (o, p, i); return o; } static char * func_lastword (char *o, char **argv, const char *funcname UNUSED) { unsigned int i; const char *words = argv[0]; /* Use a temp variable for find_next_token */ const char *p = NULL; const char *t; while ((t = find_next_token (&words, &i))) p = t; if (p != 0) o = variable_buffer_output (o, p, i); return o; } static char * func_words (char *o, char **argv, const char *funcname UNUSED) { int i = 0; const char *word_iterator = argv[0]; char buf[20]; while (find_next_token (&word_iterator, (unsigned int *) 0) != 0) ++i; sprintf (buf, "%d", i); o = variable_buffer_output (o, buf, strlen (buf)); return o; } /* Set begpp to point to the first non-whitespace character of the string, * and endpp to point to the last non-whitespace character of the string. * If the string is empty or contains nothing but whitespace, endpp will be * begpp-1. */ char * strip_whitespace (const char **begpp, const char **endpp) { while (*begpp <= *endpp && isspace ((unsigned char)**begpp)) (*begpp) ++; while (*endpp >= *begpp && isspace ((unsigned char)**endpp)) (*endpp) --; return (char *)*begpp; } static void check_numeric (const char *s, const char *msg) { const char *end = s + strlen (s) - 1; const char *beg = s; strip_whitespace (&s, &end); for (; s <= end; ++s) if (!ISDIGIT (*s)) /* ISDIGIT only evals its arg once: see make.h. */ break; if (s <= end || end - beg < 0) fatal (*expanding_var, "%s: '%s'", msg, beg); } static char * func_word (char *o, char **argv, const char *funcname UNUSED) { const char *end_p; const char *p; int i; /* Check the first argument. */ check_numeric (argv[0], _("non-numeric first argument to `word' function")); i = atoi (argv[0]); if (i == 0) fatal (*expanding_var, _("first argument to `word' function must be greater than 0")); end_p = argv[1]; while ((p = find_next_token (&end_p, 0)) != 0) if (--i == 0) break; if (i == 0) o = variable_buffer_output (o, p, end_p - p); return o; } static char * func_wordlist (char *o, char **argv, const char *funcname UNUSED) { int start, count; /* Check the arguments. */ check_numeric (argv[0], _("non-numeric first argument to `wordlist' function")); check_numeric (argv[1], _("non-numeric second argument to `wordlist' function")); start = atoi (argv[0]); if (start < 1) fatal (*expanding_var, "invalid first argument to `wordlist' function: `%d'", start); count = atoi (argv[1]) - start + 1; if (count > 0) { const char *p; const char *end_p = argv[2]; /* Find the beginning of the "start"th word. */ while (((p = find_next_token (&end_p, 0)) != 0) && --start) ; if (p) { /* Find the end of the "count"th word from start. */ while (--count && (find_next_token (&end_p, 0) != 0)) ; /* Return the stuff in the middle. */ o = variable_buffer_output (o, p, end_p - p); } } return o; } static char * func_findstring (char *o, char **argv, const char *funcname UNUSED) { /* Find the first occurrence of the first string in the second. */ if (strstr (argv[1], argv[0]) != 0) o = variable_buffer_output (o, argv[0], strlen (argv[0])); return o; } static char * func_foreach (char *o, char **argv, const char *funcname UNUSED) { /* expand only the first two. */ char *varname = expand_argument (argv[0], NULL); char *list = expand_argument (argv[1], NULL); const char *body = argv[2]; #ifdef CONFIG_WITH_VALUE_LENGTH long body_len = strlen (body); #endif int doneany = 0; const char *list_iterator = list; const char *p; unsigned int len; struct variable *var; push_new_variable_scope (); var = define_variable (varname, strlen (varname), "", o_automatic, 0); /* loop through LIST, put the value in VAR and expand BODY */ while ((p = find_next_token (&list_iterator, &len)) != 0) { #ifndef CONFIG_WITH_VALUE_LENGTH char *result = 0; free (var->value); var->value = xstrndup (p, len); result = allocated_variable_expand (body); o = variable_buffer_output (o, result, strlen (result)); o = variable_buffer_output (o, " ", 1); doneany = 1; free (result); #else /* CONFIG_WITH_VALUE_LENGTH */ if (len >= var->value_alloc_len) { # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (var->rdonly_val) var->rdonly_val = 0; else # endif free (var->value); var->value_alloc_len = VAR_ALIGN_VALUE_ALLOC (len + 1); var->value = xmalloc (var->value_alloc_len); } memcpy (var->value, p, len); var->value[len] = '\0'; var->value_length = len; variable_expand_string_2 (o, body, body_len, &o); o = variable_buffer_output (o, " ", 1); doneany = 1; #endif /* CONFIG_WITH_VALUE_LENGTH */ } if (doneany) /* Kill the last space. */ --o; pop_variable_scope (); free (varname); free (list); return o; } #ifdef CONFIG_WITH_LOOP_FUNCTIONS /* Helper for func_for that evaluates the INIT and NEXT parts. */ static void helper_eval (char *text, size_t text_len) { unsigned int buf_len; char *buf; install_variable_buffer (&buf, &buf_len); eval_buffer (text, text + text_len); restore_variable_buffer (buf, buf_len); } /* $(for init,condition,next,body) */ static char * func_for (char *o, char **argv, const char *funcname UNUSED) { char *init = argv[0]; const char *cond = argv[1]; const char *next = argv[2]; size_t next_len = strlen (next); char *next_buf = xmalloc (next_len + 1); const char *body = argv[3]; size_t body_len = strlen (body); unsigned int doneany = 0; push_new_variable_scope (); /* Evaluate INIT. */ helper_eval (init, strlen (init)); /* Loop till COND is false. */ while (expr_eval_if_conditionals (cond, NULL) == 0 /* true */) { /* Expand BODY. */ if (!doneany) doneany = 1; else o = variable_buffer_output (o, " ", 1); variable_expand_string_2 (o, body, body_len, &o); /* Evaluate NEXT. */ memcpy (next_buf, next, next_len + 1); helper_eval (next_buf, next_len); } pop_variable_scope (); free (next_buf); return o; } /* $(while condition,body) */ static char * func_while (char *o, char **argv, const char *funcname UNUSED) { const char *cond = argv[0]; const char *body = argv[1]; size_t body_len = strlen (body); unsigned int doneany = 0; push_new_variable_scope (); while (expr_eval_if_conditionals (cond, NULL) == 0 /* true */) { if (!doneany) doneany = 1; else o = variable_buffer_output (o, " ", 1); variable_expand_string_2 (o, body, body_len, &o); } pop_variable_scope (); return o; } #endif /* CONFIG_WITH_LOOP_FUNCTIONS */ struct a_word { struct a_word *next; struct a_word *chain; char *str; int length; int matched; }; static unsigned long a_word_hash_1 (const void *key) { return_STRING_HASH_1 (((struct a_word const *) key)->str); } static unsigned long a_word_hash_2 (const void *key) { return_STRING_HASH_2 (((struct a_word const *) key)->str); } static int a_word_hash_cmp (const void *x, const void *y) { int result = ((struct a_word const *) x)->length - ((struct a_word const *) y)->length; if (result) return result; return_STRING_COMPARE (((struct a_word const *) x)->str, ((struct a_word const *) y)->str); } struct a_pattern { struct a_pattern *next; char *str; char *percent; int length; int save_c; }; static char * func_filter_filterout (char *o, char **argv, const char *funcname) { struct a_word *wordhead; struct a_word **wordtail; struct a_word *wp; struct a_pattern *pathead; struct a_pattern **pattail; struct a_pattern *pp; struct hash_table a_word_table; int is_filter = streq (funcname, "filter"); const char *pat_iterator = argv[0]; const char *word_iterator = argv[1]; int literals = 0; int words = 0; int hashing = 0; char *p; unsigned int len; /* Chop ARGV[0] up into patterns to match against the words. */ pattail = &pathead; while ((p = find_next_token (&pat_iterator, &len)) != 0) { struct a_pattern *pat = alloca (sizeof (struct a_pattern)); *pattail = pat; pattail = &pat->next; if (*pat_iterator != '\0') ++pat_iterator; pat->str = p; pat->length = len; pat->save_c = p[len]; p[len] = '\0'; pat->percent = find_percent (p); if (pat->percent == 0) literals++; } *pattail = 0; /* Chop ARGV[1] up into words to match against the patterns. */ wordtail = &wordhead; while ((p = find_next_token (&word_iterator, &len)) != 0) { struct a_word *word = alloca (sizeof (struct a_word)); *wordtail = word; wordtail = &word->next; if (*word_iterator != '\0') ++word_iterator; p[len] = '\0'; word->str = p; word->length = len; word->matched = 0; word->chain = 0; words++; } *wordtail = 0; /* Only use a hash table if arg list lengths justifies the cost. */ hashing = (literals >= 2 && (literals * words) >= 10); if (hashing) { hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2, a_word_hash_cmp); for (wp = wordhead; wp != 0; wp = wp->next) { struct a_word *owp = hash_insert (&a_word_table, wp); if (owp) wp->chain = owp; } } if (words) { int doneany = 0; /* Run each pattern through the words, killing words. */ for (pp = pathead; pp != 0; pp = pp->next) { if (pp->percent) for (wp = wordhead; wp != 0; wp = wp->next) wp->matched |= pattern_matches (pp->str, pp->percent, wp->str); else if (hashing) { struct a_word a_word_key; a_word_key.str = pp->str; a_word_key.length = pp->length; wp = hash_find_item (&a_word_table, &a_word_key); while (wp) { wp->matched |= 1; wp = wp->chain; } } else for (wp = wordhead; wp != 0; wp = wp->next) wp->matched |= (wp->length == pp->length && strneq (pp->str, wp->str, wp->length)); } /* Output the words that matched (or didn't, for filter-out). */ for (wp = wordhead; wp != 0; wp = wp->next) if (is_filter ? wp->matched : !wp->matched) { o = variable_buffer_output (o, wp->str, strlen (wp->str)); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill the last space. */ --o; } for (pp = pathead; pp != 0; pp = pp->next) pp->str[pp->length] = pp->save_c; if (hashing) hash_free (&a_word_table, 0); return o; } static char * func_strip (char *o, char **argv, const char *funcname UNUSED) { const char *p = argv[0]; int doneany = 0; while (*p != '\0') { int i=0; const char *word_start; while (isspace ((unsigned char)*p)) ++p; word_start = p; for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i) {} if (!i) break; o = variable_buffer_output (o, word_start, i); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill the last space. */ --o; return o; } /* Print a warning or fatal message. */ static char * func_error (char *o, char **argv, const char *funcname) { char **argvp; char *msg, *p; int len; /* The arguments will be broken on commas. Rather than create yet another special case where function arguments aren't broken up, just create a format string that puts them back together. */ for (len=0, argvp=argv; *argvp != 0; ++argvp) len += strlen (*argvp) + 2; p = msg = alloca (len + 1); for (argvp=argv; argvp[1] != 0; ++argvp) { strcpy (p, *argvp); p += strlen (*argvp); *(p++) = ','; *(p++) = ' '; } strcpy (p, *argvp); switch (*funcname) { case 'e': fatal (reading_file, "%s", msg); case 'w': error (reading_file, "%s", msg); break; case 'i': printf ("%s\n", msg); fflush(stdout); break; default: fatal (*expanding_var, "Internal error: func_error: '%s'", funcname); } /* The warning function expands to the empty string. */ return o; } /* chop argv[0] into words, and sort them. */ static char * func_sort (char *o, char **argv, const char *funcname UNUSED) { const char *t; char **words; int wordi; char *p; unsigned int len; int i; /* Find the maximum number of words we'll have. */ t = argv[0]; wordi = 1; while (*t != '\0') { char c = *(t++); if (! isspace ((unsigned char)c)) continue; ++wordi; while (isspace ((unsigned char)*t)) ++t; } words = xmalloc (wordi * sizeof (char *)); /* Now assign pointers to each string in the array. */ t = argv[0]; wordi = 0; while ((p = find_next_token (&t, &len)) != 0) { ++t; p[len] = '\0'; words[wordi++] = p; } if (wordi) { /* Now sort the list of words. */ qsort (words, wordi, sizeof (char *), alpha_compare); /* Now write the sorted list, uniquified. */ #ifdef CONFIG_WITH_RSORT if (strcmp (funcname, "rsort")) { /* sort */ #endif for (i = 0; i < wordi; ++i) { len = strlen (words[i]); if (i == wordi - 1 || strlen (words[i + 1]) != len || strcmp (words[i], words[i + 1])) { o = variable_buffer_output (o, words[i], len); o = variable_buffer_output (o, " ", 1); } } #ifdef CONFIG_WITH_RSORT } else { /* rsort - reverse the result */ i = wordi; while (i-- > 0) { len = strlen (words[i]); if (i == 0 || strlen (words[i - 1]) != len || strcmp (words[i], words[i - 1])) { o = variable_buffer_output (o, words[i], len); o = variable_buffer_output (o, " ", 1); } } } #endif /* Kill the last space. */ --o; } free (words); return o; } /* $(if condition,true-part[,false-part]) CONDITION is false iff it evaluates to an empty string. White space before and after condition are stripped before evaluation. If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is evaluated (if it exists). Because only one of the two PARTs is evaluated, you can use $(if ...) to create side-effects (with $(shell ...), for example). */ static char * func_if (char *o, char **argv, const char *funcname UNUSED) { const char *begp = argv[0]; const char *endp = begp + strlen (argv[0]) - 1; int result = 0; /* Find the result of the condition: if we have a value, and it's not empty, the condition is true. If we don't have a value, or it's the empty string, then it's false. */ strip_whitespace (&begp, &endp); if (begp <= endp) { char *expansion = expand_argument (begp, endp+1); result = strlen (expansion); free (expansion); } /* If the result is true (1) we want to eval the first argument, and if it's false (0) we want to eval the second. If the argument doesn't exist we do nothing, otherwise expand it and add to the buffer. */ argv += 1 + !result; if (*argv) { char *expansion = expand_argument (*argv, NULL); o = variable_buffer_output (o, expansion, strlen (expansion)); free (expansion); } return o; } /* $(or condition1[,condition2[,condition3[...]]]) A CONDITION is false iff it evaluates to an empty string. White space before and after CONDITION are stripped before evaluation. CONDITION1 is evaluated. If it's true, then this is the result of expansion. If it's false, CONDITION2 is evaluated, and so on. If none of the conditions are true, the expansion is the empty string. Once a CONDITION is true no further conditions are evaluated (short-circuiting). */ static char * func_or (char *o, char **argv, const char *funcname UNUSED) { for ( ; *argv ; ++argv) { const char *begp = *argv; const char *endp = begp + strlen (*argv) - 1; char *expansion; int result = 0; /* Find the result of the condition: if it's false keep going. */ strip_whitespace (&begp, &endp); if (begp > endp) continue; expansion = expand_argument (begp, endp+1); result = strlen (expansion); /* If the result is false keep going. */ if (!result) { free (expansion); continue; } /* It's true! Keep this result and return. */ o = variable_buffer_output (o, expansion, result); free (expansion); break; } return o; } /* $(and condition1[,condition2[,condition3[...]]]) A CONDITION is false iff it evaluates to an empty string. White space before and after CONDITION are stripped before evaluation. CONDITION1 is evaluated. If it's false, then this is the result of expansion. If it's true, CONDITION2 is evaluated, and so on. If all of the conditions are true, the expansion is the result of the last condition. Once a CONDITION is false no further conditions are evaluated (short-circuiting). */ static char * func_and (char *o, char **argv, const char *funcname UNUSED) { char *expansion; int result; while (1) { const char *begp = *argv; const char *endp = begp + strlen (*argv) - 1; /* An empty condition is always false. */ strip_whitespace (&begp, &endp); if (begp > endp) return o; expansion = expand_argument (begp, endp+1); result = strlen (expansion); /* If the result is false, stop here: we're done. */ if (!result) break; /* Otherwise the result is true. If this is the last one, keep this result and quit. Otherwise go on to the next one! */ if (*(++argv)) free (expansion); else { o = variable_buffer_output (o, expansion, result); break; } } free (expansion); return o; } static char * func_wildcard (char *o, char **argv, const char *funcname UNUSED) { #ifdef _AMIGA o = wildcard_expansion (argv[0], o); #else char *p = string_glob (argv[0]); o = variable_buffer_output (o, p, strlen (p)); #endif return o; } /* $(eval ) Always resolves to the empty string. Treat the arguments as a segment of makefile, and parse them. */ static char * func_eval (char *o, char **argv, const char *funcname UNUSED) { char *buf; unsigned int len; /* Eval the buffer. Pop the current variable buffer setting so that the eval'd code can use its own without conflicting. */ install_variable_buffer (&buf, &len); #ifndef CONFIG_WITH_VALUE_LENGTH eval_buffer (argv[0]); #else eval_buffer (argv[0], strchr (argv[0], '\0')); #endif restore_variable_buffer (buf, len); return o; } #ifdef CONFIG_WITH_EVALPLUS /* Same as func_eval except that we push and pop the local variable context before evaluating the buffer. */ static char * func_evalctx (char *o, char **argv, const char *funcname UNUSED) { char *buf; unsigned int len; /* Eval the buffer. Pop the current variable buffer setting so that the eval'd code can use its own without conflicting. */ install_variable_buffer (&buf, &len); push_new_variable_scope (); eval_buffer (argv[0], strchr (argv[0], '\0')); pop_variable_scope (); restore_variable_buffer (buf, len); return o; } /* A mix of func_eval and func_value, saves memory for the expansion. This implements both evalval and evalvalctx, the latter has its own variable context just like evalctx. */ static char * func_evalval (char *o, char **argv, const char *funcname) { /* Look up the variable. */ struct variable *v = lookup_variable (argv[0], strlen (argv[0])); if (v) { char *buf; unsigned int len; int var_ctx; size_t off; const struct floc *reading_file_saved = reading_file; /* Make a copy of the value to the variable buffer since eval_buffer will make changes to its input. */ off = o - variable_buffer; variable_buffer_output (o, v->value, v->value_length + 1); o = variable_buffer + off; /* Eval the value. Pop the current variable buffer setting so that the eval'd code can use its own without conflicting. (really necessary?) */ install_variable_buffer (&buf, &len); var_ctx = !strcmp (funcname, "evalvalctx"); if (var_ctx) push_new_variable_scope (); if (v->fileinfo.filenm) reading_file = &v->fileinfo; assert (!o[v->value_length]); eval_buffer (o, o + v->value_length); reading_file = reading_file_saved; if (var_ctx) pop_variable_scope (); restore_variable_buffer (buf, len); } return o; } /* Optimizes the content of one or more variables to save time in the eval functions. This function will collapse line continuations and remove comments. */ static char * func_eval_optimize_variable (char *o, char **argv, const char *funcname) { unsigned int i; for (i = 0; argv[i]; i++) { struct variable *v = lookup_variable (argv[i], strlen (argv[i])); # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE if (v && !v->origin != o_automatic && !v->rdonly_val) # else if (v && !v->origin != o_automatic) # endif { char *eos, *src; eos = collapse_continuations (v->value, v->value_length); v->value_length = eos - v->value; /* remove comments */ src = memchr (v->value, '#', v->value_length); if (src) { unsigned char ch = '\0'; char *dst = src; do { /* drop blanks preceeding the comment */ while (dst > v->value) { ch = (unsigned char)dst[-1]; if (!isblank (ch)) break; dst--; } /* advance SRC to eol / eos. */ src = memchr (src, '\n', eos - src); if (!src) break; /* drop a preceeding newline if possible (full line comment) */ if (dst > v->value && dst[-1] == '\n') dst--; /* copy till next comment or eol. */ while (src < eos) { ch = *src++; if (ch == '#') break; *dst++ = ch; } } while (ch == '#' && src < eos); *dst = '\0'; v->value_length = dst - v->value; } } else if (v) error (NILF, _("$(%s ): variable `%s' is of the wrong type\n"), funcname, v->name); } return o; } #endif /* CONFIG_WITH_EVALPLUS */ static char * func_value (char *o, char **argv, const char *funcname UNUSED) { /* Look up the variable. */ struct variable *v = lookup_variable (argv[0], strlen (argv[0])); /* Copy its value into the output buffer without expanding it. */ if (v) #ifdef CONFIG_WITH_VALUE_LENGTH { assert (v->value_length == strlen (v->value)); o = variable_buffer_output (o, v->value, v->value_length); } #else o = variable_buffer_output (o, v->value, strlen(v->value)); #endif return o; } /* \r is replaced on UNIX as well. Is this desirable? */ static void fold_newlines (char *buffer, unsigned int *length) { char *dst = buffer; char *src = buffer; char *last_nonnl = buffer -1; src[*length] = 0; for (; *src != '\0'; ++src) { if (src[0] == '\r' && src[1] == '\n') continue; if (*src == '\n') { *dst++ = ' '; } else { last_nonnl = dst; *dst++ = *src; } } *(++last_nonnl) = '\0'; *length = last_nonnl - buffer; } int shell_function_pid = 0, shell_function_completed; #ifdef WINDOWS32 /*untested*/ #include #include #include "sub_proc.h" void windows32_openpipe (int *pipedes, pid_t *pid_p, char **command_argv, char **envp) { SECURITY_ATTRIBUTES saAttr; HANDLE hIn; HANDLE hErr; HANDLE hChildOutRd; HANDLE hChildOutWr; HANDLE hProcess; saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (DuplicateHandle (GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), GetCurrentProcess(), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fatal (NILF, _("windows32_openpipe(): DuplicateHandle(In) failed (e=%ld)\n"), GetLastError()); } if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { fatal (NILF, _("windows32_open_pipe(): DuplicateHandle(Err) failed (e=%ld)\n"), GetLastError()); } if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0)) fatal (NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError()); hProcess = process_init_fd(hIn, hChildOutWr, hErr); if (!hProcess) fatal (NILF, _("windows32_openpipe(): process_init_fd() failed\n")); /* make sure that CreateProcess() has Path it needs */ sync_Path_environment(); /* `sync_Path_environment' may realloc `environ', so take note of the new value. */ envp = environ; if (!process_begin(hProcess, command_argv, envp, command_argv[0], NULL)) { /* register process for wait */ process_register(hProcess); /* set the pid for returning to caller */ *pid_p = (pid_t) hProcess; /* set up to read data from child */ pipedes[0] = _open_osfhandle((intptr_t) hChildOutRd, O_RDONLY); /* this will be closed almost right away */ pipedes[1] = _open_osfhandle((intptr_t) hChildOutWr, O_APPEND); } else { /* reap/cleanup the failed process */ process_cleanup(hProcess); /* close handles which were duplicated, they weren't used */ CloseHandle(hIn); CloseHandle(hErr); /* close pipe handles, they won't be used */ CloseHandle(hChildOutRd); CloseHandle(hChildOutWr); /* set status for return */ pipedes[0] = pipedes[1] = -1; *pid_p = (pid_t)-1; } } #endif #ifdef __MSDOS__ FILE * msdos_openpipe (int* pipedes, int *pidp, char *text) { FILE *fpipe=0; /* MSDOS can't fork, but it has `popen'. */ struct variable *sh = lookup_variable ("SHELL", 5); int e; extern int dos_command_running, dos_status; /* Make sure not to bother processing an empty line. */ while (isblank ((unsigned char)*text)) ++text; if (*text == '\0') return 0; if (sh) { char buf[PATH_MAX + 7]; /* This makes sure $SHELL value is used by $(shell), even though the target environment is not passed to it. */ sprintf (buf, "SHELL=%s", sh->value); putenv (buf); } e = errno; errno = 0; dos_command_running = 1; dos_status = 0; /* If dos_status becomes non-zero, it means the child process was interrupted by a signal, like SIGINT or SIGQUIT. See fatal_error_signal in commands.c. */ fpipe = popen (text, "rt"); dos_command_running = 0; if (!fpipe || dos_status) { pipedes[0] = -1; *pidp = -1; if (dos_status) errno = EINTR; else if (errno == 0) errno = ENOMEM; shell_function_completed = -1; } else { pipedes[0] = fileno (fpipe); *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */ errno = e; shell_function_completed = 1; } return fpipe; } #endif /* Do shell spawning, with the naughty bits for different OSes. */ #ifdef VMS /* VMS can't do $(shell ...) */ #define func_shell 0 #else #ifndef _AMIGA static char * func_shell (char * volatile o, char **argv, const char *funcname UNUSED) { char *batch_filename = NULL; #ifdef __MSDOS__ FILE *fpipe; #endif char **command_argv; const char * volatile error_prefix; /* bird: this volatile and the 'o' one, is for shutting up gcc warnings */ char **envp; int pipedes[2]; pid_t pid; #ifndef __MSDOS__ /* Construct the argument list. */ command_argv = construct_command_argv (argv[0], NULL, NULL, 0, &batch_filename); if (command_argv == 0) return o; #endif /* Using a target environment for `shell' loses in cases like: export var = $(shell echo foobie) because target_environment hits a loop trying to expand $(var) to put it in the environment. This is even more confusing when var was not explicitly exported, but just appeared in the calling environment. See Savannah bug #10593. envp = target_environment (NILF); */ envp = environ; /* For error messages. */ if (reading_file && reading_file->filenm) { char *p = alloca (strlen (reading_file->filenm)+11+4); sprintf (p, "%s:%lu: ", reading_file->filenm, reading_file->lineno); error_prefix = p; } else error_prefix = ""; #if defined(__MSDOS__) fpipe = msdos_openpipe (pipedes, &pid, argv[0]); if (pipedes[0] < 0) { perror_with_name (error_prefix, "pipe"); return o; } #elif defined(WINDOWS32) windows32_openpipe (pipedes, &pid, command_argv, envp); if (pipedes[0] < 0) { /* open of the pipe failed, mark as failed execution */ shell_function_completed = -1; return o; } else #else if (pipe (pipedes) < 0) { perror_with_name (error_prefix, "pipe"); return o; } # ifdef __EMX__ /* close some handles that are unnecessary for the child process */ CLOSE_ON_EXEC(pipedes[1]); CLOSE_ON_EXEC(pipedes[0]); /* Never use fork()/exec() here! Use spawn() instead in exec_command() */ pid = child_execute_job (0, pipedes[1], command_argv, envp); if (pid < 0) perror_with_name (error_prefix, "spawn"); # else /* ! __EMX__ */ pid = vfork (); if (pid < 0) perror_with_name (error_prefix, "fork"); else if (pid == 0) child_execute_job (0, pipedes[1], command_argv, envp); else # endif #endif { /* We are the parent. */ char *buffer; unsigned int maxlen, i; int cc; /* Record the PID for reap_children. */ shell_function_pid = pid; #ifndef __MSDOS__ shell_function_completed = 0; /* Free the storage only the child needed. */ free (command_argv[0]); free (command_argv); /* Close the write side of the pipe. We test for -1, since pipedes[1] is -1 on MS-Windows, and some versions of MS libraries barf when `close' is called with -1. */ if (pipedes[1] >= 0) close (pipedes[1]); #endif /* Set up and read from the pipe. */ maxlen = 200; buffer = xmalloc (maxlen + 1); /* Read from the pipe until it gets EOF. */ for (i = 0; ; i += cc) { if (i == maxlen) { maxlen += 512; buffer = xrealloc (buffer, maxlen + 1); } EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i)); if (cc <= 0) break; } buffer[i] = '\0'; /* Close the read side of the pipe. */ #ifdef __MSDOS__ if (fpipe) (void) pclose (fpipe); #else # ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */ if (pipedes[0] != -1) # endif (void) close (pipedes[0]); #endif /* Loop until child_handler or reap_children() sets shell_function_completed to the status of our child shell. */ while (shell_function_completed == 0) reap_children (1, 0); if (batch_filename) { DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"), batch_filename)); remove (batch_filename); free (batch_filename); } shell_function_pid = 0; /* The child_handler function will set shell_function_completed to 1 when the child dies normally, or to -1 if it dies with status 127, which is most likely an exec fail. */ if (shell_function_completed == -1) { /* This likely means that the execvp failed, so we should just write the error message in the pipe from the child. */ fputs (buffer, stderr); fflush (stderr); } else { /* The child finished normally. Replace all newlines in its output with spaces, and put that in the variable output buffer. */ fold_newlines (buffer, &i); o = variable_buffer_output (o, buffer, i); } free (buffer); } return o; } #else /* _AMIGA */ /* Do the Amiga version of func_shell. */ static char * func_shell (char *o, char **argv, const char *funcname) { /* Amiga can't fork nor spawn, but I can start a program with redirection of my choice. However, this means that we don't have an opportunity to reopen stdout to trap it. Thus, we save our own stdout onto a new descriptor and dup a temp file's descriptor onto our stdout temporarily. After we spawn the shell program, we dup our own stdout back to the stdout descriptor. The buffer reading is the same as above, except that we're now reading from a file. */ #include #include BPTR child_stdout; char tmp_output[FILENAME_MAX]; unsigned int maxlen = 200, i; int cc; char * buffer, * ptr; char ** aptr; int len = 0; char* batch_filename = NULL; /* Construct the argument list. */ command_argv = construct_command_argv (argv[0], NULL, NULL, 0, &batch_filename); if (command_argv == 0) return o; /* Note the mktemp() is a security hole, but this only runs on Amiga. Ideally we would use main.c:open_tmpfile(), but this uses a special Open(), not fopen(), and I'm not familiar enough with the code to mess with it. */ strcpy (tmp_output, "t:MakeshXXXXXXXX"); mktemp (tmp_output); child_stdout = Open (tmp_output, MODE_NEWFILE); for (aptr=command_argv; *aptr; aptr++) len += strlen (*aptr) + 1; buffer = xmalloc (len + 1); ptr = buffer; for (aptr=command_argv; *aptr; aptr++) { strcpy (ptr, *aptr); ptr += strlen (ptr) + 1; *ptr ++ = ' '; *ptr = 0; } ptr[-1] = '\n'; Execute (buffer, NULL, child_stdout); free (buffer); Close (child_stdout); child_stdout = Open (tmp_output, MODE_OLDFILE); buffer = xmalloc (maxlen); i = 0; do { if (i == maxlen) { maxlen += 512; buffer = xrealloc (buffer, maxlen + 1); } cc = Read (child_stdout, &buffer[i], maxlen - i); if (cc > 0) i += cc; } while (cc > 0); Close (child_stdout); fold_newlines (buffer, &i); o = variable_buffer_output (o, buffer, i); free (buffer); return o; } #endif /* _AMIGA */ #endif /* !VMS */ #ifdef EXPERIMENTAL /* equality. Return is string-boolean, ie, the empty string is false. */ static char * func_eq (char *o, char **argv, const char *funcname UNUSED) { int result = ! strcmp (argv[0], argv[1]); o = variable_buffer_output (o, result ? "1" : "", result); return o; } /* string-boolean not operator. */ static char * func_not (char *o, char **argv, const char *funcname UNUSED) { const char *s = argv[0]; int result = 0; while (isspace ((unsigned char)*s)) s++; result = ! (*s); o = variable_buffer_output (o, result ? "1" : "", result); return o; } #endif #ifdef CONFIG_WITH_STRING_FUNCTIONS /* $(length string) XXX: This doesn't take multibyte locales into account. */ static char * func_length (char *o, char **argv, const char *funcname UNUSED) { size_t len = strlen (argv[0]); return math_int_to_variable_buffer (o, len); } /* $(length-var var) XXX: This doesn't take multibyte locales into account. */ static char * func_length_var (char *o, char **argv, const char *funcname UNUSED) { struct variable *var = lookup_variable (argv[0], strlen (argv[0])); return math_int_to_variable_buffer (o, var ? var->value_length : 0); } /* func_insert and func_substr helper. */ static char * helper_pad (char *o, size_t to_add, const char *pad, size_t pad_len) { while (to_add > 0) { size_t size = to_add > pad_len ? pad_len : to_add; o = variable_buffer_output (o, pad, size); to_add -= size; } return o; } /* $(insert in, str[, n[, length[, pad]]]) XXX: This doesn't take multibyte locales into account. */ static char * func_insert (char *o, char **argv, const char *funcname UNUSED) { const char *in = argv[0]; math_int in_len = (math_int)strlen (in); const char *str = argv[1]; math_int str_len = (math_int)strlen (str); math_int n = 0; math_int length = str_len; const char *pad = " "; size_t pad_len = 16; size_t i; if (argv[2] != NULL) { n = math_int_from_string (argv[2]); if (n > 0) n--; /* one-origin */ else if (n == 0) n = str_len; /* append */ else { /* n < 0: from the end */ n = str_len + n; if (n < 0) n = 0; } if (n > 16*1024*1024) /* 16MB */ fatal (NILF, _("$(insert ): n=%s is out of bounds\n"), argv[2]); if (argv[3] != NULL) { length = math_int_from_string (argv[3]); if (length < 0 || length > 16*1024*1024 /* 16MB */) fatal (NILF, _("$(insert ): length=%s is out of bounds\n"), argv[3]); if (argv[4] != NULL) { const char *tmp = argv[4]; for (i = 0; tmp[i] == ' '; i++) /* nothing */; if (tmp[i] != '\0') { pad = argv[4]; pad_len = strlen (pad); } /* else: it was all default spaces. */ } } } /* the head of the original string */ if (n > 0) { if (n <= str_len) o = variable_buffer_output (o, str, n); else { o = variable_buffer_output (o, str, str_len); o = helper_pad (o, n - str_len, pad, pad_len); } } /* insert the string */ if (length <= in_len) o = variable_buffer_output (o, in, length); else { o = variable_buffer_output (o, in, in_len); o = helper_pad (o, length - in_len, pad, pad_len); } /* the tail of the original string */ if (n < str_len) o = variable_buffer_output (o, str + n, str_len - n); return o; } /* $(pos needle, haystack[, start]) $(lastpos needle, haystack[, start]) XXX: This doesn't take multibyte locales into account. */ static char * func_pos (char *o, char **argv, const char *funcname UNUSED) { const char *needle = *argv[0] ? argv[0] : " "; size_t needle_len = strlen (needle); const char *haystack = argv[1]; size_t haystack_len = strlen (haystack); math_int start = 0; const char *hit; if (argv[2] != NULL) { start = math_int_from_string (argv[2]); if (start > 0) start--; /* one-origin */ else if (start < 0) start = haystack_len + start; /* from the end */ if (start < 0 || start + needle_len > haystack_len) return math_int_to_variable_buffer (o, 0); } else if (funcname[0] == 'l') start = haystack_len - 1; /* do the searching */ if (funcname[0] != 'l') { /* pos */ if (needle_len == 1) hit = strchr (haystack + start, *needle); else hit = strstr (haystack + start, needle); } else { /* last pos */ int ch = *needle; size_t off = start + 1; hit = NULL; while (off-- > 0) { if ( haystack[off] == ch && ( needle_len == 1 || strncmp (&haystack[off], needle, needle_len) == 0)) { hit = haystack + off; break; } } } return math_int_to_variable_buffer (o, hit ? hit - haystack + 1 : 0); } /* $(substr str, start[, length[, pad]]) XXX: This doesn't take multibyte locales into account. */ static char * func_substr (char *o, char **argv, const char *funcname UNUSED) { const char *str = argv[0]; math_int str_len = (math_int)strlen (str); math_int start = math_int_from_string (argv[1]); math_int length = 0; const char *pad = NULL; size_t pad_len = 0; if (argv[2] != NULL) { if (argv[3] != NULL) { pad = argv[3]; for (pad_len = 0; pad[pad_len] == ' '; pad_len++) /* nothing */; if (pad[pad_len] != '\0') pad_len = strlen (pad); else { pad = " "; pad_len = 16; } } length = math_int_from_string (argv[2]); if (length < 0 || (pad != NULL && length > 16*1024*1024 /* 16MB */)) fatal (NILF, _("$(substr ): length=%s is out of bounds\n"), argv[3]); if (length == 0) return o; } /* adjust start and length. */ if (pad == NULL) { if (start > 0) { start--; /* one-origin */ if (start >= str_len) return o; if (length == 0 || start + length > str_len) length = str_len - start; } else { start = str_len + start; if (start <= 0) { start += length; if (start <= 0) return o; length = start; start = 0; } else if (length == 0 || start + length > str_len) length = str_len - start; } o = variable_buffer_output (o, str + start, length); } else { if (start > 0) { start--; /* one-origin */ if (start >= str_len) return length ? helper_pad (o, length, pad, pad_len) : o; if (length == 0) length = str_len - start; } else { start = str_len + start; if (start <= 0) { if (start + length <= 0) return length ? helper_pad (o, length, pad, pad_len) : o; o = helper_pad (o, -start, pad, pad_len); return variable_buffer_output (o, str, length + start); } if (length == 0) length = str_len - start; } if (start + length <= str_len) o = variable_buffer_output (o, str + start, length); else { o = variable_buffer_output (o, str + start, str_len - start); o = helper_pad (o, start + length - str_len, pad, pad_len); } } return o; } /* $(translate string, from-set[, to-set[, pad-char]]) XXX: This doesn't take multibyte locales into account. */ static char * func_translate (char *o, char **argv, const char *funcname UNUSED) { const unsigned char *str = (const unsigned char *)argv[0]; const unsigned char *from_set = (const unsigned char *)argv[1]; const char *to_set = argv[2] != NULL ? argv[2] : ""; char trans_tab[1 << CHAR_BIT]; int i; char ch; /* init the array. */ for (i = 0; i < (1 << CHAR_BIT); i++) trans_tab[i] = i; while ( (i = *from_set) != '\0' && (ch = *to_set) != '\0') { trans_tab[i] = ch; from_set++; to_set++; } if (i != '\0') { ch = '\0'; /* no padding == remove char */ if (argv[2] != NULL && argv[3] != NULL) { ch = argv[3][0]; if (ch && argv[3][1]) fatal (NILF, _("$(translate ): pad=`%s' expected a single char\n"), argv[3]); if (ch == '\0') /* no char == space */ ch = ' '; } while ((i = *from_set++) != '\0') trans_tab[i] = ch; } /* do the translation */ while ((i = *str++) != '\0') { ch = trans_tab[i]; if (ch) o = variable_buffer_output (o, &ch, 1); } return o; } #endif /* CONFIG_WITH_STRING_FUNCTIONS */ #ifdef CONFIG_WITH_LAZY_DEPS_VARS /* This is also in file.c (bad). */ # if VMS # define FILE_LIST_SEPARATOR ',' # else # define FILE_LIST_SEPARATOR ' ' # endif /* Implements $^ and $+. The first comes with FUNCNAME 'deps', the second as 'deps-all'. If no second argument is given, or if it's empty, or if it's zero, all dependencies will be returned. If the second argument is non-zero the dependency at that position will be returned. If the argument is negative a fatal error is thrown. */ static char * func_deps (char *o, char **argv, const char *funcname) { unsigned int idx = 0; struct file *file; /* Handle the argument if present. */ if (argv[1]) { char *p = argv[1]; while (isspace ((unsigned int)*p)) p++; if (*p != '\0') { char *n; long l = strtol (p, &n, 0); while (isspace ((unsigned int)*n)) n++; idx = l; if (*n != '\0' || l < 0 || (long)idx != l) fatal (NILF, _("%s: invalid index value: `%s'\n"), funcname, p); } } /* Find the file and select the list corresponding to FUNCNAME. */ file = lookup_file (argv[0]); if (file) { struct dep *deps; struct dep *d; if (funcname[4] == '\0') { deps = file->deps_no_dupes; if (!deps && file->deps) deps = file->deps = create_uniqute_deps_chain (file->deps); } else deps = file->deps; if ( file->double_colon && ( file->double_colon != file || file->last != file)) error (NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"), funcname, file->name); if (idx == 0 /* all */) { unsigned int total_len = 0; /* calc the result length. */ for (d = deps; d; d = d->next) if (!d->ignore_mtime) { const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; total_len += strlen (c); } else #elif defined (CONFIG_WITH_STRCACHE2) total_len += strcache2_get_len (&file_strcache, c) + 1; #else total_len += strlen (c) + 1; #endif } if (total_len) { /* prepare the variable buffer dude wrt to the output size and pass along the strings. */ o = variable_buffer_output (o + total_len, "", 0) - total_len; /* a hack */ for (d = deps; d; d = d->next) if (!d->ignore_mtime) { unsigned int len; const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c); } else #elif defined (CONFIG_WITH_STRCACHE2) len = strcache2_get_len (&file_strcache, c) + 1; #else len = strlen (c) + 1; #endif o = variable_buffer_output (o, c, len); o[-1] = FILE_LIST_SEPARATOR; } --o; /* nuke the last list separator */ *o = '\0'; } } else { /* Dependency given by index. */ for (d = deps; d; d = d->next) if (!d->ignore_mtime) { if (--idx == 0) /* 1 based indexing */ { unsigned int len; const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c) - 1; } else #elif defined (CONFIG_WITH_STRCACHE2) len = strcache2_get_len (&file_strcache, c); #else len = strlen (c); #endif o = variable_buffer_output (o, c, len); break; } } } } return o; } /* Implements $?. If no second argument is given, or if it's empty, or if it's zero, all dependencies will be returned. If the second argument is non-zero the dependency at that position will be returned. If the argument is negative a fatal error is thrown. */ static char * func_deps_newer (char *o, char **argv, const char *funcname) { unsigned int idx = 0; struct file *file; /* Handle the argument if present. */ if (argv[1]) { char *p = argv[1]; while (isspace ((unsigned int)*p)) p++; if (*p != '\0') { char *n; long l = strtol (p, &n, 0); while (isspace ((unsigned int)*n)) n++; idx = l; if (*n != '\0' || l < 0 || (long)idx != l) fatal (NILF, _("%s: invalid index value: `%s'\n"), funcname, p); } } /* Find the file. */ file = lookup_file (argv[0]); if (file) { struct dep *deps = file->deps; struct dep *d; if ( file->double_colon && ( file->double_colon != file || file->last != file)) error (NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"), funcname, file->name); if (idx == 0 /* all */) { unsigned int total_len = 0; /* calc the result length. */ for (d = deps; d; d = d->next) if (!d->ignore_mtime && d->changed) { const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; total_len += strlen (c); } else #elif defined (CONFIG_WITH_STRCACHE2) total_len += strcache2_get_len (&file_strcache, c) + 1; #else total_len += strlen (c) + 1; #endif } if (total_len) { /* prepare the variable buffer dude wrt to the output size and pass along the strings. */ o = variable_buffer_output (o + total_len, "", 0) - total_len; /* a hack */ for (d = deps; d; d = d->next) if (!d->ignore_mtime && d->changed) { unsigned int len; const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c); } else #elif defined (CONFIG_WITH_STRCACHE2) len = strcache2_get_len (&file_strcache, c) + 1; #else len = strlen (c) + 1; #endif o = variable_buffer_output (o, c, len); o[-1] = FILE_LIST_SEPARATOR; } --o; /* nuke the last list separator */ *o = '\0'; } } else { /* Dependency given by index. */ for (d = deps; d; d = d->next) if (!d->ignore_mtime && d->changed) { if (--idx == 0) /* 1 based indexing */ { unsigned int len; const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c) - 1; } else #elif defined (CONFIG_WITH_STRCACHE2) len = strcache2_get_len (&file_strcache, c); #else len = strlen (c); #endif o = variable_buffer_output (o, c, len); break; } } } } return o; } /* Implements $|, the order only dependency list. If no second argument is given, or if it's empty, or if it's zero, all dependencies will be returned. If the second argument is non-zero the dependency at that position will be returned. If the argument is negative a fatal error is thrown. */ static char * func_deps_order_only (char *o, char **argv, const char *funcname) { unsigned int idx = 0; struct file *file; /* Handle the argument if present. */ if (argv[1]) { char *p = argv[1]; while (isspace ((unsigned int)*p)) p++; if (*p != '\0') { char *n; long l = strtol (p, &n, 0); while (isspace ((unsigned int)*n)) n++; idx = l; if (*n != '\0' || l < 0 || (long)idx != l) fatal (NILF, _("%s: invalid index value: `%s'\n"), funcname, p); } } /* Find the file. */ file = lookup_file (argv[0]); if (file) { struct dep *deps = file->deps; struct dep *d; if ( file->double_colon && ( file->double_colon != file || file->last != file)) error (NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"), funcname, file->name); if (idx == 0 /* all */) { unsigned int total_len = 0; /* calc the result length. */ for (d = deps; d; d = d->next) if (d->ignore_mtime) { const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; total_len += strlen (c); } else #elif defined (CONFIG_WITH_STRCACHE2) total_len += strcache2_get_len (&file_strcache, c) + 1; #else total_len += strlen (c) + 1; #endif } if (total_len) { /* prepare the variable buffer dude wrt to the output size and pass along the strings. */ o = variable_buffer_output (o + total_len, "", 0) - total_len; /* a hack */ for (d = deps; d; d = d->next) if (d->ignore_mtime) { unsigned int len; const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c); } else #elif defined (CONFIG_WITH_STRCACHE2) len = strcache2_get_len (&file_strcache, c) + 1; #else len = strlen (c) + 1; #endif o = variable_buffer_output (o, c, len); o[-1] = FILE_LIST_SEPARATOR; } --o; /* nuke the last list separator */ *o = '\0'; } } else { /* Dependency given by index. */ for (d = deps; d; d = d->next) if (d->ignore_mtime) { if (--idx == 0) /* 1 based indexing */ { unsigned int len; const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c) - 1; } else #elif defined (CONFIG_WITH_STRCACHE2) len = strcache2_get_len (&file_strcache, c); #else len = strlen (c); #endif o = variable_buffer_output (o, c, len); break; } } } } return o; } #endif /* CONFIG_WITH_LAZY_DEPS_VARS */ #ifdef CONFIG_WITH_DEFINED /* Similar to ifdef. */ static char * func_defined (char *o, char **argv, const char *funcname UNUSED) { struct variable *v = lookup_variable (argv[0], strlen (argv[0])); int result = v != NULL && *v->value != '\0'; o = variable_buffer_output (o, result ? "1" : "", result); return o; } #endif /* CONFIG_WITH_DEFINED*/ #ifdef HAVE_DOS_PATHS #define IS_ABSOLUTE(n) (n[0] && n[1] == ':') #define ROOT_LEN 3 #else #define IS_ABSOLUTE(n) (n[0] == '/') #define ROOT_LEN 1 #endif /* Return the absolute name of file NAME which does not contain any `.', `..' components nor any repeated path separators ('/'). */ #ifdef KMK char * #else static char * #endif abspath (const char *name, char *apath) { char *dest; const char *start, *end, *apath_limit; unsigned long root_len = ROOT_LEN; if (name[0] == '\0' || apath == NULL) return NULL; #ifdef WINDOWS32 /* bird */ dest = w32ify((char *)name, 1); if (!dest) return NULL; { size_t len = strlen(dest); memcpy(apath, dest, len); dest = apath + len; } (void)end; (void)start; (void)apath_limit; #elif defined __OS2__ /* bird */ if (_abspath(apath, name, GET_PATH_MAX)) return NULL; dest = strchr(apath, '\0'); (void)end; (void)start; (void)apath_limit; (void)dest; #else /* !WINDOWS32 && !__OS2__ */ apath_limit = apath + GET_PATH_MAX; if (!IS_ABSOLUTE(name)) { /* It is unlikely we would make it until here but just to make sure. */ if (!starting_directory) return NULL; strcpy (apath, starting_directory); #ifdef HAVE_DOS_PATHS if (IS_PATHSEP(name[0])) { if (IS_PATHSEP(name[1])) { /* A UNC. Don't prepend a drive letter. */ apath[0] = name[0]; apath[1] = name[1]; root_len = 2; } /* We have /foo, an absolute file name except for the drive letter. Assume the missing drive letter is the current drive, which we can get if we remove from starting_directory everything past the root directory. */ apath[root_len] = '\0'; } #endif dest = strchr (apath, '\0'); } else { strncpy (apath, name, root_len); apath[root_len] = '\0'; dest = apath + root_len; /* Get past the root, since we already copied it. */ name += root_len; #ifdef HAVE_DOS_PATHS if (!IS_PATHSEP(apath[2])) { /* Convert d:foo into d:./foo and increase root_len. */ apath[2] = '.'; apath[3] = '/'; dest++; root_len++; /* strncpy above copied one character too many. */ name--; } else apath[2] = '/'; /* make sure it's a forward slash */ #endif } for (start = end = name; *start != '\0'; start = end) { unsigned long len; /* Skip sequence of multiple path-separators. */ while (IS_PATHSEP(*start)) ++start; /* Find end of path component. */ for (end = start; *end != '\0' && !IS_PATHSEP(*end); ++end) ; len = end - start; if (len == 0) break; else if (len == 1 && start[0] == '.') /* nothing */; else if (len == 2 && start[0] == '.' && start[1] == '.') { /* Back up to previous component, ignore if at root already. */ if (dest > apath + root_len) for (--dest; !IS_PATHSEP(dest[-1]); --dest); } else { if (!IS_PATHSEP(dest[-1])) *dest++ = '/'; if (dest + len >= apath_limit) return NULL; dest = memcpy (dest, start, len); dest += len; *dest = '\0'; } } #endif /* !WINDOWS32 && !__OS2__ */ /* Unless it is root strip trailing separator. */ if (dest > apath + root_len && IS_PATHSEP(dest[-1])) --dest; *dest = '\0'; return apath; } static char * func_realpath (char *o, char **argv, const char *funcname UNUSED) { /* Expand the argument. */ const char *p = argv[0]; const char *path = 0; int doneany = 0; unsigned int len = 0; #ifndef HAVE_REALPATH struct stat st; #endif PATH_VAR (in); PATH_VAR (out); while ((path = find_next_token (&p, &len)) != 0) { if (len < GET_PATH_MAX) { strncpy (in, path, len); in[len] = '\0'; if ( #ifdef HAVE_REALPATH realpath (in, out) #else abspath (in, out) && stat (out, &st) == 0 #endif ) { o = variable_buffer_output (o, out, strlen (out)); o = variable_buffer_output (o, " ", 1); doneany = 1; } } } /* Kill last space. */ if (doneany) --o; return o; } static char * func_abspath (char *o, char **argv, const char *funcname UNUSED) { /* Expand the argument. */ const char *p = argv[0]; const char *path = 0; int doneany = 0; unsigned int len = 0; PATH_VAR (in); PATH_VAR (out); while ((path = find_next_token (&p, &len)) != 0) { if (len < GET_PATH_MAX) { strncpy (in, path, len); in[len] = '\0'; if (abspath (in, out)) { o = variable_buffer_output (o, out, strlen (out)); o = variable_buffer_output (o, " ", 1); doneany = 1; } } } /* Kill last space. */ if (doneany) --o; return o; } #ifdef CONFIG_WITH_ABSPATHEX /* Same as abspath except that the current path may be given as the 2nd argument. */ static char * func_abspathex (char *o, char **argv, const char *funcname UNUSED) { char *cwd = argv[1]; /* cwd needs leading spaces chopped and may be optional, in which case we're exactly like $(abspath ). */ if (cwd) while (isblank (*cwd)) cwd++; if (!cwd || !*cwd) o = func_abspath (o, argv, funcname); else { /* Expand the argument. */ const char *p = argv[0]; unsigned int cwd_len = ~0U; char *path = 0; int doneany = 0; unsigned int len = 0; PATH_VAR (in); PATH_VAR (out); while ((path = find_next_token (&p, &len)) != 0) { if (len < GET_PATH_MAX) { #ifdef HAVE_DOS_PATHS if (path[0] != '/' && path[0] != '\\' && (len < 2 || path[1] != ':') && cwd) #else if (path[0] != '/' && cwd) #endif { /* relative path, prefix with cwd. */ if (cwd_len == ~0U) cwd_len = strlen (cwd); if (cwd_len + len + 1 >= GET_PATH_MAX) continue; memcpy (in, cwd, cwd_len); in[cwd_len] = '/'; memcpy (in + cwd_len + 1, path, len); in[cwd_len + len + 1] = '\0'; } else { /* absolute path pass it as-is. */ memcpy (in, path, len); in[len] = '\0'; } if (abspath (in, out)) { o = variable_buffer_output (o, out, strlen (out)); o = variable_buffer_output (o, " ", 1); doneany = 1; } } } /* Kill last space. */ if (doneany) --o; } return o; } #endif #ifdef CONFIG_WITH_XARGS /* Create one or more command lines avoiding the max argument length restriction of the host OS. The last argument is the list of arguments that the normal xargs command would be fed from stdin. The first argument is initial command and it's arguments. If there are three or more arguments, the 2nd argument is the command and arguments to be used on subsequent command lines. Defaults to the initial command. If there are four or more arguments, the 3rd argument is the command to be used at the final command line. Defaults to the sub sequent or initial command . A future version of this function may define more arguments and therefor anyone specifying six or more arguments will cause fatal errors. Typical usage is: $(xargs ar cas mylib.a,$(objects)) or $(xargs ar cas mylib.a,ar as mylib.a,$(objects)) It will then create one or more "ar mylib.a ..." command lines with proper \n\t separation so it can be used when writing rules. */ static char * func_xargs (char *o, char **argv, const char *funcname UNUSED) { int argc; const char *initial_cmd; size_t initial_cmd_len; const char *subsequent_cmd; size_t subsequent_cmd_len; const char *final_cmd; size_t final_cmd_len; const char *args; size_t max_args; int i; #ifdef ARG_MAX /* ARG_MAX is a bit unreliable (environment), so drop 25% of the max. */ # define XARGS_MAX (ARG_MAX - (ARG_MAX / 4)) #else /* FIXME: update configure with a command line length test. */ # define XARGS_MAX 10240 #endif argc = 0; while (argv[argc]) argc++; if (argc > 4) fatal (NILF, _("Too many arguments for $(xargs)!\n")); /* first: the initial / default command.*/ initial_cmd = argv[0]; while (isspace ((unsigned char)*initial_cmd)) initial_cmd++; max_args = initial_cmd_len = strlen (initial_cmd); /* second: the command for the subsequent command lines. defaults to the initial cmd. */ subsequent_cmd = argc > 2 && argv[1][0] != '\0' ? argv[1] : ""; while (isspace ((unsigned char)*subsequent_cmd)) subsequent_cmd++; if (*subsequent_cmd) { subsequent_cmd_len = strlen (subsequent_cmd); if (subsequent_cmd_len > max_args) max_args = subsequent_cmd_len; } else { subsequent_cmd = initial_cmd; subsequent_cmd_len = initial_cmd_len; } /* third: the final command. defaults to the subseq cmd. */ final_cmd = argc > 3 && argv[2][0] != '\0' ? argv[2] : ""; while (isspace ((unsigned char)*final_cmd)) final_cmd++; if (*final_cmd) { final_cmd_len = strlen (final_cmd); if (final_cmd_len > max_args) max_args = final_cmd_len; } else { final_cmd = subsequent_cmd; final_cmd_len = subsequent_cmd_len; } /* last: the arguments to split up into sensible portions. */ args = argv[argc - 1]; /* calc the max argument length. */ if (XARGS_MAX <= max_args + 2) fatal (NILF, _("$(xargs): the commands are longer than the max exec argument length. (%lu <= %lu)\n"), (unsigned long)XARGS_MAX, (unsigned long)max_args + 2); max_args = XARGS_MAX - max_args - 1; /* generate the commands. */ i = 0; for (i = 0; ; i++) { unsigned int len; const char *iterator = args; const char *end = args; const char *cur; const char *tmp; /* scan the arguments till we reach the end or the max length. */ while ((cur = find_next_token(&iterator, &len)) && (size_t)((cur + len) - args) < max_args) end = cur + len; if (cur && end == args) fatal (NILF, _("$(xargs): command + one single arg is too much. giving up.\n")); /* emit the command. */ if (i == 0) { o = variable_buffer_output (o, (char *)initial_cmd, initial_cmd_len); o = variable_buffer_output (o, " ", 1); } else if (cur) { o = variable_buffer_output (o, "\n\t", 2); o = variable_buffer_output (o, (char *)subsequent_cmd, subsequent_cmd_len); o = variable_buffer_output (o, " ", 1); } else { o = variable_buffer_output (o, "\n\t", 2); o = variable_buffer_output (o, (char *)final_cmd, final_cmd_len); o = variable_buffer_output (o, " ", 1); } tmp = end; while (tmp > args && isspace ((unsigned char)tmp[-1])) /* drop trailing spaces. */ tmp--; o = variable_buffer_output (o, (char *)args, tmp - args); /* next */ if (!cur) break; args = end; while (isspace ((unsigned char)*args)) args++; } return o; } #endif #ifdef CONFIG_WITH_TOUPPER_TOLOWER static char * func_toupper_tolower (char *o, char **argv, const char *funcname) { /* Expand the argument. */ const char *p = argv[0]; while (*p) { /* convert to temporary buffer */ char tmp[256]; unsigned int i; if (!strcmp(funcname, "toupper")) for (i = 0; i < sizeof(tmp) && *p; i++, p++) tmp[i] = toupper(*p); else for (i = 0; i < sizeof(tmp) && *p; i++, p++) tmp[i] = tolower(*p); o = variable_buffer_output (o, tmp, i); } return o; } #endif /* CONFIG_WITH_TOUPPER_TOLOWER */ #if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE) /* Strip leading spaces and other things off a command. */ static const char * comp_cmds_strip_leading (const char *s, const char *e) { while (s < e) { const char ch = *s; if (!isblank (ch) && ch != '@' #ifdef CONFIG_WITH_COMMANDS_FUNC && ch != '%' #endif && ch != '+' && ch != '-') break; s++; } return s; } /* Worker for func_comp_vars() which is called if the comparision failed. It will do the slow command by command comparision of the commands when there invoked as comp-cmds. */ static char * comp_vars_ne (char *o, const char *s1, const char *e1, const char *s2, const char *e2, char *ne_retval, const char *funcname) { /* give up at once if not comp-cmds or comp-cmds-ex. */ if (strcmp (funcname, "comp-cmds") != 0 && strcmp (funcname, "comp-cmds-ex") != 0) o = variable_buffer_output (o, ne_retval, strlen (ne_retval)); else { const char * const s1_start = s1; int new_cmd = 1; int diff; for (;;) { /* if it's a new command, strip leading stuff. */ if (new_cmd) { s1 = comp_cmds_strip_leading (s1, e1); s2 = comp_cmds_strip_leading (s2, e2); new_cmd = 0; } if (s1 >= e1 || s2 >= e2) break; /* * Inner compare loop which compares one line. * FIXME: parse quoting! */ for (;;) { const char ch1 = *s1; const char ch2 = *s2; diff = ch1 - ch2; if (diff) break; if (ch1 == '\n') break; assert (ch1 != '\r'); /* next */ s1++; s2++; if (s1 >= e1 || s2 >= e2) break; } /* * If we exited because of a difference try to end-of-command * comparision, e.g. ignore trailing spaces. */ if (diff) { /* strip */ while (s1 < e1 && isblank (*s1)) s1++; while (s2 < e2 && isblank (*s2)) s2++; if (s1 >= e1 || s2 >= e2) break; /* compare again and check that it's a newline. */ if (*s2 != '\n' || *s1 != '\n') break; } /* Break out if we exited because of EOS. */ else if (s1 >= e1 || s2 >= e2) break; /* * Detect the end of command lines. */ if (*s1 == '\n') new_cmd = s1 == s1_start || s1[-1] != '\\'; s1++; s2++; } /* * Ignore trailing empty lines. */ if (s1 < e1 || s2 < e2) { while (s1 < e1 && (isblank (*s1) || *s1 == '\n')) if (*s1++ == '\n') s1 = comp_cmds_strip_leading (s1, e1); while (s2 < e2 && (isblank (*s2) || *s2 == '\n')) if (*s2++ == '\n') s2 = comp_cmds_strip_leading (s2, e2); } /* emit the result. */ if (s1 == e1 && s2 == e2) o = variable_buffer_output (o, "", 1) - 1; /** @todo check why this was necessary back the... */ else o = variable_buffer_output (o, ne_retval, strlen (ne_retval)); } return o; } /* $(comp-vars var1,var2,not-equal-return) or $(comp-cmds cmd-var1,cmd-var2,not-equal-return) Compares the two variables (that's given by name to avoid unnecessary expanding) and return the string in the third argument if not equal. If equal, nothing is returned. comp-vars will to an exact comparision only stripping leading and trailing spaces. comp-cmds will compare command by command, ignoring not only leading and trailing spaces on each line but also leading one leading '@', '-', '+' and '%' */ static char * func_comp_vars (char *o, char **argv, const char *funcname) { const char *s1, *e1, *x1, *s2, *e2, *x2; char *a1 = NULL, *a2 = NULL; size_t l, l1, l2; struct variable *var1 = lookup_variable (argv[0], strlen (argv[0])); struct variable *var2 = lookup_variable (argv[1], strlen (argv[1])); /* the simple cases */ if (var1 == var2) return variable_buffer_output (o, "", 0); /* eq */ if (!var1 || !var2) return variable_buffer_output (o, argv[2], strlen(argv[2])); if (var1->value == var2->value) return variable_buffer_output (o, "", 0); /* eq */ if (!var1->recursive && !var2->recursive) { if ( var1->value_length == var2->value_length && !memcmp (var1->value, var2->value, var1->value_length)) return variable_buffer_output (o, "", 0); /* eq */ /* ignore trailing and leading blanks */ s1 = var1->value; e1 = s1 + var1->value_length; while (isblank ((unsigned char) *s1)) s1++; while (e1 > s1 && isblank ((unsigned char) e1[-1])) e1--; s2 = var2->value; e2 = s2 + var2->value_length; while (isblank ((unsigned char) *s2)) s2++; while (e2 > s2 && isblank ((unsigned char) e2[-1])) e2--; if (e1 - s1 != e2 - s2) return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname); if (!memcmp (s1, s2, e1 - s1)) return variable_buffer_output (o, "", 0); /* eq */ return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname); } /* ignore trailing and leading blanks */ s1 = var1->value; e1 = s1 + var1->value_length; while (isblank ((unsigned char) *s1)) s1++; while (e1 > s1 && isblank ((unsigned char) e1[-1])) e1--; s2 = var2->value; e2 = s2 + var2->value_length; while (isblank((unsigned char)*s2)) s2++; while (e2 > s2 && isblank ((unsigned char) e2[-1])) e2--; /* both empty after stripping? */ if (s1 == e1 && s2 == e2) return variable_buffer_output (o, "", 0); /* eq */ /* optimist. */ if ( e1 - s1 == e2 - s2 && !memcmp(s1, s2, e1 - s1)) return variable_buffer_output (o, "", 0); /* eq */ /* compare up to the first '$' or the end. */ x1 = var1->recursive ? memchr (s1, '$', e1 - s1) : NULL; x2 = var2->recursive ? memchr (s2, '$', e2 - s2) : NULL; if (!x1 && !x2) return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname); l1 = x1 ? x1 - s1 : e1 - s1; l2 = x2 ? x2 - s2 : e2 - s2; l = l1 <= l2 ? l1 : l2; if (l && memcmp (s1, s2, l)) return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname); /* one or both buffers now require expanding. */ if (!x1) s1 += l; else { s1 = a1 = allocated_variable_expand ((char *)s1 + l); if (!l) while (isblank ((unsigned char) *s1)) s1++; e1 = strchr (s1, '\0'); while (e1 > s1 && isblank ((unsigned char) e1[-1])) e1--; } if (!x2) s2 += l; else { s2 = a2 = allocated_variable_expand ((char *)s2 + l); if (!l) while (isblank ((unsigned char) *s2)) s2++; e2 = strchr (s2, '\0'); while (e2 > s2 && isblank ((unsigned char) e2[-1])) e2--; } /* the final compare */ if ( e1 - s1 != e2 - s2 || memcmp (s1, s2, e1 - s1)) o = comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname); else o = variable_buffer_output (o, "", 1) - 1; /* eq */ /** @todo check why this was necessary back the... */ if (a1) free (a1); if (a2) free (a2); return o; } /* $(comp-cmds-ex cmds1,cmds2,not-equal-return) Compares the two strings and return the string in the third argument if not equal. If equal, nothing is returned. The comparision will be performed command by command, ignoring not only leading and trailing spaces on each line but also leading one leading '@', '-', '+' and '%'. */ static char * func_comp_cmds_ex (char *o, char **argv, const char *funcname) { const char *s1, *e1, *s2, *e2; size_t l1, l2; /* the simple cases */ s1 = argv[0]; s2 = argv[1]; if (s1 == s2) return variable_buffer_output (o, "", 0); /* eq */ l1 = strlen (argv[0]); l2 = strlen (argv[1]); if ( l1 == l2 && !memcmp (s1, s2, l1)) return variable_buffer_output (o, "", 0); /* eq */ /* ignore trailing and leading blanks */ e1 = s1 + l1; s1 = comp_cmds_strip_leading (s1, e1); e2 = s2 + l2; s2 = comp_cmds_strip_leading (s2, e2); if (e1 - s1 != e2 - s2) return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname); if (!memcmp (s1, s2, e1 - s1)) return variable_buffer_output (o, "", 0); /* eq */ return comp_vars_ne (o, s1, e1, s2, e2, argv[2], funcname); } #endif #ifdef CONFIG_WITH_DATE # if defined (_MSC_VER) /* FIXME: !defined (HAVE_STRPTIME) */ char *strptime(const char *s, const char *format, struct tm *tm) { return (char *)"strptime is not implemented"; } # endif /* Check if the string is all blanks or not. */ static int all_blanks (const char *s) { if (!s) return 1; while (isspace ((unsigned char)*s)) s++; return *s == '\0'; } /* The first argument is the strftime format string, a iso timestamp is the default if nothing is given. The second argument is a time value if given. The format is either the format from the first argument or given as an additional third argument. */ static char * func_date (char *o, char **argv, const char *funcname) { char *p; char *buf; size_t buf_size; struct tm t; const char *format; /* determin the format - use a single word as the default. */ format = !strcmp (funcname, "date-utc") ? "%Y-%m-%dT%H:%M:%SZ" : "%Y-%m-%dT%H:%M:%S"; if (!all_blanks (argv[0])) format = argv[0]; /* get the time. */ memset (&t, 0, sizeof(t)); if (argv[0] && !all_blanks (argv[1])) { const char *input_format = !all_blanks (argv[2]) ? argv[2] : format; p = strptime (argv[1], input_format, &t); if (!p || *p != '\0') { error (NILF, _("$(%s): strptime(%s,%s,) -> %s\n"), funcname, argv[1], input_format, p ? p : ""); return variable_buffer_output (o, "", 0); } } else { time_t tval; time (&tval); if (!strcmp (funcname, "date-utc")) t = *gmtime (&tval); else t = *localtime (&tval); } /* format it. note that zero isn't necessarily an error, so we'll have to keep shut about failures. */ buf_size = 64; buf = xmalloc (buf_size); while (strftime (buf, buf_size, format, &t) == 0) { if (buf_size >= 4096) { *buf = '\0'; break; } buf = xrealloc (buf, buf_size <<= 1); } o = variable_buffer_output (o, buf, strlen (buf)); free (buf); return o; } #endif #ifdef CONFIG_WITH_FILE_SIZE /* Prints the size of the specified file. Only one file is permitted, notthing is stripped. -1 is returned if stat fails. */ static char * func_file_size (char *o, char **argv, const char *funcname UNUSED) { struct stat st; if (stat (argv[0], &st)) return variable_buffer_output (o, "-1", 2); return math_int_to_variable_buffer (o, st.st_size); } #endif #ifdef CONFIG_WITH_WHICH /* Checks if the specified file exists an is executable. On systems employing executable extensions, the name may be modified to include the extension. */ static int func_which_test_x (char *file) { struct stat st; # if defined(WINDOWS32) || defined(__OS2__) char *ext; char *slash; /* fix slashes first. */ slash = file; while ((slash = strchr (slash, '\\')) != NULL) *slash++ = '/'; /* straight */ if (stat (file, &st) == 0 && S_ISREG (st.st_mode)) return 1; /* don't try add an extension if there already is one */ ext = strchr (file, '\0'); if (ext - file >= 4 && ( !stricmp (ext - 4, ".exe") || !stricmp (ext - 4, ".cmd") || !stricmp (ext - 4, ".bat") || !stricmp (ext - 4, ".com"))) return 0; /* try the extensions. */ strcpy (ext, ".exe"); if (stat (file, &st) == 0 && S_ISREG (st.st_mode)) return 1; strcpy (ext, ".cmd"); if (stat (file, &st) == 0 && S_ISREG (st.st_mode)) return 1; strcpy (ext, ".bat"); if (stat (file, &st) == 0 && S_ISREG (st.st_mode)) return 1; strcpy (ext, ".com"); if (stat (file, &st) == 0 && S_ISREG (st.st_mode)) return 1; return 0; # else return access (file, X_OK) == 0 && stat (file, &st) == 0 && S_ISREG (st.st_mode); # endif } /* Searches for the specified programs in the PATH and print their full location if found. Prints nothing if not found. */ static char * func_which (char *o, char **argv, const char *funcname UNUSED) { const char *path; struct variable *path_var; unsigned i; int first = 1; PATH_VAR (buf); path_var = lookup_variable ("PATH", 4); if (path_var) path = path_var->value; else path = "."; /* iterate input */ for (i = 0; argv[i]; i++) { unsigned int len; const char *iterator = argv[i]; char *cur; while ((cur = find_next_token (&iterator, &len))) { /* if there is a separator, don't walk the path. */ if (memchr (cur, '/', len) #ifdef HAVE_DOS_PATHS || memchr (cur, '\\', len) || memchr (cur, ':', len) #endif ) { if (len + 1 + 4 < GET_PATH_MAX) /* +4 for .exe */ { memcpy (buf, cur, len); buf[len] = '\0'; if (func_which_test_x (buf)) o = variable_buffer_output (o, buf, strlen (buf)); } } else { const char *comp = path; for (;;) { const char *src = comp; const char *end = strchr (comp, PATH_SEPARATOR_CHAR); size_t comp_len = end ? (size_t)(end - comp) : strlen (comp); if (!comp_len) { comp_len = 1; src = "."; } if (len + comp_len + 2 + 4 < GET_PATH_MAX) /* +4 for .exe */ { memcpy (buf, comp, comp_len); buf [comp_len] = '/'; memcpy (&buf[comp_len + 1], cur, len); buf[comp_len + 1 + len] = '\0'; if (func_which_test_x (buf)) { if (!first) o = variable_buffer_output (o, " ", 1); o = variable_buffer_output (o, buf, strlen (buf)); first = 0; break; } } /* next */ if (!end) break; comp = end + 1; } } } } return variable_buffer_output (o, "", 0); } #endif /* CONFIG_WITH_WHICH */ #ifdef CONFIG_WITH_IF_CONDITIONALS /* Evaluates the expression given in the argument using the same evaluator as for the new 'if' statements, except now we don't force the result into a boolean like for 'if' and '$(if-expr ,,)'. */ static char * func_expr (char *o, char **argv, const char *funcname UNUSED) { o = expr_eval_to_string (o, argv[0]); return o; } /* Same as '$(if ,,)' except the first argument is evaluated using the same evaluator as for the new 'if' statements. */ static char * func_if_expr (char *o, char **argv, const char *funcname UNUSED) { int rc; char *to_expand; /* Evaluate the condition in argv[0] and expand the 2nd or 3rd (optional) argument according to the result. */ rc = expr_eval_if_conditionals (argv[0], NULL); to_expand = rc == 0 ? argv[1] : argv[2]; if (to_expand && *to_expand) variable_expand_string_2 (o, to_expand, -1, &o); return o; } /* $(select when1-cond, when1-body[,whenN-cond, whenN-body]). */ static char * func_select (char *o, char **argv, const char *funcname UNUSED) { int i; /* Test WHEN-CONDs until one matches. The check for 'otherwise[:]' and 'default[:]' make this a bit more fun... */ for (i = 0; argv[i] != NULL; i += 2) { const char *cond = argv[i]; int is_otherwise = 0; if (argv[i + 1] == NULL) fatal (NILF, _("$(select ): not an even argument count\n")); while (isspace ((unsigned char)*cond)) cond++; if ( (*cond == 'o' && strncmp (cond, "otherwise", 9) == 0) || (*cond == 'd' && strncmp (cond, "default", 7) == 0)) { const char *end = cond + (*cond == 'o' ? 9 : 7); while (isspace ((unsigned char)*end)) end++; if (*end == ':') do end++; while (isspace ((unsigned char)*end)); is_otherwise = *end == '\0'; } if ( is_otherwise || expr_eval_if_conditionals (cond, NULL) == 0 /* true */) { variable_expand_string_2 (o, argv[i + 1], -1, &o); break; } } return o; } #endif /* CONFIG_WITH_IF_CONDITIONALS */ #ifdef CONFIG_WITH_SET_CONDITIONALS static char * func_set_intersects (char *o, char **argv, const char *funcname UNUSED) { const char *s1_cur; unsigned int s1_len; const char *s1_iterator = argv[0]; while ((s1_cur = find_next_token (&s1_iterator, &s1_len)) != 0) { const char *s2_cur; unsigned int s2_len; const char *s2_iterator = argv[1]; while ((s2_cur = find_next_token (&s2_iterator, &s2_len)) != 0) if (s2_len == s1_len && strneq (s2_cur, s1_cur, s1_len) ) return variable_buffer_output (o, "1", 1); /* found intersection */ } return o; /* no intersection */ } #endif /* CONFIG_WITH_SET_CONDITIONALS */ #ifdef CONFIG_WITH_STACK /* Push an item (string without spaces). */ static char * func_stack_push (char *o, char **argv, const char *funcname UNUSED) { do_variable_definition(NILF, argv[0], argv[1], o_file, f_append, 0 /* !target_var */); return o; } /* Pops an item off the stack / get the top stack element. (This is what's tricky to do in pure GNU make syntax.) */ static char * func_stack_pop_top (char *o, char **argv, const char *funcname) { struct variable *stack_var; const char *stack = argv[0]; stack_var = lookup_variable (stack, strlen (stack) ); if (stack_var) { unsigned int len; const char *iterator = stack_var->value; char *lastitem = NULL; char *cur; while ((cur = find_next_token (&iterator, &len))) lastitem = cur; if (lastitem != NULL) { if (strcmp (funcname, "stack-popv") != 0) o = variable_buffer_output (o, lastitem, len); if (strcmp (funcname, "stack-top") != 0) { *lastitem = '\0'; while (lastitem > stack_var->value && isspace (lastitem[-1])) *--lastitem = '\0'; #ifdef CONFIG_WITH_VALUE_LENGTH stack_var->value_length = lastitem - stack_var->value; #endif } } } return o; } #endif /* CONFIG_WITH_STACK */ #if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) || defined (CONFIG_WITH_FILE_SIZE) /* outputs the number (as a string) into the variable buffer. */ static char * math_int_to_variable_buffer (char *o, math_int num) { static const char xdigits[17] = "0123456789abcdef"; int negative; char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20 or 20 dec + sign + term => 22 */ char *str = &strbuf[sizeof (strbuf) - 1]; negative = num < 0; if (negative) num = -num; *str = '\0'; do { #ifdef HEX_MATH_NUMBERS *--str = xdigits[num & 0xf]; num >>= 4; #else *--str = xdigits[num % 10]; num /= 10; #endif } while (num); #ifdef HEX_MATH_NUMBERS *--str = 'x'; *--str = '0'; #endif if (negative) *--str = '-'; return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str); } #endif /* CONFIG_WITH_MATH || CONFIG_WITH_NANOTS */ #ifdef CONFIG_WITH_MATH /* Converts a string to an integer, causes an error if the format is invalid. */ static math_int math_int_from_string (const char *str) { const char *start; unsigned base = 0; int negative = 0; math_int num = 0; /* strip spaces */ while (isspace (*str)) str++; if (!*str) { error (NILF, _("bad number: empty\n")); return 0; } start = str; /* check for +/- */ while (*str == '+' || *str == '-' || isspace (*str)) if (*str++ == '-') negative = !negative; /* check for prefix - we do not accept octal numbers, sorry. */ if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) { base = 16; str += 2; } else { /* look for a hex digit, if not found treat it as decimal */ const char *p2 = str; for ( ; *p2; p2++) if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) ) { base = 16; break; } if (base == 0) base = 10; } /* must have at least one digit! */ if ( !isascii (*str) || !(base == 16 ? isxdigit (*str) : isdigit (*str)) ) { error (NILF, _("bad number: '%s'\n"), start); return 0; } /* convert it! */ while (*str && !isspace (*str)) { int ch = *str++; if (ch >= '0' && ch <= '9') ch -= '0'; else if (base == 16 && ch >= 'a' && ch <= 'f') ch -= 'a' - 10; else if (base == 16 && ch >= 'A' && ch <= 'F') ch -= 'A' - 10; else { error (NILF, _("bad number: '%s' (base=%u, pos=%lu)\n"), start, base, (unsigned long)(str - start)); return 0; } num *= base; num += ch; } /* check trailing spaces. */ while (isspace (*str)) str++; if (*str) { error (NILF, _("bad number: '%s'\n"), start); return 0; } return negative ? -num : num; } /* Add two or more integer numbers. */ static char * func_int_add (char *o, char **argv, const char *funcname UNUSED) { math_int num; int i; num = math_int_from_string (argv[0]); for (i = 1; argv[i]; i++) num += math_int_from_string (argv[i]); return math_int_to_variable_buffer (o, num); } /* Subtract two or more integer numbers. */ static char * func_int_sub (char *o, char **argv, const char *funcname UNUSED) { math_int num; int i; num = math_int_from_string (argv[0]); for (i = 1; argv[i]; i++) num -= math_int_from_string (argv[i]); return math_int_to_variable_buffer (o, num); } /* Multiply two or more integer numbers. */ static char * func_int_mul (char *o, char **argv, const char *funcname UNUSED) { math_int num; int i; num = math_int_from_string (argv[0]); for (i = 1; argv[i]; i++) num *= math_int_from_string (argv[i]); return math_int_to_variable_buffer (o, num); } /* Divide an integer number by one or more divisors. */ static char * func_int_div (char *o, char **argv, const char *funcname UNUSED) { math_int num; math_int divisor; int i; num = math_int_from_string (argv[0]); for (i = 1; argv[i]; i++) { divisor = math_int_from_string (argv[i]); if (!divisor) { error (NILF, _("divide by zero ('%s')\n"), argv[i]); return math_int_to_variable_buffer (o, 0); } num /= divisor; } return math_int_to_variable_buffer (o, num); } /* Divide and return the remainder. */ static char * func_int_mod (char *o, char **argv, const char *funcname UNUSED) { math_int num; math_int divisor; num = math_int_from_string (argv[0]); divisor = math_int_from_string (argv[1]); if (!divisor) { error (NILF, _("divide by zero ('%s')\n"), argv[1]); return math_int_to_variable_buffer (o, 0); } num %= divisor; return math_int_to_variable_buffer (o, num); } /* 2-complement. */ static char * func_int_not (char *o, char **argv, const char *funcname UNUSED) { math_int num; num = math_int_from_string (argv[0]); num = ~num; return math_int_to_variable_buffer (o, num); } /* Bitwise AND (two or more numbers). */ static char * func_int_and (char *o, char **argv, const char *funcname UNUSED) { math_int num; int i; num = math_int_from_string (argv[0]); for (i = 1; argv[i]; i++) num &= math_int_from_string (argv[i]); return math_int_to_variable_buffer (o, num); } /* Bitwise OR (two or more numbers). */ static char * func_int_or (char *o, char **argv, const char *funcname UNUSED) { math_int num; int i; num = math_int_from_string (argv[0]); for (i = 1; argv[i]; i++) num |= math_int_from_string (argv[i]); return math_int_to_variable_buffer (o, num); } /* Bitwise XOR (two or more numbers). */ static char * func_int_xor (char *o, char **argv, const char *funcname UNUSED) { math_int num; int i; num = math_int_from_string (argv[0]); for (i = 1; argv[i]; i++) num ^= math_int_from_string (argv[i]); return math_int_to_variable_buffer (o, num); } /* Compare two integer numbers. Returns make boolean (true="1"; false=""). */ static char * func_int_cmp (char *o, char **argv, const char *funcname) { math_int num1; math_int num2; int rc; num1 = math_int_from_string (argv[0]); num2 = math_int_from_string (argv[1]); funcname += sizeof ("int-") - 1; if (!strcmp (funcname, "eq")) rc = num1 == num2; else if (!strcmp (funcname, "ne")) rc = num1 != num2; else if (!strcmp (funcname, "gt")) rc = num1 > num2; else if (!strcmp (funcname, "ge")) rc = num1 >= num2; else if (!strcmp (funcname, "lt")) rc = num1 < num2; else /*if (!strcmp (funcname, "le"))*/ rc = num1 <= num2; return variable_buffer_output (o, rc ? "1" : "", rc); } #endif /* CONFIG_WITH_MATH */ #ifdef CONFIG_WITH_NANOTS /* Returns the current timestamp as nano seconds. The time source is a high res monotone one if the platform provides this (and we know about it). Tip. Use this with int-sub to profile makefile reading and similar. */ static char * func_nanots (char *o, char **argv UNUSED, const char *funcname UNUSED) { return math_int_to_variable_buffer (o, nano_timestamp ()); } #endif #ifdef CONFIG_WITH_OS2_LIBPATH /* Sets or gets the OS/2 libpath variables. The first argument indicates which variable - BEGINLIBPATH, ENDLIBPATH, LIBPATHSTRICT or LIBPATH. The second indicates whether this is a get (not present) or set (present) operation. When present it is the new value for the variable. */ static char * func_os2_libpath (char *o, char **argv, const char *funcname UNUSED) { char buf[4096]; ULONG fVar; APIRET rc; /* translate variable name (first arg) */ if (!strcmp (argv[0], "BEGINLIBPATH")) fVar = BEGIN_LIBPATH; else if (!strcmp (argv[0], "ENDLIBPATH")) fVar = END_LIBPATH; else if (!strcmp (argv[0], "LIBPATHSTRICT")) fVar = LIBPATHSTRICT; else if (!strcmp (argv[0], "LIBPATH")) fVar = 0; else { error (NILF, _("$(libpath): unknown variable `%s'"), argv[0]); return variable_buffer_output (o, "", 0); } if (!argv[1]) { /* get the variable value. */ if (fVar != 0) { buf[0] = buf[1] = buf[2] = buf[3] = '\0'; rc = DosQueryExtLIBPATH (buf, fVar); } else rc = DosQueryHeaderInfo (NULLHANDLE, 0, buf, sizeof(buf), QHINF_LIBPATH); if (rc != NO_ERROR) { error (NILF, _("$(libpath): failed to query `%s', rc=%d"), argv[0], rc); return variable_buffer_output (o, "", 0); } o = variable_buffer_output (o, buf, strlen (buf)); } else { /* set the variable value. */ size_t len; size_t len_max = sizeof (buf) < 2048 ? sizeof (buf) : 2048; const char *val; const char *end; if (fVar == 0) { error (NILF, _("$(libpath): LIBPATH is read-only")); return variable_buffer_output (o, "", 0); } /* strip leading and trailing spaces and check for max length. */ val = argv[1]; while (isspace (*val)) val++; end = strchr (val, '\0'); while (end > val && isspace (end[-1])) end--; len = end - val; if (len >= len_max) { error (NILF, _("$(libpath): The new `%s' value is too long (%d bytes, max %d)"), argv[0], len, len_max); return variable_buffer_output (o, "", 0); } /* make a stripped copy in low memory and try set it. */ memcpy (buf, val, len); buf[len] = '\0'; rc = DosSetExtLIBPATH (buf, fVar); if (rc != NO_ERROR) { error (NILF, _("$(libpath): failed to set `%s' to `%s', rc=%d"), argv[0], buf, rc); return variable_buffer_output (o, "", 0); } o = variable_buffer_output (o, "", 0); } return o; } #endif /* CONFIG_WITH_OS2_LIBPATH */ #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) /* Retrieve make statistics. */ static char * func_make_stats (char *o, char **argv, const char *funcname UNUSED) { char buf[512]; int len; if (!argv[0] || (!argv[0][0] && !argv[1])) { # ifdef CONFIG_WITH_MAKE_STATS len = sprintf (buf, "alloc-cur: %5ld/%3ld %3luMB hash: %5lu %2lu%%", make_stats_allocations, make_stats_reallocations, make_stats_allocated / (1024*1024), make_stats_ht_lookups, (make_stats_ht_collisions * 100) / make_stats_ht_lookups); o = variable_buffer_output (o, buf, len); #endif } else { /* selective */ int i; for (i = 0; argv[i]; i++) { unsigned long val; if (i != 0) o = variable_buffer_output (o, " ", 1); if (0) continue; # ifdef CONFIG_WITH_MAKE_STATS else if (!strcmp(argv[i], "allocations")) val = make_stats_allocations; else if (!strcmp(argv[i], "reallocations")) val = make_stats_reallocations; else if (!strcmp(argv[i], "allocated")) val = make_stats_allocated; else if (!strcmp(argv[i], "ht_lookups")) val = make_stats_ht_lookups; else if (!strcmp(argv[i], "ht_collisions")) val = make_stats_ht_collisions; else if (!strcmp(argv[i], "ht_collisions_pct")) val = (make_stats_ht_collisions * 100) / make_stats_ht_lookups; #endif else { o = variable_buffer_output (o, argv[i], strlen (argv[i])); continue; } len = sprintf (buf, "%ld", val); o = variable_buffer_output (o, buf, len); } } return o; } #endif /* CONFIG_WITH_MAKE_STATS */ #ifdef CONFIG_WITH_COMMANDS_FUNC /* Gets all the commands for a target, separated by newlines. This is useful when creating and checking target dependencies since it reduces the amount of work and the memory consuption. A new prefix character '%' has been introduced for skipping certain lines, like for instance the one calling this function and pushing to a dep file. Blank lines are also skipped. The commands function takes exactly one argument, which is the name of the target which commands should be returned. The commands-sc is identical to commands except that it uses a ';' to separate the commands. The commands-usr is similar to commands except that it takes a 2nd argument that is used to separate the commands. */ char * func_commands (char *o, char **argv, const char *funcname) { struct file *file; static int recursive = 0; if (recursive) { error (reading_file, _("$(%s ) was invoked recursivly"), funcname); return variable_buffer_output (o, "recursive", sizeof ("recursive") - 1); } if (*argv[0] == '\0') { error (reading_file, _("$(%s ) was invoked with an empty target name"), funcname); return o; } recursive = 1; file = lookup_file (argv[0]); if (file && file->cmds) { unsigned int i; int cmd_sep_len; struct commands *cmds = file->cmds; const char *cmd_sep; if (!strcmp (funcname, "commands")) { cmd_sep = "\n"; cmd_sep_len = 1; } else if (!strcmp (funcname, "commands-sc")) { cmd_sep = ";"; cmd_sep_len = 1; } else /*if (!strcmp (funcname, "commands-usr"))*/ { cmd_sep = argv[1]; cmd_sep_len = strlen (cmd_sep); } initialize_file_variables (file, 1 /* don't search for pattern vars */); set_file_variables (file, 1 /* early call */); chop_commands (cmds); for (i = 0; i < cmds->ncommand_lines; i++) { char *p; char *in, *out, *ref; /* Skip it if it has a '%' prefix or is blank. */ if (cmds->lines_flags[i] & COMMAND_GETTER_SKIP_IT) continue; p = cmds->command_lines[i]; while (isblank ((unsigned char)*p)) p++; if (*p == '\0') continue; /* --- copied from new_job() in job.c --- */ /* Collapse backslash-newline combinations that are inside variable or function references. These are left alone by the parser so that they will appear in the echoing of commands (where they look nice); and collapsed by construct_command_argv when it tokenizes. But letting them survive inside function invocations loses because we don't want the functions to see them as part of the text. */ /* IN points to where in the line we are scanning. OUT points to where in the line we are writing. When we collapse a backslash-newline combination, IN gets ahead of OUT. */ in = out = p; while ((ref = strchr (in, '$')) != 0) { ++ref; /* Move past the $. */ if (out != in) /* Copy the text between the end of the last chunk we processed (where IN points) and the new chunk we are about to process (where REF points). */ memmove (out, in, ref - in); /* Move both pointers past the boring stuff. */ out += ref - in; in = ref; if (*ref == '(' || *ref == '{') { char openparen = *ref; char closeparen = openparen == '(' ? ')' : '}'; int count; char *p2; *out++ = *in++; /* Copy OPENPAREN. */ /* IN now points past the opening paren or brace. Count parens or braces until it is matched. */ count = 0; while (*in != '\0') { if (*in == closeparen && --count < 0) break; else if (*in == '\\' && in[1] == '\n') { /* We have found a backslash-newline inside a variable or function reference. Eat it and any following whitespace. */ int quoted = 0; for (p2 = in - 1; p2 > ref && *p2 == '\\'; --p2) quoted = !quoted; if (quoted) /* There were two or more backslashes, so this is not really a continuation line. We don't collapse the quoting backslashes here as is done in collapse_continuations, because the line will be collapsed again after expansion. */ *out++ = *in++; else { /* Skip the backslash, newline and any following whitespace. */ in = next_token (in + 2); /* Discard any preceding whitespace that has already been written to the output. */ while (out > ref && isblank ((unsigned char)out[-1])) --out; /* Replace it all with a single space. */ *out++ = ' '; } } else { if (*in == openparen) ++count; *out++ = *in++; } } } /* Some of these can be amended ($< perhaps), but we're likely to be called while the dep expansion happens, so it would have to be on a hackish basis. sad... */ else if (*ref == '<' || *ref == '*' || *ref == '%' || *ref == '^' || *ref == '+') error (reading_file, _("$(%s ) does not work reliably with $%c in all cases"), funcname, *ref); } /* There are no more references in this line to worry about. Copy the remaining uninteresting text to the output. */ if (out != in) strcpy (out, in); /* --- copied from new_job() in job.c --- */ /* Finally, expand the line. */ if (i) o = variable_buffer_output (o, cmd_sep, cmd_sep_len); o = variable_expand_for_file_2 (o, cmds->command_lines[i], ~0U, file, NULL); /* Skip it if it has a '%' prefix or is blank. */ p = o; while (isblank ((unsigned char)*o) || *o == '@' || *o == '-' || *o == '+') o++; if (*o != '\0' && *o != '%') o = strchr (o, '\0'); else if (i) o = p - cmd_sep_len; else o = p; } /* for each command line */ } /* else FIXME: bitch about it? */ recursive = 0; return o; } #endif /* CONFIG_WITH_COMMANDS_FUNC */ #ifdef KMK /* Useful when debugging kmk and/or makefiles. */ char * func_breakpoint (char *o, char **argv UNUSED, const char *funcname UNUSED) { #ifdef _MSC_VER __debugbreak(); #elif defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386) \ || defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64) # ifdef __sun__ __asm__ __volatile__ ("int $3\n\t"); # else __asm__ __volatile__ ("int3\n\t"); # endif #else char *p = (char *)0; *p = '\0'; #endif return o; } /* umask | umask -S. */ char * func_get_umask (char *o, char **argv UNUSED, const char *funcname UNUSED) { char sz[80]; int off; mode_t u; int symbolic = 0; const char *psz = argv[0]; if (psz) { const char *pszEnd = strchr (psz, '\0'); strip_whitespace (&psz, &pszEnd); if (pszEnd != psz) { if ( STR_N_EQUALS (psz, pszEnd - pszEnd, "S") || STR_N_EQUALS (psz, pszEnd - pszEnd, "-S") || STR_N_EQUALS (psz, pszEnd - pszEnd, "symbolic") ) symbolic = 1; else error (reading_file, _("$(%s ) invalid argument `%s'"), funcname, argv[0]); } } u = umask (002); umask (u); if (symbolic) { off = 0; sz[off++] = 'u'; sz[off++] = '='; if ((u & S_IRUSR) == 0) sz[off++] = 'r'; if ((u & S_IWUSR) == 0) sz[off++] = 'w'; if ((u & S_IXUSR) == 0) sz[off++] = 'x'; sz[off++] = ','; sz[off++] = 'g'; sz[off++] = '='; if ((u & S_IRGRP) == 0) sz[off++] = 'r'; if ((u & S_IWGRP) == 0) sz[off++] = 'w'; if ((u & S_IXGRP) == 0) sz[off++] = 'x'; sz[off++] = ','; sz[off++] = 'o'; sz[off++] = '='; if ((u & S_IROTH) == 0) sz[off++] = 'r'; if ((u & S_IWOTH) == 0) sz[off++] = 'w'; if ((u & S_IXOTH) == 0) sz[off++] = 'x'; } else off = sprintf (sz, "%.4o", u); return variable_buffer_output (o, sz, off); } /* umask 0002 | umask u=rwx,g=rwx,o=rx. */ char * func_set_umask (char *o, char **argv UNUSED, const char *funcname UNUSED) { mode_t u; const char *psz; /* Figure what kind of input this is. */ psz = argv[0]; while (isblank ((unsigned char)*psz)) psz++; if (isdigit ((unsigned char)*psz)) { u = 0; while (*psz) { u <<= 3; if (*psz < '0' || *psz >= '8') { error (reading_file, _("$(%s ) illegal number `%s'"), funcname, argv[0]); break; } u += *psz - '0'; psz++; } if (argv[1] != NULL) error (reading_file, _("$(%s ) too many arguments for octal mode"), funcname); } else { u = umask(0); umask(u); error (reading_file, _("$(%s ) symbol mode is not implemented"), funcname); } umask(u); return o; } #endif /* KMK */ /* Lookup table for builtin functions. This doesn't have to be sorted; we use a straight lookup. We might gain some efficiency by moving most often used functions to the start of the table. If MAXIMUM_ARGS is 0, that means there is no maximum and all comma-separated values are treated as arguments. EXPAND_ARGS means that all arguments should be expanded before invocation. Functions that do namespace tricks (foreach) don't automatically expand. */ static char *func_call (char *o, char **argv, const char *funcname); static struct function_table_entry function_table_init[] = { /* Name/size */ /* MIN MAX EXP? Function */ { STRING_SIZE_TUPLE("abspath"), 0, 1, 1, func_abspath}, { STRING_SIZE_TUPLE("addprefix"), 2, 2, 1, func_addsuffix_addprefix}, { STRING_SIZE_TUPLE("addsuffix"), 2, 2, 1, func_addsuffix_addprefix}, { STRING_SIZE_TUPLE("basename"), 0, 1, 1, func_basename_dir}, { STRING_SIZE_TUPLE("dir"), 0, 1, 1, func_basename_dir}, { STRING_SIZE_TUPLE("notdir"), 0, 1, 1, func_notdir_suffix}, #ifdef CONFIG_WITH_ROOT_FUNC { STRING_SIZE_TUPLE("root"), 0, 1, 1, func_root}, { STRING_SIZE_TUPLE("notroot"), 0, 1, 1, func_notroot}, #endif { STRING_SIZE_TUPLE("subst"), 3, 3, 1, func_subst}, { STRING_SIZE_TUPLE("suffix"), 0, 1, 1, func_notdir_suffix}, { STRING_SIZE_TUPLE("filter"), 2, 2, 1, func_filter_filterout}, { STRING_SIZE_TUPLE("filter-out"), 2, 2, 1, func_filter_filterout}, { STRING_SIZE_TUPLE("findstring"), 2, 2, 1, func_findstring}, #ifdef CONFIG_WITH_DEFINED_FUNCTIONS { STRING_SIZE_TUPLE("firstdefined"), 0, 2, 1, func_firstdefined}, #endif { STRING_SIZE_TUPLE("firstword"), 0, 1, 1, func_firstword}, { STRING_SIZE_TUPLE("flavor"), 0, 1, 1, func_flavor}, { STRING_SIZE_TUPLE("join"), 2, 2, 1, func_join}, #ifdef CONFIG_WITH_DEFINED_FUNCTIONS { STRING_SIZE_TUPLE("lastdefined"), 0, 2, 1, func_lastdefined}, #endif { STRING_SIZE_TUPLE("lastword"), 0, 1, 1, func_lastword}, { STRING_SIZE_TUPLE("patsubst"), 3, 3, 1, func_patsubst}, { STRING_SIZE_TUPLE("realpath"), 0, 1, 1, func_realpath}, #ifdef CONFIG_WITH_RSORT { STRING_SIZE_TUPLE("rsort"), 0, 1, 1, func_sort}, #endif { STRING_SIZE_TUPLE("shell"), 0, 1, 1, func_shell}, { STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort}, { STRING_SIZE_TUPLE("strip"), 0, 1, 1, func_strip}, #ifdef CONFIG_WITH_WHERE_FUNCTION { STRING_SIZE_TUPLE("where"), 0, 1, 1, func_where}, #endif { STRING_SIZE_TUPLE("wildcard"), 0, 1, 1, func_wildcard}, { STRING_SIZE_TUPLE("word"), 2, 2, 1, func_word}, { STRING_SIZE_TUPLE("wordlist"), 3, 3, 1, func_wordlist}, { STRING_SIZE_TUPLE("words"), 0, 1, 1, func_words}, { STRING_SIZE_TUPLE("origin"), 0, 1, 1, func_origin}, { STRING_SIZE_TUPLE("foreach"), 3, 3, 0, func_foreach}, #ifdef CONFIG_WITH_LOOP_FUNCTIONS { STRING_SIZE_TUPLE("for"), 4, 4, 0, func_for}, { STRING_SIZE_TUPLE("while"), 2, 2, 0, func_while}, #endif { STRING_SIZE_TUPLE("call"), 1, 0, 1, func_call}, { STRING_SIZE_TUPLE("info"), 0, 1, 1, func_error}, { STRING_SIZE_TUPLE("error"), 0, 1, 1, func_error}, { STRING_SIZE_TUPLE("warning"), 0, 1, 1, func_error}, { STRING_SIZE_TUPLE("if"), 2, 3, 0, func_if}, { STRING_SIZE_TUPLE("or"), 1, 0, 0, func_or}, { STRING_SIZE_TUPLE("and"), 1, 0, 0, func_and}, { STRING_SIZE_TUPLE("value"), 0, 1, 1, func_value}, { STRING_SIZE_TUPLE("eval"), 0, 1, 1, func_eval}, #ifdef CONFIG_WITH_EVALPLUS { STRING_SIZE_TUPLE("evalctx"), 0, 1, 1, func_evalctx}, { STRING_SIZE_TUPLE("evalval"), 1, 1, 1, func_evalval}, { STRING_SIZE_TUPLE("evalvalctx"), 1, 1, 1, func_evalval}, { STRING_SIZE_TUPLE("evalcall"), 1, 0, 1, func_call}, { STRING_SIZE_TUPLE("evalcall2"), 1, 0, 1, func_call}, { STRING_SIZE_TUPLE("eval-opt-var"), 1, 0, 1, func_eval_optimize_variable}, #endif #ifdef EXPERIMENTAL { STRING_SIZE_TUPLE("eq"), 2, 2, 1, func_eq}, { STRING_SIZE_TUPLE("not"), 0, 1, 1, func_not}, #endif #ifdef CONFIG_WITH_STRING_FUNCTIONS { STRING_SIZE_TUPLE("length"), 1, 1, 1, func_length}, { STRING_SIZE_TUPLE("length-var"), 1, 1, 1, func_length_var}, { STRING_SIZE_TUPLE("insert"), 2, 5, 1, func_insert}, { STRING_SIZE_TUPLE("pos"), 2, 3, 1, func_pos}, { STRING_SIZE_TUPLE("lastpos"), 2, 3, 1, func_pos}, { STRING_SIZE_TUPLE("substr"), 2, 4, 1, func_substr}, { STRING_SIZE_TUPLE("translate"), 2, 4, 1, func_translate}, #endif #ifdef CONFIG_WITH_PRINTF { STRING_SIZE_TUPLE("printf"), 1, 0, 1, kmk_builtin_func_printf}, #endif #ifdef CONFIG_WITH_LAZY_DEPS_VARS { STRING_SIZE_TUPLE("deps"), 1, 2, 1, func_deps}, { STRING_SIZE_TUPLE("deps-all"), 1, 2, 1, func_deps}, { STRING_SIZE_TUPLE("deps-newer"), 1, 2, 1, func_deps_newer}, { STRING_SIZE_TUPLE("deps-oo"), 1, 2, 1, func_deps_order_only}, #endif #ifdef CONFIG_WITH_DEFINED { STRING_SIZE_TUPLE("defined"), 1, 1, 1, func_defined}, #endif #ifdef CONFIG_WITH_TOUPPER_TOLOWER { STRING_SIZE_TUPLE("toupper"), 0, 1, 1, func_toupper_tolower}, { STRING_SIZE_TUPLE("tolower"), 0, 1, 1, func_toupper_tolower}, #endif #ifdef CONFIG_WITH_ABSPATHEX { STRING_SIZE_TUPLE("abspathex"), 0, 2, 1, func_abspathex}, #endif #ifdef CONFIG_WITH_XARGS { STRING_SIZE_TUPLE("xargs"), 2, 0, 1, func_xargs}, #endif #if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE) { STRING_SIZE_TUPLE("comp-vars"), 3, 3, 1, func_comp_vars}, { STRING_SIZE_TUPLE("comp-cmds"), 3, 3, 1, func_comp_vars}, { STRING_SIZE_TUPLE("comp-cmds-ex"), 3, 3, 1, func_comp_cmds_ex}, #endif #ifdef CONFIG_WITH_DATE { STRING_SIZE_TUPLE("date"), 0, 1, 1, func_date}, { STRING_SIZE_TUPLE("date-utc"), 0, 3, 1, func_date}, #endif #ifdef CONFIG_WITH_FILE_SIZE { STRING_SIZE_TUPLE("file-size"), 1, 1, 1, func_file_size}, #endif #ifdef CONFIG_WITH_WHICH { STRING_SIZE_TUPLE("which"), 0, 0, 1, func_which}, #endif #ifdef CONFIG_WITH_IF_CONDITIONALS { STRING_SIZE_TUPLE("expr"), 1, 1, 0, func_expr}, { STRING_SIZE_TUPLE("if-expr"), 2, 3, 0, func_if_expr}, { STRING_SIZE_TUPLE("select"), 2, 0, 0, func_select}, #endif #ifdef CONFIG_WITH_SET_CONDITIONALS { STRING_SIZE_TUPLE("intersects"), 2, 2, 1, func_set_intersects}, #endif #ifdef CONFIG_WITH_STACK { STRING_SIZE_TUPLE("stack-push"), 2, 2, 1, func_stack_push}, { STRING_SIZE_TUPLE("stack-pop"), 1, 1, 1, func_stack_pop_top}, { STRING_SIZE_TUPLE("stack-popv"), 1, 1, 1, func_stack_pop_top}, { STRING_SIZE_TUPLE("stack-top"), 1, 1, 1, func_stack_pop_top}, #endif #ifdef CONFIG_WITH_MATH { STRING_SIZE_TUPLE("int-add"), 2, 0, 1, func_int_add}, { STRING_SIZE_TUPLE("int-sub"), 2, 0, 1, func_int_sub}, { STRING_SIZE_TUPLE("int-mul"), 2, 0, 1, func_int_mul}, { STRING_SIZE_TUPLE("int-div"), 2, 0, 1, func_int_div}, { STRING_SIZE_TUPLE("int-mod"), 2, 2, 1, func_int_mod}, { STRING_SIZE_TUPLE("int-not"), 1, 1, 1, func_int_not}, { STRING_SIZE_TUPLE("int-and"), 2, 0, 1, func_int_and}, { STRING_SIZE_TUPLE("int-or"), 2, 0, 1, func_int_or}, { STRING_SIZE_TUPLE("int-xor"), 2, 0, 1, func_int_xor}, { STRING_SIZE_TUPLE("int-eq"), 2, 2, 1, func_int_cmp}, { STRING_SIZE_TUPLE("int-ne"), 2, 2, 1, func_int_cmp}, { STRING_SIZE_TUPLE("int-gt"), 2, 2, 1, func_int_cmp}, { STRING_SIZE_TUPLE("int-ge"), 2, 2, 1, func_int_cmp}, { STRING_SIZE_TUPLE("int-lt"), 2, 2, 1, func_int_cmp}, { STRING_SIZE_TUPLE("int-le"), 2, 2, 1, func_int_cmp}, #endif #ifdef CONFIG_WITH_NANOTS { STRING_SIZE_TUPLE("nanots"), 0, 0, 0, func_nanots}, #endif #ifdef CONFIG_WITH_OS2_LIBPATH { STRING_SIZE_TUPLE("libpath"), 1, 2, 1, func_os2_libpath}, #endif #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) { STRING_SIZE_TUPLE("make-stats"), 0, 0, 0, func_make_stats}, #endif #ifdef CONFIG_WITH_COMMANDS_FUNC { STRING_SIZE_TUPLE("commands"), 1, 1, 1, func_commands}, { STRING_SIZE_TUPLE("commands-sc"), 1, 1, 1, func_commands}, { STRING_SIZE_TUPLE("commands-usr"), 2, 2, 1, func_commands}, #endif #ifdef KMK_HELPERS { STRING_SIZE_TUPLE("kb-src-tool"), 1, 1, 0, func_kbuild_source_tool}, { STRING_SIZE_TUPLE("kb-obj-base"), 1, 1, 0, func_kbuild_object_base}, { STRING_SIZE_TUPLE("kb-obj-suff"), 1, 1, 0, func_kbuild_object_suffix}, { STRING_SIZE_TUPLE("kb-src-prop"), 3, 4, 0, func_kbuild_source_prop}, { STRING_SIZE_TUPLE("kb-src-one"), 0, 1, 0, func_kbuild_source_one}, { STRING_SIZE_TUPLE("kb-exp-tmpl"), 6, 6, 1, func_kbuild_expand_template}, #endif #ifdef KMK { STRING_SIZE_TUPLE("breakpoint"), 0, 0, 0, func_breakpoint}, { STRING_SIZE_TUPLE("set-umask"), 1, 3, 1, func_set_umask}, { STRING_SIZE_TUPLE("get-umask"), 0, 0, 0, func_get_umask}, #endif }; #define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry)) /* These must come after the definition of function_table. */ static char * expand_builtin_function (char *o, int argc, char **argv, const struct function_table_entry *entry_p) { if (argc < (int)entry_p->minimum_args) fatal (*expanding_var, _("insufficient number of arguments (%d) to function `%s'"), argc, entry_p->name); /* I suppose technically some function could do something with no arguments, but so far none do, so just test it for all functions here rather than in each one. We can change it later if necessary. */ if (!argc) return o; if (!entry_p->func_ptr) fatal (*expanding_var, _("unimplemented on this platform: function `%s'"), entry_p->name); return entry_p->func_ptr (o, argv, entry_p->name); } /* Check for a function invocation in *STRINGP. *STRINGP points at the opening ( or { and is not null-terminated. If a function invocation is found, expand it into the buffer at *OP, updating *OP, incrementing *STRINGP past the reference and returning nonzero. If not, return zero. */ static int handle_function2 (const struct function_table_entry *entry_p, char **op, const char **stringp) /* bird split it up. */ { char openparen = (*stringp)[0]; char closeparen = openparen == '(' ? ')' : '}'; const char *beg; const char *end; int count = 0; char *abeg = NULL; char **argv, **argvp; int nargs; beg = *stringp + 1; /* We found a builtin function. Find the beginning of its arguments (skip whitespace after the name). */ beg = next_token (beg + entry_p->len); /* Find the end of the function invocation, counting nested use of whichever kind of parens we use. Since we're looking, count commas to get a rough estimate of how many arguments we might have. The count might be high, but it'll never be low. */ for (nargs=1, end=beg; *end != '\0'; ++end) if (*end == ',') ++nargs; else if (*end == openparen) ++count; else if (*end == closeparen && --count < 0) break; if (count >= 0) fatal (*expanding_var, _("unterminated call to function `%s': missing `%c'"), entry_p->name, closeparen); *stringp = end; /* Get some memory to store the arg pointers. */ argvp = argv = alloca (sizeof (char *) * (nargs + 2)); /* Chop the string into arguments, then a nul. As soon as we hit MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the last argument. If we're expanding, store pointers to the expansion of each one. If not, make a duplicate of the string and point into that, nul-terminating each argument. */ if (entry_p->expand_args) { const char *p; for (p=beg, nargs=0; p <= end; ++argvp) { const char *next; ++nargs; if (nargs == entry_p->maximum_args || (! (next = find_next_argument (openparen, closeparen, p, end)))) next = end; *argvp = expand_argument (p, next); p = next + 1; } } else { int len = end - beg; char *p, *aend; abeg = xmalloc (len+1); memcpy (abeg, beg, len); abeg[len] = '\0'; aend = abeg + len; for (p=abeg, nargs=0; p <= aend; ++argvp) { char *next; ++nargs; if (nargs == entry_p->maximum_args || (! (next = find_next_argument (openparen, closeparen, p, aend)))) next = aend; *argvp = p; *next = '\0'; p = next + 1; } } *argvp = NULL; /* Finally! Run the function... */ *op = expand_builtin_function (*op, nargs, argv, entry_p); /* Free memory. */ if (entry_p->expand_args) for (argvp=argv; *argvp != 0; ++argvp) free (*argvp); if (abeg) free (abeg); return 1; } int /* bird split it up and hacked it. */ #ifndef CONFIG_WITH_VALUE_LENGTH handle_function (char **op, const char **stringp) { const struct function_table_entry *entry_p = lookup_function (*stringp + 1); if (!entry_p) return 0; return handle_function2 (entry_p, op, stringp); } #else /* CONFIG_WITH_VALUE_LENGTH */ handle_function (char **op, const char **stringp, const char *nameend, const char *eol UNUSED) { const char *fname = *stringp + 1; const struct function_table_entry *entry_p = lookup_function_in_hash_tab (fname, nameend - fname); if (!entry_p) return 0; return handle_function2 (entry_p, op, stringp); } #endif /* CONFIG_WITH_VALUE_LENGTH */ /* User-defined functions. Expand the first argument as either a builtin function or a make variable, in the context of the rest of the arguments assigned to $1, $2, ... $N. $0 is the name of the function. */ static char * func_call (char *o, char **argv, const char *funcname UNUSED) { static int max_args = 0; char *fname; char *cp; char *body; int flen; int i; int saved_args; const struct function_table_entry *entry_p; struct variable *v; #ifdef CONFIG_WITH_EVALPLUS char *buf; unsigned int len; #endif #if defined (CONFIG_WITH_EVALPLUS) || defined (CONFIG_WITH_VALUE_LENGTH) char num[11]; #endif /* There is no way to define a variable with a space in the name, so strip leading and trailing whitespace as a favor to the user. */ fname = argv[0]; while (*fname != '\0' && isspace ((unsigned char)*fname)) ++fname; cp = fname + strlen (fname) - 1; while (cp > fname && isspace ((unsigned char)*cp)) --cp; cp[1] = '\0'; /* Calling nothing is a no-op */ if (*fname == '\0') return o; /* Are we invoking a builtin function? */ #ifndef CONFIG_WITH_VALUE_LENGTH entry_p = lookup_function (fname); #else entry_p = lookup_function (fname, cp - fname + 1); #endif if (entry_p) { /* How many arguments do we have? */ for (i=0; argv[i+1]; ++i) ; return expand_builtin_function (o, i, argv+1, entry_p); } /* Not a builtin, so the first argument is the name of a variable to be expanded and interpreted as a function. Find it. */ flen = strlen (fname); v = lookup_variable (fname, flen); if (v == 0) warn_undefined (fname, flen); if (v == 0 || *v->value == '\0') return o; body = alloca (flen + 4); body[0] = '$'; body[1] = '('; memcpy (body + 2, fname, flen); body[flen+2] = ')'; body[flen+3] = '\0'; /* Set up arguments $(1) .. $(N). $(0) is the function name. */ push_new_variable_scope (); for (i=0; *argv; ++i, ++argv) #ifdef CONFIG_WITH_VALUE_LENGTH define_variable (num, sprintf (num, "%d", i), *argv, o_automatic, 0); #else { char num[11]; sprintf (num, "%d", i); define_variable (num, strlen (num), *argv, o_automatic, 0); } #endif #ifdef CONFIG_WITH_EVALPLUS /* $(.ARGC) is the argument count. */ len = sprintf (num, "%d", i - 1); define_variable_vl (".ARGC", sizeof (".ARGC") - 1, num, len, 1 /* dup val */, o_automatic, 0); #endif /* If the number of arguments we have is < max_args, it means we're inside a recursive invocation of $(call ...). Fill in the remaining arguments in the new scope with the empty value, to hide them from this invocation. */ for (; i < max_args; ++i) #ifdef CONFIG_WITH_VALUE_LENGTH define_variable (num, sprintf (num, "%d", i), "", o_automatic, 0); #else { char num[11]; sprintf (num, "%d", i); define_variable (num, strlen (num), "", o_automatic, 0); } #endif saved_args = max_args; max_args = i; #ifdef CONFIG_WITH_EVALPLUS if (!strcmp (funcname, "call")) { #endif /* Expand the body in the context of the arguments, adding the result to the variable buffer. */ v->exp_count = EXP_COUNT_MAX; #ifndef CONFIG_WITH_VALUE_LENGTH o = variable_expand_string (o, body, flen+3); v->exp_count = 0; o += strlen (o); #else /* CONFIG_WITH_VALUE_LENGTH */ variable_expand_string_2 (o, body, flen+3, &o); v->exp_count = 0; #endif /* CONFIG_WITH_VALUE_LENGTH */ #ifdef CONFIG_WITH_EVALPLUS } else { const struct floc *reading_file_saved = reading_file; char *eos; if (!strcmp (funcname, "evalcall")) { /* Evaluate the variable value without expanding it. We need a copy since eval_buffer is destructive. */ size_t off = o - variable_buffer; eos = variable_buffer_output (o, v->value, v->value_length + 1) - 1; o = variable_buffer + off; if (v->fileinfo.filenm) reading_file = &v->fileinfo; } else { /* Expand the body first and then evaluate the output. */ v->exp_count = EXP_COUNT_MAX; o = variable_expand_string_2 (o, body, flen+3, &eos); v->exp_count = 0; } install_variable_buffer (&buf, &len); eval_buffer (o, eos); restore_variable_buffer (buf, len); reading_file = reading_file_saved; /* Deal with the .RETURN value if present. */ v = lookup_variable_in_set (".RETURN", sizeof (".RETURN") - 1, current_variable_set_list->set); if (v && v->value_length) { if (v->recursive) { v->exp_count = EXP_COUNT_MAX; variable_expand_string_2 (o, v->value, v->value_length, &o); v->exp_count = 0; } else o = variable_buffer_output (o, v->value, v->value_length); } } #endif /* CONFIG_WITH_EVALPLUS */ max_args = saved_args; pop_variable_scope (); return o; } void hash_init_function_table (void) { hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2, function_table_entry_hash_1, function_table_entry_hash_2, function_table_entry_hash_cmp); hash_load (&function_table, function_table_init, FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry)); #if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH) { unsigned int i; for (i = 0; i < FUNCTION_TABLE_ENTRIES; i++) { const char *fn = function_table_init[i].name; while (*fn) { func_char_map[(int)*fn] = 1; fn++; } assert (function_table_init[i].len <= MAX_FUNCTION_LENGTH); assert (function_table_init[i].len >= MIN_FUNCTION_LENGTH); } } #endif } kbuild-2695/src/kmk/TODO.private0000644000000000000000000001545612247157306015165 0ustar rootroot -*-Indented-Text-*- GNU Make TODO List ------------------ This list comes both from the authors and from users of GNU make. They are listed in no particular order! Also, I don't gaurantee that all of them will be ultimately deemed "good ideas" and implemented. These are just the ones that, at first blush, seem to have some merit (and that I can remember). However, if you see something here you really, really want, speak up. All other things being equal, I will tend to implement things that seem to maximize user satisfaction. If you want to implement some of them yourself, barring the ones I've marked below, have at it! Please contact me first to let me know you're working on it, and give me some info about the design--and, critically, information about any user-visible syntax change, etc. The Top Item ------------ If you know perl (or want to learn DejaGNU or similar), the number one priority on my list of things I don't have time to do right now is fixing up the GNU make test suite. Most importantly it needs to be made "parallelizable", so more than one regression can run at the same time (essentially, make the "work" directory local). Also, the CWD during the test should be in the work directory or, better, a test-specific temporary directory so each test gets a new directory; right now sometimes tests leak files into the main directory which causes subsequent tests to fail (some tests may need to be tweaked). Beyond that, any cleanup done to make writing, reading, or handling tests simpler would be great! Please feel free to make whatever changes you like to the current tests, given some high-level goals, and that you'll port the current tests to whatever you do :). The Rest of the List -------------------- 1) Option to check more than timestamps to determine if targets have changed. This is also a very big one. It's _close_ to my plate :), and I have very definite ideas about how I would like it done. Please pick something else unless you must have this feature. If you try it, please work _extremely_ closely with me on it. 1a) Possibly a special case of this is the .KEEP_STATE feature of Sun's make. Some great folks at W U. in Canada did an implementation of this for a class project. Their approach is reasonable and workable, but doesn't really fit into my ideas for #2. Maybe that's OK. I have paperwork for their work so if you want to do this one talk to me to get what they've already done. [K R Praveen ] 2) Currently you can use "%.foo %.bar : %.baz" to mean that one invocation of the rule builds both targets. GNU make needs a way to do that for explicit rules, too. I heard a rumor that some versions of make all you to say "a.foo + a.bar : a.baz" to do this (i.e., a "+" means one invocation builds both). Don't know if this is the best syntax or not... what if you say "a.foo + a.bar a.bam : a.baz"; what does that mean? 3) Multi-token pattern rule matching (allow %1/%2.c : %1/obj/%2.o, etc., or something like that). Maybe using regex? 4) Provide a .TARGETS variable, containing the names of the targets defined in the makefile. Actually, I now think a $(targets ...) function, at least, might be better than a MAKETARGETS variable. The argument would be types of targets to list: "phony" is the most useful one. I suppose "default" might also be useful. Maybe some others; check the bitfields to see what might be handy. 5) Some sort of operating-system independent way of handling paths would be outstanding, so makefiles can be written for UNIX, VMS, DOS, MS-Windows, Amiga, etc. with a minimum of specialization. Or, perhaps related/instead of, some sort of meta-quoting syntax so make can deal with filenames containing spaces, colons, etc. I dunno, maybe something like $[...]? This may well not be worth doing until #1 is done. 6) Right now the .PRECIOUS, .INTERMEDIATE, and .SECONDARY pseudo-targets have different capabilities. For example, .PRECIOUS can take a "%", the others can't. Etc. These should all work the same, insofar as that makes sense. 7) Improved debugging/logging/etc. capabilities. Part of this is done: I introduced a number of debugging enhancements. Tim Magill is (I think) looking into options to control output more selectively. One thing I want to do in debugging is add a flag to allow debugging of variables as they're expanded (!). This would be incredibly verbose, but could be invaluable when nothing else seems to work and you just can't figure it out. The way variables are expanded now means this isn't 100% trivial, but it probably won't be hard. 8) Integration of Guile as an embedded scripting language. This means: allowing Guile functions to be declared in makefiles somehow, then providing a syntax for invoking them. At least one formulation of that would have the function resolve to a string which would be substituted in the makefile, kind of like $(shell ...) does now, but using the embedded interpreter so there's no process forked of course. Obviously this is an optional add-on feature. It could be more advanced than that, even, who knows? Maybe make could provide Guile functions that allow Guile scripts more direct access to internal make structures, somehow. This kind of thing needs a lot of thought. Also there's always the flip side: in some very fundamental ways make isn't the best choice right now for a complex build tool. It's great for simple-to-medium tasks, but there are already other tools available for the really tough situations. Ask yourself, realistically, how much work is worthwhile to add to make, given the fundamentals you can't really overcome without significantly affecting backward compatibility--and then why not use another tool in the first place? Something to think about. ------------------------------------------------------------------------------- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . kbuild-2695/src/kmk/testcase-2ndtargetexp.kmk0000644000000000000000000000341712247157306017742 0ustar rootroot# $Id: testcase-2ndtargetexp.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the 2nd target expansion feature. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk # # Enable it. # .SECONDTARGETEXPANSION: # # This is expanded immediately. # foo1 = foo1 $(foo1): $(if $(eq $@,foo1),$(ECHO) "foo1 works",$(ECHO) "foo1 is busted @=$@"; exit 1) # Mostly for making sure the ifeq test works below. flush_command_recoding := 1 # see record_waiting_files() in read.c ifeq ($(strip $(commands foo1)),) $(error No commands for foo1: $(commands foo1)) endif # # This is expanded in the 2nd round. # $$(foo2): $(if $(eq $@,foo2),$(ECHO) "foo2 works",$(ECHO) "foo2 is busted @=$@"; exit 1) # Check that a $(foo2) file exists. flush_command_recoding := 1 # see record_waiting_files() in read.c # $ (info $$(foo2) commands: $(commands $$(foo2))) ifeq ($(strip $(commands $$(foo2))),) $(error No commands for $$(foo2): $(commands $$(foo2))) endif all_recursive: foo1 foo2 $(ECHO) "2nd target expansion passes smoke testing" # define this last foo2 = foo2 kbuild-2695/src/kmk/amiga.c0000644000000000000000000000513012247157306014232 0ustar rootroot/* Running commands on Amiga Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "variable.h" #include "amiga.h" #include #include #include #include #include static const char Amiga_version[] = "$VER: Make 3.74.3 (12.05.96) \n" "Amiga Port by A. Digulla (digulla@home.lake.de)"; int MyExecute (char **argv) { char * buffer, * ptr; char ** aptr; int len = 0; int status; for (aptr=argv; *aptr; aptr++) { len += strlen (*aptr) + 4; } buffer = AllocMem (len, MEMF_ANY); if (!buffer) fatal (NILF, "MyExecute: Cannot allocate space for calling a command"); ptr = buffer; for (aptr=argv; *aptr; aptr++) { if (((*aptr)[0] == ';' && !(*aptr)[1])) { *ptr ++ = '"'; strcpy (ptr, *aptr); ptr += strlen (ptr); *ptr ++ = '"'; } else if ((*aptr)[0] == '@' && (*aptr)[1] == '@' && !(*aptr)[2]) { *ptr ++ = '\n'; continue; } else { strcpy (ptr, *aptr); ptr += strlen (ptr); } *ptr ++ = ' '; *ptr = 0; } ptr[-1] = '\n'; status = SystemTags (buffer, SYS_UserShell, TRUE, TAG_END); FreeMem (buffer, len); if (SetSignal(0L,0L) & SIGBREAKF_CTRL_C) status = 20; /* Warnings don't count */ if (status == 5) status = 0; return status; } char * wildcard_expansion (char *wc, char *o) { # define PATH_SIZE 1024 struct AnchorPath * apath; if ( (apath = AllocMem (sizeof (struct AnchorPath) + PATH_SIZE, MEMF_CLEAR)) ) { apath->ap_Strlen = PATH_SIZE; if (MatchFirst (wc, apath) == 0) { do { o = variable_buffer_output (o, apath->ap_Buf, strlen (apath->ap_Buf)); o = variable_buffer_output (o, " ",1); } while (MatchNext (apath) == 0); } MatchEnd (apath); FreeMem (apath, sizeof (struct AnchorPath) + PATH_SIZE); } return o; } kbuild-2695/src/kmk/config.h.solaris0000644000000000000000000003000312247157306016076 0ustar rootroot/* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using `getloadavg.c'. */ /* #undef C_GETLOADAVG */ /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 1 /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ #define HAVE_ALLOCA_H 1 /* Define to 1 if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 /* Define to 1 if you have the `bsd_signal' function. */ #define HAVE_BSD_SIGNAL 1 /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ #define HAVE_CLOCK_GETTIME 1 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 0 /* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you don't. */ #define HAVE_DECL__SYS_SIGLIST 1 /* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you don't. */ #define HAVE_DECL___SYS_SIGLIST 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #define HAVE_DOPRNT 1 /* Use platform specific coding */ /* #undef HAVE_DOS_PATHS */ /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getgroups' function. */ #define HAVE_GETGROUPS 1 /* Define to 1 if you have the `gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the `gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the `getloadavg' function. */ #define HAVE_GETLOADAVG 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have a standard gettimeofday function */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the `kstat' library (-lkstat). */ #define HAVE_LIBKSTAT 1 /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the `lstat' function. */ #define HAVE_LSTAT 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkstemp' function. */ #define HAVE_MKSTEMP 1 /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the `pipe' function. */ #define HAVE_PIPE 1 /* Define to 1 if you have the `pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the `readlink' function. */ #define HAVE_READLINK 1 /* Define to 1 if you have the `realpath' function. */ #define HAVE_REALPATH 1 /* Define to 1 if defines the SA_RESTART constant. */ #define HAVE_SA_RESTART 1 /* Define to 1 if you have the `setegid' function. */ #define HAVE_SETEGID 1 /* Define to 1 if you have the `seteuid' function. */ #define HAVE_SETEUID 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `setlocale' function. */ /* #undef HAVE_SETLOCALE */ /* Define to 1 if you have the `setregid' function. */ #define HAVE_SETREGID 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setrlimit' function. */ #define HAVE_SETRLIMIT 1 /* Define to 1 if you have the `setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if you have the `sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the `socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strcmpi' function. */ /* #undef HAVE_STRCMPI */ /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `stricmp' function. */ /* #undef HAVE_STRICMP */ /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_DIR_H */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the \`union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VARARGS_H */ /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the `wait3' function. */ #define HAVE_WAIT3 1 /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Build host information. (not used by kmk) */ #define MAKE_HOST "i386-pc-solaris2.11" /* Define to 1 to enable job server support in GNU make. */ #define MAKE_JOBSERVER 1 /* Define to 1 to enable symbolic link timestamp checking. */ #define MAKE_SYMLINKS 1 /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define to 1 if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of package */ #define PACKAGE "make" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ #define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "get" /* Define to 1 if the SCCS 'get' command understands the '-G' option. */ #define SCCS_GET_MINUS_G 1 /* Define to 1 if the `setvbuf' function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ /* #undef SETVBUF_REVERSED */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ #define ST_MTIM_NSEC tv_nsec /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ #define _FILE_OFFSET_BITS 64 /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* Define like PROTOTYPES; this can be used by system headers. */ #define __PROTOTYPES 1 /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `int' if doesn't define. */ /* #undef gid_t */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `int' if doesn't define. */ /* #undef uid_t */ /* Define uintmax_t if not defined in or . */ /* #undef uintmax_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ #include "inlined_memchr.h" kbuild-2695/src/kmk/COPYING0000644000000000000000000010451312247157306014050 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . kbuild-2695/src/kmk/rule.h0000644000000000000000000000422712247157307014137 0ustar rootroot/* Definitions for using pattern rules in GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Structure used for pattern (implicit) rules. */ struct rule { struct rule *next; const char **targets; /* Targets of the rule. */ unsigned int *lens; /* Lengths of each target. */ const char **suffixes; /* Suffixes (after `%') of each target. */ struct dep *deps; /* Dependencies of the rule. */ struct commands *cmds; /* Commands to execute. */ unsigned short num; /* Number of targets. */ char terminal; /* If terminal (double-colon). */ char in_use; /* If in use by a parent pattern_search. */ }; /* For calling install_pattern_rule. */ struct pspec { char *target, *dep, *commands; }; extern struct rule *pattern_rules; extern struct rule *last_pattern_rule; extern unsigned int num_pattern_rules; extern unsigned int max_pattern_deps; extern unsigned int max_pattern_targets; extern unsigned int max_pattern_dep_length; extern struct file *suffix_file; extern unsigned int maxsuffix; void count_implicit_rule_limits (void); void convert_to_pattern (void); void install_pattern_rule (struct pspec *p, int terminal); void create_pattern_rule (const char **targets, const char **target_percents, unsigned int num, int terminal, struct dep *deps, struct commands *commands, int override); kbuild-2695/src/kmk/incdep.c0000644000000000000000000014304512247157306014426 0ustar rootroot#ifdef CONFIG_WITH_INCLUDEDEP /* $Id: incdep.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * incdep - Simple dependency files. */ /* * Copyright (c) 2007-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #ifdef __OS2__ # define INCL_BASE # define INCL_ERRORS #endif #include "make.h" #if !defined(WINDOWS32) && !defined(__OS2__) # define HAVE_PTHREAD #endif #include #include #include "dep.h" #include "filedef.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" #include "debug.h" #include "strcache2.h" #ifdef HAVE_FCNTL_H # include #else # include #endif #ifdef WINDOWS32 # include # include # include # define PARSE_IN_WORKER #endif #ifdef __OS2__ # include # include #endif #ifdef HAVE_PTHREAD # include #endif #ifdef __APPLE__ # include # define PARSE_IN_WORKER #endif #if defined(__gnu_linux__) || defined(__linux__) # define PARSE_IN_WORKER #endif /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ struct incdep_variable_in_set { struct incdep_variable_in_set *next; /* the parameters */ struct strcache2_entry *name_entry; /* dep strcache - WRONG */ const char *value; /* xmalloc'ed */ unsigned int value_length; int duplicate_value; /* 0 */ enum variable_origin origin; int recursive; struct variable_set *set; const struct floc *flocp; /* NILF */ }; struct incdep_variable_def { struct incdep_variable_def *next; /* the parameters */ const struct floc *flocp; /* NILF */ struct strcache2_entry *name_entry; /* dep strcache - WRONG */ char *value; /* xmalloc'ed, free it */ unsigned int value_length; enum variable_origin origin; enum variable_flavor flavor; int target_var; }; struct incdep_recorded_file { struct incdep_recorded_file *next; /* the parameters */ struct strcache2_entry *filename_entry; /* dep strcache; converted to a nameseq record. */ struct dep *deps; /* All the names are dep strcache entries. */ const struct floc *flocp; /* NILF */ }; /* per dep file structure. */ struct incdep { struct incdep *next; char *file_base; char *file_end; int worker_tid; #ifdef PARSE_IN_WORKER unsigned int err_line_no; const char *err_msg; struct incdep_variable_in_set *recorded_variables_in_set_head; struct incdep_variable_in_set *recorded_variables_in_set_tail; struct incdep_variable_def *recorded_variable_defs_head; struct incdep_variable_def *recorded_variable_defs_tail; struct incdep_recorded_file *recorded_file_head; struct incdep_recorded_file *recorded_file_tail; #endif char name[1]; }; /******************************************************************************* * Global Variables * *******************************************************************************/ /* mutex protecting the globals and an associated condition/event. */ #ifdef HAVE_PTHREAD static pthread_mutex_t incdep_mtx; static pthread_cond_t incdep_cond_todo; static pthread_cond_t incdep_cond_done; #elif defined (WINDOWS32) static CRITICAL_SECTION incdep_mtx; static HANDLE incdep_hev_todo; static HANDLE incdep_hev_done; static int volatile incdep_hev_todo_waiters; static int volatile incdep_hev_done_waiters; #elif defined (__OS2__) static _fmutex incdep_mtx; static HEV incdep_hev_todo; static HEV incdep_hev_done; static int volatile incdep_hev_todo_waiters; static int volatile incdep_hev_done_waiters; #endif /* flag indicating whether the threads, lock and event/condvars has been initialized or not. */ static int incdep_initialized; /* the list of files that needs reading. */ static struct incdep * volatile incdep_head_todo; static struct incdep * volatile incdep_tail_todo; /* the number of files that are currently being read. */ static int volatile incdep_num_reading; /* the list of files that have been read. */ static struct incdep * volatile incdep_head_done; static struct incdep * volatile incdep_tail_done; /* The handles to the worker threads. */ #ifdef HAVE_PTHREAD # define INCDEP_MAX_THREADS 1 static pthread_t incdep_threads[INCDEP_MAX_THREADS]; #elif defined (WINDOWS32) # define INCDEP_MAX_THREADS 2 static HANDLE incdep_threads[INCDEP_MAX_THREADS]; #elif defined (__OS2__) # define INCDEP_MAX_THREADS 2 static TID incdep_threads[INCDEP_MAX_THREADS]; #endif static struct alloccache incdep_rec_caches[INCDEP_MAX_THREADS]; static struct alloccache incdep_dep_caches[INCDEP_MAX_THREADS]; static struct strcache2 incdep_dep_strcaches[INCDEP_MAX_THREADS]; static struct strcache2 incdep_var_strcaches[INCDEP_MAX_THREADS]; static unsigned incdep_num_threads; /* flag indicating whether the worker threads should terminate or not. */ static int volatile incdep_terminate; #ifdef __APPLE__ /* malloc zone for the incdep threads. */ static malloc_zone_t *incdep_zone; #endif /******************************************************************************* * Internal Functions * *******************************************************************************/ static void incdep_flush_it (struct floc *); static void eval_include_dep_file (struct incdep *, struct floc *); static void incdep_commit_recorded_file (const char *filename, struct dep *deps, const struct floc *flocp); /* xmalloc wrapper. For working around multithreaded performance problems found on Darwin, Linux (glibc), and possibly other systems. */ static void * incdep_xmalloc (struct incdep *cur, size_t size) { void *ptr; #ifdef __APPLE__ if (cur && cur->worker_tid != -1) { ptr = malloc_zone_malloc (incdep_zone, size); if (!ptr) fatal (NILF, _("virtual memory exhausted")); } else ptr = xmalloc (size); #else ptr = xmalloc (size); #endif (void)cur; return ptr; } #if 0 /* memset(malloc(sz),'\0',sz) wrapper. */ static void * incdep_xcalloc (struct incdep *cur, size_t size) { void *ptr; #ifdef __APPLE__ if (cur && cur->worker_tid != -1) ptr = malloc_zone_calloc (incdep_zone, size, 1); else ptr = calloc (size, 1); #else ptr = calloc (size, 1); #endif if (!ptr) fatal (NILF, _("virtual memory exhausted")); (void)cur; return ptr; } #endif /* unused */ /* free wrapper */ static void incdep_xfree (struct incdep *cur, void *ptr) { /* free() *must* work for the allocation hacks above because of free_dep_chain. */ free (ptr); (void)cur; } /* alloc a dep structure. These are allocated in bunches to save time. */ struct dep * incdep_alloc_dep (struct incdep *cur) { struct alloccache *cache; if (cur->worker_tid != -1) cache = &incdep_dep_caches[cur->worker_tid]; else cache = &dep_cache; return alloccache_calloc (cache); } /* allocate a record. */ static void * incdep_alloc_rec (struct incdep *cur) { return alloccache_alloc (&incdep_rec_caches[cur->worker_tid]); } /* free a record. */ static void incdep_free_rec (struct incdep *cur, void *rec) { /*alloccache_free (&incdep_rec_caches[cur->worker_tid], rec); - doesn't work of course. */ } /* grow a cache. */ static void * incdep_cache_allocator (void *thrd, unsigned int size) { (void)thrd; #ifdef __APPLE__ return malloc_zone_malloc (incdep_zone, size); #else return xmalloc (size); #endif } /* term a cache. */ static void incdep_cache_deallocator (void *thrd, void *ptr, unsigned int size) { (void)thrd; (void)size; free (ptr); } /* acquires the lock */ void incdep_lock(void) { #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) pthread_mutex_lock (&incdep_mtx); #elif defined (WINDOWS32) EnterCriticalSection (&incdep_mtx); #elif defined (__OS2__) _fmutex_request (&incdep_mtx, 0); #endif } /* releases the lock */ void incdep_unlock(void) { #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) pthread_mutex_unlock (&incdep_mtx); #elif defined(WINDOWS32) LeaveCriticalSection (&incdep_mtx); #elif defined(__OS2__) _fmutex_release (&incdep_mtx); #endif } /* signals the main thread that there is stuff todo. caller owns the lock. */ static void incdep_signal_done (void) { #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) pthread_cond_broadcast (&incdep_cond_done); #elif defined (WINDOWS32) if (incdep_hev_done_waiters) SetEvent (incdep_hev_done); #elif defined (__OS2__) if (incdep_hev_done_waiters) DosPostEventSem (incdep_hev_done); #endif } /* waits for a reader to finish reading. caller owns the lock. */ static void incdep_wait_done (void) { #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) pthread_cond_wait (&incdep_cond_done, &incdep_mtx); #elif defined (WINDOWS32) ResetEvent (incdep_hev_done); incdep_hev_done_waiters++; incdep_unlock (); WaitForSingleObject (incdep_hev_done, INFINITE); incdep_lock (); incdep_hev_done_waiters--; #elif defined (__OS2__) ULONG ulIgnore; DosResetEventSem (incdep_hev_done, &ulIgnore); incdep_hev_done_waiters++; incdep_unlock (); DosWaitEventSem (incdep_hev_done, SEM_INDEFINITE_WAIT); incdep_lock (); incdep_hev_done_waiters--; #endif } /* signals the worker threads. caller owns the lock. */ static void incdep_signal_todo (void) { #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) pthread_cond_broadcast (&incdep_cond_todo); #elif defined(WINDOWS32) if (incdep_hev_todo_waiters) SetEvent (incdep_hev_todo); #elif defined(__OS2__) if (incdep_hev_todo_waiters) DosPostEventSem (incdep_hev_todo); #endif } /* waits for stuff to arrive in the todo list. caller owns the lock. */ static void incdep_wait_todo (void) { #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) pthread_cond_wait (&incdep_cond_todo, &incdep_mtx); #elif defined (WINDOWS32) ResetEvent (incdep_hev_todo); incdep_hev_todo_waiters++; incdep_unlock (); WaitForSingleObject (incdep_hev_todo, INFINITE); incdep_lock (); incdep_hev_todo_waiters--; #elif defined (__OS2__) ULONG ulIgnore; DosResetEventSem (incdep_hev_todo, &ulIgnore); incdep_hev_todo_waiters++; incdep_unlock (); DosWaitEventSem (incdep_hev_todo, SEM_INDEFINITE_WAIT); incdep_lock (); incdep_hev_todo_waiters--; #endif } /* Reads a dep file into memory. */ static int incdep_read_file (struct incdep *cur, struct floc *f) { int fd; struct stat st; errno = 0; #ifdef O_BINARY fd = open (cur->name, O_RDONLY | O_BINARY, 0); #else fd = open (cur->name, O_RDONLY, 0); #endif if (fd < 0) { /* ignore non-existing dependency files. */ int err = errno; if (err == ENOENT || stat (cur->name, &st) != 0) return 1; error (f, "%s: %s", cur->name, strerror (err)); return -1; } if (!fstat (fd, &st)) { cur->file_base = incdep_xmalloc (cur, st.st_size + 1); if (read (fd, cur->file_base, st.st_size) == st.st_size) { close (fd); cur->file_end = cur->file_base + st.st_size; cur->file_base[st.st_size] = '\0'; return 0; } /* bail out */ error (f, "%s: read: %s", cur->name, strerror (errno)); incdep_xfree (cur, cur->file_base); } else error (f, "%s: fstat: %s", cur->name, strerror (errno)); close (fd); cur->file_base = cur->file_end = NULL; return -1; } /* Free the incdep structure. */ static void incdep_freeit (struct incdep *cur) { #ifdef PARSE_IN_WORKER assert (!cur->recorded_variables_in_set_head); assert (!cur->recorded_variable_defs_head); assert (!cur->recorded_file_head); #endif incdep_xfree (cur, cur->file_base); cur->next = NULL; free (cur); } /* A worker thread. */ void incdep_worker (int thrd) { incdep_lock (); while (!incdep_terminate) { /* get job from the todo list. */ struct incdep *cur = incdep_head_todo; if (!cur) { incdep_wait_todo (); continue; } if (cur->next) incdep_head_todo = cur->next; else incdep_head_todo = incdep_tail_todo = NULL; incdep_num_reading++; /* read the file. */ incdep_unlock (); cur->worker_tid = thrd; incdep_read_file (cur, NILF); #ifdef PARSE_IN_WORKER eval_include_dep_file (cur, NILF); #endif cur->worker_tid = -1; incdep_lock (); /* insert finished job into the done list. */ incdep_num_reading--; cur->next = NULL; if (incdep_tail_done) incdep_tail_done->next = cur; else incdep_head_done = cur; incdep_tail_done = cur; incdep_signal_done (); } incdep_unlock (); } /* Thread library specific thread functions wrapping incdep_wroker. */ #ifdef HAVE_PTHREAD static void * incdep_worker_pthread (void *thrd) { incdep_worker ((size_t)thrd); return NULL; } #elif defined (WINDOWS32) static unsigned __stdcall incdep_worker_windows (void *thrd) { incdep_worker ((size_t)thrd); return 0; } #elif defined (__OS2__) static void incdep_worker_os2 (void *thrd) { incdep_worker ((size_t)thrd); } #endif /* Checks if threads are enabled or not. This is a special hack so that is possible to disable the threads when in a debian fakeroot environment. Thus, in addition to the KMK_THREADS_DISABLED and KMK_THREADS_ENABLED environment variable check we also check for signs of fakeroot. */ static int incdep_are_threads_enabled (void) { #if defined (CONFIG_WITHOUT_THREADS) return 0; #endif /* Generic overrides. */ if (getenv ("KMK_THREADS_DISABLED")) { message (1, "Threads disabled (environment)"); return 0; } if (getenv ("KMK_THREADS_ENABLED")) return 1; #if defined (__gnu_linux__) || defined (__linux__) /* Try detect fakeroot. */ if (getenv ("FAKEROOTKEY") || getenv ("FAKEROOTUID") || getenv ("FAKEROOTGID") || getenv ("FAKEROOTEUID") || getenv ("FAKEROOTEGID") || getenv ("FAKEROOTSUID") || getenv ("FAKEROOTSGID") || getenv ("FAKEROOTFUID") || getenv ("FAKEROOTFGID") || getenv ("FAKEROOTDONTTRYCHOWN") || getenv ("FAKEROOT_FD_BASE") || getenv ("FAKEROOT_DB_SEARCH_PATHS")) { message (1, "Threads disabled (fakeroot)"); return 0; } /* LD_PRELOAD could indicate undetected debian fakeroot or some other ingenius library which cannot deal correctly with threads. */ if (getenv ("LD_PRELOAD")) { message (1, "Threads disabled (LD_PRELOAD)"); return 0; } #elif defined(__APPLE__) \ || defined(__sun__) || defined(__SunOS__) || defined(__sun) || defined(__SunOS) \ || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) \ || defined(__HAIKU__) /* No broken preload libraries known to be in common use on these platforms... */ #elif defined(_MSC_VER) || defined(_WIN32) || defined(__OS2__) /* No preload mess to care about. */ #else # error "Add your self to the appropriate case above and send a patch to bird." #endif return 1; } /* Creates the the worker threads. */ static void incdep_init (struct floc *f) { unsigned i; #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) int rc; pthread_attr_t attr; #elif defined (WINDOWS32) unsigned tid; uintptr_t hThread; #elif defined (__OS2__) int rc; int tid; #endif (void)f; /* heap hacks */ #ifdef __APPLE__ incdep_zone = malloc_create_zone (0, 0); if (!incdep_zone) incdep_zone = malloc_default_zone (); #endif /* create the mutex and two condition variables / event objects. */ #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) rc = pthread_mutex_init (&incdep_mtx, NULL); if (rc) fatal (f, _("pthread_mutex_init failed: err=%d"), rc); rc = pthread_cond_init (&incdep_cond_todo, NULL); if (rc) fatal (f, _("pthread_cond_init failed: err=%d"), rc); rc = pthread_cond_init (&incdep_cond_done, NULL); if (rc) fatal (f, _("pthread_cond_init failed: err=%d"), rc); #elif defined (WINDOWS32) InitializeCriticalSection (&incdep_mtx); incdep_hev_todo = CreateEvent (NULL, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL); if (!incdep_hev_todo) fatal (f, _("CreateEvent failed: err=%d"), GetLastError()); incdep_hev_done = CreateEvent (NULL, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL); if (!incdep_hev_done) fatal (f, _("CreateEvent failed: err=%d"), GetLastError()); incdep_hev_todo_waiters = 0; incdep_hev_done_waiters = 0; #elif defined (__OS2__) _fmutex_create (&incdep_mtx, 0); rc = DosCreateEventSem (NULL, &incdep_hev_todo, 0, FALSE); if (rc) fatal (f, _("DosCreateEventSem failed: rc=%d"), rc); rc = DosCreateEventSem (NULL, &incdep_hev_done, 0, FALSE); if (rc) fatal (f, _("DosCreateEventSem failed: rc=%d"), rc); incdep_hev_todo_waiters = 0; incdep_hev_done_waiters = 0; #endif /* create the worker threads and associated per thread data. */ incdep_terminate = 0; if (incdep_are_threads_enabled()) { incdep_num_threads = sizeof (incdep_threads) / sizeof (incdep_threads[0]); if (incdep_num_threads + 1 > job_slots) incdep_num_threads = job_slots <= 1 ? 1 : job_slots - 1; for (i = 0; i < incdep_num_threads; i++) { /* init caches */ unsigned rec_size = sizeof (struct incdep_variable_in_set); if (rec_size < sizeof (struct incdep_variable_def)) rec_size = sizeof (struct incdep_variable_def); if (rec_size < sizeof (struct incdep_recorded_file)) rec_size = sizeof (struct incdep_recorded_file); alloccache_init (&incdep_rec_caches[i], rec_size, "incdep rec", incdep_cache_allocator, (void *)(size_t)i); alloccache_init (&incdep_dep_caches[i], sizeof(struct dep), "incdep dep", incdep_cache_allocator, (void *)(size_t)i); strcache2_init (&incdep_dep_strcaches[i], "incdep dep", /* name */ 65536, /* hash size */ 0, /* default segment size*/ #ifdef HAVE_CASE_INSENSITIVE_FS 1, /* case insensitive */ #else 0, /* case insensitive */ #endif 0); /* thread safe */ strcache2_init (&incdep_var_strcaches[i], "incdep var", /* name */ 32768, /* hash size */ 0, /* default segment size*/ 0, /* case insensitive */ 0); /* thread safe */ /* create the thread. */ #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS) rc = pthread_attr_init (&attr); if (rc) fatal (f, _("pthread_attr_init failed: err=%d"), rc); /*rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); */ rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); if (rc) fatal (f, _("pthread_attr_setdetachstate failed: err=%d"), rc); rc = pthread_create(&incdep_threads[i], &attr, incdep_worker_pthread, (void *)(size_t)i); if (rc) fatal (f, _("pthread_mutex_init failed: err=%d"), rc); pthread_attr_destroy (&attr); #elif defined (WINDOWS32) tid = 0; hThread = _beginthreadex (NULL, 128*1024, incdep_worker_windows, (void *)i, 0, &tid); if (hThread == 0 || hThread == ~(uintptr_t)0) fatal (f, _("_beginthreadex failed: err=%d"), errno); incdep_threads[i] = (HANDLE)hThread; #elif defined (__OS2__) tid = _beginthread (incdep_worker_os2, NULL, 128*1024, (void *)i); if (tid <= 0) fatal (f, _("_beginthread failed: err=%d"), errno); incdep_threads[i] = tid; #endif } } else incdep_num_threads = 0; incdep_initialized = 1; } /* Flushes outstanding work and terminates the worker threads. This is called from snap_deps(). */ void incdep_flush_and_term (void) { unsigned i; if (!incdep_initialized) return; /* flush any out standing work */ incdep_flush_it (NILF); /* tell the threads to terminate */ incdep_lock (); incdep_terminate = 1; incdep_signal_todo (); incdep_unlock (); /* wait for the threads to quit */ for (i = 0; i < incdep_num_threads; i++) { /* more later? */ /* terminate or join up the allocation caches. */ alloccache_term (&incdep_rec_caches[i], incdep_cache_deallocator, (void *)(size_t)i); alloccache_join (&dep_cache, &incdep_dep_caches[i]); strcache2_term (&incdep_dep_strcaches[i]); strcache2_term (&incdep_var_strcaches[i]); } incdep_num_threads = 0; /* destroy the lock and condition variables / event objects. */ /* later */ incdep_initialized = 0; } #ifdef PARSE_IN_WORKER /* Flushes a strcache entry returning the actual string cache entry. The input is freed! */ static const char * incdep_flush_strcache_entry (struct strcache2_entry *entry) { if (!entry->user) entry->user = (void *) strcache2_add_hashed_file (&file_strcache, (const char *)(entry + 1), entry->length, entry->hash); return (const char *)entry->user; } /* Flushes the recorded instructions. */ static void incdep_flush_recorded_instructions (struct incdep *cur) { struct incdep_variable_in_set *rec_vis; struct incdep_variable_def *rec_vd; struct incdep_recorded_file *rec_f; /* define_variable_in_set */ rec_vis = cur->recorded_variables_in_set_head; cur->recorded_variables_in_set_head = cur->recorded_variables_in_set_tail = NULL; if (rec_vis) do { void *free_me = rec_vis; unsigned int name_length = rec_vis->name_entry->length; define_variable_in_set (incdep_flush_strcache_entry (rec_vis->name_entry), name_length, rec_vis->value, rec_vis->value_length, rec_vis->duplicate_value, rec_vis->origin, rec_vis->recursive, rec_vis->set, rec_vis->flocp); rec_vis = rec_vis->next; incdep_free_rec (cur, free_me); } while (rec_vis); /* do_variable_definition */ rec_vd = cur->recorded_variable_defs_head; cur->recorded_variable_defs_head = cur->recorded_variable_defs_tail = NULL; if (rec_vd) do { void *free_me = rec_vd; do_variable_definition_2 (rec_vd->flocp, incdep_flush_strcache_entry (rec_vd->name_entry), rec_vd->value, rec_vd->value_length, 0, rec_vd->value, rec_vd->origin, rec_vd->flavor, rec_vd->target_var); rec_vd = rec_vd->next; incdep_free_rec (cur, free_me); } while (rec_vd); /* record_files */ rec_f = cur->recorded_file_head; cur->recorded_file_head = cur->recorded_file_tail = NULL; if (rec_f) do { void *free_me = rec_f; struct dep *dep; for (dep = rec_f->deps; dep; dep = dep->next) dep->name = incdep_flush_strcache_entry ((struct strcache2_entry *)dep->name); incdep_commit_recorded_file (incdep_flush_strcache_entry (rec_f->filename_entry), rec_f->deps, rec_f->flocp); rec_f = rec_f->next; incdep_free_rec (cur, free_me); } while (rec_f); } #endif /* PARSE_IN_WORKER */ /* Record / issue a warning about a misformed dep file. */ static void incdep_warn (struct incdep *cur, unsigned int line_no, const char *msg) { if (cur->worker_tid == -1) error (NILF, "%s(%d): %s", cur->name, line_no, msg); #ifdef PARSE_IN_WORKER else { cur->err_line_no = line_no; cur->err_msg = msg; } #endif } /* Dependency or file strcache allocation / recording. */ static const char * incdep_dep_strcache (struct incdep *cur, const char *str, int len) { const char *ret; if (cur->worker_tid == -1) { /* Make sure the string is terminated before we hand it to strcache_add_len so it does have to make a temporary copy of it on the stack. */ char ch = str[len]; ((char *)str)[len] = '\0'; ret = strcache_add_len (str, len); ((char *)str)[len] = ch; } else { /* Add it out the strcache of the thread. */ ret = strcache2_add (&incdep_dep_strcaches[cur->worker_tid], str, len); ret = (const char *)strcache2_get_entry(&incdep_dep_strcaches[cur->worker_tid], ret); } return ret; } /* Variable name allocation / recording. */ static const char * incdep_var_strcache (struct incdep *cur, const char *str, int len) { const char *ret; if (cur->worker_tid == -1) { /* XXX: we're leaking this memory now! This will be fixed later. */ ret = xmalloc (len + 1); memcpy ((char *)ret, str, len); ((char *)ret)[len] = '\0'; } else { /* Add it out the strcache of the thread. */ ret = strcache2_add (&incdep_var_strcaches[cur->worker_tid], str, len); ret = (const char *)strcache2_get_entry(&incdep_var_strcaches[cur->worker_tid], ret); } return ret; } /* Record / perform a variable definition in a set. The NAME is in the string cache. The VALUE is on the heap. The DUPLICATE_VALUE is always 0. */ static void incdep_record_variable_in_set (struct incdep *cur, const char *name, unsigned int name_length, const char *value, unsigned int value_length, int duplicate_value, enum variable_origin origin, int recursive, struct variable_set *set, const struct floc *flocp) { assert (!duplicate_value); if (cur->worker_tid == -1) define_variable_in_set (name, name_length, value, value_length, duplicate_value, origin, recursive, set, flocp); #ifdef PARSE_IN_WORKER else { struct incdep_variable_in_set *rec = (struct incdep_variable_in_set *)incdep_alloc_rec (cur); rec->name_entry = (struct strcache2_entry *)name; rec->value = value; rec->value_length = value_length; rec->duplicate_value = duplicate_value; rec->origin = origin; rec->recursive = recursive; rec->set = set; rec->flocp = flocp; rec->next = NULL; if (cur->recorded_variables_in_set_tail) cur->recorded_variables_in_set_tail->next = rec; else cur->recorded_variables_in_set_head = rec; cur->recorded_variables_in_set_tail = rec; } #endif } /* Record / perform a variable definition. The VALUE should be disposed of. */ static void incdep_record_variable_def (struct incdep *cur, const struct floc *flocp, const char *name, unsigned int name_length, char *value, unsigned int value_length, enum variable_origin origin, enum variable_flavor flavor, int target_var) { if (cur->worker_tid == -1) do_variable_definition_2 (flocp, name, value, value_length, 0, value, origin, flavor, target_var); #ifdef PARSE_IN_WORKER else { struct incdep_variable_def *rec = (struct incdep_variable_def *)incdep_alloc_rec (cur); rec->flocp = flocp; rec->name_entry = (struct strcache2_entry *)name; rec->value = value; rec->value_length = value_length; rec->origin = origin; rec->flavor = flavor; rec->target_var = target_var; rec->next = NULL; if (cur->recorded_variable_defs_tail) cur->recorded_variable_defs_tail->next = rec; else cur->recorded_variable_defs_head = rec; cur->recorded_variable_defs_tail = rec; } #else (void)name_length; #endif } /* Similar to record_files in read.c, only much much simpler. */ static void incdep_commit_recorded_file (const char *filename, struct dep *deps, const struct floc *flocp) { struct file *f; /* Perform some validations. */ if (filename[0] == '.' && ( streq(filename, ".POSIX") || streq(filename, ".EXPORT_ALL_VARIABLES") || streq(filename, ".INTERMEDIATE") || streq(filename, ".LOW_RESOLUTION_TIME") || streq(filename, ".NOTPARALLEL") || streq(filename, ".ONESHELL") || streq(filename, ".PHONY") || streq(filename, ".PRECIOUS") || streq(filename, ".SECONDARY") || streq(filename, ".SECONDTARGETEXPANSION") || streq(filename, ".SILENT") || streq(filename, ".SHELLFLAGS") || streq(filename, ".SUFFIXES") ) ) { error (flocp, _("reserved filename '%s' used in dependency file, ignored"), filename); return; } /* Lookup or create an entry in the database. */ f = enter_file (filename); if (f->double_colon) { error (flocp, _("dependency file '%s' has a double colon entry already, ignoring"), filename); return; } f->is_target = 1; /* Append dependencies. */ deps = enter_prereqs (deps, NULL); if (deps) { struct dep *last = f->deps; if (!last) f->deps = deps; else { while (last->next) last = last->next; last->next = deps; } } } /* Record a file.*/ static void incdep_record_file (struct incdep *cur, const char *filename, struct dep *deps, const struct floc *flocp) { if (cur->worker_tid == -1) incdep_commit_recorded_file (filename, deps, flocp); #ifdef PARSE_IN_WORKER else { struct incdep_recorded_file *rec = (struct incdep_recorded_file *) incdep_alloc_rec (cur); rec->filename_entry = (struct strcache2_entry *)filename; rec->deps = deps; rec->flocp = flocp; rec->next = NULL; if (cur->recorded_file_tail) cur->recorded_file_tail->next = rec; else cur->recorded_file_head = rec; cur->recorded_file_tail = rec; } #endif } /* no nonsense dependency file including. Because nobody wants bogus dependency files to break their incremental builds with hard to comprehend error messages, this function does not use the normal eval routine but does all the parsing itself. This isn't, as much work as it sounds, because the necessary feature set is very limited. eval_include_dep_file groks: define var endef var [|:|?|>]= value [\] [\] file: [deps] [\] */ static void eval_include_dep_file (struct incdep *curdep, struct floc *f) { unsigned line_no = 1; const char *file_end = curdep->file_end; const char *cur = curdep->file_base; const char *endp; /* if no file data, just return immediately. */ if (!cur) return; /* now parse the file. */ while (cur < file_end) { /* skip empty lines */ while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n') ++cur; if (cur >= file_end) break; if (*cur == '#') { cur = memchr (cur, '\n', file_end - cur); if (!cur) break; } if (*cur == '\\') { unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3 : (file_end - cur == 1) ? 1 : 0; if (eol_len) { cur += eol_len; line_no++; continue; } } if (*cur == '\n') { cur++; line_no++; continue; } /* define var ... endef */ if (strneq (cur, "define ", 7)) { const char *var; unsigned var_len; const char *value_start; const char *value_end; char *value; unsigned value_len; int found_endef = 0; /* extract the variable name. */ cur += 7; while (isblank ((unsigned char)*cur)) ++cur; value_start = endp = memchr (cur, '\n', file_end - cur); if (!endp) endp = cur; while (endp > cur && isspace ((unsigned char)endp[-1])) --endp; var_len = endp - cur; if (!var_len) { incdep_warn (curdep, line_no, "bogus define statement."); break; } var = incdep_var_strcache (curdep, cur, var_len); /* find the end of the variable. */ cur = value_end = value_start = value_start + 1; ++line_no; while (cur < file_end) { /* check for endef, don't bother with skipping leading spaces. */ if ( file_end - cur >= 5 && strneq (cur, "endef", 5)) { endp = cur + 5; while (endp < file_end && isspace ((unsigned char)*endp) && *endp != '\n') endp++; if (endp >= file_end || *endp == '\n') { found_endef = 1; cur = endp >= file_end ? file_end : endp + 1; break; } } /* skip a line ahead. */ cur = value_end = memchr (cur, '\n', file_end - cur); if (cur != NULL) ++cur; else cur = value_end = file_end; ++line_no; } if (!found_endef) { incdep_warn (curdep, line_no, "missing endef, dropping the rest of the file."); break; } value_len = value_end - value_start; if (memchr (value_start, '\0', value_len)) { incdep_warn (curdep, line_no, "'\\0' in define, dropping the rest of the file."); break; } /* make a copy of the value, converting \r\n to \n, and define it. */ value = incdep_xmalloc (curdep, value_len + 1); endp = memchr (value_start, '\r', value_len); if (endp) { const char *src = value_start; char *dst = value; for (;;) { size_t len = endp - src; memcpy (dst, src, len); dst += len; src = endp; if (src + 1 < file_end && src[1] == '\n') src++; /* skip the '\r' */ if (src >= value_end) break; endp = memchr (endp + 1, '\r', src - value_end); if (!endp) endp = value_end; } value_len = dst - value; } else memcpy (value, value_start, value_len); value [value_len] = '\0'; incdep_record_variable_in_set (curdep, var, var_len, value, value_len, 0 /* don't duplicate */, o_file, 0 /* defines are recursive but this is faster */, NULL /* global set */, f); } /* file: deps OR variable [:]= value */ else { const char *colonp; const char *equalp; /* Look for a colon and an equal sign, optimize for colon. Only one file is support and the colon / equal must be on the same line. */ colonp = memchr (cur, ':', file_end - cur); #ifdef HAVE_DOS_PATHS while ( colonp && colonp + 1 < file_end && (colonp[1] == '/' || colonp[1] == '\\') && colonp > cur && isalpha ((unsigned char)colonp[-1]) && ( colonp == cur + 1 || strchr (" \t(", colonp[-2]) != 0)) colonp = memchr (colonp + 1, ':', file_end - (colonp + 1)); #endif endp = NULL; if ( !colonp || (endp = memchr (cur, '\n', colonp - cur))) { colonp = NULL; equalp = memchr (cur, '=', (endp ? endp : file_end) - cur); if ( !equalp || (!endp && memchr (cur, '\n', equalp - cur))) { incdep_warn (curdep, line_no, "no colon."); break; } } else equalp = memchr (cur, '=', (colonp + 2 <= file_end ? colonp + 2 : file_end) - cur); if (equalp) { /* An assignment of some sort. */ const char *var; unsigned var_len; const char *value_start; const char *value_end; char *value; unsigned value_len; unsigned multi_line = 0; enum variable_flavor flavor; /* figure the flavor first. */ flavor = f_recursive; if (equalp > cur) { if (equalp[-1] == ':') flavor = f_simple; else if (equalp[-1] == '?') flavor = f_conditional; else if (equalp[-1] == '+') flavor = f_append; else if (equalp[-1] == '>') flavor = f_prepend; } /* extract the variable name. */ endp = flavor == f_recursive ? equalp : equalp - 1; while (endp > cur && isblank ((unsigned char)endp[-1])) --endp; var_len = endp - cur; if (!var_len) { incdep_warn (curdep, line_no, "empty variable. (includedep)"); break; } if ( memchr (cur, '$', var_len) || memchr (cur, ' ', var_len) || memchr (cur, '\t', var_len)) { incdep_warn (curdep, line_no, "fancy variable name. (includedep)"); break; } var = incdep_var_strcache (curdep, cur, var_len); /* find the start of the value. */ cur = equalp + 1; while (cur < file_end && isblank ((unsigned char)*cur)) cur++; value_start = cur; /* find the end of the value / line (this isn't 101% correct). */ value_end = cur; while (cur < file_end) { endp = value_end = memchr (cur, '\n', file_end - cur); if (!value_end) value_end = file_end; if (value_end - 1 >= cur && value_end[-1] == '\r') --value_end; if (value_end - 1 < cur || value_end[-1] != '\\') { cur = endp ? endp + 1 : file_end; break; } --value_end; if (value_end - 1 >= cur && value_end[-1] == '\\') { incdep_warn (curdep, line_no, "fancy escaping! (includedep)"); cur = NULL; break; } if (!endp) { cur = file_end; break; } cur = endp + 1; ++multi_line; ++line_no; } if (!cur) break; ++line_no; /* make a copy of the value, converting \r\n to \n, and define it. */ value_len = value_end - value_start; value = incdep_xmalloc (curdep, value_len + 1); if (!multi_line) memcpy (value, value_start, value_len); else { /* unescape it */ const char *src = value_start; char *dst = value; while (src < value_end) { const char *nextp; endp = memchr (src, '\n', value_end - src); if (!endp) nextp = endp = value_end; else nextp = endp + 1; if (endp > src && endp[-1] == '\r') --endp; if (endp > src && endp[-1] == '\\') --endp; if (src != value_start) *dst++ = ' '; memcpy (dst, src, endp - src); dst += endp - src; src = nextp; } value_len = dst - value; } value [value_len] = '\0'; /* do the definition */ if (flavor == f_recursive || ( flavor == f_simple && !memchr (value, '$', value_len))) incdep_record_variable_in_set (curdep, var, var_len, value, value_len, 0 /* don't duplicate */, o_file, flavor == f_recursive /* recursive */, NULL /* global set */, f); else incdep_record_variable_def (curdep, f, var, var_len, value, value_len, o_file, flavor, 0 /* not target var */); } else { /* file: dependencies */ const char *filename; struct dep *deps = 0; struct dep **nextdep = &deps; struct dep *dep; /* extract the filename, ASSUME a single one. */ endp = colonp; while (endp > cur && isblank ((unsigned char)endp[-1])) --endp; if (cur == endp) { incdep_warn (curdep, line_no, "empty filename."); break; } if ( memchr (cur, '$', endp - cur) || memchr (cur, ' ', endp - cur) || memchr (cur, '\t', endp - cur)) { incdep_warn (curdep, line_no, "multiple / fancy file name. (includedep)"); break; } filename = incdep_dep_strcache (curdep, cur, endp - cur); /* parse any dependencies. */ cur = colonp + 1; while (cur < file_end) { /* skip blanks and count lines. */ while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n') ++cur; if (cur >= file_end) break; if (*cur == '\n') { cur++; line_no++; break; } /* continuation + eol? */ if (*cur == '\\') { unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3 : (file_end - cur == 1) ? 1 : 0; if (eol_len) { cur += eol_len; line_no++; continue; } } /* find the end of the filename */ endp = cur; while (endp < file_end && !isspace ((unsigned char)*endp)) ++endp; /* add it to the list. */ *nextdep = dep = incdep_alloc_dep (curdep); dep->name = incdep_dep_strcache (curdep, cur, endp - cur); dep->includedep = 1; nextdep = &dep->next; cur = endp; } /* enter the file with its dependencies. */ incdep_record_file (curdep, filename, deps, f); } } } /* free the file data */ incdep_xfree (curdep, curdep->file_base); curdep->file_base = curdep->file_end = NULL; } /* Flushes the incdep todo and done lists. */ static void incdep_flush_it (struct floc *f) { incdep_lock (); for (;;) { struct incdep *cur = incdep_head_done; /* if the done list is empty, grab a todo list entry. */ if (!cur && incdep_head_todo) { cur = incdep_head_todo; if (cur->next) incdep_head_todo = cur->next; else incdep_head_todo = incdep_tail_todo = NULL; incdep_unlock (); incdep_read_file (cur, f); eval_include_dep_file (cur, f); incdep_freeit (cur); incdep_lock (); continue; } /* if the todo list and done list are empty we're either done or will have to wait for the thread(s) to finish. */ if (!cur && !incdep_num_reading) break; /* done */ if (!cur) { while (!incdep_head_done) incdep_wait_done (); cur = incdep_head_done; } /* we grab the entire done list and work thru it. */ incdep_head_done = incdep_tail_done = NULL; incdep_unlock (); while (cur) { struct incdep *next = cur->next; #ifdef PARSE_IN_WORKER incdep_flush_recorded_instructions (cur); #else eval_include_dep_file (cur, f); #endif incdep_freeit (cur); cur = next; } incdep_lock (); } /* outer loop */ incdep_unlock (); } /* splits up a list of file names and feeds it to eval_include_dep_file, employing threads to try speed up the file reading. */ void eval_include_dep (const char *names, struct floc *f, enum incdep_op op) { struct incdep *head = 0; struct incdep *tail = 0; struct incdep *cur; const char *names_iterator = names; const char *name; unsigned int name_len; /* loop through NAMES, creating a todo list out of them. */ while ((name = find_next_token (&names_iterator, &name_len)) != 0) { cur = xmalloc (sizeof (*cur) + name_len); /* not incdep_xmalloc here */ cur->file_base = cur->file_end = NULL; memcpy (cur->name, name, name_len); cur->name[name_len] = '\0'; cur->worker_tid = -1; #ifdef PARSE_IN_WORKER cur->err_line_no = 0; cur->err_msg = NULL; cur->recorded_variables_in_set_head = NULL; cur->recorded_variables_in_set_tail = NULL; cur->recorded_variable_defs_head = NULL; cur->recorded_variable_defs_tail = NULL; cur->recorded_file_head = NULL; cur->recorded_file_tail = NULL; #endif cur->next = NULL; if (tail) tail->next = cur; else head = cur; tail = cur; } #ifdef ELECTRIC_HEAP if (1) #else if (op == incdep_read_it) #endif { /* work our way thru the files directly */ cur = head; while (cur) { struct incdep *next = cur->next; incdep_read_file (cur, f); eval_include_dep_file (cur, f); incdep_freeit (cur); cur = next; } } else { /* initialize the worker threads and related stuff the first time around. */ if (!incdep_initialized) incdep_init (f); /* queue the files and notify the worker threads. */ incdep_lock (); if (incdep_tail_todo) incdep_tail_todo->next = head; else incdep_head_todo = head; incdep_tail_todo = tail; incdep_signal_todo (); incdep_unlock (); /* flush the todo queue if we're requested to do so. */ if (op == incdep_flush) incdep_flush_it (f); } } #endif /* CONFIG_WITH_INCLUDEDEP */ kbuild-2695/src/kmk/strcache2.c0000644000000000000000000011477612247157306015053 0ustar rootroot/* $Id: strcache2.c 2413 2010-09-11 17:43:04Z bird $ */ /** @file * strcache2 - New string cache. */ /* * Copyright (c) 2008-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "make.h" #include "strcache2.h" #include #include "debug.h" #ifdef _MSC_VER typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; #else # include #endif #ifdef WINDOWS32 # include # include # include # define PARSE_IN_WORKER #endif #ifdef __OS2__ # include #endif #ifdef HAVE_PTHREAD # include #endif /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /* The default size of a memory segment (1MB). */ #define STRCACHE2_SEG_SIZE (1024U*1024U) /* The default hash table shift (hash size give as a power of two). */ #define STRCACHE2_HASH_SHIFT 16 /** Does the modding / masking of a hash number into an index. */ #ifdef STRCACHE2_USE_MASK # define STRCACHE2_MOD_IT(cache, hash) ((hash) & (cache)->hash_mask) #else # define STRCACHE2_MOD_IT(cache, hash) ((hash) % (cache)->hash_div) #endif # if defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64) \ || defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386) # define strcache2_get_unaligned_16bits(ptr) ( *((const uint16_t *)(ptr))) # else /* (endian doesn't matter) */ # define strcache2_get_unaligned_16bits(ptr) ( (((const uint8_t *)(ptr))[0] << 8) \ | (((const uint8_t *)(ptr))[1]) ) # endif /******************************************************************************* * Global Variables * *******************************************************************************/ /* List of initialized string caches. */ static struct strcache2 *strcache_head; /** Finds the closest primary number for power of two value (or something else * useful if not support). */ MY_INLINE unsigned int strcache2_find_prime(unsigned int shift) { switch (shift) { case 5: return 31; case 6: return 61; case 7: return 127; case 8: return 251; case 9: return 509; case 10: return 1021; case 11: return 2039; case 12: return 4093; case 13: return 8191; case 14: return 16381; case 15: return 32749; case 16: return 65521; case 17: return 131063; case 18: return 262139; case 19: return 524269; case 20: return 1048573; case 21: return 2097143; case 22: return 4194301; case 23: return 8388593; default: assert (0); return (1 << shift) - 1; } } /* The following is a bit experiment. It produces longer chains, i.e. worse distribution of the strings in the table, however the actual make performances is better (> 2); while (head-- > 0) { hash += strcache2_get_unaligned_16bits (str); tmp = (strcache2_get_unaligned_16bits (str + 2) << 11) ^ hash; hash = (hash << 16) ^ tmp; str += 2 * sizeof (uint16_t); hash += hash >> 11; } /* tail BIG_HASH_TAIL bytes (minus the odd ones) */ str += (len - BIG_HASH_HEAD - BIG_HASH_TAIL) & ~3U; head = (BIG_HASH_TAIL >> 2); while (head-- > 0) { hash += strcache2_get_unaligned_16bits (str); tmp = (strcache2_get_unaligned_16bits (str + 2) << 11) ^ hash; hash = (hash << 16) ^ tmp; str += 2 * sizeof (uint16_t); hash += hash >> 11; } /* force "avalanching" of final 127 bits. */ hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4; hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6; return hash; } #endif /* BIG_HASH_SIZE */ MY_INLINE unsigned int strcache2_case_sensitive_hash (const char *str, unsigned int len) { #if 1 /* Paul Hsieh hash SuperFast function: http://www.azillionmonkeys.com/qed/hash.html This performs very good and as a sligtly better distribution than STRING_N_HASH_1 on a typical kBuild run. It is also 37% faster than return_STRING_N_HASH_1 when running the two 100 times over typical kBuild strings that end up here (did a fprintf here and built kBuild). Compiler was 32-bit gcc 4.0.1, darwin, with -O2. FIXME: A path for well aligned data should be added to speed up execution on alignment sensitive systems. */ unsigned int rem; uint32_t hash; uint32_t tmp; assert (sizeof (uint8_t) == sizeof (char)); # ifdef BIG_HASH_SIZE /* long string? */ # if 0 /*BIG_HASH_SIZE > 128*/ if (MY_PREDICT_FALSE(len >= BIG_HASH_SIZE)) # else if (len >= BIG_HASH_SIZE) # endif return strcache2_case_sensitive_hash_big (str, len); # endif /* short string: main loop, walking on 2 x uint16_t */ hash = len; rem = len & 3; len >>= 2; while (len > 0) { hash += strcache2_get_unaligned_16bits (str); tmp = (strcache2_get_unaligned_16bits (str + 2) << 11) ^ hash; hash = (hash << 16) ^ tmp; str += 2 * sizeof (uint16_t); hash += hash >> 11; len--; } /* the remainder */ switch (rem) { case 3: hash += strcache2_get_unaligned_16bits (str); hash ^= hash << 16; hash ^= str[sizeof (uint16_t)] << 18; hash += hash >> 11; break; case 2: hash += strcache2_get_unaligned_16bits (str); hash ^= hash << 11; hash += hash >> 17; break; case 1: hash += *str; hash ^= hash << 10; hash += hash >> 1; break; } /* force "avalanching" of final 127 bits. */ hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4; hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6; return hash; #elif 1 /* Note! This implementation is 18% faster than return_STRING_N_HASH_1 when running the two 100 times over typical kBuild strings that end up here (did a fprintf here and built kBuild). Compiler was 32-bit gcc 4.0.1, darwin, with -O2. */ unsigned int hash = 0; if (MY_PREDICT_TRUE(len >= 2)) { unsigned int ch0 = *str++; hash = 0; len--; while (len >= 2) { unsigned int ch1 = *str++; hash += ch0 << (ch1 & 0xf); ch0 = *str++; hash += ch1 << (ch0 & 0xf); len -= 2; } if (len == 1) { unsigned ch1 = *str; hash += ch0 << (ch1 & 0xf); hash += ch1; } else hash += ch0; } else if (len) { hash = *str; hash += hash << (hash & 0xf); } else hash = 0; return hash; #elif 1 # if 0 /* This is SDBM. This specific form/unroll was benchmarked to be 28% faster than return_STRING_N_HASH_1. (Now the weird thing is that putting the (ch) first in the assignment made it noticably slower.) However, it is noticably slower in practice, most likely because of more collisions. Hrmpf. */ # define UPDATE_HASH(ch) hash = (hash << 6) + (hash << 16) - hash + (ch) unsigned int hash = 0; # else /* This is DJB2. This specific form/unroll was benchmarked to be 27% fast than return_STRING_N_HASH_1. Ditto. */ # define UPDATE_HASH(ch) hash = (hash << 5) + hash + (ch) unsigned int hash = 5381; # endif while (len >= 4) { UPDATE_HASH (str[0]); UPDATE_HASH (str[1]); UPDATE_HASH (str[2]); UPDATE_HASH (str[3]); str += 4; len -= 4; } switch (len) { default: case 0: return hash; case 1: UPDATE_HASH (str[0]); return hash; case 2: UPDATE_HASH (str[0]); UPDATE_HASH (str[1]); return hash; case 3: UPDATE_HASH (str[0]); UPDATE_HASH (str[1]); UPDATE_HASH (str[2]); return hash; } #endif } MY_INLINE unsigned int strcache2_case_insensitive_hash (const char *str, unsigned int len) { unsigned int hash = 0; if (MY_PREDICT_TRUE(len >= 2)) { unsigned int ch0 = *str++; ch0 = tolower (ch0); hash = 0; len--; while (len >= 2) { unsigned int ch1 = *str++; ch1 = tolower (ch1); hash += ch0 << (ch1 & 0xf); ch0 = *str++; ch0 = tolower (ch0); hash += ch1 << (ch0 & 0xf); len -= 2; } if (len == 1) { unsigned ch1 = *str; ch1 = tolower (ch1); hash += ch0 << (ch1 & 0xf); hash += ch1; } else hash += ch0; } else if (len) { hash = *str; hash += hash << (hash & 0xf); } else hash = 0; return hash; } MY_INLINE int strcache2_memcmp_inline_short (const char *xs, const char *ys, unsigned int length) { if (length <= 8) { /* short string compare - ~50% of the kBuild calls. */ assert ( !((size_t)ys & 3) ); if (!((size_t)xs & 3)) { /* aligned */ int result; switch (length) { default: /* memcmp for longer strings */ return memcmp (xs, ys, length); case 8: result = *(int32_t*)(xs + 4) - *(int32_t*)(ys + 4); result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 7: result = xs[6] - ys[6]; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 6: result = xs[5] - ys[5]; result |= xs[4] - ys[4]; result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 5: result = xs[4] - ys[4]; result |= *(int32_t*)xs - *(int32_t*)ys; return result; case 4: return *(int32_t*)xs - *(int32_t*)ys; case 3: result = xs[2] - ys[2]; result |= xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 2: result = xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 1: return *xs - *ys; case 0: return 0; } } else { /* unaligned */ int result = 0; switch (length) { case 8: result |= xs[7] - ys[7]; case 7: result |= xs[6] - ys[6]; case 6: result |= xs[5] - ys[5]; case 5: result |= xs[4] - ys[4]; case 4: result |= xs[3] - ys[3]; case 3: result |= xs[2] - ys[2]; case 2: result |= xs[1] - ys[1]; case 1: result |= xs[0] - ys[0]; case 0: return result; } } } /* memcmp for longer strings */ return memcmp (xs, ys, length); } MY_INLINE int strcache2_memcmp_inlined (const char *xs, const char *ys, unsigned int length) { #ifndef ELECTRIC_HEAP assert ( !((size_t)ys & 3) ); #endif if (!((size_t)xs & 3)) { int result; /* aligned */ while (length >= 8) { result = *(int32_t*)xs - *(int32_t*)ys; result |= *(int32_t*)(xs + 4) - *(int32_t*)(ys + 4); if (MY_PREDICT_FALSE(result)) return result; xs += 8; ys += 8; length -= 8; } switch (length) { case 7: result = *(int32_t*)xs - *(int32_t*)ys; result |= xs[6] - ys[6]; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; return result; case 6: result = *(int32_t*)xs - *(int32_t*)ys; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; return result; case 5: result = *(int32_t*)xs - *(int32_t*)ys; result |= xs[4] - ys[4]; return result; case 4: return *(int32_t*)xs - *(int32_t*)ys; case 3: result = xs[2] - ys[2]; result |= xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 2: result = xs[1] - ys[1]; result |= xs[0] - ys[0]; return result; case 1: return *xs - *ys; default: case 0: return 0; } } else { /* unaligned */ int result; while (length >= 8) { #if defined(__i386__) || defined(__x86_64__) result = ( ((int32_t)xs[3] << 24) | ((int32_t)xs[2] << 16) | ((int32_t)xs[1] << 8) | xs[0] ) - *(int32_t*)ys; result |= ( ((int32_t)xs[7] << 24) | ((int32_t)xs[6] << 16) | ((int32_t)xs[5] << 8) | xs[4] ) - *(int32_t*)(ys + 4); #else result = xs[3] - ys[3]; result |= xs[2] - ys[2]; result |= xs[1] - ys[1]; result |= xs[0] - ys[0]; result |= xs[7] - ys[7]; result |= xs[6] - ys[6]; result |= xs[5] - ys[5]; result |= xs[4] - ys[4]; #endif if (MY_PREDICT_FALSE(result)) return result; xs += 8; ys += 8; length -= 8; } result = 0; switch (length) { case 7: result |= xs[6] - ys[6]; case 6: result |= xs[5] - ys[5]; case 5: result |= xs[4] - ys[4]; case 4: result |= xs[3] - ys[3]; case 3: result |= xs[2] - ys[2]; case 2: result |= xs[1] - ys[1]; case 1: result |= xs[0] - ys[0]; return result; default: case 0: return 0; } } } MY_INLINE int strcache2_is_equal (struct strcache2 *cache, struct strcache2_entry const *entry, const char *str, unsigned int length, unsigned int hash) { assert (!cache->case_insensitive); /* the simple stuff first. */ if ( entry->hash != hash || entry->length != length) return 0; #if 0 return memcmp (str, entry + 1, length) == 0; #elif 1 return strcache2_memcmp_inlined (str, (const char *)(entry + 1), length) == 0; #else return strcache2_memcmp_inline_short (str, (const char *)(entry + 1), length) == 0; #endif } MY_INLINE int strcache2_is_iequal (struct strcache2 *cache, struct strcache2_entry const *entry, const char *str, unsigned int length, unsigned int hash) { assert (cache->case_insensitive); /* the simple stuff first. */ if ( entry->hash != hash || entry->length != length) return 0; #if defined(_MSC_VER) || defined(__OS2__) return _memicmp (entry + 1, str, length) == 0; #else return strncasecmp ((const char *)(entry + 1), str, length) == 0; #endif } static void strcache2_rehash (struct strcache2 *cache) { unsigned int src = cache->hash_size; struct strcache2_entry **src_tab = cache->hash_tab; struct strcache2_entry **dst_tab; #ifndef STRCACHE2_USE_MASK unsigned int hash_shift; #endif /* Allocate a new hash table twice the size of the current. */ cache->hash_size <<= 1; #ifdef STRCACHE2_USE_MASK cache->hash_mask <<= 1; cache->hash_mask |= 1; #else for (hash_shift = 1; (1U << hash_shift) < cache->hash_size; hash_shift++) /* nothing */; cache->hash_div = strcache2_find_prime (hash_shift); #endif cache->rehash_count <<= 1; cache->hash_tab = dst_tab = (struct strcache2_entry **) xmalloc (cache->hash_size * sizeof (struct strcache2_entry *)); memset (dst_tab, '\0', cache->hash_size * sizeof (struct strcache2_entry *)); /* Copy the entries from the old to the new hash table. */ cache->collision_count = 0; while (src-- > 0) { struct strcache2_entry *entry = src_tab[src]; while (entry) { struct strcache2_entry *next = entry->next; unsigned int dst = STRCACHE2_MOD_IT (cache, entry->hash); if ((entry->next = dst_tab[dst]) != 0) cache->collision_count++; dst_tab[dst] = entry; entry = next; } } /* That's it, just free the old table and we're done. */ free (src_tab); } static struct strcache2_seg * strcache2_new_seg (struct strcache2 *cache, unsigned int minlen) { struct strcache2_seg *seg; size_t size; size_t off; size = cache->def_seg_size; if (size < (size_t)minlen + sizeof (struct strcache2_seg) + STRCACHE2_ENTRY_ALIGNMENT) { size = (size_t)minlen * 2; size = (size + 0xfff) & ~(size_t)0xfff; } seg = xmalloc (size); seg->start = (char *)(seg + 1); seg->size = size - sizeof (struct strcache2_seg); off = (size_t)seg->start & (STRCACHE2_ENTRY_ALIGNMENT - 1); if (off) { off = STRCACHE2_ENTRY_ALIGNMENT - off; seg->start += off; seg->size -= off; } assert (seg->size > minlen); seg->cursor = seg->start; seg->avail = seg->size; seg->next = cache->seg_head; cache->seg_head = seg; return seg; } /* Internal worker that enters a new string into the cache. */ static const char * strcache2_enter_string (struct strcache2 *cache, unsigned int idx, const char *str, unsigned int length, unsigned int hash) { struct strcache2_entry *entry; struct strcache2_seg *seg; unsigned int size; char *str_copy; /* Allocate space for the string. */ size = length + 1 + sizeof (struct strcache2_entry); size = (size + STRCACHE2_ENTRY_ALIGNMENT - 1) & ~(STRCACHE2_ENTRY_ALIGNMENT - 1U); seg = cache->seg_head; if (MY_PREDICT_FALSE(seg->avail < size)) { do seg = seg->next; while (seg && seg->avail < size); if (!seg) seg = strcache2_new_seg (cache, size); } entry = (struct strcache2_entry *) seg->cursor; assert (!((size_t)entry & (STRCACHE2_ENTRY_ALIGNMENT - 1))); seg->cursor += size; seg->avail -= size; /* Setup the entry, copy the string and insert it into the hash table. */ entry->user = NULL; entry->length = length; entry->hash = hash; str_copy = (char *) memcpy (entry + 1, str, length); str_copy[length] = '\0'; if ((entry->next = cache->hash_tab[idx]) != 0) cache->collision_count++; cache->hash_tab[idx] = entry; cache->count++; if (cache->count >= cache->rehash_count) strcache2_rehash (cache); return str_copy; } /* The public add string interface. */ const char * strcache2_add (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_sensitive_hash (str, length); unsigned int idx; assert (!cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public add string interface for prehashed strings. Use strcache2_hash_str to calculate the hash of a string. */ const char * strcache2_add_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash) { struct strcache2_entry const *entry; unsigned int idx; #ifndef NDEBUG unsigned correct_hash; assert (!cache->case_insensitive); assert (!memchr (str, '\0', length)); correct_hash = strcache2_case_sensitive_hash (str, length); MY_ASSERT_MSG (hash == correct_hash, ("%#x != %#x\n", hash, correct_hash)); #endif /* NDEBUG */ MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public lookup (case sensitive) string interface. */ const char * strcache2_lookup (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_sensitive_hash (str, length); unsigned int idx; assert (!cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } #if defined(HAVE_CASE_INSENSITIVE_FS) /* The public add string interface for case insensitive strings. */ const char * strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_insensitive_hash (str, length); unsigned int idx; assert (cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public add string interface for prehashed case insensitive strings. Use strcache2_hash_istr to calculate the hash of a string. */ const char * strcache2_iadd_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash) { struct strcache2_entry const *entry; unsigned int idx; #ifndef NDEBUG unsigned correct_hash; assert (cache->case_insensitive); assert (!memchr (str, '\0', length)); correct_hash = strcache2_case_insensitive_hash (str, length); MY_ASSERT_MSG (hash == correct_hash, ("%#x != %#x\n", hash, correct_hash)); #endif /* NDEBUG */ MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. If not found, enter the string at IDX. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return strcache2_enter_string (cache, idx, str, length, hash); if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } /* The public lookup (case insensitive) string interface. */ const char * strcache2_ilookup (struct strcache2 *cache, const char *str, unsigned int length) { struct strcache2_entry const *entry; unsigned int hash = strcache2_case_insensitive_hash (str, length); unsigned int idx; assert (cache->case_insensitive); assert (!memchr (str, '\0', length)); MAKE_STATS (cache->lookup_count++); /* Lookup the entry in the hash table, hoping for an early match. */ idx = STRCACHE2_MOD_IT (cache, hash); entry = cache->hash_tab[idx]; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_1st_count++); entry = entry->next; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_2nd_count++); /* Loop the rest. */ for (;;) { entry = entry->next; if (!entry) return NULL; if (strcache2_is_equal (cache, entry, str, length, hash)) return (const char *)(entry + 1); MAKE_STATS (cache->collision_3rd_count++); } /* not reached */ } #endif /* HAVE_CASE_INSENSITIVE_FS */ /* Is the given string cached? returns 1 if it is, 0 if it isn't. */ int strcache2_is_cached (struct strcache2 *cache, const char *str) { /* Check mandatory alignment first. */ if (!((size_t)str & (sizeof (void *) - 1))) { /* Check the segment list and consider the question answered if the string is within one of them. (Could check it more thoroughly...) */ struct strcache2_seg const *seg; for (seg = cache->seg_head; seg; seg = seg->next) if ((size_t)(str - seg->start) < seg->size) return 1; } return 0; } /* Verify the integrity of the specified string, returning 0 if OK. */ int strcache2_verify_entry (struct strcache2 *cache, const char *str) { struct strcache2_entry const *entry; unsigned int hash; unsigned int length; const char *end; entry = (struct strcache2_entry const *)str - 1; if ((size_t)entry & (STRCACHE2_ENTRY_ALIGNMENT - 1)) { fprintf (stderr, "strcache2[%s]: missaligned entry %p\nstring: %p=%s\n", cache->name, (void *)entry, (void *)str, str); return -1; } end = memchr (str, '\0', entry->length + 1); length = end - str; if (length != entry->length) { fprintf (stderr, "strcache2[%s]: corrupt entry %p, length: %u, expected %u;\nstring: %s\n", cache->name, (void *)entry, length, entry->length, str); return -1; } hash = cache->case_insensitive ? strcache2_case_insensitive_hash (str, entry->length) : strcache2_case_sensitive_hash (str, entry->length); if (hash != entry->hash) { fprintf (stderr, "strcache2[%s]: corrupt entry %p, hash: %x, expected %x;\nstring: %s\n", cache->name, (void *)entry, hash, entry->hash, str); return -1; } return 0; } /* Calculates the case sensitive hash values of the string. The first hash is returned, the other is put at HASH2P. */ unsigned int strcache2_hash_str (const char *str, unsigned int length, unsigned int *hash2p) { *hash2p = 1; return strcache2_case_sensitive_hash (str, length); } /* Calculates the case insensitive hash values of the string. The first hash is returned, the other is put at HASH2P. */ unsigned int strcache2_hash_istr (const char *str, unsigned int length, unsigned int *hash2p) { *hash2p = 1; return strcache2_case_insensitive_hash (str, length); } /* Initalizes a new cache. */ void strcache2_init (struct strcache2 *cache, const char *name, unsigned int size, unsigned int def_seg_size, int case_insensitive, int thread_safe) { unsigned hash_shift; assert (!thread_safe); /* calc the size as a power of two */ if (!size) hash_shift = STRCACHE2_HASH_SHIFT; else { assert (size <= (~0U / 2 + 1)); for (hash_shift = 8; (1U << hash_shift) < size; hash_shift++) /* nothing */; } /* adjust the default segment size */ if (!def_seg_size) def_seg_size = STRCACHE2_SEG_SIZE; else if (def_seg_size < sizeof (struct strcache2_seg) * 10) def_seg_size = sizeof (struct strcache2_seg) * 10; else if ((def_seg_size & 0xfff) < 0xf00) def_seg_size = ((def_seg_size + 0xfff) & ~0xfffU); /* init the structure. */ cache->case_insensitive = case_insensitive; #ifdef STRCACHE2_USE_MASK cache->hash_mask = (1U << hash_shift) - 1U; #else cache->hash_div = strcache2_find_prime(hash_shift); #endif cache->count = 0; cache->collision_count = 0; cache->lookup_count = 0; cache->collision_1st_count = 0; cache->collision_2nd_count = 0; cache->collision_3rd_count = 0; cache->rehash_count = (1U << hash_shift) / 4 * 3; /* rehash at 75% */ cache->init_size = 1U << hash_shift; cache->hash_size = 1U << hash_shift; cache->def_seg_size = def_seg_size; cache->lock = NULL; cache->name = name; /* allocate the hash table and first segment. */ cache->hash_tab = (struct strcache2_entry **) xmalloc (cache->init_size * sizeof (struct strcache2_entry *)); memset (cache->hash_tab, '\0', cache->init_size * sizeof (struct strcache2_entry *)); strcache2_new_seg (cache, 0); /* link it */ cache->next = strcache_head; strcache_head = cache; } /* Terminates a string cache, freeing all memory and other associated resources. */ void strcache2_term (struct strcache2 *cache) { /* unlink it */ if (strcache_head == cache) strcache_head = cache->next; else { struct strcache2 *prev = strcache_head; while (prev->next != cache) prev = prev->next; assert (prev); prev->next = cache->next; } /* free the memory segments */ do { void *free_it = cache->seg_head; cache->seg_head = cache->seg_head->next; free (free_it); } while (cache->seg_head); /* free the hash and clear the structure. */ free (cache->hash_tab); memset (cache, '\0', sizeof (struct strcache2)); } /* Print statistics a string cache. */ void strcache2_print_stats (struct strcache2 *cache, const char *prefix) { unsigned int seg_count = 0; unsigned long seg_total_bytes = 0; unsigned long seg_avg_bytes; unsigned long seg_avail_bytes = 0; unsigned long seg_max_bytes = 0; struct strcache2_seg *seg; unsigned int str_count = 0; unsigned long str_total_len = 0; unsigned int str_avg_len; unsigned int str_min_len = ~0U; unsigned int str_max_len = 0; unsigned int idx; unsigned int rehashes; unsigned int chain_depths[32]; printf (_("\n%s strcache2: %s\n"), prefix, cache->name); /* Segment statistics. */ for (seg = cache->seg_head; seg; seg = seg->next) { seg_count++; seg_total_bytes += seg->size; seg_avail_bytes += seg->avail; if (seg->size > seg_max_bytes) seg_max_bytes = seg->size; } seg_avg_bytes = seg_total_bytes / seg_count; printf (_("%s %u segments: total = %lu / max = %lu / avg = %lu / def = %u avail = %lu\n"), prefix, seg_count, seg_total_bytes, seg_max_bytes, seg_avg_bytes, cache->def_seg_size, seg_avail_bytes); /* String statistics. */ memset (chain_depths, '\0', sizeof (chain_depths)); idx = cache->hash_size; while (idx-- > 0) { struct strcache2_entry const *entry = cache->hash_tab[idx]; unsigned int depth = 0; for (; entry != 0; entry = entry->next, depth++) { unsigned int length = entry->length; str_total_len += length; if (length > str_max_len) str_max_len = length; if (length < str_min_len) str_min_len = length; str_count++; } chain_depths[depth >= 32 ? 31 : depth]++; } str_avg_len = cache->count ? str_total_len / cache->count : 0; printf (_("%s %u strings: total len = %lu / max = %u / avg = %u / min = %u\n"), prefix, cache->count, str_total_len, str_max_len, str_avg_len, str_min_len); if (str_count != cache->count) printf (_("%s string count mismatch! cache->count=%u, actual count is %u\n"), prefix, cache->count, str_count); /* Hash statistics. */ idx = cache->init_size; rehashes = 0; while (idx < cache->hash_size) { idx *= 2; rehashes++; } #ifdef STRCACHE2_USE_MASK printf (_("%s hash size = %u mask = %#x rehashed %u times"), prefix, cache->hash_size, cache->hash_mask, rehashes); #else printf (_("%s hash size = %u div = %#x rehashed %u times"), prefix, cache->hash_size, cache->hash_div, rehashes); #endif if (cache->lookup_count) printf (_("%s lookups = %lu\n" "%s hash collisions 1st = %lu (%u%%) 2nd = %lu (%u%%) 3rd = %lu (%u%%)"), prefix, cache->lookup_count, prefix, cache->collision_1st_count, (unsigned int)((100.0 * cache->collision_1st_count) / cache->lookup_count), cache->collision_2nd_count, (unsigned int)((100.0 * cache->collision_2nd_count) / cache->lookup_count), cache->collision_3rd_count, (unsigned int)((100.0 * cache->collision_3rd_count) / cache->lookup_count)); printf (_("\n%s hash insert collisions = %u (%u%%)\n"), prefix, cache->collision_count,(unsigned int)((100.0 * cache->collision_count) / cache->count)); printf (_("%s %5u (%u%%) empty hash table slots\n"), prefix, chain_depths[0], (unsigned int)((100.0 * chain_depths[0]) / cache->hash_size)); printf (_("%s %5u (%u%%) occupied hash table slots\n"), prefix, chain_depths[1], (unsigned int)((100.0 * chain_depths[1]) / cache->hash_size)); for (idx = 2; idx < 32; idx++) { unsigned strs_at_this_depth = chain_depths[idx]; unsigned i; for (i = idx + 1; i < 32; i++) strs_at_this_depth += chain_depths[i]; if (strs_at_this_depth) printf (_("%s %5u (%2u%%) with %u string%s chained on; %5u (%2u%%) strings at depth %u.\n"), prefix, chain_depths[idx], (unsigned int)((100.0 * chain_depths[idx]) / (cache->count - cache->collision_count)), idx - 1, idx == 2 ? " " : "s", strs_at_this_depth, (unsigned int)((100.0 * strs_at_this_depth) / cache->count), idx - 1); } } /* Print statistics for all string caches. */ void strcache2_print_stats_all (const char *prefix) { struct strcache2 *cur; for (cur = strcache_head; cur; cur = cur->next) strcache2_print_stats (cur, prefix); } kbuild-2695/src/kmk/config.h.win0000644000000000000000000003777512247157306015246 0ustar rootroot/* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Suppress some Visual C++ warnings. Maybe after the code cleanup for ISO C we can remove some/all of these. */ #if _MSC_VER > 1000 # pragma warning(disable:4100) /* unreferenced formal parameter */ # pragma warning(disable:4102) /* unreferenced label */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4131) /* uses old-style declarator */ # pragma warning(disable:4702) /* unreachable code */ #endif /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using `getloadavg.c'. */ /*#define C_GETLOADAVG 1*/ /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 0 /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Define to 1 if you have the `bsd_signal' function. */ /* #undef HAVE_BSD_SIGNAL */ /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define if you have the clock_gettime function. */ /* #undef HAVE_CLOCK_GETTIME */ /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file, and it defines getcwd() and chdir(). */ #if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__INTERIX) # define HAVE_DIRECT_H 1 #endif /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Use platform specific coding */ #define HAVE_DOS_PATHS 1 /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fdopen' function. */ /*#define HAVE_FDOPEN 1*/ /* Define to 1 if you have the `fork' function. */ /* #undef HAVE_FORK */ /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getgroups' function. */ /* #undef HAVE_GETGROUPS */ /* Define to 1 if you have the `gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the `gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the `getloadavg' function. */ /* #undef HAVE_GETLOADAVG */ /* Define to 1 if you have the `getrlimit' function. */ /* #undef HAVE_GETRLIMIT */ /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define if you have a standard gettimeofday function */ /* #undef HAVE_GETTIMEOFDAY */ /* Define if you have the iconv() function. */ /* #undef HAVE_ICONV */ /* Define to 1 if you have the header file. */ /*#define HAVE_INTTYPES_H 1*/ /* Define to 1 if you have the `dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the `kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkstemp' function. */ /* #undef HAVE_MKSTEMP */ /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the `pipe' function. */ /* #undef HAVE_PIPE */ /* Define to 1 if you have the `pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the `realpath' function. */ /* #undef HAVE_REALPATH */ /* Define if defines the SA_RESTART constant. */ /* #undef HAVE_SA_RESTART */ /* Define to 1 if you have the `setegid' function. */ /* #undef HAVE_SETEGID */ /* Define to 1 if you have the `seteuid' function. */ /* #undef HAVE_SETEUID */ /* Define to 1 if you have the `setlinebuf' function. */ /* #undef HAVE_SETLINEBUF */ /* Define to 1 if you have the `setlocale' function. */ /*#define HAVE_SETLOCALE 1*/ /* Define to 1 if you have the `setregid' function. */ /* #undef HAVE_SETREGID */ /* Define to 1 if you have the `setreuid' function. */ /* #undef HAVE_SETREUID */ /* Define to 1 if you have the `setrlimit' function. */ /* #undef HAVE_SETRLIMIT */ /* Define to 1 if you have the `setvbuf' function. */ /*#define HAVE_SETVBUF 1 */ /* Define to 1 if you have the `sigaction' function. */ /* #undef HAVE_SIGACTION */ /* Define to 1 if you have the `sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the `socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ /*#define HAVE_STDINT_H 1*/ /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ /* #undef HAVE_STRCASECMP */ /* Define to 1 if you have the `strcmpi' function. */ #define HAVE_STRCMPI 1 /* Define to 1 if you have the `stricmp' function. */ /* #undef HAVE_STRICMP */ /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* bird */ /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ /* #define HAVE_STRINGS_H 1 */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strsignal' function. */ /* #undef HAVE_STRSIGNAL */ /* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_DIR_H */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ /* #define HAVE_SYS_PARAM_H 1 */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_RESOURCE_H */ /* Define to 1 if you have the header file. */ /* #define HAVE_SYS_STAT_H 1 */ /* Define to 1 if you have the header file. */ /*#define HAVE_SYS_TIMEB_H 1*/ /* Define to 1 if you have the header file. */ /*#define HAVE_SYS_TIME_H 1*/ /* Define to 1 if you have the header file. */ /*#define HAVE_SYS_TYPES_H 1*/ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_WAIT_H */ /* Define this if you have the \`union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ /* #define HAVE_UNISTD_H 1*/ /* Define to 1 if you have the header file. */ /* #undef HAVE_VARARGS_H */ /* Define to 1 if you have the `vfork' function. */ /* #undef HAVE_VFORK */ /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the `wait3' function. */ /* #undef HAVE_WAIT3 */ /* Define to 1 if you have the `waitpid' function. */ /* #undef HAVE_WAITPID */ /* Define to 1 if `fork' works. */ /* #undef HAVE_WORKING_FORK */ /* Define to 1 if `vfork' works. */ /* #undef HAVE_WORKING_VFORK */ /* Build host information. (not used by kmk) */ #define MAKE_HOST "Windows32" /* Define this to enable job server support in GNU make. */ /* #undef MAKE_JOBSERVER */ /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of this package (needed by automake) */ #define PACKAGE "make" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-make@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ #define PACKAGE_VERSION "3.82" /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "echo no sccs get" /* Define this if the SCCS 'get' command understands the '-G' option. */ /* #undef SCCS_GET_MINUS_G */ /* Define to 1 if the `setvbuf' function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ /* #undef SETVBUF_REVERSED */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ /* #undef ST_MTIM_NSEC */ /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ /* #define TIME_WITH_SYS_TIME 1 */ /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "3.82" /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ #define _POSIX_SOURCE 1 /* Define like PROTOTYPES; this can be used by system headers. */ /*#define __PROTOTYPES 1*/ /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `int' if doesn't define. */ #define gid_t int /* Define to `int' if does not define. */ #define pid_t int /* Define to `int' if doesn't define. */ #define uid_t int /* Define uintmax_t if not defined in or . */ #if 0 #define uintmax_t unsigned long #else #define uintmax_t unsigned __int64 #endif /* Define as `fork' if `vfork' does not work. */ /*#define vfork fork*/ #if 0/* see above */ /* Define to `unsigned long' or `unsigned long long' if doesn't define. */ #define uintmax_t unsigned long #endif /* Define if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define if your struct stat has st_rdev. */ #undef HAVE_ST_RDEV #define HAVE_ST_RDEV 1 /* Define if you have the strftime function. */ #undef HAVE_STRFTIME #define HAVE_STRFTIME 1 /* Define if you have that is POSIX.1 compatible. */ /* #undef HAVE_SYS_WAIT_H */ /* Define if your struct tm has tm_zone. */ /* #undef HAVE_TM_ZONE */ /* Define if you don't have tm_zone but do have the external array tzname. */ #undef HAVE_TZNAME #define HAVE_TZNAME 1 /* Define if utime(file, NULL) sets file's timestamp to the present. */ #undef HAVE_UTIME_NULL #define HAVE_UTIME_NULL 1 /* Define to the installation directory for locales. */ #define LOCALEDIR "" /* * Refer to README.W32 for info on the following settings */ /* * If you have a shell that does not grok 'sh -c quoted-command-line' * correctly, you need this setting. Please see below for specific * shell support. */ /*#define BATCH_MODE_ONLY_SHELL 1 */ /* * Define if you have the Cygnus "Cygwin" GNU Windows32 tool set. * Do NOT define BATCH_MODE_ONLY_SHELL if you define HAVE_CYGWIN_SHELL */ /*#define HAVE_CYGWIN_SHELL 1 */ /* * Define if you have the MKS tool set or shell. Do NOT define * BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL */ /*#define HAVE_MKS_SHELL 1 */ /* * Enforce the mutual exclusivity restriction. */ #ifdef HAVE_MKS_SHELL #undef BATCH_MODE_ONLY_SHELL #endif #ifdef HAVE_CYGWIN_SHELL #undef BATCH_MODE_ONLY_SHELL #endif /* bird hacks - similar in mscfakes.h */ #include #include #include #ifndef STAT_REDEFINED_ALREADY # define STAT_REDEFINED_ALREADY # undef stat # define stat(_path, _st) bird_w32_stat(_path, _st) extern int bird_w32_stat(const char *, struct stat *); #endif /* cygwin sucks to much in one end or the other. */ #define BATCH_MODE_ONLY_SHELL #include "inlined_memchr.h" #ifdef CONFIG_WITH_FAST_IS_SPACE # include # if _MSC_VER >= 1400 # include # pragma intrinsic(_bittest) # pragma intrinsic(_bittestandset) # define space_map_size 32 # define set_space_map_entry(ch) _bittestandset((long *)&space_map[0], (unsigned char)(ch)) # define isspace(ch) _bittest((long *)&space_map[0], (unsigned char)(ch)) # else # define space_map_size 256 # define set_space_map_entry(ch) (space_map[(unsigned char)(ch)] = 1) # define isspace(ch) (space_map[(unsigned char)(ch)]) # endif extern char space_map[space_map_size]; #endif kbuild-2695/src/kmk/filedef.h0000644000000000000000000002472512247157306014572 0ustar rootroot/* Definition of target file data structures for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Structure that represents the info on one file that the makefile says how to make. All of these are chained together through `next'. */ #include "hash.h" struct file { const char *name; const char *hname; /* Hashed filename */ const char *vpath; /* VPATH/vpath pathname */ struct dep *deps; /* all dependencies, including duplicates */ #ifdef CONFIG_WITH_LAZY_DEPS_VARS struct dep *deps_no_dupes; /* dependencies without duplicates, created on demaned by func_deps. */ #endif struct commands *cmds; /* Commands to execute for this target. */ int command_flags; /* Flags OR'd in for cmds; see commands.h. */ const char *stem; /* Implicit stem, if an implicit rule has been used */ struct dep *also_make; /* Targets that are made by making this. */ FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */ FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating has been performed. */ struct file *prev; /* Previous entry for same file name; used when there are multiple double-colon entries for the same file. */ struct file *last; /* Last entry for the same file name. */ /* File that this file was renamed to. After any time that a file could be renamed, call `check_renamed' (below). */ struct file *renamed; /* List of variable sets used for this file. */ struct variable_set_list *variables; /* Pattern-specific variable reference for this target, or null if there isn't one. Also see the pat_searched flag, below. */ struct variable_set_list *pat_variables; /* Immediate dependent that caused this target to be remade, or nil if there isn't one. */ struct file *parent; /* For a double-colon entry, this is the first double-colon entry for the same file. Otherwise this is null. */ struct file *double_colon; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* For a target of an explicit multi target rule, this points to the primary target. Otherwise this is null. */ struct file *multi_head; /* Pointer to next target of an explicit multi target rule. */ struct file *multi_next; #endif short int update_status; /* Status of the last attempt to update, or -1 if none has been made. */ enum cmd_state /* State of the commands. */ { /* Note: It is important that cs_not_started be zero. */ cs_not_started, /* Not yet started. */ cs_deps_running, /* Dep commands running. */ cs_running, /* Commands running. */ cs_finished /* Commands finished. */ } command_state ENUM_BITFIELD (2); unsigned int precious:1; /* Non-0 means don't delete file on quit */ unsigned int low_resolution_time:1; /* Nonzero if this file's time stamp has only one-second resolution. */ unsigned int tried_implicit:1; /* Nonzero if have searched for implicit rule for making this file; don't search again. */ unsigned int updating:1; /* Nonzero while updating deps of this file */ unsigned int updated:1; /* Nonzero if this file has been remade. */ unsigned int is_target:1; /* Nonzero if file is described as target. */ unsigned int cmd_target:1; /* Nonzero if file was given on cmd line. */ unsigned int phony:1; /* Nonzero if this is a phony file i.e., a prerequisite of .PHONY. */ unsigned int intermediate:1;/* Nonzero if this is an intermediate file. */ unsigned int secondary:1; /* Nonzero means remove_intermediates should not delete it. */ unsigned int dontcare:1; /* Nonzero if no complaint is to be made if this target cannot be remade. */ unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name. */ unsigned int pat_searched:1;/* Nonzero if we already searched for pattern-specific variables. */ unsigned int considered:1; /* equal to 'considered' if file has been considered on current scan of goal chain */ unsigned int no_diag:1; /* True if the file failed to update and no diagnostics has been issued (dontcare). */ #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET unsigned int multi_maybe:1; /* Nonzero if this file isn't always updated by the explicit multi target rule. */ #endif #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION unsigned int need_2nd_target_expansion:1; /* Nonzero if this file needs second expansion of its name. Whether it can receive this is decided at parse time, and the expanding done in snap_deps. */ #endif }; extern struct file *suffix_file, *default_file; struct file *lookup_file (const char *name); #ifdef CONFIG_WITH_STRCACHE2 struct file *lookup_file_cached (const char *name); #endif struct file *enter_file (const char *name); struct dep *split_prereqs (char *prereqstr); struct dep *enter_prereqs (struct dep *prereqs, const char *stem); void remove_intermediates (int sig); void snap_deps (void); void rename_file (struct file *file, const char *name); void rehash_file (struct file *file, const char *name); void set_command_state (struct file *file, enum cmd_state state); void notice_finished_file (struct file *file); void init_hash_files (void); char *build_target_list (char *old_list); void print_prereqs (const struct dep *deps); void print_file_data_base (void); #if FILE_TIMESTAMP_HI_RES # define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ file_timestamp_cons (fname, (st).st_mtime, (st).st_mtim.ST_MTIM_NSEC) #else # define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ file_timestamp_cons (fname, (st).st_mtime, 0) #endif /* If FILE_TIMESTAMP is 64 bits (or more), use nanosecond resolution. (Multiply by 2**30 instead of by 10**9 to save time at the cost of slightly decreasing the number of available timestamps.) With 64-bit FILE_TIMESTAMP, this stops working on 2514-05-30 01:53:04 UTC, but by then uintmax_t should be larger than 64 bits. */ #define FILE_TIMESTAMPS_PER_S (FILE_TIMESTAMP_HI_RES ? 1000000000 : 1) #define FILE_TIMESTAMP_LO_BITS (FILE_TIMESTAMP_HI_RES ? 30 : 0) #define FILE_TIMESTAMP_S(ts) (((ts) - ORDINARY_MTIME_MIN) \ >> FILE_TIMESTAMP_LO_BITS) #define FILE_TIMESTAMP_NS(ts) ((int) (((ts) - ORDINARY_MTIME_MIN) \ & ((1 << FILE_TIMESTAMP_LO_BITS) - 1))) /* Upper bound on length of string "YYYY-MM-DD HH:MM:SS.NNNNNNNNN" representing a file timestamp. The upper bound is not necessarily 19, since the year might be less than -999 or greater than 9999. Subtract one for the sign bit if in case file timestamps can be negative; subtract FLOOR_LOG2_SECONDS_PER_YEAR to yield an upper bound on how many file timestamp bits might affect the year; 302 / 1000 is log10 (2) rounded up; add one for integer division truncation; add one more for a minus sign if file timestamps can be negative; add 4 to allow for any 4-digit epoch year (e.g. 1970); add 25 to allow for "-MM-DD HH:MM:SS.NNNNNNNNN". */ #define FLOOR_LOG2_SECONDS_PER_YEAR 24 #define FILE_TIMESTAMP_PRINT_LEN_BOUND \ (((sizeof (FILE_TIMESTAMP) * CHAR_BIT - 1 - FLOOR_LOG2_SECONDS_PER_YEAR) \ * 302 / 1000) \ + 1 + 1 + 4 + 25) FILE_TIMESTAMP file_timestamp_cons (char const *, time_t, int); FILE_TIMESTAMP file_timestamp_now (int *); void file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts); /* Return the mtime of file F (a struct file *), caching it. The value is NONEXISTENT_MTIME if the file does not exist. */ #define file_mtime(f) file_mtime_1 ((f), 1) /* Return the mtime of file F (a struct file *), caching it. Don't search using vpath for the file--if it doesn't actually exist, we don't find it. The value is NONEXISTENT_MTIME if the file does not exist. */ #define file_mtime_no_search(f) file_mtime_1 ((f), 0) FILE_TIMESTAMP f_mtime (struct file *file, int search); #define file_mtime_1(f, v) \ ((f)->last_mtime == UNKNOWN_MTIME ? f_mtime ((f), v) : (f)->last_mtime) /* Special timestamp values. */ /* The file's timestamp is not yet known. */ #define UNKNOWN_MTIME 0 /* The file does not exist. */ #define NONEXISTENT_MTIME 1 /* The file does not exist, and we assume that it is older than any actual file. */ #define OLD_MTIME 2 /* The smallest and largest ordinary timestamps. */ #define ORDINARY_MTIME_MIN (OLD_MTIME + 1) #if FILE_TIMESTAMP_HI_RES == 0 /* bird: shut up annoying warnings! ASSUMES: unsigned FILE_TIMESTAMP ++. */ # define ORDINARY_MTIME_MAX ( ~ (FILE_TIMESTAMP) 0 ) #else #define ORDINARY_MTIME_MAX ((FILE_TIMESTAMP_S (NEW_MTIME) \ << FILE_TIMESTAMP_LO_BITS) \ + ORDINARY_MTIME_MIN + FILE_TIMESTAMPS_PER_S - 1) #endif /* Modtime value to use for `infinitely new'. We used to get the current time from the system and use that whenever we wanted `new'. But that causes trouble when the machine running make and the machine holding a file have different ideas about what time it is; and can also lose for `force' targets, which need to be considered newer than anything that depends on them, even if said dependents' modtimes are in the future. */ #if 1 /* bird: ASSUME the type is unsigned and the wrath of a pedantic gcc. */ # define NEW_MTIME ( ~ (FILE_TIMESTAMP) 0 ) #else #define NEW_MTIME INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) #endif #define check_renamed(file) \ while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here. */ /* Have we snapped deps yet? */ extern int snapped_deps; kbuild-2695/src/kmk/main.c0000644000000000000000000034751512247157306014120 0ustar rootroot/* Argument parsing and main program of GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #include "dep.h" #include "filedef.h" #include "variable.h" #include "job.h" #include "commands.h" #include "rule.h" #include "debug.h" #include "getopt.h" #ifdef KMK # include "kbuild.h" #endif #include #ifdef _AMIGA # include # include #endif #ifdef WINDOWS32 #include #include #include "pathstuff.h" #endif #ifdef __EMX__ # include # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifdef KMK /* for get_online_cpu_count */ # if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # include # endif # ifdef __OS2__ # define INCL_BASE # include # endif # ifdef __HAIKU__ # include # endif #endif /* KMK*/ #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) # define SET_STACK_SIZE #endif #ifdef SET_STACK_SIZE # include #endif #ifdef _AMIGA int __stack = 20000; /* Make sure we have 20K of stack space */ #endif void init_dir (void); void remote_setup (void); void remote_cleanup (void); RETSIGTYPE fatal_error_signal (int sig); void print_variable_data_base (void); void print_dir_data_base (void); void print_rule_data_base (void); void print_vpath_data_base (void); void verify_file_data_base (void); #ifdef CONFIG_WITH_PRINT_STATS_SWITCH void print_variable_stats (void); void print_file_stats (void); #endif #if defined HAVE_WAITPID || defined HAVE_WAIT3 # define HAVE_WAIT_NOHANG #endif #if !defined(HAVE_UNISTD_H) && !defined(_MSC_VER) /* bird */ int chdir (); #endif #ifndef STDC_HEADERS # ifndef sun /* Sun has an incorrect decl in a header. */ void exit (int) __attribute__ ((noreturn)); # endif double atof (); #endif static void clean_jobserver (int status); static void print_data_base (void); static void print_version (void); static void decode_switches (int argc, char **argv, int env); static void decode_env_switches (char *envar, unsigned int len); static const char *define_makeflags (int all, int makefile); static char *quote_for_env (char *out, const char *in); static void initialize_global_hash_tables (void); /* The structure that describes an accepted command switch. */ struct command_switch { int c; /* The switch character. */ enum /* Type of the value. */ { flag, /* Turn int flag on. */ flag_off, /* Turn int flag off. */ string, /* One string per switch. */ filename, /* A string containing a file name. */ positive_int, /* A positive integer. */ floating, /* A floating-point number (double). */ ignore /* Ignored. */ } type; void *value_ptr; /* Pointer to the value-holding variable. */ unsigned int env:1; /* Can come from MAKEFLAGS. */ unsigned int toenv:1; /* Should be put in MAKEFLAGS. */ unsigned int no_makefile:1; /* Don't propagate when remaking makefiles. */ const void *noarg_value; /* Pointer to value used if no arg given. */ const void *default_value; /* Pointer to default value. */ char *long_name; /* Long option name. */ }; /* True if C is a switch value that corresponds to a short option. */ #define short_option(c) ((c) <= CHAR_MAX) /* The structure used to hold the list of strings given in command switches of a type that takes string arguments. */ struct stringlist { const char **list; /* Nil-terminated list of strings. */ unsigned int idx; /* Index into above. */ unsigned int max; /* Number of pointers allocated. */ }; /* The recognized command switches. */ /* Nonzero means do not print commands to be executed (-s). */ int silent_flag; /* Nonzero means just touch the files that would appear to need remaking (-t) */ int touch_flag; /* Nonzero means just print what commands would need to be executed, don't actually execute them (-n). */ int just_print_flag; #ifdef CONFIG_PRETTY_COMMAND_PRINTING /* Nonzero means to print commands argument for argument skipping blanks. */ int pretty_command_printing; #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH /* Nonzero means to print internal statistics before exiting. */ int print_stats_flag; #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH /* Minimum number of seconds to report, -1 if disabled. */ int print_time_min = -1; static int default_print_time_min = -1; static int no_val_print_time_min = 0; static big_int make_start_ts = -1; int print_time_width = 5; #endif /* Print debugging info (--debug). */ static struct stringlist *db_flags; static int debug_flag = 0; int db_level = 0; /* Output level (--verbosity). */ static struct stringlist *verbosity_flags; #ifdef WINDOWS32 /* Suspend make in main for a short time to allow debugger to attach */ int suspend_flag = 0; #endif /* Environment variables override makefile definitions. */ int env_overrides = 0; /* Nonzero means ignore status codes returned by commands executed to remake files. Just treat them all as successful (-i). */ int ignore_errors_flag = 0; /* Nonzero means don't remake anything, just print the data base that results from reading the makefile (-p). */ int print_data_base_flag = 0; /* Nonzero means don't remake anything; just return a nonzero status if the specified targets are not up to date (-q). */ int question_flag = 0; /* Nonzero means do not use any of the builtin rules (-r) / variables (-R). */ int no_builtin_rules_flag = 0; int no_builtin_variables_flag = 0; /* Nonzero means keep going even if remaking some file fails (-k). */ int keep_going_flag; int default_keep_going_flag = 0; /* Nonzero means check symlink mtimes. */ int check_symlink_flag = 0; /* Nonzero means print directory before starting and when done (-w). */ int print_directory_flag = 0; /* Nonzero means ignore print_directory_flag and never print the directory. This is necessary because print_directory_flag is set implicitly. */ int inhibit_print_directory_flag = 0; /* Nonzero means print version information. */ int print_version_flag = 0; /* List of makefiles given with -f switches. */ static struct stringlist *makefiles = 0; /* Size of the stack when we started. */ #ifdef SET_STACK_SIZE struct rlimit stack_limit; #endif /* Number of job slots (commands that can be run at once). */ unsigned int job_slots = 1; unsigned int default_job_slots = 1; static unsigned int master_job_slots = 0; /* Value of job_slots that means no limit. */ static unsigned int inf_jobs = 0; /* File descriptors for the jobs pipe. */ static struct stringlist *jobserver_fds = 0; int job_fds[2] = { -1, -1 }; int job_rfd = -1; /* Maximum load average at which multiple jobs will be run. Negative values mean unlimited, while zero means limit to zero load (which could be useful to start infinite jobs remotely but one at a time locally). */ #ifndef NO_FLOAT double max_load_average = -1.0; double default_load_average = -1.0; #else int max_load_average = -1; int default_load_average = -1; #endif /* List of directories given with -C switches. */ static struct stringlist *directories = 0; /* List of include directories given with -I switches. */ static struct stringlist *include_directories = 0; /* List of files given with -o switches. */ static struct stringlist *old_files = 0; /* List of files given with -W switches. */ static struct stringlist *new_files = 0; /* List of strings to be eval'd. */ static struct stringlist *eval_strings = 0; /* If nonzero, we should just print usage and exit. */ static int print_usage_flag = 0; /* If nonzero, we should print a warning message for each reference to an undefined variable. */ int warn_undefined_variables_flag; /* If nonzero, always build all targets, regardless of whether they appear out of date or not. */ static int always_make_set = 0; int always_make_flag = 0; /* If nonzero, we're in the "try to rebuild makefiles" phase. */ int rebuilding_makefiles = 0; /* Remember the original value of the SHELL variable, from the environment. */ struct variable shell_var; /* This character introduces a command: it's the first char on the line. */ char cmd_prefix = '\t'; #ifdef KMK /* Process priority. 0 = no change; 1 = idle / max nice; 2 = below normal / nice 10; 3 = normal / nice 0; 4 = high / nice -10; 5 = realtime / nice -19; */ int process_priority = 0; /* Process affinity mask; 0 means any CPU. */ int process_affinity = 0; #endif /* KMK */ #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) /* When set, we'll gather expensive statistics like for the heap. */ int make_expensive_statistics = 0; #endif /* The usage output. We write it this way to make life easier for the translators, especially those trying to translate to right-to-left languages like Hebrew. */ static const char *const usage[] = { N_("Options:\n"), N_("\ -b, -m Ignored for compatibility.\n"), N_("\ -B, --always-make Unconditionally make all targets.\n"), N_("\ -C DIRECTORY, --directory=DIRECTORY\n\ Change to DIRECTORY before doing anything.\n"), N_("\ -d Print lots of debugging information.\n"), N_("\ --debug[=FLAGS] Print various types of debugging information.\n"), N_("\ -e, --environment-overrides\n\ Environment variables override makefiles.\n"), N_("\ --eval=STRING Evaluate STRING as a makefile statement.\n"), N_("\ -f FILE, --file=FILE, --makefile=FILE\n\ Read FILE as a makefile.\n"), N_("\ -h, --help Print this message and exit.\n"), N_("\ -i, --ignore-errors Ignore errors from recipes.\n"), N_("\ -I DIRECTORY, --include-dir=DIRECTORY\n\ Search DIRECTORY for included makefiles.\n"), #ifdef KMK N_("\ -j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg.\n\ The default is the number of active CPUs.\n"), #else N_("\ -j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg.\n"), #endif N_("\ -k, --keep-going Keep going when some targets can't be made.\n"), N_("\ -l [N], --load-average[=N], --max-load[=N]\n\ Don't start multiple jobs unless load is below N.\n"), N_("\ -L, --check-symlink-times Use the latest mtime between symlinks and target.\n"), N_("\ -n, --just-print, --dry-run, --recon\n\ Don't actually run any recipe; just print them.\n"), N_("\ -o FILE, --old-file=FILE, --assume-old=FILE\n\ Consider FILE to be very old and don't remake it.\n"), N_("\ -p, --print-data-base Print make's internal database.\n"), N_("\ -q, --question Run no recipe; exit status says if up to date.\n"), N_("\ -r, --no-builtin-rules Disable the built-in implicit rules.\n"), N_("\ -R, --no-builtin-variables Disable the built-in variable settings.\n"), N_("\ -s, --silent, --quiet Don't echo recipes.\n"), N_("\ -S, --no-keep-going, --stop\n\ Turns off -k.\n"), N_("\ -t, --touch Touch targets instead of remaking them.\n"), N_("\ -v, --version Print the version number of make and exit.\n"), N_("\ -w, --print-directory Print the current directory.\n"), N_("\ --no-print-directory Turn off -w, even if it was turned on implicitly.\n"), N_("\ -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE\n\ Consider FILE to be infinitely new.\n"), N_("\ --warn-undefined-variables Warn when an undefined variable is referenced.\n"), #ifdef KMK N_("\ --affinity=mask Sets the CPU affinity on some hosts.\n"), N_("\ --priority=1-5 Sets the process priority / nice level:\n\ 1 = idle / max nice;\n\ 2 = below normal / nice 10;\n\ 3 = normal / nice 0;\n\ 4 = high / nice -10;\n\ 5 = realtime / nice -19;\n"), #endif /* KMK */ #ifdef CONFIG_PRETTY_COMMAND_PRINTING N_("\ --pretty-command-printing Makes the command echo easier to read.\n"), #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH N_("\ --print-stats Print make statistics.\n"), #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH N_("\ --print-time[=MIN-SEC] Print file build times starting at arg.\n"), #endif #ifdef CONFIG_WITH_MAKE_STATS N_("\ --statistics Gather extra statistics for $(make-stats ).\n"), #endif NULL }; /* The table of command switches. */ static const struct command_switch switches[] = { { 'b', ignore, 0, 0, 0, 0, 0, 0, 0 }, { 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make" }, { 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" }, { 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0 }, { CHAR_MAX+1, string, &db_flags, 1, 1, 0, "basic", 0, "debug" }, #ifdef WINDOWS32 { 'D', flag, &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" }, #endif { 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", }, { 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" }, { 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help" }, { 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors" }, { 'I', filename, &include_directories, 1, 1, 0, 0, 0, "include-dir" }, { 'j', positive_int, &job_slots, 1, 1, 0, &inf_jobs, &default_job_slots, "jobs" }, { CHAR_MAX+2, string, &jobserver_fds, 1, 1, 0, 0, 0, "jobserver-fds" }, { 'k', flag, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag, "keep-going" }, #ifndef NO_FLOAT { 'l', floating, &max_load_average, 1, 1, 0, &default_load_average, &default_load_average, "load-average" }, #else { 'l', positive_int, &max_load_average, 1, 1, 0, &default_load_average, &default_load_average, "load-average" }, #endif { 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times" }, { 'm', ignore, 0, 0, 0, 0, 0, 0, 0 }, { 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print" }, { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" }, { 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base" }, #ifdef CONFIG_PRETTY_COMMAND_PRINTING { CHAR_MAX+10, flag, (char *) &pretty_command_printing, 1, 1, 1, 0, 0, "pretty-command-printing" }, #endif #ifdef CONFIG_WITH_PRINT_STATS_SWITCH { CHAR_MAX+11, flag, (char *) &print_stats_flag, 1, 1, 1, 0, 0, "print-stats" }, #endif #ifdef CONFIG_WITH_PRINT_TIME_SWITCH { CHAR_MAX+12, positive_int, (char *) &print_time_min, 1, 1, 0, (char *) &no_val_print_time_min, (char *) &default_print_time_min, "print-time" }, #endif #ifdef KMK { CHAR_MAX+14, positive_int, (char *) &process_priority, 1, 1, 0, (char *) &process_priority, (char *) &process_priority, "priority" }, { CHAR_MAX+15, positive_int, (char *) &process_affinity, 1, 1, 0, (char *) &process_affinity, (char *) &process_affinity, "affinity" }, #endif { 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" }, { 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" }, { 'R', flag, &no_builtin_variables_flag, 1, 1, 0, 0, 0, "no-builtin-variables" }, { 's', flag, &silent_flag, 1, 1, 0, 0, 0, "silent" }, { 'S', flag_off, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag, "no-keep-going" }, #if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) { CHAR_MAX+16, flag, (char *) &make_expensive_statistics, 1, 1, 1, 0, 0, "statistics" }, #endif { 't', flag, &touch_flag, 1, 1, 1, 0, 0, "touch" }, { 'v', flag, &print_version_flag, 1, 1, 0, 0, 0, "version" }, { CHAR_MAX+3, string, &verbosity_flags, 1, 1, 0, 0, 0, "verbosity" }, { 'w', flag, &print_directory_flag, 1, 1, 0, 0, 0, "print-directory" }, { CHAR_MAX+4, flag, &inhibit_print_directory_flag, 1, 1, 0, 0, 0, "no-print-directory" }, { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" }, { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0, "warn-undefined-variables" }, { CHAR_MAX+6, string, &eval_strings, 1, 0, 0, 0, 0, "eval" }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; /* Secondary long names for options. */ static struct option long_option_aliases[] = { { "quiet", no_argument, 0, 's' }, { "stop", no_argument, 0, 'S' }, { "new-file", required_argument, 0, 'W' }, { "assume-new", required_argument, 0, 'W' }, { "assume-old", required_argument, 0, 'o' }, { "max-load", optional_argument, 0, 'l' }, { "dry-run", no_argument, 0, 'n' }, { "recon", no_argument, 0, 'n' }, { "makefile", required_argument, 0, 'f' }, }; /* List of goal targets. */ #ifndef KMK static #endif struct dep *goals, *lastgoal; /* List of variables which were defined on the command line (or, equivalently, in MAKEFLAGS). */ struct command_variable { struct command_variable *next; struct variable *variable; }; static struct command_variable *command_variables; /* The name we were invoked with. */ char *program; /* Our current directory before processing any -C options. */ char *directory_before_chdir; /* Our current directory after processing all -C options. */ char *starting_directory; /* Value of the MAKELEVEL variable at startup (or 0). */ unsigned int makelevel; /* Pointer to the value of the .DEFAULT_GOAL special variable. The value will be the name of the goal to remake if the command line does not override it. It can be set by the makefile, or else it's the first target defined in the makefile whose name does not start with '.'. */ struct variable * default_goal_var; /* Pointer to structure for the file .DEFAULT whose commands are used for any file that has none of its own. This is zero if the makefiles do not define .DEFAULT. */ struct file *default_file; /* Nonzero if we have seen the magic `.POSIX' target. This turns on pedantic compliance with POSIX.2. */ int posix_pedantic; /* Nonzero if we have seen the '.SECONDEXPANSION' target. This turns on secondary expansion of prerequisites. */ int second_expansion; /* Nonzero if we have seen the '.ONESHELL' target. This causes the entire recipe to be handed to SHELL as a single string, potentially containing newlines. */ int one_shell; #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION /* Nonzero if we have seen the '.SECONDTARGETEXPANSION' target. This turns on secondary expansion of targets. */ int second_target_expansion; #endif #ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL /* Nonzero if we have seen the `.NOTPARALLEL' target. This turns off parallel builds for this invocation of make. */ #else /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ /* Negative if we have seen the `.NOTPARALLEL' target with an empty dependency list. Zero if no `.NOTPARALLEL' or no file in the dependency list is being executed. Positive when a file in the `.NOTPARALLEL' dependency list is in progress, the value is the number of notparallel files in progress (running or queued for running). In short, any nonzero value means no more parallel builing. */ #endif /* CONFIG_WITH_EXTENDED_NOTPARALLEL */ int not_parallel; /* Nonzero if some rule detected clock skew; we keep track so (a) we only print one warning about it during the run, and (b) we can print a final warning at the end of the run. */ int clock_skew_detected; /* Mask of signals that are being caught with fatal_error_signal. */ #ifdef POSIX sigset_t fatal_signal_set; #else # ifdef HAVE_SIGSETMASK int fatal_signal_mask; # endif #endif #if !HAVE_DECL_BSD_SIGNAL && !defined bsd_signal # if !defined HAVE_SIGACTION # define bsd_signal signal # else typedef RETSIGTYPE (*bsd_signal_ret_t) (int); static bsd_signal_ret_t bsd_signal (int sig, bsd_signal_ret_t func) { struct sigaction act, oact; act.sa_handler = func; act.sa_flags = SA_RESTART; sigemptyset (&act.sa_mask); sigaddset (&act.sa_mask, sig); if (sigaction (sig, &act, &oact) != 0) return SIG_ERR; return oact.sa_handler; } # endif #endif #ifdef CONFIG_WITH_ALLOC_CACHES struct alloccache dep_cache; struct alloccache file_cache; struct alloccache commands_cache; struct alloccache nameseq_cache; struct alloccache variable_cache; struct alloccache variable_set_cache; struct alloccache variable_set_list_cache; static void initialize_global_alloc_caches (void) { alloccache_init (&dep_cache, sizeof (struct dep), "dep", NULL, NULL); alloccache_init (&file_cache, sizeof (struct file), "file", NULL, NULL); alloccache_init (&commands_cache, sizeof (struct commands), "commands", NULL, NULL); alloccache_init (&nameseq_cache, sizeof (struct nameseq), "nameseq", NULL, NULL); alloccache_init (&variable_cache, sizeof (struct variable), "variable", NULL, NULL); alloccache_init (&variable_set_cache, sizeof (struct variable_set), "variable_set", NULL, NULL); alloccache_init (&variable_set_list_cache, sizeof (struct variable_set_list), "variable_set_list", NULL, NULL); } #endif /* CONFIG_WITH_ALLOC_CACHES */ static void initialize_global_hash_tables (void) { init_hash_global_variable_set (); strcache_init (); init_hash_files (); hash_init_directories (); hash_init_function_table (); } static const char * expand_command_line_file (char *name) { const char *cp; char *expanded = 0; if (name[0] == '\0') fatal (NILF, _("empty string invalid as file name")); if (name[0] == '~') { expanded = tilde_expand (name); if (expanded != 0) name = expanded; } /* This is also done in parse_file_seq, so this is redundant for names read from makefiles. It is here for names passed on the command line. */ while (name[0] == '.' && name[1] == '/' && name[2] != '\0') { name += 2; while (*name == '/') /* Skip following slashes: ".//foo" is "foo", not "/foo". */ ++name; } if (*name == '\0') { /* It was all slashes! Move back to the dot and truncate it after the first slash, so it becomes just "./". */ do --name; while (name[0] != '.'); name[2] = '\0'; } cp = strcache_add (name); if (expanded) free (expanded); return cp; } /* Toggle -d on receipt of SIGUSR1. */ #ifdef SIGUSR1 static RETSIGTYPE debug_signal_handler (int sig UNUSED) { db_level = db_level ? DB_NONE : DB_BASIC; } #endif static void decode_debug_flags (void) { const char **pp; if (debug_flag) db_level = DB_ALL; if (!db_flags) return; for (pp=db_flags->list; *pp; ++pp) { const char *p = *pp; while (1) { switch (tolower (p[0])) { case 'a': db_level |= DB_ALL; break; case 'b': db_level |= DB_BASIC; break; case 'i': db_level |= DB_BASIC | DB_IMPLICIT; break; case 'j': db_level |= DB_JOBS; break; case 'm': db_level |= DB_BASIC | DB_MAKEFILES; break; case 'v': db_level |= DB_BASIC | DB_VERBOSE; break; #ifdef DB_KMK case 'k': db_level |= DB_KMK; break; #endif /* DB_KMK */ default: fatal (NILF, _("unknown debug level specification `%s'"), p); } while (*(++p) != '\0') if (*p == ',' || *p == ' ') break; if (*p == '\0') break; ++p; } } } #ifdef KMK static void set_make_priority_and_affinity (void) { # ifdef WINDOWS32 DWORD dwPriority; if (process_affinity) if (!SetProcessAffinityMask (GetCurrentProcess (), process_affinity)) fprintf (stderr, "warning: SetPriorityClass (,%#x) failed with last error %d\n", process_affinity, GetLastError ()); switch (process_priority) { case 0: return; case 1: dwPriority = IDLE_PRIORITY_CLASS; break; case 2: dwPriority = BELOW_NORMAL_PRIORITY_CLASS; break; case 3: dwPriority = NORMAL_PRIORITY_CLASS; break; case 4: dwPriority = HIGH_PRIORITY_CLASS; break; case 5: dwPriority = REALTIME_PRIORITY_CLASS; break; default: fatal (NILF, _("invalid priority %d\n"), process_priority); } if (!SetPriorityClass (GetCurrentProcess (), dwPriority)) fprintf (stderr, "warning: SetPriorityClass (,%#x) failed with last error %d\n", dwPriority, GetLastError ()); #elif defined(__HAIKU__) int32 iNewPriority; status_t error; switch (process_priority) { case 0: return; case 1: iNewPriority = B_LOWEST_ACTIVE_PRIORITY; break; case 2: iNewPriority = B_LOW_PRIORITY; break; case 3: iNewPriority = B_NORMAL_PRIORITY; break; case 4: iNewPriority = B_URGENT_DISPLAY_PRIORITY; break; case 5: iNewPriority = B_REAL_TIME_DISPLAY_PRIORITY; break; default: fatal (NILF, _("invalid priority %d\n"), process_priority); } error = set_thread_priority (find_thread (NULL), iNewPriority); if (error != B_OK) fprintf (stderr, "warning: set_thread_priority (,%d) failed: %s\n", iNewPriority, strerror (error)); # else /*#elif HAVE_NICE */ int nice_level = 0; switch (process_priority) { case 0: return; case 1: nice_level = 19; break; case 2: nice_level = 10; break; case 3: nice_level = 0; break; case 4: nice_level = -10; break; case 5: nice_level = -19; break; default: fatal (NILF, _("invalid priority %d\n"), process_priority); } errno = 0; if (nice (nice_level) == -1 && errno != 0) fprintf (stderr, "warning: nice (%d) failed: %s\n", nice_level, strerror (errno)); # endif } #endif /* KMK */ #ifdef WINDOWS32 /* * HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture * exception and print it to stderr instead. * * If ! DB_VERBOSE, just print a simple message and exit. * If DB_VERBOSE, print a more verbose message. * If compiled for DEBUG, let exception pass through to GUI so that * debuggers can attach. */ LONG WINAPI handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo ) { PEXCEPTION_RECORD exrec = exinfo->ExceptionRecord; LPSTR cmdline = GetCommandLine(); LPSTR prg = strtok(cmdline, " "); CHAR errmsg[1024]; #ifdef USE_EVENT_LOG HANDLE hEventSource; LPTSTR lpszStrings[1]; #endif if (! ISDB (DB_VERBOSE)) { sprintf(errmsg, _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\n"), prg, exrec->ExceptionCode, exrec->ExceptionAddress); fprintf(stderr, errmsg); exit(255); } sprintf(errmsg, _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = 0x%p\n"), prg, exrec->ExceptionCode, exrec->ExceptionFlags, exrec->ExceptionAddress); if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exrec->NumberParameters >= 2) sprintf(&errmsg[strlen(errmsg)], (exrec->ExceptionInformation[0] ? _("Access violation: write operation at address 0x%p\n") : _("Access violation: read operation at address 0x%p\n")), (PVOID)exrec->ExceptionInformation[1]); /* turn this on if we want to put stuff in the event log too */ #ifdef USE_EVENT_LOG hEventSource = RegisterEventSource(NULL, "GNU Make"); lpszStrings[0] = errmsg; if (hEventSource != NULL) { ReportEvent(hEventSource, /* handle of event source */ EVENTLOG_ERROR_TYPE, /* event type */ 0, /* event category */ 0, /* event ID */ NULL, /* current user's SID */ 1, /* strings in lpszStrings */ 0, /* no bytes of raw data */ lpszStrings, /* array of error strings */ NULL); /* no raw data */ (VOID) DeregisterEventSource(hEventSource); } #endif /* Write the error to stderr too */ fprintf(stderr, errmsg); #ifdef DEBUG return EXCEPTION_CONTINUE_SEARCH; #else exit(255); return (255); /* not reached */ #endif } /* * On WIN32 systems we don't have the luxury of a /bin directory that * is mapped globally to every drive mounted to the system. Since make could * be invoked from any drive, and we don't want to propogate /bin/sh * to every single drive. Allow ourselves a chance to search for * a value for default shell here (if the default path does not exist). */ int find_and_set_default_shell (const char *token) { int sh_found = 0; char *atoken = 0; char *search_token; char *tokend; PATH_VAR(sh_path); extern char *default_shell; if (!token) search_token = default_shell; else atoken = search_token = xstrdup (token); /* If the user explicitly requests the DOS cmd shell, obey that request. However, make sure that's what they really want by requiring the value of SHELL either equal, or have a final path element of, "cmd" or "cmd.exe" case-insensitive. */ tokend = search_token + strlen (search_token) - 3; if (((tokend == search_token || (tokend > search_token && (tokend[-1] == '/' || tokend[-1] == '\\'))) && !strcasecmp (tokend, "cmd")) || ((tokend - 4 == search_token || (tokend - 4 > search_token && (tokend[-5] == '/' || tokend[-5] == '\\'))) && !strcasecmp (tokend - 4, "cmd.exe"))) { batch_mode_shell = 1; unixy_shell = 0; sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), default_shell)); sh_found = 1; } else if (!no_default_sh_exe && (token == NULL || !strcmp (search_token, default_shell))) { /* no new information, path already set or known */ sh_found = 1; } else if (file_exists_p (search_token)) { /* search token path was found */ sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), default_shell)); sh_found = 1; } else { char *p; struct variable *v = lookup_variable (STRING_SIZE_TUPLE ("PATH")); /* Search Path for shell */ if (v && v->value) { char *ep; p = v->value; ep = strchr (p, PATH_SEPARATOR_CHAR); while (ep && *ep) { *ep = '\0'; if (dir_file_exists_p (p, search_token)) { sprintf (sh_path, "%s/%s", p, search_token); default_shell = xstrdup (w32ify (sh_path, 0)); sh_found = 1; *ep = PATH_SEPARATOR_CHAR; /* terminate loop */ p += strlen (p); } else { *ep = PATH_SEPARATOR_CHAR; p = ++ep; } ep = strchr (p, PATH_SEPARATOR_CHAR); } /* be sure to check last element of Path */ if (p && *p && dir_file_exists_p (p, search_token)) { sprintf (sh_path, "%s/%s", p, search_token); default_shell = xstrdup (w32ify (sh_path, 0)); sh_found = 1; } if (sh_found) DB (DB_VERBOSE, (_("find_and_set_shell() path search set default_shell = %s\n"), default_shell)); } } #if 0/* def KMK - has been fixed in sub_proc.c */ /* WORKAROUND: With GNU Make 3.81, this kludge was necessary to get double quotes working correctly again (worked fine with the 3.81beta1 code). beta1 was forcing batch_mode_shell I think, so let's enforce that for the kBuild shell. */ if (sh_found && strstr(default_shell, "kmk_ash")) { unixy_shell = 1; batch_mode_shell = 1; } else #endif /* naive test */ if (!unixy_shell && sh_found && (strstr (default_shell, "sh") || strstr (default_shell, "SH"))) { unixy_shell = 1; batch_mode_shell = 0; } #ifdef BATCH_MODE_ONLY_SHELL batch_mode_shell = 1; #endif if (atoken) free (atoken); return (sh_found); } /* bird: */ #ifdef CONFIG_NEW_WIN32_CTRL_EVENT #include static UINT g_tidMainThread = 0; static int volatile g_sigPending = 0; /* lazy bird */ # ifndef _M_IX86 static LONG volatile g_lTriggered = 0; static CONTEXT g_Ctx; # endif # ifdef _M_IX86 static __declspec(naked) void dispatch_stub(void) { __asm { pushfd pushad cld } fflush(stdout); /*fprintf(stderr, "dbg: raising %s on the main thread (%d)\n", g_sigPending == SIGINT ? "SIGINT" : "SIGBREAK", _getpid());*/ raise(g_sigPending); __asm { popad popfd ret } } # else /* !_M_IX86 */ static void dispatch_stub(void) { fflush(stdout); /*fprintf(stderr, "dbg: raising %s on the main thread (%d)\n", g_sigPending == SIGINT ? "SIGINT" : "SIGBREAK", _getpid());*/ raise(g_sigPending); SetThreadContext(GetCurrentThread(), &g_Ctx); fprintf(stderr, "fatal error: SetThreadContext failed with last error %d\n", GetLastError()); for (;;) exit(131); } # endif /* !_M_IX86 */ static BOOL WINAPI ctrl_event(DWORD CtrlType) { int sig = (CtrlType == CTRL_C_EVENT) ? SIGINT : SIGBREAK; HANDLE hThread; CONTEXT Ctx; #ifndef _M_IX86 /* only once. */ if (InterlockedExchange(&g_lTriggered, 1)) { Sleep(1); return TRUE; } #endif /* open the main thread and suspend it. */ hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, g_tidMainThread); SuspendThread(hThread); /* Get the thread context and if we've get a valid Esp, dispatch it on the main thread otherwise raise the signal in the ctrl-event thread (this). */ memset(&Ctx, 0, sizeof(Ctx)); Ctx.ContextFlags = CONTEXT_FULL; if (GetThreadContext(hThread, &Ctx) #ifdef _M_IX86 && Ctx.Esp >= 0x1000 #else && Ctx.Rsp >= 0x1000 #endif ) { #ifdef _M_IX86 ((uintptr_t *)Ctx.Esp)[-1] = Ctx.Eip; Ctx.Esp -= sizeof(uintptr_t); Ctx.Eip = (uintptr_t)&dispatch_stub; #else g_Ctx = Ctx; Ctx.Rsp -= 0x20; Ctx.Rsp &= ~(uintptr_t)0xf; Ctx.Rip = (uintptr_t)&dispatch_stub; #endif SetThreadContext(hThread, &Ctx); g_sigPending = sig; ResumeThread(hThread); CloseHandle(hThread); } else { fprintf(stderr, "dbg: raising %s on the ctrl-event thread (%d)\n", sig == SIGINT ? "SIGINT" : "SIGBREAK", _getpid()); raise(sig); ResumeThread(hThread); CloseHandle(hThread); exit(130); } Sleep(1); return TRUE; } #endif /* CONFIG_NEW_WIN32_CTRL_EVENT */ #endif /* WINDOWS32 */ #ifdef KMK /* Determins the number of CPUs that are currently online. This is used to setup the default number of job slots. */ static int get_online_cpu_count(void) { # ifdef WINDOWS32 /* Windows: Count the active CPUs. */ int cpus, i; SYSTEM_INFO si; GetSystemInfo(&si); for (i = cpus = 0; i < sizeof(si.dwActiveProcessorMask) * 8; i++) { if (si.dwActiveProcessorMask & 1) cpus++; si.dwActiveProcessorMask >>= 1; } return cpus ? cpus : 1; # elif defined(__OS2__) /* OS/2: Count the active CPUs. */ int cpus, i, j; MPAFFINITY mp; if (DosQueryThreadAffinity(AFNTY_SYSTEM, &mp)) return 1; for (j = cpus = 0; j < sizeof(mp.mask) / sizeof(mp.mask[0]); j++) for (i = 0; i < 32; i++) if (mp.mask[j] & (1UL << i)) cpus++; return cpus ? cpus : 1; # else /* UNIX like systems, try sysconf and sysctl. */ int cpus = -1; # if defined(CTL_HW) int mib[2]; size_t sz; # endif # ifdef _SC_NPROCESSORS_ONLN cpus = sysconf(_SC_NPROCESSORS_ONLN); if (cpus >= 1) return cpus; cpus = -1; # endif # if defined(CTL_HW) # ifdef HW_AVAILCPU sz = sizeof(cpus); mib[0] = CTL_HW; mib[1] = HW_AVAILCPU; if (!sysctl(mib, 2, &cpus, &sz, NULL, 0) && cpus >= 1) return cpus; cpus = -1; # endif /* HW_AVAILCPU */ sz = sizeof(cpus); mib[0] = CTL_HW; mib[1] = HW_NCPU; if (!sysctl(mib, 2, &cpus, &sz, NULL, 0) && cpus >= 1) return cpus; cpus = -1; # endif /* CTL_HW */ /* no idea / failure, just return 1. */ return 1; # endif } #endif /* KMK */ #ifdef __MSDOS__ static void msdos_return_to_initial_directory (void) { if (directory_before_chdir) chdir (directory_before_chdir); } #endif /* __MSDOS__ */ #ifndef _MSC_VER /* bird */ char *mktemp (char *template); #endif int mkstemp (char *template); FILE * open_tmpfile(char **name, const char *template) { #ifdef HAVE_FDOPEN int fd; #endif #if defined HAVE_MKSTEMP || defined HAVE_MKTEMP # define TEMPLATE_LEN strlen (template) #else # define TEMPLATE_LEN L_tmpnam #endif *name = xmalloc (TEMPLATE_LEN + 1); strcpy (*name, template); #if defined HAVE_MKSTEMP && defined HAVE_FDOPEN /* It's safest to use mkstemp(), if we can. */ fd = mkstemp (*name); if (fd == -1) return 0; return fdopen (fd, "w"); #else # ifdef HAVE_MKTEMP (void) mktemp (*name); # else (void) tmpnam (*name); # endif # ifdef HAVE_FDOPEN /* Can't use mkstemp(), but guard against a race condition. */ fd = open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600); if (fd == -1) return 0; return fdopen (fd, "w"); # else /* Not secure, but what can we do? */ return fopen (*name, "w"); # endif #endif } #ifdef CONFIG_WITH_FAST_IS_SPACE /*bird*/ char space_map[space_map_size]; #endif /* CONFIG_WITH_FAST_IS_SPACE */ #ifdef _AMIGA int main (int argc, char **argv) #else int main (int argc, char **argv, char **envp) #endif { static char *stdin_nm = 0; int makefile_status = MAKE_SUCCESS; struct dep *read_makefiles; PATH_VAR (current_directory); unsigned int restarts = 0; #ifdef WINDOWS32 char *unix_path = NULL; char *windows32_path = NULL; #ifndef ELECTRIC_HEAP /* Drop this because it prevents JIT debugging. */ SetUnhandledExceptionFilter(handle_runtime_exceptions); #endif /* !ELECTRIC_HEAP */ /* start off assuming we have no shell */ unixy_shell = 0; no_default_sh_exe = 1; #endif # ifdef CONFIG_WITH_FAST_IS_SPACE /* bird */ memset (space_map, '\0', sizeof(space_map)); set_space_map_entry (' '); set_space_map_entry ('\f'); set_space_map_entry ('\n'); set_space_map_entry ('\r'); set_space_map_entry ('\t'); set_space_map_entry ('\v'); # endif /* CONFIG_WITH_FAST_IS_SPACE */ #ifdef CONFIG_WITH_PRINT_TIME_SWITCH make_start_ts = nano_timestamp (); #endif #ifdef SET_STACK_SIZE /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca does not fail. */ if (getrlimit (RLIMIT_STACK, &rlim) == 0 && rlim.rlim_cur > 0 && rlim.rlim_cur < rlim.rlim_max) { stack_limit = rlim; rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } else stack_limit.rlim_cur = 0; } #endif #ifdef HAVE_ATEXIT atexit (close_stdout); #endif /* Needed for OS/2 */ initialize_main(&argc, &argv); #ifdef KMK init_kbuild (argc, argv); #endif reading_file = 0; #if defined (__MSDOS__) && !defined (_POSIX_SOURCE) /* Request the most powerful version of `system', to make up for the dumb default shell. */ __system_flags = (__system_redirect | __system_use_shell | __system_allow_multiple_cmds | __system_allow_long_cmds | __system_handle_null_commands | __system_emulate_chdir); #endif /* Set up gettext/internationalization support. */ setlocale (LC_ALL, ""); /* The cast to void shuts up compiler warnings on systems that disable NLS. */ #ifdef LOCALEDIR /* bird */ (void)bindtextdomain (PACKAGE, LOCALEDIR); (void)textdomain (PACKAGE); #endif #ifdef POSIX sigemptyset (&fatal_signal_set); #define ADD_SIG(sig) sigaddset (&fatal_signal_set, sig) #else #ifdef HAVE_SIGSETMASK fatal_signal_mask = 0; #define ADD_SIG(sig) fatal_signal_mask |= sigmask (sig) #else #define ADD_SIG(sig) (void)sig /* Needed to avoid warnings in MSVC. */ #endif #endif #define FATAL_SIG(sig) \ if (bsd_signal (sig, fatal_error_signal) == SIG_IGN) \ bsd_signal (sig, SIG_IGN); \ else \ ADD_SIG (sig); #ifdef SIGHUP FATAL_SIG (SIGHUP); #endif #ifdef SIGQUIT FATAL_SIG (SIGQUIT); #endif FATAL_SIG (SIGINT); FATAL_SIG (SIGTERM); #ifdef __MSDOS__ /* Windows 9X delivers FP exceptions in child programs to their parent! We don't want Make to die when a child divides by zero, so we work around that lossage by catching SIGFPE. */ FATAL_SIG (SIGFPE); #endif #ifdef SIGDANGER FATAL_SIG (SIGDANGER); #endif #ifdef SIGXCPU FATAL_SIG (SIGXCPU); #endif #ifdef SIGXFSZ FATAL_SIG (SIGXFSZ); #endif #ifdef CONFIG_NEW_WIN32_CTRL_EVENT /* bird: dispatch signals in our own way to try avoid deadlocks. */ g_tidMainThread = GetCurrentThreadId (); SetConsoleCtrlHandler (ctrl_event, TRUE); #endif /* CONFIG_NEW_WIN32_CTRL_EVENT */ #undef FATAL_SIG /* Do not ignore the child-death signal. This must be done before any children could possibly be created; otherwise, the wait functions won't work on systems with the SVR4 ECHILD brain damage, if our invoker is ignoring this signal. */ #ifdef HAVE_WAIT_NOHANG # if defined SIGCHLD (void) bsd_signal (SIGCHLD, SIG_DFL); # endif # if defined SIGCLD && SIGCLD != SIGCHLD (void) bsd_signal (SIGCLD, SIG_DFL); # endif #endif /* Make sure stdout is line-buffered. */ #ifdef HAVE_SETVBUF # ifdef SETVBUF_REVERSED setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ); # else /* setvbuf not reversed. */ /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */ setvbuf (stdout, 0, _IOLBF, BUFSIZ); # endif /* setvbuf reversed. */ #elif HAVE_SETLINEBUF setlinebuf (stdout); #endif /* setlinebuf missing. */ /* Figure out where this program lives. */ if (argv[0] == 0) argv[0] = ""; if (argv[0][0] == '\0') #ifdef KMK program = "kmk"; #else program = "make"; #endif else { #ifdef VMS program = strrchr (argv[0], ']'); #else program = strrchr (argv[0], '/'); #endif #if defined(__MSDOS__) || defined(__EMX__) if (program == 0) program = strrchr (argv[0], '\\'); else { /* Some weird environments might pass us argv[0] with both kinds of slashes; we must find the rightmost. */ char *p = strrchr (argv[0], '\\'); if (p && p > program) program = p; } if (program == 0 && argv[0][1] == ':') program = argv[0] + 1; #endif #ifdef WINDOWS32 if (program == 0) { /* Extract program from full path */ int argv0_len; program = strrchr (argv[0], '\\'); if (program) { argv0_len = strlen(program); if (argv0_len > 4 && streq (&program[argv0_len - 4], ".exe")) /* Remove .exe extension */ program[argv0_len - 4] = '\0'; } } #endif if (program == 0) program = argv[0]; else ++program; } /* Set up to access user data (files). */ user_access (); #ifdef CONFIG_WITH_ALLOC_CACHES initialize_global_alloc_caches (); #endif initialize_global_hash_tables (); /* Figure out where we are. */ #ifdef WINDOWS32 if (getcwd_fs (current_directory, GET_PATH_MAX) == 0) #else if (getcwd (current_directory, GET_PATH_MAX) == 0) #endif { #ifdef HAVE_GETCWD perror_with_name ("getcwd", ""); #else error (NILF, "getwd: %s", current_directory); #endif current_directory[0] = '\0'; directory_before_chdir = 0; } else directory_before_chdir = xstrdup (current_directory); #ifdef __MSDOS__ /* Make sure we will return to the initial directory, come what may. */ atexit (msdos_return_to_initial_directory); #endif /* Initialize the special variables. */ define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1; /* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */ define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1; define_variable_cname (".SHELLFLAGS", "-c", o_default, 0); /* Set up .FEATURES We must do this in multiple calls because define_variable_cname() is a macro and some compilers (MSVC) don't like conditionals in macros. */ { const char *features = "target-specific order-only second-expansion" " else-if shortest-stem undefine" #ifndef NO_ARCHIVES " archives" #endif #ifdef MAKE_JOBSERVER " jobserver" #endif #ifdef MAKE_SYMLINKS " check-symlink" #endif #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET " explicit-multitarget" #endif #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT " prepend-assignment" #endif ; define_variable_cname (".FEATURES", features, o_default, 0); } #ifdef KMK /* Initialize the default number of jobs to the cpu/core/smt count. */ default_job_slots = job_slots = get_online_cpu_count (); #endif /* KMK */ /* Read in variables from the environment. It is important that this be done before $(MAKE) is figured out so its definitions will not be from the environment. */ #ifndef _AMIGA { unsigned int i; for (i = 0; envp[i] != 0; ++i) { int do_not_define = 0; char *ep = envp[i]; while (*ep != '\0' && *ep != '=') ++ep; #ifdef WINDOWS32 if (!unix_path && strneq(envp[i], "PATH=", 5)) unix_path = ep+1; else if (!strnicmp(envp[i], "Path=", 5)) { do_not_define = 1; /* it gets defined after loop exits */ if (!windows32_path) windows32_path = ep+1; } #endif /* The result of pointer arithmetic is cast to unsigned int for machines where ptrdiff_t is a different size that doesn't widen the same. */ if (!do_not_define) { struct variable *v; v = define_variable (envp[i], (unsigned int) (ep - envp[i]), ep + 1, o_env, 1); /* Force exportation of every variable culled from the environment. We used to rely on target_environment's v_default code to do this. But that does not work for the case where an environment variable is redefined in a makefile with `override'; it should then still be exported, because it was originally in the environment. */ v->export = v_export; /* Another wrinkle is that POSIX says the value of SHELL set in the makefile won't change the value of SHELL given to subprocesses. */ if (streq (v->name, "SHELL")) { #ifndef __MSDOS__ v->export = v_noexport; #endif #ifndef CONFIG_WITH_STRCACHE2 shell_var.name = "SHELL"; #else shell_var.name = v->name; #endif shell_var.length = 5; #ifndef CONFIG_WITH_VALUE_LENGTH shell_var.value = xstrdup (ep + 1); #else shell_var.value = xstrndup (v->value, v->value_length); shell_var.value_length = v->value_length; #endif } /* If MAKE_RESTARTS is set, remember it but don't export it. */ if (streq (v->name, "MAKE_RESTARTS")) { v->export = v_noexport; restarts = (unsigned int) atoi (ep + 1); } } } } #ifdef WINDOWS32 /* If we didn't find a correctly spelled PATH we define PATH as * either the first mispelled value or an empty string */ if (!unix_path) define_variable_cname ("PATH", windows32_path ? windows32_path : "", o_env, 1)->export = v_export; #endif #else /* For Amiga, read the ENV: device, ignoring all dirs */ { BPTR env, file, old; char buffer[1024]; int len; __aligned struct FileInfoBlock fib; env = Lock ("ENV:", ACCESS_READ); if (env) { old = CurrentDir (DupLock(env)); Examine (env, &fib); while (ExNext (env, &fib)) { if (fib.fib_DirEntryType < 0) /* File */ { /* Define an empty variable. It will be filled in variable_lookup(). Makes startup quite a bit faster. */ define_variable (fib.fib_FileName, strlen (fib.fib_FileName), "", o_env, 1)->export = v_export; } } UnLock (env); UnLock(CurrentDir(old)); } } #endif /* Decode the switches. */ #ifdef KMK decode_env_switches (STRING_SIZE_TUPLE ("KMK_FLAGS")); #else /* !KMK */ decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS")); #if 0 /* People write things like: MFLAGS="CC=gcc -pipe" "CFLAGS=-g" and we set the -p, -i and -e switches. Doesn't seem quite right. */ decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); #endif #endif /* !KMK */ decode_switches (argc, argv, 0); #ifdef WINDOWS32 if (suspend_flag) { fprintf(stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId()); fprintf(stderr, _("%s is suspending for 30 seconds..."), argv[0]); Sleep(30 * 1000); fprintf(stderr, _("done sleep(30). Continuing.\n")); } #endif decode_debug_flags (); #ifdef KMK set_make_priority_and_affinity (); #endif /* Set always_make_flag if -B was given and we've not restarted already. */ always_make_flag = always_make_set && (restarts == 0); /* Print version information. */ if (print_version_flag || print_data_base_flag || db_level) { print_version (); /* `make --version' is supposed to just print the version and exit. */ if (print_version_flag) die (0); } #ifndef VMS /* Set the "MAKE_COMMAND" variable to the name we were invoked with. (If it is a relative pathname with a slash, prepend our directory name so the result will run the same program regardless of the current dir. If it is a name with no slash, we can only hope that PATH did not find it in the current directory.) */ #ifdef WINDOWS32 /* * Convert from backslashes to forward slashes for * programs like sh which don't like them. Shouldn't * matter if the path is one way or the other for * CreateProcess(). */ if (strpbrk(argv[0], "/:\\") || strstr(argv[0], "..") || strneq(argv[0], "//", 2)) argv[0] = xstrdup(w32ify(argv[0],1)); #else /* WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) if (strchr (argv[0], '\\')) { char *p; argv[0] = xstrdup (argv[0]); for (p = argv[0]; *p; p++) if (*p == '\\') *p = '/'; } /* If argv[0] is not in absolute form, prepend the current directory. This can happen when Make is invoked by another DJGPP program that uses a non-absolute name. */ if (current_directory[0] != '\0' && argv[0] != 0 && (argv[0][0] != '/' && (argv[0][0] == '\0' || argv[0][1] != ':')) # ifdef __EMX__ /* do not prepend cwd if argv[0] contains no '/', e.g. "make" */ && (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0) # endif ) argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #else /* !__MSDOS__ */ if (current_directory[0] != '\0' && argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0 #ifdef HAVE_DOS_PATHS && (argv[0][0] != '\\' && (!argv[0][0] || argv[0][1] != ':')) && strchr (argv[0], '\\') != 0 #endif ) argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #endif /* !__MSDOS__ */ #endif /* WINDOWS32 */ #endif /* The extra indirection through $(MAKE_COMMAND) is done for hysterical raisins. */ define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0); define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1); #ifdef KMK (void) define_variable ("KMK", 3, argv[0], o_default, 1); #endif if (command_variables != 0) { struct command_variable *cv; struct variable *v; unsigned int len = 0; char *value, *p; /* Figure out how much space will be taken up by the command-line variable definitions. */ for (cv = command_variables; cv != 0; cv = cv->next) { v = cv->variable; len += 2 * strlen (v->name); if (! v->recursive) ++len; ++len; len += 2 * strlen (v->value); ++len; } /* Now allocate a buffer big enough and fill it. */ p = value = alloca (len); for (cv = command_variables; cv != 0; cv = cv->next) { v = cv->variable; p = quote_for_env (p, v->name); if (! v->recursive) *p++ = ':'; *p++ = '='; p = quote_for_env (p, v->value); *p++ = ' '; } p[-1] = '\0'; /* Kill the final space and terminate. */ /* Define an unchangeable variable with a name that no POSIX.2 makefile could validly use for its own variable. */ define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0); /* Define the variable; this will not override any user definition. Normally a reference to this variable is written into the value of MAKEFLAGS, allowing the user to override this value to affect the exported value of MAKEFLAGS. In POSIX-pedantic mode, we cannot allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so a reference to this hidden variable is written instead. */ #ifdef KMK define_variable_cname ("KMK_OVERRIDES", "${-*-command-variables-*-}", o_env, 1); #else define_variable_cname ("MAKEOVERRIDES", "${-*-command-variables-*-}", o_env, 1); #endif } /* If there were -C flags, move ourselves about. */ if (directories != 0) { unsigned int i; for (i = 0; directories->list[i] != 0; ++i) { const char *dir = directories->list[i]; #ifdef WINDOWS32 /* WINDOWS32 chdir() doesn't work if the directory has a trailing '/' But allow -C/ just in case someone wants that. */ { char *p = (char *)dir + strlen (dir) - 1; while (p > dir && (p[0] == '/' || p[0] == '\\')) --p; p[1] = '\0'; } #endif if (chdir (dir) < 0) pfatal_with_name (dir); } } #ifdef KMK /* Check for [Mm]akefile.kup and change directory when found. Makefile.kmk overrides Makefile.kup but not plain Makefile. If no -C arguments were given, fake one to indicate chdir. */ if (makefiles == 0) { struct stat st; if (( ( stat ("Makefile.kup", &st) == 0 && S_ISREG (st.st_mode) ) || ( stat ("makefile.kup", &st) == 0 && S_ISREG (st.st_mode) ) ) && stat ("Makefile.kmk", &st) < 0 && stat ("makefile.kmk", &st) < 0) { static char fake_path[3*16 + 32] = ".."; char *cur = &fake_path[2]; int up_levels = 1; while (up_levels < 16) { /* File with higher precedence.s */ strcpy (cur, "/Makefile.kmk"); if (stat (fake_path, &st) == 0) break; strcpy (cur, "/makefile.kmk"); if (stat (fake_path, &st) == 0) break; /* the .kup files */ strcpy (cur, "/Makefile.kup"); if ( stat (fake_path, &st) != 0 || !S_ISREG (st.st_mode)) { strcpy (cur, "/makefile.kup"); if ( stat (fake_path, &st) != 0 || !S_ISREG (st.st_mode)) break; } /* ok */ strcpy (cur, "/.."); cur += 3; up_levels++; } if (up_levels >= 16) fatal (NILF, _("Makefile.kup recursion is too deep.")); /* attempt to change to the directory. */ *cur = '\0'; if (chdir (fake_path) < 0) pfatal_with_name (fake_path); /* add the string to the directories. */ if (!directories) { directories = xmalloc (sizeof(*directories)); directories->list = xmalloc (5 * sizeof (char *)); directories->max = 5; directories->idx = 0; } else if (directories->idx == directories->max - 1) { directories->max += 5; directories->list = xrealloc ((void *)directories->list, directories->max * sizeof (char *)); } directories->list[directories->idx++] = fake_path; } } #endif /* KMK */ #ifdef WINDOWS32 /* * THIS BLOCK OF CODE MUST COME AFTER chdir() CALL ABOVE IN ORDER * TO NOT CONFUSE THE DEPENDENCY CHECKING CODE IN implicit.c. * * The functions in dir.c can incorrectly cache information for "." * before we have changed directory and this can cause file * lookups to fail because the current directory (.) was pointing * at the wrong place when it was first evaluated. */ #ifdef KMK /* this is really a candidate for all platforms... */ { extern char *default_shell; const char *bin = get_kbuild_bin_path(); size_t len = strlen (bin); default_shell = xmalloc (len + sizeof("/kmk_ash.exe")); memcpy (default_shell, bin, len); strcpy (default_shell + len, "/kmk_ash.exe"); no_default_sh_exe = 0; batch_mode_shell = 1; } #else /* !KMK */ no_default_sh_exe = !find_and_set_default_shell(NULL); #endif /* !KMK */ #endif /* WINDOWS32 */ /* Figure out the level of recursion. */ { struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME)); if (v != 0 && v->value[0] != '\0' && v->value[0] != '-') makelevel = (unsigned int) atoi (v->value); else makelevel = 0; } /* Except under -s, always do -w in sub-makes and under -C. */ if (!silent_flag && (directories != 0 || makelevel > 0)) print_directory_flag = 1; /* Let the user disable that with --no-print-directory. */ if (inhibit_print_directory_flag) print_directory_flag = 0; /* If -R was given, set -r too (doesn't make sense otherwise!) */ if (no_builtin_variables_flag) no_builtin_rules_flag = 1; /* Construct the list of include directories to search. */ construct_include_path (include_directories == 0 ? 0 : include_directories->list); /* Figure out where we are now, after chdir'ing. */ if (directories == 0) /* We didn't move, so we're still in the same place. */ starting_directory = current_directory; else { #ifdef WINDOWS32 if (getcwd_fs (current_directory, GET_PATH_MAX) == 0) #else if (getcwd (current_directory, GET_PATH_MAX) == 0) #endif { #ifdef HAVE_GETCWD perror_with_name ("getcwd", ""); #else error (NILF, "getwd: %s", current_directory); #endif starting_directory = 0; } else starting_directory = current_directory; } define_variable_cname ("CURDIR", current_directory, o_file, 0); /* Read any stdin makefiles into temporary files. */ if (makefiles != 0) { unsigned int i; for (i = 0; i < makefiles->idx; ++i) if (makefiles->list[i][0] == '-' && makefiles->list[i][1] == '\0') { /* This makefile is standard input. Since we may re-exec and thus re-read the makefiles, we read standard input into a temporary file and read from that. */ FILE *outfile; char *template, *tmpdir; if (stdin_nm) fatal (NILF, _("Makefile from standard input specified twice.")); #ifdef VMS # define DEFAULT_TMPDIR "sys$scratch:" #else # ifdef P_tmpdir # define DEFAULT_TMPDIR P_tmpdir # else # define DEFAULT_TMPDIR "/tmp" # endif #endif #define DEFAULT_TMPFILE "GmXXXXXX" if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0') #if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__) /* These are also used commonly on these platforms. */ && ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0') && ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0') #endif ) tmpdir = DEFAULT_TMPDIR; template = alloca (strlen (tmpdir) + sizeof (DEFAULT_TMPFILE) + 1); strcpy (template, tmpdir); #ifdef HAVE_DOS_PATHS if (strchr ("/\\", template[strlen (template) - 1]) == NULL) strcat (template, "/"); #else # ifndef VMS if (template[strlen (template) - 1] != '/') strcat (template, "/"); # endif /* !VMS */ #endif /* !HAVE_DOS_PATHS */ strcat (template, DEFAULT_TMPFILE); outfile = open_tmpfile (&stdin_nm, template); if (outfile == 0) pfatal_with_name (_("fopen (temporary file)")); while (!feof (stdin) && ! ferror (stdin)) { char buf[2048]; unsigned int n = fread (buf, 1, sizeof (buf), stdin); if (n > 0 && fwrite (buf, 1, n, outfile) != n) pfatal_with_name (_("fwrite (temporary file)")); } fclose (outfile); /* Replace the name that read_all_makefiles will see with the name of the temporary file. */ makefiles->list[i] = strcache_add (stdin_nm); /* Make sure the temporary file will not be remade. */ { struct file *f = enter_file (strcache_add (stdin_nm)); f->updated = 1; f->update_status = 0; f->command_state = cs_finished; /* Can't be intermediate, or it'll be removed too early for make re-exec. */ f->intermediate = 0; f->dontcare = 0; } } } #if !defined(__EMX__) || defined(__KLIBC__) /* Don't use a SIGCHLD handler for good old EMX (bird) */ #if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG) /* Set up to handle children dying. This must be done before reading in the makefiles so that `shell' function calls will work. If we don't have a hanging wait we have to fall back to old, broken functionality here and rely on the signal handler and counting children. If we're using the jobs pipe we need a signal handler so that SIGCHLD is not ignored; we need it to interrupt the read(2) of the jobserver pipe in job.c if we're waiting for a token. If none of these are true, we don't need a signal handler at all. */ { RETSIGTYPE child_handler (int sig); # if defined SIGCHLD bsd_signal (SIGCHLD, child_handler); # endif # if defined SIGCLD && SIGCLD != SIGCHLD bsd_signal (SIGCLD, child_handler); # endif } #endif #endif /* Let the user send us SIGUSR1 to toggle the -d flag during the run. */ #ifdef SIGUSR1 bsd_signal (SIGUSR1, debug_signal_handler); #endif /* Define the initial list of suffixes for old-style rules. */ set_default_suffixes (); /* Define the file rules for the built-in suffix rules. These will later be converted into pattern rules. We used to do this in install_default_implicit_rules, but since that happens after reading makefiles, it results in the built-in pattern rules taking precedence over makefile-specified suffix rules, which is wrong. */ install_default_suffix_rules (); /* Define some internal and special variables. */ define_automatic_variables (); /* Set up the MAKEFLAGS and MFLAGS variables so makefiles can look at them. */ define_makeflags (0, 0); /* Define the default variables. */ define_default_variables (); default_file = enter_file (strcache_add (".DEFAULT")); default_goal_var = define_variable_cname (".DEFAULT_GOAL", "", o_file, 0); /* Evaluate all strings provided with --eval. Also set up the $(-*-eval-flags-*-) variable. */ if (eval_strings) { char *p, *value; unsigned int i; unsigned int len = sizeof ("--eval=") * eval_strings->idx; for (i = 0; i < eval_strings->idx; ++i) { #ifndef CONFIG_WITH_VALUE_LENGTH p = xstrdup (eval_strings->list[i]); len += 2 * strlen (p); eval_buffer (p); #else unsigned int sub_len = strlen(eval_strings->list[i]); p = xstrndup (eval_strings->list[i], sub_len); len += 2 * sub_len; eval_buffer (p, p + sub_len); #endif free (p); } p = value = alloca (len); for (i = 0; i < eval_strings->idx; ++i) { strcpy (p, "--eval="); p += strlen (p); p = quote_for_env (p, eval_strings->list[i]); *(p++) = ' '; } p[-1] = '\0'; define_variable_cname ("-*-eval-flags-*-", value, o_automatic, 0); } /* Read all the makefiles. */ read_makefiles = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list); #ifdef WINDOWS32 /* look one last time after reading all Makefiles */ if (no_default_sh_exe) no_default_sh_exe = !find_and_set_default_shell(NULL); #endif /* WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) /* We need to know what kind of shell we will be using. */ { extern int _is_unixy_shell (const char *_path); struct variable *shv = lookup_variable (STRING_SIZE_TUPLE ("SHELL")); extern int unixy_shell; extern char *default_shell; if (shv && *shv->value) { char *shell_path = recursively_expand(shv); if (shell_path && _is_unixy_shell (shell_path)) unixy_shell = 1; else unixy_shell = 0; if (shell_path) default_shell = shell_path; } } #endif /* __MSDOS__ || __EMX__ */ /* Decode switches again, in case the variables were set by the makefile. */ #ifdef KMK decode_env_switches (STRING_SIZE_TUPLE ("KMK_FLAGS")); #else /* !KMK */ decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS")); #if 0 decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); #endif #endif /* !KMK */ #if defined (__MSDOS__) || defined (__EMX__) if (job_slots != 1 # ifdef __EMX__ && _osmode != OS2_MODE /* turn off -j if we are in DOS mode */ # endif ) { error (NILF, _("Parallel jobs (-j) are not supported on this platform.")); error (NILF, _("Resetting to single job (-j1) mode.")); job_slots = 1; } #endif #ifdef MAKE_JOBSERVER /* If the jobserver-fds option is seen, make sure that -j is reasonable. */ if (jobserver_fds) { const char *cp; unsigned int ui; for (ui=1; ui < jobserver_fds->idx; ++ui) if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui])) fatal (NILF, _("internal error: multiple --jobserver-fds options")); /* Now parse the fds string and make sure it has the proper format. */ cp = jobserver_fds->list[0]; if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2) fatal (NILF, _("internal error: invalid --jobserver-fds string `%s'"), cp); DB (DB_JOBS, (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1])); /* The combination of a pipe + !job_slots means we're using the jobserver. If !job_slots and we don't have a pipe, we can start infinite jobs. If we see both a pipe and job_slots >0 that means the user set -j explicitly. This is broken; in this case obey the user (ignore the jobserver pipe for this make) but print a message. */ if (job_slots > 0) error (NILF, _("warning: -jN forced in submake: disabling jobserver mode.")); /* Create a duplicate pipe, that will be closed in the SIGCHLD handler. If this fails with EBADF, the parent has closed the pipe on us because it didn't think we were a submake. If so, print a warning then default to -j1. */ else if ((job_rfd = dup (job_fds[0])) < 0) { if (errno != EBADF) pfatal_with_name (_("dup jobserver")); error (NILF, _("warning: jobserver unavailable: using -j1. Add `+' to parent make rule.")); job_slots = 1; } if (job_slots > 0) { close (job_fds[0]); close (job_fds[1]); job_fds[0] = job_fds[1] = -1; free (jobserver_fds->list); free (jobserver_fds); jobserver_fds = 0; } } /* If we have >1 slot but no jobserver-fds, then we're a top-level make. Set up the pipe and install the fds option for our children. */ if (job_slots > 1) { char *cp; char c = '+'; if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0) pfatal_with_name (_("creating jobs pipe")); /* Every make assumes that it always has one job it can run. For the submakes it's the token they were given by their parent. For the top make, we just subtract one from the number the user wants. We want job_slots to be 0 to indicate we're using the jobserver. */ master_job_slots = job_slots; while (--job_slots) { int r; EINTRLOOP (r, write (job_fds[1], &c, 1)); if (r != 1) pfatal_with_name (_("init jobserver pipe")); } /* Fill in the jobserver_fds struct for our children. */ cp = xmalloc ((sizeof ("1024")*2)+1); sprintf (cp, "%d,%d", job_fds[0], job_fds[1]); jobserver_fds = (struct stringlist *) xmalloc (sizeof (struct stringlist)); jobserver_fds->list = xmalloc (sizeof (char *)); jobserver_fds->list[0] = cp; jobserver_fds->idx = 1; jobserver_fds->max = 1; } #endif #ifndef MAKE_SYMLINKS if (check_symlink_flag) { error (NILF, _("Symbolic links not supported: disabling -L.")); check_symlink_flag = 0; } #endif /* Set up MAKEFLAGS and MFLAGS again, so they will be right. */ define_makeflags (1, 0); /* Make each `struct dep' point at the `struct file' for the file depended on. Also do magic for special targets. */ snap_deps (); /* Convert old-style suffix rules to pattern rules. It is important to do this before installing the built-in pattern rules below, so that makefile-specified suffix rules take precedence over built-in pattern rules. */ convert_to_pattern (); /* Install the default implicit pattern rules. This used to be done before reading the makefiles. But in that case, built-in pattern rules were in the chain before user-defined ones, so they matched first. */ install_default_implicit_rules (); /* Compute implicit rule limits. */ count_implicit_rule_limits (); /* Construct the listings of directories in VPATH lists. */ build_vpath_lists (); /* Mark files given with -o flags as very old and as having been updated already, and files given with -W flags as brand new (time-stamp as far as possible into the future). If restarts is set we'll do -W later. */ if (old_files != 0) { const char **p; for (p = old_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = OLD_MTIME; f->updated = 1; f->update_status = 0; f->command_state = cs_finished; } } if (!restarts && new_files != 0) { const char **p; for (p = new_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = NEW_MTIME; } } /* Initialize the remote job module. */ remote_setup (); if (read_makefiles != 0) { /* Update any makefiles if necessary. */ FILE_TIMESTAMP *makefile_mtimes = 0; unsigned int mm_idx = 0; char **nargv; int nargc; int orig_db_level = db_level; int status; if (! ISDB (DB_MAKEFILES)) db_level = DB_NONE; DB (DB_BASIC, (_("Updating makefiles....\n"))); /* Remove any makefiles we don't want to try to update. Also record the current modtimes so we can compare them later. */ { register struct dep *d, *last; last = 0; d = read_makefiles; while (d != 0) { struct file *f = d->file; if (f->double_colon) for (f = f->double_colon; f != NULL; f = f->prev) { if (f->deps == 0 && f->cmds != 0) { /* This makefile is a :: target with commands, but no dependencies. So, it will always be remade. This might well cause an infinite loop, so don't try to remake it. (This will only happen if your makefiles are written exceptionally stupidly; but if you work for Athena, that's how you write your makefiles.) */ DB (DB_VERBOSE, (_("Makefile `%s' might loop; not remaking it.\n"), f->name)); if (last == 0) read_makefiles = d->next; else last->next = d->next; /* Free the storage. */ free_dep (d); d = last == 0 ? read_makefiles : last->next; break; } } if (f == NULL || !f->double_colon) { makefile_mtimes = xrealloc (makefile_mtimes, (mm_idx+1) * sizeof (FILE_TIMESTAMP)); makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file); last = d; d = d->next; } } } /* Set up `MAKEFLAGS' specially while remaking makefiles. */ define_makeflags (1, 1); rebuilding_makefiles = 1; status = update_goal_chain (read_makefiles); rebuilding_makefiles = 0; switch (status) { case 1: /* The only way this can happen is if the user specified -q and asked * for one of the makefiles to be remade as a target on the command * line. Since we're not actually updating anything with -q we can * treat this as "did nothing". */ case -1: /* Did nothing. */ break; case 2: /* Failed to update. Figure out if we care. */ { /* Nonzero if any makefile was successfully remade. */ int any_remade = 0; /* Nonzero if any makefile we care about failed in updating or could not be found at all. */ int any_failed = 0; unsigned int i; struct dep *d; for (i = 0, d = read_makefiles; d != 0; ++i, d = d->next) { /* Reset the considered flag; we may need to look at the file again to print an error. */ d->file->considered = 0; if (d->file->updated) { /* This makefile was updated. */ if (d->file->update_status == 0) { /* It was successfully updated. */ any_remade |= (file_mtime_no_search (d->file) != makefile_mtimes[i]); } else if (! (d->changed & RM_DONTCARE)) { FILE_TIMESTAMP mtime; /* The update failed and this makefile was not from the MAKEFILES variable, so we care. */ error (NILF, _("Failed to remake makefile `%s'."), d->file->name); mtime = file_mtime_no_search (d->file); any_remade |= (mtime != NONEXISTENT_MTIME && mtime != makefile_mtimes[i]); makefile_status = MAKE_FAILURE; } } else /* This makefile was not found at all. */ if (! (d->changed & RM_DONTCARE)) { /* This is a makefile we care about. See how much. */ if (d->changed & RM_INCLUDED) /* An included makefile. We don't need to die, but we do want to complain. */ error (NILF, _("Included makefile `%s' was not found."), dep_name (d)); else { /* A normal makefile. We must die later. */ error (NILF, _("Makefile `%s' was not found"), dep_name (d)); any_failed = 1; } } } /* Reset this to empty so we get the right error message below. */ read_makefiles = 0; if (any_remade) goto re_exec; if (any_failed) die (2); break; } case 0: re_exec: /* Updated successfully. Re-exec ourselves. */ remove_intermediates (0); if (print_data_base_flag) print_data_base (); log_working_directory (0); clean_jobserver (0); if (makefiles != 0) { /* These names might have changed. */ int i, j = 0; for (i = 1; i < argc; ++i) if (strneq (argv[i], "-f", 2)) /* XXX */ { if (argv[i][2] == '\0') /* This cast is OK since we never modify argv. */ argv[++i] = (char *) makefiles->list[j]; else argv[i] = xstrdup (concat (2, "-f", makefiles->list[j])); ++j; } } /* Add -o option for the stdin temporary file, if necessary. */ nargc = argc; if (stdin_nm) { nargv = xmalloc ((nargc + 2) * sizeof (char *)); memcpy (nargv, argv, argc * sizeof (char *)); nargv[nargc++] = xstrdup (concat (2, "-o", stdin_nm)); nargv[nargc] = 0; } else nargv = argv; if (directories != 0 && directories->idx > 0) { int bad = 1; if (directory_before_chdir != 0) { if (chdir (directory_before_chdir) < 0) perror_with_name ("chdir", ""); else bad = 0; } if (bad) fatal (NILF, _("Couldn't change back to original directory.")); } ++restarts; /* Reset makeflags in case they were changed. */ { const char *pv = define_makeflags (1, 1); char *p = alloca (sizeof ("MAKEFLAGS=") + strlen (pv) + 1); sprintf (p, "MAKEFLAGS=%s", pv); putenv (p); } if (ISDB (DB_BASIC)) { char **p; printf (_("Re-executing[%u]:"), restarts); for (p = nargv; *p != 0; ++p) printf (" %s", *p); putchar ('\n'); } #ifndef _AMIGA { char **p; for (p = environ; *p != 0; ++p) { if (strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH) && (*p)[MAKELEVEL_LENGTH] == '=') { *p = alloca (40); sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel); } if (strneq (*p, "MAKE_RESTARTS=", 14)) { *p = alloca (40); sprintf (*p, "MAKE_RESTARTS=%u", restarts); restarts = 0; } } } #else /* AMIGA */ { char buffer[256]; sprintf (buffer, "%u", makelevel); SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY); sprintf (buffer, "%u", restarts); SetVar ("MAKE_RESTARTS", buffer, -1, GVF_GLOBAL_ONLY); restarts = 0; } #endif /* If we didn't set the restarts variable yet, add it. */ if (restarts) { char *b = alloca (40); sprintf (b, "MAKE_RESTARTS=%u", restarts); putenv (b); } fflush (stdout); fflush (stderr); /* Close the dup'd jobserver pipe if we opened one. */ if (job_rfd >= 0) close (job_rfd); #ifdef _AMIGA exec_command (nargv); exit (0); #elif defined (__EMX__) { /* It is not possible to use execve() here because this would cause the parent process to be terminated with exit code 0 before the child process has been terminated. Therefore it may be the best solution simply to spawn the child process including all file handles and to wait for its termination. */ int pid; int status; pid = child_execute_job (0, 1, nargv, environ); /* is this loop really necessary? */ do { pid = wait (&status); } while (pid <= 0); /* use the exit code of the child process */ exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); } #else exec_command (nargv, environ); #endif /* NOTREACHED */ default: #define BOGUS_UPDATE_STATUS 0 assert (BOGUS_UPDATE_STATUS); break; } db_level = orig_db_level; /* Free the makefile mtimes (if we allocated any). */ if (makefile_mtimes) free (makefile_mtimes); } /* Set up `MAKEFLAGS' again for the normal targets. */ define_makeflags (1, 0); /* Set always_make_flag if -B was given. */ always_make_flag = always_make_set; /* If restarts is set we haven't set up -W files yet, so do that now. */ if (restarts && new_files != 0) { const char **p; for (p = new_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = NEW_MTIME; } } /* If there is a temp file from reading a makefile from stdin, get rid of it now. */ if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT) perror_with_name (_("unlink (temporary file): "), stdin_nm); /* If there were no command-line goals, use the default. */ if (goals == 0) { char *p; if (default_goal_var->recursive) p = variable_expand (default_goal_var->value); else { p = variable_buffer_output (variable_buffer, default_goal_var->value, strlen (default_goal_var->value)); *p = '\0'; p = variable_buffer; } if (*p != '\0') { struct file *f = lookup_file (p); /* If .DEFAULT_GOAL is a non-existent target, enter it into the table and let the standard logic sort it out. */ if (f == 0) { struct nameseq *ns; ns = PARSE_FILE_SEQ (&p, struct nameseq, '\0', NULL, 0); if (ns) { /* .DEFAULT_GOAL should contain one target. */ if (ns->next != 0) fatal (NILF, _(".DEFAULT_GOAL contains more than one target")); #ifndef CONFIG_WITH_VALUE_LENGTH f = enter_file (strcache_add (ns->name)); #else f = enter_file (ns->name); #endif ns->name = 0; /* It was reused by enter_file(). */ free_ns_chain (ns); } } if (f) { goals = alloc_dep (); goals->file = f; } } } else lastgoal->next = 0; if (!goals) { if (read_makefiles == 0) fatal (NILF, _("No targets specified and no makefile found")); fatal (NILF, _("No targets")); } /* Update the goals. */ DB (DB_BASIC, (_("Updating goal targets....\n"))); { int status; switch (update_goal_chain (goals)) { case -1: /* Nothing happened. */ case 0: /* Updated successfully. */ status = makefile_status; break; case 1: /* We are under -q and would run some commands. */ status = MAKE_TROUBLE; break; case 2: /* Updating failed. POSIX.2 specifies exit status >1 for this; but in VMS, there is only success and failure. */ status = MAKE_FAILURE; break; default: abort (); } /* If we detected some clock skew, generate one last warning */ if (clock_skew_detected) error (NILF, _("warning: Clock skew detected. Your build may be incomplete.")); /* Exit. */ die (status); } /* NOTREACHED */ return 0; } /* Parsing of arguments, decoding of switches. */ static char options[1 + sizeof (switches) / sizeof (switches[0]) * 3]; static struct option long_options[(sizeof (switches) / sizeof (switches[0])) + (sizeof (long_option_aliases) / sizeof (long_option_aliases[0]))]; /* Fill in the string and vector for getopt. */ static void init_switches (void) { char *p; unsigned int c; unsigned int i; if (options[0] != '\0') /* Already done. */ return; p = options; /* Return switch and non-switch args in order, regardless of POSIXLY_CORRECT. Non-switch args are returned as option 1. */ *p++ = '-'; for (i = 0; switches[i].c != '\0'; ++i) { long_options[i].name = (switches[i].long_name == 0 ? "" : switches[i].long_name); long_options[i].flag = 0; long_options[i].val = switches[i].c; if (short_option (switches[i].c)) *p++ = switches[i].c; switch (switches[i].type) { case flag: case flag_off: case ignore: long_options[i].has_arg = no_argument; break; case string: case filename: case positive_int: case floating: if (short_option (switches[i].c)) *p++ = ':'; if (switches[i].noarg_value != 0) { if (short_option (switches[i].c)) *p++ = ':'; long_options[i].has_arg = optional_argument; } else long_options[i].has_arg = required_argument; break; } } *p = '\0'; for (c = 0; c < (sizeof (long_option_aliases) / sizeof (long_option_aliases[0])); ++c) long_options[i++] = long_option_aliases[c]; long_options[i].name = 0; } static void handle_non_switch_argument (char *arg, int env) { /* Non-option argument. It might be a variable definition. */ struct variable *v; if (arg[0] == '-' && arg[1] == '\0') /* Ignore plain `-' for compatibility. */ return; v = try_variable_definition (0, arg IF_WITH_VALUE_LENGTH_PARAM(NULL), o_command, 0); if (v != 0) { /* It is indeed a variable definition. If we don't already have this one, record a pointer to the variable for later use in define_makeflags. */ struct command_variable *cv; for (cv = command_variables; cv != 0; cv = cv->next) if (cv->variable == v) break; if (! cv) { cv = xmalloc (sizeof (*cv)); cv->variable = v; cv->next = command_variables; command_variables = cv; } } else if (! env) { /* Not an option or variable definition; it must be a goal target! Enter it as a file and add it to the dep chain of goals. */ struct file *f = enter_file (strcache_add (expand_command_line_file (arg))); f->cmd_target = 1; if (goals == 0) { goals = alloc_dep (); lastgoal = goals; } else { lastgoal->next = alloc_dep (); lastgoal = lastgoal->next; } lastgoal->file = f; { /* Add this target name to the MAKECMDGOALS variable. */ struct variable *gv; const char *value; gv = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS")); if (gv == 0) value = f->name; else { /* Paste the old and new values together */ unsigned int oldlen, newlen; char *vp; oldlen = strlen (gv->value); newlen = strlen (f->name); vp = alloca (oldlen + 1 + newlen + 1); memcpy (vp, gv->value, oldlen); vp[oldlen] = ' '; memcpy (&vp[oldlen + 1], f->name, newlen + 1); value = vp; } define_variable_cname ("MAKECMDGOALS", value, o_default, 0); } } } /* Print a nice usage method. */ static void print_usage (int bad) { const char *const *cpp; FILE *usageto; if (print_version_flag) print_version (); usageto = bad ? stderr : stdout; fprintf (usageto, _("Usage: %s [options] [target] ...\n"), program); for (cpp = usage; *cpp; ++cpp) fputs (_(*cpp), usageto); #ifdef KMK if (!remote_description || *remote_description == '\0') fprintf (usageto, _("\nThis program is built for %s/%s/%s [" __DATE__ " " __TIME__ "]\n"), KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU); else fprintf (usageto, _("\nThis program is built for %s/%s/%s (%s) [" __DATE__ " " __TIME__ "]\n"), KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description); #else /* !KMK */ if (!remote_description || *remote_description == '\0') fprintf (usageto, _("\nThis program built for %s\n"), make_host); else fprintf (usageto, _("\nThis program built for %s (%s)\n"), make_host, remote_description); #endif /* !KMK */ fprintf (usageto, _("Report bugs to \n")); } /* Decode switches from ARGC and ARGV. They came from the environment if ENV is nonzero. */ static void decode_switches (int argc, char **argv, int env) { int bad = 0; register const struct command_switch *cs; register struct stringlist *sl; register int c; /* getopt does most of the parsing for us. First, get its vectors set up. */ init_switches (); /* Let getopt produce error messages for the command line, but not for options from the environment. */ opterr = !env; /* Reset getopt's state. */ optind = 0; while (optind < argc) { /* Parse the next argument. */ c = getopt_long (argc, argv, options, long_options, (int *) 0); if (c == EOF) /* End of arguments, or "--" marker seen. */ break; else if (c == 1) /* An argument not starting with a dash. */ handle_non_switch_argument (optarg, env); else if (c == '?') /* Bad option. We will print a usage message and die later. But continue to parse the other options so the user can see all he did wrong. */ bad = 1; else for (cs = switches; cs->c != '\0'; ++cs) if (cs->c == c) { /* Whether or not we will actually do anything with this switch. We test this individually inside the switch below rather than just once outside it, so that options which are to be ignored still consume args. */ int doit = !env || cs->env; switch (cs->type) { default: abort (); case ignore: break; case flag: case flag_off: if (doit) *(int *) cs->value_ptr = cs->type == flag; break; case string: case filename: if (!doit) break; if (optarg == 0) optarg = xstrdup (cs->noarg_value); else if (*optarg == '\0') { char opt[2] = "c"; const char *op = opt; if (short_option (cs->c)) opt[0] = cs->c; else op = cs->long_name; error (NILF, _("the `%s%s' option requires a non-empty string argument"), short_option (cs->c) ? "-" : "--", op); bad = 1; } sl = *(struct stringlist **) cs->value_ptr; if (sl == 0) { sl = (struct stringlist *) xmalloc (sizeof (struct stringlist)); sl->max = 5; sl->idx = 0; sl->list = xmalloc (5 * sizeof (char *)); *(struct stringlist **) cs->value_ptr = sl; } else if (sl->idx == sl->max - 1) { sl->max += 5; /* MSVC erroneously warns without a cast here. */ sl->list = xrealloc ((void *)sl->list, sl->max * sizeof (char *)); } if (cs->type == filename) sl->list[sl->idx++] = expand_command_line_file (optarg); else sl->list[sl->idx++] = optarg; sl->list[sl->idx] = 0; break; case positive_int: /* See if we have an option argument; if we do require that it's all digits, not something like "10foo". */ if (optarg == 0 && argc > optind) { const char *cp; for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp) ; if (cp[0] == '\0') optarg = argv[optind++]; } if (!doit) break; if (optarg != 0) { int i = atoi (optarg); const char *cp; /* Yes, I realize we're repeating this in some cases. */ for (cp = optarg; ISDIGIT (cp[0]); ++cp) ; if (i < 1 || cp[0] != '\0') { error (NILF, _("the `-%c' option requires a positive integral argument"), cs->c); bad = 1; } else *(unsigned int *) cs->value_ptr = i; } else *(unsigned int *) cs->value_ptr = *(unsigned int *) cs->noarg_value; break; #ifndef NO_FLOAT case floating: if (optarg == 0 && optind < argc && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.')) optarg = argv[optind++]; if (doit) *(double *) cs->value_ptr = (optarg != 0 ? atof (optarg) : *(double *) cs->noarg_value); break; #endif } /* We've found the switch. Stop looking. */ break; } } /* There are no more options according to getting getopt, but there may be some arguments left. Since we have asked for non-option arguments to be returned in order, this only happens when there is a "--" argument to prevent later arguments from being options. */ while (optind < argc) handle_non_switch_argument (argv[optind++], env); if (!env && (bad || print_usage_flag)) { print_usage (bad); die (bad ? 2 : 0); } } /* Decode switches from environment variable ENVAR (which is LEN chars long). We do this by chopping the value into a vector of words, prepending a dash to the first word if it lacks one, and passing the vector to decode_switches. */ static void decode_env_switches (char *envar, unsigned int len) { char *varref = alloca (2 + len + 2); char *value, *p; int argc; char **argv; /* Get the variable's value. */ varref[0] = '$'; varref[1] = '('; memcpy (&varref[2], envar, len); varref[2 + len] = ')'; varref[2 + len + 1] = '\0'; value = variable_expand (varref); /* Skip whitespace, and check for an empty value. */ value = next_token (value); len = strlen (value); if (len == 0) return; /* Allocate a vector that is definitely big enough. */ argv = alloca ((1 + len + 1) * sizeof (char *)); /* Allocate a buffer to copy the value into while we split it into words and unquote it. We must use permanent storage for this because decode_switches may store pointers into the passed argument words. */ p = xmalloc (2 * len); /* getopt will look at the arguments starting at ARGV[1]. Prepend a spacer word. */ argv[0] = 0; argc = 1; argv[argc] = p; while (*value != '\0') { if (*value == '\\' && value[1] != '\0') ++value; /* Skip the backslash. */ else if (isblank ((unsigned char)*value)) { /* End of the word. */ *p++ = '\0'; argv[++argc] = p; do ++value; while (isblank ((unsigned char)*value)); continue; } *p++ = *value++; } *p = '\0'; argv[++argc] = 0; if (argv[1][0] != '-' && strchr (argv[1], '=') == 0) /* The first word doesn't start with a dash and isn't a variable definition. Add a dash and pass it along to decode_switches. We need permanent storage for this in case decode_switches saves pointers into the value. */ argv[1] = xstrdup (concat (2, "-", argv[1])); /* Parse those words. */ decode_switches (argc, argv, 1); } /* Quote the string IN so that it will be interpreted as a single word with no magic by decode_env_switches; also double dollar signs to avoid variable expansion in make itself. Write the result into OUT, returning the address of the next character to be written. Allocating space for OUT twice the length of IN is always sufficient. */ static char * quote_for_env (char *out, const char *in) { while (*in != '\0') { if (*in == '$') *out++ = '$'; else if (isblank ((unsigned char)*in) || *in == '\\') *out++ = '\\'; *out++ = *in++; } return out; } /* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the command switches. Include options with args if ALL is nonzero. Don't include options with the `no_makefile' flag set if MAKEFILE. */ static const char * define_makeflags (int all, int makefile) { #ifdef KMK static const char ref[] = "$(KMK_OVERRIDES)"; #else static /*<- bird*/ const char ref[] = "$(MAKEOVERRIDES)"; #endif static /*<- bird*/ const char posixref[] = "$(-*-command-variables-*-)"; static /*<- bird*/ const char evalref[] = "$(-*-eval-flags-*-)"; const struct command_switch *cs; char *flagstring; register char *p; unsigned int words; struct variable *v; /* We will construct a linked list of `struct flag's describing all the flags which need to go in MAKEFLAGS. Then, once we know how many there are and their lengths, we can put them all together in a string. */ struct flag { struct flag *next; const struct command_switch *cs; const char *arg; }; struct flag *flags = 0; unsigned int flagslen = 0; #define ADD_FLAG(ARG, LEN) \ do { \ struct flag *new = alloca (sizeof (struct flag)); \ new->cs = cs; \ new->arg = (ARG); \ new->next = flags; \ flags = new; \ if (new->arg == 0) \ ++flagslen; /* Just a single flag letter. */ \ else \ /* " -x foo", plus space to expand "foo". */ \ flagslen += 1 + 1 + 1 + 1 + (3 * (LEN)); \ if (!short_option (cs->c)) \ /* This switch has no single-letter version, so we use the long. */ \ flagslen += 2 + strlen (cs->long_name); \ } while (0) for (cs = switches; cs->c != '\0'; ++cs) if (cs->toenv && (!makefile || !cs->no_makefile)) switch (cs->type) { case ignore: break; case flag: case flag_off: if (!*(int *) cs->value_ptr == (cs->type == flag_off) && (cs->default_value == 0 || *(int *) cs->value_ptr != *(int *) cs->default_value)) ADD_FLAG (0, 0); break; case positive_int: if (all) { if ((cs->default_value != 0 && (*(unsigned int *) cs->value_ptr == *(unsigned int *) cs->default_value))) break; else if (cs->noarg_value != 0 && (*(unsigned int *) cs->value_ptr == *(unsigned int *) cs->noarg_value)) ADD_FLAG ("", 0); /* Optional value omitted; see below. */ #if !defined(KMK) || !defined(WINDOWS32) /* jobserver stuff doesn't work on windows???. */ else if (cs->c == 'j') /* Special case for `-j'. */ ADD_FLAG ("1", 1); #endif else { char *buf = alloca (30); sprintf (buf, "%u", *(unsigned int *) cs->value_ptr); ADD_FLAG (buf, strlen (buf)); } } break; #ifndef NO_FLOAT case floating: if (all) { if (cs->default_value != 0 && (*(double *) cs->value_ptr == *(double *) cs->default_value)) break; else if (cs->noarg_value != 0 && (*(double *) cs->value_ptr == *(double *) cs->noarg_value)) ADD_FLAG ("", 0); /* Optional value omitted; see below. */ else { char *buf = alloca (100); sprintf (buf, "%g", *(double *) cs->value_ptr); ADD_FLAG (buf, strlen (buf)); } } break; #endif case filename: case string: if (all) { struct stringlist *sl = *(struct stringlist **) cs->value_ptr; if (sl != 0) { /* Add the elements in reverse order, because all the flags get reversed below; and the order matters for some switches (like -I). */ unsigned int i = sl->idx; while (i-- > 0) ADD_FLAG (sl->list[i], strlen (sl->list[i])); } } break; default: abort (); } /* Four more for the possible " -- ". */ flagslen += 4 + sizeof (posixref) + sizeof (evalref); #undef ADD_FLAG /* Construct the value in FLAGSTRING. We allocate enough space for a preceding dash and trailing null. */ flagstring = alloca (1 + flagslen + 1); memset (flagstring, '\0', 1 + flagslen + 1); p = flagstring; words = 1; *p++ = '-'; while (flags != 0) { /* Add the flag letter or name to the string. */ if (short_option (flags->cs->c)) *p++ = flags->cs->c; else { if (*p != '-') { *p++ = ' '; *p++ = '-'; } *p++ = '-'; strcpy (p, flags->cs->long_name); p += strlen (p); } if (flags->arg != 0) { /* A flag that takes an optional argument which in this case is omitted is specified by ARG being "". We must distinguish because a following flag appended without an intervening " -" is considered the arg for the first. */ if (flags->arg[0] != '\0') { /* Add its argument too. */ *p++ = !short_option (flags->cs->c) ? '=' : ' '; p = quote_for_env (p, flags->arg); } ++words; /* Write a following space and dash, for the next flag. */ *p++ = ' '; *p++ = '-'; } else if (!short_option (flags->cs->c)) { ++words; /* Long options must each go in their own word, so we write the following space and dash. */ *p++ = ' '; *p++ = '-'; } flags = flags->next; } /* Define MFLAGS before appending variable definitions. */ if (p == &flagstring[1]) /* No flags. */ flagstring[0] = '\0'; else if (p[-1] == '-') { /* Kill the final space and dash. */ p -= 2; *p = '\0'; } else /* Terminate the string. */ *p = '\0'; #ifdef KMK /* Since MFLAGS is not parsed for flags, there is no reason to override any makefile redefinition. */ define_variable_cname ("MFLAGS", flagstring, o_env, 1); #endif /* !KMK */ /* Write a reference to -*-eval-flags-*-, which contains all the --eval flag options. */ if (eval_strings) { if (p == &flagstring[1]) /* No flags written, so elide the leading dash already written. */ p = flagstring; else *p++ = ' '; memcpy (p, evalref, sizeof (evalref) - 1); p += sizeof (evalref) - 1; } if (all && command_variables != 0) { /* Now write a reference to $(MAKEOVERRIDES), which contains all the command-line variable definitions. */ if (p == &flagstring[1]) /* No flags written, so elide the leading dash already written. */ p = flagstring; else { /* Separate the variables from the switches with a "--" arg. */ if (p[-1] != '-') { /* We did not already write a trailing " -". */ *p++ = ' '; *p++ = '-'; } /* There is a trailing " -"; fill it out to " -- ". */ *p++ = '-'; *p++ = ' '; } /* Copy in the string. */ if (posix_pedantic) { memcpy (p, posixref, sizeof (posixref) - 1); p += sizeof (posixref) - 1; } else { memcpy (p, ref, sizeof (ref) - 1); p += sizeof (ref) - 1; } } else if (p == &flagstring[1]) { words = 0; --p; } else if (p[-1] == '-') /* Kill the final space and dash. */ p -= 2; /* Terminate the string. */ *p = '\0'; /* If there are switches, omit the leading dash unless it is a single long option with two leading dashes. */ if (flagstring[0] == '-' && flagstring[1] != '-') ++flagstring; #ifdef KMK v = define_variable_cname ("KMK_FLAGS", flagstring, /* This used to use o_env, but that lost when a makefile defined MAKEFLAGS. Makefiles set MAKEFLAGS to add switches, but we still want to redefine its value with the full set of switches. Of course, an override or command definition will still take precedence. */ o_file, 1); #else v = define_variable_cname ("MAKEFLAGS", flagstring, /* This used to use o_env, but that lost when a makefile defined MAKEFLAGS. Makefiles set MAKEFLAGS to add switches, but we still want to redefine its value with the full set of switches. Of course, an override or command definition will still take precedence. */ o_file, 1); #endif if (! all) /* The first time we are called, set MAKEFLAGS to always be exported. We should not do this again on the second call, because that is after reading makefiles which might have done `unexport MAKEFLAGS'. */ v->export = v_export; #ifdef KMK /* Provide simple access to some of the options. */ { char val[32]; sprintf (val, "%u", job_slots); define_variable_cname ("KMK_OPTS_JOBS", val, o_default, 1); define_variable_cname ("KMK_OPTS_KEEP_GOING", keep_going_flag ? "1" : "0", o_default, 1); define_variable_cname ("KMK_OPTS_JUST_PRINT", just_print_flag ? "1" : "0", o_default, 1); define_variable_cname ("KMK_OPTS_PRETTY_COMMAND_PRINTING", pretty_command_printing ? "1" : "0", o_default, 1); sprintf (val, "%u", process_priority); define_variable_cname ("KMK_OPTS_PRORITY", val, o_default, 1); sprintf (val, "%u", process_affinity); define_variable_cname ("KMK_OPTS_AFFINITY", val, o_default, 1); # if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) define_variable_cname ("KMK_OPTS_STATISTICS", make_expensive_statistics ? "1" : "0", o_default, 1); # endif # ifdef CONFIG_WITH_PRINT_TIME_SWITCH sprintf (val, "%u", print_time_min); define_variable_cname ("KMK_OPTS_PRINT_TIME", val, o_default, 1); # endif } #endif return v->value; } /* Print version information. */ static void print_version (void) { static int printed_version = 0; char *precede = print_data_base_flag ? "# " : ""; if (printed_version) /* Do it only once. */ return; #ifdef KMK printf ("%skmk - kBuild version %d.%d.%d (r%u)\n\ \n", precede, KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); printf("%sBased on GNU Make %s:\n", precede, version_string); #else /* !KMK */ printf ("%sGNU Make %s\n", precede, version_string); if (!remote_description || *remote_description == '\0') printf (_("%sBuilt for %s\n"), precede, make_host); else printf (_("%sBuilt for %s (%s)\n"), precede, make_host, remote_description); #endif /* !KMK */ /* Print this untranslated. The coding standards recommend translating the (C) to the copyright symbol, but this string is going to change every year, and none of the rest of it should be translated (including the word "Copyright", so it hardly seems worth it. */ printf ("%sCopyright (C) 2010 Free Software Foundation, Inc.\n", precede); printf (_("%sLicense GPLv3+: GNU GPL version 3 or later \n\ %sThis is free software: you are free to change and redistribute it.\n\ %sThere is NO WARRANTY, to the extent permitted by law.\n"), precede, precede, precede); #ifdef KMK printf ("\n\ %skBuild modifications:\n\ %s Copyright (c) 2005-2009 knut st. osmundsen.\n\ \n\ %skmkbuiltin commands derived from *BSD sources:\n\ %s Copyright (c) 1983 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994\n\ %s The Regents of the University of California. All rights reserved.\n\ %s Copyright (c) 1998 Todd C. Miller \n", precede, precede, precede, precede, precede, precede); # ifdef KBUILD_PATH printf (_("\n\ %sKBUILD_PATH: '%s' (default '%s')\n\ %sKBUILD_BIN_PATH: '%s' (default '%s')\n\ \n"), precede, get_kbuild_path(), KBUILD_PATH, precede, get_kbuild_bin_path(), KBUILD_BIN_PATH); # else /* !KBUILD_PATH */ printf ("\n\ %sKBUILD_PATH: '%s'\n\ %sKBUILD_BIN_PATH: '%s'\n\ \n", precede, get_kbuild_path(), precede, get_kbuild_bin_path()); # endif /* !KBUILD_PATH */ if (!remote_description || *remote_description == '\0') printf (_("%sThis program is a %s build, built for %s/%s/%s [" __DATE__ " " __TIME__ "]\n\n"), precede, KBUILD_TYPE, KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU); else printf (_("%sThis program is a %s build, built for %s/%s/%s (%s) [" __DATE__ " " __TIME__ "]\n\n"), precede, KBUILD_TYPE, KBUILD_HOST, KBUILD_HOST_ARCH, KBUILD_HOST_CPU, remote_description); #endif /* KMK */ printed_version = 1; /* Flush stdout so the user doesn't have to wait to see the version information while things are thought about. */ fflush (stdout); } /* Print a bunch of information about this and that. */ static void print_data_base () { time_t when; when = time ((time_t *) 0); printf (_("\n# Make data base, printed on %s"), ctime (&when)); print_variable_data_base (); print_dir_data_base (); print_rule_data_base (); print_file_data_base (); print_vpath_data_base (); #ifdef KMK print_kbuild_data_base (); #endif #ifndef CONFIG_WITH_STRCACHE2 strcache_print_stats ("#"); #else strcache2_print_stats_all ("#"); #endif #ifdef CONFIG_WITH_ALLOC_CACHES alloccache_print_all (); #endif when = time ((time_t *) 0); printf (_("\n# Finished Make data base on %s\n"), ctime (&when)); } #ifdef CONFIG_WITH_PRINT_STATS_SWITCH static void print_stats () { time_t when; when = time ((time_t *) 0); printf (_("\n# Make statistics, printed on %s"), ctime (&when)); print_variable_stats (); print_file_stats (); # ifdef KMK print_kbuild_define_stats (); # endif # ifndef CONFIG_WITH_STRCACHE2 strcache_print_stats ("#"); # else strcache2_print_stats_all ("#"); # endif # ifdef CONFIG_WITH_ALLOC_CACHES alloccache_print_all (); # endif print_heap_stats (); when = time ((time_t *) 0); printf (_("\n# Finished Make statistics on %s\n"), ctime (&when)); } #endif static void clean_jobserver (int status) { char token = '+'; /* Sanity: have we written all our jobserver tokens back? If our exit status is 2 that means some kind of syntax error; we might not have written all our tokens so do that now. If tokens are left after any other error code, that's bad. */ if (job_fds[0] != -1 && jobserver_tokens) { if (status != 2) error (NILF, "INTERNAL: Exiting with %u jobserver tokens (should be 0)!", jobserver_tokens); else while (jobserver_tokens--) { int r; EINTRLOOP (r, write (job_fds[1], &token, 1)); if (r != 1) perror_with_name ("write", ""); } } /* Sanity: If we're the master, were all the tokens written back? */ if (master_job_slots) { /* We didn't write one for ourself, so start at 1. */ unsigned int tcnt = 1; /* Close the write side, so the read() won't hang. */ close (job_fds[1]); while (read (job_fds[0], &token, 1) == 1) ++tcnt; if (tcnt != master_job_slots) error (NILF, "INTERNAL: Exiting with %u jobserver tokens available; should be %u!", tcnt, master_job_slots); close (job_fds[0]); /* Clean out jobserver_fds so we don't pass this information to any sub-makes. Also reset job_slots since it will be put on the command line, not in MAKEFLAGS. */ job_slots = default_job_slots; if (jobserver_fds) { /* MSVC erroneously warns without a cast here. */ free ((void *)jobserver_fds->list); free (jobserver_fds); jobserver_fds = 0; } } } /* Exit with STATUS, cleaning up as necessary. */ void die (int status) { static char dying = 0; #ifdef KMK static char need_2nd_error = 0; #endif if (!dying) { int err; dying = 1; if (print_version_flag) print_version (); #ifdef KMK /* Flag 2nd error message. */ if (status != 0 && ( job_slots_used > 0 || print_data_base_flag || print_stats_flag)) need_2nd_error = 1; #endif /* KMK */ /* Wait for children to die. */ err = (status != 0); while (job_slots_used > 0) reap_children (1, err); /* Let the remote job module clean up its state. */ remote_cleanup (); /* Remove the intermediate files. */ remove_intermediates (0); if (print_data_base_flag) print_data_base (); #ifdef CONFIG_WITH_PRINT_STATS_SWITCH if (print_stats_flag) print_stats (); #endif #ifdef NDEBUG /* bird: Don't waste time on debug sanity checks. */ if (print_data_base_flag || db_level) #endif verify_file_data_base (); clean_jobserver (status); /* Try to move back to the original directory. This is essential on MS-DOS (where there is really only one process), and on Unix it puts core files in the original directory instead of the -C directory. Must wait until after remove_intermediates(), or unlinks of relative pathnames fail. */ if (directory_before_chdir != 0) { /* If it fails we don't care: shut up GCC. */ int _x; _x = chdir (directory_before_chdir); } #ifdef CONFIG_WITH_PRINT_TIME_SWITCH if (print_time_min != -1) { big_int elapsed = nano_timestamp () - make_start_ts; if (elapsed >= print_time_min * BIG_INT_C(1000000000)) { char buf[64]; format_elapsed_nano (buf, sizeof (buf), elapsed); message (1, _("%*s"), print_time_width, buf); } } #endif log_working_directory (0); } #ifdef KMK /* The failure might be lost in a -j run, so mention the failure again before exiting. */ if (need_2nd_error != 0) error (NILF, _("*** Exiting with status %d"), status); #endif exit (status); } /* Write a message indicating that we've just entered or left (according to ENTERING) the current directory. */ void log_working_directory (int entering) { static int entered = 0; /* Print nothing without the flag. Don't print the entering message again if we already have. Don't print the leaving message if we haven't printed the entering message. */ if (! print_directory_flag || entering == entered) return; entered = entering; if (print_data_base_flag) fputs ("# ", stdout); /* Use entire sentences to give the translators a fighting chance. */ if (makelevel == 0) if (starting_directory == 0) if (entering) printf (_("%s: Entering an unknown directory\n"), program); else printf (_("%s: Leaving an unknown directory\n"), program); else if (entering) printf (_("%s: Entering directory `%s'\n"), program, starting_directory); else printf (_("%s: Leaving directory `%s'\n"), program, starting_directory); else if (starting_directory == 0) if (entering) printf (_("%s[%u]: Entering an unknown directory\n"), program, makelevel); else printf (_("%s[%u]: Leaving an unknown directory\n"), program, makelevel); else if (entering) printf (_("%s[%u]: Entering directory `%s'\n"), program, makelevel, starting_directory); else printf (_("%s[%u]: Leaving directory `%s'\n"), program, makelevel, starting_directory); /* Flush stdout to be sure this comes before any stderr output. */ fflush (stdout); } kbuild-2695/src/kmk/getopt.h0000644000000000000000000001076112247157306014471 0ustar rootroot/* Declarations for getopt. Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* getopt.h */ kbuild-2695/src/kmk/testcase-includedep-sub.kmk0000644000000000000000000000167412247157306020241 0ustar rootroot# $Id: testcase-includedep-sub.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the includdep directive, helper file # that gets included all the time. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # testcase-includedep-sub.kmk=included kbuild-2695/src/kmk/arscan.c0000644000000000000000000005271612247157307014440 0ustar rootroot/* Library function for scanning an archive file. Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #ifdef HAVE_FCNTL_H #include #else #include #endif #ifndef NO_ARCHIVES #ifdef VMS #include #include #include #include #include #if __DECC #include #include #endif static void *VMS_lib_idx; static char *VMS_saved_memname; static time_t VMS_member_date; static long int (*VMS_function) (); static int VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa) { int status, i; long int fnval; time_t val; static struct dsc$descriptor_s bufdesc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; struct mhddef *mhd; char filename[128]; bufdesc.dsc$a_pointer = filename; bufdesc.dsc$w_length = sizeof (filename); status = lbr$set_module (&VMS_lib_idx, rfa, &bufdesc, &bufdesc.dsc$w_length, 0); if (! (status & 1)) { error (NILF, _("lbr$set_module() failed to extract module info, status = %d"), status); lbr$close (&VMS_lib_idx); return 0; } mhd = (struct mhddef *) filename; #ifdef __DECC /* John Fowler writes this is needed in his environment, * but that decc$fix_time() isn't documented to work this way. Let me * know if this causes problems in other VMS environments. */ { /* Modified by M. Gehre at 11-JAN-2008 because old formula is wrong: * val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600; * a) daylight specifies, if the timezone has daylight saving enabled, not * if it is active * b) what we need is the information, if daylight saving was active, if * the library module was replaced. This information we get using the * localtime function */ struct tm *tmp; /* Conversion from VMS time to C time */ val = decc$fix_time (&mhd->mhd$l_datim); /* * Conversion from local time (stored in library) to GMT (needed for gmake) * Note: The tm_gmtoff element is a VMS extension to the ANSI standard. */ tmp = localtime (&val); val -= tmp->tm_gmtoff; } #endif for (i = 0; i < module->dsc$w_length; i++) filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]); filename[i] = '\0'; VMS_member_date = (time_t) -1; fnval = (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0, VMS_saved_memname); if (fnval) { VMS_member_date = fnval; return 0; } else return 1; } /* Takes three arguments ARCHIVE, FUNCTION and ARG. Open the archive named ARCHIVE, find its members one by one, and for each one call FUNCTION with the following arguments: archive file descriptor for reading the data, member name, member name might be truncated flag, member header position in file, member data position in file, member data size, member date, member uid, member gid, member protection mode, ARG. NOTE: on VMS systems, only name, date, and arg are meaningful! The descriptor is poised to read the data of the member when FUNCTION is called. It does not matter how much data FUNCTION reads. If FUNCTION returns nonzero, we immediately return what FUNCTION returned. Returns -1 if archive does not exist, Returns -2 if archive has invalid format. Returns 0 if have scanned successfully. */ long int ar_scan (const char *archive, ar_member_func_t function, const void *arg) { char *p; static struct dsc$descriptor_s libdesc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; unsigned long func = LBR$C_READ; unsigned long type = LBR$C_TYP_UNK; unsigned long index = 1; int status; status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0); if (! (status & 1)) { error (NILF, _("lbr$ini_control() failed with status = %d"), status); return -2; } /* there is no such descriptor with "const char *dsc$a_pointer" */ libdesc.dsc$a_pointer = (char *)archive; libdesc.dsc$w_length = strlen (archive); status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0); if (! (status & 1)) { error (NILF, _("unable to open library `%s' to lookup member `%s'"), archive, (char *)arg); return -1; } VMS_saved_memname = (char *)arg; /* For comparison, delete .obj from arg name. */ p = strrchr (VMS_saved_memname, '.'); if (p) *p = '\0'; VMS_function = function; VMS_member_date = (time_t) -1; lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0); /* Undo the damage. */ if (p) *p = '.'; lbr$close (&VMS_lib_idx); return VMS_member_date > 0 ? VMS_member_date : 0; } #else /* !VMS */ /* SCO Unix's compiler defines both of these. */ #ifdef M_UNIX #undef M_XENIX #endif /* On the sun386i and in System V rel 3, ar.h defines two different archive formats depending upon whether you have defined PORTAR (normal) or PORT5AR (System V Release 1). There is no default, one or the other must be defined to have a nonzero value. */ #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0) #undef PORTAR #ifdef M_XENIX /* According to Jim Sievert , for SCO XENIX defining PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the right one. */ #define PORTAR 0 #else #define PORTAR 1 #endif #endif /* On AIX, define these symbols to be sure to get both archive formats. AIX 4.3 introduced the "big" archive format to support 64-bit object files, so on AIX 4.3 systems we need to support both the "normal" and "big" archive formats. An archive's format is indicated in the "fl_magic" field of the "FL_HDR" structure. For a normal archive, this field will be the string defined by the AIAMAG symbol. For a "big" archive, it will be the string defined by the AIAMAGBIG symbol (at least on AIX it works this way). Note: we'll define these symbols regardless of which AIX version we're compiling on, but this is okay since we'll use the new symbols only if they're present. */ #ifdef _AIX # define __AR_SMALL__ # define __AR_BIG__ #endif #ifndef WINDOWS32 # if !defined(__BEOS__) && !defined(__HAIKU__) # include # else /* BeOS 5 doesn't have but has archives in the same format * as many other Unices. This was taken from GNU binutils for BeOS. */ # define ARMAG "!\n" /* String that begins an archive file. */ # define SARMAG 8 /* Size of that string. */ # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */ struct ar_hdr { char ar_name[16]; /* Member file name, sometimes / terminated. */ char ar_date[12]; /* File date, decimal seconds since Epoch. */ char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */ char ar_mode[8]; /* File mode, in ASCII octal. */ char ar_size[10]; /* File size, in ASCII decimal. */ char ar_fmag[2]; /* Always contains ARFMAG. */ }; # endif # define TOCHAR(_m) (_m) #else /* These should allow us to read Windows (VC++) libraries (according to Frank * Libbrecht ) */ # include # include # include # define ARMAG IMAGE_ARCHIVE_START # define SARMAG IMAGE_ARCHIVE_START_SIZE # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER # define ar_name Name # define ar_mode Mode # define ar_size Size # define ar_date Date # define ar_uid UserID # define ar_gid GroupID /* In Windows the member names have type BYTE so we must cast them. */ # define TOCHAR(_m) ((char *)(_m)) #endif /* Cray's apparently defines this. */ #ifndef AR_HDR_SIZE # define AR_HDR_SIZE (sizeof (struct ar_hdr)) #endif /* Takes three arguments ARCHIVE, FUNCTION and ARG. Open the archive named ARCHIVE, find its members one by one, and for each one call FUNCTION with the following arguments: archive file descriptor for reading the data, member name, member name might be truncated flag, member header position in file, member data position in file, member data size, member date, member uid, member gid, member protection mode, ARG. The descriptor is poised to read the data of the member when FUNCTION is called. It does not matter how much data FUNCTION reads. If FUNCTION returns nonzero, we immediately return what FUNCTION returned. Returns -1 if archive does not exist, Returns -2 if archive has invalid format. Returns 0 if have scanned successfully. */ long int ar_scan (const char *archive, ar_member_func_t function, const void *arg) { #ifdef AIAMAG FL_HDR fl_header; #ifdef AIAMAGBIG int big_archive = 0; FL_HDR_BIG fl_header_big; #endif #else int long_name = 0; #endif char *namemap = 0; int desc = open (archive, O_RDONLY, 0); if (desc < 0) return -1; #ifdef SARMAG { char buf[SARMAG]; register int nread = read (desc, buf, SARMAG); if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG)) { (void) close (desc); return -2; } } #else #ifdef AIAMAG { register int nread = read (desc, &fl_header, FL_HSZ); if (nread != FL_HSZ) { (void) close (desc); return -2; } #ifdef AIAMAGBIG /* If this is a "big" archive, then set the flag and re-read the header into the "big" structure. */ if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG)) { big_archive = 1; /* seek back to beginning of archive */ if (lseek (desc, 0, 0) < 0) { (void) close (desc); return -2; } /* re-read the header into the "big" structure */ nread = read (desc, &fl_header_big, FL_HSZ_BIG); if (nread != FL_HSZ_BIG) { (void) close (desc); return -2; } } else #endif /* Check to make sure this is a "normal" archive. */ if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG)) { (void) close (desc); return -2; } } #else { #ifndef M_XENIX int buf; #else unsigned short int buf; #endif register int nread = read(desc, &buf, sizeof (buf)); if (nread != sizeof (buf) || buf != ARMAG) { (void) close (desc); return -2; } } #endif #endif /* Now find the members one by one. */ { #ifdef SARMAG register long int member_offset = SARMAG; #else #ifdef AIAMAG long int member_offset; long int last_member_offset; #ifdef AIAMAGBIG if ( big_archive ) { sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset); sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset); } else #endif { sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset); sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset); } if (member_offset == 0) { /* Empty archive. */ close (desc); return 0; } #else #ifndef M_XENIX register long int member_offset = sizeof (int); #else /* Xenix. */ register long int member_offset = sizeof (unsigned short int); #endif /* Not Xenix. */ #endif #endif while (1) { register int nread; struct ar_hdr member_header; #ifdef AIAMAGBIG struct ar_hdr_big member_header_big; #endif #ifdef AIAMAG char name[256]; int name_len; long int dateval; int uidval, gidval; long int data_offset; #else char namebuf[sizeof member_header.ar_name + 1]; char *name; int is_namemap; /* Nonzero if this entry maps long names. */ #endif long int eltsize; int eltmode; long int fnval; if (lseek (desc, member_offset, 0) < 0) { (void) close (desc); return -2; } #ifdef AIAMAG #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name)) #ifdef AIAMAGBIG if (big_archive) { nread = read (desc, &member_header_big, AR_MEMHDR_SZ(member_header_big) ); if (nread != AR_MEMHDR_SZ(member_header_big)) { (void) close (desc); return -2; } sscanf (member_header_big.ar_namlen, "%4d", &name_len); nread = read (desc, name, name_len); if (nread != name_len) { (void) close (desc); return -2; } name[name_len] = 0; sscanf (member_header_big.ar_date, "%12ld", &dateval); sscanf (member_header_big.ar_uid, "%12d", &uidval); sscanf (member_header_big.ar_gid, "%12d", &gidval); sscanf (member_header_big.ar_mode, "%12o", &eltmode); sscanf (member_header_big.ar_size, "%20ld", &eltsize); data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big) + name_len + 2); } else #endif { nread = read (desc, &member_header, AR_MEMHDR_SZ(member_header) ); if (nread != AR_MEMHDR_SZ(member_header)) { (void) close (desc); return -2; } sscanf (member_header.ar_namlen, "%4d", &name_len); nread = read (desc, name, name_len); if (nread != name_len) { (void) close (desc); return -2; } name[name_len] = 0; sscanf (member_header.ar_date, "%12ld", &dateval); sscanf (member_header.ar_uid, "%12d", &uidval); sscanf (member_header.ar_gid, "%12d", &gidval); sscanf (member_header.ar_mode, "%12o", &eltmode); sscanf (member_header.ar_size, "%12ld", &eltsize); data_offset = (member_offset + AR_MEMHDR_SZ(member_header) + name_len + 2); } data_offset += data_offset % 2; fnval = (*function) (desc, name, 0, member_offset, data_offset, eltsize, dateval, uidval, gidval, eltmode, arg); #else /* Not AIAMAG. */ nread = read (desc, &member_header, AR_HDR_SIZE); if (nread == 0) /* No data left means end of file; that is OK. */ break; if (nread != AR_HDR_SIZE #if defined(ARFMAG) || defined(ARFZMAG) || ( # ifdef ARFMAG memcmp (member_header.ar_fmag, ARFMAG, 2) # else 1 # endif && # ifdef ARFZMAG memcmp (member_header.ar_fmag, ARFZMAG, 2) # else 1 # endif ) #endif ) { (void) close (desc); return -2; } name = namebuf; memcpy (name, member_header.ar_name, sizeof member_header.ar_name); { register char *p = name + sizeof member_header.ar_name; do *p = '\0'; while (p > name && *--p == ' '); #ifndef AIAMAG /* If the member name is "//" or "ARFILENAMES/" this may be a list of file name mappings. The maximum file name length supported by the standard archive format is 14 characters. This member will actually always be the first or second entry in the archive, but we don't check that. */ is_namemap = (!strcmp (name, "//") || !strcmp (name, "ARFILENAMES/")); #endif /* Not AIAMAG. */ /* On some systems, there is a slash after each member name. */ if (*p == '/') *p = '\0'; #ifndef AIAMAG /* If the member name starts with a space or a slash, this is an index into the file name mappings (used by GNU ar). Otherwise if the member name looks like #1/NUMBER the real member name appears in the element data (used by 4.4BSD). */ if (! is_namemap && (name[0] == ' ' || name[0] == '/') && namemap != 0) { name = namemap + atoi (name + 1); long_name = 1; } else if (name[0] == '#' && name[1] == '1' && name[2] == '/') { int namesize = atoi (name + 3); name = alloca (namesize + 1); nread = read (desc, name, namesize); if (nread != namesize) { close (desc); return -2; } name[namesize] = '\0'; long_name = 1; } #endif /* Not AIAMAG. */ } #ifndef M_XENIX sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode); eltsize = atol (TOCHAR (member_header.ar_size)); #else /* Xenix. */ eltmode = (unsigned short int) member_header.ar_mode; eltsize = member_header.ar_size; #endif /* Not Xenix. */ fnval = (*function) (desc, name, ! long_name, member_offset, member_offset + AR_HDR_SIZE, eltsize, #ifndef M_XENIX atol (TOCHAR (member_header.ar_date)), atoi (TOCHAR (member_header.ar_uid)), atoi (TOCHAR (member_header.ar_gid)), #else /* Xenix. */ member_header.ar_date, member_header.ar_uid, member_header.ar_gid, #endif /* Not Xenix. */ eltmode, arg); #endif /* AIAMAG. */ if (fnval) { (void) close (desc); return fnval; } #ifdef AIAMAG if (member_offset == last_member_offset) /* End of the chain. */ break; #ifdef AIAMAGBIG if (big_archive) sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset); else #endif sscanf (member_header.ar_nxtmem, "%12ld", &member_offset); if (lseek (desc, member_offset, 0) != member_offset) { (void) close (desc); return -2; } #else /* If this member maps archive names, we must read it in. The name map will always precede any members whose names must be mapped. */ if (is_namemap) { char *clear; char *limit; namemap = alloca (eltsize); nread = read (desc, namemap, eltsize); if (nread != eltsize) { (void) close (desc); return -2; } /* The names are separated by newlines. Some formats have a trailing slash. Null terminate the strings for convenience. */ limit = namemap + eltsize; for (clear = namemap; clear < limit; clear++) { if (*clear == '\n') { *clear = '\0'; if (clear[-1] == '/') clear[-1] = '\0'; } } is_namemap = 0; } member_offset += AR_HDR_SIZE + eltsize; if (member_offset % 2 != 0) member_offset++; #endif } } close (desc); return 0; } #endif /* !VMS */ /* Return nonzero iff NAME matches MEM. If TRUNCATED is nonzero, MEM may be truncated to sizeof (struct ar_hdr.ar_name) - 1. */ int ar_name_equal (const char *name, const char *mem, int truncated) { const char *p; p = strrchr (name, '/'); if (p != 0) name = p + 1; #ifndef VMS if (truncated) { #ifdef AIAMAG /* TRUNCATED should never be set on this system. */ abort (); #else struct ar_hdr hdr; #if !defined (__hpux) && !defined (cray) return strneq (name, mem, sizeof(hdr.ar_name) - 1); #else return strneq (name, mem, sizeof(hdr.ar_name) - 2); #endif /* !__hpux && !cray */ #endif /* !AIAMAG */ } #endif /* !VMS */ return !strcmp (name, mem); } #ifndef VMS /* ARGSUSED */ static long int ar_member_pos (int desc UNUSED, const char *mem, int truncated, long int hdrpos, long int datapos UNUSED, long int size UNUSED, long int date UNUSED, int uid UNUSED, int gid UNUSED, int mode UNUSED, const void *name) { if (!ar_name_equal (name, mem, truncated)) return 0; return hdrpos; } /* Set date of member MEMNAME in archive ARNAME to current time. Returns 0 if successful, -1 if file ARNAME does not exist, -2 if not a valid archive, -3 if other random system call error (including file read-only), 1 if valid but member MEMNAME does not exist. */ int ar_member_touch (const char *arname, const char *memname) { long int pos = ar_scan (arname, ar_member_pos, memname); int fd; struct ar_hdr ar_hdr; int i; unsigned int ui; struct stat statbuf; if (pos < 0) return (int) pos; if (!pos) return 1; fd = open (arname, O_RDWR, 0666); if (fd < 0) return -3; /* Read in this member's header */ if (lseek (fd, pos, 0) < 0) goto lose; if (AR_HDR_SIZE != read (fd, &ar_hdr, AR_HDR_SIZE)) goto lose; /* Write back the header, thus touching the archive file. */ if (lseek (fd, pos, 0) < 0) goto lose; if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE)) goto lose; /* The file's mtime is the time we we want. */ EINTRLOOP (i, fstat (fd, &statbuf)); if (i < 0) goto lose; #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32) /* Advance member's time to that time */ for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++) ar_hdr.ar_date[ui] = ' '; sprintf (TOCHAR (ar_hdr.ar_date), "%ld", (long int) statbuf.st_mtime); #ifdef AIAMAG ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' '; #endif #else ar_hdr.ar_date = statbuf.st_mtime; #endif /* Write back this member's header */ if (lseek (fd, pos, 0) < 0) goto lose; if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE)) goto lose; close (fd); return 0; lose: i = errno; close (fd); errno = i; return -3; } #endif #ifdef TEST long int describe_member (int desc, const char *name, int truncated, long int hdrpos, long int datapos, long int size, long int date, int uid, int gid, int mode, const void *arg) { extern char *ctime (); printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"), name, truncated ? _(" (name might be truncated)") : "", size, hdrpos, datapos); printf (_(" Date %s"), ctime (&date)); printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode); return 0; } int main (int argc, char **argv) { ar_scan (argv[1], describe_member, NULL); return 0; } #endif /* TEST. */ #endif /* NO_ARCHIVES. */ kbuild-2695/src/kmk/config.h.W32.template0000644000000000000000000003572312247157306016625 0ustar rootroot/* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Suppress some Visual C++ warnings. Maybe after the code cleanup for ISO C we can remove some/all of these. */ #if _MSC_VER > 1000 # pragma warning(disable:4100) /* unreferenced formal parameter */ # pragma warning(disable:4102) /* unreferenced label */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4131) /* uses old-style declarator */ # pragma warning(disable:4702) /* unreachable code */ # define _CRT_SECURE_NO_WARNINGS /* function or variable may be unsafe */ # define _CRT_NONSTDC_NO_WARNINGS /* functions w/o a leading underscore */ #endif /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if using `getloadavg.c'. */ /*#define C_GETLOADAVG 1*/ /* Define to 1 for DGUX with . */ /* #undef DGUX */ /* Define to 1 if translation of program messages to the user's native language is requested. */ /* #undef ENABLE_NLS */ /* Use high resolution file timestamps if nonzero. */ #define FILE_TIMESTAMP_HI_RES 0 /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ /* #undef GETLOADAVG_PRIVILEGED */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define if your compiler conforms to the ANSI C standard. */ #define HAVE_ANSI_COMPILER 1 /* Define to 1 if you have the `bsd_signal' function. */ /* #undef HAVE_BSD_SIGNAL */ /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define if you have the clock_gettime function. */ /* #undef HAVE_CLOCK_GETTIME */ /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* #undef HAVE_DCGETTEXT */ /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file, and it defines getcwd() and chdir(). */ #if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__INTERIX) # define HAVE_DIRECT_H 1 #endif /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Use platform specific coding */ #define HAVE_DOS_PATHS 1 /* Define to 1 if you have the `dup2' function. */ #define HAVE_DUP2 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fdopen' function. */ /*#define HAVE_FDOPEN 1*/ /* Define to 1 if you have the `fork' function. */ /* #undef HAVE_FORK */ /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getgroups' function. */ /* #undef HAVE_GETGROUPS */ /* Define to 1 if you have the `gethostbyname' function. */ /* #undef HAVE_GETHOSTBYNAME */ /* Define to 1 if you have the `gethostname' function. */ /* #undef HAVE_GETHOSTNAME */ /* Define to 1 if you have the `getloadavg' function. */ /* #undef HAVE_GETLOADAVG */ /* Define to 1 if you have the `getrlimit' function. */ /* #undef HAVE_GETRLIMIT */ /* Define if the GNU gettext() function is already present or preinstalled. */ /* #undef HAVE_GETTEXT */ /* Define if you have a standard gettimeofday function */ /* #undef HAVE_GETTIMEOFDAY */ /* Define if you have the iconv() function. */ /* #undef HAVE_ICONV */ /* Define to 1 if you have the header file. */ /*#define HAVE_INTTYPES_H 1*/ /* Define to 1 if you have the `dgc' library (-ldgc). */ /* #undef HAVE_LIBDGC */ /* Define to 1 if you have the `kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ /*#define HAVE_LOCALE_H 1*/ /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mkstemp' function. */ /* #undef HAVE_MKSTEMP */ /* Define to 1 if you have the `mktemp' function. */ #define HAVE_MKTEMP 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NLIST_H */ /* Define to 1 if you have the `pipe' function. */ /* #undef HAVE_PIPE */ /* Define to 1 if you have the `pstat_getdynamic' function. */ /* #undef HAVE_PSTAT_GETDYNAMIC */ /* Define to 1 if you have the `realpath' function. */ /* #undef HAVE_REALPATH */ /* Define if defines the SA_RESTART constant. */ /* #undef HAVE_SA_RESTART */ /* Define to 1 if you have the `setegid' function. */ /* #undef HAVE_SETEGID */ /* Define to 1 if you have the `seteuid' function. */ /* #undef HAVE_SETEUID */ /* Define to 1 if you have the `setlinebuf' function. */ /* #undef HAVE_SETLINEBUF */ /* Define to 1 if you have the `setlocale' function. */ /*#define HAVE_SETLOCALE 1*/ /* Define to 1 if you have the `setregid' function. */ /* #undef HAVE_SETREGID */ /* Define to 1 if you have the `setreuid' function. */ /* #undef HAVE_SETREUID */ /* Define to 1 if you have the `setrlimit' function. */ /* #undef HAVE_SETRLIMIT */ /* Define to 1 if you have the `setvbuf' function. */ /*#define HAVE_SETVBUF 1 */ /* Define to 1 if you have the `sigaction' function. */ /* #undef HAVE_SIGACTION */ /* Define to 1 if you have the `sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the `socket' function. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ /*#define HAVE_STDINT_H 1*/ /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ /* #undef HAVE_STRCASECMP */ /* Define to 1 if you have the `strcmpi' function. */ /* #undef HAVE_STRCMPI */ /* Define to 1 if you have the `stricmp' function. */ #define HAVE_STRICMP 1 /* Define to 1 if you have the `strncasecmp' function. */ /* #undef HAVE_STRNCASECMP */ /* Define to 1 if you have the `strncmpi' function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the `strnicmp' function. */ #define HAVE_STRNICMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* bird */ /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ /* #define HAVE_STRINGS_H 1 */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strsignal' function. */ /* #undef HAVE_STRSIGNAL */ /* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_DIR_H */ /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ /* #define HAVE_SYS_PARAM_H 1 */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_RESOURCE_H */ /* Define to 1 if you have the header file. */ /* #define HAVE_SYS_STAT_H 1 */ /* Define to 1 if you have the header file. */ /*#define HAVE_SYS_TIMEB_H 1*/ /* Define to 1 if you have the header file. */ /*#define HAVE_SYS_TIME_H 1*/ /* Define to 1 if you have the header file. */ /*#define HAVE_SYS_TYPES_H 1*/ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_WAIT_H */ /* Define this if you have the \`union wait' type in . */ /* #undef HAVE_UNION_WAIT */ /* Define to 1 if you have the header file. */ /* #define HAVE_UNISTD_H 1*/ /* Define to 1 if you have the header file. */ /* #undef HAVE_VARARGS_H */ /* Define to 1 if you have the `vfork' function. */ /* #undef HAVE_VFORK */ /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if you have the `wait3' function. */ /* #undef HAVE_WAIT3 */ /* Define to 1 if you have the `waitpid' function. */ /* #undef HAVE_WAITPID */ /* Define to 1 if `fork' works. */ /* #undef HAVE_WORKING_FORK */ /* Define to 1 if `vfork' works. */ /* #undef HAVE_WORKING_VFORK */ /* Build host information. (not used by kmk) */ #define MAKE_HOST "Windows32" /* Define this to enable job server support in GNU make. */ /* #undef MAKE_JOBSERVER */ /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* #undef NLIST_NAME_UNION */ /* Define if struct nlist.n_name is a pointer rather than an array. */ /* #undef NLIST_STRUCT */ /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Name of this package (needed by automake) */ #define PACKAGE "%PACKAGE%" /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the name of the SCCS 'get' command. */ #define SCCS_GET "echo no sccs get" /* Define this if the SCCS 'get' command understands the '-G' option. */ /* #undef SCCS_GET_MINUS_G */ /* Define to 1 if the `setvbuf' function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ /* #undef SETVBUF_REVERSED */ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define if struct stat contains a nanoseconds field */ /* #undef ST_MTIM_NSEC */ /* Define to 1 on System V Release 4. */ /* #undef SVR4 */ /* Define to 1 if you can safely include both and . */ /* #define TIME_WITH_SYS_TIME 1 */ /* Define to 1 for Encore UMAX. */ /* #undef UMAX */ /* Define to 1 for Encore UMAX 4.3 that has instead of . */ /* #undef UMAX4_3 */ /* Version number of package */ #define VERSION "%VERSION%" /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE /* # undef _ALL_SOURCE */ #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ #define _POSIX_SOURCE 1 /* Define like PROTOTYPES; this can be used by system headers. */ /*#define __PROTOTYPES 1*/ /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ #include /* Define to `int' if doesn't define. */ #define gid_t int /* Define to `int' if does not define. */ /* GCC 4.x reportedly defines pid_t. */ #ifndef _PID_T_ #ifdef _WIN64 #define pid_t __int64 #else #define pid_t int #endif #endif /* Define to `int' if doesn't define. */ #define uid_t int /* Define uintmax_t if not defined in or . */ #define uintmax_t unsigned long /* Define as `fork' if `vfork' does not work. */ /*#define vfork fork*/ /* Define to `unsigned long' or `unsigned long long' if doesn't define. */ #define uintmax_t unsigned long /* Define if you support file names longer than 14 characters. */ #define HAVE_LONG_FILE_NAMES 1 /* Define if your struct stat has st_rdev. */ #undef HAVE_ST_RDEV #define HAVE_ST_RDEV 1 /* Define if you have the strftime function. */ #undef HAVE_STRFTIME #define HAVE_STRFTIME 1 /* Define if you have that is POSIX.1 compatible. */ /* #undef HAVE_SYS_WAIT_H */ /* Define if your struct tm has tm_zone. */ /* #undef HAVE_TM_ZONE */ /* Define if you don't have tm_zone but do have the external array tzname. */ #undef HAVE_TZNAME #define HAVE_TZNAME 1 /* Define if utime(file, NULL) sets file's timestamp to the present. */ #undef HAVE_UTIME_NULL #define HAVE_UTIME_NULL 1 /* Define to the installation directory for locales. */ #define LOCALEDIR "" /* * Refer to README.W32 for info on the following settings */ /* * If you have a shell that does not grok 'sh -c quoted-command-line' * correctly, you need this setting. Please see below for specific * shell support. */ /*#define BATCH_MODE_ONLY_SHELL 1 */ /* * Define if you have the Cygnus "Cygwin" GNU Windows32 tool set. * Do NOT define BATCH_MODE_ONLY_SHELL if you define HAVE_CYGWIN_SHELL */ /*#define HAVE_CYGWIN_SHELL 1 */ /* * Define if you have the MKS tool set or shell. Do NOT define * BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL */ /*#define HAVE_MKS_SHELL 1 */ /* * Enforce the mutual exclusivity restriction. */ #ifdef HAVE_MKS_SHELL #undef BATCH_MODE_ONLY_SHELL #endif #ifdef HAVE_CYGWIN_SHELL #undef BATCH_MODE_ONLY_SHELL #endif kbuild-2695/src/kmk/testcase-lazy-deps-vars.kmk0000644000000000000000000000451212247157306020211 0ustar rootroot# $Id: testcase-lazy-deps-vars.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the lazy dependency lists. # # # Copyright (c) 2008-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifneq ($(not 1),) $(error The 'not' function is missing) endif ifneq ($(eq 1,1),1) $(error The 'eq' function is missing) endif all: simple_1 simple_1: variable.c variable.h variable.c variable.c variable.h function.c | variable.h read.c @$(ECHO) "testcase-lazy-deps-vars.kmk::$@: TESTING..." @$(ECHO) "pluss: $+" $(if $(eq $+,variable.c variable.h variable.c variable.c variable.h function.c),,exit 1) $(if $(eq $(deps-all $@,1),variable.c),,exit 1) $(if $(eq $(deps-all $@,2),variable.h),,exit 2) $(if $(eq $(deps-all $@,3),variable.c),,exit 3) $(if $(eq $(deps-all $@,4),variable.c),,exit 4) $(if $(eq $(deps-all $@,5),variable.h),,exit 5) $(if $(eq $(deps-all $@,6),function.c),,exit 6) $(if $(eq $(deps-all $@,7),),,exit 7) @$(ECHO) "caret: $^" $(if $(eq $^,variable.c variable.h function.c),,exit 1) $(if $(eq $(deps $@,1),variable.c),,exit 1) $(if $(eq $(deps $@,2),variable.h),,exit 2) $(if $(eq $(deps $@,3),function.c),,exit 3) $(if $(eq $(deps $@,4),),,exit 4) @$(ECHO) "qmark: $?" $(if $(eq $?,variable.c variable.h function.c),,exit 1) $(if $(eq $(deps-newer $@,1),variable.c),,exit 1) $(if $(eq $(deps-newer $@,2),variable.h),,exit 2) $(if $(eq $(deps-newer $@,3),function.c),,exit 3) $(if $(eq $(deps-newer $@,4),),,exit 4) @$(ECHO) " bar: $|" $(if $(eq $|,read.c),,exit 1) $(if $(eq $(deps-oo $@,1),read.c),,exit 1) $(if $(eq $(deps-oo $@,2),),,exit 2) @$(ECHO) "testcase-lazy-deps-vars.kmk::simple_1: SUCCESS" kbuild-2695/src/kmk/ar.c0000644000000000000000000001612312247157306013562 0ustar rootroot/* Interface to `ar' archives for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "make.h" #ifndef NO_ARCHIVES #include "filedef.h" #include "dep.h" #include /* Return nonzero if NAME is an archive-member reference, zero if not. An archive-member reference is a name like `lib(member)' where member is a non-empty string. If a name like `lib((entry))' is used, a fatal error is signaled at the attempt to use this unsupported feature. */ int ar_name (const char *name) { const char *p = strchr (name, '('); const char *end; if (p == 0 || p == name) return 0; end = p + strlen (p) - 1; if (*end != ')' || end == p + 1) return 0; if (p[1] == '(' && end[-1] == ')') fatal (NILF, _("attempt to use unsupported feature: `%s'"), name); return 1; } /* Parse the archive-member reference NAME into the archive and member names. Creates one allocated string containing both names, pointed to by ARNAME_P. MEMNAME_P points to the member. */ void ar_parse_name (const char *name, char **arname_p, char **memname_p) { char *p; *arname_p = xstrdup (name); p = strchr (*arname_p, '('); *(p++) = '\0'; p[strlen(p) - 1] = '\0'; *memname_p = p; } /* This function is called by `ar_scan' to find which member to look at. */ /* ARGSUSED */ static long int ar_member_date_1 (int desc UNUSED, const char *mem, int truncated, long int hdrpos UNUSED, long int datapos UNUSED, long int size UNUSED, long int date, int uid UNUSED, int gid UNUSED, int mode UNUSED, const void *name) { return ar_name_equal (name, mem, truncated) ? date : 0; } /* Return the modtime of NAME. */ time_t ar_member_date (const char *name) { char *arname; char *memname; long int val; ar_parse_name (name, &arname, &memname); /* Make sure we know the modtime of the archive itself because we are likely to be called just before commands to remake a member are run, and they will change the archive itself. But we must be careful not to enter_file the archive itself if it does not exist, because pattern_search assumes that files found in the data base exist or can be made. */ { struct file *arfile; arfile = lookup_file (arname); if (arfile == 0 && file_exists_p (arname)) arfile = enter_file (strcache_add (arname)); if (arfile != 0) (void) f_mtime (arfile, 0); } val = ar_scan (arname, ar_member_date_1, memname); free (arname); return (val <= 0 ? (time_t) -1 : (time_t) val); } /* Set the archive-member NAME's modtime to now. */ #ifdef VMS int ar_touch (const char *name) { error (NILF, _("touch archive member is not available on VMS")); return -1; } #else int ar_touch (const char *name) { char *arname, *memname; int val; ar_parse_name (name, &arname, &memname); /* Make sure we know the modtime of the archive itself before we touch the member, since this will change the archive modtime. */ { struct file *arfile; arfile = enter_file (strcache_add (arname)); f_mtime (arfile, 0); } val = 1; switch (ar_member_touch (arname, memname)) { case -1: error (NILF, _("touch: Archive `%s' does not exist"), arname); break; case -2: error (NILF, _("touch: `%s' is not a valid archive"), arname); break; case -3: perror_with_name ("touch: ", arname); break; case 1: error (NILF, _("touch: Member `%s' does not exist in `%s'"), memname, arname); break; case 0: val = 0; break; default: error (NILF, _("touch: Bad return code from ar_member_touch on `%s'"), name); } free (arname); return val; } #endif /* !VMS */ /* State of an `ar_glob' run, passed to `ar_glob_match'. */ struct ar_glob_state { const char *arname; const char *pattern; unsigned int size; struct nameseq *chain; unsigned int n; }; /* This function is called by `ar_scan' to match one archive element against the pattern in STATE. */ static long int ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED, long int hdrpos UNUSED, long int datapos UNUSED, long int size UNUSED, long int date UNUSED, int uid UNUSED, int gid UNUSED, int mode UNUSED, const void *arg) { struct ar_glob_state *state = (struct ar_glob_state *)arg; if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0) { /* We have a match. Add it to the chain. */ struct nameseq *new = xcalloc (state->size); new->name = strcache_add (concat (4, state->arname, "(", mem, ")")); new->next = state->chain; state->chain = new; ++state->n; } return 0L; } /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ static int glob_pattern_p (const char *pattern, int quote) { const char *p; int opened = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) { case '?': case '*': return 1; case '\\': if (quote) ++p; break; case '[': opened = 1; break; case ']': if (opened) return 1; break; } return 0; } /* Glob for MEMBER_PATTERN in archive ARNAME. Return a malloc'd chain of matching elements (or nil if none). */ struct nameseq * ar_glob (const char *arname, const char *member_pattern, unsigned int size) { struct ar_glob_state state; struct nameseq *n; const char **names; unsigned int i; if (! glob_pattern_p (member_pattern, 1)) return 0; /* Scan the archive for matches. ar_glob_match will accumulate them in STATE.chain. */ state.arname = arname; state.pattern = member_pattern; state.size = size; state.chain = 0; state.n = 0; ar_scan (arname, ar_glob_match, &state); if (state.chain == 0) return 0; /* Now put the names into a vector for sorting. */ names = alloca (state.n * sizeof (const char *)); i = 0; for (n = state.chain; n != 0; n = n->next) names[i++] = n->name; /* Sort them alphabetically. */ /* MSVC erroneously warns without a cast here. */ qsort ((void *)names, i, sizeof (*names), alpha_compare); /* Put them back into the chain in the sorted order. */ i = 0; for (n = state.chain; n != 0; n = n->next) n->name = names[i++]; return state.chain; } #endif /* Not NO_ARCHIVES. */ kbuild-2695/src/kmk/kdepdb.c0000644000000000000000000007567612247157306014433 0ustar rootroot/* $Id: incdep.c 2283 2009-02-24 04:54:00Z bird $ */ /** @file * kdepdb - Dependency database. */ /* * Copyright (c) 2009-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "make.h" #include "../lib/k/kDefs.h" #include "../lib/k/kTypes.h" #include #include #include "dep.h" #include "filedef.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" #include "debug.h" #include "strcache2.h" #ifdef HAVE_FCNTL_H # include #else # include #endif #if K_OS == K_WINDOWS # include #else # include # include #endif /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** @def KDEPDB_ASSERT_SIZE * Check the size of an on-disk type. * * @param Type The type which size it being checked. * @param Size The size it should have. */ #ifdef __GNUC__ # define KDEPDB_ASSERT_SIZE(Type, Size) \ extern int kDepDbAssertSize[1] __attribute__((unused)), \ kDepDbAssertSize[sizeof(Type) == (Size)] __attribute__((unused)) #else # define KDEPDB_ASSERT_SIZE(Type, Size) \ typedef int kDepDbAssertSize[sizeof(Type) == (Size)] #endif KDEPDB_ASSERT_SIZE(KU8, 1); KDEPDB_ASSERT_SIZE(KU16, 2); KDEPDB_ASSERT_SIZE(KU32, 4); KDEPDB_ASSERT_SIZE(KU64, 8); /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ /** * File header. * * @remarks All on-disk formats are in little-endian format. */ typedef struct KDEPDBHDR { /** The file magic. */ KU8 szMagic[8]; /** The major file format version. */ KU8 uVerMajor; /** The minor file format version. */ KU8 uVerMinor; /** Reserved \#2. */ KU16 uReserved2; /** Reserved \#1. */ KU32 uReserved1; /** The internal name of this file. */ KU8 szName[16]; } KDEPDBHDR; KDEPDB_ASSERT_SIZE(KDEPDBHDR, 32); /** The file header magic value. */ #define KDEPDBHDR_MAGIC "kDepDb\0" /** The current major file format version number. */ #define KDEPDBHDR_VERSION_MAJOR 0 /** The current minor file format version number. * Numbers above 240 indicate unsupported development variants. */ #define KDEPDBHDR_VERSION_MINOR 240 /** * Hash table file. * * The hash table is recreated in a new file when we have to grow it. */ typedef struct KDEPDBHASH { /** The file header. */ KDEPDBHDR Hdr; /** The number of hash table entries. */ KU32 cEntries; /** The number of hash table entries with content. */ KU32 cUsedEntries; /** The number of collisions on insert. */ KU32 cCollisions; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** The hash table. */ KU32 auEntries[32]; } KDEPDBHASH; KDEPDB_ASSERT_SIZE(KDEPDBHASH, 32+32+4*32); /** The item value indicating that it is unused. */ #define KDEPDBHASH_UNUSED KU32_C(0xffffffff) /** The item indicating that it hash been deleted. */ #define KDEPDBHASH_DELETED KU32_C(0xfffffffe) /** The first special item value. */ #define KDEPDBHASH_END KU32_C(0xfffffff0) /** * A string table string entry. * * This should be a multiple of 32 bytes. */ typedef struct KDEPDBSTRING { /** The hash number for the string. */ KU32 uHash; /** The string length, excluding the zero terminator. */ KU32 cchString; /** The string. */ KU8 szString[24]; } KDEPDBSTRING; KDEPDB_ASSERT_SIZE(KDEPDBSTRING, 32); /** * String table file. * * The file is insertion only and will grow forever. */ typedef struct KDEPDBSTRTAB { /** The file header. */ KDEPDBHDR Hdr; /** The end of the valid string table indexes. */ KU32 iStringEnd; /** Reserved member \#7. */ KU32 uReserved7; /** Reserved member \#6. */ KU32 uReserved6; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** The string table. */ KDEPDBSTRING aStrings[1]; } KDEPDBSTRTAB; KDEPDB_ASSERT_SIZE(KDEPDBSTRTAB, 32+32+32); /** The end of the valid string table indexes (exclusive). */ #define KDEPDBG_STRTAB_IDX_END KU32_C(0x80000000) /** The string was not found. */ #define KDEPDBG_STRTAB_IDX_NOT_FOUND KU32_C(0xfffffffd) /** Error during string table operation. */ #define KDEPDBG_STRTAB_IDX_ERROR KU32_C(0xfffffffe) /** Generic invalid string table index. */ #define KDEPDBG_STRTAB_IDX_INVALID KU32_C(0xffffffff) /** * Directory entry. */ typedef struct KDEPDBDIRENTRY { /** The string table index of the entry name. * Unused entries are set to KDEPDBG_STRTAB_IDX_INVALID. */ KU32 iName; /** The actual data stream size. * Unused entries are set to KU32_MAX. */ KU32 cbData; /** The number of blocks allocated for this stream. * Unused entries are set to KU32_MAX. */ KU32 cBlocks; /** The start block number. * The stream is a contiguous sequence of blocks. This optimizes and * simplifies reading the stream at the expense of operations extending it. * * In unused entries, this serves as the free chain pointer with KU32_MAX as * nil value. */ KU32 iStartBlock; } KDEPDBDIRENTRY; KDEPDB_ASSERT_SIZE(KDEPDBDIRENTRY, 16); /** * Directory file. */ typedef struct KDEPDBDIR { /** The file header. */ KDEPDBHDR Hdr; /** The number of entries. */ KU32 cEntries; /** The head of the free chain. (Index into aEntries.) */ KU32 iFreeHead; /** Reserved member \#6. */ KU32 uReserved6; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** Directory entries. */ KDEPDBDIRENTRY aEntries[2]; } KDEPDBDIR; KDEPDB_ASSERT_SIZE(KDEPDBDIR, 32+32+32); /** * A block allocation bitmap. * * This can track 2^(12+8) = 2^20 = 1M blocks. */ typedef struct KDEPDBDATABITMAP { /** Bitmap where each bit is a block. * 0 indicates unused blocks and 1 indicates used ones. */ KU8 bm[4096]; } KDEPDBDATABITMAP; KDEPDB_ASSERT_SIZE(KDEPDBDATABITMAP, 4096); /** * Data file. * * The block numbering starts with this structure as block 0. */ typedef struct KDEPDBDATA { /** The file header. */ KDEPDBHDR Hdr; /** The size of a block. */ KU32 cbBlock; /** Reserved member \#7. */ KU32 uReserved7; /** Reserved member \#6. */ KU32 uReserved6; /** Reserved member \#5. */ KU32 uReserved5; /** Reserved member \#4. */ KU32 uReserved4; /** Reserved member \#3. */ KU32 uReserved3; /** Reserved member \#2. */ KU32 uReserved2; /** Reserved member \#1. */ KU32 uReserved1; /** Block numbers for the allocation bitmaps. */ KU32 aiBitmaps[4096]; } KDEPDBDATA; /** The end of the valid block indexes (exclusive). */ #define KDEPDB_BLOCK_IDX_END KU32_C(0xfffffff0) /** The index of an unallocated bitmap block. */ #define KDEPDB_BLOCK_IDX_UNALLOCATED KU32_C(0xffffffff) /** * Stream storing dependencies. * * The stream name gives the output file name, so all that we need is the list * of files it depends on. These are serialized as a list of string table * indexes. */ typedef struct KDEPDBDEPSTREAM { /** String table indexes for the dependencies. */ KU32 aiDeps[1]; } KDEPDBDEPSTREAM; /** * A file handle structure. */ typedef struct KDEPDBFH { #if K_OS == K_OS_WINDOWS /** The file handle. */ HANDLE hFile; /** The mapping object handle. */ HANDLE hMapObj; #else /** The file handle. */ int fd; #endif /** The current file size. */ KU32 cb; } KDEPDBFH; /** * Internal control structure for a string table. */ typedef struct KDEPDBINTSTRTAB { /** The hash file. */ KDEPDBHASH *pHash; /** The handle of the hash file. */ KDEPDBFH hHash; /** The string table file. */ KDEPDBSTRTAB *pStrTab; /** The handle of the string table file. */ KDEPDBFH hStrTab; /** The end of the allocated string table indexes (i.e. when to grow the * file). */ KU32 iStringAlloced; } KDEPDBINTSTRTAB; /** * Internal control structure for a data set. * * This governs the directory file, the directory hash file and the data file. */ typedef struct KDEPDBINTDATASET { /** The hash file. */ KDEPDBHASH pHash; /** The size of the hash file. */ KU32 cbHash; /** The size of the directory file. */ KU32 cbDir; /** The mapping of the directory file. */ KDEPDBHASH pDir; /** The data file. */ KDEPDBDATA pData; /** The size of the data file. */ KU32 cbData; /** The handle of the hash file. */ KDEPDBFH hHash; /** The handle of the directory file. */ KDEPDBFH hDir; /** The handle of the data file. */ KDEPDBFH hData; } KDEPDBINTDATASET; /** * The database instance. * * To simplifiy things the database uses 8 files for storing the different kinds * of data. This greatly reduces the complexity compared to a single file * solution. */ typedef struct KDEPDB { /** The string table. */ KDEPDBINTSTRTAB StrTab; /** The variable data set. */ KDEPDBINTDATASET DepSet; /** The command data set. */ KDEPDBINTDATASET CmdSet; } KDEPDB; /******************************************************************************* * Internal Functions * *******************************************************************************/ static void *kDepDbAlloc(KSIZE cb); static void kDepDbFree(void *pv); static void kDepDbFHInit(KDEPDBFH *pFH); static int kDepDbFHUpdateSize(KDEPDBFH *pFH); static int kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfNew); static int kDepDbFHClose(KDEPDBFH *pFH); static int kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf); static int kDepDbFHMap(KDEPDBFH *pFH, void **ppvMap); static int kDepDbFHUnmap(KDEPDBFH *pFH, void **ppvMap); static int kDepDbFHGrow(KDEPDBFH *pFH, KSIZE cbNew, void **ppvMap); static KU32 kDepDbHashString(const char *pszString, size_t cchString); /** xmalloc wrapper. */ static void *kDepDbAlloc(KSIZE cb) { return xmalloc(cb); } /** free wrapper. */ static void kDepDbFree(void *pv) { if (pv) free(pv); } /** * Initializes the file handle structure so closing it without first opening it * will work smoothly. * * @param pFH The file handle structure. */ static void kDepDbFHInit(KDEPDBFH *pFH) { #if K_OS == K_OS_WINDOWS pFH->hFile = INVALID_HANDLE_VALUE; pFH->hMapObj = INVALID_HANDLE_VALUE; #else pFH->fd = -1; #endif pFH->cb = 0; } /** * Updates the file size. * * @returns 0 on success. Some non-zero native error code on failure. * @param pFH The file handle structure. */ static int kDepDbFHUpdateSize(KDEPDBFH *pFH) { #if K_OS == K_OS_WINDOWS DWORD rc; DWORD dwHigh; DWORD dwLow; SetLastError(0); dwLow = GetFileSize(File, &High); rc = GetLastError(); if (rc) { pFH->cb = 0; return (int)rc; } if (High) pFH->cb = KU32_MAX; else pFH->cb = dwLow; #else off_t cb; cb = lseek(pFH->fd, 0, SEEK_END); if (cb == -1) { pFH->cb = 0; return errno; } pFH->cb = cb; if ((off_t)pFH->cb != cb) pFH->cb = KU32_MAX; #endif return 0; } /** * Opens an existing file or creates a new one. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param pszFilename The name of the file. * @param fCreate Whether we should create the file or not. * @param pfCreated Where to return whether we created it or not. */ static int kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfCreated) { int rc; #if K_OS == K_OS_WINDOWS SECURITY_ATTRIBUTES SecAttr; SecAttr.bInheritHandle = FALSE; SecAttr.lpSecurityDescriptor = NULL; SecAttr.nLength = 0; pFH->cb = 0; SetLastError(0); pFH->hFile = CreateFile(pszFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &SecAttr, fCreate ? OPEN_ALWAYS : OPEN_EXISTING, 0, NULL); if (pFH->hFile == INVALID_HANDLE_VALUE) return GetLastError(); *pfCreated = GetLastError() == 0; #else int fFlags = O_RDWR; # ifdef O_BINARY fFlags |= O_BINARY; # endif pFH->cb = 0; pFH->fd = open(pszFilename, fFlags, 0); if (pFH->fd >= 0) *pfCreated = K_FALSE; else if (!fCreate) return errno; else { pFH->fd = open(pszFilename, fFlags | O_EXCL | O_CREAT, 0666); if (pFH->fd < 0) return errno; *pfCreated = K_TRUE; } fcntl(pFH->fd, F_SETFD, FD_CLOEXEC); #endif /* update the size */ rc = kDepDbFHUpdateSize(pFH); if (rc) kDepDbFHClose(pFH); return rc; } /** * Closes an open file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. */ static int kDepDbFHClose(KDEPDBFH *pFH) { #if K_OS == K_OS_WINDOWS if (pFH->hFile != INVALID_HANDLE_VALUE) { if (!CloseHandle(pFH->hFile)) return GetLastError(); pFH->hFile = INVALID_HANDLE_VALUE; } #else if (pFH->fd >= 0) { if (close(pFH->fd) != 0) return errno; pFH->fd = -1; } #endif pFH->cb = 0; return 0; } /** * Writes to a file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param off The offset into the file to start writing at. * @param pvBuf What to write. * @param cbBuf How much to write. */ static int kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf) { #if K_OS == K_OS_WINDOWS ULONG cbWritten; if (SetFilePointer(pFH->hFile, off, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) return GetLastError(); if (!WriteFile(pFH->hFile, pvBuf, cbBuf, &cbWritten, NULL)) return GetLastError(); if (cbWritten != cbBuf) return -1; #else ssize_t cbWritten; if (lseek(pFH->fd, off, SEEK_SET) == -1) return errno; errno = 0; cbWritten = write(pFH->fd, pvBuf, cbBuf); if ((size_t)cbWritten != cbBuf) return errno ? errno : EIO; #endif return kDepDbFHUpdateSize(pFH); } /** * Creates a memory mapping of the file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param ppvMap Where to return the map address. */ static int kDepDbFHMap(KDEPDBFH *pFH, void **ppvMap) { #if K_OS == K_OS_WINDOWS *ppvMap = NULL; return -1; #else *ppvMap = mmap(NULL, pFH->cb, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pFH->fd, 0); if (*ppvMap == (void *)-1) { *ppvMap = NULL; return errno; } #endif return 0; } /** * Flushes and destroys a memory of the file. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param ppvMap The pointer to the mapping pointer. This will be set to * NULL on success. */ static int kDepDbFHUnmap(KDEPDBFH *pFH, void **ppvMap) { #if K_OS == K_OS_WINDOWS return -1; #else if (msync(*ppvMap, pFH->cb, MS_SYNC) == -1) return errno; if (munmap(*ppvMap, pFH->cb) == -1) return errno; *ppvMap = NULL; #endif return 0; } /** * Grows the memory mapping of the file. * * The content of the new space is undefined. * * @returns 0 on success. Some non-zero native error code on failure. * * @param pFH The file handle structure. * @param cbNew The new mapping size. * @param ppvMap The pointer to the mapping pointer. This may change and * may be set to NULL on failure. */ static int kDepDbFHGrow(KDEPDBFH *pFH, KSIZE cbNew, void **ppvMap) { #if K_OS == K_OS_WINDOWS return -1; #else if ((KU32)cbNew != cbNew) return ERANGE; if (cbNew <= pFH->cb) return 0; if (munmap(*ppvMap, pFH->cb) == -1) return errno; *ppvMap = NULL; pFH->cb = cbNew; return kDepDbFHMap(pFH, ppvMap); #endif } /** Macro for reading an potentially unaligned 16-bit word from a string. */ # if K_ARCH == K_ARCH_AMD64 \ || K_ARCH == K_ARCH_X86_32 \ || K_ARCH == K_ARCH_X86_16 # define kDepDbHashString_get_unaligned_16bits(ptr) ( *((const KU16 *)(ptr)) ) # elif K_ENDIAN == K_ENDIAN_LITTLE # define kDepDbHashString_get_unaligned_16bits(ptr) ( (((const KU8 *)(ptr))[0]) \ | (((const KU8 *)(ptr))[1] << 8) ) # else # define kDepDbHashString_get_unaligned_16bits(ptr) ( (((const KU8 *)(ptr))[0] << 8) \ | (((const KU8 *)(ptr))[1]) ) # endif /** * Hash a string. * * @returns Hash value. * * @param pszString The string to hash. * @param cchString How much to hash. */ static KU32 kDepDbHashString(const char *pszString, size_t cchString) { /* * Paul Hsieh hash SuperFast function: * http://www.azillionmonkeys.com/qed/hash.html */ /** @todo A path for well aligned data should be added to speed up execution on * alignment sensitive systems. */ unsigned int uRem; KU32 uHash; KU32 uTmp; assert(sizeof(KU8) == sizeof(char)); /* main loop, walking on 2 x KU16 */ uHash = cchString; uRem = cchString & 3; cchString >>= 2; while (cchString > 0) { uHash += kDepDbHashString_get_unaligned_16bits(pszString); uTmp = (kDepDbHashString_get_unaligned_16bits(pszString + 2) << 11) ^ uHash; uHash = (uHash << 16) ^ uTmp; pszString += 2 * sizeof(KU16); uHash += uHash >> 11; cchString--; } /* the remainder */ switch (uRem) { case 3: uHash += kDepDbHashString_get_unaligned_16bits(pszString); uHash ^= uHash << 16; uHash ^= pszString[sizeof(KU16)] << 18; uHash += uHash >> 11; break; case 2: uHash += kDepDbHashString_get_unaligned_16bits(pszString); uHash ^= uHash << 11; uHash += uHash >> 17; break; case 1: uHash += *pszString; uHash ^= uHash << 10; uHash += uHash >> 1; break; } /* force "avalanching" of final 127 bits. */ uHash ^= uHash << 3; uHash += uHash >> 5; uHash ^= uHash << 4; uHash += uHash >> 17; uHash ^= uHash << 25; uHash += uHash >> 6; return uHash; } /*** * Looks up a string in the string table. * * @returns The string table index. * @retval KDEPDBG_STRTAB_IDX_NOT_FOUND is not found. * @retval KDEPDBG_STRTAB_IDX_ERROR on internal inconsistency. * * @param pStrTab The string table. * @param pszString The string. * @param cchStringIn The string length. * @param uHash The hash of the string. */ static KU32 kDepDbStrTabLookupHashed(KDEPDBINTSTRTAB const *pStrTab, const char *pszString, size_t cchStringIn, KU32 uHash) { KU32 const cchString = (KU32)cchStringIn; KDEPDBHASH const *pHash = pStrTab->pHash; KDEPDBSTRING const *paStrings = &pStrTab->pStrTab->aStrings[0]; KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd); KU32 iHash; /* sanity */ if (cchString != cchStringIn) return KDEPDBG_STRTAB_IDX_NOT_FOUND; /* * Hash lookup of the string. */ iHash = uHash % pHash->cEntries; for (;;) { KU32 iString = K_LE2H_U32(pHash->auEntries[iHash]); if (iString < iStringEnd) { KDEPDBSTRING const *pString = &paStrings[iString]; if ( K_LE2H_U32(pString->uHash) == uHash && K_LE2H_U32(pString->cchString) == cchString && !memcmp(pString->szString, pszString, cchString)) return iString; } else if (iString == KDEPDBHASH_UNUSED) return KDEPDBG_STRTAB_IDX_NOT_FOUND; else if (iString != KDEPDBHASH_DELETED) return KDEPDBG_STRTAB_IDX_ERROR; /* advance */ iHash = (iHash + 1) % pHash->cEntries; } } /** * Doubles the hash table size and rehashes it. * * @returns 0 on success, -1 on failure. * @param pStrTab The string table. * @todo Rebuild from string table, we'll be accessing it anyways. */ static int kDepDbStrTabReHash(KDEPDBINTSTRTAB *pStrTab) { KDEPDBSTRING const *paStrings = &pStrTab->pStrTab->aStrings[0]; KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd); KDEPDBHASH *pHash = pStrTab->pHash; KDEPDBHASH HashHdr = *pHash; KU32 *pauNew; KU32 cEntriesNew; KU32 i; /* * Calc the size of the new hash table. */ if (pHash->cEntries >= KU32_C(0x80000000)) return -1; cEntriesNew = 1024; while (cEntriesNew <= pHash->cEntries) cEntriesNew <<= 1; /* * Allocate and initialize an empty hash table in memory. */ pauNew = kDepDbAlloc(cEntriesNew * sizeof(KU32)); if (!pauNew) return -1; i = cEntriesNew; while (i-- > 0) pauNew[i] = KDEPDBHASH_UNUSED; /* * Popuplate the new table. */ HashHdr.cEntries = K_LE2H_U32(cEntriesNew); HashHdr.cCollisions = 0; HashHdr.cUsedEntries = 0; i = pHash->cEntries; while (i-- > 0) { KU32 iString = K_LE2H_U32(pHash->auEntries[i]); if (iString < iStringEnd) { KU32 iHash = (paStrings[iString].uHash % cEntriesNew); if (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED)) { do { iHash = (iHash + 1) % cEntriesNew; HashHdr.cCollisions++; } while (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED)); } pauNew[iHash] = iString; HashHdr.cUsedEntries++; } else if ( iString != KDEPDBHASH_UNUSED && iString != KDEPDBHASH_DELETED) { kDepDbFree(pauNew); return -1; } } HashHdr.cCollisions = K_H2LE_U32(HashHdr.cCollisions); HashHdr.cUsedEntries = K_H2LE_U32(HashHdr.cUsedEntries); /* * Unmap the hash, write the new hash table and map it again. */ if (!kDepDbFHUnmap(&pStrTab->hHash, (void **)&pStrTab->pHash)) { if ( !kDepDbFHWriteAt(&pStrTab->hHash, 0, &HashHdr, K_OFFSETOF(KDEPDBHASH, auEntries)) && !kDepDbFHWriteAt(&pStrTab->hHash, K_OFFSETOF(KDEPDBHASH, auEntries), pauNew, sizeof(pauNew[0]) * cEntriesNew)) { kDepDbFree(pauNew); pauNew = NULL; if (!kDepDbFHMap(&pStrTab->hHash, (void **)&pStrTab->pHash)) return 0; } else kDepDbFHWriteAt(&pStrTab->hHash, 0, "\0\0\0\0", 4); /* file is screwed, trash the magic. */ } kDepDbFree(pauNew); return -1; } /** * Add a string to the string table. * * If already in the table, the index of the existing entry is returned. * * @returns String index on success, * @retval KDEPDBG_STRTAB_IDX_ERROR on I/O and inconsistency errors. * * @param pStrTab The string table. * @param pszString The string to add. * @param cchStringIn The length of the string. * @param uHash The hash of the string. */ static KU32 kDepDbStrTabAddHashed(KDEPDBINTSTRTAB *pStrTab, const char *pszString, size_t cchStringIn, KU32 uHash) { KU32 const cchString = (KU32)cchStringIn; KDEPDBHASH *pHash = pStrTab->pHash; KDEPDBSTRING *paStrings = &pStrTab->pStrTab->aStrings[0]; KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd); KU32 iInsertAt = KDEPDBHASH_UNUSED; KU32 cCollisions = 0; KU32 iHash; KU32 iString; KU32 cEntries; KDEPDBSTRING *pNewString; /* sanity */ if (cchString != cchStringIn) return KDEPDBG_STRTAB_IDX_NOT_FOUND; /* * Hash lookup of the string, finding either an existing copy or where to * insert the new string at in the hash table. */ iHash = uHash % pHash->cEntries; for (;;) { iString = K_LE2H_U32(pHash->auEntries[iHash]); if (iString < iStringEnd) { KDEPDBSTRING const *pString = &paStrings[iString]; if ( K_LE2H_U32(pString->uHash) == uHash && K_LE2H_U32(pString->cchString) == cchString && !memcmp(pString->szString, pszString, cchString)) return iString; } else { if (iInsertAt == KDEPDBHASH_UNUSED) iInsertAt = iHash; if (iString == KDEPDBHASH_UNUSED) break; if (iString != KDEPDBHASH_DELETED) return KDEPDBG_STRTAB_IDX_ERROR; } /* advance */ cCollisions++; iHash = (iHash + 1) % pHash->cEntries; } /* * Add string to the string table. * The string table file is grown in 256KB increments and ensuring at least 64KB unused new space. */ cEntries = cchString + 1 <= sizeof(paStrings[0].szString) ? 1 : (cchString + 1 - sizeof(paStrings[0].szString) + sizeof(KDEPDBSTRING) - 1) / sizeof(KDEPDBSTRING); if (iStringEnd + cEntries > pStrTab->iStringAlloced) { KSIZE cbNewSize = K_ALIGN_Z((iStringEnd + cEntries) * sizeof(KDEPDBSTRING) + 64*1024, 256*1024); KU32 iStringAlloced = (pStrTab->hStrTab.cb - K_OFFSETOF(KDEPDBSTRTAB, aStrings)) / sizeof(KDEPDBSTRING); if ( iStringAlloced <= pStrTab->iStringAlloced || iStringAlloced >= KDEPDBG_STRTAB_IDX_END || iStringAlloced >= KDEPDBHASH_END) return KDEPDBG_STRTAB_IDX_ERROR; if (kDepDbFHGrow(&pStrTab->hStrTab, cbNewSize, (void **)&pStrTab->pStrTab) != 0) return KDEPDBG_STRTAB_IDX_ERROR; pStrTab->iStringAlloced = iStringAlloced; paStrings = &pStrTab->pStrTab->aStrings[0]; } pNewString = &paStrings[iStringEnd]; pNewString->uHash = K_H2LE_U32(uHash); pNewString->cchString = K_H2LE_U32(cchString); memcpy(&pNewString->szString, pszString, cchString); pNewString->szString[cchString] = '\0'; pStrTab->pStrTab->iStringEnd = K_H2LE_U32(iStringEnd + cEntries); /* * Insert hash table entry, rehash it if necessary. */ pHash->auEntries[iInsertAt] = K_H2LE_U32(iStringEnd); pHash->cUsedEntries = K_H2LE_U32(K_LE2H_U32(pHash->cUsedEntries) + 1); pHash->cCollisions = K_H2LE_U32(K_LE2H_U32(pHash->cCollisions) + cCollisions); if ( K_LE2H_U32(pHash->cUsedEntries) > K_LE2H_U32(pHash->cEntries) / 3 * 2 && kDepDbStrTabReHash(pStrTab) != 0) return KDEPDBG_STRTAB_IDX_ERROR; return iStringEnd; } /** Wrapper for kDepDbStrTabLookupHashed. */ static KU32 kDepDbStrTabLookupN(KDEPDBINTSTRTAB const *pStrTab, const char *pszString, size_t cchString) { return kDepDbStrTabLookupHashed(pStrTab, pszString, cchString, kDepDbHashString(pszString, cchString)); } /** Wrapper for kDepDbStrTabAddHashed. */ static KU32 kDepDbStrTabAddN(KDEPDBINTSTRTAB *pStrTab, const char *pszString, size_t cchString) { return kDepDbStrTabAddHashed(pStrTab, pszString, cchString, kDepDbHashString(pszString, cchString)); } /** Wrapper for kDepDbStrTabLookupHashed. */ static KU32 kDepDbStrTabLookup(KDEPDBINTSTRTAB const *pStrTab, const char *pszString) { return kDepDbStrTabLookupN(pStrTab, pszString, strlen(pszString)); } /** Wrapper for kDepDbStrTabAddHashed. */ static KU32 kDepDbStrTabAdd(KDEPDBINTSTRTAB *pStrTab, const char *pszString) { return kDepDbStrTabAddN(pStrTab, pszString, strlen(pszString)); } /** * Opens the string table files, creating them if necessary. */ static int kDepDbStrTabInit(KDEPDBINTSTRTAB *pStrTab, const char *pszFilenameBase) { size_t cchFilenameBase = strlen(pszFilenameBase); char szPath[4096]; int rc; KBOOL fNew; /* Basic member init, so kDepDbStrTabTerm always works. */ pStrTab->pHash = NULL; kDepDbFHInit(&pStrTab->hHash); pStrTab->pStrTab = NULL; kDepDbFHInit(&pStrTab->hStrTab); pStrTab->iStringAlloced = 0; /* check the length. */ if (cchFilenameBase + sizeof(".strtab.hash") > sizeof(szPath)) return -1; /* * Open the string table first. */ memcpy(szPath, pszFilenameBase, cchFilenameBase); memcpy(&szPath[cchFilenameBase], ".strtab", sizeof(".strtab")); rc = kDepDbFHOpen(&pStrTab->hStrTab, szPath, K_TRUE, &fNew); return -1; } kbuild-2695/src/kmk/strcache2.h0000644000000000000000000001556212247157306015051 0ustar rootroot/* $Id: strcache2.h 2413 2010-09-11 17:43:04Z bird $ */ /** @file * strcache - New string cache. */ /* * Copyright (c) 2006-2010 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ #ifndef ___strcache2_h #define ___strcache2_h #ifndef CHAR_BIT # error "include after make.h!" #endif #define STRCACHE2_USE_MASK 1 /* string cache memory segment. */ struct strcache2_seg { struct strcache2_seg *next; /* The next cache segment. */ char *start; /* The first byte in the segment. */ size_t size; /* The size of the segment. */ size_t avail; /* The number of available bytes. */ char *cursor; /* Allocation cursor. */ }; /* string cache hash table entry. */ struct strcache2_entry { struct strcache2_entry *next; /* Collision chain. */ void *user; unsigned int hash; unsigned int length; }; /* The entry alignment, cacheline size if it's known & sensible. On x86/AMD64 we assume a 64-byte cacheline size. As it is difficult to guess other right now, these default 16 chars as that shouldn't cause much trouble, even if it not the most optimial value. Override, or modify for other platforms. */ #ifndef STRCACHE2_ENTRY_ALIGN_SHIFT # if defined (__i386__) || defined(__x86_64__) # define STRCACHE2_ENTRY_ALIGN_SHIFT 6 # else # define STRCACHE2_ENTRY_ALIGN_SHIFT 4 # endif #endif #define STRCACHE2_ENTRY_ALIGNMENT (1 << STRCACHE2_ENTRY_ALIGN_SHIFT) struct strcache2 { struct strcache2_entry **hash_tab; /* The hash table. */ int case_insensitive; /* case insensitive or not. */ #ifdef STRCACHE2_USE_MASK unsigned int hash_mask; /* The AND mask matching hash_size.*/ #else unsigned int hash_div; /* The number (prime) to mod by. */ #endif unsigned long lookup_count; /* The number of lookups. */ unsigned long collision_1st_count; /* The number of 1st level collisions. */ unsigned long collision_2nd_count; /* The number of 2nd level collisions. */ unsigned long collision_3rd_count; /* The number of 3rd level collisions. */ unsigned int count; /* Number entries in the cache. */ unsigned int collision_count; /* Number of entries in chains. */ unsigned int rehash_count; /* When to rehash the table. */ unsigned int init_size; /* The initial hash table size. */ unsigned int hash_size; /* The hash table size. */ unsigned int def_seg_size; /* The default segment size. */ void *lock; /* The lock handle. */ struct strcache2_seg *seg_head; /* The memory segment list. */ struct strcache2 *next; /* The next string cache. */ const char *name; /* Cache name. */ }; void strcache2_init (struct strcache2 *cache, const char *name, unsigned int size, unsigned int def_seg_size, int case_insensitive, int thread_safe); void strcache2_term (struct strcache2 *cache); void strcache2_print_stats (struct strcache2 *cache, const char *prefix); void strcache2_print_stats_all (const char *prefix); const char *strcache2_add (struct strcache2 *cache, const char *str, unsigned int length); const char *strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length); const char *strcache2_add_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash); const char *strcache2_iadd_hashed (struct strcache2 *cache, const char *str, unsigned int length, unsigned int hash); const char *strcache2_lookup (struct strcache2 *cache, const char *str, unsigned int length); const char *strcache2_ilookup (struct strcache2 *cache, const char *str, unsigned int length); #ifdef HAVE_CASE_INSENSITIVE_FS # define strcache2_add_file strcache2_iadd # define strcache2_add_hashed_file strcache2_iadd_hashed # define strcache2_lookup_file strcache2_ilookup #else # define strcache2_add_file strcache2_add # define strcache2_add_hashed_file strcache2_add_hashed # define strcache2_lookup_file strcache2_lookup #endif int strcache2_is_cached (struct strcache2 *cache, const char *str); int strcache2_verify_entry (struct strcache2 *cache, const char *str); unsigned int strcache2_get_hash2_fallback (struct strcache2 *cache, const char *str); unsigned int strcache2_hash_str (const char *str, unsigned int length, unsigned int *hash2p); unsigned int strcache2_hash_istr (const char *str, unsigned int length, unsigned int *hash2p); /* Get the hash table entry pointer. */ MY_INLINE struct strcache2_entry const * strcache2_get_entry (struct strcache2 *cache, const char *str) { #ifndef NDEBUG strcache2_verify_entry (cache, str); #endif return (struct strcache2_entry const *)str - 1; } /* Get the string length. */ MY_INLINE unsigned int strcache2_get_len (struct strcache2 *cache, const char *str) { return strcache2_get_entry (cache, str)->length; } /* Get the first hash value for the string. */ MY_INLINE unsigned int strcache2_get_hash (struct strcache2 *cache, const char *str) { return strcache2_get_entry (cache, str)->hash; } /* Calc the pointer hash value for the string. This takes the string address, shift out the bits that are always zero due to alignment, and then returns the unsigned integer value of it. The results from using this is generally better than for any of the other hash values. It is also sligtly faster code as it does not involve any memory accesses, just a right SHIFT and an optional AND. */ MY_INLINE unsigned int strcache2_calc_ptr_hash (struct strcache2 *cache, const char *str) { (void)cache; return (size_t)str >> STRCACHE2_ENTRY_ALIGN_SHIFT; } /* Get the user value for the string. */ MY_INLINE void * strcache2_get_user_val (struct strcache2 *cache, const char *str) { return strcache2_get_entry (cache, str)->user; } /* Get the user value for the string. */ MY_INLINE void strcache2_set_user_val (struct strcache2 *cache, const char *str, void *value) { struct strcache2_entry *entry = (struct strcache2_entry *)str - 1; #ifndef NDEBUG strcache2_verify_entry (cache, str); #endif entry->user = value; } #endif kbuild-2695/src/kmk/variable.h0000644000000000000000000004505512247157306014760 0ustar rootroot/* Definitions for using variables in GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "hash.h" /* Codes in a variable definition saying where the definition came from. Increasing numeric values signify less-overridable definitions. */ enum variable_origin { o_default, /* Variable from the default set. */ o_env, /* Variable from environment. */ o_file, /* Variable given in a makefile. */ o_env_override, /* Variable from environment, if -e. */ o_command, /* Variable given by user. */ o_override, /* Variable from an `override' directive. */ #ifdef CONFIG_WITH_LOCAL_VARIABLES o_local, /* Variable from an 'local' directive. */ #endif o_automatic, /* Automatic variable -- cannot be set. */ o_invalid /* Core dump time. */ }; enum variable_flavor { f_bogus, /* Bogus (error) */ f_simple, /* Simple definition (:=) */ f_recursive, /* Recursive definition (=) */ f_append, /* Appending definition (+=) */ #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT f_prepend, /* Prepending definition (>=) */ #endif f_conditional /* Conditional definition (?=) */ }; /* Structure that represents one variable definition. Each bucket of the hash table is a chain of these, chained through `next'. */ #define EXP_COUNT_BITS 15 /* This gets all the bitfields into 32 bits */ #define EXP_COUNT_MAX ((1<1, allow this many self-referential expansions. */ #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE unsigned int rdonly_val:1; /* VALUE is read only (strcache/const). */ #endif enum variable_flavor flavor ENUM_BITFIELD (3); /* Variable flavor. */ enum variable_origin #ifdef CONFIG_WITH_LOCAL_VARIABLES origin ENUM_BITFIELD (4); /* Variable origin. */ #else origin ENUM_BITFIELD (3); /* Variable origin. */ #endif enum variable_export { v_export, /* Export this variable. */ v_noexport, /* Don't export this variable. */ v_ifset, /* Export it if it has a non-default value. */ v_default /* Decide in target_environment. */ } export ENUM_BITFIELD (2); #ifdef CONFIG_WITH_MAKE_STATS unsigned int changes; unsigned int reallocs; #endif }; /* Structure that represents a variable set. */ struct variable_set { struct hash_table table; /* Hash table of variables. */ }; /* Structure that represents a list of variable sets. */ struct variable_set_list { struct variable_set_list *next; /* Link in the chain. */ struct variable_set *set; /* Variable set. */ int next_is_parent; /* True if next is a parent target. */ }; /* Structure used for pattern-specific variables. */ struct pattern_var { struct pattern_var *next; const char *suffix; const char *target; unsigned int len; struct variable variable; }; extern char *variable_buffer; extern struct variable_set_list *current_variable_set_list; extern struct variable *default_goal_var; #ifdef KMK extern unsigned int variable_buffer_length; # define VARIABLE_BUFFER_ZONE 5 #endif /* expand.c */ #ifndef KMK char * variable_buffer_output (char *ptr, const char *string, unsigned int length); #else /* KMK */ /* Subroutine of variable_expand and friends: The text to add is LENGTH chars starting at STRING to the variable_buffer. The text is added to the buffer at PTR, and the updated pointer into the buffer is returned as the value. Thus, the value returned by each call to variable_buffer_output should be the first argument to the following call. */ __inline static char * variable_buffer_output (char *ptr, const char *string, unsigned int length) { register unsigned int newlen = length + (ptr - variable_buffer); if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length) { unsigned int offset = ptr - variable_buffer; variable_buffer_length = variable_buffer_length <= 1024 ? 2048 : variable_buffer_length * 4; if (variable_buffer_length < newlen + 100) variable_buffer_length = (newlen + 100 + 1023) & ~1023U; variable_buffer = xrealloc (variable_buffer, variable_buffer_length); ptr = variable_buffer + offset; } # ifndef _MSC_VER switch (length) { case 4: ptr[3] = string[3]; case 3: ptr[2] = string[2]; case 2: ptr[1] = string[1]; case 1: ptr[0] = string[0]; case 0: break; default: memcpy (ptr, string, length); break; } # else memcpy (ptr, string, length); # endif return ptr + length; } #endif /* KMK */ char *variable_expand (const char *line); char *variable_expand_for_file (const char *line, struct file *file); #if defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_COMMANDS_FUNC) char *variable_expand_for_file_2 (char *o, const char *line, unsigned int lenght, struct file *file, unsigned int *value_lenp); #endif char *allocated_variable_expand_for_file (const char *line, struct file *file); #ifndef CONFIG_WITH_VALUE_LENGTH #define allocated_variable_expand(line) \ allocated_variable_expand_for_file (line, (struct file *) 0) #else /* CONFIG_WITH_VALUE_LENGTH */ # define allocated_variable_expand(line) \ allocated_variable_expand_2 (line, -1, NULL) char *allocated_variable_expand_2 (const char *line, unsigned int length, unsigned int *value_lenp); char *allocated_variable_expand_3 (const char *line, unsigned int length, unsigned int *value_lenp, unsigned int *buffer_lengthp); void recycle_variable_buffer (char *buffer, unsigned int length); #endif /* CONFIG_WITH_VALUE_LENGTH */ char *expand_argument (const char *str, const char *end); #ifndef CONFIG_WITH_VALUE_LENGTH char * variable_expand_string (char *line, const char *string, long length); #else /* CONFIG_WITH_VALUE_LENGTH */ char * variable_expand_string_2 (char *line, const char *string, long length, char **eol); __inline static char * variable_expand_string (char *line, const char *string, long length) { char *ignored; return variable_expand_string_2 (line, string, length, &ignored); } #endif /* CONFIG_WITH_VALUE_LENGTH */ void install_variable_buffer (char **bufp, unsigned int *lenp); void restore_variable_buffer (char *buf, unsigned int len); #ifdef CONFIG_WITH_VALUE_LENGTH void append_expanded_string_to_variable (struct variable *v, const char *value, unsigned int value_len, int append); #endif /* function.c */ #ifndef CONFIG_WITH_VALUE_LENGTH int handle_function (char **op, const char **stringp); #else int handle_function (char **op, const char **stringp, const char *nameend, const char *eol); #endif int pattern_matches (const char *pattern, const char *percent, const char *str); char *subst_expand (char *o, const char *text, const char *subst, const char *replace, unsigned int slen, unsigned int rlen, int by_word); char *patsubst_expand_pat (char *o, const char *text, const char *pattern, const char *replace, const char *pattern_percent, const char *replace_percent); char *patsubst_expand (char *o, const char *text, char *pattern, char *replace); #ifdef CONFIG_WITH_COMMANDS_FUNC char *func_commands (char *o, char **argv, const char *funcname); #endif #if defined (CONFIG_WITH_VALUE_LENGTH) /* Avoid calling handle_function for every variable, do the basic checks in variable_expand_string_2. */ extern char func_char_map[256]; # define MAX_FUNCTION_LENGTH 12 # define MIN_FUNCTION_LENGTH 2 MY_INLINE const char * may_be_function_name (const char *name, const char *eos) { unsigned char ch; unsigned int len = name - eos; /* Minimum length is MIN + whitespace. Check this directly. ASSUMES: MIN_FUNCTION_LENGTH == 2 */ if (MY_PREDICT_TRUE(len < MIN_FUNCTION_LENGTH + 1 || !func_char_map[(int)(name[0])] || !func_char_map[(int)(name[1])])) return 0; if (MY_PREDICT_TRUE(!func_char_map[ch = name[2]])) return isspace (ch) ? name + 2 : 0; name += 3; if (len > MAX_FUNCTION_LENGTH) len = MAX_FUNCTION_LENGTH - 3; else if (len == 3) len -= 3; if (!len) return 0; /* Loop over the remaining possiblities. */ while (func_char_map[ch = *name]) { if (!len--) return 0; name++; } if (ch == '\0' || isblank (ch)) return name; return 0; } #endif /* CONFIG_WITH_VALUE_LENGTH */ /* expand.c */ #ifndef CONFIG_WITH_VALUE_LENGTH char *recursively_expand_for_file (struct variable *v, struct file *file); #define recursively_expand(v) recursively_expand_for_file (v, NULL) #else char *recursively_expand_for_file (struct variable *v, struct file *file, unsigned int *value_lenp); #define recursively_expand(v) recursively_expand_for_file (v, NULL, NULL) #endif /* variable.c */ struct variable_set_list *create_new_variable_set (void); void free_variable_set (struct variable_set_list *); struct variable_set_list *push_new_variable_scope (void); void pop_variable_scope (void); void define_automatic_variables (void); void initialize_file_variables (struct file *file, int reading); void print_file_variables (const struct file *file); void print_variable_set (struct variable_set *set, char *prefix); void merge_variable_set_lists (struct variable_set_list **to_list, struct variable_set_list *from_list); #ifndef CONFIG_WITH_VALUE_LENGTH struct variable *do_variable_definition (const struct floc *flocp, const char *name, const char *value, enum variable_origin origin, enum variable_flavor flavor, int target_var); #else /* CONFIG_WITH_VALUE_LENGTH */ # define do_variable_definition(flocp, varname, value, origin, flavor, target_var) \ do_variable_definition_2 ((flocp), (varname), (value), ~0U, 0, NULL, \ (origin), (flavor), (target_var)) struct variable *do_variable_definition_2 (const struct floc *flocp, const char *varname, const char *value, unsigned int value_len, int simple_value, char *free_value, enum variable_origin origin, enum variable_flavor flavor, int target_var); #endif /* CONFIG_WITH_VALUE_LENGTH */ char *parse_variable_definition (const char *line, enum variable_flavor *flavor); struct variable *assign_variable_definition (struct variable *v, char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos)); struct variable *try_variable_definition (const struct floc *flocp, char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos), enum variable_origin origin, int target_var); void init_hash_global_variable_set (void); void hash_init_function_table (void); struct variable *lookup_variable (const char *name, unsigned int length); struct variable *lookup_variable_in_set (const char *name, unsigned int length, const struct variable_set *set); #ifdef CONFIG_WITH_VALUE_LENGTH void append_string_to_variable (struct variable *v, const char *value, unsigned int value_len, int append); struct variable *define_variable_in_set (const char *name, unsigned int length, const char *value, unsigned int value_length, int duplicate_value, enum variable_origin origin, int recursive, struct variable_set *set, const struct floc *flocp); /* Define a variable in the current variable set. */ #define define_variable(n,l,v,o,r) \ define_variable_in_set((n),(l),(v),~0U,1,(o),(r),\ current_variable_set_list->set,NILF) #define define_variable_vl(n,l,v,vl,dv,o,r) \ define_variable_in_set((n),(l),(v),(vl),(dv),(o),(r),\ current_variable_set_list->set,NILF) /* Define a variable with a constant name in the current variable set. */ #define define_variable_cname(n,v,o,r) \ define_variable_in_set((n),(sizeof (n) - 1),(v),~0U,1,(o),(r),\ current_variable_set_list->set,NILF) /* Define a variable with a location in the current variable set. */ #define define_variable_loc(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),~0U,1,(o),(r),\ current_variable_set_list->set,(f)) /* Define a variable with a location in the global variable set. */ #define define_variable_global(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),~0U,1,(o),(r),NULL,(f)) #define define_variable_vl_global(n,l,v,vl,dv,o,r,f) \ define_variable_in_set((n),(l),(v),(vl),(dv),(o),(r),NULL,(f)) /* Define a variable in FILE's variable set. */ #define define_variable_for_file(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),~0U,1,(o),(r),(f)->variables->set,NILF) #else /* !CONFIG_WITH_VALUE_LENGTH */ struct variable *define_variable_in_set (const char *name, unsigned int length, const char *value, enum variable_origin origin, int recursive, struct variable_set *set, const struct floc *flocp); /* Define a variable in the current variable set. */ #define define_variable(n,l,v,o,r) \ define_variable_in_set((n),(l),(v),(o),(r),\ current_variable_set_list->set,NILF) /* force merge conflict */ /* Define a variable with a constant name in the current variable set. */ #define define_variable_cname(n,v,o,r) \ define_variable_in_set((n),(sizeof (n) - 1),(v),(o),(r),\ current_variable_set_list->set,NILF) /* force merge conflict */ /* Define a variable with a location in the current variable set. */ #define define_variable_loc(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),(o),(r),\ current_variable_set_list->set,(f)) /* force merge conflict */ /* Define a variable with a location in the global variable set. */ #define define_variable_global(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),(o),(r),NULL,(f)) /* force merge conflict */ /* Define a variable in FILE's variable set. */ #define define_variable_for_file(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF) /* force merge conflict */ #endif /* !CONFIG_WITH_VALUE_LENGTH */ void undefine_variable_in_set (const char *name, unsigned int length, enum variable_origin origin, struct variable_set *set); /* Remove variable from the current variable set. */ #define undefine_variable_global(n,l,o) \ undefine_variable_in_set((n),(l),(o),NULL) /* Warn that NAME is an undefined variable. */ #define warn_undefined(n,l) do{\ if (warn_undefined_variables_flag) \ error (reading_file, \ _("warning: undefined variable `%.*s'"), \ (int)(l), (n)); \ }while(0) char **target_environment (struct file *file); struct pattern_var *create_pattern_var (const char *target, const char *suffix); extern int export_all_variables; #ifdef CONFIG_WITH_STRCACHE2 extern struct strcache2 variable_strcache; #endif #ifdef KMK # define MAKELEVEL_NAME "KMK_LEVEL" #else #define MAKELEVEL_NAME "MAKELEVEL" #endif #define MAKELEVEL_LENGTH (sizeof (MAKELEVEL_NAME) - 1) kbuild-2695/src/kmk/testcase-stack.kmk0000644000000000000000000000545712247157306016446 0ustar rootroot# $Id: testcase-stack.kmk 2413 2010-09-11 17:43:04Z bird $ ## @file # kBuild - testcase for the functions. # # # Copyright (c) 2007-2010 knut st. osmundsen # # This file is part of kBuild. # # kBuild is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # kBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with kBuild. If not, see # # DEPTH = ../.. include $(PATH_KBUILD)/header.kmk ifneq ($(not 1),) $(error The 'not' function is missing) endif ifneq ($(eq 1,1),1) $(error The 'eq' function is missing) endif ASSERT1 = $(if $(not $(eq $(STACK1),$(1))),$(error failure: STACK1:='$(STACK1)' expected='$(1)')) $(call stack-push,STACK1,1) $(call ASSERT,1) $(call stack-push,STACK1,2) $(call ASSERT,1 2) $(call stack-push,STACK1,3) $(call ASSERT,1 2 3) $(call stack-push,STACK1,4) $(call ASSERT,1 2 3 4) $(call stack-push,STACK1,5) $(call ASSERT,1 2 3 4 5) $(call stack-popv,STACK1) $(call ASSERT,1 2 3 4) $(call stack-push,STACK1,5) $(call ASSERT,1 2 3 4 5) $(call stack-popv,STACK1) $(call ASSERT,1 2 3 4) $(call stack-popv,STACK1) $(call ASSERT,1 2 3) $(call stack-push,STACK1,4) $(call ASSERT,1 2 3 4) $(call stack-push,STACK1,5) $(call ASSERT,1 2 3 4 5) top := $(call stack-top,STACK1) $(if $(not $(eq $(top),5)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='5')) $(call ASSERT,1 2 3 4 5) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),5)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='5')) $(call ASSERT,1 2 3 4) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),4)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='4')) $(call ASSERT,1 2 3) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),3)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='3')) $(call ASSERT,1 2) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),2)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='2')) $(call ASSERT,1) top := $(call stack-top,STACK1) $(if $(not $(eq $(top),1)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='1')) $(call ASSERT,1) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),1)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='1')) $(call ASSERT,) top := $(call stack-pop,STACK1) $(if $(not $(eq $(top),)),$(error failure STACK1:='$(STACK1)' top:='$(top)' expected='')) $(call ASSERT,) all_recursive: $(ECHO) The stack works.$(STACK1) kbuild-2695/src/kmk/kbuild-read.c0000644000000000000000000004232412247157306015345 0ustar rootroot/* $Id: kbuild-read.c 2549 2011-11-09 01:22:04Z bird $ */ /** @file * kBuild specific make functionality related to read.c. */ /* * Copyright (c) 2011 knut st. osmundsen * * This file is part of kBuild. * * kBuild is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * kBuild is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kBuild. If not, see * */ /* No GNU coding style here! */ /******************************************************************************* * Header Files * *******************************************************************************/ #include "make.h" #include "filedef.h" #include "variable.h" #include "dep.h" #include "debug.h" #include "kbuild.h" #include /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ #define WORD_IS(a_pszWord, a_cchWord, a_szWord2) \ ( (a_cchWord) == sizeof(a_szWord2) - 1 && memcmp((a_pszWord), a_szWord2, sizeof(a_szWord2) - 1) == 0) /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ /** Indicate which kind of kBuild define we're working on. */ enum kBuildDef { kBuildDef_Invalid, kBuildDef_Target, kBuildDef_Template, kBuildDef_Tool, kBuildDef_Sdk, kBuildDef_Unit }; enum kBuildExtendBy { kBuildExtendBy_NoParent, kBuildExtendBy_Overriding, kBuildExtendBy_Appending, kBuildExtendBy_Prepending }; /** * The data we stack during eval. */ struct kbuild_eval_data { /** The kind of define. */ enum kBuildDef enmKind; /** The bare name of the define. */ char *pszName; /** The file location where this define was declared. */ struct floc FileLoc; /** Pointer to the next element in the global list. */ struct kbuild_eval_data *pGlobalNext; /** Pointer to the element below us on the stack. */ struct kbuild_eval_data *pStackDown; /** The variable set associated with this define. */ struct variable_set_list *pVariables; /** The saved current variable set, for restoring in kBuild-endef. */ struct variable_set_list *pVariablesSaved; /** The parent name, NULL if none. */ char *pszParent; /** The inheritance method. */ enum kBuildExtendBy enmExtendBy; /** Pointer to the parent. Resolved lazily, so it can be NULL even if we have * a parent. */ struct kbuild_eval_data *pParent; /** The template, NULL if none. Only applicable to targets. */ char *pszTemplate; /** Pointer to the template. Resolved lazily, so it can be NULL even if we have * a parent. */ struct kbuild_eval_data *pTemplate; /** The variable prefix. */ char *pszVarPrefix; /** The length of the variable prefix. */ size_t cchVarPrefix; }; /******************************************************************************* * Header Files * *******************************************************************************/ /** Linked list (LIFO) of kBuild defines. * @todo use a hash! */ struct kbuild_eval_data *g_pHeadKbDefs = NULL; /** Stack of kBuild defines. */ struct kbuild_eval_data *g_pTopKbDef = NULL; struct variable_set * get_top_kbuild_variable_set(void) { struct kbuild_eval_data *pTop = g_pTopKbDef; assert(pTop != NULL); return pTop->pVariables->set; } char * kbuild_prefix_variable(const char *pszName, unsigned int *pcchName) { struct kbuild_eval_data *pTop = g_pTopKbDef; char *pszPrefixed; unsigned int cchPrefixed; assert(pTop != NULL); cchPrefixed = pTop->cchVarPrefix + *pcchName; pszPrefixed = xmalloc(cchPrefixed + 1); memcpy(pszPrefixed, pTop->pszVarPrefix, pTop->cchVarPrefix); memcpy(&pszPrefixed[pTop->cchVarPrefix], pszName, *pcchName); pszPrefixed[cchPrefixed] = '\0'; *pcchName = cchPrefixed; return pszPrefixed; } static const char * eval_kbuild_kind_to_string(enum kBuildDef enmKind) { switch (enmKind) { case kBuildDef_Target: return "target"; case kBuildDef_Template: return "template"; case kBuildDef_Tool: return "tool"; case kBuildDef_Sdk: return "sdk"; case kBuildDef_Unit: return "unit"; default: case kBuildDef_Invalid: return "invalid"; } } static char * allocate_expanded_next_token(const char **ppszCursor, const char *pszEos, unsigned int *pcchToken, int fStrip) { unsigned int cchToken; char *pszToken = find_next_token_eos(ppszCursor, pszEos, &cchToken); if (pszToken) { pszToken = allocated_variable_expand_2(pszToken, cchToken, &cchToken); if (pszToken) { if (fStrip) { unsigned int off = 0; while (MY_IS_BLANK(pszToken[off])) off++; if (off) { cchToken -= off; memmove(pszToken, &pszToken[off], cchToken + 1); } while (cchToken > 0 && MY_IS_BLANK(pszToken[cchToken - 1])) pszToken[--cchToken] = '\0'; } assert(cchToken == strlen(pszToken)); if (pcchToken) *pcchToken = cchToken; } } return pszToken; } static struct kbuild_eval_data * eval_kbuild_resolve_parent(struct kbuild_eval_data *pData) { if ( !pData->pParent && pData->pszParent) { struct kbuild_eval_data *pCur = g_pHeadKbDefs; while (pCur) { if ( pCur->enmKind == pData->enmKind && !strcmp(pCur->pszName, pData->pszParent)) { if ( pCur->pszParent && ( pCur->pParent == pData || !strcmp(pCur->pszParent, pData->pszName)) ) fatal(&pData->FileLoc, _("'%s' and '%s' are both trying to be each other children..."), pData->pszName, pCur->pszName); pData->pParent = pCur; pData->pVariables->next = pData->pVariables; break; } pCur = pCur->pGlobalNext; } } return pData->pParent; } static int eval_kbuild_define_xxxx(struct kbuild_eval_data **ppData, const struct floc *pFileLoc, const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildDef enmKind) { unsigned int cch; unsigned int cchName; char ch; char *psz; const char *pszPrefix; struct kbuild_eval_data *pData; if (fIgnoring) return 0; /* * Create a new kBuild eval data item. */ pData = xmalloc(sizeof(*pData)); pData->enmKind = enmKind; pData->pszName = NULL; pData->FileLoc = *pFileLoc; pData->pGlobalNext = g_pHeadKbDefs; g_pHeadKbDefs = pData; pData->pStackDown = *ppData; *ppData = g_pTopKbDef = pData; pData->pVariables = create_new_variable_set(); pData->pVariablesSaved = NULL; pData->pszParent = NULL; pData->enmExtendBy = kBuildExtendBy_NoParent; pData->pParent = NULL; pData->pszTemplate = NULL; pData->pTemplate = NULL; pData->pszVarPrefix = NULL; pData->cchVarPrefix = 0; /* * The first word is the name. */ pData->pszName = allocate_expanded_next_token(&pszLine, pszEos, &cchName, 1 /*strip*/); if (!pData->pszName || !*pData->pszName) fatal(pFileLoc, _("The kBuild define requires a name")); psz = pData->pszName; while ((ch = *psz++) != '\0') if (!isgraph(ch)) { error(pFileLoc, _("The 'kBuild-define-%s' name '%s' contains one or more invalid characters"), eval_kbuild_kind_to_string(enmKind), pData->pszName); break; } /* * Parse subsequent words. */ psz = find_next_token_eos(&pszLine, pszEos, &cch); while (psz) { if (WORD_IS(psz, cch, "extending")) { /* Inheritance directive. */ if (pData->pszParent != NULL) fatal(pFileLoc, _("'extending' can only occure once")); pData->pszParent = allocate_expanded_next_token(&pszLine, pszEos, &cch, 1 /*strip*/); if (!pData->pszParent || !*pData->pszParent) fatal(pFileLoc, _("'extending' requires a parent name")); pData->enmExtendBy = kBuildExtendBy_Overriding; /* optionally 'by overriding|prepending|appending' */ psz = find_next_token_eos(&pszLine, pszEos, &cch); if (psz && WORD_IS(psz, cch, "by")) { cch = 0; psz = find_next_token_eos(&pszLine, pszEos, &cch); if (WORD_IS(psz, cch, "overriding")) pData->enmExtendBy = kBuildExtendBy_Overriding; else if (WORD_IS(psz, cch, "appending")) pData->enmExtendBy = kBuildExtendBy_Appending; else if (WORD_IS(psz, cch, "prepending")) pData->enmExtendBy = kBuildExtendBy_Prepending; else fatal(pFileLoc, _("Unknown 'extending by' method '%.*s'"), (int)cch, psz); /* next token */ psz = find_next_token_eos(&pszLine, pszEos, &cch); } } else if (WORD_IS(psz, cch, "using")) { /* Template directive. */ if (enmKind != kBuildDef_Tool) fatal(pFileLoc, _("'using