* Tracked down the mkdepend tool which Ingo used in his updated makefile-engine
which auto-generates dependencies. It was written by Lars Duening for BeOS and uses libglob, which is also part of make. To re-use libglob and since make is already part of the Haiku tree, I added mkdepend to the bin tools. * Added Lars Duening's copyright to AboutSystem. * Added skeleton makefile and makefile-engine to data/develop. * Added mkdepend and makefile-engine files to the Development optional package. It could be argued to move the make bin command there too, from it's current location in the HaikuImage file. However, make could be useful to always have available. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29609 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d15b54c97f
commit
432ce3738d
@ -197,6 +197,21 @@ if [ IsOptionalHaikuImagePackageAdded Development ] && $(TARGET_ARCH) = x86 {
|
||||
# cc and c++ wrapper scripts
|
||||
AddFilesToHaikuImage beos bin : cc c++ ;
|
||||
|
||||
# mkdepend build tool, which is part of the Haiku source tree
|
||||
# (same as make, but make is already included independent of the
|
||||
# Development package)
|
||||
AddFilesToHaikuImage beos bin : mkdepend ;
|
||||
|
||||
# skeleton makefile and makefile-engine
|
||||
local makefileEngineFiles =
|
||||
<makefile-engine>makefile
|
||||
<makefile-engine>makefile-engine
|
||||
;
|
||||
SEARCH on $(makefileEngineFiles)
|
||||
= [ FDirName $(HAIKU_TOP) data develop ] ;
|
||||
AddFilesToHaikuImage develop etc
|
||||
: $(makefileEngineFiles) ;
|
||||
|
||||
# headers
|
||||
AddHeaderDirectoryToHaikuImage gnu : 3rdparty ;
|
||||
AddHeaderDirectoryToHaikuImage os ;
|
||||
|
120
data/develop/makefile
Normal file
120
data/develop/makefile
Normal file
@ -0,0 +1,120 @@
|
||||
## BeOS Generic Makefile v2.2 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS and Haiku.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME=
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE=
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
SRCS=
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS=
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS=
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS=
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS =
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS =
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
OPTIMIZE=
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES=
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS =
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS =
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from a source-level
|
||||
# debugger. Note that this will disable all optimzation.
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS =
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
# specify the version of this particular item
|
||||
# (for example, -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL")
|
||||
# This may also be specified in a resource.
|
||||
APP_VERSION =
|
||||
|
||||
# (for TYPE == DRIVER only) Specify desired location of driver in the /dev
|
||||
# hierarchy. Used by the driverinstall rule. E.g., DRIVER_PATH = video/usb will
|
||||
# instruct the driverinstall rule to place a symlink to your driver's binary in
|
||||
# ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will appear at
|
||||
# /dev/video/usb when loaded. Default is "misc".
|
||||
DRIVER_PATH =
|
||||
|
||||
## include the makefile-engine
|
||||
include $(BUILDHOME)/etc/makefile-engine
|
361
data/develop/makefile-engine
Normal file
361
data/develop/makefile-engine
Normal file
@ -0,0 +1,361 @@
|
||||
## BeOS and Haiku Generic Makefile Engine v2.2.0
|
||||
## Does all the hard work for the Generic Makefile
|
||||
## which simply defines the project parameters
|
||||
|
||||
## Supports Generic Makefile v2.0, 2.01, 2.1, 2.2
|
||||
|
||||
# determine wheather running on x86 or ppc
|
||||
MACHINE=$(shell uname -m)
|
||||
ifeq ($(MACHINE), BePC)
|
||||
CPU = x86
|
||||
else
|
||||
CPU = ppc
|
||||
endif
|
||||
|
||||
# set the directory where object files and binaries will be created
|
||||
OBJ_DIR := obj.$(CPU)
|
||||
|
||||
# create some default settings
|
||||
ifeq ($(NAME), )
|
||||
NAME = NameThisApp
|
||||
endif
|
||||
|
||||
ifeq ($(TYPE), )
|
||||
TYPE = APP
|
||||
endif
|
||||
|
||||
ifeq ($(DRIVER_PATH), )
|
||||
DRIVER_PATH = misc
|
||||
endif
|
||||
|
||||
# specify that the binary should be created in the object directory
|
||||
# NOTE: make doesn't find the target if its name is enclosed in
|
||||
# quotation marks
|
||||
# TARGET := "$(OBJ_DIR)/$(NAME)"
|
||||
TARGET := $(OBJ_DIR)/$(NAME)
|
||||
|
||||
# specify the mimeset tool
|
||||
MIMESET := mimeset
|
||||
|
||||
# specify the tools for adding and removing resources
|
||||
XRES = xres
|
||||
|
||||
|
||||
# platform specific settings
|
||||
|
||||
# x86 Settings
|
||||
ifeq ($(CPU), x86)
|
||||
# set the compiler and compiler flags
|
||||
CC = gcc
|
||||
|
||||
# SETTING: set the CFLAGS for each binary type
|
||||
ifeq ($(TYPE), DRIVER)
|
||||
CFLAGS += -D_KERNEL_MODE=1 -no-fpic
|
||||
else
|
||||
CFLAGS +=
|
||||
endif
|
||||
|
||||
# SETTING: set the proper optimization level
|
||||
ifeq ($(OPTIMIZE), FULL)
|
||||
OPTIMIZER = -O3
|
||||
else
|
||||
ifeq ($(OPTIMIZE), SOME)
|
||||
OPTIMIZER = -O1
|
||||
else
|
||||
ifeq ($(OPTIMIZE), NONE)
|
||||
OPTIMIZER = -O0
|
||||
else
|
||||
# OPTIMIZE not set so set to full
|
||||
OPTIMIZER = -O3
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
|
||||
# SETTING: set proper debugger flags
|
||||
ifeq ($(DEBUGGER), TRUE)
|
||||
DEBUG += -g
|
||||
OPTIMIZER = -O0
|
||||
endif
|
||||
|
||||
CFLAGS += $(OPTIMIZER) $(DEBUG)
|
||||
|
||||
# SETTING: set warning level
|
||||
ifeq ($(WARNINGS), ALL)
|
||||
CFLAGS += -Wall -Wno-multichar -Wno-ctor-dtor-privacy
|
||||
else
|
||||
ifeq ($(WARNINGS), NONE)
|
||||
CFLAGS += -w
|
||||
endif
|
||||
endif
|
||||
|
||||
# set the linker and linker flags
|
||||
LD = gcc
|
||||
LDFLAGS += $(DEBUG)
|
||||
|
||||
# SETTING: set linker flags for each binary type
|
||||
ifeq ($(TYPE), APP)
|
||||
LDFLAGS += -Xlinker -soname=_APP_
|
||||
else
|
||||
ifeq ($(TYPE), SHARED)
|
||||
LDFLAGS += -nostart -Xlinker -soname=$(NAME)
|
||||
else
|
||||
ifeq ($(TYPE), DRIVER)
|
||||
LDFLAGS += -nostdlib /boot/develop/lib/x86/_KERNEL_
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
else
|
||||
|
||||
# ppc Settings
|
||||
ifeq ($(CPU), ppc)
|
||||
# set the compiler and compiler flags
|
||||
CC = mwcc
|
||||
CFLAGS +=
|
||||
|
||||
# SETTING: set the proper optimization level
|
||||
ifeq ($(OPTIMIZE), FULL)
|
||||
OPTIMIZER = -O7
|
||||
else
|
||||
ifeq ($(OPTIMIZE), SOME)
|
||||
OPTIMIZER = -O3
|
||||
else
|
||||
ifeq ($(OPTIMIZE), NONE)
|
||||
OPTIMIZER = -O0
|
||||
else
|
||||
# OPTIMIZE not set so set to full
|
||||
OPTIMIZER = -O7
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
#set the proper debugger settings
|
||||
ifeq ($(DEBUGGER), TRUE)
|
||||
DEBUG += -g
|
||||
endif
|
||||
|
||||
CFLAGS += $(OPTIMIZER) $(DEBUG)
|
||||
|
||||
# SETTING: set warning level
|
||||
ifeq ($(WARNINGS), ALL)
|
||||
CFLAGS += -w on -requireprotos
|
||||
else
|
||||
ifeq ($(WARNINGS), NONE)
|
||||
CFLAGS += -w off
|
||||
endif
|
||||
endif
|
||||
|
||||
# clear the standard environment variable
|
||||
# now there are no standard libraries to link against
|
||||
BELIBFILES=
|
||||
|
||||
# set the linker and linker flags
|
||||
LD = mwldppc
|
||||
|
||||
# SETTING: set linker flags for each binary type
|
||||
ifeq ($(TYPE), APP)
|
||||
LDFLAGS +=
|
||||
else
|
||||
ifeq ($(TYPE), SHARED)
|
||||
LDFLAGS += -xms
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(TYPE), DRIVER)
|
||||
LDFLAGS += -nodefaults \
|
||||
-export all \
|
||||
-G \
|
||||
/boot/develop/lib/ppc/glue-noinit.a \
|
||||
/boot/develop/lib/ppc/_KERNEL_
|
||||
else
|
||||
LDFLAGS += -export pragma \
|
||||
-init _init_routine_ \
|
||||
-term _term_routine_ \
|
||||
-lroot \
|
||||
/boot/develop/lib/ppc/glue-noinit.a \
|
||||
/boot/develop/lib/ppc/init_term_dyn.o \
|
||||
/boot/develop/lib/ppc/start_dyn.o
|
||||
endif
|
||||
|
||||
|
||||
# SETTING: output symbols in an xMAP file
|
||||
ifeq ($(SYMBOLS), TRUE)
|
||||
LDFLAGS += -map $(TARGET).xMAP
|
||||
endif
|
||||
|
||||
# SETTING: output debugging info to a .SYM file
|
||||
ifeq ($(DEBUGGER), TRUE)
|
||||
LDFLAGS += -g -osym $(TARGET).SYM
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
# psuedo-function for converting a list of source files in SRCS variable
|
||||
# to a corresponding list of object files in $(OBJ_DIR)/xxx.o
|
||||
# The "function" strips off the src file suffix (.ccp or .c or whatever)
|
||||
# and then strips of the directory name, leaving just the root file name.
|
||||
# It then appends the .o suffix and prepends the $(OBJ_DIR)/ path
|
||||
define SRCS_LIST_TO_OBJS
|
||||
$(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \
|
||||
$(basename $(notdir $(file))))))
|
||||
endef
|
||||
|
||||
define SRCS_LIST_TO_DEPENDS
|
||||
$(addprefix $(OBJ_DIR)/, $(addsuffix .d, $(foreach file, $(SRCS), \
|
||||
$(basename $(notdir $(file))))))
|
||||
endef
|
||||
|
||||
OBJS = $(SRCS_LIST_TO_OBJS)
|
||||
DEPENDS = $(SRCS_LIST_TO_DEPENDS)
|
||||
|
||||
# create a unique list of paths to our sourcefiles
|
||||
SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file))))
|
||||
|
||||
# add source paths to VPATH if not already present
|
||||
VPATH :=
|
||||
VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS))))
|
||||
|
||||
# SETTING: build the local and system include paths
|
||||
ifeq ($(CPU), x86)
|
||||
LOC_INCLUDES = $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -I, $(path)))
|
||||
SYS_INCLUDES += -I-
|
||||
SYS_INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -I, $(path)))
|
||||
else
|
||||
ifeq ($(CPU), ppc)
|
||||
LOC_INCLUDES = $(foreach path, $(SRC_PATHS) $(LOCAL_INCLUDE_PATHS), $(addprefix -I, $(path)))
|
||||
SYS_INCLUDES += -i-
|
||||
SYS_INCLUDES += $(foreach path, $(SYSTEM_INCLUDE_PATHS), $(addprefix -i , $(path)))
|
||||
endif
|
||||
endif
|
||||
|
||||
INCLUDES = $(LOC_INCLUDES) $(SYS_INCLUDES)
|
||||
|
||||
# SETTING: add the -L prefix to all library paths to search
|
||||
LINK_PATHS = $(foreach path, $(SRC_PATHS) $(LIBPATHS), \
|
||||
$(addprefix -L, $(path)))
|
||||
|
||||
# SETTING: specify the additional libraries to link against
|
||||
# if the libraries have a .so or .a prefix, or if they are _APP_ or _KERNEL_
|
||||
# simply add them to the list
|
||||
LINK_LIBS += $(filter %.so %.a _APP_ _KERNEL_, $(LIBS))
|
||||
# if the libraries do not have suffixes and are not _APP_ or _KERNEL_
|
||||
# prepend -l to each name: be becomes -lbe
|
||||
LINK_LIBS += $(foreach lib, $(filter-out %.so %.a _APP_ _KERNEL_, $(LIBS)), $(addprefix -l, $(lib)))
|
||||
|
||||
# add to the linker flags
|
||||
LDFLAGS += $(LINK_PATHS) $(LINK_LIBS)
|
||||
|
||||
# SETTING: add the defines to the compiler flags
|
||||
CFLAGS += $(foreach define, $(DEFINES), $(addprefix -D, $(define)))
|
||||
|
||||
# SETTING: add the additional compiler flags
|
||||
CFLAGS += $(COMPILER_FLAGS)
|
||||
|
||||
# SETTING: add the additional linker flags
|
||||
LDFLAGS += $(LINKER_FLAGS)
|
||||
|
||||
# SETTING: use the archive tools if building a static library
|
||||
# otherwise use the linker
|
||||
ifeq ($(TYPE), STATIC)
|
||||
BUILD_LINE = ar -cru "$(TARGET)" $(OBJS)
|
||||
else
|
||||
BUILD_LINE = $(LD) -o $@ $(OBJS) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
# create the resource instruction
|
||||
ifeq ($(RSRCS), )
|
||||
DO_RSRCS :=
|
||||
else
|
||||
DO_RSRCS := $(XRES) -o "$(TARGET)" $(RSRCS)
|
||||
endif
|
||||
|
||||
|
||||
# define the actual work to be done
|
||||
default: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJ_DIR) $(OBJS) $(RSRCS)
|
||||
$(BUILD_LINE)
|
||||
$(DO_RSRCS)
|
||||
$(MIMESET) -f $@
|
||||
|
||||
|
||||
# rule to create the object file directory if needed
|
||||
$(OBJ_DIR)::
|
||||
@[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1
|
||||
|
||||
# rules to make the dependency files
|
||||
$(OBJ_DIR)/%.d : %.c
|
||||
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
|
||||
mkdepend $(LOC_INCLUDES) -p .c:$(OBJ_DIR)/%n.o -m -f $@ $<
|
||||
$(OBJ_DIR)/%.d : %.cpp
|
||||
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
|
||||
mkdepend $(LOC_INCLUDES) -p .cpp:$(OBJ_DIR)/%n.o -m -f $@ $<
|
||||
$(OBJ_DIR)/%.d : %.cp
|
||||
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
|
||||
mkdepend $(LOC_INCLUDES) -p .cp:$(OBJ_DIR)/%n.o -m -f $@ $<
|
||||
$(OBJ_DIR)/%.d : %.cc
|
||||
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
|
||||
mkdepend $(LOC_INCLUDES) -p .cc:$(OBJ_DIR)/%n.o -m -f $@ $<
|
||||
$(OBJ_DIR)/%.d : %.C
|
||||
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
|
||||
mkdepend $(LOC_INCLUDES) -p .C:$(OBJ_DIR)/%n.o -m -f $@ $<
|
||||
$(OBJ_DIR)/%.d : %.CC
|
||||
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
|
||||
mkdepend $(LOC_INCLUDES) -p .CC:$(OBJ_DIR)/%n.o -m -f $@ $<
|
||||
$(OBJ_DIR)/%.d : %.CPP
|
||||
[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1; \
|
||||
mkdepend $(LOC_INCLUDES) -p .CPP:$(OBJ_DIR)/%n.o -m -f $@ $<
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
# rules to make the object files
|
||||
$(OBJ_DIR)/%.o : %.c
|
||||
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o $@
|
||||
$(OBJ_DIR)/%.o : %.cpp
|
||||
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o $@
|
||||
$(OBJ_DIR)/%.o : %.cp
|
||||
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o $@
|
||||
$(OBJ_DIR)/%.o : %.cc
|
||||
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o $@
|
||||
$(OBJ_DIR)/%.o : %.C
|
||||
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o $@
|
||||
$(OBJ_DIR)/%.o : %.CC
|
||||
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o $@
|
||||
$(OBJ_DIR)/%.o : %.CPP
|
||||
$(CC) -c $< $(INCLUDES) $(CFLAGS) -o $@
|
||||
|
||||
# rules to handle lex/flex and yacc/bison files
|
||||
|
||||
$(OBJ_DIR)/%.o: %.l
|
||||
flex $<
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) lex.yy.c -o $@
|
||||
$(OBJ_DIR)/%.o: %.y
|
||||
bison -d -y $<
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) y.tab.c -o $@
|
||||
|
||||
# empty rule. Things that depend on this rule will always get triggered
|
||||
FORCE:
|
||||
|
||||
# The generic clean command. Delete everything in the object folder.
|
||||
clean :: FORCE
|
||||
-rm -rf $(OBJ_DIR)
|
||||
|
||||
# remove just the application from the object folder
|
||||
rmapp ::
|
||||
-rm -f $(TARGET)
|
||||
|
||||
# make it easy to install drivers for testing
|
||||
USER_BIN_PATH = /boot/home/config/add-ons/kernel/drivers/bin
|
||||
USER_DEV_PATH = /boot/home/config/add-ons/kernel/drivers/dev
|
||||
|
||||
driverinstall ::
|
||||
ifeq ($(TYPE), DRIVER)
|
||||
copyattr --data $(OBJ_DIR)/$(NAME) $(USER_BIN_PATH)/$(NAME)
|
||||
mkdir -p $(USER_DEV_PATH)/$(DRIVER_PATH)
|
||||
ln -sf $(USER_BIN_PATH)/$(NAME) $(USER_DEV_PATH)/$(DRIVER_PATH)/$(NAME)
|
||||
endif
|
@ -788,6 +788,11 @@ AboutView::AboutView(const BRect &rect)
|
||||
"All rights reserved.",
|
||||
"http://tc.umn.edu/~ringx004");
|
||||
|
||||
// MkDepend 1.7 copyright (Makefile dependency generator)
|
||||
AddCopyrightEntry("MkDepend",
|
||||
"Copyright " B_UTF8_COPYRIGHT "1995-2001 Lars Düning. "
|
||||
"All rights reserved.");
|
||||
|
||||
// OpenSound
|
||||
// AddCopyrightEntry("OpenSound",
|
||||
// "Copyright " B_UTF8_COPYRIGHT " 1996-2008 4Front Technologies ",
|
||||
|
@ -194,6 +194,7 @@ SubInclude HAIKU_TOP src bin listdev ;
|
||||
SubInclude HAIKU_TOP src bin make ;
|
||||
SubInclude HAIKU_TOP src bin makebootable ;
|
||||
#SubInclude HAIKU_TOP src bin makeudfimage ;
|
||||
SubInclude HAIKU_TOP src bin mkdepend ;
|
||||
SubInclude HAIKU_TOP src bin mkdos ;
|
||||
SubInclude HAIKU_TOP src bin mkfs ;
|
||||
SubInclude HAIKU_TOP src bin multiuser ;
|
||||
|
110
src/bin/mkdepend/HISTORY
Normal file
110
src/bin/mkdepend/HISTORY
Normal file
@ -0,0 +1,110 @@
|
||||
** 14-Oct-2001, Lars Düning **
|
||||
- RELEASE 1.7
|
||||
- (main, args) New options '--no-warn-exit' to return a zero exitcode
|
||||
('success') when a warning was generated (for use in Makefiles).
|
||||
- (main, args) New options '--ignore-missing' to ignore missing include
|
||||
files (apart from printing a diagnostic).
|
||||
- (Makefile, libglob/Makefile) Added x86->PPC cross-compilation.
|
||||
|
||||
** 01-Mar-2000, Lars Düning **
|
||||
- RELEASE 1.6
|
||||
- (main, args, nodes) New option '--select' to narrow the dependency
|
||||
generation to a few selected files.
|
||||
- (Makefile, libglob/Makefile) Added crosscompilation PPC->x86.
|
||||
|
||||
** 03-Feb-1999, Lars Düning **
|
||||
- (main, args) When out of memory, the error message also contains a slightly
|
||||
cryptic hint where the program failed.
|
||||
- (Makefile) The 'archive' target also creates a checksum file for the
|
||||
archive, using the /bin/cksum command.
|
||||
The .dependencies are included only when no 'clean' or 'clobber' is
|
||||
requested (this solves the behavior Dianne noticed, that a 'make clean'
|
||||
first recreates .dependencies only to delete it again).
|
||||
|
||||
** 02-Feb-1999, Lars Düning **
|
||||
- (args.*) All information about an include directory is now combined
|
||||
in one structure.
|
||||
- (main.c, nodes.*) Rewrote the file identification and searching routines,
|
||||
the old code failed to discriminate files which are included from
|
||||
different directories.
|
||||
- (util.*) New.
|
||||
|
||||
- (getargs.c) A long option matched even when only the first characters
|
||||
were given. A test for the proper length corrected this.
|
||||
|
||||
** 25-Nov-1998, Lars Düning **
|
||||
- (getargs.c) A long option matched even when only the first characters
|
||||
were given. A test for the proper length corrected this.
|
||||
|
||||
** 01-Nov-1998, Lars Düning **
|
||||
- (getargs.c) If a value for an option was missing, the parser printed
|
||||
the wrong option name in the error message.
|
||||
|
||||
** 25-Oct-1998, Lars Düning **
|
||||
- RELEASE 1.4.5
|
||||
- (Makefile, libglob/Makefile) Adapted for R4 compilations.
|
||||
- (Makefile) Improved the dependency generation: dependencies are
|
||||
kept in the file .dependencies; and the rule is clever enough
|
||||
to fall back to the compiler facilities if mkdepend is not
|
||||
on the system.
|
||||
- (getargs) Separated the commandline parser into here.
|
||||
- (args) New options '--longhelp' to print a long help text, and
|
||||
'--version' to print the program version.
|
||||
'--include' distinguishes between normal and system include paths.
|
||||
- (main) Default file suffixes now also cover a whole range of
|
||||
C++ suffixes (.cc, .cpp, .cxx, .cc).
|
||||
Filenames with embedded spaces are written in quotes.
|
||||
- (nodes, reader, main) Added support for system includes.
|
||||
|
||||
** 15-Oct-1998, Lars Düning **
|
||||
- (main.c) The name for the makefile backup was allocated one character
|
||||
too short.
|
||||
|
||||
** 04-Jul-1998, Lars Düning **
|
||||
- RELEASE 1.4
|
||||
RCS-Name is 'Rel-1_4', State is 'Rel'.
|
||||
- Converted the program to BeOS. I decided to not keep the old Amiga
|
||||
code - it's available on Aminet and I won't further develop it anyway.
|
||||
New files: LICENSE.
|
||||
Changed files: Just about everything else.
|
||||
- Added libglob/ for filename globbing.
|
||||
|
||||
** 02-Mar-1996, Lars Düning **
|
||||
- RELEASE 1.3
|
||||
- Oops, when confronted with target/source relations, MkDepend put the
|
||||
source name into the dependency list as well. Though intentional, this
|
||||
had the potential to confuse implicit make rules. Now this behaviour
|
||||
is optional, triggered by specifying '+' with the object extension.
|
||||
(main.c, args.ch)
|
||||
- RCS tweaks to the Makefiles.
|
||||
|
||||
** 25-Feb-1996, Lars Düning **
|
||||
- RELEASE 1.2
|
||||
- main.c (output_tree, output): Added output of includers of a file.
|
||||
- main.c (readfiles): If a file can't be found, it's users known so far
|
||||
are printed in the warning notice.
|
||||
- nodes.c,h: Added .pUsers (List of includers of this file) to the Node
|
||||
structure, extended routines nodes_depend() and nodes_deplist()
|
||||
accordingly.
|
||||
- Put under RCS (the Makefiles still need tweaking for this, though).
|
||||
|
||||
** 04-Feb-1996, Lars Düning **
|
||||
- main.c (output, getargs, main): The program is now able to write the
|
||||
list of dependencies into a separate file as well.
|
||||
- main.c (output_tree): New to write the dependency tree into a file.
|
||||
- args.ch, main.c: Exported argument parsing into args.c.
|
||||
- reader.c (reader_openrw): Immediate writing if no file to read is
|
||||
opened is now possible.
|
||||
|
||||
** 13-Oct-1995, Lars Düning **
|
||||
- RELEASE 1.1
|
||||
- reader.c (reader_copymake2): Copies the remainder of the original
|
||||
Makefile starting with the second tagline.
|
||||
|
||||
** 12-Oct-1995, Lars Düning **
|
||||
- main.c (make_objname): %p pattern expanded to %[-][<][<number>]p.
|
||||
- Makefile, DMakefile: Making the 'archive' missed some files.
|
||||
|
||||
** 18-Sep-1995, Lars Düning **
|
||||
- RELEASE 1.0
|
||||
|
14
src/bin/mkdepend/Jamfile
Normal file
14
src/bin/mkdepend/Jamfile
Normal file
@ -0,0 +1,14 @@
|
||||
SubDir HAIKU_TOP src bin mkdepend ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
SubDirHdrs [ FDirName $(SUBDIR) .. make glob ] ;
|
||||
|
||||
BinCommand mkdepend :
|
||||
args.c
|
||||
getargs.c
|
||||
main.c
|
||||
reader.c
|
||||
nodes.c
|
||||
util.c
|
||||
: <make>libglob.a : mkdepend.rdef ;
|
28
src/bin/mkdepend/LICENSE
Normal file
28
src/bin/mkdepend/LICENSE
Normal file
@ -0,0 +1,28 @@
|
||||
MkDepend License
|
||||
|
||||
Copyright (c) 1995-2000, Lars Düning.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- 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.
|
||||
|
||||
- Modifications of the original software, in parts or as a whole,
|
||||
must be clearly recognizable as such.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
$Id: LICENSE 1.2 Wed, 01 Mar 2000 21:15:40 -0700 lars $
|
622
src/bin/mkdepend/MkDepend.doc
Normal file
622
src/bin/mkdepend/MkDepend.doc
Normal file
@ -0,0 +1,622 @@
|
||||
$Id: MkDepend.doc 1.10 Wed, 01 Mar 2000 21:15:40 -0700 lars $
|
||||
|
||||
MkDepend 1.7
|
||||
|
||||
Copyright (c) 1995-2001 by Lars Düning
|
||||
All Rights Reserved.
|
||||
|
||||
|
||||
"Good information are hard to get. It is even more difficult to put
|
||||
it into use." -- Sherlock Holmes
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
Makefiles are very useful in the development of larger program systems,
|
||||
as they notate the various dependencies and associated needed actions
|
||||
in a machine-useable notation. Unfortunately it's the most important
|
||||
dependency between C sources and their includes which have to be
|
||||
maintained by hand, a most boring and errorprone task.
|
||||
|
||||
MkDepend is one of those programs which attempt to automate this part
|
||||
of development by scanning source files for includes and repeating this
|
||||
step recursively until the complete transitive closure of included files
|
||||
is determined. The found dependencies are then written into an existing
|
||||
makefile, keeping it up to date, and/or into a separate file (the 'depfile')
|
||||
for use by the makefile or for documentary purposes.
|
||||
|
||||
The advantage of using MkDepend instead of the built-in dependency
|
||||
facilities of modern compilers is that (a) MkDepend is faster,
|
||||
(b) simplifies the maintenance of multiple and/or portable Makefiles,
|
||||
and (c) you can modify it for your special needs.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
MkDepend is a shell-only program, compiled for R4.5
|
||||
|
||||
|
||||
mkdepend {-i|-I|--include <includepath>[::<symbol>]}
|
||||
{-x|--except <filepattern>}
|
||||
{-S|--select <filepattern>}
|
||||
{-s|--suffix <src_ext>{,<src_ext>}[+][:<obj_ext>] | [+]:<obj_ext>}
|
||||
{-p|--objpat <src_ext>{,<src_ext>}[+]:<obj_pattern>}
|
||||
[-f|--file <makefile>]
|
||||
[-d|--dep <depfile>]
|
||||
[-l|--flat]
|
||||
[-m|--ignore-missing]
|
||||
[-w|--no-warn-exit]
|
||||
[-v|--verbose]
|
||||
[-h|-?|--help|--longhelp]
|
||||
[-V|--version]
|
||||
{<filename>}
|
||||
|
||||
|
||||
All option keywords are case sensitive. The space between the short
|
||||
form of the keywords and their operands may be omitted. For example
|
||||
|
||||
mkdepend -I/include
|
||||
mkdepend -i /include
|
||||
mkdepend -I=/include
|
||||
mkdepend --include=/include
|
||||
mkdepend --include /include
|
||||
|
||||
are all equivalent. Several short options may be combined, but only
|
||||
one of them may take an argument, and it must be the last one. For
|
||||
example:
|
||||
|
||||
mkdepend -vl
|
||||
mkdepend -vf Makefile
|
||||
|
||||
are legal, but
|
||||
|
||||
mkdepend -fv Makefile
|
||||
|
||||
will be misunderstood as 'mkdepend -f=v Makefile'.
|
||||
|
||||
The option '--' is special in that it marks the end of all option
|
||||
recognition. All following arguments are considered filenames even
|
||||
if they start with '-' or '--'.
|
||||
|
||||
|
||||
General Operation
|
||||
-----------------
|
||||
|
||||
MkDepend is given a 'skeleton' of C source files and searches them for
|
||||
included files. The includes found are recursively searched for includes
|
||||
themselves, until the complete transitive closure has been determined.
|
||||
MkDepend searches the includes first in the current directory, then in
|
||||
the given paths (if any), imitating the C preprocessor's behaviour.
|
||||
The files are scanned for include statements of the form
|
||||
|
||||
#include "filename"
|
||||
#include <filename>
|
||||
|
||||
excluding those which are commented out using C-style /* */- or
|
||||
C++-style //-comments. Every other content of the files is ignored.
|
||||
|
||||
After all includes have been found, the dependencies are written into
|
||||
a makefile (creating it if necessary). The makefile is searched for
|
||||
a line
|
||||
|
||||
# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS FOLLOW ---
|
||||
|
||||
after which MkDepend adds the dependencies, overwriting old ones, then
|
||||
terminating the dependencies with the line
|
||||
|
||||
# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS PRECEDE ---
|
||||
|
||||
Text following the second tagline in the makefile is not modified.
|
||||
|
||||
If the first tagline is not found, the tagged dependencies are simply
|
||||
appended to the file. Existing makefiles are modified by renaming it
|
||||
to <origname>.bak and then re-creating the makefile by copying the
|
||||
data not to be modified.
|
||||
|
||||
The found dependencies for the 'skeleton' files are written as
|
||||
|
||||
<skeleton> : <included file 1> <included file 2>...
|
||||
|
||||
Lines are limited to 80 chars, longer entries are folded into several
|
||||
lines, ending each but the last line with a backslash (\). If a
|
||||
name contains spaces, it is written within double quotes.
|
||||
|
||||
MkDepend can be taught to know about source/object file relationships
|
||||
to be used in the entries written. E,g, the entry generated for a typical
|
||||
C source file would be of the form
|
||||
|
||||
<skeleton>.o : <include 1> <include 2> ...
|
||||
|
||||
Includes appear with that path in the list under which MkDepend found
|
||||
them. To support multi-platform development, replacement texts may
|
||||
be specified for the paths which are then used instead in the output.
|
||||
|
||||
|
||||
For documentary purposes MkDepend may additionally (or instead) write
|
||||
the dependencies into a separate file, either as flat lists or in
|
||||
tree form. Here it writes the 'a includes b' relationships in the
|
||||
form "a <- b" as well as the 'b is included by a' relationsships
|
||||
in the form "b -> a".
|
||||
|
||||
|
||||
Selected-File Operation
|
||||
-----------------------
|
||||
|
||||
MkDepend can be instructed just look for dependencies involving
|
||||
some selected include files. This mode is activated by the use
|
||||
of one or more '-S' arguments; and the output in this mode is
|
||||
restricted to just the skeleton and the selected file.
|
||||
|
||||
For example, where a normal MkDepend run would generate
|
||||
|
||||
foobar.o : foobar.h yacc.tab.h main.h
|
||||
|
||||
call MkDepend with the argument '-S yacc.tab.h' would reduce this output
|
||||
to
|
||||
|
||||
foobar.o : yacc.tab.h
|
||||
|
||||
In the Makefile, these selected dependencies are put between
|
||||
|
||||
# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS FOLLOW ---
|
||||
# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS PRECEDE ---
|
||||
|
||||
delimiter lines, so that both kinds of operations can be used on the
|
||||
same Makefile.
|
||||
|
||||
|
||||
In addition, the output of the other dependency files is modified in
|
||||
a similar way.
|
||||
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
<filepattern>
|
||||
|
||||
Any command argument not recognizable as option is considered as
|
||||
specification of one of the 'skeleton' sources.
|
||||
Wildcards are recognized.
|
||||
|
||||
Default: *.c
|
||||
|
||||
Example:
|
||||
|
||||
mkdepend *.c *.cc grammar.y
|
||||
|
||||
All files ending in ".c" or ".cc" and the file "grammar.y"
|
||||
are considered.
|
||||
|
||||
The expansion of the wildcards is done by the shell.
|
||||
|
||||
------
|
||||
|
||||
-x <filepattern>
|
||||
--except <filepattern>
|
||||
|
||||
Files which are not part of the 'skeleton', even if they are specified
|
||||
as such. The filepattern may contain the typical bash-wildcards, which
|
||||
are expanded by MkDepend.
|
||||
|
||||
Example:
|
||||
|
||||
mkdepend *.c -x 'test*'
|
||||
|
||||
All files ending in ".c", except those whose name start with "test",
|
||||
are considered as sources. Note the quotes around "test*" to protect
|
||||
it from shell name expansion.
|
||||
|
||||
------
|
||||
|
||||
-S <filepattern>
|
||||
--select <filepattern>
|
||||
|
||||
The output of dependency information is restricted to just those
|
||||
'skeleton' source which include at least one of the <filepattern> files.
|
||||
Furthermore, only the named files are printed in the dependency lists.
|
||||
|
||||
The filepattern may contain the typical bash-wildcards, which are
|
||||
expanded by MkDepend _against the files existing at the time of
|
||||
program start_. The pattern has to match the full filename
|
||||
of the included file, including the directory part implicitely given
|
||||
by any -I argument.
|
||||
|
||||
Example:
|
||||
|
||||
mkdepend *.c -S 'yacc.tab.h'
|
||||
|
||||
Only the files which include "yacc.tab.h" will be listed in the
|
||||
output.
|
||||
|
||||
------
|
||||
|
||||
-I <includedir>[::<symbol>]}
|
||||
--include <includedir>[::<symbol>]}
|
||||
|
||||
Specify a directory to be searched for include files. The paths are
|
||||
searched in the order given on the command line. Unless '-I-' was
|
||||
specified, the directory the including file is in is searched first.
|
||||
|
||||
If <symbol> is specified, it replaces the <includedir> when writing
|
||||
dependencies to a makefile.
|
||||
|
||||
Usually, the path, made up from all given <includedir>s, is searched
|
||||
fully for both ""- and <>-includes. This behaviour changes if the
|
||||
path is split using the special dirname '-' (like in '-I-').
|
||||
|
||||
If '-I-' is used, all directories given before the '-I-' are searched
|
||||
only for ""-includes. The directories given after the '-I-' are
|
||||
searched for both ""- and <>-includes again. Also the directories of
|
||||
the including files are no longer searched automatically.
|
||||
|
||||
If a ""-include is not found, MkDepend will print a warning, but
|
||||
still list the file in the generated dependencies. Missing <>-includes
|
||||
on the other hand are silently ignored.
|
||||
|
||||
Example:
|
||||
|
||||
mkdepend -I /include -I- -I libglob
|
||||
|
||||
""-include files are searched in the current directory, in /include
|
||||
and in libglob. <>-include files are searched only in the
|
||||
current directory and libglob.
|
||||
|
||||
mkdepend -I '/include/pdlibs::$(PDLIBS)'
|
||||
|
||||
Include files are searched in the current directory and
|
||||
in /include/pdlibs. A file like "/include/pdlibs/tree.h" will be
|
||||
written as "$(PDLIBS)tree.h" into the makefile.
|
||||
Again note the use of quotes to keep the shell from expanding
|
||||
the text '$(PDLIBS)'.
|
||||
|
||||
Note that the syntax of this option is similar, but not identical to
|
||||
what most compilers expect. One example of an exception is the GNU
|
||||
C-Compiler which distinguishes between '-I' and '-i' in meaning. It is
|
||||
therefore advisable to only use the uppercase '-I' for both compiler
|
||||
and MkDepend.
|
||||
|
||||
------
|
||||
|
||||
-s <src_ext>{,<src_ext>}[+][:<obj_ext>] | [+]:<obj_ext>}
|
||||
--suffix <src_ext>{,<src_ext>}[+][:<obj_ext>] | [+]:<obj_ext>}
|
||||
|
||||
Specify a name relationship between source and object files.
|
||||
If a source name ends in one of the given <src_ext>s, an Makefile entry
|
||||
with the object name constructed using the associated <obj_ext>.
|
||||
The <obj_ext> given with no associated <src_ext> serves as default
|
||||
extension used for those <src_ext> which are given without own
|
||||
<obj_ext>.
|
||||
When constructing the dependency list for a defined source/object
|
||||
relation, the sourcefile itself is not included in the list, as
|
||||
usually implicit makerules take care of them. This can be overridden
|
||||
by specifying the '+' sign (which is associated with the given source
|
||||
extensions).
|
||||
|
||||
Default: -s :.o -s .c,.cc,.cpp,.cp,.cxx
|
||||
|
||||
Example:
|
||||
|
||||
mkdepend -s :.o -s '.c,.cc'
|
||||
|
||||
Default <obj_ext> is ".obj", which is used for files with the
|
||||
extensions ".c" and ".cc".
|
||||
|
||||
------
|
||||
|
||||
-p <src_ext>{,<src_ext>}[+]:<obj_pattern>
|
||||
--objpat <src_ext>{,<src_ext>}[+]:<obj_pattern>
|
||||
|
||||
Similar to SUFFIX, but allows more complicated name relations.
|
||||
<obj_pattern> gives the object file name verbatim, using placeholders
|
||||
for the actual filenames:
|
||||
|
||||
%s: the full sourcename (w/o suffix)
|
||||
%p: the path part of the sourcename
|
||||
%[-][<][<number>]p: the path part of the sourcename
|
||||
<number>: skip the first <number> directories of the path,
|
||||
defaults to 0.
|
||||
< : count the directories from the end or the path part.
|
||||
- : use, don't skip the counted directories.
|
||||
%n: the base of the sourcename (w/o suffix)
|
||||
%%: the character '%'.
|
||||
%x: the character x for every other character.
|
||||
|
||||
Example:
|
||||
|
||||
mkdepend -p .c:obj/%n.o
|
||||
|
||||
For every sourcefile <name>.c, an entry for obj/<name>.o is
|
||||
created.
|
||||
|
||||
mkdepend -p .c:obj/%1p%n.o 'source/*.c'
|
||||
|
||||
For every sourcefile source/<name>.c, an entry for obj/<name>.o is
|
||||
created.
|
||||
|
||||
------
|
||||
|
||||
-f <makefile>
|
||||
--file <makefile>
|
||||
|
||||
Specify the makefile to modify. If none is specified and the --dep
|
||||
option is missing as well, MkDepend searches in order for "Makefile",
|
||||
"makefile", "Makefile.mk", "makefile.mk" and "GNUMakefile". If none
|
||||
of these exist, 'Makefile' is used and thus created.
|
||||
|
||||
------
|
||||
|
||||
-d <depfile>
|
||||
--dep <depfile>
|
||||
|
||||
Specify the depfile to write the dependencies into.
|
||||
The output hereinto notes just the plain dependencies between the
|
||||
skeleton and the included files, i.e. ignores any --objpat or --objpat
|
||||
setting. However, symbolic include paths are used here as well.
|
||||
MkDepend prints both the 'a is included by b' as well as the
|
||||
'b includes a' relationships. The former are tagged with '<-' in
|
||||
the output, the latter with '->'.
|
||||
|
||||
If --flat is not specified, the dependencies are written in tree
|
||||
form with indentation representating the nesting.
|
||||
If --flat is specified, a flat list like that in Makefiles will
|
||||
be written.
|
||||
|
||||
------
|
||||
|
||||
-l
|
||||
--flat
|
||||
|
||||
Print the plain dependency file (see option --dep) as flat list instead
|
||||
of tree form.
|
||||
|
||||
------
|
||||
|
||||
-m|--ignore-missing
|
||||
|
||||
If an include file is not found, it is NOT added to the dependencies.
|
||||
However, MkDepend will still print diagnostic.
|
||||
|
||||
------
|
||||
|
||||
-w|--no-warn-exit
|
||||
|
||||
If MkDepend generates a warning, it does not return a non-zero exit
|
||||
code to the caller (useful for use within makefiles).
|
||||
|
||||
------
|
||||
|
||||
-v
|
||||
--verbose
|
||||
|
||||
Print some output during operation, namely the program name and the
|
||||
file currently under examination.
|
||||
------
|
||||
|
||||
-h
|
||||
--help
|
||||
--longhelp
|
||||
|
||||
Print a (short) summary of the commandline arguments and exit the
|
||||
program.
|
||||
|
||||
------
|
||||
|
||||
-V
|
||||
--version
|
||||
|
||||
Print the program version and exit.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
Copy the executable "mkdepend" into a suitable directory, profitably
|
||||
into one in your search path. The PPC executable is in the subdirectory
|
||||
obj.ppc/, the x86 executable in the subdirectory obj.x86/.
|
||||
|
||||
|
||||
Using MkDepend
|
||||
--------------
|
||||
The straightforward use of MkDepend is of course the call from the
|
||||
commandline a la 'mkdepend *.c', give or take a few command options. This
|
||||
would scan all C source files, compute the dependencies and update the
|
||||
Makefile in the same directory with these dependencies. Easy to use and
|
||||
as easy to forget to do after an important change (trust me, it happens!).
|
||||
Also, modifying the Makefile may not be what you want; after all, it adds
|
||||
quite a bunch of junk to the file which is of no direct interest to you.
|
||||
|
||||
Let's solve the second problem first: the solution is to instruct MkDepend
|
||||
to write all dependencies into an auxiliary file '.dependencies', which is
|
||||
done with the '-f' command option. The command now looks like this:
|
||||
'mkdepend -f .dependencies *.c'. To make use of this new file, the following
|
||||
statement must be added to the Makefile on a separate line:
|
||||
'-include .dependencies'. When make processes this line, it will read the
|
||||
contents of .dependencies and treat them as if they were written in the
|
||||
Makefile. The '-' in the command tells make to ignore the whole statement
|
||||
should .dependencies not exist.
|
||||
|
||||
The solution to the first problem (calling MkDepend automatically whenever
|
||||
a file changes) is to put the MkDepend call into the Makefile, too.
|
||||
Fortunately for us, Be's standard make allows a Makefile to change itself
|
||||
or any included file: if such a change is detected, make will simply
|
||||
re-read the affected files. Putting MkDepend into a Makefile requires the
|
||||
following changes/additions to be done (modified according to your special
|
||||
needs where necessary):
|
||||
|
||||
- the main build rule for $(TARGET) must be changed to include .dependencies
|
||||
as one of the requisites:
|
||||
|
||||
$(TARGET) : .dependencies $(OBJS) ...
|
||||
|
||||
- since MkDepend is not part of the BeOS distribution, the Makefile must
|
||||
be able to use the normal compiler as a standin for MkDepend. The variable
|
||||
DEP_FLAGS is set to the appropriate value to do so:
|
||||
|
||||
ifeq ($(CC), gcc)
|
||||
DEP_FLAGS = -M
|
||||
endif
|
||||
|
||||
ifeq ($(CC), mwcc$(CPU))
|
||||
DEP_FLAGS = -make
|
||||
endif
|
||||
|
||||
- the rule to generate the .dependencies file:
|
||||
|
||||
.dependencies: $(SRCS)
|
||||
$(SHELL) -ec '\
|
||||
if [ -n "`type -t mkdepend`" ]; then \
|
||||
mkdepend $(SRCS) $(INCLUDES) -p '\''.c:obj.$$(CPU)/%n.o'\'' -f$@; \
|
||||
else \
|
||||
$(CC) $(DEP_FLAGS) $(INCLUDES) $(SRCS) \
|
||||
| tr '\''\011'\'' '\''\040'\'' \
|
||||
| sed '\''s;^\([^ :][^ :]*\);$$(OBJ)/\1;g'\'' > $@; \
|
||||
fi'
|
||||
|
||||
- gmake automatically makes '.dependencies' when it is missing; however,
|
||||
if our intent is to 'clean' all auxiliary files, this behaviour is
|
||||
rather annoying. The solution is to include the .dependencies into
|
||||
the Makefile only when no cleaning action is requested:
|
||||
|
||||
ifneq (,$(filter clean clobber cleanall clobberall, $MAKECMDGOALS))
|
||||
-include .dependencies
|
||||
endif
|
||||
|
||||
- a rule to point out missing header files (this allows a smoother make
|
||||
process in case of outdated .dependencies):
|
||||
|
||||
%.h :
|
||||
@echo "Warning: Can't find $@."
|
||||
|
||||
And that's all.
|
||||
|
||||
The same changes apply if you chose to let mkdepend modify the Makefile
|
||||
directly, just replace every occurence of '.dependencies' with 'Makefile'
|
||||
(and of course do not '-include Makefile' in your Makefile).
|
||||
|
||||
For a real-life example take a look at MkDepend's own Makefile.
|
||||
|
||||
|
||||
Program Information
|
||||
-------------------
|
||||
MkDepend consists of these source files:
|
||||
|
||||
main.c,.h : Program control, data generation routines.
|
||||
args.c,.h : Argument parsing.
|
||||
getargs.c,.h : Generic commandline parser.
|
||||
reader.c,.h : Reading of source files and scanning for #include statements.
|
||||
Copying and writing of makefiles.
|
||||
nodes.c,.h : Management of the names and locations of the files analysed.
|
||||
It is implemented as a binary search tree with an additional
|
||||
linked list.
|
||||
util.c,.h : Some helpful functions - ok, right now just one function.
|
||||
version.h : The version number, automatically updated by PRCS.
|
||||
|
||||
Filename expansion is provided by the static library libglob, which comes
|
||||
under the GNU Library Public License in the subdirectory libglob/.
|
||||
|
||||
The provided Makefile takes care of all the necessary steps to compile and
|
||||
link both MkDepend and the libglob. See the head comment of the Makefile
|
||||
for further information about available targets and cross-compilation.
|
||||
|
||||
MkDepend was developed with Metrowerks C, Gnu C and GNU make; PRCS provides
|
||||
the source code version management.
|
||||
|
||||
|
||||
Bugs/TODO
|
||||
---------
|
||||
Maybe allow the modification of several makefiles with one call.
|
||||
Maybe omit from the depends list those files that could not be found.
|
||||
The Makefile should be more generic.
|
||||
|
||||
|
||||
History
|
||||
-------
|
||||
v 1.6 (01-Mar-2000)
|
||||
Added the possibility to select certain files for dependency generation.
|
||||
|
||||
v 1.5 (03-Feb-1999)
|
||||
Added the search for include files in the directory of the including
|
||||
file; older versions of MkDepend searched in the directory from where
|
||||
MkDepend was started.
|
||||
|
||||
v 1.4.5 (25-Oct-1998)
|
||||
R4 support (PPC and x86).
|
||||
The version number is now handled by PRCS.
|
||||
New command options '--longhelp' and '--version'.
|
||||
Default file suffixes now also cover a whole range of
|
||||
C++ suffixes (.cc, .cpp, .cxx, .cc).
|
||||
Systemincludes (<>-includes) are now handled; with the help of
|
||||
the new command option -i-.
|
||||
Filenames with embedded spaces are quoted when written to a Makefile.
|
||||
|
||||
v 1.4 (04-Jul-1998) :
|
||||
Moved to BeOS, Amiga support dropped.
|
||||
New option -?|-h|--help for online help.
|
||||
|
||||
v 1.3 (02-Mar-1996) :
|
||||
For source/object relations, the source is no longer included in
|
||||
dependency list, except when demanded by '+'-command option.
|
||||
|
||||
v 1.2 (25-Feb-1996) :
|
||||
New option -D=DEP/K for separate file with then plain source
|
||||
dependencies.
|
||||
New option -L=FLAT/S to write the plain dependencies as flat
|
||||
list instead of a tree.
|
||||
|
||||
v 1.1 (13-Oct-1995) :
|
||||
The dependencies may now be placed in midst of a makefile.
|
||||
Object file name pattern %p expanded to %[-][<][<number>]p .
|
||||
|
||||
v 1.0 (18-Sep-1995) :
|
||||
Initial release, at that time for Amiga OS.
|
||||
|
||||
|
||||
Authors
|
||||
-------
|
||||
Lars Düning, 10 Morningside Gardens, Edinburgh, EH10 5LA, United Kingdom
|
||||
EMail: lars@bearnip.com, or duening@ibr.cs.tu-bs.de (deprecated)
|
||||
|
||||
The file reader was inspired by the input module of lcc by David Hanson
|
||||
and Christopher Fraser.
|
||||
|
||||
The elaborate %p pattern follows a suggestion by Michael A. Wiedmer
|
||||
(<maw@paralax.demon.co.uk>).
|
||||
|
||||
The initial support for R4/x86 and a nice generic Makefile was provided
|
||||
by Stephen van Egmond (<svanegmond@home.com>).
|
||||
|
||||
Dianne Kyra Hackborn (<hackbod@angryredplanet.com>) and
|
||||
Stephen van Egmond provided valuable input.
|
||||
|
||||
|
||||
Legalese
|
||||
--------
|
||||
The following license is replicated in the file LICENSE. It applies to
|
||||
all files and derivates thereof which are part of the MkDepend package,
|
||||
except for those files which explicitely state otherwise.
|
||||
|
||||
|
||||
Copyright (c) 1995-1999, Lars Düning.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- 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.
|
||||
|
||||
- Modifications of the original software, of parts or of the whole,
|
||||
must be clearly recognizable as such.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
21
src/bin/mkdepend/MkDepend.txt
Normal file
21
src/bin/mkdepend/MkDepend.txt
Normal file
@ -0,0 +1,21 @@
|
||||
========================================================================
|
||||
File: mkdepend-17.zip
|
||||
Author: Lars Duening (lars@bearnip.com)
|
||||
Release: 1.7 (14. Oct 2001)
|
||||
Compatibility: R5
|
||||
Location: contrib/development
|
||||
Description: Dependencygenerator for Makefiles
|
||||
Notes:
|
||||
|
||||
MkDepend scans C-source files recursively for includes and
|
||||
writes the found dependency trees into an existing makefile.
|
||||
Special features of MkDepend are:
|
||||
- generates the complete transitive closure of all included files;
|
||||
- searches the included files in several definable paths, and allows
|
||||
to represent these pathnames by symbols in the generated Makefile;
|
||||
- the source/object filename relationships may be flexibly defined;
|
||||
- quite fast file scanner :-).
|
||||
|
||||
The archive comes with full source and precompiled executables for
|
||||
both x86 and (cross-compiled) PPC.
|
||||
========================================================================
|
670
src/bin/mkdepend/args.c
Normal file
670
src/bin/mkdepend/args.c
Normal file
@ -0,0 +1,670 @@
|
||||
/* $Id: args.c 1.9 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
** Arguments parsing and variables.
|
||||
**
|
||||
** Copyright (c) 1996-2001 by Lars Düning. All Rights Reserved.
|
||||
** This file is free software. For terms of use see the file LICENSE.
|
||||
**---------------------------------------------------------------------------
|
||||
** Parsed arguments:
|
||||
**
|
||||
** {-i|--include <includepath>[::<symbol>]}
|
||||
** [-i-]
|
||||
** {-x|--except <filepattern>}
|
||||
** {-S|--select <filepattern>}
|
||||
** {-s|--suffix <src_ext>{,<src_ext>}[+][:<obj_ext>] | [+]:<obj_ext>}
|
||||
** {-p|--objpat <src_ext>{,<src_ext>}[+]:<obj_pattern>
|
||||
** [-f|--file <makefile>]
|
||||
** [-d|--dep <depfile>]
|
||||
** [-l|--flat]
|
||||
** [-m|--ignore-missing]
|
||||
** [-w|--no-warn-exit]
|
||||
** [-v|--verbose]
|
||||
** [-h|-?|--help|--longhelp]
|
||||
** [-V|--version]
|
||||
** {<filename>}
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "args.h"
|
||||
#include "getargs.h"
|
||||
#include "main.h"
|
||||
#include "glob.h"
|
||||
#include "version.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* Program arguments */
|
||||
|
||||
short bVerbose = FALSE; /* TRUE: Verbose action */
|
||||
SArray aFiles = { 0, 0, NULL }; /* Source files */
|
||||
SArray aAvoid = { 0, 0, NULL }; /* Source files to avoid */
|
||||
SArray aSelect = { 0, 0, NULL }; /* Selected include files to print */
|
||||
Include * aIncl = NULL; /* Include directories */
|
||||
int iInclSize = 0; /* Number of valid entries in aIncl */
|
||||
static int allocIncl = 0; /* Allcoated size of pIncl */
|
||||
short bSplitPath = FALSE; /* TRUE: distinguish between normal
|
||||
* and system include path. */
|
||||
SArray aSrcExt = { 0, 0, NULL }; /* Source file extensions */
|
||||
static int allocGiveSrc = 0, sizeGiveSrc = 0;
|
||||
/* Allocated/used size of *bGiveSrc */
|
||||
short * bGiveSrc = NULL; /* For each entry in aSrcExt:
|
||||
* TRUE if the source name shall appear
|
||||
* in the dependency list, too. */
|
||||
SArray aObjExt = { 0, 0, NULL }; /* Associated object file extensions */
|
||||
SArray aObjPat = { 0, 0, NULL }; /* Associated object file patterns */
|
||||
char * sObjExt = NULL; /* Default object file extension */
|
||||
short bDefGSrc = FALSE; /* For sObjExt: TRUE if the source
|
||||
* name shall appear in the depency
|
||||
* list, too */
|
||||
char * sMake = NULL; /* Name of the Makefile */
|
||||
char * sDepfile = NULL; /* Name of the dependency file */
|
||||
short bFlat = FALSE; /* TRUE: Depfile in flat format */
|
||||
short bNoWarnExit = FALSE; /* TRUE: Don't return RETURN_WARN
|
||||
* from program */
|
||||
short bIgnoreMiss = FALSE; /* TRUE: Ignore missing includes */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* Every recognized option has a ordinal number */
|
||||
|
||||
typedef enum OptNumber {
|
||||
cUnknown = OPTION_UNKNOWN /* unknown option */
|
||||
, cArgument = OPTION_ARGUMENT /* normal argument (for us: filename) */
|
||||
, cInclude /* --include */
|
||||
, cExcept /* --except */
|
||||
, cSelect /* --select */
|
||||
, cSuffix /* --suffix */
|
||||
, cObjPat /* --objpat */
|
||||
, cFile /* --file */
|
||||
, cDep /* --dep */
|
||||
, cFlat /* --flat */
|
||||
, cNoWarn // --no-warn-exit
|
||||
, cIgnMiss // --ignore-missing
|
||||
, cHelp /* --help */
|
||||
, cLongHelp /* --longhelp */
|
||||
, cVerbose /* --verbose */
|
||||
, cVersion /* --version */
|
||||
} OptNumber;
|
||||
|
||||
/* Comprehensive lists of recognized options */
|
||||
|
||||
static OptionDesc aOptions[]
|
||||
= { { 'i', "include", cInclude, TRUE }
|
||||
, { 'I', NULL, cInclude, TRUE }
|
||||
, { 'x', "except", cExcept, TRUE }
|
||||
, { 'S', "select", cSelect, TRUE }
|
||||
, { 's', "suffix", cSuffix, TRUE }
|
||||
, { 'p', "objpat", cObjPat, TRUE }
|
||||
, { 'f', "file", cFile, TRUE }
|
||||
, { 'd', "dep", cDep, TRUE }
|
||||
, { 'l', "flat", cFlat, FALSE }
|
||||
, { 'm', "ignore-missing", cIgnMiss, FALSE }
|
||||
, { 'w', "no-warn-exit", cNoWarn, FALSE }
|
||||
, { 'h', "help", cHelp, FALSE }
|
||||
, { '?', NULL, cHelp, FALSE }
|
||||
, { '\0', "longhelp", cLongHelp, FALSE }
|
||||
, { 'v', "verbose", cVerbose, FALSE }
|
||||
, { 'V', "version", cVersion, FALSE }
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
version (void)
|
||||
|
||||
/* Print the version of the program. */
|
||||
|
||||
{
|
||||
fputs("MkDepend " VERSION " - Makefile Dependency Generator\n"
|
||||
"\nReleased: " RELEASE_DATE
|
||||
"\nCompiled: " __DATE__
|
||||
#ifdef __TIME__
|
||||
" " __TIME__
|
||||
#endif
|
||||
"\n", stdout);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
shortusage (void)
|
||||
|
||||
/* Print the short help information to stdout. */
|
||||
|
||||
{
|
||||
version();
|
||||
printf("\nUsage: %s [options] <filename>...\n", aPgmName);
|
||||
fputs(
|
||||
"\nOptions are:\n"
|
||||
"\n"
|
||||
" -i|--include <includepath>[::<symbol>]\n"
|
||||
" -x|--except <filepattern>\n"
|
||||
" -S|--select <filepattern>\n"
|
||||
" -s|--suffix <src_ext>{,<src_ext>}[+][:<obj_ext>]\n"
|
||||
" -s|--suffix [+]:<obj_ext>\n"
|
||||
" -p|--objpat <src_ext>{,<src_ext>}[+]:<obj_pattern>\n"
|
||||
" -f|--file <makefile>\n"
|
||||
" -d|--dep <depfile>\n"
|
||||
" -l|--flat\n"
|
||||
" -m|--ignore-missing\n"
|
||||
" -w|--no-warn-exit\n"
|
||||
" -v|--verbose\n"
|
||||
" -h|-?|--help|--longhelp\n"
|
||||
" -V|--version\n"
|
||||
, stdout);
|
||||
|
||||
} /* shortusage() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void
|
||||
usage (void)
|
||||
|
||||
/* Print the help information to stdout. */
|
||||
|
||||
{
|
||||
version();
|
||||
printf("\nUsage: %s [options] <filename>...\n", aPgmName);
|
||||
fputs(
|
||||
"\nOptions are:\n"
|
||||
"\n"
|
||||
" -i|--include <includepath>[::<symbol>]\n"
|
||||
" Add <includepath> to the list of searched directories. If given,\n"
|
||||
" <symbol> is used in the generated dependencies to denote\n"
|
||||
" the <includepath>.\n"
|
||||
" The special notation '-i-' is used to split the search path into\n"
|
||||
" a non-system and a common part.\n"
|
||||
"\n"
|
||||
" -x|--except <filepattern>\n"
|
||||
" Except all matching files from the root set.\n"
|
||||
"\n"
|
||||
" -S|--select <filepattern>\n"
|
||||
" Only the dependencies for files including <filepattern> are printed,\n"
|
||||
" and in those only the included files matching <filepattern> are listed.\n"
|
||||
" Except all matching files from the root set.\n"
|
||||
"\n"
|
||||
" -s|--suffix <src_ext>{,<src_ext>}[+][:<obj_ext>]\n"
|
||||
" Set the recognized source file suffixes (and optionally associated\n"
|
||||
" object file suffixes).\n"
|
||||
"\n"
|
||||
" -s|--suffix [+]:<obj_ext>\n"
|
||||
" Set the default object file suffix.\n"
|
||||
"\n"
|
||||
" -p|--objpat <src_ext>{,<src_ext>}[+]:<obj_pattern>\n"
|
||||
" Define a complex source/object file name relation.\n"
|
||||
" The <objpattern> recognizes as meta-symbols:\n"
|
||||
" %s: the full sourcename (w/o suffix)\n"
|
||||
" %[-][<][<number>]p: the path part of the sourcename\n"
|
||||
" <number>: skip first <number> directories of the path,\n"
|
||||
" defaults to 0.\n"
|
||||
" < : directories are counted from the end.\n"
|
||||
" - : use, don't skip the counted directories.\n"
|
||||
" %n: the base of the sourcename (w/o suffix)\n"
|
||||
" %%: the character %\n"
|
||||
" %x: the character 'x' for every other character.\n"
|
||||
"\n"
|
||||
" -f|--file <makefile>\n"
|
||||
" Update <makefile> with the found dependencies (default is 'Makefile').\n"
|
||||
"\n"
|
||||
" -d|--dep <depfile>\n"
|
||||
" Write the found dependencies into <depfile>.\n"
|
||||
"\n"
|
||||
" -l|--flat\n"
|
||||
" When generating a <depfile> write the dependencies in flat form.\n"
|
||||
"\n"
|
||||
" -m|--ignore-missing\n"
|
||||
" If an include file is not found, it is NOT added to the dependencies.\n"
|
||||
"\n"
|
||||
" -w|--no-warn-exit\n"
|
||||
" If MkDepend generates a warning, it does not return a non-zero exit\n"
|
||||
" code to the caller (useful for use within makefiles).\n"
|
||||
"\n"
|
||||
" -v|--verbose\n"
|
||||
" Verbose operation.\n"
|
||||
"\n"
|
||||
" -V|--version\n"
|
||||
" Display the version of the program and exit.\n"
|
||||
"\n"
|
||||
" --longhelp\n"
|
||||
" Display this help and exit.\n"
|
||||
"\n"
|
||||
" -h|-?|--help\n"
|
||||
" Display the short help text and exit.\n"
|
||||
"\n"
|
||||
, stdout);
|
||||
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int
|
||||
givesrc_addflag (short bFlag)
|
||||
|
||||
/* Add <bFlag> to *bGiveSrc.
|
||||
* Return 0 on success, non-0 on error.
|
||||
*/
|
||||
|
||||
{
|
||||
short * pFlags;
|
||||
assert(sizeGiveSrc <= allocGiveSrc);
|
||||
if (sizeGiveSrc+1 > allocGiveSrc)
|
||||
{
|
||||
pFlags = (short*)realloc(bGiveSrc, sizeof(short)*(allocGiveSrc+4));
|
||||
if (!pFlags)
|
||||
return 1;
|
||||
bGiveSrc = pFlags;
|
||||
allocGiveSrc += 4;
|
||||
}
|
||||
bGiveSrc[sizeGiveSrc] = bFlag;
|
||||
sizeGiveSrc++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int
|
||||
include_addinfo (char * pPath, char * pSymbol, int bSystem)
|
||||
|
||||
/* Add the given data to to *bIncl.
|
||||
* Return 0 on success, non-0 on error.
|
||||
*/
|
||||
|
||||
{
|
||||
Include * pNew;
|
||||
|
||||
assert(iInclSize <= allocIncl);
|
||||
if (iInclSize+1 > allocIncl)
|
||||
{
|
||||
pNew = realloc(aIncl, sizeof(Include)*(allocIncl+4));
|
||||
if (!pNew)
|
||||
return 1;
|
||||
aIncl = pNew;
|
||||
allocIncl += 4;
|
||||
}
|
||||
aIncl[iInclSize].pPath = pPath;
|
||||
aIncl[iInclSize].pSymbol = pSymbol;
|
||||
aIncl[iInclSize].bSysPath = bSystem;
|
||||
iInclSize++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
array_addfile (SArray *pArray, const char * pName)
|
||||
|
||||
/* Add a copy of <*pName> to the string array <pArray>.
|
||||
* Return 0 on success, non-0 on error.
|
||||
* If pName is NULL, the array is simply extended by a NULL pointer.
|
||||
*/
|
||||
|
||||
{
|
||||
char ** pStrs;
|
||||
assert(pArray->size <= pArray->alloc);
|
||||
if (pArray->size+1 > pArray->alloc)
|
||||
{
|
||||
pStrs = (char **)realloc(pArray->strs, sizeof(char *)*(pArray->alloc+4));
|
||||
if (!pStrs)
|
||||
return 1;
|
||||
pArray->strs = pStrs;
|
||||
pArray->alloc += 4;
|
||||
}
|
||||
else
|
||||
pStrs = pArray->strs;
|
||||
if (pName)
|
||||
{
|
||||
pStrs[pArray->size] = strdup(pName);
|
||||
if (!pStrs[pArray->size])
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
pStrs[pArray->size] = NULL;
|
||||
pArray->size++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
array_addlist (SArray *pArray, int count, const char ** pList)
|
||||
|
||||
/* Add the <count> strings from <pList> to string array <pArray>.
|
||||
* pList and contained strings may be freed after return.
|
||||
* Return 0 on success, non-0 else.
|
||||
*/
|
||||
|
||||
{
|
||||
char ** pStrs;
|
||||
int i;
|
||||
|
||||
assert(pList);
|
||||
if (!count)
|
||||
return 0;
|
||||
assert(pArray->size <= pArray->alloc);
|
||||
if (pArray->size+count > pArray->alloc)
|
||||
{
|
||||
pStrs = (char **)realloc(pArray->strs, sizeof(char *)*(pArray->alloc+count));
|
||||
if (!pStrs)
|
||||
return 1;
|
||||
pArray->strs = pStrs;
|
||||
pArray->alloc += count;
|
||||
}
|
||||
else
|
||||
pStrs = pArray->strs;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
char * pString;
|
||||
|
||||
pString = strdup(pList[i]);
|
||||
if (!pString)
|
||||
return 1;
|
||||
pStrs[pArray->size++] = pString;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
add_expfile (SArray *pArray, const char * pName)
|
||||
|
||||
/* Glob filename <*pName> and add the filenames to string array <pArray>.
|
||||
* Return 0 on success, non-0 else.
|
||||
*/
|
||||
|
||||
{
|
||||
glob_t aGlob;
|
||||
int rc;
|
||||
|
||||
memset(&aGlob, 0, sizeof(aGlob));
|
||||
|
||||
switch (glob(pName, GLOB_NOSORT|GLOB_BRACE|GLOB_TILDE, NULL, &aGlob))
|
||||
{
|
||||
case GLOB_NOSPACE:
|
||||
globfree(&aGlob);
|
||||
exit_nomem(" (add_expfile: glob)");
|
||||
break;
|
||||
|
||||
case GLOB_ABORTED:
|
||||
printf("%s: Error expanding %s\n", aPgmName, pName);
|
||||
globfree(&aGlob);
|
||||
set_rc(RETURN_ERROR, TRUE);
|
||||
break;
|
||||
|
||||
case GLOB_NOMATCH:
|
||||
globfree(&aGlob);
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
/* No error */
|
||||
break;
|
||||
|
||||
default:
|
||||
globfree(&aGlob);
|
||||
exit_doserr(RETURN_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(aGlob.gl_pathc > 0);
|
||||
|
||||
rc = 0;
|
||||
if (aGlob.gl_pathc > 0)
|
||||
rc = array_addlist(pArray, aGlob.gl_pathc, (const char **)aGlob.gl_pathv);
|
||||
|
||||
globfree(&aGlob);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int
|
||||
handler (int eOption, const char * pValue)
|
||||
|
||||
/* Callback function for getargs(). It is called when option <eOption>
|
||||
* was recognized, possibly also passing an associated value in <pValue>.
|
||||
* Return 0 on success, non-zero else.
|
||||
*/
|
||||
|
||||
{
|
||||
int i; /* All purpose */
|
||||
|
||||
switch (eOption)
|
||||
{
|
||||
case cArgument:
|
||||
i = array_addfile(&aFiles, pValue);
|
||||
if (i)
|
||||
exit_nomem(" (args: add file)");
|
||||
break;
|
||||
|
||||
case cInclude:
|
||||
{
|
||||
char * pSym, * pMark;
|
||||
char * pVal;
|
||||
|
||||
/* Special case: check for the '-' marker */
|
||||
if (!strcmp(pValue, "-"))
|
||||
{
|
||||
bSplitPath = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Since we're going to hack into pValue, possibly extending it
|
||||
* by one character, we better make a copy of it. We need it
|
||||
* anyway to store the data in aIncl[].
|
||||
*/
|
||||
pVal = malloc(strlen(pValue)+2);
|
||||
if (!pVal)
|
||||
exit_nomem(" (args: dup include arg)");
|
||||
strcpy(pVal, pValue);
|
||||
|
||||
/* Allow for <path>::<symbol> notation */
|
||||
pSym = NULL;
|
||||
pMark = pVal+strlen(pVal);
|
||||
if (pMark != pVal)
|
||||
{
|
||||
pMark--;
|
||||
while (!pSym && pMark >= pVal+1)
|
||||
{
|
||||
if (':' != *pMark)
|
||||
{
|
||||
pMark--;
|
||||
continue;
|
||||
}
|
||||
if (':' != *(pMark-1))
|
||||
{
|
||||
pMark -= 2;
|
||||
continue;
|
||||
}
|
||||
pSym = pMark+1;
|
||||
*(pMark-1) = '\0';
|
||||
}
|
||||
}
|
||||
if (pSym && !strlen(pSym))
|
||||
pSym = NULL;
|
||||
else if (pSym)
|
||||
{
|
||||
pSym = strdup(pSym);
|
||||
if (!pSym)
|
||||
exit_nomem(" (args: dup include sym)");
|
||||
}
|
||||
|
||||
/* Make sure <path> ends in a ':' or '/' */
|
||||
pMark = pVal+strlen(pVal);
|
||||
if (pMark > pVal && ':' != *(pMark-1) && '/' != *(pMark-1))
|
||||
{
|
||||
*pMark = '/';
|
||||
*(pMark+1) = '\0';
|
||||
}
|
||||
i = include_addinfo(pVal, pSym, bSplitPath);
|
||||
if (i)
|
||||
exit_nomem(" (args: add include info)");
|
||||
}
|
||||
break;
|
||||
|
||||
case cExcept:
|
||||
i = add_expfile(&aAvoid, pValue);
|
||||
if (i)
|
||||
exit_nomem(" (args: add except)");
|
||||
break;
|
||||
|
||||
case cSelect:
|
||||
i = add_expfile(&aSelect, pValue);
|
||||
if (i)
|
||||
exit_nomem(" (args: add select)");
|
||||
break;
|
||||
|
||||
case cSuffix:
|
||||
case cObjPat:
|
||||
{
|
||||
char * pMark, *pOsfix;
|
||||
short bGotPlus;
|
||||
|
||||
/* Allow for <src_suffix>[+]:<obj_suffix> notation */
|
||||
bGotPlus = FALSE;
|
||||
pOsfix = NULL;
|
||||
pMark = (char *)pValue+strlen(pValue);
|
||||
if (pMark != pValue)
|
||||
{
|
||||
pMark--;
|
||||
while (!pOsfix && pMark >= pValue)
|
||||
{
|
||||
if (':' != *pMark)
|
||||
{
|
||||
pMark--;
|
||||
continue;
|
||||
}
|
||||
pOsfix = pMark+1;
|
||||
if (pMark != pValue && *(pMark-1) == '+')
|
||||
{
|
||||
bGotPlus = TRUE;
|
||||
pMark--;
|
||||
}
|
||||
*pMark = '\0';
|
||||
}
|
||||
}
|
||||
if (pOsfix && !strlen(pOsfix))
|
||||
pOsfix = NULL;
|
||||
|
||||
/* --objpat needs the [+]:<obj_pattern> part! */
|
||||
if (cObjPat == eOption && !pOsfix)
|
||||
{
|
||||
printf("%s: <obj_pattern> not specified.\n", aPgmName);
|
||||
set_rc(RETURN_ERROR, TRUE);
|
||||
}
|
||||
|
||||
/* [+]:<obj_suffix> alone defines default object suffix */
|
||||
if (pOsfix && !strlen(pValue))
|
||||
{
|
||||
if (sObjExt)
|
||||
free(sObjExt);
|
||||
sObjExt = strdup(pOsfix);
|
||||
if (!sObjExt)
|
||||
exit_nomem(" (args: dup obj suffix)");
|
||||
bDefGSrc = bGotPlus;
|
||||
}
|
||||
else
|
||||
{
|
||||
char * pSfix;
|
||||
|
||||
/* Allow for <sfix1>,<sfix2>,...,<sfixn> for source suffixes */
|
||||
for ( pSfix = (char *)pValue
|
||||
; NULL != (pMark = strchr(pSfix, ','))
|
||||
; pSfix = pMark+1
|
||||
)
|
||||
{
|
||||
*pMark = '\0';
|
||||
if (strlen(pSfix))
|
||||
{
|
||||
if ( array_addfile(&aSrcExt, pSfix)
|
||||
|| givesrc_addflag(bGotPlus)
|
||||
|| (cSuffix == eOption ? array_addfile(&aObjExt, pOsfix)
|
||||
: array_addfile(&aObjPat, pOsfix)
|
||||
)
|
||||
)
|
||||
exit_nomem(" (args: add obj suffix)");
|
||||
}
|
||||
}
|
||||
if (strlen(pSfix))
|
||||
{
|
||||
if ( array_addfile(&aSrcExt, pSfix)
|
||||
|| givesrc_addflag(bGotPlus)
|
||||
|| (cSuffix == eOption ? array_addfile(&aObjExt, pOsfix)
|
||||
: array_addfile(&aObjPat, pOsfix)
|
||||
)
|
||||
)
|
||||
exit_nomem(" (args: add last obj suffix)");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case cFile:
|
||||
if (sMake)
|
||||
free(sMake);
|
||||
sMake = strdup(pValue);
|
||||
if (!sMake)
|
||||
exit_nomem(" (args: dup make)");
|
||||
break;
|
||||
|
||||
case cDep:
|
||||
if (sDepfile)
|
||||
free(sDepfile);
|
||||
sDepfile = strdup(pValue);
|
||||
if (!sDepfile)
|
||||
exit_nomem(" (args: dup dep)");
|
||||
break;
|
||||
|
||||
case cFlat:
|
||||
bFlat = TRUE;
|
||||
break;
|
||||
|
||||
case cIgnMiss:
|
||||
bIgnoreMiss = TRUE;
|
||||
break;
|
||||
|
||||
case cNoWarn:
|
||||
bNoWarnExit = TRUE;
|
||||
break;
|
||||
|
||||
case cVerbose:
|
||||
bVerbose = TRUE;
|
||||
break;
|
||||
|
||||
case cHelp:
|
||||
shortusage();
|
||||
set_rc(RETURN_WARN, TRUE);
|
||||
break;
|
||||
|
||||
case cLongHelp:
|
||||
usage();
|
||||
set_rc(RETURN_WARN, TRUE);
|
||||
break;
|
||||
|
||||
case cVersion:
|
||||
version();
|
||||
set_rc(RETURN_WARN, TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* This shouldn't happen. */
|
||||
printf("%s: (getargs) Internal error, eOption is %d\n", aPgmName, eOption);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
parseargs (int argc, char ** argv)
|
||||
|
||||
/* Get the arguments from the commandline and fill in the exported variables.
|
||||
* In case of an error, the program is terminated.
|
||||
*/
|
||||
|
||||
{
|
||||
if (getargs(argc, argv, aOptions, handler))
|
||||
set_rc(RETURN_ERROR, TRUE);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
61
src/bin/mkdepend/args.h
Normal file
61
src/bin/mkdepend/args.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* $Id: args.h 1.6 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Copyright (c) 1999-2001 by Lars Düning. All Rights Reserved.
|
||||
* This file is free software. For terms of use see the file LICENSE.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __ARGS_H__
|
||||
#define __ARGS_H__ 1
|
||||
|
||||
/* Dynamic string array */
|
||||
|
||||
typedef struct _sarray
|
||||
{
|
||||
int size; /* Number of used strings */
|
||||
int alloc; /* Number of allocated string pointers */
|
||||
char ** strs; /* Array of string pointers */
|
||||
} SArray;
|
||||
|
||||
/* Information about one include directory */
|
||||
|
||||
typedef struct _inclinfo {
|
||||
char * pPath; /* Pathname of the directory */
|
||||
char * pSymbol; /* Symbol to use in Makefiles, NULL if none */
|
||||
int bSysPath; /* TRUE for system directories */
|
||||
} Include;
|
||||
|
||||
/* Program arguments */
|
||||
|
||||
extern short bVerbose; /* TRUE: Verbose action */
|
||||
extern SArray aFiles; /* Source files */
|
||||
extern SArray aAvoid; /* Source files to avoid */
|
||||
extern SArray aSelect; /* Selected include files to print */
|
||||
extern Include * aIncl; /* Include directory information */
|
||||
extern int iInclSize; /* Number of valid entries in aIncl */
|
||||
extern short bSplitPath; /* Include path handling */
|
||||
extern SArray aSrcExt; /* Source file extensions */
|
||||
extern SArray aObjExt; /* Associated object file extensions */
|
||||
extern SArray aObjPat; /* Associated object file patterns */
|
||||
extern short * bGiveSrc; /* For each entry in aSrcExt: TRUE if the
|
||||
* source name shall appear in the
|
||||
* dependency list, too. */
|
||||
extern char * sObjExt; /* Default object file extension */
|
||||
extern short bDefGSrc; /* For sObjExt: TRUE if the source name
|
||||
* shall appear in the depency list, too
|
||||
*/
|
||||
extern char * sMake; /* Name of the Makefile */
|
||||
extern char * sDepfile; /* Name of the dependency file */
|
||||
extern short bFlat; /* TRUE: Depfile in flat format */
|
||||
extern short bNoWarnExit; /* TRUE: Don't return RETURN_WARN from program */
|
||||
extern short bIgnoreMiss; /* TRUE: Ignore missing includes */
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
extern void parseargs (int argc, char ** argv);
|
||||
extern int array_addlist (SArray *, int, const char **);
|
||||
extern int array_addfile (SArray *, const char *);
|
||||
extern int add_expfile (SArray *, const char *);
|
||||
|
||||
#endif
|
326
src/bin/mkdepend/getargs.c
Normal file
326
src/bin/mkdepend/getargs.c
Normal file
@ -0,0 +1,326 @@
|
||||
/* $Id: getargs.c 1.5 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Commandline argument parser.
|
||||
*
|
||||
* Copyright (c) 1998-2000 by Lars Düning. All Rights Reserved.
|
||||
* This file is free software. For terms of use see the file LICENSE.
|
||||
*---------------------------------------------------------------------------
|
||||
* This code parses the arguments passed to the program in the count <argc>
|
||||
* and the array of strings <argv>. The parser distinguishes options, which
|
||||
* start with a '-', from normal arguments; options are further distinguished
|
||||
* by their name and may take an additional value. The parser neither
|
||||
* imposes nor expects any order of options and arguments.
|
||||
*
|
||||
* Options are recognized in two forms. In the short form the option must
|
||||
* be given as a single '-' followed by a single letter. In the long form,
|
||||
* options start with '--' followed by a string of arbitrary length.
|
||||
* Short options are case sensitive, long options aren't.
|
||||
* Examples are: '-r' and '--recursive'.
|
||||
*
|
||||
* If an option takes a value, it must follow the option immediately after
|
||||
* a separating space or '='. Additionally, the value for a short option
|
||||
* may follow the option without separator. Examples are: '-fMakefile',
|
||||
* '-f Makefile', '--file=Makefile' and '--file Makefile'.
|
||||
*
|
||||
* Short options may be collated into one argument, e.g. '-rtl', but
|
||||
* of these only the last may take a value.
|
||||
*
|
||||
* The option '--' marks the end of options. All following command arguments
|
||||
* are considered proper arguments even if they start with a '-' or '--'.
|
||||
*-------------------------------------------------------------------------
|
||||
* Internally every option recognized by the program is associated with
|
||||
* an id number, assigned by the user. The parser itself uses the two
|
||||
* id numbers 'OPTION_UNKNOWN' for unrecognized options, and
|
||||
* 'OPTION_ARGUMENT' for proper command arguments.
|
||||
*
|
||||
* Id numbers are associated with their option strings/letters by the
|
||||
* the array aOptions, which is passed to the parser function. Every element
|
||||
* in this array is a structure defining the option's name (string
|
||||
* or letter), the associated id number, and whether or not the option
|
||||
* takes a value. An element can hold just one type of option (short or
|
||||
* long) by setting the description the other option to \0 resp. NULL.
|
||||
* The order of the elements does not matter. The end of the array is
|
||||
* marked with an element using OPTION_UNKNOWN as assigned id number.
|
||||
*
|
||||
* The parsing is done by calling the function
|
||||
*
|
||||
* int getargs( int argc, char ** argv
|
||||
* , const OptionDesc aOptions[]
|
||||
* , OptionHandler handler)
|
||||
*
|
||||
* The function is passed the argument count <argc> and vector <argv> as
|
||||
* they were received from the main() function, the option description
|
||||
* array <aOptions> and a callback function* <handler>. getargs()
|
||||
* returns 0 if the parsing completed successfully, and non-zero else.
|
||||
*
|
||||
* The handler function is called for every successfully recognized option
|
||||
* and argument. Its prototype is
|
||||
*
|
||||
* int handler(int iOption, const char *pValue)
|
||||
*
|
||||
* Parameter <iOption> denotes the recognized option, and pValue points
|
||||
* to the beginning of the value string if the option takes a value.
|
||||
* Proper arguments are parsed with eOption==OPTION_ARGUMENT and pValue
|
||||
* pointing to the argument string. The handler has to return 0 if the
|
||||
* option/argument was processed correctly, and non-zero else.
|
||||
*
|
||||
* Additionally, getargs() puts the basename of the program (as determined
|
||||
* by argv[0]) into the exported variable
|
||||
*
|
||||
* const char *aPgmName
|
||||
*
|
||||
* when called the first time.
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "getargs.h"
|
||||
|
||||
const char *aPgmName = NULL;
|
||||
/* The exported program name. */
|
||||
|
||||
#define MY_TRUE 1
|
||||
#define MY_FALSE 0
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
getargs ( int argc, char ** argv
|
||||
, OptionDesc aOptions[]
|
||||
, OptionHandler opt_eval
|
||||
)
|
||||
|
||||
/* Get the arguments from the commandline and pass them
|
||||
* as (number, optional value) to the <opt_eval> callback.
|
||||
* The options are defined by the array <aOptions>, with an OPTION_UNKNOWN
|
||||
* element marking the last entry.
|
||||
*
|
||||
* If opt_eval() returns non-zero, argument scanning is terminated.
|
||||
* In that case, or if getargs() detects an error itself, getargs() returns
|
||||
* non-zero.
|
||||
* A zero return means 'success' in both cases.
|
||||
*
|
||||
* Additionally, on the first call getargs() sets aPgmName to the basename
|
||||
* of the program as derived from argv[0].
|
||||
*/
|
||||
|
||||
{
|
||||
int i; /* all purpose */
|
||||
int nOptions; /* Number of options */
|
||||
int iArg; /* Number of argument under inspection */
|
||||
int eOption; /* The current recognized option */
|
||||
int xOption; /* The index of the recog otion in aOptions */
|
||||
short bCont; /* True: find another option in the same argument */
|
||||
short bDone; /* True: all options parsed, only args left */
|
||||
short bShort; /* True: current argument is a short option */
|
||||
char * pArg; /* Next argument character to consider */
|
||||
|
||||
assert(aOptions != NULL);
|
||||
assert(opt_eval != NULL);
|
||||
|
||||
/* Determine the program's name */
|
||||
if (NULL == aPgmName)
|
||||
{
|
||||
char * newName;
|
||||
|
||||
newName = strdup(basename(argv[0]));
|
||||
if (NULL == newName)
|
||||
aPgmName = (const char *)argv[0];
|
||||
else
|
||||
aPgmName = (const char *)newName;
|
||||
}
|
||||
|
||||
/* Make the compiler happy */
|
||||
bShort = MY_FALSE;
|
||||
pArg = NULL;
|
||||
|
||||
/* Count the options */
|
||||
for (nOptions = 0; aOptions[nOptions].iNumber != OPTION_UNKNOWN; nOptions++)
|
||||
/* SKIP */ ;
|
||||
|
||||
/* Scan all arguments */
|
||||
bCont = MY_FALSE;
|
||||
bDone = MY_FALSE;
|
||||
for (iArg = 1; iArg < argc; !bCont ? iArg++ : iArg)
|
||||
{
|
||||
ssize_t iArglen; /* Length of remaining argument */
|
||||
char * pValue; /* First character of an option value, or NULL */
|
||||
int bTakesValue; /* This option takes a value */
|
||||
|
||||
/* Make the compiler happy */
|
||||
iArglen = 0;
|
||||
pValue = NULL;
|
||||
bTakesValue = MY_FALSE;
|
||||
|
||||
if (bDone)
|
||||
eOption = OPTION_ARGUMENT;
|
||||
else
|
||||
/* If this is not a continuation, reinitialise the inspection vars.
|
||||
* For --opt=val arguments, pValue is set to the first character of val.
|
||||
*/
|
||||
if (!bCont)
|
||||
{
|
||||
pArg = argv[iArg];
|
||||
if ('-' == pArg[0] && '-' == pArg[1]) /* Long option? */
|
||||
{
|
||||
eOption = OPTION_UNKNOWN;
|
||||
bShort = MY_FALSE;
|
||||
pArg += 2;
|
||||
/* Special case: if the argument is just '--', it marks the
|
||||
* end of all options.
|
||||
* We set a flag and continue with the next argument.
|
||||
*/
|
||||
if ('\0' == *pArg)
|
||||
{
|
||||
bDone = MY_TRUE;
|
||||
continue;
|
||||
}
|
||||
pValue = strchr(pArg, '=');
|
||||
if (pValue != NULL)
|
||||
{
|
||||
iArglen = pValue - pArg;
|
||||
pValue++;
|
||||
}
|
||||
else
|
||||
iArglen = (signed)strlen(pArg);
|
||||
}
|
||||
else if ('-' == pArg[0]) /* Short option? */
|
||||
{
|
||||
eOption = OPTION_UNKNOWN;
|
||||
bShort = MY_TRUE;
|
||||
pArg++;
|
||||
iArglen = (signed)strlen(pArg);
|
||||
pValue = NULL;
|
||||
}
|
||||
else /* No option */
|
||||
{
|
||||
eOption = OPTION_ARGUMENT;
|
||||
pValue = pArg;
|
||||
iArglen = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
eOption = OPTION_UNKNOWN;
|
||||
|
||||
/* If the option is not determined yet, do it.
|
||||
* Set pValue to the first character of the value if any.
|
||||
*/
|
||||
if (OPTION_UNKNOWN == eOption)
|
||||
{
|
||||
xOption = 0;
|
||||
if (bShort) /* search the short option */
|
||||
{
|
||||
for (i = 0; i < nOptions; i++)
|
||||
if ('\0' != aOptions[i].cOption && *pArg == aOptions[i].cOption)
|
||||
{
|
||||
xOption = i;
|
||||
eOption = aOptions[i].iNumber;
|
||||
bTakesValue = aOptions[i].bValue;
|
||||
pArg++; iArglen--; /* Consume this character */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Consume a following '=' if appropriate */
|
||||
if (OPTION_UNKNOWN != eOption
|
||||
&& bTakesValue
|
||||
&& iArglen > 0 && '=' == *pArg)
|
||||
{
|
||||
pArg++; iArglen--;
|
||||
}
|
||||
|
||||
/* If there is a value following in the same argument, set pValue to
|
||||
* it and mark the remaining characters as 'consumed'
|
||||
*/
|
||||
if (OPTION_UNKNOWN != eOption && bTakesValue && iArglen > 0)
|
||||
{
|
||||
pValue = pArg;
|
||||
pArg += iArglen;
|
||||
iArglen = 0;
|
||||
}
|
||||
}
|
||||
else /* search the long option */
|
||||
{
|
||||
for (i = 0; i < nOptions; i++)
|
||||
if (NULL != aOptions[i].pOption
|
||||
&& (size_t)iArglen == strlen(aOptions[i].pOption)
|
||||
&& !strncasecmp(pArg, aOptions[i].pOption, (unsigned)iArglen))
|
||||
{
|
||||
xOption = i;
|
||||
eOption = aOptions[i].iNumber;
|
||||
bTakesValue = aOptions[i].bValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (OPTION_UNKNOWN == eOption)
|
||||
{
|
||||
fprintf(stderr, "%s: Unknown option '", aPgmName);
|
||||
if (bShort)
|
||||
fprintf(stderr, "-%c", *pArg);
|
||||
else
|
||||
fprintf(stderr, "--%*.*s", (int)iArglen, (int)iArglen, pArg);
|
||||
fputs("'.\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If at this point bTakesValue is true, but pValue is still NULL,
|
||||
* then the value is in the next argument. Get it if it's there.
|
||||
*/
|
||||
if (bTakesValue && pValue == NULL && iArg + 1 < argc)
|
||||
{
|
||||
iArg++;
|
||||
pValue = argv[iArg];
|
||||
}
|
||||
|
||||
/* Signal an error if pValue is still NULL or if it's empty. */
|
||||
if (bTakesValue && (pValue == NULL || !strlen(pValue)))
|
||||
{
|
||||
fprintf(stderr, "%s: Option '", aPgmName);
|
||||
if (bShort)
|
||||
putc(aOptions[xOption].cOption, stderr);
|
||||
else
|
||||
fputs(aOptions[xOption].pOption, stderr);
|
||||
fputs("' expects a value.\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} /* if (unknown option) */
|
||||
|
||||
/* Before evaluation of the parsed option, determine 'bCont' */
|
||||
bCont = bShort && (iArglen > 0) && !bTakesValue;
|
||||
|
||||
/* --- The option evaluation --- */
|
||||
|
||||
i = (*opt_eval)(eOption, pValue);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
} /* for (iArg) */
|
||||
|
||||
return 0;
|
||||
} /* getargs() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
char *
|
||||
basename (const char *pName)
|
||||
|
||||
/* Find the basename (filename) in a UNIX-style pathname and return
|
||||
* a pointer to its first character.
|
||||
* Example: basename("/boot/home/data/l.txt") returns a pointer to "l.txt".
|
||||
*/
|
||||
|
||||
{
|
||||
char * pBase, * cp;
|
||||
|
||||
pBase = (char *)pName;
|
||||
for (cp = (char *)pName; *cp; cp++)
|
||||
if ('/' == *cp)
|
||||
pBase = cp+1;
|
||||
return pBase;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
37
src/bin/mkdepend/getargs.h
Normal file
37
src/bin/mkdepend/getargs.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* $Id: getargs.h 1.2 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
** Copyright (c) 1995-1998 by Lars Düning. All Rights Reserved.
|
||||
** This file is free software. For terms of use see the file LICENSE.
|
||||
**---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __GETARGS_H__
|
||||
#define __GETARGS_H__ 1
|
||||
|
||||
/* Description of an option */
|
||||
|
||||
typedef struct OptionDesc {
|
||||
unsigned char cOption; /* The option character (may be \0) */
|
||||
char * pOption; /* The option string (may be NULL) */
|
||||
int iNumber; /* The associated option number */
|
||||
short bValue; /* True: option takes a value */
|
||||
} OptionDesc;
|
||||
|
||||
/* Callback function type for option handling */
|
||||
|
||||
typedef int (*OptionHandler)(int iOption, const char * pValue);
|
||||
|
||||
/* Predefined values for OptionDesc.eNumber */
|
||||
|
||||
#define OPTION_UNKNOWN 0 /* Option unknown, or 'end of descriptor array' */
|
||||
#define OPTION_ARGUMENT 1 /* Not an option, but a real argument */
|
||||
|
||||
/* --- Prototypes --- */
|
||||
extern char * basename (const char *);
|
||||
extern int getargs(int, char **, OptionDesc[], OptionHandler);
|
||||
|
||||
/* --- Variables --- */
|
||||
extern const char * aPgmName;
|
||||
|
||||
#endif /* __GETARGS_H__ */
|
1503
src/bin/mkdepend/main.c
Normal file
1503
src/bin/mkdepend/main.c
Normal file
File diff suppressed because it is too large
Load Diff
37
src/bin/mkdepend/main.h
Normal file
37
src/bin/mkdepend/main.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* $Id: main.h 1.4 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
** Copyright (c) 1995-2000 by Lars Düning. All Rights Reserved.
|
||||
** This file is free software. For terms of use see the file LICENSE.
|
||||
**---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __MAIN_H__
|
||||
#define __MAIN_H__ 1
|
||||
|
||||
/* Return codes */
|
||||
|
||||
#define RETURN_OK 0 /* Everything is ok */
|
||||
#define RETURN_WARN 1 /* A warning was issued */
|
||||
#define RETURN_ERROR 2 /* An error occured */
|
||||
#define RETURN_FAIL 3 /* A fatal error occured */
|
||||
|
||||
/* Boolean values */
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
/* Macros */
|
||||
|
||||
#define IS_SELECT_MODE (aSelect.size != 0)
|
||||
/* The macro returns TRUE if only selected dependencies are to be
|
||||
* generated.
|
||||
*/
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
extern void set_rc (int, int);
|
||||
extern void exit_doserr (int);
|
||||
extern void exit_nomem (char *);
|
||||
|
||||
#endif
|
11
src/bin/mkdepend/mkdepend.rdef
Normal file
11
src/bin/mkdepend/mkdepend.rdef
Normal file
@ -0,0 +1,11 @@
|
||||
resource app_version
|
||||
{
|
||||
major = 1,
|
||||
middle = 7,
|
||||
minor = 1,
|
||||
variety = 5,
|
||||
internal = 0,
|
||||
short_info = "1.7.1",
|
||||
long_info = "1.7.1 © 1995-2001 Lars Düning. All rights reserved."
|
||||
};
|
||||
|
587
src/bin/mkdepend/nodes.c
Normal file
587
src/bin/mkdepend/nodes.c
Normal file
@ -0,0 +1,587 @@
|
||||
/* $Id: nodes.c 1.6 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Management of the dependency tree and nodes.
|
||||
*
|
||||
* Copyright (c) 1995-2000 by Lars Düning. All Rights Reserved.
|
||||
* This file is free software. For terms of use see the file LICENSE.
|
||||
*---------------------------------------------------------------------------
|
||||
* Each file (source or include) is associated one node which is kept in
|
||||
* a binary search tree with the name as index. Glued to each node is
|
||||
* a list of that nodes which files the master nodes includes.
|
||||
* Each node contains an extra node pointer the module uses to implement
|
||||
* tree-independant lists, namely the TODO list of files still to read
|
||||
* and a virtual stack for inorder tree traversals.
|
||||
*
|
||||
* Adding and retrieving the files to analyse is done using the functions
|
||||
* nodes_addsource()
|
||||
* nodes_depend()
|
||||
* nodes_todo()
|
||||
* nodes_select_mark()
|
||||
*
|
||||
* The output of the dependency tree is done inorder using
|
||||
* nodes_initwalk()
|
||||
* nodes_inorder()
|
||||
*
|
||||
* The list of dependencies for one single node is managed using
|
||||
* nodes_deplist()
|
||||
* nodes_freelist()
|
||||
*
|
||||
* Tree traversal and creation must not be mixed!
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "main.h"
|
||||
#include "nodes.h"
|
||||
#include "util.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* Types for block allocation of Nodes and NodeRefs.
|
||||
* Note that Nodes are never freed.
|
||||
*/
|
||||
|
||||
#define NBLOCKSIZE 16
|
||||
|
||||
typedef struct nodeblock
|
||||
{
|
||||
struct nodeblock * pNext; /* Next nodeblock */
|
||||
int iFree; /* Number of first free node */
|
||||
Node aNodes[NBLOCKSIZE]; /* Block of nodes */
|
||||
}
|
||||
NodeBlock;
|
||||
|
||||
#define RBLOCKSIZE 16
|
||||
|
||||
typedef struct refblock
|
||||
{
|
||||
struct refblock * pNext; /* Next refblock */
|
||||
int iFree; /* Number of first free noderef */
|
||||
NodeRef aRefs[NBLOCKSIZE]; /* Block of noderefs */
|
||||
}
|
||||
RefBlock;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static NodeBlock *pFreeNBlocks = NULL; /* Nodeblocks */
|
||||
static RefBlock *pFreeRBlocks = NULL; /* Refblocks */
|
||||
static NodeRef *pFreeRefs = NULL; /* List of free NodeRefs */
|
||||
static Node *pTree = NULL; /* Dependency tree */
|
||||
static Node *pList = NULL; /* List of (tree) nodes */
|
||||
/* The List is used as TODO list for the files to analyse as well as
|
||||
* stack simulation for the tree traversal.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static Node *
|
||||
nodes_newnode (void)
|
||||
|
||||
/* Allocate a new Node.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the new Node, or NULL on error.
|
||||
*
|
||||
* The memory of the Node is cleared, except for .flags which is set
|
||||
* to NODE_NEW.
|
||||
*/
|
||||
|
||||
{
|
||||
Node * pNode;
|
||||
|
||||
if (!pFreeNBlocks || !pFreeNBlocks->iFree)
|
||||
{
|
||||
NodeBlock * pNewBlock;
|
||||
pNewBlock = (NodeBlock *)malloc(sizeof(*pNewBlock));
|
||||
if (!pNewBlock)
|
||||
return NULL;
|
||||
memset(pNewBlock, 0, sizeof(*pNewBlock));
|
||||
pNewBlock->iFree = NBLOCKSIZE;
|
||||
pNewBlock->pNext = pFreeNBlocks;
|
||||
pFreeNBlocks = pNewBlock;
|
||||
}
|
||||
pNode = &(pFreeNBlocks->aNodes[--pFreeNBlocks->iFree]);
|
||||
pNode->flags |= NODE_NEW;
|
||||
pNode->iInclude = -1;
|
||||
return pNode;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static NodeRef *
|
||||
nodes_newref (void)
|
||||
|
||||
/* Allocate a new NodeRef.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the new NodeRef, or NULL on error.
|
||||
*
|
||||
* The memory of the NodeRef is cleared.
|
||||
*/
|
||||
|
||||
{
|
||||
NodeRef * pRef;
|
||||
|
||||
if (pFreeRefs)
|
||||
{
|
||||
pRef = pFreeRefs;
|
||||
pFreeRefs = pRef->pNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pFreeRBlocks || !pFreeRBlocks->iFree)
|
||||
{
|
||||
RefBlock * pNewBlock;
|
||||
pNewBlock = (RefBlock *)malloc(sizeof(*pNewBlock));
|
||||
if (!pNewBlock)
|
||||
return NULL;
|
||||
pNewBlock->iFree = NBLOCKSIZE;
|
||||
pNewBlock->pNext = pFreeRBlocks;
|
||||
pFreeRBlocks = pNewBlock;
|
||||
}
|
||||
pRef = &(pFreeRBlocks->aRefs[--pFreeRBlocks->iFree]);
|
||||
}
|
||||
memset(pRef, 0, sizeof(*pRef));
|
||||
return pRef;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
Node *
|
||||
nodes_findadd (const char *pName, int bAddToList)
|
||||
|
||||
/* Find the node associated with file *pName.
|
||||
* If necessary, add the node.
|
||||
*
|
||||
* pName: Pointer to the (minimalized) filename of the node.
|
||||
* bAddToList: If true, a newly allocated node is also added to
|
||||
* the TODO list.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the node associated with this filename, or NULL on error.
|
||||
*
|
||||
* If the node has been added by this call, NODE_NEW is set in its .flags,
|
||||
* but it is empty otherwise.
|
||||
*/
|
||||
|
||||
{
|
||||
Node * pThis, * pPrev;
|
||||
int i;
|
||||
|
||||
assert(pName);
|
||||
|
||||
if (!pTree)
|
||||
{
|
||||
pTree = nodes_newnode();
|
||||
if (bAddToList)
|
||||
{
|
||||
pTree->pNext = pList;
|
||||
pList = pTree;
|
||||
}
|
||||
return pTree;
|
||||
}
|
||||
|
||||
pPrev = NULL;
|
||||
pThis = pTree;
|
||||
while(pThis)
|
||||
{
|
||||
i = strcmp(pThis->pName, pName);
|
||||
if (!i)
|
||||
return pThis;
|
||||
pPrev = pThis;
|
||||
if (i > 0)
|
||||
pThis = pThis->pLeft;
|
||||
else
|
||||
pThis = pThis->pRight;
|
||||
}
|
||||
pThis = nodes_newnode();
|
||||
if (pThis)
|
||||
{
|
||||
if (i > 0)
|
||||
pPrev->pLeft = pThis;
|
||||
else
|
||||
pPrev->pRight = pThis;
|
||||
|
||||
if (bAddToList)
|
||||
{
|
||||
pThis->pNext = pList;
|
||||
pList = pThis;
|
||||
}
|
||||
}
|
||||
return pThis;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
Node *
|
||||
nodes_find (const char *pName)
|
||||
|
||||
/* Find the node associated with file *pName.
|
||||
*
|
||||
* pName: Pointer to the (minimalized) filename of the node.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the node associated with this filename, or NULL on error.
|
||||
*/
|
||||
|
||||
{
|
||||
Node * pThis, * pPrev;
|
||||
int i;
|
||||
|
||||
assert(pName);
|
||||
|
||||
if (!pTree)
|
||||
return NULL;
|
||||
|
||||
pPrev = NULL;
|
||||
pThis = pTree;
|
||||
while(pThis)
|
||||
{
|
||||
i = strcmp(pThis->pName, pName);
|
||||
if (!i)
|
||||
return pThis;
|
||||
pPrev = pThis;
|
||||
if (i > 0)
|
||||
pThis = pThis->pLeft;
|
||||
else
|
||||
pThis = pThis->pRight;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
nodes_addsource (char *pName, int bAvoid)
|
||||
|
||||
/* Add a source file to the dependency tree.
|
||||
*
|
||||
* pName : Name of the file to add (it will be duplicated).
|
||||
* bAvoid: TRUE if this is a file to be avoided.
|
||||
*
|
||||
* Result:
|
||||
* 0 on success, non-0 on error (out of memory).
|
||||
*
|
||||
* The file is also added to the internal TODO list of files if it is
|
||||
* a genuine source file.
|
||||
*/
|
||||
|
||||
{
|
||||
Node *pNode;
|
||||
char *pBasename;
|
||||
|
||||
assert(pName);
|
||||
|
||||
pName = util_getpath(pName, &pBasename);
|
||||
if (!pName)
|
||||
return 1;
|
||||
pNode = nodes_findadd(pName, !bAvoid);
|
||||
if (!pNode)
|
||||
return 1;
|
||||
if (pNode->flags & NODE_NEW)
|
||||
{
|
||||
pNode->flags = NODE_SOURCE;
|
||||
pNode->pName = pName;
|
||||
pNode->pBase = pBasename;
|
||||
pNode->pPath = util_getpath(pName, NULL);
|
||||
if (!pNode->pPath)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
free(pName);
|
||||
|
||||
if (bAvoid)
|
||||
pNode->flags |= NODE_AVOID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
nodes_depend (Node * pChild, Node * pParent)
|
||||
|
||||
/* Add node pChild to the list of dependees of pParent, vice versa add
|
||||
* pParent to the list of users of pName.
|
||||
*
|
||||
* pChild : Node of the file included by pParent.
|
||||
* pParent: Node which depends on pChild.
|
||||
*
|
||||
* Result:
|
||||
* 0 on success, non-0 on error (out of memory).
|
||||
*
|
||||
* The file is added to the dependee- and user-lists.
|
||||
*/
|
||||
|
||||
{
|
||||
NodeRef * pRef;
|
||||
|
||||
assert(pParent);
|
||||
assert(pChild);
|
||||
|
||||
/* Add pChild to pParent->pDeps if not already there */
|
||||
for ( pRef = pParent->pDeps
|
||||
; pRef && pRef->pNode != pChild
|
||||
; pRef = pRef->pNext
|
||||
) /* SKIP */;
|
||||
if (!pRef)
|
||||
{
|
||||
pRef = nodes_newref();
|
||||
if (!pRef)
|
||||
return 1;
|
||||
pRef->pNode = pChild;
|
||||
pRef->pNext = pParent->pDeps;
|
||||
pParent->pDeps = pRef;
|
||||
}
|
||||
|
||||
/* Add pParent to pChild->pUsers if not already there */
|
||||
for ( pRef = pChild->pUsers
|
||||
; pRef && pRef->pNode != pParent
|
||||
; pRef = pRef->pNext
|
||||
) /* SKIP */;
|
||||
if (!pRef)
|
||||
{
|
||||
pRef = nodes_newref();
|
||||
if (!pRef)
|
||||
return 1;
|
||||
pRef->pNode = pParent;
|
||||
pRef->pNext = pChild->pUsers;
|
||||
pChild->pUsers = pRef;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
Node *
|
||||
nodes_todo (void)
|
||||
|
||||
/* Return the tree node of the next file to analyse.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the node of the next file to analyse, or NULL if there is
|
||||
* none.
|
||||
*/
|
||||
|
||||
{
|
||||
Node * pNode;
|
||||
|
||||
/* NODE_DONE should not happen, but checking it is free */
|
||||
while (pList && (pList->flags & (NODE_AVOID|NODE_DONE)))
|
||||
pList = pList->pNext;
|
||||
if (pList)
|
||||
{
|
||||
pNode = pList;
|
||||
pList = pList->pNext;
|
||||
pNode->flags |= NODE_DONE;
|
||||
}
|
||||
else
|
||||
pNode = NULL;
|
||||
return pNode;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
nodes_mark_select (Node *pNode)
|
||||
|
||||
/* Check if this node, or one of its dependency nodes has been marked
|
||||
* as selected. If yes, mark pNode as well and return TRUE, otherwise
|
||||
* return FALSE.
|
||||
*
|
||||
* This is a recursive function. We avoid loops by temporarily marking
|
||||
* the node.
|
||||
*/
|
||||
|
||||
{
|
||||
int rc;
|
||||
NodeRef * pRef;
|
||||
|
||||
assert(pNode);
|
||||
|
||||
if (NODES_MARKED(pNode))
|
||||
return FALSE;
|
||||
|
||||
if (pNode->flags & NODE_ISELECT)
|
||||
return TRUE;
|
||||
|
||||
NODES_MARK(pNode);
|
||||
/* First, recurse into the dependency nodes */
|
||||
rc = FALSE;
|
||||
for (pRef = pNode->pDeps; pRef != NULL; pRef = pRef->pNext)
|
||||
{
|
||||
if (nodes_mark_select(pRef->pNode))
|
||||
rc = TRUE;
|
||||
}
|
||||
|
||||
if (rc && !(pNode->flags & NODE_SELECT))
|
||||
{
|
||||
pNode->flags |= NODE_ISELECT;
|
||||
}
|
||||
|
||||
NODES_UNMARK(pNode);
|
||||
|
||||
return rc || (pNode->flags & (NODE_SELECT|NODE_ISELECT));
|
||||
} /* nodes_mark_select() */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
nodes_initwalk (void)
|
||||
|
||||
/* Initialise a tree traversal.
|
||||
*/
|
||||
|
||||
{
|
||||
assert(!pList);
|
||||
pList = pTree;
|
||||
if (pList)
|
||||
{
|
||||
pList->iStage = 0;
|
||||
pList->pNext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
Node *
|
||||
nodes_inorder (void)
|
||||
|
||||
/* Return the next Node of an inorder tree traversal.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the next node, or NULL if traversal is complete.
|
||||
*/
|
||||
|
||||
{
|
||||
Node *pNode = NULL;
|
||||
if (!pList)
|
||||
return NULL;
|
||||
while (pList)
|
||||
{
|
||||
switch (pList->iStage)
|
||||
{
|
||||
case 0:
|
||||
pList->iStage++;
|
||||
pNode = pList->pLeft;
|
||||
break;
|
||||
case 1:
|
||||
pList->iStage++;
|
||||
return pList;
|
||||
break;
|
||||
case 2:
|
||||
pList->iStage++;
|
||||
pNode = pList->pRight;
|
||||
break;
|
||||
case 3:
|
||||
pList = pList->pNext;
|
||||
pNode = NULL;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
if (pNode)
|
||||
{
|
||||
pNode->pNext = pList;
|
||||
pList = pNode;
|
||||
pNode->iStage = 0;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
NodeRef *
|
||||
nodes_deplist (Node * pNode, int bUsers, int bSelect)
|
||||
|
||||
/* Gather the list of dependees or users of *pNode.
|
||||
*
|
||||
* pNode: the Node to get the list for.
|
||||
* bUsers: TRUE: gather the list of users instead of the dependees.
|
||||
* bSelect: TRUE: gather only files marked as NODE_SELECT.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the list of dependees/users, or NULL if an error occurs.
|
||||
* First entry in the list is pNode itself.
|
||||
*/
|
||||
|
||||
{
|
||||
NodeRef *pDList;
|
||||
NodeRef *pMark;
|
||||
NodeRef *pThis;
|
||||
NodeRef *pRover;
|
||||
Node *pDep;
|
||||
|
||||
assert(pNode);
|
||||
pDList = nodes_newref();
|
||||
if (!pDList)
|
||||
return NULL;
|
||||
|
||||
/* The list of dependencies is gathered in a wide search. */
|
||||
pDList->pNode = pNode;
|
||||
NODES_MARK(pNode);
|
||||
for ( pThis = pDList, pMark = pDList
|
||||
; pMark
|
||||
; pMark = pMark->pNext
|
||||
)
|
||||
{
|
||||
for ( pRover = (bUsers ? pMark->pNode->pUsers : pMark->pNode->pDeps)
|
||||
; pRover
|
||||
; pRover = pRover->pNext
|
||||
)
|
||||
{
|
||||
pDep = pRover->pNode;
|
||||
if (!NODES_MARKED(pDep))
|
||||
{
|
||||
pThis->pNext = nodes_newref();
|
||||
if (!pThis->pNext)
|
||||
return NULL;
|
||||
pThis = pThis->pNext;
|
||||
pThis->pNode = pDep;
|
||||
NODES_MARK(pDep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If bSelect is requested, remove all non-SELECT nodes from the list
|
||||
* (but always keep the first one).
|
||||
*/
|
||||
if (bSelect)
|
||||
{
|
||||
pThis = pDList;
|
||||
while (pThis->pNext != NULL)
|
||||
{
|
||||
pMark = pThis->pNext;
|
||||
if (!(pMark->pNode->flags & NODE_SELECT))
|
||||
{
|
||||
NODES_UNMARK(pMark->pNode);
|
||||
pThis->pNext = pMark->pNext;
|
||||
pMark->pNext = pFreeRefs;
|
||||
pFreeRefs = pMark;
|
||||
}
|
||||
else
|
||||
pThis = pMark;
|
||||
}
|
||||
}
|
||||
|
||||
return pDList;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
nodes_freelist (NodeRef * pDList)
|
||||
|
||||
/* Free a dependency list produced earlier by nodes_deplist().
|
||||
*
|
||||
* pDList: Base of the list to free.
|
||||
*/
|
||||
|
||||
{
|
||||
NodeRef * pThis;
|
||||
|
||||
while (pDList)
|
||||
{
|
||||
NODES_UNMARK(pDList->pNode);
|
||||
pThis = pDList;
|
||||
pDList = pDList->pNext;
|
||||
pThis->pNext = pFreeRefs;
|
||||
pFreeRefs = pThis;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
95
src/bin/mkdepend/nodes.h
Normal file
95
src/bin/mkdepend/nodes.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* $Id: nodes.h 1.5 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
** Copyright (c) 1995-2000 by Lars Düning. All Rights Reserved.
|
||||
** This file is free software. For terms of use see the file LICENSE.
|
||||
**---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __NODES_H__
|
||||
#define __NODES_H__ 1
|
||||
|
||||
struct noderef; /* forward */
|
||||
|
||||
/* Node structure to build the dependency tree
|
||||
*/
|
||||
typedef struct node
|
||||
{
|
||||
struct node * pLeft, * pRight; /* Tree pointers */
|
||||
struct node * pNext; /* List of Files to do; stack for traversals */
|
||||
|
||||
char * pName;
|
||||
/* Searchkey: Name of this file.
|
||||
* This is the minimal full pathname with which the file can be read.
|
||||
* For source files (and files to be avoided) it is identical with the name
|
||||
* given on the commandline.
|
||||
*/
|
||||
char * pBase;
|
||||
/* The filename part of the the file's pathname.
|
||||
* This is a pointer into pName.
|
||||
*/
|
||||
char * pPath;
|
||||
/* The directory part of the file's pathname.
|
||||
* Relative paths are interpreted depending on the type of the file:
|
||||
* source files are relative to the current working directory,
|
||||
* non-source files are relative to aIncl[.iInclude].
|
||||
*/
|
||||
int iInclude;
|
||||
/* Included non-sourcefiles: the index into aIncl[]/aSymbol[].
|
||||
* A negative index denotes an absolute filename, or one relative
|
||||
* to the cwd.
|
||||
*/
|
||||
short flags; /* misc flags */
|
||||
struct noderef * pDeps; /* What this file depends on */
|
||||
struct noderef * pUsers; /* Who depends on this file */
|
||||
short iStage; /* Stage counter for tree traversals */
|
||||
}
|
||||
Node;
|
||||
|
||||
/* Node.flags
|
||||
*/
|
||||
#define NODE_MARK (1<<0) /* Generic Node marker, used e.g. in tree walks */
|
||||
#define NODE_NEW (1<<1) /* Node is unused */
|
||||
#define NODE_SOURCE (1<<2) /* Node is a skeleton source */
|
||||
#define NODE_AVOID (1<<3) /* Node is not part of the skeleton sources */
|
||||
#define NODE_NOTFND (1<<4) /* Node describes a non-existant file */
|
||||
#define NODE_DONE (1<<5) /* Node has been evaluated */
|
||||
#define NODE_SYSTEM (1<<6) /* File is an <>-include */
|
||||
#define NODE_IGNORE (1<<7) /* Data for this node shall not be printed */
|
||||
#define NODE_SELECT (1<<8) /* Marks selected include files */
|
||||
#define NODE_ISELECT (1<<9) /* Marks nodes between source and selected
|
||||
* include files */
|
||||
|
||||
/* Node marking
|
||||
*/
|
||||
#define NODES_MARK(node) ((node)->flags |= NODE_MARK)
|
||||
#define NODES_UNMARK(node) ((node)->flags &= (short)(~NODE_MARK))
|
||||
#define NODES_MARKED(node) ((node)->flags & NODE_MARK)
|
||||
|
||||
/* Test if the _SYSTEM flag has a specific value
|
||||
*/
|
||||
#define NODES_SYSTEST(node,value) ( (node)->flags & NODE_SYSTEM ? (value) : !(value) )
|
||||
|
||||
/* Reference structure to treenodes
|
||||
*/
|
||||
typedef struct noderef
|
||||
{
|
||||
struct noderef * pNext; /* next NodeRef */
|
||||
Node * pNode; /* referenced Node */
|
||||
}
|
||||
NodeRef;
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
extern Node * nodes_findadd (const char *, int);
|
||||
extern Node * nodes_find (const char *);
|
||||
extern int nodes_addsource (char *, int);
|
||||
extern int nodes_depend (Node *, Node *);
|
||||
extern int nodes_mark_select (Node *);
|
||||
extern Node * nodes_todo (void);
|
||||
extern void nodes_initwalk (void);
|
||||
extern Node * nodes_inorder (void);
|
||||
extern NodeRef * nodes_deplist (Node *, int, int);
|
||||
extern void nodes_freelist (NodeRef *);
|
||||
|
||||
#endif
|
658
src/bin/mkdepend/reader.c
Normal file
658
src/bin/mkdepend/reader.c
Normal file
@ -0,0 +1,658 @@
|
||||
/* $Id: reader.c 1.9 Wed, 01 Mar 2000 22:36:57 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
** Reading of C-Sources and filter for #include statements.
|
||||
** Also here are routines for the modification of Makefiles.
|
||||
**
|
||||
** Copyright (c) 1995-1998 by Lars Düning. All Rights Reserved.
|
||||
** This files is free software. For terms of use see the file LICENSE.
|
||||
**---------------------------------------------------------------------------
|
||||
** Credits:
|
||||
** The buffering scheme was inspired by the input module of lcc (by
|
||||
** Chris Fraser & David Hanson).
|
||||
**---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "reader.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct filestate
|
||||
{
|
||||
int len; /* Number of bytes buffered */
|
||||
char buf[1]; /* allocated to <len> bytes */
|
||||
};
|
||||
|
||||
#define BUFSIZE 10240 /* Size of the file buffer */
|
||||
static char aBuffer[BUFSIZE+1]; /* File buffer */
|
||||
static int fdFile; /* Filehandle */
|
||||
static int fdFile2; /* Filehandle Writer */
|
||||
static char * pLimit; /* Pointer to closing sentinel in buffer */
|
||||
static char * pch; /* Pointer to actual char in buffer */
|
||||
static char * pIName; /* Start of include filename */
|
||||
static struct filestate * pState; /* Saved state of the Makefile */
|
||||
|
||||
#define END_OF_BUF() (pch >= pLimit)
|
||||
#define END_OF_FILE() (pLimit == aBuffer)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void
|
||||
reader_init (void)
|
||||
|
||||
/* Initialize the reader.
|
||||
*/
|
||||
|
||||
{
|
||||
fdFile = -1;
|
||||
fdFile2 = -1;
|
||||
aBuffer[BUFSIZE] = '\n';
|
||||
pLimit = aBuffer+BUFSIZE;
|
||||
pch = pLimit;
|
||||
pIName = NULL;
|
||||
pState = NULL;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int
|
||||
fillbuffer (void)
|
||||
|
||||
/* Read in the next chunk from file such that incrementing pch will
|
||||
* access the newly read data.
|
||||
*
|
||||
* Result:
|
||||
* 0 on success, non-0 else (errno holds error code then).
|
||||
* pch is set to the start of the new data.
|
||||
*/
|
||||
|
||||
{
|
||||
int iRead;
|
||||
|
||||
if (END_OF_FILE())
|
||||
return 1;
|
||||
if (pIName)
|
||||
{
|
||||
if (pch > pLimit)
|
||||
pch = pLimit;
|
||||
memcpy(aBuffer, pIName, (unsigned)(pLimit-pIName));
|
||||
pch -= (pLimit-pIName);
|
||||
}
|
||||
else
|
||||
pch = aBuffer;
|
||||
iRead = read(fdFile, pch, (unsigned)(aBuffer+BUFSIZE-pch));
|
||||
if (iRead >= 0)
|
||||
{
|
||||
pLimit = pch+iRead;
|
||||
*pLimit = '\n';
|
||||
}
|
||||
return iRead < 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_open (const char *pName)
|
||||
|
||||
/* Open a file for reading.
|
||||
*
|
||||
* pName: Name of the file to read.
|
||||
*
|
||||
* Result:
|
||||
* 0 on success, non-0 else (errno contains error code then).
|
||||
*
|
||||
* The reader is initialized to read and filter the file name *pName.
|
||||
*/
|
||||
|
||||
{
|
||||
assert(pName);
|
||||
assert(fdFile < 0);
|
||||
reader_init();
|
||||
fdFile = open(pName, O_RDONLY);
|
||||
return fdFile >= 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_openrw (const char *pNameR, const char *pNameW)
|
||||
|
||||
/* Open two makefiles for modification.
|
||||
*
|
||||
* pNameR: Name of the file to read, may be NULL.
|
||||
* pNameW: Name of the file to read.
|
||||
*
|
||||
* Result:
|
||||
* 0 on success, non-0 else (errno contains error code then).
|
||||
*
|
||||
* The reader is initialized to read the old makefile *pNameR and writing
|
||||
* of new makefile *pNameW.
|
||||
* If no pNameR is given, the reader is immediately initialized to
|
||||
* write *pNameW.
|
||||
*/
|
||||
|
||||
{
|
||||
assert(pNameW);
|
||||
assert(fdFile < 0);
|
||||
assert(fdFile2 < 0);
|
||||
reader_init();
|
||||
fdFile2 = open(pNameW, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
||||
if (fdFile2 < 0)
|
||||
return 1;
|
||||
if (pNameR)
|
||||
{
|
||||
fdFile = open(pNameR, O_RDONLY);
|
||||
if (fdFile < 0)
|
||||
{
|
||||
close(fdFile2);
|
||||
fdFile2 = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
pch = aBuffer;
|
||||
return fdFile2 < 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_close (void)
|
||||
|
||||
/* Close the file currently read.
|
||||
* Result:
|
||||
* 0 on success, non-0 else.
|
||||
* errno set to error code in case.
|
||||
*/
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
if (fdFile >= 0)
|
||||
{
|
||||
i = close(fdFile);
|
||||
}
|
||||
fdFile = -1;
|
||||
if (fdFile2 >= 0)
|
||||
{
|
||||
i = close(fdFile2) || i;
|
||||
}
|
||||
fdFile2 = -1;
|
||||
if (pState)
|
||||
{
|
||||
free(pState);
|
||||
}
|
||||
pState = NULL;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_eof (void)
|
||||
|
||||
/* Test if the file read is at its end.
|
||||
*
|
||||
* Result:
|
||||
* Non-0 on end of file.
|
||||
*/
|
||||
|
||||
{
|
||||
return END_OF_FILE();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
const char *
|
||||
reader_get (int * pType)
|
||||
|
||||
/* Extract the next include statement from the file being read.
|
||||
*
|
||||
* Result:
|
||||
* Pointer to the filename extracted from the statement, or NULL on error
|
||||
* or end of file.
|
||||
* The memory is property of reader_get(), the pointer valid just until
|
||||
* the next call to reader_get().
|
||||
* <*pType> is set to 0 for an ""-include, and non-zero for an <>-include.
|
||||
* <errn>o set to an error code in case.
|
||||
*/
|
||||
|
||||
{
|
||||
enum { StartOfLine, InLine, FoundHash, SkipComment, SkipLComment, FoundInclude
|
||||
} eState;
|
||||
/* For debugging purposes:
|
||||
char *stab[]
|
||||
= {
|
||||
"Start "
|
||||
, "InLine"
|
||||
, "Found#"
|
||||
, "SkipC "
|
||||
, "SkipLC"
|
||||
, "FoundI"
|
||||
};
|
||||
*/
|
||||
char ch;
|
||||
int iFound; /* Number of chars found of "include" */
|
||||
int bDone; /* 0: still searching, 1: found include */
|
||||
int bType; /* 0: ""-include, 1: <>-include */
|
||||
|
||||
#define GETCHAR() \
|
||||
ch = *pch++; \
|
||||
if (ch == '\n' && pch >= pLimit) \
|
||||
{ \
|
||||
if (fillbuffer()) { \
|
||||
pIName = NULL; \
|
||||
return NULL; \
|
||||
} \
|
||||
ch = *pch++; \
|
||||
}
|
||||
|
||||
if (pIName)
|
||||
eState = InLine;
|
||||
else
|
||||
eState = StartOfLine;
|
||||
pIName = NULL;
|
||||
|
||||
iFound = 0;
|
||||
bType = 0;
|
||||
bDone = 0;
|
||||
while (!bDone)
|
||||
{
|
||||
/* Get the next interesting non-linefeed character */
|
||||
do {
|
||||
GETCHAR()
|
||||
if (ch == '\n' || ch == '\r' || ch == '\v' || ch == '\f')
|
||||
{
|
||||
eState = StartOfLine;
|
||||
pIName = NULL;
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
switch(eState)
|
||||
{
|
||||
case StartOfLine:
|
||||
switch (ch)
|
||||
{
|
||||
case '#':
|
||||
eState = FoundHash;
|
||||
iFound = 0;
|
||||
break;
|
||||
case '/':
|
||||
GETCHAR()
|
||||
if (ch == '/')
|
||||
eState = SkipLComment;
|
||||
else if (ch == '*')
|
||||
eState = SkipComment;
|
||||
else
|
||||
eState = InLine;
|
||||
break;
|
||||
case ' ': case '\t':
|
||||
/* still: eState = StartOfLine; */
|
||||
break;
|
||||
default:
|
||||
eState = InLine;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case InLine:
|
||||
switch (ch)
|
||||
{
|
||||
case '/':
|
||||
GETCHAR()
|
||||
if (ch == '/')
|
||||
eState = SkipLComment;
|
||||
else if (ch == '*')
|
||||
eState = SkipComment;
|
||||
else
|
||||
eState = InLine;
|
||||
break;
|
||||
case '\\':
|
||||
GETCHAR()
|
||||
/* still: eState = InLine; */
|
||||
break;
|
||||
default:
|
||||
/* still: eState = InLine; */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FoundHash:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ': case '\t':
|
||||
if (iFound)
|
||||
{
|
||||
eState = InLine;
|
||||
iFound = 0;
|
||||
}
|
||||
/* else still: eState = FoundHash */
|
||||
break;
|
||||
case 'i': case 'n': case 'c': case 'l':
|
||||
case 'u': case 'd': case 'e':
|
||||
if ("include"[iFound] != ch)
|
||||
{
|
||||
eState = InLine;
|
||||
iFound = 0;
|
||||
}
|
||||
else if (ch == 'e')
|
||||
{
|
||||
eState = FoundInclude;
|
||||
pIName = NULL;
|
||||
}
|
||||
else
|
||||
iFound++;
|
||||
break;
|
||||
default:
|
||||
eState = InLine;
|
||||
}
|
||||
break;
|
||||
|
||||
case FoundInclude:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ': case '\t':
|
||||
/* still: eState = FoundInclude */
|
||||
break;
|
||||
case '<':
|
||||
if (!pIName)
|
||||
{
|
||||
pIName = pch;
|
||||
bType = 1;
|
||||
}
|
||||
else
|
||||
eState = InLine;
|
||||
break;
|
||||
case '>':
|
||||
if (!pIName)
|
||||
{
|
||||
eState = InLine;
|
||||
}
|
||||
else if (bType)
|
||||
{
|
||||
*(pch-1) = '\0';
|
||||
if (pch-1 == pIName)
|
||||
pIName = NULL;
|
||||
else
|
||||
bDone = 1;
|
||||
eState = InLine;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
if (!pIName)
|
||||
{
|
||||
pIName = pch;
|
||||
bType = 0;
|
||||
}
|
||||
else if (!bType)
|
||||
{
|
||||
*(pch-1) = '\0';
|
||||
if (pch-1 == pIName)
|
||||
pIName = NULL;
|
||||
else
|
||||
bDone = 1;
|
||||
eState = InLine;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!pIName)
|
||||
eState = InLine;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SkipComment:
|
||||
case SkipLComment:
|
||||
break;
|
||||
} /* switch (eState) */
|
||||
|
||||
/* Skip comments immediately */
|
||||
if (eState == SkipComment)
|
||||
{
|
||||
while(1) {
|
||||
do {
|
||||
GETCHAR()
|
||||
} while (ch != '*');
|
||||
GETCHAR()
|
||||
if (ch == '/')
|
||||
break;
|
||||
}
|
||||
eState = StartOfLine;
|
||||
}
|
||||
else if (eState == SkipLComment)
|
||||
{
|
||||
do {
|
||||
GETCHAR()
|
||||
} while (ch != '\n' && ch != '\r' && ch != '\v' && ch != '\f');
|
||||
eState = StartOfLine;
|
||||
}
|
||||
} /* while(!bDone) */
|
||||
|
||||
*pType = bType;
|
||||
return pIName;
|
||||
|
||||
#undef GETCHAR
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_writeflush (void)
|
||||
|
||||
/* Write out the buffer to the written makefile.
|
||||
* Return 0 on success, non-0 else (errno holds the error code then).
|
||||
*/
|
||||
|
||||
{
|
||||
if (pch > aBuffer
|
||||
&& write(fdFile2, aBuffer, (unsigned)(pch-aBuffer)) != pch-aBuffer)
|
||||
return 1;
|
||||
pch = aBuffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_writen (const char *pText, size_t len)
|
||||
|
||||
/* Append the first <len> characters of <pText> to the written file.
|
||||
* Return 0 on success, non-0 else (errno holds the error code then)
|
||||
*/
|
||||
|
||||
{
|
||||
assert(pText);
|
||||
assert(fdFile2 >= 0);
|
||||
if (pLimit-pch < (signed)len && reader_writeflush())
|
||||
return 1;
|
||||
memcpy(pch, pText, len);
|
||||
pch += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_write (const char *pText)
|
||||
|
||||
/* Append <pText> to the written file.
|
||||
* Return 0 on success, non-0 else (errno holds the error code then)
|
||||
*/
|
||||
|
||||
{
|
||||
return reader_writen(pText, strlen(pText));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_copymake (const char * pTagline)
|
||||
|
||||
/* Copy the file from fdFile to fdFile2 up to including the tagline.
|
||||
* If the tagline is not found, it is appended.
|
||||
* The tagline MUST end in a newline character!
|
||||
* Return 0 on success, non-0 on error (errno holds the error code then).
|
||||
*/
|
||||
|
||||
{
|
||||
size_t len;
|
||||
int count; /* Next charactor to compare in pTagline, or -1 if to skip
|
||||
* up to the next Newline */
|
||||
char ch;
|
||||
|
||||
|
||||
assert(pTagline);
|
||||
assert(fdFile2);
|
||||
len = strlen(pTagline);
|
||||
assert(len < 120);
|
||||
|
||||
/* Simplest case: no old makefile to copy */
|
||||
if (fdFile < 0)
|
||||
{
|
||||
strcpy(aBuffer, pTagline);
|
||||
pch = aBuffer+len;
|
||||
return 0;
|
||||
}
|
||||
if (fillbuffer())
|
||||
return 1;
|
||||
count = 0;
|
||||
|
||||
while (!END_OF_FILE() && count < (signed)len)
|
||||
{
|
||||
if (END_OF_BUF())
|
||||
{
|
||||
if (write(fdFile2, aBuffer, (unsigned)(pch-aBuffer)) != pch-aBuffer)
|
||||
return 1;
|
||||
if (fillbuffer())
|
||||
return 1;
|
||||
if (END_OF_FILE())
|
||||
break;
|
||||
}
|
||||
ch = *pch;
|
||||
if (count < 0)
|
||||
{
|
||||
if (ch == '\n')
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ch == pTagline[count])
|
||||
count++;
|
||||
else if (ch == '\n')
|
||||
count = 0;
|
||||
else
|
||||
count = -1;
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
|
||||
/* Remember the state of the Makefile read */
|
||||
if (!END_OF_FILE())
|
||||
{
|
||||
pState = (struct filestate *) malloc(sizeof(*pState)+(pLimit-pch));
|
||||
if (pState)
|
||||
{
|
||||
pState->len = pLimit-pch;
|
||||
memcpy(pState->buf, pch, (size_t)pState->len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Switch to write mode */
|
||||
pLimit = aBuffer+BUFSIZE;
|
||||
|
||||
/* Append a newline if missing */
|
||||
if (count < 0 && reader_writen("\n", 1))
|
||||
return 1;
|
||||
|
||||
/* Put the Tagline into the buffer if necessary */
|
||||
if (count < (signed)len && reader_writen(pTagline, (size_t)len))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int
|
||||
reader_copymake2 (const char * pTagline)
|
||||
|
||||
/* Copy the remainder from fdFile to fdFile2 starting with the tagline.
|
||||
* The tagline MUST end in a newline character!
|
||||
* Return 0 on success, non-0 on error (errno holds the error code then).
|
||||
*/
|
||||
|
||||
{
|
||||
size_t len;
|
||||
int count; /* Next charactor to compare in pTagline, or -1 if to skip
|
||||
* up to the next Newline */
|
||||
char ch;
|
||||
|
||||
|
||||
assert(pTagline);
|
||||
assert(fdFile);
|
||||
assert(fdFile2);
|
||||
len = strlen(pTagline);
|
||||
assert(len < 120);
|
||||
|
||||
/* Append the tagline to the file written */
|
||||
if (reader_write(pTagline) || reader_writeflush())
|
||||
return 1;
|
||||
|
||||
/* Easiest case: nothing to left copy */
|
||||
if (!pState)
|
||||
return 0;
|
||||
|
||||
/* Restore the aBuffer to the point where the reading stopped */
|
||||
pLimit = aBuffer+BUFSIZE;
|
||||
pch = pLimit-pState->len;
|
||||
memcpy(pch, pState->buf, (size_t)pState->len);
|
||||
free(pState);
|
||||
pState = NULL;
|
||||
pIName = NULL;
|
||||
|
||||
/* Fill up the buffer */
|
||||
if (END_OF_BUF() && fillbuffer())
|
||||
return 1;
|
||||
|
||||
/* Skip the Makefile read until the tagline has been found */
|
||||
count = 0;
|
||||
while (!END_OF_FILE() && count < (signed)len)
|
||||
{
|
||||
if (END_OF_BUF())
|
||||
{
|
||||
if (fillbuffer())
|
||||
return 1;
|
||||
if (END_OF_FILE())
|
||||
break;
|
||||
}
|
||||
ch = *pch;
|
||||
if (count < 0)
|
||||
{
|
||||
if (ch == '\n')
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ch == pTagline[count])
|
||||
count++;
|
||||
else if (ch == '\n')
|
||||
count = 0;
|
||||
else
|
||||
count = -1;
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
|
||||
/* Copy the remainder of the Makefile */
|
||||
do
|
||||
{
|
||||
if (!END_OF_BUF()
|
||||
&& write(fdFile2, pch, (unsigned)(pLimit-pch)) != pLimit-pch)
|
||||
return 1;
|
||||
if (!END_OF_FILE() && fillbuffer())
|
||||
return 1;
|
||||
}
|
||||
while (!END_OF_FILE());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
24
src/bin/mkdepend/reader.h
Normal file
24
src/bin/mkdepend/reader.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* $Id: reader.h 1.4 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
** Copyright (c) 1995-1998 by Lars Düning. All Rights Reserved.
|
||||
** This file is free software. For terms of use see the file LICENSE.
|
||||
**---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __READER_H__
|
||||
#define __READER_H__ 1
|
||||
|
||||
extern void reader_init (void);
|
||||
extern int reader_open (const char *);
|
||||
extern int reader_openrw (const char *, const char *);
|
||||
extern int reader_close (void);
|
||||
extern int reader_eof (void);
|
||||
extern const char * reader_get (int *);
|
||||
extern int reader_writeflush (void);
|
||||
extern int reader_writen (const char *, size_t);
|
||||
extern int reader_write (const char *);
|
||||
extern int reader_copymake (const char *);
|
||||
extern int reader_copymake2 (const char *);
|
||||
|
||||
#endif
|
146
src/bin/mkdepend/util.c
Normal file
146
src/bin/mkdepend/util.c
Normal file
@ -0,0 +1,146 @@
|
||||
/* $Id: util.c 1.2 Wed, 01 Mar 2000 21:23:27 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Useful functions.
|
||||
*
|
||||
* Copyright (c) 1999 by Lars Düning. All Rights Reserved.
|
||||
* This file is free software. For terms of use see the file LICENSE.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
char *
|
||||
util_getpath (const char * pDirtyName, char ** ppBasename)
|
||||
|
||||
/* Take the <pDirtyName> and eliminate as many '.' and '..' from it
|
||||
* as possible. Return a freshly allocated copy of the cleaned up path.
|
||||
* If ppBasename is NULL, the returned name will only contain the
|
||||
* directory parts, the filename will be dropped. If ppBasename is not
|
||||
* NULL, the returned name will contain the filename, and *ppBasename
|
||||
* will be set to point to its first character.
|
||||
*
|
||||
* Return NULL when out of memory.
|
||||
*/
|
||||
|
||||
{
|
||||
char * pPath; /* The newly created pathname */
|
||||
char * pStart; /* The first non-'/'-character of pPath */
|
||||
char * pSrc, * pDest; /* Working pointers */
|
||||
size_t oFilename; /* Offset of filename in pDirtyName */
|
||||
|
||||
assert(pDirtyName);
|
||||
|
||||
pPath = strdup(pDirtyName);
|
||||
if (!pPath)
|
||||
return NULL;
|
||||
|
||||
pStart = ('/' == *pPath) ? pPath+1 : pPath;
|
||||
|
||||
/* First scan: find the first character of the filename
|
||||
* and end the string there, leaving just the directory path.
|
||||
* But remember the offset of the filename.
|
||||
*/
|
||||
pDest = pStart; /* First character after last '/' found */
|
||||
pSrc = pStart; /* Rover */
|
||||
while ('\0' != *pSrc)
|
||||
{
|
||||
if ('/' == *pSrc++)
|
||||
pDest = pSrc;
|
||||
}
|
||||
*pDest = '\0';
|
||||
oFilename = (unsigned)(pDest - pPath);
|
||||
|
||||
/* pPath now ends in a '/', or *pStart is a '\0' */
|
||||
|
||||
/* Second scan: visit all directory parts and eliminate '.'
|
||||
* and '..' where possible.
|
||||
*/
|
||||
pDest = pStart; /* First character after last valid '/' */
|
||||
pSrc = pStart;
|
||||
|
||||
/* Skip initial '.' entries */
|
||||
while ('.' == *pSrc)
|
||||
{
|
||||
if ('/' == pSrc[1])
|
||||
{
|
||||
pSrc += 2;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
while ('\0' != *pSrc)
|
||||
{
|
||||
char ch;
|
||||
|
||||
/* Copy forward until the next '/' */
|
||||
do
|
||||
{
|
||||
ch = *pSrc++;
|
||||
*pDest++ = ch;
|
||||
} while ('/' != ch);
|
||||
|
||||
/* If a '.' follows, it might be a '.' or '..' entry */
|
||||
while ('.' == *pSrc)
|
||||
{
|
||||
pSrc++;
|
||||
|
||||
if ('/' == *pSrc)
|
||||
{
|
||||
/* Simply skip the '.' entry */
|
||||
pSrc++;
|
||||
}
|
||||
else if ('.' == pSrc[0] && '/' == pSrc[1] && pDest != pStart)
|
||||
{
|
||||
/* For a '..' entry, move pDest back one directory unless
|
||||
* it is at the start of the string
|
||||
*/
|
||||
char * pLastDest;
|
||||
|
||||
for ( pLastDest = pDest-1
|
||||
; pLastDest != pStart && '/' != pLastDest[-1]
|
||||
; pLastDest--) /* SKIP */;
|
||||
|
||||
/* Special case: if the part just unrolled is '..' itself,
|
||||
* don't do the unrolling and instead break the loop.
|
||||
*/
|
||||
if (pLastDest + 3 == pDest && pLastDest[0] == '.' && pLastDest[1] == '.')
|
||||
{
|
||||
*pDest++ = '.';
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrc += 2;
|
||||
pDest = pLastDest;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Its not a '.' or handleable '..' entry */
|
||||
*pDest++ = '.';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
/* If the caller wants to have the filename too, append it to
|
||||
* the clean directory.
|
||||
*/
|
||||
if (ppBasename)
|
||||
{
|
||||
strcpy(pDest, pDirtyName+oFilename);
|
||||
*ppBasename = pDest;
|
||||
}
|
||||
|
||||
return pPath;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
14
src/bin/mkdepend/util.h
Normal file
14
src/bin/mkdepend/util.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* $Id: util.h 1.1 Tue, 02 Feb 1999 17:57:55 -0700 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Copyright (c) 1999 by Lars Düning. All Rights Reserved.
|
||||
* This file is free software. For terms of use see the file LICENSE.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_H__
|
||||
#define __UTIL_H__ 1
|
||||
|
||||
extern char * util_getpath(const char *, char **);
|
||||
|
||||
#endif
|
38
src/bin/mkdepend/version.h
Normal file
38
src/bin/mkdepend/version.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* $Id: version.h 1.2 Sat, 24 Oct 1998 19:54:13 -0600 lars $ */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Version information for MkDepend.
|
||||
*
|
||||
* Copyright (c) 1998 by Lars Düning. All Rights Reserved.
|
||||
* This file is free software. For terms of use see the file LICENSE.
|
||||
*---------------------------------------------------------------------------
|
||||
* This macros are exported:
|
||||
*
|
||||
* VERSION: a string of the form "x.y" or "x.y.z", with z being >= 2.
|
||||
* RELEASEDATE: a string with date and time when the current version was
|
||||
* checked in.
|
||||
* PRCS_LEVEL: the internal minor version of MkDepend, used for <z>
|
||||
* in VERSION when the value is >= 2.
|
||||
*
|
||||
* The values are created by PRCS.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __VERSION_H__
|
||||
#define __VERSION_H__
|
||||
|
||||
/* $Format: "#define RELEASE_DATE \"$ReleaseDate$\""$ */
|
||||
#define RELEASE_DATE "Thu, 19 Mar 2009 11:20:00 -0100"
|
||||
|
||||
/* $Format: "#define PRCS_LEVEL $ProjectMinorVersion$"$ */
|
||||
#define PRCS_LEVEL 1
|
||||
|
||||
#if PRCS_LEVEL > 1
|
||||
/* $Format: "#define VERSION \"$ReleaseVersion$.$ProjectMinorVersion$\""$ */
|
||||
#define VERSION "1.7.1"
|
||||
#else
|
||||
/* $Format: "#define VERSION \"$ReleaseVersion$\""$ */
|
||||
#define VERSION "1.7"
|
||||
#endif
|
||||
|
||||
#endif /* __VERSION_H__ */
|
Loading…
Reference in New Issue
Block a user