aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-20 09:00:56 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-20 11:36:48 -0400
commit0780060124011b94af55830939c86cc0916be0f5 (patch)
tree883a4d0ed69862ab49e6d4bf4e19debafeb5c48c /Documentation
parentd24e473e5b2ca86d1288b9416227ccc603313d0f (diff)
perf_counter tools: add in basic glue from Git
First very raw version at having a central 'perf' command and a list of subcommands: perf top perf stat perf record perf report ... This is done by picking up Git's collection of utility functions, and hacking them to build fine in this new environment. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/perf_counter/.gitignore179
-rw-r--r--Documentation/perf_counter/Makefile1037
-rw-r--r--Documentation/perf_counter/PERF-BUILD-OPTIONS4
-rw-r--r--Documentation/perf_counter/PERF-CFLAGS1
-rw-r--r--Documentation/perf_counter/PERF-VERSION-FILE1
-rwxr-xr-xDocumentation/perf_counter/PERF-VERSION-GEN42
-rw-r--r--Documentation/perf_counter/abspath.c117
-rw-r--r--Documentation/perf_counter/alias.c77
-rw-r--r--Documentation/perf_counter/builtin-help.c463
-rw-r--r--Documentation/perf_counter/builtin-top.c1411
-rw-r--r--Documentation/perf_counter/builtin.h18
-rw-r--r--Documentation/perf_counter/cache.h97
-rw-r--r--Documentation/perf_counter/command-list.txt4
-rw-r--r--Documentation/perf_counter/config.c966
-rw-r--r--Documentation/perf_counter/ctype.c26
-rw-r--r--Documentation/perf_counter/exec_cmd.c165
-rw-r--r--Documentation/perf_counter/exec_cmd.h13
-rwxr-xr-xDocumentation/perf_counter/generate-cmdlist.sh24
-rw-r--r--Documentation/perf_counter/help.c366
-rw-r--r--Documentation/perf_counter/help.h29
-rw-r--r--Documentation/perf_counter/levenshtein.c84
-rw-r--r--Documentation/perf_counter/levenshtein.h8
-rw-r--r--Documentation/perf_counter/parse-options.c495
-rw-r--r--Documentation/perf_counter/parse-options.h172
-rw-r--r--Documentation/perf_counter/path.c392
-rw-r--r--Documentation/perf_counter/perf.c411
-rw-r--r--Documentation/perf_counter/quote.c478
-rw-r--r--Documentation/perf_counter/quote.h68
-rw-r--r--Documentation/perf_counter/run-command.c395
-rw-r--r--Documentation/perf_counter/run-command.h93
-rw-r--r--Documentation/perf_counter/strbuf.c359
-rw-r--r--Documentation/perf_counter/strbuf.h137
-rw-r--r--Documentation/perf_counter/usage.c80
-rw-r--r--Documentation/perf_counter/util.h394
-rw-r--r--Documentation/perf_counter/wrapper.c206
35 files changed, 7953 insertions, 859 deletions
diff --git a/Documentation/perf_counter/.gitignore b/Documentation/perf_counter/.gitignore
new file mode 100644
index 000000000000..41c0b20a76ce
--- /dev/null
+++ b/Documentation/perf_counter/.gitignore
@@ -0,0 +1,179 @@
1GIT-BUILD-OPTIONS
2GIT-CFLAGS
3GIT-GUI-VARS
4GIT-VERSION-FILE
5git
6git-add
7git-add--interactive
8git-am
9git-annotate
10git-apply
11git-archimport
12git-archive
13git-bisect
14git-bisect--helper
15git-blame
16git-branch
17git-bundle
18git-cat-file
19git-check-attr
20git-check-ref-format
21git-checkout
22git-checkout-index
23git-cherry
24git-cherry-pick
25git-clean
26git-clone
27git-commit
28git-commit-tree
29git-config
30git-count-objects
31git-cvsexportcommit
32git-cvsimport
33git-cvsserver
34git-daemon
35git-diff
36git-diff-files
37git-diff-index
38git-diff-tree
39git-difftool
40git-difftool--helper
41git-describe
42git-fast-export
43git-fast-import
44git-fetch
45git-fetch--tool
46git-fetch-pack
47git-filter-branch
48git-fmt-merge-msg
49git-for-each-ref
50git-format-patch
51git-fsck
52git-fsck-objects
53git-gc
54git-get-tar-commit-id
55git-grep
56git-hash-object
57git-help
58git-http-fetch
59git-http-push
60git-imap-send
61git-index-pack
62git-init
63git-init-db
64git-instaweb
65git-log
66git-lost-found
67git-ls-files
68git-ls-remote
69git-ls-tree
70git-mailinfo
71git-mailsplit
72git-merge
73git-merge-base
74git-merge-index
75git-merge-file
76git-merge-tree
77git-merge-octopus
78git-merge-one-file
79git-merge-ours
80git-merge-recursive
81git-merge-resolve
82git-merge-subtree
83git-mergetool
84git-mergetool--lib
85git-mktag
86git-mktree
87git-name-rev
88git-mv
89git-pack-redundant
90git-pack-objects
91git-pack-refs
92git-parse-remote
93git-patch-id
94git-peek-remote
95git-prune
96git-prune-packed
97git-pull
98git-push
99git-quiltimport
100git-read-tree
101git-rebase
102git-rebase--interactive
103git-receive-pack
104git-reflog
105git-relink
106git-remote
107git-repack
108git-repo-config
109git-request-pull
110git-rerere
111git-reset
112git-rev-list
113git-rev-parse
114git-revert
115git-rm
116git-send-email
117git-send-pack
118git-sh-setup
119git-shell
120git-shortlog
121git-show
122git-show-branch
123git-show-index
124git-show-ref
125git-stage
126git-stash
127git-status
128git-stripspace
129git-submodule
130git-svn
131git-symbolic-ref
132git-tag
133git-tar-tree
134git-unpack-file
135git-unpack-objects
136git-update-index
137git-update-ref
138git-update-server-info
139git-upload-archive
140git-upload-pack
141git-var
142git-verify-pack
143git-verify-tag
144git-web--browse
145git-whatchanged
146git-write-tree
147git-core-*/?*
148gitk-wish
149gitweb/gitweb.cgi
150test-chmtime
151test-ctype
152test-date
153test-delta
154test-dump-cache-tree
155test-genrandom
156test-match-trees
157test-parse-options
158test-path-utils
159test-sha1
160test-sigchain
161common-cmds.h
162*.tar.gz
163*.dsc
164*.deb
165git.spec
166*.exe
167*.[aos]
168*.py[co]
169config.mak
170autom4te.cache
171config.cache
172config.log
173config.status
174config.mak.autogen
175config.mak.append
176configure
177tags
178TAGS
179cscope*
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile
index 6e0838b03ad1..11809b943fc3 100644
--- a/Documentation/perf_counter/Makefile
+++ b/Documentation/perf_counter/Makefile
@@ -13,16 +13,9 @@ all::
13# Define NO_OPENSSL environment variable if you do not have OpenSSL. 13# Define NO_OPENSSL environment variable if you do not have OpenSSL.
14# This also implies MOZILLA_SHA1. 14# This also implies MOZILLA_SHA1.
15# 15#
16# Define NO_CURL if you do not have libcurl installed. git-http-pull and
17# git-http-push are not built, and you cannot use http:// and https://
18# transports.
19#
20# Define CURLDIR=/foo/bar if your curl header and library files are in 16# Define CURLDIR=/foo/bar if your curl header and library files are in
21# /foo/bar/include and /foo/bar/lib directories. 17# /foo/bar/include and /foo/bar/lib directories.
22# 18#
23# Define NO_EXPAT if you do not have expat installed. git-http-push is
24# not built, and you cannot push using http:// and https:// transports.
25#
26# Define EXPATDIR=/foo/bar if your expat header and library files are in 19# Define EXPATDIR=/foo/bar if your expat header and library files are in
27# /foo/bar/include and /foo/bar/lib directories. 20# /foo/bar/include and /foo/bar/lib directories.
28# 21#
@@ -40,8 +33,6 @@ all::
40# 33#
41# Define NO_MEMMEM if you don't have memmem. 34# Define NO_MEMMEM if you don't have memmem.
42# 35#
43# Define NO_STRLCPY if you don't have strlcpy.
44#
45# Define NO_STRTOUMAX if you don't have strtoumax in the C library. 36# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
46# If your compiler also does not support long long or does not have 37# If your compiler also does not support long long or does not have
47# strtoull, define NO_STRTOULL. 38# strtoull, define NO_STRTOULL.
@@ -54,7 +45,7 @@ all::
54# 45#
55# Define NO_SYS_SELECT_H if you don't have sys/select.h. 46# Define NO_SYS_SELECT_H if you don't have sys/select.h.
56# 47#
57# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link. 48# Define NO_SYMLINK_HEAD if you never want .perf/HEAD to be a symbolic link.
58# Enable it on Windows. By default, symrefs are still used. 49# Enable it on Windows. By default, symrefs are still used.
59# 50#
60# Define NO_SVN_TESTS if you want to skip time-consuming SVN interoperability 51# Define NO_SVN_TESTS if you want to skip time-consuming SVN interoperability
@@ -62,13 +53,13 @@ all::
62# but are not needed unless you plan to talk to SVN repos. 53# but are not needed unless you plan to talk to SVN repos.
63# 54#
64# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink 55# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink
65# installed in /sw, but don't want GIT to link against any libraries 56# installed in /sw, but don't want PERF to link against any libraries
66# installed there. If defined you may specify your own (or Fink's) 57# installed there. If defined you may specify your own (or Fink's)
67# include directories and library directories by defining CFLAGS 58# include directories and library directories by defining CFLAGS
68# and LDFLAGS appropriately. 59# and LDFLAGS appropriately.
69# 60#
70# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X, 61# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X,
71# have DarwinPorts installed in /opt/local, but don't want GIT to 62# have DarwinPorts installed in /opt/local, but don't want PERF to
72# link against any libraries installed there. If defined you may 63# link against any libraries installed there. If defined you may
73# specify your own (or DarwinPort's) include directories and 64# specify your own (or DarwinPort's) include directories and
74# library directories by defining CFLAGS and LDFLAGS appropriately. 65# library directories by defining CFLAGS and LDFLAGS appropriately.
@@ -120,7 +111,7 @@ all::
120# that tells runtime paths to dynamic libraries; 111# that tells runtime paths to dynamic libraries;
121# "-Wl,-rpath=/path/lib" is used instead. 112# "-Wl,-rpath=/path/lib" is used instead.
122# 113#
123# Define USE_NSEC below if you want git to care about sub-second file mtimes 114# Define USE_NSEC below if you want perf to care about sub-second file mtimes
124# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and 115# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
125# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely 116# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
126# randomly break unless your underlying filesystem supports those sub-second 117# randomly break unless your underlying filesystem supports those sub-second
@@ -132,7 +123,7 @@ all::
132# Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec" 123# Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec"
133# available. This automatically turns USE_NSEC off. 124# available. This automatically turns USE_NSEC off.
134# 125#
135# Define USE_STDEV below if you want git to care about the underlying device 126# Define USE_STDEV below if you want perf to care about the underlying device
136# change being considered an inode change from the update-index perspective. 127# change being considered an inode change from the update-index perspective.
137# 128#
138# Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks 129# Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks
@@ -150,27 +141,24 @@ all::
150# Define NO_TCLTK if you do not want Tcl/Tk GUI. 141# Define NO_TCLTK if you do not want Tcl/Tk GUI.
151# 142#
152# The TCL_PATH variable governs the location of the Tcl interpreter 143# The TCL_PATH variable governs the location of the Tcl interpreter
153# used to optimize git-gui for your system. Only used if NO_TCLTK 144# used to optimize perf-gui for your system. Only used if NO_TCLTK
154# is not set. Defaults to the bare 'tclsh'. 145# is not set. Defaults to the bare 'tclsh'.
155# 146#
156# The TCLTK_PATH variable governs the location of the Tcl/Tk interpreter. 147# The TCLTK_PATH variable governs the location of the Tcl/Tk interpreter.
157# If not set it defaults to the bare 'wish'. If it is set to the empty 148# If not set it defaults to the bare 'wish'. If it is set to the empty
158# string then NO_TCLTK will be forced (this is used by configure script). 149# string then NO_TCLTK will be forced (this is used by configure script).
159# 150#
160# Define THREADED_DELTA_SEARCH if you have pthreads and wish to exploit
161# parallel delta searching when packing objects.
162#
163# Define INTERNAL_QSORT to use Git's implementation of qsort(), which 151# Define INTERNAL_QSORT to use Git's implementation of qsort(), which
164# is a simplified version of the merge sort used in glibc. This is 152# is a simplified version of the merge sort used in glibc. This is
165# recommended if Git triggers O(n^2) behavior in your platform's qsort(). 153# recommended if Git triggers O(n^2) behavior in your platform's qsort().
166# 154#
167# Define NO_EXTERNAL_GREP if you don't want "git grep" to ever call 155# Define NO_EXTERNAL_GREP if you don't want "perf grep" to ever call
168# your external grep (e.g., if your system lacks grep, if its grep is 156# your external grep (e.g., if your system lacks grep, if its grep is
169# broken, or spawning external process is slower than built-in grep git has). 157# broken, or spawning external process is slower than built-in grep perf has).
170 158
171GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE 159PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
172 @$(SHELL_PATH) ./GIT-VERSION-GEN 160 @$(SHELL_PATH) ./PERF-VERSION-GEN
173-include GIT-VERSION-FILE 161-include PERF-VERSION-FILE
174 162
175uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 163uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
176uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') 164uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
@@ -182,20 +170,20 @@ uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
182# CFLAGS and LDFLAGS are for the users to override from the command line. 170# CFLAGS and LDFLAGS are for the users to override from the command line.
183 171
184CFLAGS = -g -O2 -Wall 172CFLAGS = -g -O2 -Wall
185LDFLAGS = 173LDFLAGS = -lpthread -lrt
186ALL_CFLAGS = $(CFLAGS) 174ALL_CFLAGS = $(CFLAGS)
187ALL_LDFLAGS = $(LDFLAGS) 175ALL_LDFLAGS = $(LDFLAGS)
188STRIP ?= strip 176STRIP ?= strip
189 177
190# Among the variables below, these: 178# Among the variables below, these:
191# gitexecdir 179# perfexecdir
192# template_dir 180# template_dir
193# mandir 181# mandir
194# infodir 182# infodir
195# htmldir 183# htmldir
196# ETC_GITCONFIG (but not sysconfdir) 184# ETC_PERFCONFIG (but not sysconfdir)
197# can be specified as a relative path some/where/else; 185# can be specified as a relative path some/where/else;
198# this is interpreted as relative to $(prefix) and "git" at 186# this is interpreted as relative to $(prefix) and "perf" at
199# runtime figures out where they are based on the path to the executable. 187# runtime figures out where they are based on the path to the executable.
200# This can help installing the suite in a relocatable way. 188# This can help installing the suite in a relocatable way.
201 189
@@ -204,38 +192,20 @@ bindir_relative = bin
204bindir = $(prefix)/$(bindir_relative) 192bindir = $(prefix)/$(bindir_relative)
205mandir = share/man 193mandir = share/man
206infodir = share/info 194infodir = share/info
207gitexecdir = libexec/git-core 195perfexecdir = libexec/perf-core
208sharedir = $(prefix)/share 196sharedir = $(prefix)/share
209template_dir = share/git-core/templates 197template_dir = share/perf-core/templates
210htmldir = share/doc/git-doc 198htmldir = share/doc/perf-doc
211ifeq ($(prefix),/usr) 199ifeq ($(prefix),/usr)
212sysconfdir = /etc 200sysconfdir = /etc
213ETC_GITCONFIG = $(sysconfdir)/gitconfig 201ETC_PERFCONFIG = $(sysconfdir)/perfconfig
214else 202else
215sysconfdir = $(prefix)/etc 203sysconfdir = $(prefix)/etc
216ETC_GITCONFIG = etc/gitconfig 204ETC_PERFCONFIG = etc/perfconfig
217endif 205endif
218lib = lib 206lib = lib
219# DESTDIR= 207# DESTDIR=
220 208
221# default configuration for gitweb
222GITWEB_CONFIG = gitweb_config.perl
223GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf
224GITWEB_HOME_LINK_STR = projects
225GITWEB_SITENAME =
226GITWEB_PROJECTROOT = /pub/git
227GITWEB_PROJECT_MAXDEPTH = 2007
228GITWEB_EXPORT_OK =
229GITWEB_STRICT_EXPORT =
230GITWEB_BASE_URL =
231GITWEB_LIST =
232GITWEB_HOMETEXT = indextext.html
233GITWEB_CSS = gitweb.css
234GITWEB_LOGO = git-logo.png
235GITWEB_FAVICON = git-favicon.png
236GITWEB_SITE_HEADER =
237GITWEB_SITE_FOOTER =
238
239export prefix bindir sharedir sysconfdir 209export prefix bindir sharedir sysconfdir
240 210
241CC = gcc 211CC = gcc
@@ -277,89 +247,46 @@ SCRIPT_PERL =
277SCRIPT_SH = 247SCRIPT_SH =
278TEST_PROGRAMS = 248TEST_PROGRAMS =
279 249
280SCRIPT_SH += git-am.sh 250#
281SCRIPT_SH += git-bisect.sh 251# No scripts right now:
282SCRIPT_SH += git-difftool--helper.sh 252#
283SCRIPT_SH += git-filter-branch.sh 253
284SCRIPT_SH += git-lost-found.sh 254# SCRIPT_SH += perf-am.sh
285SCRIPT_SH += git-merge-octopus.sh 255
286SCRIPT_SH += git-merge-one-file.sh 256#
287SCRIPT_SH += git-merge-resolve.sh 257# No Perl scripts right now:
288SCRIPT_SH += git-mergetool.sh 258#
289SCRIPT_SH += git-mergetool--lib.sh 259
290SCRIPT_SH += git-parse-remote.sh 260# SCRIPT_PERL += perf-add--interactive.perl
291SCRIPT_SH += git-pull.sh
292SCRIPT_SH += git-quiltimport.sh
293SCRIPT_SH += git-rebase--interactive.sh
294SCRIPT_SH += git-rebase.sh
295SCRIPT_SH += git-repack.sh
296SCRIPT_SH += git-request-pull.sh
297SCRIPT_SH += git-sh-setup.sh
298SCRIPT_SH += git-stash.sh
299SCRIPT_SH += git-submodule.sh
300SCRIPT_SH += git-web--browse.sh
301
302SCRIPT_PERL += git-add--interactive.perl
303SCRIPT_PERL += git-difftool.perl
304SCRIPT_PERL += git-archimport.perl
305SCRIPT_PERL += git-cvsexportcommit.perl
306SCRIPT_PERL += git-cvsimport.perl
307SCRIPT_PERL += git-cvsserver.perl
308SCRIPT_PERL += git-relink.perl
309SCRIPT_PERL += git-send-email.perl
310SCRIPT_PERL += git-svn.perl
311 261
312SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ 262SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
313 $(patsubst %.perl,%,$(SCRIPT_PERL)) \ 263 $(patsubst %.perl,%,$(SCRIPT_PERL))
314 git-instaweb
315 264
316# Empty... 265# Empty...
317EXTRA_PROGRAMS = 266EXTRA_PROGRAMS =
318 267
319# ... and all the rest that could be moved out of bindir to gitexecdir 268# ... and all the rest that could be moved out of bindir to perfexecdir
320PROGRAMS += $(EXTRA_PROGRAMS) 269PROGRAMS += $(EXTRA_PROGRAMS)
321PROGRAMS += git-fast-import$X 270
322PROGRAMS += git-hash-object$X 271#
323PROGRAMS += git-index-pack$X 272# None right now:
324PROGRAMS += git-merge-index$X 273#
325PROGRAMS += git-merge-tree$X 274# PROGRAMS += perf-fast-import$X
326PROGRAMS += git-mktag$X
327PROGRAMS += git-mktree$X
328PROGRAMS += git-pack-redundant$X
329PROGRAMS += git-patch-id$X
330PROGRAMS += git-shell$X
331PROGRAMS += git-show-index$X
332PROGRAMS += git-unpack-file$X
333PROGRAMS += git-update-server-info$X
334PROGRAMS += git-upload-pack$X
335PROGRAMS += git-var$X
336 275
337# List built-in command $C whose implementation cmd_$C() is not in 276# List built-in command $C whose implementation cmd_$C() is not in
338# builtin-$C.o but is linked in as part of some other command. 277# builtin-$C.o but is linked in as part of some other command.
339BUILT_INS += $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS)) 278BUILT_INS += $(patsubst builtin-%.o,perf-%$X,$(BUILTIN_OBJS))
340 279
341BUILT_INS += git-cherry$X 280#
342BUILT_INS += git-cherry-pick$X 281# None right now:
343BUILT_INS += git-format-patch$X 282#
344BUILT_INS += git-fsck-objects$X 283# BUILT_INS += perf-init $X
345BUILT_INS += git-get-tar-commit-id$X 284
346BUILT_INS += git-init$X 285# what 'all' will build and 'install' will install, in perfexecdir
347BUILT_INS += git-merge-subtree$X
348BUILT_INS += git-peek-remote$X
349BUILT_INS += git-repo-config$X
350BUILT_INS += git-show$X
351BUILT_INS += git-stage$X
352BUILT_INS += git-status$X
353BUILT_INS += git-whatchanged$X
354
355# what 'all' will build and 'install' will install, in gitexecdir
356ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) 286ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
357 287
358# what 'all' will build but not install in gitexecdir 288# what 'all' will build but not install in perfexecdir
359OTHER_PROGRAMS = git$X 289OTHER_PROGRAMS = perf$X
360ifndef NO_PERL
361OTHER_PROGRAMS += gitweb/gitweb.cgi
362endif
363 290
364# Set paths to tools early so that they can be used for version tests. 291# Set paths to tools early so that they can be used for version tests.
365ifndef SHELL_PATH 292ifndef SHELL_PATH
@@ -371,250 +298,34 @@ endif
371 298
372export PERL_PATH 299export PERL_PATH
373 300
374LIB_FILE=libgit.a 301LIB_FILE=libperf.a
375XDIFF_LIB=xdiff/lib.a 302
376 303LIB_H += ../../include/linux/perf_counter.h
377LIB_H += archive.h
378LIB_H += attr.h
379LIB_H += blob.h
380LIB_H += builtin.h
381LIB_H += cache.h
382LIB_H += cache-tree.h
383LIB_H += commit.h
384LIB_H += compat/cygwin.h
385LIB_H += compat/mingw.h
386LIB_H += csum-file.h
387LIB_H += decorate.h
388LIB_H += delta.h
389LIB_H += diffcore.h
390LIB_H += diff.h
391LIB_H += dir.h
392LIB_H += fsck.h
393LIB_H += git-compat-util.h
394LIB_H += graph.h
395LIB_H += grep.h
396LIB_H += hash.h
397LIB_H += help.h
398LIB_H += levenshtein.h 304LIB_H += levenshtein.h
399LIB_H += list-objects.h
400LIB_H += ll-merge.h
401LIB_H += log-tree.h
402LIB_H += mailmap.h
403LIB_H += merge-recursive.h
404LIB_H += object.h
405LIB_H += pack.h
406LIB_H += pack-refs.h
407LIB_H += pack-revindex.h
408LIB_H += parse-options.h 305LIB_H += parse-options.h
409LIB_H += patch-ids.h
410LIB_H += pkt-line.h
411LIB_H += progress.h
412LIB_H += quote.h 306LIB_H += quote.h
413LIB_H += reflog-walk.h
414LIB_H += refs.h
415LIB_H += remote.h
416LIB_H += rerere.h
417LIB_H += revision.h
418LIB_H += run-command.h
419LIB_H += sha1-lookup.h
420LIB_H += sideband.h
421LIB_H += sigchain.h
422LIB_H += strbuf.h 307LIB_H += strbuf.h
423LIB_H += string-list.h 308LIB_H += run-command.h
424LIB_H += tag.h
425LIB_H += transport.h
426LIB_H += tree.h
427LIB_H += tree-walk.h
428LIB_H += unpack-trees.h
429LIB_H += userdiff.h
430LIB_H += utf8.h
431LIB_H += wt-status.h
432 309
433LIB_OBJS += abspath.o 310LIB_OBJS += abspath.o
434LIB_OBJS += alias.o 311LIB_OBJS += alias.o
435LIB_OBJS += alloc.o
436LIB_OBJS += archive.o
437LIB_OBJS += archive-tar.o
438LIB_OBJS += archive-zip.o
439LIB_OBJS += attr.o
440LIB_OBJS += base85.o
441LIB_OBJS += bisect.o
442LIB_OBJS += blob.o
443LIB_OBJS += branch.o
444LIB_OBJS += bundle.o
445LIB_OBJS += cache-tree.o
446LIB_OBJS += color.o
447LIB_OBJS += combine-diff.o
448LIB_OBJS += commit.o
449LIB_OBJS += config.o 312LIB_OBJS += config.o
450LIB_OBJS += connect.o
451LIB_OBJS += convert.o
452LIB_OBJS += copy.o
453LIB_OBJS += csum-file.o
454LIB_OBJS += ctype.o 313LIB_OBJS += ctype.o
455LIB_OBJS += date.o
456LIB_OBJS += decorate.o
457LIB_OBJS += diffcore-break.o
458LIB_OBJS += diffcore-delta.o
459LIB_OBJS += diffcore-order.o
460LIB_OBJS += diffcore-pickaxe.o
461LIB_OBJS += diffcore-rename.o
462LIB_OBJS += diff-delta.o
463LIB_OBJS += diff-lib.o
464LIB_OBJS += diff-no-index.o
465LIB_OBJS += diff.o
466LIB_OBJS += dir.o
467LIB_OBJS += editor.o
468LIB_OBJS += entry.o
469LIB_OBJS += environment.o
470LIB_OBJS += exec_cmd.o 314LIB_OBJS += exec_cmd.o
471LIB_OBJS += fsck.o
472LIB_OBJS += graph.o
473LIB_OBJS += grep.o
474LIB_OBJS += hash.o
475LIB_OBJS += help.o 315LIB_OBJS += help.o
476LIB_OBJS += ident.o
477LIB_OBJS += levenshtein.o 316LIB_OBJS += levenshtein.o
478LIB_OBJS += list-objects.o
479LIB_OBJS += ll-merge.o
480LIB_OBJS += lockfile.o
481LIB_OBJS += log-tree.o
482LIB_OBJS += mailmap.o
483LIB_OBJS += match-trees.o
484LIB_OBJS += merge-file.o
485LIB_OBJS += merge-recursive.o
486LIB_OBJS += name-hash.o
487LIB_OBJS += object.o
488LIB_OBJS += pack-check.o
489LIB_OBJS += pack-refs.o
490LIB_OBJS += pack-revindex.o
491LIB_OBJS += pack-write.o
492LIB_OBJS += pager.o
493LIB_OBJS += parse-options.o 317LIB_OBJS += parse-options.o
494LIB_OBJS += patch-delta.o
495LIB_OBJS += patch-ids.o
496LIB_OBJS += path.o 318LIB_OBJS += path.o
497LIB_OBJS += pkt-line.o
498LIB_OBJS += preload-index.o
499LIB_OBJS += pretty.o
500LIB_OBJS += progress.o
501LIB_OBJS += quote.o
502LIB_OBJS += reachable.o
503LIB_OBJS += read-cache.o
504LIB_OBJS += reflog-walk.o
505LIB_OBJS += refs.o
506LIB_OBJS += remote.o
507LIB_OBJS += rerere.o
508LIB_OBJS += revision.o
509LIB_OBJS += run-command.o 319LIB_OBJS += run-command.o
510LIB_OBJS += server-info.o 320LIB_OBJS += quote.o
511LIB_OBJS += setup.o
512LIB_OBJS += sha1-lookup.o
513LIB_OBJS += sha1_file.o
514LIB_OBJS += sha1_name.o
515LIB_OBJS += shallow.o
516LIB_OBJS += sideband.o
517LIB_OBJS += sigchain.o
518LIB_OBJS += strbuf.o 321LIB_OBJS += strbuf.o
519LIB_OBJS += string-list.o
520LIB_OBJS += symlinks.o
521LIB_OBJS += tag.o
522LIB_OBJS += trace.o
523LIB_OBJS += transport.o
524LIB_OBJS += tree-diff.o
525LIB_OBJS += tree.o
526LIB_OBJS += tree-walk.o
527LIB_OBJS += unpack-trees.o
528LIB_OBJS += usage.o 322LIB_OBJS += usage.o
529LIB_OBJS += userdiff.o
530LIB_OBJS += utf8.o
531LIB_OBJS += walker.o
532LIB_OBJS += wrapper.o 323LIB_OBJS += wrapper.o
533LIB_OBJS += write_or_die.o 324
534LIB_OBJS += ws.o
535LIB_OBJS += wt-status.o
536LIB_OBJS += xdiff-interface.o
537
538BUILTIN_OBJS += builtin-add.o
539BUILTIN_OBJS += builtin-annotate.o
540BUILTIN_OBJS += builtin-apply.o
541BUILTIN_OBJS += builtin-archive.o
542BUILTIN_OBJS += builtin-bisect--helper.o
543BUILTIN_OBJS += builtin-blame.o
544BUILTIN_OBJS += builtin-branch.o
545BUILTIN_OBJS += builtin-bundle.o
546BUILTIN_OBJS += builtin-cat-file.o
547BUILTIN_OBJS += builtin-check-attr.o
548BUILTIN_OBJS += builtin-check-ref-format.o
549BUILTIN_OBJS += builtin-checkout-index.o
550BUILTIN_OBJS += builtin-checkout.o
551BUILTIN_OBJS += builtin-clean.o
552BUILTIN_OBJS += builtin-clone.o
553BUILTIN_OBJS += builtin-commit-tree.o
554BUILTIN_OBJS += builtin-commit.o
555BUILTIN_OBJS += builtin-config.o
556BUILTIN_OBJS += builtin-count-objects.o
557BUILTIN_OBJS += builtin-describe.o
558BUILTIN_OBJS += builtin-diff-files.o
559BUILTIN_OBJS += builtin-diff-index.o
560BUILTIN_OBJS += builtin-diff-tree.o
561BUILTIN_OBJS += builtin-diff.o
562BUILTIN_OBJS += builtin-fast-export.o
563BUILTIN_OBJS += builtin-fetch--tool.o
564BUILTIN_OBJS += builtin-fetch-pack.o
565BUILTIN_OBJS += builtin-fetch.o
566BUILTIN_OBJS += builtin-fmt-merge-msg.o
567BUILTIN_OBJS += builtin-for-each-ref.o
568BUILTIN_OBJS += builtin-fsck.o
569BUILTIN_OBJS += builtin-gc.o
570BUILTIN_OBJS += builtin-grep.o
571BUILTIN_OBJS += builtin-help.o 325BUILTIN_OBJS += builtin-help.o
572BUILTIN_OBJS += builtin-init-db.o 326BUILTIN_OBJS += builtin-top.o
573BUILTIN_OBJS += builtin-log.o 327
574BUILTIN_OBJS += builtin-ls-files.o 328PERFLIBS = $(LIB_FILE)
575BUILTIN_OBJS += builtin-ls-remote.o
576BUILTIN_OBJS += builtin-ls-tree.o
577BUILTIN_OBJS += builtin-mailinfo.o
578BUILTIN_OBJS += builtin-mailsplit.o
579BUILTIN_OBJS += builtin-merge.o
580BUILTIN_OBJS += builtin-merge-base.o
581BUILTIN_OBJS += builtin-merge-file.o
582BUILTIN_OBJS += builtin-merge-ours.o
583BUILTIN_OBJS += builtin-merge-recursive.o
584BUILTIN_OBJS += builtin-mv.o
585BUILTIN_OBJS += builtin-name-rev.o
586BUILTIN_OBJS += builtin-pack-objects.o
587BUILTIN_OBJS += builtin-pack-refs.o
588BUILTIN_OBJS += builtin-prune-packed.o
589BUILTIN_OBJS += builtin-prune.o
590BUILTIN_OBJS += builtin-push.o
591BUILTIN_OBJS += builtin-read-tree.o
592BUILTIN_OBJS += builtin-receive-pack.o
593BUILTIN_OBJS += builtin-reflog.o
594BUILTIN_OBJS += builtin-remote.o
595BUILTIN_OBJS += builtin-rerere.o
596BUILTIN_OBJS += builtin-reset.o
597BUILTIN_OBJS += builtin-rev-list.o
598BUILTIN_OBJS += builtin-rev-parse.o
599BUILTIN_OBJS += builtin-revert.o
600BUILTIN_OBJS += builtin-rm.o
601BUILTIN_OBJS += builtin-send-pack.o
602BUILTIN_OBJS += builtin-shortlog.o
603BUILTIN_OBJS += builtin-show-branch.o
604BUILTIN_OBJS += builtin-show-ref.o
605BUILTIN_OBJS += builtin-stripspace.o
606BUILTIN_OBJS += builtin-symbolic-ref.o
607BUILTIN_OBJS += builtin-tag.o
608BUILTIN_OBJS += builtin-tar-tree.o
609BUILTIN_OBJS += builtin-unpack-objects.o
610BUILTIN_OBJS += builtin-update-index.o
611BUILTIN_OBJS += builtin-update-ref.o
612BUILTIN_OBJS += builtin-upload-archive.o
613BUILTIN_OBJS += builtin-verify-pack.o
614BUILTIN_OBJS += builtin-verify-tag.o
615BUILTIN_OBJS += builtin-write-tree.o
616
617GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
618EXTLIBS = 329EXTLIBS =
619 330
620# 331#
@@ -625,221 +336,6 @@ EXTLIBS =
625# because maintaining the nesting to match is a pain. If 336# because maintaining the nesting to match is a pain. If
626# we had "elif" things would have been much nicer... 337# we had "elif" things would have been much nicer...
627 338
628ifeq ($(uname_S),Linux)
629 NO_STRLCPY = YesPlease
630 THREADED_DELTA_SEARCH = YesPlease
631endif
632ifeq ($(uname_S),GNU/kFreeBSD)
633 NO_STRLCPY = YesPlease
634 THREADED_DELTA_SEARCH = YesPlease
635endif
636ifeq ($(uname_S),UnixWare)
637 CC = cc
638 NEEDS_SOCKET = YesPlease
639 NEEDS_NSL = YesPlease
640 NEEDS_SSL_WITH_CRYPTO = YesPlease
641 NEEDS_LIBICONV = YesPlease
642 SHELL_PATH = /usr/local/bin/bash
643 NO_IPV6 = YesPlease
644 NO_HSTRERROR = YesPlease
645 BASIC_CFLAGS += -Kthread
646 BASIC_CFLAGS += -I/usr/local/include
647 BASIC_LDFLAGS += -L/usr/local/lib
648 INSTALL = ginstall
649 TAR = gtar
650 NO_STRCASESTR = YesPlease
651 NO_MEMMEM = YesPlease
652endif
653ifeq ($(uname_S),SCO_SV)
654 ifeq ($(uname_R),3.2)
655 CFLAGS = -O2
656 endif
657 ifeq ($(uname_R),5)
658 CC = cc
659 BASIC_CFLAGS += -Kthread
660 endif
661 NEEDS_SOCKET = YesPlease
662 NEEDS_NSL = YesPlease
663 NEEDS_SSL_WITH_CRYPTO = YesPlease
664 NEEDS_LIBICONV = YesPlease
665 SHELL_PATH = /usr/bin/bash
666 NO_IPV6 = YesPlease
667 NO_HSTRERROR = YesPlease
668 BASIC_CFLAGS += -I/usr/local/include
669 BASIC_LDFLAGS += -L/usr/local/lib
670 NO_STRCASESTR = YesPlease
671 NO_MEMMEM = YesPlease
672 INSTALL = ginstall
673 TAR = gtar
674endif
675ifeq ($(uname_S),Darwin)
676 NEEDS_SSL_WITH_CRYPTO = YesPlease
677 NEEDS_LIBICONV = YesPlease
678 ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
679 OLD_ICONV = UnfortunatelyYes
680 endif
681 ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2)
682 NO_STRLCPY = YesPlease
683 endif
684 NO_MEMMEM = YesPlease
685 THREADED_DELTA_SEARCH = YesPlease
686 USE_ST_TIMESPEC = YesPlease
687endif
688ifeq ($(uname_S),SunOS)
689 NEEDS_SOCKET = YesPlease
690 NEEDS_NSL = YesPlease
691 SHELL_PATH = /bin/bash
692 NO_STRCASESTR = YesPlease
693 NO_MEMMEM = YesPlease
694 NO_HSTRERROR = YesPlease
695 NO_MKDTEMP = YesPlease
696 OLD_ICONV = UnfortunatelyYes
697 ifeq ($(uname_R),5.8)
698 NO_UNSETENV = YesPlease
699 NO_SETENV = YesPlease
700 NO_C99_FORMAT = YesPlease
701 NO_STRTOUMAX = YesPlease
702 endif
703 ifeq ($(uname_R),5.9)
704 NO_UNSETENV = YesPlease
705 NO_SETENV = YesPlease
706 NO_C99_FORMAT = YesPlease
707 NO_STRTOUMAX = YesPlease
708 endif
709 INSTALL = ginstall
710 TAR = gtar
711 BASIC_CFLAGS += -D__EXTENSIONS__
712endif
713ifeq ($(uname_O),Cygwin)
714 NO_D_TYPE_IN_DIRENT = YesPlease
715 NO_D_INO_IN_DIRENT = YesPlease
716 NO_STRCASESTR = YesPlease
717 NO_MEMMEM = YesPlease
718 NO_SYMLINK_HEAD = YesPlease
719 NEEDS_LIBICONV = YesPlease
720 NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
721 NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
722 OLD_ICONV = UnfortunatelyYes
723 # There are conflicting reports about this.
724 # On some boxes NO_MMAP is needed, and not so elsewhere.
725 # Try commenting this out if you suspect MMAP is more efficient
726 NO_MMAP = YesPlease
727 NO_IPV6 = YesPlease
728 X = .exe
729endif
730ifeq ($(uname_S),FreeBSD)
731 NEEDS_LIBICONV = YesPlease
732 NO_MEMMEM = YesPlease
733 BASIC_CFLAGS += -I/usr/local/include
734 BASIC_LDFLAGS += -L/usr/local/lib
735 DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
736 USE_ST_TIMESPEC = YesPlease
737 THREADED_DELTA_SEARCH = YesPlease
738 ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
739 PTHREAD_LIBS = -pthread
740 NO_UINTMAX_T = YesPlease
741 NO_STRTOUMAX = YesPlease
742 endif
743endif
744ifeq ($(uname_S),OpenBSD)
745 NO_STRCASESTR = YesPlease
746 NO_MEMMEM = YesPlease
747 NEEDS_LIBICONV = YesPlease
748 BASIC_CFLAGS += -I/usr/local/include
749 BASIC_LDFLAGS += -L/usr/local/lib
750 THREADED_DELTA_SEARCH = YesPlease
751endif
752ifeq ($(uname_S),NetBSD)
753 ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
754 NEEDS_LIBICONV = YesPlease
755 endif
756 BASIC_CFLAGS += -I/usr/pkg/include
757 BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
758 THREADED_DELTA_SEARCH = YesPlease
759endif
760ifeq ($(uname_S),AIX)
761 NO_STRCASESTR=YesPlease
762 NO_MEMMEM = YesPlease
763 NO_MKDTEMP = YesPlease
764 NO_STRLCPY = YesPlease
765 NO_NSEC = YesPlease
766 FREAD_READS_DIRECTORIES = UnfortunatelyYes
767 INTERNAL_QSORT = UnfortunatelyYes
768 NEEDS_LIBICONV=YesPlease
769 BASIC_CFLAGS += -D_LARGE_FILES
770 ifneq ($(shell expr "$(uname_V)" : '[1234]'),1)
771 THREADED_DELTA_SEARCH = YesPlease
772 else
773 NO_PTHREADS = YesPlease
774 endif
775endif
776ifeq ($(uname_S),GNU)
777 # GNU/Hurd
778 NO_STRLCPY=YesPlease
779endif
780ifeq ($(uname_S),IRIX64)
781 NO_IPV6=YesPlease
782 NO_SETENV=YesPlease
783 NO_STRCASESTR=YesPlease
784 NO_MEMMEM = YesPlease
785 NO_STRLCPY = YesPlease
786 NO_SOCKADDR_STORAGE=YesPlease
787 SHELL_PATH=/usr/gnu/bin/bash
788 BASIC_CFLAGS += -DPATH_MAX=1024
789 # for now, build 32-bit version
790 BASIC_LDFLAGS += -L/usr/lib32
791endif
792ifeq ($(uname_S),HP-UX)
793 NO_IPV6=YesPlease
794 NO_SETENV=YesPlease
795 NO_STRCASESTR=YesPlease
796 NO_MEMMEM = YesPlease
797 NO_STRLCPY = YesPlease
798 NO_MKDTEMP = YesPlease
799 NO_UNSETENV = YesPlease
800 NO_HSTRERROR = YesPlease
801 NO_SYS_SELECT_H = YesPlease
802 SNPRINTF_RETURNS_BOGUS = YesPlease
803endif
804ifneq (,$(findstring CYGWIN,$(uname_S)))
805 COMPAT_OBJS += compat/cygwin.o
806endif
807ifneq (,$(findstring MINGW,$(uname_S)))
808 NO_PREAD = YesPlease
809 NO_OPENSSL = YesPlease
810 NO_CURL = YesPlease
811 NO_SYMLINK_HEAD = YesPlease
812 NO_IPV6 = YesPlease
813 NO_SETENV = YesPlease
814 NO_UNSETENV = YesPlease
815 NO_STRCASESTR = YesPlease
816 NO_STRLCPY = YesPlease
817 NO_MEMMEM = YesPlease
818 NO_PTHREADS = YesPlease
819 NEEDS_LIBICONV = YesPlease
820 OLD_ICONV = YesPlease
821 NO_C99_FORMAT = YesPlease
822 NO_STRTOUMAX = YesPlease
823 NO_MKDTEMP = YesPlease
824 SNPRINTF_RETURNS_BOGUS = YesPlease
825 NO_SVN_TESTS = YesPlease
826 NO_PERL_MAKEMAKER = YesPlease
827 RUNTIME_PREFIX = YesPlease
828 NO_POSIX_ONLY_PROGRAMS = YesPlease
829 NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
830 NO_NSEC = YesPlease
831 USE_WIN32_MMAP = YesPlease
832 COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
833 COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
834 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
835 COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/regex/regex.o compat/winansi.o
836 EXTLIBS += -lws2_32
837 X = .exe
838endif
839ifneq (,$(findstring arm,$(uname_M)))
840 ARM_SHA1 = YesPlease
841endif
842
843-include config.mak.autogen 339-include config.mak.autogen
844-include config.mak 340-include config.mak
845 341
@@ -869,72 +365,12 @@ ifndef CC_LD_DYNPATH
869 endif 365 endif
870endif 366endif
871 367
872ifdef NO_CURL
873 BASIC_CFLAGS += -DNO_CURL
874else
875 ifdef CURLDIR
876 # Try "-Wl,-rpath=$(CURLDIR)/$(lib)" in such a case.
877 BASIC_CFLAGS += -I$(CURLDIR)/include
878 CURL_LIBCURL = -L$(CURLDIR)/$(lib) $(CC_LD_DYNPATH)$(CURLDIR)/$(lib) -lcurl
879 else
880 CURL_LIBCURL = -lcurl
881 endif
882 BUILTIN_OBJS += builtin-http-fetch.o
883 EXTLIBS += $(CURL_LIBCURL)
884 LIB_OBJS += http.o http-walker.o
885 curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
886 ifeq "$(curl_check)" "070908"
887 ifndef NO_EXPAT
888 PROGRAMS += git-http-push$X
889 endif
890 endif
891 ifndef NO_EXPAT
892 ifdef EXPATDIR
893 BASIC_CFLAGS += -I$(EXPATDIR)/include
894 EXPAT_LIBEXPAT = -L$(EXPATDIR)/$(lib) $(CC_LD_DYNPATH)$(EXPATDIR)/$(lib) -lexpat
895 else
896 EXPAT_LIBEXPAT = -lexpat
897 endif
898 endif
899endif
900
901ifdef ZLIB_PATH 368ifdef ZLIB_PATH
902 BASIC_CFLAGS += -I$(ZLIB_PATH)/include 369 BASIC_CFLAGS += -I$(ZLIB_PATH)/include
903 EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib) 370 EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib)
904endif 371endif
905EXTLIBS += -lz 372EXTLIBS += -lz
906 373
907ifndef NO_POSIX_ONLY_PROGRAMS
908 PROGRAMS += git-daemon$X
909 PROGRAMS += git-imap-send$X
910endif
911ifndef NO_OPENSSL
912 OPENSSL_LIBSSL = -lssl
913 ifdef OPENSSLDIR
914 BASIC_CFLAGS += -I$(OPENSSLDIR)/include
915 OPENSSL_LINK = -L$(OPENSSLDIR)/$(lib) $(CC_LD_DYNPATH)$(OPENSSLDIR)/$(lib)
916 else
917 OPENSSL_LINK =
918 endif
919else
920 BASIC_CFLAGS += -DNO_OPENSSL
921 MOZILLA_SHA1 = 1
922 OPENSSL_LIBSSL =
923endif
924ifdef NEEDS_SSL_WITH_CRYPTO
925 LIB_4_CRYPTO = $(OPENSSL_LINK) -lcrypto -lssl
926else
927 LIB_4_CRYPTO = $(OPENSSL_LINK) -lcrypto
928endif
929ifdef NEEDS_LIBICONV
930 ifdef ICONVDIR
931 BASIC_CFLAGS += -I$(ICONVDIR)/include
932 ICONV_LINK = -L$(ICONVDIR)/$(lib) $(CC_LD_DYNPATH)$(ICONVDIR)/$(lib)
933 else
934 ICONV_LINK =
935 endif
936 EXTLIBS += $(ICONV_LINK) -liconv
937endif
938ifdef NEEDS_SOCKET 374ifdef NEEDS_SOCKET
939 EXTLIBS += -lsocket 375 EXTLIBS += -lsocket
940endif 376endif
@@ -977,10 +413,6 @@ ifdef NO_STRCASESTR
977 COMPAT_CFLAGS += -DNO_STRCASESTR 413 COMPAT_CFLAGS += -DNO_STRCASESTR
978 COMPAT_OBJS += compat/strcasestr.o 414 COMPAT_OBJS += compat/strcasestr.o
979endif 415endif
980ifdef NO_STRLCPY
981 COMPAT_CFLAGS += -DNO_STRLCPY
982 COMPAT_OBJS += compat/strlcpy.o
983endif
984ifdef NO_STRTOUMAX 416ifdef NO_STRTOUMAX
985 COMPAT_CFLAGS += -DNO_STRTOUMAX 417 COMPAT_CFLAGS += -DNO_STRTOUMAX
986 COMPAT_OBJS += compat/strtoumax.o 418 COMPAT_OBJS += compat/strtoumax.o
@@ -1090,17 +522,6 @@ ifdef RUNTIME_PREFIX
1090 COMPAT_CFLAGS += -DRUNTIME_PREFIX 522 COMPAT_CFLAGS += -DRUNTIME_PREFIX
1091endif 523endif
1092 524
1093ifdef NO_PTHREADS
1094 THREADED_DELTA_SEARCH =
1095 BASIC_CFLAGS += -DNO_PTHREADS
1096else
1097 EXTLIBS += $(PTHREAD_LIBS)
1098endif
1099
1100ifdef THREADED_DELTA_SEARCH
1101 BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
1102 LIB_OBJS += thread-utils.o
1103endif
1104ifdef DIR_HAS_BSD_GROUP_SEMANTICS 525ifdef DIR_HAS_BSD_GROUP_SEMANTICS
1105 COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS 526 COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
1106endif 527endif
@@ -1148,14 +569,14 @@ endif
1148# Shell quote (do not use $(call) to accommodate ancient setups); 569# Shell quote (do not use $(call) to accommodate ancient setups);
1149 570
1150SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER)) 571SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
1151ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG)) 572ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
1152 573
1153DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) 574DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
1154bindir_SQ = $(subst ','\'',$(bindir)) 575bindir_SQ = $(subst ','\'',$(bindir))
1155bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) 576bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
1156mandir_SQ = $(subst ','\'',$(mandir)) 577mandir_SQ = $(subst ','\'',$(mandir))
1157infodir_SQ = $(subst ','\'',$(infodir)) 578infodir_SQ = $(subst ','\'',$(infodir))
1158gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) 579perfexecdir_SQ = $(subst ','\'',$(perfexecdir))
1159template_dir_SQ = $(subst ','\'',$(template_dir)) 580template_dir_SQ = $(subst ','\'',$(template_dir))
1160htmldir_SQ = $(subst ','\'',$(htmldir)) 581htmldir_SQ = $(subst ','\'',$(htmldir))
1161prefix_SQ = $(subst ','\'',$(prefix)) 582prefix_SQ = $(subst ','\'',$(prefix))
@@ -1164,7 +585,7 @@ SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
1164PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) 585PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
1165TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) 586TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
1166 587
1167LIBS = $(GITLIBS) $(EXTLIBS) 588LIBS = $(PERFLIBS) $(EXTLIBS)
1168 589
1169BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \ 590BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
1170 $(COMPAT_CFLAGS) 591 $(COMPAT_CFLAGS)
@@ -1180,15 +601,15 @@ export TAR INSTALL DESTDIR SHELL_PATH
1180 601
1181SHELL = $(SHELL_PATH) 602SHELL = $(SHELL_PATH)
1182 603
1183all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS 604all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) PERF-BUILD-OPTIONS
1184ifneq (,$X) 605ifneq (,$X)
1185 $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$p' -ef '$p$X' || $(RM) '$p';) 606 $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
1186endif 607endif
1187 608
1188all:: 609all::
1189ifndef NO_TCLTK 610ifndef NO_TCLTK
1190 $(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) gitexecdir='$(gitexec_instdir_SQ)' all 611 $(QUIET_SUBDIR0)perf-gui $(QUIET_SUBDIR1) perfexecdir='$(perfexec_instdir_SQ)' all
1191 $(QUIET_SUBDIR0)gitk-git $(QUIET_SUBDIR1) all 612 $(QUIET_SUBDIR0)perfk-perf $(QUIET_SUBDIR1) all
1192endif 613endif
1193ifndef NO_PERL 614ifndef NO_PERL
1194 $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all 615 $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
@@ -1200,33 +621,33 @@ please_set_SHELL_PATH_to_a_more_modern_shell:
1200 621
1201shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell 622shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
1202 623
1203strip: $(PROGRAMS) git$X 624strip: $(PROGRAMS) perf$X
1204 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X 625 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) perf$X
1205 626
1206git.o: git.c common-cmds.h GIT-CFLAGS 627perf.o: perf.c common-cmds.h PERF-CFLAGS
1207 $(QUIET_CC)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ 628 $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \
1208 '-DGIT_HTML_PATH="$(htmldir_SQ)"' \ 629 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
1209 $(ALL_CFLAGS) -c $(filter %.c,$^) 630 $(ALL_CFLAGS) -c $(filter %.c,$^)
1210 631
1211git$X: git.o $(BUILTIN_OBJS) $(GITLIBS) 632perf$X: perf.o $(BUILTIN_OBJS) $(PERFLIBS)
1212 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \ 633 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ perf.o \
1213 $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) 634 $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
1214 635
1215builtin-help.o: builtin-help.c common-cmds.h GIT-CFLAGS 636builtin-help.o: builtin-help.c common-cmds.h PERF-CFLAGS
1216 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \ 637 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
1217 '-DGIT_HTML_PATH="$(htmldir_SQ)"' \ 638 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
1218 '-DGIT_MAN_PATH="$(mandir_SQ)"' \ 639 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
1219 '-DGIT_INFO_PATH="$(infodir_SQ)"' $< 640 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
1220 641
1221$(BUILT_INS): git$X 642$(BUILT_INS): perf$X
1222 $(QUIET_BUILT_IN)$(RM) $@ && \ 643 $(QUIET_BUILT_IN)$(RM) $@ && \
1223 ln git$X $@ 2>/dev/null || \ 644 ln perf$X $@ 2>/dev/null || \
1224 ln -s git$X $@ 2>/dev/null || \ 645 ln -s perf$X $@ 2>/dev/null || \
1225 cp git$X $@ 646 cp perf$X $@
1226 647
1227common-cmds.h: ./generate-cmdlist.sh command-list.txt 648common-cmds.h: ./generate-cmdlist.sh command-list.txt
1228 649
1229common-cmds.h: $(wildcard Documentation/git-*.txt) 650common-cmds.h: $(wildcard Documentation/perf-*.txt)
1230 $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@ 651 $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
1231 652
1232$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh 653$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
@@ -1234,152 +655,55 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
1234 sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ 655 sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
1235 -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \ 656 -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
1236 -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \ 657 -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
1237 -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ 658 -e 's/@@PERF_VERSION@@/$(PERF_VERSION)/g' \
1238 -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ 659 -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
1239 $@.sh >$@+ && \ 660 $@.sh >$@+ && \
1240 chmod +x $@+ && \ 661 chmod +x $@+ && \
1241 mv $@+ $@ 662 mv $@+ $@
1242 663
1243ifndef NO_PERL
1244$(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
1245
1246perl/perl.mak: GIT-CFLAGS perl/Makefile perl/Makefile.PL
1247 $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
1248
1249$(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
1250 $(QUIET_GEN)$(RM) $@ $@+ && \
1251 INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C perl -s --no-print-directory instlibdir` && \
1252 sed -e '1{' \
1253 -e ' s|#!.*perl|#!$(PERL_PATH_SQ)|' \
1254 -e ' h' \
1255 -e ' s=.*=use lib (split(/:/, $$ENV{GITPERLLIB} || "@@INSTLIBDIR@@"));=' \
1256 -e ' H' \
1257 -e ' x' \
1258 -e '}' \
1259 -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
1260 -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
1261 $@.perl >$@+ && \
1262 chmod +x $@+ && \
1263 mv $@+ $@
1264
1265gitweb/gitweb.cgi: gitweb/gitweb.perl
1266 $(QUIET_GEN)$(RM) $@ $@+ && \
1267 sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
1268 -e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
1269 -e 's|++GIT_BINDIR++|$(bindir)|g' \
1270 -e 's|++GITWEB_CONFIG++|$(GITWEB_CONFIG)|g' \
1271 -e 's|++GITWEB_CONFIG_SYSTEM++|$(GITWEB_CONFIG_SYSTEM)|g' \
1272 -e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \
1273 -e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \
1274 -e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \
1275 -e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \
1276 -e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \
1277 -e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \
1278 -e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \
1279 -e 's|++GITWEB_LIST++|$(GITWEB_LIST)|g' \
1280 -e 's|++GITWEB_HOMETEXT++|$(GITWEB_HOMETEXT)|g' \
1281 -e 's|++GITWEB_CSS++|$(GITWEB_CSS)|g' \
1282 -e 's|++GITWEB_LOGO++|$(GITWEB_LOGO)|g' \
1283 -e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
1284 -e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
1285 -e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
1286 $< >$@+ && \
1287 chmod +x $@+ && \
1288 mv $@+ $@
1289
1290git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
1291 $(QUIET_GEN)$(RM) $@ $@+ && \
1292 sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
1293 -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
1294 -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
1295 -e '/@@GITWEB_CGI@@/r gitweb/gitweb.cgi' \
1296 -e '/@@GITWEB_CGI@@/d' \
1297 -e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \
1298 -e '/@@GITWEB_CSS@@/d' \
1299 -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
1300 $@.sh > $@+ && \
1301 chmod +x $@+ && \
1302 mv $@+ $@
1303else # NO_PERL
1304$(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
1305 $(QUIET_GEN)$(RM) $@ $@+ && \
1306 sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
1307 -e 's|@@REASON@@|NO_PERL=$(NO_PERL)|g' \
1308 unimplemented.sh >$@+ && \
1309 chmod +x $@+ && \
1310 mv $@+ $@
1311endif # NO_PERL
1312
1313configure: configure.ac 664configure: configure.ac
1314 $(QUIET_GEN)$(RM) $@ $<+ && \ 665 $(QUIET_GEN)$(RM) $@ $<+ && \
1315 sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ 666 sed -e 's/@@PERF_VERSION@@/$(PERF_VERSION)/g' \
1316 $< > $<+ && \ 667 $< > $<+ && \
1317 autoconf -o $@ $<+ && \ 668 autoconf -o $@ $<+ && \
1318 $(RM) $<+ 669 $(RM) $<+
1319 670
1320# These can record GIT_VERSION 671# These can record PERF_VERSION
1321git.o git.spec \ 672perf.o perf.spec \
1322 $(patsubst %.sh,%,$(SCRIPT_SH)) \ 673 $(patsubst %.sh,%,$(SCRIPT_SH)) \
1323 $(patsubst %.perl,%,$(SCRIPT_PERL)) \ 674 $(patsubst %.perl,%,$(SCRIPT_PERL)) \
1324 : GIT-VERSION-FILE 675 : PERF-VERSION-FILE
1325 676
1326%.o: %.c GIT-CFLAGS 677%.o: %.c PERF-CFLAGS
1327 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< 678 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
1328%.s: %.c GIT-CFLAGS 679%.s: %.c PERF-CFLAGS
1329 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< 680 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
1330%.o: %.S 681%.o: %.S
1331 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< 682 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
1332 683
1333exec_cmd.o: exec_cmd.c GIT-CFLAGS 684exec_cmd.o: exec_cmd.c PERF-CFLAGS
1334 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \ 685 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
1335 '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \ 686 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
1336 '-DBINDIR="$(bindir_relative_SQ)"' \ 687 '-DBINDIR="$(bindir_relative_SQ)"' \
1337 '-DPREFIX="$(prefix_SQ)"' \ 688 '-DPREFIX="$(prefix_SQ)"' \
1338 $< 689 $<
1339 690
1340builtin-init-db.o: builtin-init-db.c GIT-CFLAGS 691builtin-init-db.o: builtin-init-db.c PERF-CFLAGS
1341 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $< 692 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_PERF_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
1342
1343config.o: config.c GIT-CFLAGS
1344 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' $<
1345 693
1346http.o: http.c GIT-CFLAGS 694config.o: config.c PERF-CFLAGS
1347 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $< 695 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
1348 696
1349ifdef NO_EXPAT 697perf-%$X: %.o $(PERFLIBS)
1350http-walker.o: http-walker.c http.h GIT-CFLAGS
1351 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
1352endif
1353
1354git-%$X: %.o $(GITLIBS)
1355 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 698 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
1356 699
1357git-imap-send$X: imap-send.o $(GITLIBS)
1358 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
1359 $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
1360
1361http.o http-walker.o http-push.o transport.o: http.h
1362
1363git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
1364 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
1365 $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
1366
1367$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) 700$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
1368$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) 701$(patsubst perf-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
1369builtin-revert.o wt-status.o: wt-status.h 702builtin-revert.o wt-status.o: wt-status.h
1370 703
1371$(LIB_FILE): $(LIB_OBJS) 704$(LIB_FILE): $(LIB_OBJS)
1372 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) 705 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
1373 706
1374XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
1375 xdiff/xmerge.o xdiff/xpatience.o
1376$(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
1377 xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
1378
1379$(XDIFF_LIB): $(XDIFF_OBJS)
1380 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(XDIFF_OBJS)
1381
1382
1383doc: 707doc:
1384 $(MAKE) -C Documentation all 708 $(MAKE) -C Documentation all
1385 709
@@ -1409,19 +733,19 @@ cscope:
1409 733
1410### Detect prefix changes 734### Detect prefix changes
1411TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\ 735TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\
1412 $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) 736 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
1413 737
1414GIT-CFLAGS: .FORCE-GIT-CFLAGS 738PERF-CFLAGS: .FORCE-PERF-CFLAGS
1415 @FLAGS='$(TRACK_CFLAGS)'; \ 739 @FLAGS='$(TRACK_CFLAGS)'; \
1416 if test x"$$FLAGS" != x"`cat GIT-CFLAGS 2>/dev/null`" ; then \ 740 if test x"$$FLAGS" != x"`cat PERF-CFLAGS 2>/dev/null`" ; then \
1417 echo 1>&2 " * new build flags or prefix"; \ 741 echo 1>&2 " * new build flags or prefix"; \
1418 echo "$$FLAGS" >GIT-CFLAGS; \ 742 echo "$$FLAGS" >PERF-CFLAGS; \
1419 fi 743 fi
1420 744
1421# We need to apply sq twice, once to protect from the shell 745# We need to apply sq twice, once to protect from the shell
1422# that runs GIT-BUILD-OPTIONS, and then again to protect it 746# that runs PERF-BUILD-OPTIONS, and then again to protect it
1423# and the first level quoting from the shell that runs "echo". 747# and the first level quoting from the shell that runs "echo".
1424GIT-BUILD-OPTIONS: .FORCE-GIT-BUILD-OPTIONS 748PERF-BUILD-OPTIONS: .FORCE-PERF-BUILD-OPTIONS
1425 @echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@ 749 @echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
1426 @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@ 750 @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
1427 @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@ 751 @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
@@ -1431,14 +755,14 @@ GIT-BUILD-OPTIONS: .FORCE-GIT-BUILD-OPTIONS
1431ifndef NO_TCLTK 755ifndef NO_TCLTK
1432TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)') 756TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)')
1433 757
1434GIT-GUI-VARS: .FORCE-GIT-GUI-VARS 758PERF-GUI-VARS: .FORCE-PERF-GUI-VARS
1435 @VARS='$(TRACK_VARS)'; \ 759 @VARS='$(TRACK_VARS)'; \
1436 if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \ 760 if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
1437 echo 1>&2 " * new Tcl/Tk interpreter location"; \ 761 echo 1>&2 " * new Tcl/Tk interpreter location"; \
1438 echo "$$VARS" >$@; \ 762 echo "$$VARS" >$@; \
1439 fi 763 fi
1440 764
1441.PHONY: .FORCE-GIT-GUI-VARS 765.PHONY: .FORCE-PERF-GUI-VARS
1442endif 766endif
1443 767
1444### Testing rules 768### Testing rules
@@ -1476,7 +800,7 @@ test-parse-options$X: parse-options.o
1476 800
1477.PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS)) 801.PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
1478 802
1479test-%$X: test-%.o $(GITLIBS) 803test-%$X: test-%.o $(PERFLIBS)
1480 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 804 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
1481 805
1482check-sha1:: test-sha1$X 806check-sha1:: test-sha1$X
@@ -1506,40 +830,40 @@ template_instdir = $(prefix)/$(template_dir)
1506endif 830endif
1507export template_instdir 831export template_instdir
1508 832
1509ifneq ($(filter /%,$(firstword $(gitexecdir))),) 833ifneq ($(filter /%,$(firstword $(perfexecdir))),)
1510gitexec_instdir = $(gitexecdir) 834perfexec_instdir = $(perfexecdir)
1511else 835else
1512gitexec_instdir = $(prefix)/$(gitexecdir) 836perfexec_instdir = $(prefix)/$(perfexecdir)
1513endif 837endif
1514gitexec_instdir_SQ = $(subst ','\'',$(gitexec_instdir)) 838perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
1515export gitexec_instdir 839export perfexec_instdir
1516 840
1517install: all 841install: all
1518 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 842 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
1519 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' 843 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
1520 $(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' 844 $(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
1521 $(INSTALL) git$X git-upload-pack$X git-receive-pack$X git-upload-archive$X git-shell$X git-cvsserver '$(DESTDIR_SQ)$(bindir_SQ)' 845 $(INSTALL) perf$X perf-upload-pack$X perf-receive-pack$X perf-upload-archive$X perf-shell$X perf-cvsserver '$(DESTDIR_SQ)$(bindir_SQ)'
1522 $(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install 846 $(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
1523 $(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install 847 $(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
1524ifndef NO_TCLTK 848ifndef NO_TCLTK
1525 $(MAKE) -C gitk-git install 849 $(MAKE) -C perfk-perf install
1526 $(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install 850 $(MAKE) -C perf-gui perfexecdir='$(perfexec_instdir_SQ)' install
1527endif 851endif
1528ifneq (,$X) 852ifneq (,$X)
1529 $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';) 853 $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), $(RM) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$p';)
1530endif 854endif
1531 bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \ 855 bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
1532 execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \ 856 execdir=$$(cd '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' && pwd) && \
1533 { $(RM) "$$execdir/git-add$X" && \ 857 { $(RM) "$$execdir/perf-add$X" && \
1534 ln "$$bindir/git$X" "$$execdir/git-add$X" 2>/dev/null || \ 858 ln "$$bindir/perf$X" "$$execdir/perf-add$X" 2>/dev/null || \
1535 cp "$$bindir/git$X" "$$execdir/git-add$X"; } && \ 859 cp "$$bindir/perf$X" "$$execdir/perf-add$X"; } && \
1536 { for p in $(filter-out git-add$X,$(BUILT_INS)); do \ 860 { for p in $(filter-out perf-add$X,$(BUILT_INS)); do \
1537 $(RM) "$$execdir/$$p" && \ 861 $(RM) "$$execdir/$$p" && \
1538 ln "$$execdir/git-add$X" "$$execdir/$$p" 2>/dev/null || \ 862 ln "$$execdir/perf-add$X" "$$execdir/$$p" 2>/dev/null || \
1539 ln -s "git-add$X" "$$execdir/$$p" 2>/dev/null || \ 863 ln -s "perf-add$X" "$$execdir/$$p" 2>/dev/null || \
1540 cp "$$execdir/git-add$X" "$$execdir/$$p" || exit; \ 864 cp "$$execdir/perf-add$X" "$$execdir/$$p" || exit; \
1541 done } && \ 865 done } && \
1542 ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X" 866 ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/perf-add$X"
1543 867
1544install-doc: 868install-doc:
1545 $(MAKE) -C Documentation install 869 $(MAKE) -C Documentation install
@@ -1569,31 +893,31 @@ quick-install-html:
1569 893
1570### Maintainer's dist rules 894### Maintainer's dist rules
1571 895
1572git.spec: git.spec.in 896perf.spec: perf.spec.in
1573 sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@+ 897 sed -e 's/@@VERSION@@/$(PERF_VERSION)/g' < $< > $@+
1574 mv $@+ $@ 898 mv $@+ $@
1575 899
1576GIT_TARNAME=git-$(GIT_VERSION) 900PERF_TARNAME=perf-$(PERF_VERSION)
1577dist: git.spec git-archive$(X) configure 901dist: perf.spec perf-archive$(X) configure
1578 ./git-archive --format=tar \ 902 ./perf-archive --format=tar \
1579 --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar 903 --prefix=$(PERF_TARNAME)/ HEAD^{tree} > $(PERF_TARNAME).tar
1580 @mkdir -p $(GIT_TARNAME) 904 @mkdir -p $(PERF_TARNAME)
1581 @cp git.spec configure $(GIT_TARNAME) 905 @cp perf.spec configure $(PERF_TARNAME)
1582 @echo $(GIT_VERSION) > $(GIT_TARNAME)/version 906 @echo $(PERF_VERSION) > $(PERF_TARNAME)/version
1583 @$(MAKE) -C git-gui TARDIR=../$(GIT_TARNAME)/git-gui dist-version 907 @$(MAKE) -C perf-gui TARDIR=../$(PERF_TARNAME)/perf-gui dist-version
1584 $(TAR) rf $(GIT_TARNAME).tar \ 908 $(TAR) rf $(PERF_TARNAME).tar \
1585 $(GIT_TARNAME)/git.spec \ 909 $(PERF_TARNAME)/perf.spec \
1586 $(GIT_TARNAME)/configure \ 910 $(PERF_TARNAME)/configure \
1587 $(GIT_TARNAME)/version \ 911 $(PERF_TARNAME)/version \
1588 $(GIT_TARNAME)/git-gui/version 912 $(PERF_TARNAME)/perf-gui/version
1589 @$(RM) -r $(GIT_TARNAME) 913 @$(RM) -r $(PERF_TARNAME)
1590 gzip -f -9 $(GIT_TARNAME).tar 914 gzip -f -9 $(PERF_TARNAME).tar
1591 915
1592rpm: dist 916rpm: dist
1593 $(RPMBUILD) -ta $(GIT_TARNAME).tar.gz 917 $(RPMBUILD) -ta $(PERF_TARNAME).tar.gz
1594 918
1595htmldocs = git-htmldocs-$(GIT_VERSION) 919htmldocs = perf-htmldocs-$(PERF_VERSION)
1596manpages = git-manpages-$(GIT_VERSION) 920manpages = perf-manpages-$(PERF_VERSION)
1597dist-doc: 921dist-doc:
1598 $(RM) -r .doc-tmp-dir 922 $(RM) -r .doc-tmp-dir
1599 mkdir .doc-tmp-dir 923 mkdir .doc-tmp-dir
@@ -1618,51 +942,46 @@ distclean: clean
1618 $(RM) configure 942 $(RM) configure
1619 943
1620clean: 944clean:
1621 $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \ 945 $(RM) *.o $(LIB_FILE)
1622 $(LIB_FILE) $(XDIFF_LIB) 946 $(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X
1623 $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
1624 $(RM) $(TEST_PROGRAMS) 947 $(RM) $(TEST_PROGRAMS)
1625 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope* 948 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
1626 $(RM) -r autom4te.cache 949 $(RM) -r autom4te.cache
1627 $(RM) config.log config.mak.autogen config.mak.append config.status config.cache 950 $(RM) config.log config.mak.autogen config.mak.append config.status config.cache
1628 $(RM) -r $(GIT_TARNAME) .doc-tmp-dir 951 $(RM) -r $(PERF_TARNAME) .doc-tmp-dir
1629 $(RM) $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz 952 $(RM) $(PERF_TARNAME).tar.gz perf-core_$(PERF_VERSION)-*.tar.gz
1630 $(RM) $(htmldocs).tar.gz $(manpages).tar.gz 953 $(RM) $(htmldocs).tar.gz $(manpages).tar.gz
1631 $(MAKE) -C Documentation/ clean 954 $(MAKE) -C Documentation/ clean
1632ifndef NO_PERL
1633 $(RM) gitweb/gitweb.cgi
1634 $(MAKE) -C perl clean
1635endif
1636 $(MAKE) -C templates/ clean 955 $(MAKE) -C templates/ clean
1637 $(MAKE) -C t/ clean 956 $(MAKE) -C t/ clean
1638ifndef NO_TCLTK 957ifndef NO_TCLTK
1639 $(MAKE) -C gitk-git clean 958 $(MAKE) -C perfk-perf clean
1640 $(MAKE) -C git-gui clean 959 $(MAKE) -C perf-gui clean
1641endif 960endif
1642 $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS 961 $(RM) PERF-VERSION-FILE PERF-CFLAGS PERF-GUI-VARS PERF-BUILD-OPTIONS
1643 962
1644.PHONY: all install clean strip 963.PHONY: all install clean strip
1645.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 964.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
1646.PHONY: .FORCE-GIT-VERSION-FILE TAGS tags cscope .FORCE-GIT-CFLAGS 965.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
1647.PHONY: .FORCE-GIT-BUILD-OPTIONS 966.PHONY: .FORCE-PERF-BUILD-OPTIONS
1648 967
1649### Check documentation 968### Check documentation
1650# 969#
1651check-docs:: 970check-docs::
1652 @(for v in $(ALL_PROGRAMS) $(BUILT_INS) git gitk; \ 971 @(for v in $(ALL_PROGRAMS) $(BUILT_INS) perf perfk; \
1653 do \ 972 do \
1654 case "$$v" in \ 973 case "$$v" in \
1655 git-merge-octopus | git-merge-ours | git-merge-recursive | \ 974 perf-merge-octopus | perf-merge-ours | perf-merge-recursive | \
1656 git-merge-resolve | git-merge-subtree | \ 975 perf-merge-resolve | perf-merge-subtree | \
1657 git-fsck-objects | git-init-db | \ 976 perf-fsck-objects | perf-init-db | \
1658 git-?*--?* ) continue ;; \ 977 perf-?*--?* ) continue ;; \
1659 esac ; \ 978 esac ; \
1660 test -f "Documentation/$$v.txt" || \ 979 test -f "Documentation/$$v.txt" || \
1661 echo "no doc: $$v"; \ 980 echo "no doc: $$v"; \
1662 sed -e '/^#/d' command-list.txt | \ 981 sed -e '/^#/d' command-list.txt | \
1663 grep -q "^$$v[ ]" || \ 982 grep -q "^$$v[ ]" || \
1664 case "$$v" in \ 983 case "$$v" in \
1665 git) ;; \ 984 perf) ;; \
1666 *) echo "no link: $$v";; \ 985 *) echo "no link: $$v";; \
1667 esac ; \ 986 esac ; \
1668 done; \ 987 done; \
@@ -1670,37 +989,37 @@ check-docs::
1670 sed -e '/^#/d' \ 989 sed -e '/^#/d' \
1671 -e 's/[ ].*//' \ 990 -e 's/[ ].*//' \
1672 -e 's/^/listed /' command-list.txt; \ 991 -e 's/^/listed /' command-list.txt; \
1673 ls -1 Documentation/git*txt | \ 992 ls -1 Documentation/perf*txt | \
1674 sed -e 's|Documentation/|documented |' \ 993 sed -e 's|Documentation/|documented |' \
1675 -e 's/\.txt//'; \ 994 -e 's/\.txt//'; \
1676 ) | while read how cmd; \ 995 ) | while read how cmd; \
1677 do \ 996 do \
1678 case "$$how,$$cmd" in \ 997 case "$$how,$$cmd" in \
1679 *,git-citool | \ 998 *,perf-citool | \
1680 *,git-gui | \ 999 *,perf-gui | \
1681 *,git-help | \ 1000 *,perf-help | \
1682 documented,gitattributes | \ 1001 documented,perfattributes | \
1683 documented,gitignore | \ 1002 documented,perfignore | \
1684 documented,gitmodules | \ 1003 documented,perfmodules | \
1685 documented,gitcli | \ 1004 documented,perfcli | \
1686 documented,git-tools | \ 1005 documented,perf-tools | \
1687 documented,gitcore-tutorial | \ 1006 documented,perfcore-tutorial | \
1688 documented,gitcvs-migration | \ 1007 documented,perfcvs-migration | \
1689 documented,gitdiffcore | \ 1008 documented,perfdiffcore | \
1690 documented,gitglossary | \ 1009 documented,perfglossary | \
1691 documented,githooks | \ 1010 documented,perfhooks | \
1692 documented,gitrepository-layout | \ 1011 documented,perfrepository-layout | \
1693 documented,gittutorial | \ 1012 documented,perftutorial | \
1694 documented,gittutorial-2 | \ 1013 documented,perftutorial-2 | \
1695 sentinel,not,matching,is,ok ) continue ;; \ 1014 sentinel,not,matching,is,ok ) continue ;; \
1696 esac; \ 1015 esac; \
1697 case " $(ALL_PROGRAMS) $(BUILT_INS) git gitk " in \ 1016 case " $(ALL_PROGRAMS) $(BUILT_INS) perf perfk " in \
1698 *" $$cmd "*) ;; \ 1017 *" $$cmd "*) ;; \
1699 *) echo "removed but $$how: $$cmd" ;; \ 1018 *) echo "removed but $$how: $$cmd" ;; \
1700 esac; \ 1019 esac; \
1701 done ) | sort 1020 done ) | sort
1702 1021
1703### Make sure built-ins do not have dups and listed in git.c 1022### Make sure built-ins do not have dups and listed in perf.c
1704# 1023#
1705check-builtins:: 1024check-builtins::
1706 ./check-builtins.sh 1025 ./check-builtins.sh
diff --git a/Documentation/perf_counter/PERF-BUILD-OPTIONS b/Documentation/perf_counter/PERF-BUILD-OPTIONS
new file mode 100644
index 000000000000..46d8d6ceb2f4
--- /dev/null
+++ b/Documentation/perf_counter/PERF-BUILD-OPTIONS
@@ -0,0 +1,4 @@
1SHELL_PATH='/bin/sh'
2TAR='tar'
3NO_CURL=''
4NO_PERL=''
diff --git a/Documentation/perf_counter/PERF-CFLAGS b/Documentation/perf_counter/PERF-CFLAGS
new file mode 100644
index 000000000000..f24906ca688d
--- /dev/null
+++ b/Documentation/perf_counter/PERF-CFLAGS
@@ -0,0 +1 @@
-g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>' : /home/mingo/bin:libexec/perf-core:share/perf-core/templates:/home/mingo
diff --git a/Documentation/perf_counter/PERF-VERSION-FILE b/Documentation/perf_counter/PERF-VERSION-FILE
new file mode 100644
index 000000000000..328e244c0c81
--- /dev/null
+++ b/Documentation/perf_counter/PERF-VERSION-FILE
@@ -0,0 +1 @@
PERF_VERSION = 0.0.1.PERF
diff --git a/Documentation/perf_counter/PERF-VERSION-GEN b/Documentation/perf_counter/PERF-VERSION-GEN
new file mode 100755
index 000000000000..c561d1538c03
--- /dev/null
+++ b/Documentation/perf_counter/PERF-VERSION-GEN
@@ -0,0 +1,42 @@
1#!/bin/sh
2
3GVF=PERF-VERSION-FILE
4DEF_VER=v0.0.1.PERF
5
6LF='
7'
8
9# First see if there is a version file (included in release tarballs),
10# then try git-describe, then default.
11if test -f version
12then
13 VN=$(cat version) || VN="$DEF_VER"
14elif test -d .git -o -f .git &&
15 VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
16 case "$VN" in
17 *$LF*) (exit 1) ;;
18 v[0-9]*)
19 git update-index -q --refresh
20 test -z "$(git diff-index --name-only HEAD --)" ||
21 VN="$VN-dirty" ;;
22 esac
23then
24 VN=$(echo "$VN" | sed -e 's/-/./g');
25else
26 VN="$DEF_VER"
27fi
28
29VN=$(expr "$VN" : v*'\(.*\)')
30
31if test -r $GVF
32then
33 VC=$(sed -e 's/^PERF_VERSION = //' <$GVF)
34else
35 VC=unset
36fi
37test "$VN" = "$VC" || {
38 echo >&2 "PERF_VERSION = $VN"
39 echo "PERF_VERSION = $VN" >$GVF
40}
41
42
diff --git a/Documentation/perf_counter/abspath.c b/Documentation/perf_counter/abspath.c
new file mode 100644
index 000000000000..649f34f83365
--- /dev/null
+++ b/Documentation/perf_counter/abspath.c
@@ -0,0 +1,117 @@
1#include "cache.h"
2
3/*
4 * Do not use this for inspecting *tracked* content. When path is a
5 * symlink to a directory, we do not want to say it is a directory when
6 * dealing with tracked content in the working tree.
7 */
8int is_directory(const char *path)
9{
10 struct stat st;
11 return (!stat(path, &st) && S_ISDIR(st.st_mode));
12}
13
14/* We allow "recursive" symbolic links. Only within reason, though. */
15#define MAXDEPTH 5
16
17const char *make_absolute_path(const char *path)
18{
19 static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
20 char cwd[1024] = "";
21 int buf_index = 1, len;
22
23 int depth = MAXDEPTH;
24 char *last_elem = NULL;
25 struct stat st;
26
27 if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
28 die ("Too long path: %.*s", 60, path);
29
30 while (depth--) {
31 if (!is_directory(buf)) {
32 char *last_slash = strrchr(buf, '/');
33 if (last_slash) {
34 *last_slash = '\0';
35 last_elem = xstrdup(last_slash + 1);
36 } else {
37 last_elem = xstrdup(buf);
38 *buf = '\0';
39 }
40 }
41
42 if (*buf) {
43 if (!*cwd && !getcwd(cwd, sizeof(cwd)))
44 die ("Could not get current working directory");
45
46 if (chdir(buf))
47 die ("Could not switch to '%s'", buf);
48 }
49 if (!getcwd(buf, PATH_MAX))
50 die ("Could not get current working directory");
51
52 if (last_elem) {
53 int len = strlen(buf);
54 if (len + strlen(last_elem) + 2 > PATH_MAX)
55 die ("Too long path name: '%s/%s'",
56 buf, last_elem);
57 buf[len] = '/';
58 strcpy(buf + len + 1, last_elem);
59 free(last_elem);
60 last_elem = NULL;
61 }
62
63 if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
64 len = readlink(buf, next_buf, PATH_MAX);
65 if (len < 0)
66 die ("Invalid symlink: %s", buf);
67 if (PATH_MAX <= len)
68 die("symbolic link too long: %s", buf);
69 next_buf[len] = '\0';
70 buf = next_buf;
71 buf_index = 1 - buf_index;
72 next_buf = bufs[buf_index];
73 } else
74 break;
75 }
76
77 if (*cwd && chdir(cwd))
78 die ("Could not change back to '%s'", cwd);
79
80 return buf;
81}
82
83static const char *get_pwd_cwd(void)
84{
85 static char cwd[PATH_MAX + 1];
86 char *pwd;
87 struct stat cwd_stat, pwd_stat;
88 if (getcwd(cwd, PATH_MAX) == NULL)
89 return NULL;
90 pwd = getenv("PWD");
91 if (pwd && strcmp(pwd, cwd)) {
92 stat(cwd, &cwd_stat);
93 if (!stat(pwd, &pwd_stat) &&
94 pwd_stat.st_dev == cwd_stat.st_dev &&
95 pwd_stat.st_ino == cwd_stat.st_ino) {
96 strlcpy(cwd, pwd, PATH_MAX);
97 }
98 }
99 return cwd;
100}
101
102const char *make_nonrelative_path(const char *path)
103{
104 static char buf[PATH_MAX + 1];
105
106 if (is_absolute_path(path)) {
107 if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
108 die("Too long path: %.*s", 60, path);
109 } else {
110 const char *cwd = get_pwd_cwd();
111 if (!cwd)
112 die("Cannot determine the current working directory");
113 if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
114 die("Too long path: %.*s", 60, path);
115 }
116 return buf;
117}
diff --git a/Documentation/perf_counter/alias.c b/Documentation/perf_counter/alias.c
new file mode 100644
index 000000000000..9b3dd2b428df
--- /dev/null
+++ b/Documentation/perf_counter/alias.c
@@ -0,0 +1,77 @@
1#include "cache.h"
2
3static const char *alias_key;
4static char *alias_val;
5
6static int alias_lookup_cb(const char *k, const char *v, void *cb)
7{
8 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
9 if (!v)
10 return config_error_nonbool(k);
11 alias_val = strdup(v);
12 return 0;
13 }
14 return 0;
15}
16
17char *alias_lookup(const char *alias)
18{
19 alias_key = alias;
20 alias_val = NULL;
21 perf_config(alias_lookup_cb, NULL);
22 return alias_val;
23}
24
25int split_cmdline(char *cmdline, const char ***argv)
26{
27 int src, dst, count = 0, size = 16;
28 char quoted = 0;
29
30 *argv = malloc(sizeof(char*) * size);
31
32 /* split alias_string */
33 (*argv)[count++] = cmdline;
34 for (src = dst = 0; cmdline[src];) {
35 char c = cmdline[src];
36 if (!quoted && isspace(c)) {
37 cmdline[dst++] = 0;
38 while (cmdline[++src]
39 && isspace(cmdline[src]))
40 ; /* skip */
41 if (count >= size) {
42 size += 16;
43 *argv = realloc(*argv, sizeof(char*) * size);
44 }
45 (*argv)[count++] = cmdline + dst;
46 } else if (!quoted && (c == '\'' || c == '"')) {
47 quoted = c;
48 src++;
49 } else if (c == quoted) {
50 quoted = 0;
51 src++;
52 } else {
53 if (c == '\\' && quoted != '\'') {
54 src++;
55 c = cmdline[src];
56 if (!c) {
57 free(*argv);
58 *argv = NULL;
59 return error("cmdline ends with \\");
60 }
61 }
62 cmdline[dst++] = c;
63 src++;
64 }
65 }
66
67 cmdline[dst] = 0;
68
69 if (quoted) {
70 free(*argv);
71 *argv = NULL;
72 return error("unclosed quote");
73 }
74
75 return count;
76}
77
diff --git a/Documentation/perf_counter/builtin-help.c b/Documentation/perf_counter/builtin-help.c
new file mode 100644
index 000000000000..125fcc2f4901
--- /dev/null
+++ b/Documentation/perf_counter/builtin-help.c
@@ -0,0 +1,463 @@
1/*
2 * builtin-help.c
3 *
4 * Builtin help command
5 */
6#include "cache.h"
7#include "builtin.h"
8#include "exec_cmd.h"
9#include "common-cmds.h"
10#include "parse-options.h"
11#include "run-command.h"
12#include "help.h"
13
14static struct man_viewer_list {
15 struct man_viewer_list *next;
16 char name[FLEX_ARRAY];
17} *man_viewer_list;
18
19static struct man_viewer_info_list {
20 struct man_viewer_info_list *next;
21 const char *info;
22 char name[FLEX_ARRAY];
23} *man_viewer_info_list;
24
25enum help_format {
26 HELP_FORMAT_MAN,
27 HELP_FORMAT_INFO,
28 HELP_FORMAT_WEB,
29};
30
31static int show_all = 0;
32static enum help_format help_format = HELP_FORMAT_MAN;
33static struct option builtin_help_options[] = {
34 OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
35 OPT_SET_INT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
36 OPT_SET_INT('w', "web", &help_format, "show manual in web browser",
37 HELP_FORMAT_WEB),
38 OPT_SET_INT('i', "info", &help_format, "show info page",
39 HELP_FORMAT_INFO),
40 OPT_END(),
41};
42
43static const char * const builtin_help_usage[] = {
44 "perf help [--all] [--man|--web|--info] [command]",
45 NULL
46};
47
48static enum help_format parse_help_format(const char *format)
49{
50 if (!strcmp(format, "man"))
51 return HELP_FORMAT_MAN;
52 if (!strcmp(format, "info"))
53 return HELP_FORMAT_INFO;
54 if (!strcmp(format, "web") || !strcmp(format, "html"))
55 return HELP_FORMAT_WEB;
56 die("unrecognized help format '%s'", format);
57}
58
59static const char *get_man_viewer_info(const char *name)
60{
61 struct man_viewer_info_list *viewer;
62
63 for (viewer = man_viewer_info_list; viewer; viewer = viewer->next)
64 {
65 if (!strcasecmp(name, viewer->name))
66 return viewer->info;
67 }
68 return NULL;
69}
70
71static int check_emacsclient_version(void)
72{
73 struct strbuf buffer = STRBUF_INIT;
74 struct child_process ec_process;
75 const char *argv_ec[] = { "emacsclient", "--version", NULL };
76 int version;
77
78 /* emacsclient prints its version number on stderr */
79 memset(&ec_process, 0, sizeof(ec_process));
80 ec_process.argv = argv_ec;
81 ec_process.err = -1;
82 ec_process.stdout_to_stderr = 1;
83 if (start_command(&ec_process)) {
84 fprintf(stderr, "Failed to start emacsclient.\n");
85 return -1;
86 }
87 strbuf_read(&buffer, ec_process.err, 20);
88 close(ec_process.err);
89
90 /*
91 * Don't bother checking return value, because "emacsclient --version"
92 * seems to always exits with code 1.
93 */
94 finish_command(&ec_process);
95
96 if (prefixcmp(buffer.buf, "emacsclient")) {
97 fprintf(stderr, "Failed to parse emacsclient version.\n");
98 strbuf_release(&buffer);
99 return -1;
100 }
101
102 strbuf_remove(&buffer, 0, strlen("emacsclient"));
103 version = atoi(buffer.buf);
104
105 if (version < 22) {
106 fprintf(stderr,
107 "emacsclient version '%d' too old (< 22).\n",
108 version);
109 strbuf_release(&buffer);
110 return -1;
111 }
112
113 strbuf_release(&buffer);
114 return 0;
115}
116
117static void exec_woman_emacs(const char* path, const char *page)
118{
119 if (!check_emacsclient_version()) {
120 /* This works only with emacsclient version >= 22. */
121 struct strbuf man_page = STRBUF_INIT;
122
123 if (!path)
124 path = "emacsclient";
125 strbuf_addf(&man_page, "(woman \"%s\")", page);
126 execlp(path, "emacsclient", "-e", man_page.buf, NULL);
127 warning("failed to exec '%s': %s", path, strerror(errno));
128 }
129}
130
131static void exec_man_konqueror(const char* path, const char *page)
132{
133 const char *display = getenv("DISPLAY");
134 if (display && *display) {
135 struct strbuf man_page = STRBUF_INIT;
136 const char *filename = "kfmclient";
137
138 /* It's simpler to launch konqueror using kfmclient. */
139 if (path) {
140 const char *file = strrchr(path, '/');
141 if (file && !strcmp(file + 1, "konqueror")) {
142 char *new = strdup(path);
143 char *dest = strrchr(new, '/');
144
145 /* strlen("konqueror") == strlen("kfmclient") */
146 strcpy(dest + 1, "kfmclient");
147 path = new;
148 }
149 if (file)
150 filename = file;
151 } else
152 path = "kfmclient";
153 strbuf_addf(&man_page, "man:%s(1)", page);
154 execlp(path, filename, "newTab", man_page.buf, NULL);
155 warning("failed to exec '%s': %s", path, strerror(errno));
156 }
157}
158
159static void exec_man_man(const char* path, const char *page)
160{
161 if (!path)
162 path = "man";
163 execlp(path, "man", page, NULL);
164 warning("failed to exec '%s': %s", path, strerror(errno));
165}
166
167static void exec_man_cmd(const char *cmd, const char *page)
168{
169 struct strbuf shell_cmd = STRBUF_INIT;
170 strbuf_addf(&shell_cmd, "%s %s", cmd, page);
171 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL);
172 warning("failed to exec '%s': %s", cmd, strerror(errno));
173}
174
175static void add_man_viewer(const char *name)
176{
177 struct man_viewer_list **p = &man_viewer_list;
178 size_t len = strlen(name);
179
180 while (*p)
181 p = &((*p)->next);
182 *p = calloc(1, (sizeof(**p) + len + 1));
183 strncpy((*p)->name, name, len);
184}
185
186static int supported_man_viewer(const char *name, size_t len)
187{
188 return (!strncasecmp("man", name, len) ||
189 !strncasecmp("woman", name, len) ||
190 !strncasecmp("konqueror", name, len));
191}
192
193static void do_add_man_viewer_info(const char *name,
194 size_t len,
195 const char *value)
196{
197 struct man_viewer_info_list *new = calloc(1, sizeof(*new) + len + 1);
198
199 strncpy(new->name, name, len);
200 new->info = strdup(value);
201 new->next = man_viewer_info_list;
202 man_viewer_info_list = new;
203}
204
205static int add_man_viewer_path(const char *name,
206 size_t len,
207 const char *value)
208{
209 if (supported_man_viewer(name, len))
210 do_add_man_viewer_info(name, len, value);
211 else
212 warning("'%s': path for unsupported man viewer.\n"
213 "Please consider using 'man.<tool>.cmd' instead.",
214 name);
215
216 return 0;
217}
218
219static int add_man_viewer_cmd(const char *name,
220 size_t len,
221 const char *value)
222{
223 if (supported_man_viewer(name, len))
224 warning("'%s': cmd for supported man viewer.\n"
225 "Please consider using 'man.<tool>.path' instead.",
226 name);
227 else
228 do_add_man_viewer_info(name, len, value);
229
230 return 0;
231}
232
233static int add_man_viewer_info(const char *var, const char *value)
234{
235 const char *name = var + 4;
236 const char *subkey = strrchr(name, '.');
237
238 if (!subkey)
239 return error("Config with no key for man viewer: %s", name);
240
241 if (!strcmp(subkey, ".path")) {
242 if (!value)
243 return config_error_nonbool(var);
244 return add_man_viewer_path(name, subkey - name, value);
245 }
246 if (!strcmp(subkey, ".cmd")) {
247 if (!value)
248 return config_error_nonbool(var);
249 return add_man_viewer_cmd(name, subkey - name, value);
250 }
251
252 warning("'%s': unsupported man viewer sub key.", subkey);
253 return 0;
254}
255
256static int perf_help_config(const char *var, const char *value, void *cb)
257{
258 if (!strcmp(var, "help.format")) {
259 if (!value)
260 return config_error_nonbool(var);
261 help_format = parse_help_format(value);
262 return 0;
263 }
264 if (!strcmp(var, "man.viewer")) {
265 if (!value)
266 return config_error_nonbool(var);
267 add_man_viewer(value);
268 return 0;
269 }
270 if (!prefixcmp(var, "man."))
271 return add_man_viewer_info(var, value);
272
273 return perf_default_config(var, value, cb);
274}
275
276static struct cmdnames main_cmds, other_cmds;
277
278void list_common_cmds_help(void)
279{
280 int i, longest = 0;
281
282 for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
283 if (longest < strlen(common_cmds[i].name))
284 longest = strlen(common_cmds[i].name);
285 }
286
287 puts("The most commonly used perf commands are:");
288 for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
289 printf(" %s ", common_cmds[i].name);
290 mput_char(' ', longest - strlen(common_cmds[i].name));
291 puts(common_cmds[i].help);
292 }
293}
294
295static int is_perf_command(const char *s)
296{
297 return is_in_cmdlist(&main_cmds, s) ||
298 is_in_cmdlist(&other_cmds, s);
299}
300
301static const char *prepend(const char *prefix, const char *cmd)
302{
303 size_t pre_len = strlen(prefix);
304 size_t cmd_len = strlen(cmd);
305 char *p = malloc(pre_len + cmd_len + 1);
306 memcpy(p, prefix, pre_len);
307 strcpy(p + pre_len, cmd);
308 return p;
309}
310
311static const char *cmd_to_page(const char *perf_cmd)
312{
313 if (!perf_cmd)
314 return "perf";
315 else if (!prefixcmp(perf_cmd, "perf"))
316 return perf_cmd;
317 else if (is_perf_command(perf_cmd))
318 return prepend("perf-", perf_cmd);
319 else
320 return prepend("perf", perf_cmd);
321}
322
323static void setup_man_path(void)
324{
325 struct strbuf new_path = STRBUF_INIT;
326 const char *old_path = getenv("MANPATH");
327
328 /* We should always put ':' after our path. If there is no
329 * old_path, the ':' at the end will let 'man' to try
330 * system-wide paths after ours to find the manual page. If
331 * there is old_path, we need ':' as delimiter. */
332 strbuf_addstr(&new_path, system_path(PERF_MAN_PATH));
333 strbuf_addch(&new_path, ':');
334 if (old_path)
335 strbuf_addstr(&new_path, old_path);
336
337 setenv("MANPATH", new_path.buf, 1);
338
339 strbuf_release(&new_path);
340}
341
342static void exec_viewer(const char *name, const char *page)
343{
344 const char *info = get_man_viewer_info(name);
345
346 if (!strcasecmp(name, "man"))
347 exec_man_man(info, page);
348 else if (!strcasecmp(name, "woman"))
349 exec_woman_emacs(info, page);
350 else if (!strcasecmp(name, "konqueror"))
351 exec_man_konqueror(info, page);
352 else if (info)
353 exec_man_cmd(info, page);
354 else
355 warning("'%s': unknown man viewer.", name);
356}
357
358static void show_man_page(const char *perf_cmd)
359{
360 struct man_viewer_list *viewer;
361 const char *page = cmd_to_page(perf_cmd);
362 const char *fallback = getenv("PERF_MAN_VIEWER");
363
364 setup_man_path();
365 for (viewer = man_viewer_list; viewer; viewer = viewer->next)
366 {
367 exec_viewer(viewer->name, page); /* will return when unable */
368 }
369 if (fallback)
370 exec_viewer(fallback, page);
371 exec_viewer("man", page);
372 die("no man viewer handled the request");
373}
374
375static void show_info_page(const char *perf_cmd)
376{
377 const char *page = cmd_to_page(perf_cmd);
378 setenv("INFOPATH", system_path(PERF_INFO_PATH), 1);
379 execlp("info", "info", "perfman", page, NULL);
380}
381
382static void get_html_page_path(struct strbuf *page_path, const char *page)
383{
384 struct stat st;
385 const char *html_path = system_path(PERF_HTML_PATH);
386
387 /* Check that we have a perf documentation directory. */
388 if (stat(mkpath("%s/perf.html", html_path), &st)
389 || !S_ISREG(st.st_mode))
390 die("'%s': not a documentation directory.", html_path);
391
392 strbuf_init(page_path, 0);
393 strbuf_addf(page_path, "%s/%s.html", html_path, page);
394}
395
396/*
397 * If open_html is not defined in a platform-specific way (see for
398 * example compat/mingw.h), we use the script web--browse to display
399 * HTML.
400 */
401#ifndef open_html
402void open_html(const char *path)
403{
404 execl_perf_cmd("web--browse", "-c", "help.browser", path, NULL);
405}
406#endif
407
408static void show_html_page(const char *perf_cmd)
409{
410 const char *page = cmd_to_page(perf_cmd);
411 struct strbuf page_path; /* it leaks but we exec bellow */
412
413 get_html_page_path(&page_path, page);
414
415 open_html(page_path.buf);
416}
417
418int cmd_help(int argc, const char **argv, const char *prefix)
419{
420 int nonperf;
421 const char *alias;
422 load_command_list("perf-", &main_cmds, &other_cmds);
423
424 /* setup_perf_directory_gently(&nonperf); */
425 perf_config(perf_help_config, NULL);
426
427 argc = parse_options(argc, argv, builtin_help_options,
428 builtin_help_usage, 0);
429
430 if (show_all) {
431 printf("usage: %s\n\n", perf_usage_string);
432 list_commands("perf commands", &main_cmds, &other_cmds);
433 printf("%s\n", perf_more_info_string);
434 return 0;
435 }
436
437 if (!argv[0]) {
438 printf("usage: %s\n\n", perf_usage_string);
439 list_common_cmds_help();
440 printf("\n%s\n", perf_more_info_string);
441 return 0;
442 }
443
444 alias = alias_lookup(argv[0]);
445 if (alias && !is_perf_command(argv[0])) {
446 printf("`perf %s' is aliased to `%s'\n", argv[0], alias);
447 return 0;
448 }
449
450 switch (help_format) {
451 case HELP_FORMAT_MAN:
452 show_man_page(argv[0]);
453 break;
454 case HELP_FORMAT_INFO:
455 show_info_page(argv[0]);
456 break;
457 case HELP_FORMAT_WEB:
458 show_html_page(argv[0]);
459 break;
460 }
461
462 return 0;
463}
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
new file mode 100644
index 000000000000..9d2c769e5f83
--- /dev/null
+++ b/Documentation/perf_counter/builtin-top.c
@@ -0,0 +1,1411 @@
1/*
2 * kerneltop.c: show top kernel functions - performance counters showcase
3
4 Build with:
5
6 cc -O6 -Wall -c -o kerneltop.o kerneltop.c -lrt
7
8 Sample output:
9
10------------------------------------------------------------------------------
11 KernelTop: 2669 irqs/sec [NMI, cache-misses/cache-refs], (all, cpu: 2)
12------------------------------------------------------------------------------
13
14 weight RIP kernel function
15 ______ ________________ _______________
16
17 35.20 - ffffffff804ce74b : skb_copy_and_csum_dev
18 33.00 - ffffffff804cb740 : sock_alloc_send_skb
19 31.26 - ffffffff804ce808 : skb_push
20 22.43 - ffffffff80510004 : tcp_established_options
21 19.00 - ffffffff8027d250 : find_get_page
22 15.76 - ffffffff804e4fc9 : eth_type_trans
23 15.20 - ffffffff804d8baa : dst_release
24 14.86 - ffffffff804cf5d8 : skb_release_head_state
25 14.00 - ffffffff802217d5 : read_hpet
26 12.00 - ffffffff804ffb7f : __ip_local_out
27 11.97 - ffffffff804fc0c8 : ip_local_deliver_finish
28 8.54 - ffffffff805001a3 : ip_queue_xmit
29 */
30
31/*
32 * perfstat: /usr/bin/time -alike performance counter statistics utility
33
34 It summarizes the counter events of all tasks (and child tasks),
35 covering all CPUs that the command (or workload) executes on.
36 It only counts the per-task events of the workload started,
37 independent of how many other tasks run on those CPUs.
38
39 Sample output:
40
41 $ ./perfstat -e 1 -e 3 -e 5 ls -lR /usr/include/ >/dev/null
42
43 Performance counter stats for 'ls':
44
45 163516953 instructions
46 2295 cache-misses
47 2855182 branch-misses
48 */
49
50 /*
51 * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
52 *
53 * Improvements and fixes by:
54 *
55 * Arjan van de Ven <arjan@linux.intel.com>
56 * Yanmin Zhang <yanmin.zhang@intel.com>
57 * Wu Fengguang <fengguang.wu@intel.com>
58 * Mike Galbraith <efault@gmx.de>
59 * Paul Mackerras <paulus@samba.org>
60 *
61 * Released under the GPL v2. (and only v2, not any later version)
62 */
63
64#include "util.h"
65
66#define _GNU_SOURCE
67#include <sys/types.h>
68#include <sys/stat.h>
69#include <sys/time.h>
70#include <unistd.h>
71#include <stdint.h>
72#include <stdlib.h>
73#include <string.h>
74#include <limits.h>
75#include <getopt.h>
76#include <assert.h>
77#include <fcntl.h>
78#include <stdio.h>
79#include <errno.h>
80#include <ctype.h>
81#include <time.h>
82#include <sched.h>
83#include <pthread.h>
84
85#include <sys/syscall.h>
86#include <sys/ioctl.h>
87#include <sys/poll.h>
88#include <sys/prctl.h>
89#include <sys/wait.h>
90#include <sys/uio.h>
91#include <sys/mman.h>
92
93#include <linux/unistd.h>
94#include <linux/types.h>
95
96#include "../../include/linux/perf_counter.h"
97
98
99/*
100 * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all
101 * counters in the current task.
102 */
103#define PR_TASK_PERF_COUNTERS_DISABLE 31
104#define PR_TASK_PERF_COUNTERS_ENABLE 32
105
106#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
107
108#define rdclock() \
109({ \
110 struct timespec ts; \
111 \
112 clock_gettime(CLOCK_MONOTONIC, &ts); \
113 ts.tv_sec * 1000000000ULL + ts.tv_nsec; \
114})
115
116/*
117 * Pick up some kernel type conventions:
118 */
119#define __user
120#define asmlinkage
121
122#ifdef __x86_64__
123#define __NR_perf_counter_open 295
124#define rmb() asm volatile("lfence" ::: "memory")
125#define cpu_relax() asm volatile("rep; nop" ::: "memory");
126#endif
127
128#ifdef __i386__
129#define __NR_perf_counter_open 333
130#define rmb() asm volatile("lfence" ::: "memory")
131#define cpu_relax() asm volatile("rep; nop" ::: "memory");
132#endif
133
134#ifdef __powerpc__
135#define __NR_perf_counter_open 319
136#define rmb() asm volatile ("sync" ::: "memory")
137#define cpu_relax() asm volatile ("" ::: "memory");
138#endif
139
140#define unlikely(x) __builtin_expect(!!(x), 0)
141#define min(x, y) ({ \
142 typeof(x) _min1 = (x); \
143 typeof(y) _min2 = (y); \
144 (void) (&_min1 == &_min2); \
145 _min1 < _min2 ? _min1 : _min2; })
146
147asmlinkage int sys_perf_counter_open(
148 struct perf_counter_hw_event *hw_event_uptr __user,
149 pid_t pid,
150 int cpu,
151 int group_fd,
152 unsigned long flags)
153{
154 return syscall(
155 __NR_perf_counter_open, hw_event_uptr, pid, cpu, group_fd, flags);
156}
157
158#define MAX_COUNTERS 64
159#define MAX_NR_CPUS 256
160
161#define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id))
162
163static int run_perfstat = 0;
164static int system_wide = 0;
165
166static int nr_counters = 0;
167static __u64 event_id[MAX_COUNTERS] = {
168 EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK),
169 EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES),
170 EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS),
171 EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS),
172
173 EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES),
174 EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS),
175 EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES),
176 EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES),
177};
178static int default_interval = 100000;
179static int event_count[MAX_COUNTERS];
180static int fd[MAX_NR_CPUS][MAX_COUNTERS];
181
182static __u64 count_filter = 100;
183
184static int tid = -1;
185static int profile_cpu = -1;
186static int nr_cpus = 0;
187static int nmi = 1;
188static unsigned int realtime_prio = 0;
189static int group = 0;
190static unsigned int page_size;
191static unsigned int mmap_pages = 16;
192static int use_mmap = 0;
193static int use_munmap = 0;
194
195static char *vmlinux;
196
197static char *sym_filter;
198static unsigned long filter_start;
199static unsigned long filter_end;
200
201static int delay_secs = 2;
202static int zero;
203static int dump_symtab;
204
205static int scale;
206
207struct source_line {
208 uint64_t EIP;
209 unsigned long count;
210 char *line;
211 struct source_line *next;
212};
213
214static struct source_line *lines;
215static struct source_line **lines_tail;
216
217const unsigned int default_count[] = {
218 1000000,
219 1000000,
220 10000,
221 10000,
222 1000000,
223 10000,
224};
225
226static char *hw_event_names[] = {
227 "CPU cycles",
228 "instructions",
229 "cache references",
230 "cache misses",
231 "branches",
232 "branch misses",
233 "bus cycles",
234};
235
236static char *sw_event_names[] = {
237 "cpu clock ticks",
238 "task clock ticks",
239 "pagefaults",
240 "context switches",
241 "CPU migrations",
242 "minor faults",
243 "major faults",
244};
245
246struct event_symbol {
247 __u64 event;
248 char *symbol;
249};
250
251static struct event_symbol event_symbols[] = {
252 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cpu-cycles", },
253 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cycles", },
254 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS), "instructions", },
255 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES), "cache-references", },
256 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES), "cache-misses", },
257 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branch-instructions", },
258 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branches", },
259 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_MISSES), "branch-misses", },
260 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BUS_CYCLES), "bus-cycles", },
261
262 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK), "cpu-clock", },
263 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK), "task-clock", },
264 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "page-faults", },
265 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "faults", },
266 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MIN), "minor-faults", },
267 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MAJ), "major-faults", },
268 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "context-switches", },
269 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "cs", },
270 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "cpu-migrations", },
271 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "migrations", },
272};
273
274#define __PERF_COUNTER_FIELD(config, name) \
275 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
276
277#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
278#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
279#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
280#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
281
282static void display_events_help(void)
283{
284 unsigned int i;
285 __u64 e;
286
287 printf(
288 " -e EVENT --event=EVENT # symbolic-name abbreviations");
289
290 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
291 int type, id;
292
293 e = event_symbols[i].event;
294 type = PERF_COUNTER_TYPE(e);
295 id = PERF_COUNTER_ID(e);
296
297 printf("\n %d:%d: %-20s",
298 type, id, event_symbols[i].symbol);
299 }
300
301 printf("\n"
302 " rNNN: raw PMU events (eventsel+umask)\n\n");
303}
304
305static void display_perfstat_help(void)
306{
307 printf(
308 "Usage: perfstat [<events...>] <cmd...>\n\n"
309 "PerfStat Options (up to %d event types can be specified):\n\n",
310 MAX_COUNTERS);
311
312 display_events_help();
313
314 printf(
315 " -l # scale counter values\n"
316 " -a # system-wide collection\n");
317 exit(0);
318}
319
320static void display_help(void)
321{
322 if (run_perfstat)
323 return display_perfstat_help();
324
325 printf(
326 "Usage: kerneltop [<options>]\n"
327 " Or: kerneltop -S [<options>] COMMAND [ARGS]\n\n"
328 "KernelTop Options (up to %d event types can be specified at once):\n\n",
329 MAX_COUNTERS);
330
331 display_events_help();
332
333 printf(
334 " -S --stat # perfstat COMMAND\n"
335 " -a # system-wide collection (for perfstat)\n\n"
336 " -c CNT --count=CNT # event period to sample\n\n"
337 " -C CPU --cpu=CPU # CPU (-1 for all) [default: -1]\n"
338 " -p PID --pid=PID # PID of sampled task (-1 for all) [default: -1]\n\n"
339 " -l # show scale factor for RR events\n"
340 " -d delay --delay=<seconds> # sampling/display delay [default: 2]\n"
341 " -f CNT --filter=CNT # min-event-count filter [default: 100]\n\n"
342 " -r prio --realtime=<prio> # event acquisition runs with SCHED_FIFO policy\n"
343 " -s symbol --symbol=<symbol> # function to be showed annotated one-shot\n"
344 " -x path --vmlinux=<path> # the vmlinux binary, required for -s use\n"
345 " -z --zero # zero counts after display\n"
346 " -D --dump_symtab # dump symbol table to stderr on startup\n"
347 " -m pages --mmap_pages=<pages> # number of mmap data pages\n"
348 " -M --mmap_info # print mmap info stream\n"
349 " -U --munmap_info # print munmap info stream\n"
350 );
351
352 exit(0);
353}
354
355static char *event_name(int ctr)
356{
357 __u64 config = event_id[ctr];
358 int type = PERF_COUNTER_TYPE(config);
359 int id = PERF_COUNTER_ID(config);
360 static char buf[32];
361
362 if (PERF_COUNTER_RAW(config)) {
363 sprintf(buf, "raw 0x%llx", PERF_COUNTER_CONFIG(config));
364 return buf;
365 }
366
367 switch (type) {
368 case PERF_TYPE_HARDWARE:
369 if (id < PERF_HW_EVENTS_MAX)
370 return hw_event_names[id];
371 return "unknown-hardware";
372
373 case PERF_TYPE_SOFTWARE:
374 if (id < PERF_SW_EVENTS_MAX)
375 return sw_event_names[id];
376 return "unknown-software";
377
378 default:
379 break;
380 }
381
382 return "unknown";
383}
384
385/*
386 * Each event can have multiple symbolic names.
387 * Symbolic names are (almost) exactly matched.
388 */
389static __u64 match_event_symbols(char *str)
390{
391 __u64 config, id;
392 int type;
393 unsigned int i;
394
395 if (sscanf(str, "r%llx", &config) == 1)
396 return config | PERF_COUNTER_RAW_MASK;
397
398 if (sscanf(str, "%d:%llu", &type, &id) == 2)
399 return EID(type, id);
400
401 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
402 if (!strncmp(str, event_symbols[i].symbol,
403 strlen(event_symbols[i].symbol)))
404 return event_symbols[i].event;
405 }
406
407 return ~0ULL;
408}
409
410static int parse_events(char *str)
411{
412 __u64 config;
413
414again:
415 if (nr_counters == MAX_COUNTERS)
416 return -1;
417
418 config = match_event_symbols(str);
419 if (config == ~0ULL)
420 return -1;
421
422 event_id[nr_counters] = config;
423 nr_counters++;
424
425 str = strstr(str, ",");
426 if (str) {
427 str++;
428 goto again;
429 }
430
431 return 0;
432}
433
434
435/*
436 * perfstat
437 */
438
439char fault_here[1000000];
440
441static void create_perfstat_counter(int counter)
442{
443 struct perf_counter_hw_event hw_event;
444
445 memset(&hw_event, 0, sizeof(hw_event));
446 hw_event.config = event_id[counter];
447 hw_event.record_type = 0;
448 hw_event.nmi = 0;
449 if (scale)
450 hw_event.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
451 PERF_FORMAT_TOTAL_TIME_RUNNING;
452
453 if (system_wide) {
454 int cpu;
455 for (cpu = 0; cpu < nr_cpus; cpu ++) {
456 fd[cpu][counter] = sys_perf_counter_open(&hw_event, -1, cpu, -1, 0);
457 if (fd[cpu][counter] < 0) {
458 printf("perfstat error: syscall returned with %d (%s)\n",
459 fd[cpu][counter], strerror(errno));
460 exit(-1);
461 }
462 }
463 } else {
464 hw_event.inherit = 1;
465 hw_event.disabled = 1;
466
467 fd[0][counter] = sys_perf_counter_open(&hw_event, 0, -1, -1, 0);
468 if (fd[0][counter] < 0) {
469 printf("perfstat error: syscall returned with %d (%s)\n",
470 fd[0][counter], strerror(errno));
471 exit(-1);
472 }
473 }
474}
475
476int do_perfstat(int argc, char *argv[])
477{
478 unsigned long long t0, t1;
479 int counter;
480 ssize_t res;
481 int status;
482 int pid;
483
484 if (!system_wide)
485 nr_cpus = 1;
486
487 for (counter = 0; counter < nr_counters; counter++)
488 create_perfstat_counter(counter);
489
490 argc -= optind;
491 argv += optind;
492
493 if (!argc)
494 display_help();
495
496 /*
497 * Enable counters and exec the command:
498 */
499 t0 = rdclock();
500 prctl(PR_TASK_PERF_COUNTERS_ENABLE);
501
502 if ((pid = fork()) < 0)
503 perror("failed to fork");
504 if (!pid) {
505 if (execvp(argv[0], argv)) {
506 perror(argv[0]);
507 exit(-1);
508 }
509 }
510 while (wait(&status) >= 0)
511 ;
512 prctl(PR_TASK_PERF_COUNTERS_DISABLE);
513 t1 = rdclock();
514
515 fflush(stdout);
516
517 fprintf(stderr, "\n");
518 fprintf(stderr, " Performance counter stats for \'%s\':\n",
519 argv[0]);
520 fprintf(stderr, "\n");
521
522 for (counter = 0; counter < nr_counters; counter++) {
523 int cpu, nv;
524 __u64 count[3], single_count[3];
525 int scaled;
526
527 count[0] = count[1] = count[2] = 0;
528 nv = scale ? 3 : 1;
529 for (cpu = 0; cpu < nr_cpus; cpu ++) {
530 res = read(fd[cpu][counter],
531 single_count, nv * sizeof(__u64));
532 assert(res == nv * sizeof(__u64));
533
534 count[0] += single_count[0];
535 if (scale) {
536 count[1] += single_count[1];
537 count[2] += single_count[2];
538 }
539 }
540
541 scaled = 0;
542 if (scale) {
543 if (count[2] == 0) {
544 fprintf(stderr, " %14s %-20s\n",
545 "<not counted>", event_name(counter));
546 continue;
547 }
548 if (count[2] < count[1]) {
549 scaled = 1;
550 count[0] = (unsigned long long)
551 ((double)count[0] * count[1] / count[2] + 0.5);
552 }
553 }
554
555 if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK) ||
556 event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK)) {
557
558 double msecs = (double)count[0] / 1000000;
559
560 fprintf(stderr, " %14.6f %-20s (msecs)",
561 msecs, event_name(counter));
562 } else {
563 fprintf(stderr, " %14Ld %-20s (events)",
564 count[0], event_name(counter));
565 }
566 if (scaled)
567 fprintf(stderr, " (scaled from %.2f%%)",
568 (double) count[2] / count[1] * 100);
569 fprintf(stderr, "\n");
570 }
571 fprintf(stderr, "\n");
572 fprintf(stderr, " Wall-clock time elapsed: %12.6f msecs\n",
573 (double)(t1-t0)/1e6);
574 fprintf(stderr, "\n");
575
576 return 0;
577}
578
579/*
580 * Symbols
581 */
582
583static uint64_t min_ip;
584static uint64_t max_ip = -1ll;
585
586struct sym_entry {
587 unsigned long long addr;
588 char *sym;
589 unsigned long count[MAX_COUNTERS];
590 int skip;
591 struct source_line *source;
592};
593
594#define MAX_SYMS 100000
595
596static int sym_table_count;
597
598struct sym_entry *sym_filter_entry;
599
600static struct sym_entry sym_table[MAX_SYMS];
601
602static void show_details(struct sym_entry *sym);
603
604/*
605 * Ordering weight: count-1 * count-2 * ... / count-n
606 */
607static double sym_weight(const struct sym_entry *sym)
608{
609 double weight;
610 int counter;
611
612 weight = sym->count[0];
613
614 for (counter = 1; counter < nr_counters-1; counter++)
615 weight *= sym->count[counter];
616
617 weight /= (sym->count[counter] + 1);
618
619 return weight;
620}
621
622static int compare(const void *__sym1, const void *__sym2)
623{
624 const struct sym_entry *sym1 = __sym1, *sym2 = __sym2;
625
626 return sym_weight(sym1) < sym_weight(sym2);
627}
628
629static long events;
630static long userspace_events;
631static const char CONSOLE_CLEAR[] = "";
632
633static struct sym_entry tmp[MAX_SYMS];
634
635static void print_sym_table(void)
636{
637 int i, printed;
638 int counter;
639 float events_per_sec = events/delay_secs;
640 float kevents_per_sec = (events-userspace_events)/delay_secs;
641 float sum_kevents = 0.0;
642
643 events = userspace_events = 0;
644 memcpy(tmp, sym_table, sizeof(sym_table[0])*sym_table_count);
645 qsort(tmp, sym_table_count, sizeof(tmp[0]), compare);
646
647 for (i = 0; i < sym_table_count && tmp[i].count[0]; i++)
648 sum_kevents += tmp[i].count[0];
649
650 write(1, CONSOLE_CLEAR, strlen(CONSOLE_CLEAR));
651
652 printf(
653"------------------------------------------------------------------------------\n");
654 printf( " KernelTop:%8.0f irqs/sec kernel:%4.1f%% [%s, ",
655 events_per_sec,
656 100.0 - (100.0*((events_per_sec-kevents_per_sec)/events_per_sec)),
657 nmi ? "NMI" : "IRQ");
658
659 if (nr_counters == 1)
660 printf("%d ", event_count[0]);
661
662 for (counter = 0; counter < nr_counters; counter++) {
663 if (counter)
664 printf("/");
665
666 printf("%s", event_name(counter));
667 }
668
669 printf( "], ");
670
671 if (tid != -1)
672 printf(" (tid: %d", tid);
673 else
674 printf(" (all");
675
676 if (profile_cpu != -1)
677 printf(", cpu: %d)\n", profile_cpu);
678 else {
679 if (tid != -1)
680 printf(")\n");
681 else
682 printf(", %d CPUs)\n", nr_cpus);
683 }
684
685 printf("------------------------------------------------------------------------------\n\n");
686
687 if (nr_counters == 1)
688 printf(" events pcnt");
689 else
690 printf(" weight events pcnt");
691
692 printf(" RIP kernel function\n"
693 " ______ ______ _____ ________________ _______________\n\n"
694 );
695
696 for (i = 0, printed = 0; i < sym_table_count; i++) {
697 float pcnt;
698 int count;
699
700 if (printed <= 18 && tmp[i].count[0] >= count_filter) {
701 pcnt = 100.0 - (100.0*((sum_kevents-tmp[i].count[0])/sum_kevents));
702
703 if (nr_counters == 1)
704 printf("%19.2f - %4.1f%% - %016llx : %s\n",
705 sym_weight(tmp + i),
706 pcnt, tmp[i].addr, tmp[i].sym);
707 else
708 printf("%8.1f %10ld - %4.1f%% - %016llx : %s\n",
709 sym_weight(tmp + i),
710 tmp[i].count[0],
711 pcnt, tmp[i].addr, tmp[i].sym);
712 printed++;
713 }
714 /*
715 * Add decay to the counts:
716 */
717 for (count = 0; count < nr_counters; count++)
718 sym_table[i].count[count] = zero ? 0 : sym_table[i].count[count] * 7 / 8;
719 }
720
721 if (sym_filter_entry)
722 show_details(sym_filter_entry);
723
724 {
725 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
726
727 if (poll(&stdin_poll, 1, 0) == 1) {
728 printf("key pressed - exiting.\n");
729 exit(0);
730 }
731 }
732}
733
734static void *display_thread(void *arg)
735{
736 printf("KernelTop refresh period: %d seconds\n", delay_secs);
737
738 while (!sleep(delay_secs))
739 print_sym_table();
740
741 return NULL;
742}
743
744static int read_symbol(FILE *in, struct sym_entry *s)
745{
746 static int filter_match = 0;
747 char *sym, stype;
748 char str[500];
749 int rc, pos;
750
751 rc = fscanf(in, "%llx %c %499s", &s->addr, &stype, str);
752 if (rc == EOF)
753 return -1;
754
755 assert(rc == 3);
756
757 /* skip until end of line: */
758 pos = strlen(str);
759 do {
760 rc = fgetc(in);
761 if (rc == '\n' || rc == EOF || pos >= 499)
762 break;
763 str[pos] = rc;
764 pos++;
765 } while (1);
766 str[pos] = 0;
767
768 sym = str;
769
770 /* Filter out known duplicates and non-text symbols. */
771 if (!strcmp(sym, "_text"))
772 return 1;
773 if (!min_ip && !strcmp(sym, "_stext"))
774 return 1;
775 if (!strcmp(sym, "_etext") || !strcmp(sym, "_sinittext"))
776 return 1;
777 if (stype != 'T' && stype != 't')
778 return 1;
779 if (!strncmp("init_module", sym, 11) || !strncmp("cleanup_module", sym, 14))
780 return 1;
781 if (strstr(sym, "_text_start") || strstr(sym, "_text_end"))
782 return 1;
783
784 s->sym = malloc(strlen(str));
785 assert(s->sym);
786
787 strcpy((char *)s->sym, str);
788 s->skip = 0;
789
790 /* Tag events to be skipped. */
791 if (!strcmp("default_idle", s->sym) || !strcmp("cpu_idle", s->sym))
792 s->skip = 1;
793 else if (!strcmp("enter_idle", s->sym) || !strcmp("exit_idle", s->sym))
794 s->skip = 1;
795 else if (!strcmp("mwait_idle", s->sym))
796 s->skip = 1;
797
798 if (filter_match == 1) {
799 filter_end = s->addr;
800 filter_match = -1;
801 if (filter_end - filter_start > 10000) {
802 printf("hm, too large filter symbol <%s> - skipping.\n",
803 sym_filter);
804 printf("symbol filter start: %016lx\n", filter_start);
805 printf(" end: %016lx\n", filter_end);
806 filter_end = filter_start = 0;
807 sym_filter = NULL;
808 sleep(1);
809 }
810 }
811 if (filter_match == 0 && sym_filter && !strcmp(s->sym, sym_filter)) {
812 filter_match = 1;
813 filter_start = s->addr;
814 }
815
816 return 0;
817}
818
819int compare_addr(const void *__sym1, const void *__sym2)
820{
821 const struct sym_entry *sym1 = __sym1, *sym2 = __sym2;
822
823 return sym1->addr > sym2->addr;
824}
825
826static void sort_symbol_table(void)
827{
828 int i, dups;
829
830 do {
831 qsort(sym_table, sym_table_count, sizeof(sym_table[0]), compare_addr);
832 for (i = 0, dups = 0; i < sym_table_count; i++) {
833 if (sym_table[i].addr == sym_table[i+1].addr) {
834 sym_table[i+1].addr = -1ll;
835 dups++;
836 }
837 }
838 sym_table_count -= dups;
839 } while(dups);
840}
841
842static void parse_symbols(void)
843{
844 struct sym_entry *last;
845
846 FILE *kallsyms = fopen("/proc/kallsyms", "r");
847
848 if (!kallsyms) {
849 printf("Could not open /proc/kallsyms - no CONFIG_KALLSYMS_ALL=y?\n");
850 exit(-1);
851 }
852
853 while (!feof(kallsyms)) {
854 if (read_symbol(kallsyms, &sym_table[sym_table_count]) == 0) {
855 sym_table_count++;
856 assert(sym_table_count <= MAX_SYMS);
857 }
858 }
859
860 sort_symbol_table();
861 min_ip = sym_table[0].addr;
862 max_ip = sym_table[sym_table_count-1].addr;
863 last = sym_table + sym_table_count++;
864
865 last->addr = -1ll;
866 last->sym = "<end>";
867
868 if (filter_end) {
869 int count;
870 for (count=0; count < sym_table_count; count ++) {
871 if (!strcmp(sym_table[count].sym, sym_filter)) {
872 sym_filter_entry = &sym_table[count];
873 break;
874 }
875 }
876 }
877 if (dump_symtab) {
878 int i;
879
880 for (i = 0; i < sym_table_count; i++)
881 fprintf(stderr, "%llx %s\n",
882 sym_table[i].addr, sym_table[i].sym);
883 }
884}
885
886/*
887 * Source lines
888 */
889
890static void parse_vmlinux(char *filename)
891{
892 FILE *file;
893 char command[PATH_MAX*2];
894 if (!filename)
895 return;
896
897 sprintf(command, "objdump --start-address=0x%016lx --stop-address=0x%016lx -dS %s", filter_start, filter_end, filename);
898
899 file = popen(command, "r");
900 if (!file)
901 return;
902
903 lines_tail = &lines;
904 while (!feof(file)) {
905 struct source_line *src;
906 size_t dummy = 0;
907 char *c;
908
909 src = malloc(sizeof(struct source_line));
910 assert(src != NULL);
911 memset(src, 0, sizeof(struct source_line));
912
913 if (getline(&src->line, &dummy, file) < 0)
914 break;
915 if (!src->line)
916 break;
917
918 c = strchr(src->line, '\n');
919 if (c)
920 *c = 0;
921
922 src->next = NULL;
923 *lines_tail = src;
924 lines_tail = &src->next;
925
926 if (strlen(src->line)>8 && src->line[8] == ':')
927 src->EIP = strtoull(src->line, NULL, 16);
928 if (strlen(src->line)>8 && src->line[16] == ':')
929 src->EIP = strtoull(src->line, NULL, 16);
930 }
931 pclose(file);
932}
933
934static void record_precise_ip(uint64_t ip)
935{
936 struct source_line *line;
937
938 for (line = lines; line; line = line->next) {
939 if (line->EIP == ip)
940 line->count++;
941 if (line->EIP > ip)
942 break;
943 }
944}
945
946static void lookup_sym_in_vmlinux(struct sym_entry *sym)
947{
948 struct source_line *line;
949 char pattern[PATH_MAX];
950 sprintf(pattern, "<%s>:", sym->sym);
951
952 for (line = lines; line; line = line->next) {
953 if (strstr(line->line, pattern)) {
954 sym->source = line;
955 break;
956 }
957 }
958}
959
960static void show_lines(struct source_line *line_queue, int line_queue_count)
961{
962 int i;
963 struct source_line *line;
964
965 line = line_queue;
966 for (i = 0; i < line_queue_count; i++) {
967 printf("%8li\t%s\n", line->count, line->line);
968 line = line->next;
969 }
970}
971
972#define TRACE_COUNT 3
973
974static void show_details(struct sym_entry *sym)
975{
976 struct source_line *line;
977 struct source_line *line_queue = NULL;
978 int displayed = 0;
979 int line_queue_count = 0;
980
981 if (!sym->source)
982 lookup_sym_in_vmlinux(sym);
983 if (!sym->source)
984 return;
985
986 printf("Showing details for %s\n", sym->sym);
987
988 line = sym->source;
989 while (line) {
990 if (displayed && strstr(line->line, ">:"))
991 break;
992
993 if (!line_queue_count)
994 line_queue = line;
995 line_queue_count ++;
996
997 if (line->count >= count_filter) {
998 show_lines(line_queue, line_queue_count);
999 line_queue_count = 0;
1000 line_queue = NULL;
1001 } else if (line_queue_count > TRACE_COUNT) {
1002 line_queue = line_queue->next;
1003 line_queue_count --;
1004 }
1005
1006 line->count = 0;
1007 displayed++;
1008 if (displayed > 300)
1009 break;
1010 line = line->next;
1011 }
1012}
1013
1014/*
1015 * Binary search in the histogram table and record the hit:
1016 */
1017static void record_ip(uint64_t ip, int counter)
1018{
1019 int left_idx, middle_idx, right_idx, idx;
1020 unsigned long left, middle, right;
1021
1022 record_precise_ip(ip);
1023
1024 left_idx = 0;
1025 right_idx = sym_table_count-1;
1026 assert(ip <= max_ip && ip >= min_ip);
1027
1028 while (left_idx + 1 < right_idx) {
1029 middle_idx = (left_idx + right_idx) / 2;
1030
1031 left = sym_table[ left_idx].addr;
1032 middle = sym_table[middle_idx].addr;
1033 right = sym_table[ right_idx].addr;
1034
1035 if (!(left <= middle && middle <= right)) {
1036 printf("%016lx...\n%016lx...\n%016lx\n", left, middle, right);
1037 printf("%d %d %d\n", left_idx, middle_idx, right_idx);
1038 }
1039 assert(left <= middle && middle <= right);
1040 if (!(left <= ip && ip <= right)) {
1041 printf(" left: %016lx\n", left);
1042 printf(" ip: %016lx\n", (unsigned long)ip);
1043 printf("right: %016lx\n", right);
1044 }
1045 assert(left <= ip && ip <= right);
1046 /*
1047 * [ left .... target .... middle .... right ]
1048 * => right := middle
1049 */
1050 if (ip < middle) {
1051 right_idx = middle_idx;
1052 continue;
1053 }
1054 /*
1055 * [ left .... middle ... target ... right ]
1056 * => left := middle
1057 */
1058 left_idx = middle_idx;
1059 }
1060
1061 idx = left_idx;
1062
1063 if (!sym_table[idx].skip)
1064 sym_table[idx].count[counter]++;
1065 else events--;
1066}
1067
1068static void process_event(uint64_t ip, int counter)
1069{
1070 events++;
1071
1072 if (ip < min_ip || ip > max_ip) {
1073 userspace_events++;
1074 return;
1075 }
1076
1077 record_ip(ip, counter);
1078}
1079
1080static void process_options(int argc, char *argv[])
1081{
1082 int error = 0, counter;
1083
1084 if (strstr(argv[0], "perfstat"))
1085 run_perfstat = 1;
1086
1087 for (;;) {
1088 int option_index = 0;
1089 /** Options for getopt */
1090 static struct option long_options[] = {
1091 {"count", required_argument, NULL, 'c'},
1092 {"cpu", required_argument, NULL, 'C'},
1093 {"delay", required_argument, NULL, 'd'},
1094 {"dump_symtab", no_argument, NULL, 'D'},
1095 {"event", required_argument, NULL, 'e'},
1096 {"filter", required_argument, NULL, 'f'},
1097 {"group", required_argument, NULL, 'g'},
1098 {"help", no_argument, NULL, 'h'},
1099 {"nmi", required_argument, NULL, 'n'},
1100 {"mmap_info", no_argument, NULL, 'M'},
1101 {"mmap_pages", required_argument, NULL, 'm'},
1102 {"munmap_info", no_argument, NULL, 'U'},
1103 {"pid", required_argument, NULL, 'p'},
1104 {"realtime", required_argument, NULL, 'r'},
1105 {"scale", no_argument, NULL, 'l'},
1106 {"symbol", required_argument, NULL, 's'},
1107 {"stat", no_argument, NULL, 'S'},
1108 {"vmlinux", required_argument, NULL, 'x'},
1109 {"zero", no_argument, NULL, 'z'},
1110 {NULL, 0, NULL, 0 }
1111 };
1112 int c = getopt_long(argc, argv, "+:ac:C:d:De:f:g:hln:m:p:r:s:Sx:zMU",
1113 long_options, &option_index);
1114 if (c == -1)
1115 break;
1116
1117 switch (c) {
1118 case 'a': system_wide = 1; break;
1119 case 'c': default_interval = atoi(optarg); break;
1120 case 'C':
1121 /* CPU and PID are mutually exclusive */
1122 if (tid != -1) {
1123 printf("WARNING: CPU switch overriding PID\n");
1124 sleep(1);
1125 tid = -1;
1126 }
1127 profile_cpu = atoi(optarg); break;
1128 case 'd': delay_secs = atoi(optarg); break;
1129 case 'D': dump_symtab = 1; break;
1130
1131 case 'e': error = parse_events(optarg); break;
1132
1133 case 'f': count_filter = atoi(optarg); break;
1134 case 'g': group = atoi(optarg); break;
1135 case 'h': display_help(); break;
1136 case 'l': scale = 1; break;
1137 case 'n': nmi = atoi(optarg); break;
1138 case 'p':
1139 /* CPU and PID are mutually exclusive */
1140 if (profile_cpu != -1) {
1141 printf("WARNING: PID switch overriding CPU\n");
1142 sleep(1);
1143 profile_cpu = -1;
1144 }
1145 tid = atoi(optarg); break;
1146 case 'r': realtime_prio = atoi(optarg); break;
1147 case 's': sym_filter = strdup(optarg); break;
1148 case 'S': run_perfstat = 1; break;
1149 case 'x': vmlinux = strdup(optarg); break;
1150 case 'z': zero = 1; break;
1151 case 'm': mmap_pages = atoi(optarg); break;
1152 case 'M': use_mmap = 1; break;
1153 case 'U': use_munmap = 1; break;
1154 default: error = 1; break;
1155 }
1156 }
1157 if (error)
1158 display_help();
1159
1160 if (!nr_counters) {
1161 if (run_perfstat)
1162 nr_counters = 8;
1163 else {
1164 nr_counters = 1;
1165 event_id[0] = 0;
1166 }
1167 }
1168
1169 for (counter = 0; counter < nr_counters; counter++) {
1170 if (event_count[counter])
1171 continue;
1172
1173 event_count[counter] = default_interval;
1174 }
1175}
1176
1177struct mmap_data {
1178 int counter;
1179 void *base;
1180 unsigned int mask;
1181 unsigned int prev;
1182};
1183
1184static unsigned int mmap_read_head(struct mmap_data *md)
1185{
1186 struct perf_counter_mmap_page *pc = md->base;
1187 int head;
1188
1189 head = pc->data_head;
1190 rmb();
1191
1192 return head;
1193}
1194
1195struct timeval last_read, this_read;
1196
1197static void mmap_read(struct mmap_data *md)
1198{
1199 unsigned int head = mmap_read_head(md);
1200 unsigned int old = md->prev;
1201 unsigned char *data = md->base + page_size;
1202 int diff;
1203
1204 gettimeofday(&this_read, NULL);
1205
1206 /*
1207 * If we're further behind than half the buffer, there's a chance
1208 * the writer will bite our tail and screw up the events under us.
1209 *
1210 * If we somehow ended up ahead of the head, we got messed up.
1211 *
1212 * In either case, truncate and restart at head.
1213 */
1214 diff = head - old;
1215 if (diff > md->mask / 2 || diff < 0) {
1216 struct timeval iv;
1217 unsigned long msecs;
1218
1219 timersub(&this_read, &last_read, &iv);
1220 msecs = iv.tv_sec*1000 + iv.tv_usec/1000;
1221
1222 fprintf(stderr, "WARNING: failed to keep up with mmap data."
1223 " Last read %lu msecs ago.\n", msecs);
1224
1225 /*
1226 * head points to a known good entry, start there.
1227 */
1228 old = head;
1229 }
1230
1231 last_read = this_read;
1232
1233 for (; old != head;) {
1234 struct ip_event {
1235 struct perf_event_header header;
1236 __u64 ip;
1237 __u32 pid, tid;
1238 };
1239 struct mmap_event {
1240 struct perf_event_header header;
1241 __u32 pid, tid;
1242 __u64 start;
1243 __u64 len;
1244 __u64 pgoff;
1245 char filename[PATH_MAX];
1246 };
1247
1248 typedef union event_union {
1249 struct perf_event_header header;
1250 struct ip_event ip;
1251 struct mmap_event mmap;
1252 } event_t;
1253
1254 event_t *event = (event_t *)&data[old & md->mask];
1255
1256 event_t event_copy;
1257
1258 unsigned int size = event->header.size;
1259
1260 /*
1261 * Event straddles the mmap boundary -- header should always
1262 * be inside due to u64 alignment of output.
1263 */
1264 if ((old & md->mask) + size != ((old + size) & md->mask)) {
1265 unsigned int offset = old;
1266 unsigned int len = min(sizeof(*event), size), cpy;
1267 void *dst = &event_copy;
1268
1269 do {
1270 cpy = min(md->mask + 1 - (offset & md->mask), len);
1271 memcpy(dst, &data[offset & md->mask], cpy);
1272 offset += cpy;
1273 dst += cpy;
1274 len -= cpy;
1275 } while (len);
1276
1277 event = &event_copy;
1278 }
1279
1280 old += size;
1281
1282 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
1283 if (event->header.type & PERF_RECORD_IP)
1284 process_event(event->ip.ip, md->counter);
1285 } else {
1286 switch (event->header.type) {
1287 case PERF_EVENT_MMAP:
1288 case PERF_EVENT_MUNMAP:
1289 printf("%s: %Lu %Lu %Lu %s\n",
1290 event->header.type == PERF_EVENT_MMAP
1291 ? "mmap" : "munmap",
1292 event->mmap.start,
1293 event->mmap.len,
1294 event->mmap.pgoff,
1295 event->mmap.filename);
1296 break;
1297 }
1298 }
1299 }
1300
1301 md->prev = old;
1302}
1303
1304int cmd_top(int argc, const char **argv, const char *prefix)
1305{
1306 struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
1307 struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
1308 struct perf_counter_hw_event hw_event;
1309 pthread_t thread;
1310 int i, counter, group_fd, nr_poll = 0;
1311 unsigned int cpu;
1312 int ret;
1313
1314 page_size = sysconf(_SC_PAGE_SIZE);
1315
1316 process_options(argc, argv);
1317
1318 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1319 assert(nr_cpus <= MAX_NR_CPUS);
1320 assert(nr_cpus >= 0);
1321
1322 if (run_perfstat)
1323 return do_perfstat(argc, argv);
1324
1325 if (tid != -1 || profile_cpu != -1)
1326 nr_cpus = 1;
1327
1328 parse_symbols();
1329 if (vmlinux && sym_filter_entry)
1330 parse_vmlinux(vmlinux);
1331
1332 for (i = 0; i < nr_cpus; i++) {
1333 group_fd = -1;
1334 for (counter = 0; counter < nr_counters; counter++) {
1335
1336 cpu = profile_cpu;
1337 if (tid == -1 && profile_cpu == -1)
1338 cpu = i;
1339
1340 memset(&hw_event, 0, sizeof(hw_event));
1341 hw_event.config = event_id[counter];
1342 hw_event.irq_period = event_count[counter];
1343 hw_event.record_type = PERF_RECORD_IP | PERF_RECORD_TID;
1344 hw_event.nmi = nmi;
1345 hw_event.mmap = use_mmap;
1346 hw_event.munmap = use_munmap;
1347
1348 fd[i][counter] = sys_perf_counter_open(&hw_event, tid, cpu, group_fd, 0);
1349 if (fd[i][counter] < 0) {
1350 int err = errno;
1351 printf("kerneltop error: syscall returned with %d (%s)\n",
1352 fd[i][counter], strerror(err));
1353 if (err == EPERM)
1354 printf("Are you root?\n");
1355 exit(-1);
1356 }
1357 assert(fd[i][counter] >= 0);
1358 fcntl(fd[i][counter], F_SETFL, O_NONBLOCK);
1359
1360 /*
1361 * First counter acts as the group leader:
1362 */
1363 if (group && group_fd == -1)
1364 group_fd = fd[i][counter];
1365
1366 event_array[nr_poll].fd = fd[i][counter];
1367 event_array[nr_poll].events = POLLIN;
1368 nr_poll++;
1369
1370 mmap_array[i][counter].counter = counter;
1371 mmap_array[i][counter].prev = 0;
1372 mmap_array[i][counter].mask = mmap_pages*page_size - 1;
1373 mmap_array[i][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
1374 PROT_READ, MAP_SHARED, fd[i][counter], 0);
1375 if (mmap_array[i][counter].base == MAP_FAILED) {
1376 printf("kerneltop error: failed to mmap with %d (%s)\n",
1377 errno, strerror(errno));
1378 exit(-1);
1379 }
1380 }
1381 }
1382
1383 if (pthread_create(&thread, NULL, display_thread, NULL)) {
1384 printf("Could not create display thread.\n");
1385 exit(-1);
1386 }
1387
1388 if (realtime_prio) {
1389 struct sched_param param;
1390
1391 param.sched_priority = realtime_prio;
1392 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
1393 printf("Could not set realtime priority.\n");
1394 exit(-1);
1395 }
1396 }
1397
1398 while (1) {
1399 int hits = events;
1400
1401 for (i = 0; i < nr_cpus; i++) {
1402 for (counter = 0; counter < nr_counters; counter++)
1403 mmap_read(&mmap_array[i][counter]);
1404 }
1405
1406 if (hits == events)
1407 ret = poll(event_array, nr_poll, 100);
1408 }
1409
1410 return 0;
1411}
diff --git a/Documentation/perf_counter/builtin.h b/Documentation/perf_counter/builtin.h
new file mode 100644
index 000000000000..41637444ce2d
--- /dev/null
+++ b/Documentation/perf_counter/builtin.h
@@ -0,0 +1,18 @@
1#ifndef BUILTIN_H
2#define BUILTIN_H
3
4#include "util.h"
5#include "strbuf.h"
6
7extern const char perf_version_string[];
8extern const char perf_usage_string[];
9extern const char perf_more_info_string[];
10
11extern void list_common_cmds_help(void);
12extern const char *help_unknown_cmd(const char *cmd);
13extern void prune_packed_objects(int);
14extern int read_line_with_nul(char *buf, int size, FILE *file);
15extern int check_pager_config(const char *cmd);
16
17extern int cmd_top(int argc, const char **argv, const char *prefix);
18#endif
diff --git a/Documentation/perf_counter/cache.h b/Documentation/perf_counter/cache.h
new file mode 100644
index 000000000000..dc085640a57d
--- /dev/null
+++ b/Documentation/perf_counter/cache.h
@@ -0,0 +1,97 @@
1#ifndef CACHE_H
2#define CACHE_H
3
4#include "util.h"
5#include "strbuf.h"
6
7#define PERF_DIR_ENVIRONMENT "PERF_DIR"
8#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
9#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
10#define DB_ENVIRONMENT "PERF_OBJECT_DIRECTORY"
11#define INDEX_ENVIRONMENT "PERF_INDEX_FILE"
12#define GRAFT_ENVIRONMENT "PERF_GRAFT_FILE"
13#define TEMPLATE_DIR_ENVIRONMENT "PERF_TEMPLATE_DIR"
14#define CONFIG_ENVIRONMENT "PERF_CONFIG"
15#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
16#define CEILING_DIRECTORIES_ENVIRONMENT "PERF_CEILING_DIRECTORIES"
17#define PERFATTRIBUTES_FILE ".perfattributes"
18#define INFOATTRIBUTES_FILE "info/attributes"
19#define ATTRIBUTE_MACRO_PREFIX "[attr]"
20
21typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *);
23extern int perf_config_from_file(config_fn_t fn, const char *, void *);
24extern int perf_config(config_fn_t fn, void *);
25extern int perf_parse_ulong(const char *, unsigned long *);
26extern int perf_config_int(const char *, const char *);
27extern unsigned long perf_config_ulong(const char *, const char *);
28extern int perf_config_bool_or_int(const char *, const char *, int *);
29extern int perf_config_bool(const char *, const char *);
30extern int perf_config_string(const char **, const char *, const char *);
31extern int perf_config_set(const char *, const char *);
32extern int perf_config_set_multivar(const char *, const char *, const char *, int);
33extern int perf_config_rename_section(const char *, const char *);
34extern const char *perf_etc_perfconfig(void);
35extern int check_repository_format_version(const char *var, const char *value, void *cb);
36extern int perf_config_system(void);
37extern int perf_config_global(void);
38extern int config_error_nonbool(const char *);
39extern const char *config_exclusive_filename;
40
41#define MAX_PERFNAME (1000)
42extern char perf_default_email[MAX_PERFNAME];
43extern char perf_default_name[MAX_PERFNAME];
44extern int user_ident_explicitly_given;
45
46extern const char *perf_log_output_encoding;
47extern const char *perf_mailmap_file;
48
49/* IO helper functions */
50extern void maybe_flush_or_die(FILE *, const char *);
51extern int copy_fd(int ifd, int ofd);
52extern int copy_file(const char *dst, const char *src, int mode);
53extern ssize_t read_in_full(int fd, void *buf, size_t count);
54extern ssize_t write_in_full(int fd, const void *buf, size_t count);
55extern void write_or_die(int fd, const void *buf, size_t count);
56extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
57extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
58extern void fsync_or_die(int fd, const char *);
59
60/* pager.c */
61extern void setup_pager(void);
62extern const char *pager_program;
63extern int pager_in_use(void);
64extern int pager_use_color;
65
66extern const char *editor_program;
67extern const char *excludes_file;
68
69char *alias_lookup(const char *alias);
70int split_cmdline(char *cmdline, const char ***argv);
71
72#define alloc_nr(x) (((x)+16)*3/2)
73
74/*
75 * Realloc the buffer pointed at by variable 'x' so that it can hold
76 * at least 'nr' entries; the number of entries currently allocated
77 * is 'alloc', using the standard growing factor alloc_nr() macro.
78 *
79 * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
80 */
81#define ALLOC_GROW(x, nr, alloc) \
82 do { \
83 if ((nr) > alloc) { \
84 if (alloc_nr(alloc) < (nr)) \
85 alloc = (nr); \
86 else \
87 alloc = alloc_nr(alloc); \
88 x = xrealloc((x), alloc * sizeof(*(x))); \
89 } \
90 } while(0)
91
92
93static inline int is_absolute_path(const char *path)
94{
95 return path[0] == '/';
96}
97#endif /* CACHE_H */
diff --git a/Documentation/perf_counter/command-list.txt b/Documentation/perf_counter/command-list.txt
new file mode 100644
index 000000000000..1eab3659b206
--- /dev/null
+++ b/Documentation/perf_counter/command-list.txt
@@ -0,0 +1,4 @@
1# List of known perf commands.
2# command name category [deprecated] [common]
3perf-top mainporcelain common
4
diff --git a/Documentation/perf_counter/config.c b/Documentation/perf_counter/config.c
new file mode 100644
index 000000000000..672d53959334
--- /dev/null
+++ b/Documentation/perf_counter/config.c
@@ -0,0 +1,966 @@
1/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 * Copyright (C) Johannes Schindelin, 2005
6 *
7 */
8#include "util.h"
9#include "cache.h"
10#include "exec_cmd.h"
11
12#define MAXNAME (256)
13
14static FILE *config_file;
15static const char *config_file_name;
16static int config_linenr;
17static int config_file_eof;
18static int zlib_compression_seen;
19
20const char *config_exclusive_filename = NULL;
21
22static int get_next_char(void)
23{
24 int c;
25 FILE *f;
26
27 c = '\n';
28 if ((f = config_file) != NULL) {
29 c = fgetc(f);
30 if (c == '\r') {
31 /* DOS like systems */
32 c = fgetc(f);
33 if (c != '\n') {
34 ungetc(c, f);
35 c = '\r';
36 }
37 }
38 if (c == '\n')
39 config_linenr++;
40 if (c == EOF) {
41 config_file_eof = 1;
42 c = '\n';
43 }
44 }
45 return c;
46}
47
48static char *parse_value(void)
49{
50 static char value[1024];
51 int quote = 0, comment = 0, len = 0, space = 0;
52
53 for (;;) {
54 int c = get_next_char();
55 if (len >= sizeof(value) - 1)
56 return NULL;
57 if (c == '\n') {
58 if (quote)
59 return NULL;
60 value[len] = 0;
61 return value;
62 }
63 if (comment)
64 continue;
65 if (isspace(c) && !quote) {
66 space = 1;
67 continue;
68 }
69 if (!quote) {
70 if (c == ';' || c == '#') {
71 comment = 1;
72 continue;
73 }
74 }
75 if (space) {
76 if (len)
77 value[len++] = ' ';
78 space = 0;
79 }
80 if (c == '\\') {
81 c = get_next_char();
82 switch (c) {
83 case '\n':
84 continue;
85 case 't':
86 c = '\t';
87 break;
88 case 'b':
89 c = '\b';
90 break;
91 case 'n':
92 c = '\n';
93 break;
94 /* Some characters escape as themselves */
95 case '\\': case '"':
96 break;
97 /* Reject unknown escape sequences */
98 default:
99 return NULL;
100 }
101 value[len++] = c;
102 continue;
103 }
104 if (c == '"') {
105 quote = 1-quote;
106 continue;
107 }
108 value[len++] = c;
109 }
110}
111
112static inline int iskeychar(int c)
113{
114 return isalnum(c) || c == '-';
115}
116
117static int get_value(config_fn_t fn, void *data, char *name, unsigned int len)
118{
119 int c;
120 char *value;
121
122 /* Get the full name */
123 for (;;) {
124 c = get_next_char();
125 if (config_file_eof)
126 break;
127 if (!iskeychar(c))
128 break;
129 name[len++] = tolower(c);
130 if (len >= MAXNAME)
131 return -1;
132 }
133 name[len] = 0;
134 while (c == ' ' || c == '\t')
135 c = get_next_char();
136
137 value = NULL;
138 if (c != '\n') {
139 if (c != '=')
140 return -1;
141 value = parse_value();
142 if (!value)
143 return -1;
144 }
145 return fn(name, value, data);
146}
147
148static int get_extended_base_var(char *name, int baselen, int c)
149{
150 do {
151 if (c == '\n')
152 return -1;
153 c = get_next_char();
154 } while (isspace(c));
155
156 /* We require the format to be '[base "extension"]' */
157 if (c != '"')
158 return -1;
159 name[baselen++] = '.';
160
161 for (;;) {
162 int c = get_next_char();
163 if (c == '\n')
164 return -1;
165 if (c == '"')
166 break;
167 if (c == '\\') {
168 c = get_next_char();
169 if (c == '\n')
170 return -1;
171 }
172 name[baselen++] = c;
173 if (baselen > MAXNAME / 2)
174 return -1;
175 }
176
177 /* Final ']' */
178 if (get_next_char() != ']')
179 return -1;
180 return baselen;
181}
182
183static int get_base_var(char *name)
184{
185 int baselen = 0;
186
187 for (;;) {
188 int c = get_next_char();
189 if (config_file_eof)
190 return -1;
191 if (c == ']')
192 return baselen;
193 if (isspace(c))
194 return get_extended_base_var(name, baselen, c);
195 if (!iskeychar(c) && c != '.')
196 return -1;
197 if (baselen > MAXNAME / 2)
198 return -1;
199 name[baselen++] = tolower(c);
200 }
201}
202
203static int perf_parse_file(config_fn_t fn, void *data)
204{
205 int comment = 0;
206 int baselen = 0;
207 static char var[MAXNAME];
208
209 /* U+FEFF Byte Order Mark in UTF8 */
210 static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf";
211 const unsigned char *bomptr = utf8_bom;
212
213 for (;;) {
214 int c = get_next_char();
215 if (bomptr && *bomptr) {
216 /* We are at the file beginning; skip UTF8-encoded BOM
217 * if present. Sane editors won't put this in on their
218 * own, but e.g. Windows Notepad will do it happily. */
219 if ((unsigned char) c == *bomptr) {
220 bomptr++;
221 continue;
222 } else {
223 /* Do not tolerate partial BOM. */
224 if (bomptr != utf8_bom)
225 break;
226 /* No BOM at file beginning. Cool. */
227 bomptr = NULL;
228 }
229 }
230 if (c == '\n') {
231 if (config_file_eof)
232 return 0;
233 comment = 0;
234 continue;
235 }
236 if (comment || isspace(c))
237 continue;
238 if (c == '#' || c == ';') {
239 comment = 1;
240 continue;
241 }
242 if (c == '[') {
243 baselen = get_base_var(var);
244 if (baselen <= 0)
245 break;
246 var[baselen++] = '.';
247 var[baselen] = 0;
248 continue;
249 }
250 if (!isalpha(c))
251 break;
252 var[baselen] = tolower(c);
253 if (get_value(fn, data, var, baselen+1) < 0)
254 break;
255 }
256 die("bad config file line %d in %s", config_linenr, config_file_name);
257}
258
259static int parse_unit_factor(const char *end, unsigned long *val)
260{
261 if (!*end)
262 return 1;
263 else if (!strcasecmp(end, "k")) {
264 *val *= 1024;
265 return 1;
266 }
267 else if (!strcasecmp(end, "m")) {
268 *val *= 1024 * 1024;
269 return 1;
270 }
271 else if (!strcasecmp(end, "g")) {
272 *val *= 1024 * 1024 * 1024;
273 return 1;
274 }
275 return 0;
276}
277
278static int perf_parse_long(const char *value, long *ret)
279{
280 if (value && *value) {
281 char *end;
282 long val = strtol(value, &end, 0);
283 unsigned long factor = 1;
284 if (!parse_unit_factor(end, &factor))
285 return 0;
286 *ret = val * factor;
287 return 1;
288 }
289 return 0;
290}
291
292int perf_parse_ulong(const char *value, unsigned long *ret)
293{
294 if (value && *value) {
295 char *end;
296 unsigned long val = strtoul(value, &end, 0);
297 if (!parse_unit_factor(end, &val))
298 return 0;
299 *ret = val;
300 return 1;
301 }
302 return 0;
303}
304
305static void die_bad_config(const char *name)
306{
307 if (config_file_name)
308 die("bad config value for '%s' in %s", name, config_file_name);
309 die("bad config value for '%s'", name);
310}
311
312int perf_config_int(const char *name, const char *value)
313{
314 long ret = 0;
315 if (!perf_parse_long(value, &ret))
316 die_bad_config(name);
317 return ret;
318}
319
320unsigned long perf_config_ulong(const char *name, const char *value)
321{
322 unsigned long ret;
323 if (!perf_parse_ulong(value, &ret))
324 die_bad_config(name);
325 return ret;
326}
327
328int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
329{
330 *is_bool = 1;
331 if (!value)
332 return 1;
333 if (!*value)
334 return 0;
335 if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on"))
336 return 1;
337 if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off"))
338 return 0;
339 *is_bool = 0;
340 return perf_config_int(name, value);
341}
342
343int perf_config_bool(const char *name, const char *value)
344{
345 int discard;
346 return !!perf_config_bool_or_int(name, value, &discard);
347}
348
349int perf_config_string(const char **dest, const char *var, const char *value)
350{
351 if (!value)
352 return config_error_nonbool(var);
353 *dest = strdup(value);
354 return 0;
355}
356
357static int perf_default_core_config(const char *var, const char *value)
358{
359 /* Add other config variables here and to Documentation/config.txt. */
360 return 0;
361}
362
363int perf_default_config(const char *var, const char *value, void *dummy)
364{
365 if (!prefixcmp(var, "core."))
366 return perf_default_core_config(var, value);
367
368 /* Add other config variables here and to Documentation/config.txt. */
369 return 0;
370}
371
372int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
373{
374 int ret;
375 FILE *f = fopen(filename, "r");
376
377 ret = -1;
378 if (f) {
379 config_file = f;
380 config_file_name = filename;
381 config_linenr = 1;
382 config_file_eof = 0;
383 ret = perf_parse_file(fn, data);
384 fclose(f);
385 config_file_name = NULL;
386 }
387 return ret;
388}
389
390const char *perf_etc_perfconfig(void)
391{
392 static const char *system_wide;
393 if (!system_wide)
394 system_wide = system_path(ETC_PERFCONFIG);
395 return system_wide;
396}
397
398static int perf_env_bool(const char *k, int def)
399{
400 const char *v = getenv(k);
401 return v ? perf_config_bool(k, v) : def;
402}
403
404int perf_config_system(void)
405{
406 return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0);
407}
408
409int perf_config_global(void)
410{
411 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
412}
413
414int perf_config(config_fn_t fn, void *data)
415{
416 int ret = 0, found = 0;
417 char *repo_config = NULL;
418 const char *home = NULL;
419
420 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
421 if (config_exclusive_filename)
422 return perf_config_from_file(fn, config_exclusive_filename, data);
423 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) {
424 ret += perf_config_from_file(fn, perf_etc_perfconfig(),
425 data);
426 found += 1;
427 }
428
429 home = getenv("HOME");
430 if (perf_config_global() && home) {
431 char *user_config = strdup(mkpath("%s/.perfconfig", home));
432 if (!access(user_config, R_OK)) {
433 ret += perf_config_from_file(fn, user_config, data);
434 found += 1;
435 }
436 free(user_config);
437 }
438
439 repo_config = perf_pathdup("config");
440 if (!access(repo_config, R_OK)) {
441 ret += perf_config_from_file(fn, repo_config, data);
442 found += 1;
443 }
444 free(repo_config);
445 if (found == 0)
446 return -1;
447 return ret;
448}
449
450/*
451 * Find all the stuff for perf_config_set() below.
452 */
453
454#define MAX_MATCHES 512
455
456static struct {
457 int baselen;
458 char* key;
459 int do_not_match;
460 regex_t* value_regex;
461 int multi_replace;
462 size_t offset[MAX_MATCHES];
463 enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
464 int seen;
465} store;
466
467static int matches(const char* key, const char* value)
468{
469 return !strcmp(key, store.key) &&
470 (store.value_regex == NULL ||
471 (store.do_not_match ^
472 !regexec(store.value_regex, value, 0, NULL, 0)));
473}
474
475static int store_aux(const char* key, const char* value, void *cb)
476{
477 const char *ep;
478 size_t section_len;
479
480 switch (store.state) {
481 case KEY_SEEN:
482 if (matches(key, value)) {
483 if (store.seen == 1 && store.multi_replace == 0) {
484 warning("%s has multiple values", key);
485 } else if (store.seen >= MAX_MATCHES) {
486 error("too many matches for %s", key);
487 return 1;
488 }
489
490 store.offset[store.seen] = ftell(config_file);
491 store.seen++;
492 }
493 break;
494 case SECTION_SEEN:
495 /*
496 * What we are looking for is in store.key (both
497 * section and var), and its section part is baselen
498 * long. We found key (again, both section and var).
499 * We would want to know if this key is in the same
500 * section as what we are looking for. We already
501 * know we are in the same section as what should
502 * hold store.key.
503 */
504 ep = strrchr(key, '.');
505 section_len = ep - key;
506
507 if ((section_len != store.baselen) ||
508 memcmp(key, store.key, section_len+1)) {
509 store.state = SECTION_END_SEEN;
510 break;
511 }
512
513 /*
514 * Do not increment matches: this is no match, but we
515 * just made sure we are in the desired section.
516 */
517 store.offset[store.seen] = ftell(config_file);
518 /* fallthru */
519 case SECTION_END_SEEN:
520 case START:
521 if (matches(key, value)) {
522 store.offset[store.seen] = ftell(config_file);
523 store.state = KEY_SEEN;
524 store.seen++;
525 } else {
526 if (strrchr(key, '.') - key == store.baselen &&
527 !strncmp(key, store.key, store.baselen)) {
528 store.state = SECTION_SEEN;
529 store.offset[store.seen] = ftell(config_file);
530 }
531 }
532 }
533 return 0;
534}
535
536static int write_error(const char *filename)
537{
538 error("failed to write new configuration file %s", filename);
539
540 /* Same error code as "failed to rename". */
541 return 4;
542}
543
544static int store_write_section(int fd, const char* key)
545{
546 const char *dot;
547 int i, success;
548 struct strbuf sb = STRBUF_INIT;
549
550 dot = memchr(key, '.', store.baselen);
551 if (dot) {
552 strbuf_addf(&sb, "[%.*s \"", (int)(dot - key), key);
553 for (i = dot - key + 1; i < store.baselen; i++) {
554 if (key[i] == '"' || key[i] == '\\')
555 strbuf_addch(&sb, '\\');
556 strbuf_addch(&sb, key[i]);
557 }
558 strbuf_addstr(&sb, "\"]\n");
559 } else {
560 strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
561 }
562
563 success = write_in_full(fd, sb.buf, sb.len) == sb.len;
564 strbuf_release(&sb);
565
566 return success;
567}
568
569static int store_write_pair(int fd, const char* key, const char* value)
570{
571 int i, success;
572 int length = strlen(key + store.baselen + 1);
573 const char *quote = "";
574 struct strbuf sb = STRBUF_INIT;
575
576 /*
577 * Check to see if the value needs to be surrounded with a dq pair.
578 * Note that problematic characters are always backslash-quoted; this
579 * check is about not losing leading or trailing SP and strings that
580 * follow beginning-of-comment characters (i.e. ';' and '#') by the
581 * configuration parser.
582 */
583 if (value[0] == ' ')
584 quote = "\"";
585 for (i = 0; value[i]; i++)
586 if (value[i] == ';' || value[i] == '#')
587 quote = "\"";
588 if (i && value[i - 1] == ' ')
589 quote = "\"";
590
591 strbuf_addf(&sb, "\t%.*s = %s",
592 length, key + store.baselen + 1, quote);
593
594 for (i = 0; value[i]; i++)
595 switch (value[i]) {
596 case '\n':
597 strbuf_addstr(&sb, "\\n");
598 break;
599 case '\t':
600 strbuf_addstr(&sb, "\\t");
601 break;
602 case '"':
603 case '\\':
604 strbuf_addch(&sb, '\\');
605 default:
606 strbuf_addch(&sb, value[i]);
607 break;
608 }
609 strbuf_addf(&sb, "%s\n", quote);
610
611 success = write_in_full(fd, sb.buf, sb.len) == sb.len;
612 strbuf_release(&sb);
613
614 return success;
615}
616
617static ssize_t find_beginning_of_line(const char* contents, size_t size,
618 size_t offset_, int* found_bracket)
619{
620 size_t equal_offset = size, bracket_offset = size;
621 ssize_t offset;
622
623contline:
624 for (offset = offset_-2; offset > 0
625 && contents[offset] != '\n'; offset--)
626 switch (contents[offset]) {
627 case '=': equal_offset = offset; break;
628 case ']': bracket_offset = offset; break;
629 }
630 if (offset > 0 && contents[offset-1] == '\\') {
631 offset_ = offset;
632 goto contline;
633 }
634 if (bracket_offset < equal_offset) {
635 *found_bracket = 1;
636 offset = bracket_offset+1;
637 } else
638 offset++;
639
640 return offset;
641}
642
643int perf_config_set(const char* key, const char* value)
644{
645 return perf_config_set_multivar(key, value, NULL, 0);
646}
647
648/*
649 * If value==NULL, unset in (remove from) config,
650 * if value_regex!=NULL, disregard key/value pairs where value does not match.
651 * if multi_replace==0, nothing, or only one matching key/value is replaced,
652 * else all matching key/values (regardless how many) are removed,
653 * before the new pair is written.
654 *
655 * Returns 0 on success.
656 *
657 * This function does this:
658 *
659 * - it locks the config file by creating ".perf/config.lock"
660 *
661 * - it then parses the config using store_aux() as validator to find
662 * the position on the key/value pair to replace. If it is to be unset,
663 * it must be found exactly once.
664 *
665 * - the config file is mmap()ed and the part before the match (if any) is
666 * written to the lock file, then the changed part and the rest.
667 *
668 * - the config file is removed and the lock file rename()d to it.
669 *
670 */
671int perf_config_set_multivar(const char* key, const char* value,
672 const char* value_regex, int multi_replace)
673{
674 int i, dot;
675 int fd = -1, in_fd;
676 int ret;
677 char* config_filename;
678 const char* last_dot = strrchr(key, '.');
679
680 if (config_exclusive_filename)
681 config_filename = strdup(config_exclusive_filename);
682 else
683 config_filename = perf_pathdup("config");
684
685 /*
686 * Since "key" actually contains the section name and the real
687 * key name separated by a dot, we have to know where the dot is.
688 */
689
690 if (last_dot == NULL) {
691 error("key does not contain a section: %s", key);
692 ret = 2;
693 goto out_free;
694 }
695 store.baselen = last_dot - key;
696
697 store.multi_replace = multi_replace;
698
699 /*
700 * Validate the key and while at it, lower case it for matching.
701 */
702 store.key = malloc(strlen(key) + 1);
703 dot = 0;
704 for (i = 0; key[i]; i++) {
705 unsigned char c = key[i];
706 if (c == '.')
707 dot = 1;
708 /* Leave the extended basename untouched.. */
709 if (!dot || i > store.baselen) {
710 if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) {
711 error("invalid key: %s", key);
712 free(store.key);
713 ret = 1;
714 goto out_free;
715 }
716 c = tolower(c);
717 } else if (c == '\n') {
718 error("invalid key (newline): %s", key);
719 free(store.key);
720 ret = 1;
721 goto out_free;
722 }
723 store.key[i] = c;
724 }
725 store.key[i] = 0;
726
727 /*
728 * If .perf/config does not exist yet, write a minimal version.
729 */
730 in_fd = open(config_filename, O_RDONLY);
731 if ( in_fd < 0 ) {
732 free(store.key);
733
734 if ( ENOENT != errno ) {
735 error("opening %s: %s", config_filename,
736 strerror(errno));
737 ret = 3; /* same as "invalid config file" */
738 goto out_free;
739 }
740 /* if nothing to unset, error out */
741 if (value == NULL) {
742 ret = 5;
743 goto out_free;
744 }
745
746 store.key = (char*)key;
747 if (!store_write_section(fd, key) ||
748 !store_write_pair(fd, key, value))
749 goto write_err_out;
750 } else {
751 struct stat st;
752 char* contents;
753 size_t contents_sz, copy_begin, copy_end;
754 int i, new_line = 0;
755
756 if (value_regex == NULL)
757 store.value_regex = NULL;
758 else {
759 if (value_regex[0] == '!') {
760 store.do_not_match = 1;
761 value_regex++;
762 } else
763 store.do_not_match = 0;
764
765 store.value_regex = (regex_t*)malloc(sizeof(regex_t));
766 if (regcomp(store.value_regex, value_regex,
767 REG_EXTENDED)) {
768 error("invalid pattern: %s", value_regex);
769 free(store.value_regex);
770 ret = 6;
771 goto out_free;
772 }
773 }
774
775 store.offset[0] = 0;
776 store.state = START;
777 store.seen = 0;
778
779 /*
780 * After this, store.offset will contain the *end* offset
781 * of the last match, or remain at 0 if no match was found.
782 * As a side effect, we make sure to transform only a valid
783 * existing config file.
784 */
785 if (perf_config_from_file(store_aux, config_filename, NULL)) {
786 error("invalid config file %s", config_filename);
787 free(store.key);
788 if (store.value_regex != NULL) {
789 regfree(store.value_regex);
790 free(store.value_regex);
791 }
792 ret = 3;
793 goto out_free;
794 }
795
796 free(store.key);
797 if (store.value_regex != NULL) {
798 regfree(store.value_regex);
799 free(store.value_regex);
800 }
801
802 /* if nothing to unset, or too many matches, error out */
803 if ((store.seen == 0 && value == NULL) ||
804 (store.seen > 1 && multi_replace == 0)) {
805 ret = 5;
806 goto out_free;
807 }
808
809 fstat(in_fd, &st);
810 contents_sz = xsize_t(st.st_size);
811 contents = mmap(NULL, contents_sz, PROT_READ,
812 MAP_PRIVATE, in_fd, 0);
813 close(in_fd);
814
815 if (store.seen == 0)
816 store.seen = 1;
817
818 for (i = 0, copy_begin = 0; i < store.seen; i++) {
819 if (store.offset[i] == 0) {
820 store.offset[i] = copy_end = contents_sz;
821 } else if (store.state != KEY_SEEN) {
822 copy_end = store.offset[i];
823 } else
824 copy_end = find_beginning_of_line(
825 contents, contents_sz,
826 store.offset[i]-2, &new_line);
827
828 if (copy_end > 0 && contents[copy_end-1] != '\n')
829 new_line = 1;
830
831 /* write the first part of the config */
832 if (copy_end > copy_begin) {
833 if (write_in_full(fd, contents + copy_begin,
834 copy_end - copy_begin) <
835 copy_end - copy_begin)
836 goto write_err_out;
837 if (new_line &&
838 write_in_full(fd, "\n", 1) != 1)
839 goto write_err_out;
840 }
841 copy_begin = store.offset[i];
842 }
843
844 /* write the pair (value == NULL means unset) */
845 if (value != NULL) {
846 if (store.state == START) {
847 if (!store_write_section(fd, key))
848 goto write_err_out;
849 }
850 if (!store_write_pair(fd, key, value))
851 goto write_err_out;
852 }
853
854 /* write the rest of the config */
855 if (copy_begin < contents_sz)
856 if (write_in_full(fd, contents + copy_begin,
857 contents_sz - copy_begin) <
858 contents_sz - copy_begin)
859 goto write_err_out;
860
861 munmap(contents, contents_sz);
862 }
863
864 ret = 0;
865
866out_free:
867 free(config_filename);
868 return ret;
869
870write_err_out:
871 goto out_free;
872
873}
874
875static int section_name_match (const char *buf, const char *name)
876{
877 int i = 0, j = 0, dot = 0;
878 for (; buf[i] && buf[i] != ']'; i++) {
879 if (!dot && isspace(buf[i])) {
880 dot = 1;
881 if (name[j++] != '.')
882 break;
883 for (i++; isspace(buf[i]); i++)
884 ; /* do nothing */
885 if (buf[i] != '"')
886 break;
887 continue;
888 }
889 if (buf[i] == '\\' && dot)
890 i++;
891 else if (buf[i] == '"' && dot) {
892 for (i++; isspace(buf[i]); i++)
893 ; /* do_nothing */
894 break;
895 }
896 if (buf[i] != name[j++])
897 break;
898 }
899 return (buf[i] == ']' && name[j] == 0);
900}
901
902/* if new_name == NULL, the section is removed instead */
903int perf_config_rename_section(const char *old_name, const char *new_name)
904{
905 int ret = 0, remove = 0;
906 char *config_filename;
907 int out_fd;
908 char buf[1024];
909
910 if (config_exclusive_filename)
911 config_filename = strdup(config_exclusive_filename);
912 else
913 config_filename = perf_pathdup("config");
914 if (out_fd < 0) {
915 ret = error("could not lock config file %s", config_filename);
916 goto out;
917 }
918
919 if (!(config_file = fopen(config_filename, "rb"))) {
920 /* no config file means nothing to rename, no error */
921 goto unlock_and_out;
922 }
923
924 while (fgets(buf, sizeof(buf), config_file)) {
925 int i;
926 int length;
927 for (i = 0; buf[i] && isspace(buf[i]); i++)
928 ; /* do nothing */
929 if (buf[i] == '[') {
930 /* it's a section */
931 if (section_name_match (&buf[i+1], old_name)) {
932 ret++;
933 if (new_name == NULL) {
934 remove = 1;
935 continue;
936 }
937 store.baselen = strlen(new_name);
938 if (!store_write_section(out_fd, new_name)) {
939 goto out;
940 }
941 continue;
942 }
943 remove = 0;
944 }
945 if (remove)
946 continue;
947 length = strlen(buf);
948 if (write_in_full(out_fd, buf, length) != length) {
949 goto out;
950 }
951 }
952 fclose(config_file);
953 unlock_and_out:
954 out:
955 free(config_filename);
956 return ret;
957}
958
959/*
960 * Call this to report error for your variable that should not
961 * get a boolean value (i.e. "[my] var" means "true").
962 */
963int config_error_nonbool(const char *var)
964{
965 return error("Missing value for '%s'", var);
966}
diff --git a/Documentation/perf_counter/ctype.c b/Documentation/perf_counter/ctype.c
new file mode 100644
index 000000000000..b90ec004f29c
--- /dev/null
+++ b/Documentation/perf_counter/ctype.c
@@ -0,0 +1,26 @@
1/*
2 * Sane locale-independent, ASCII ctype.
3 *
4 * No surprises, and works with signed and unsigned chars.
5 */
6#include "cache.h"
7
8enum {
9 S = GIT_SPACE,
10 A = GIT_ALPHA,
11 D = GIT_DIGIT,
12 G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */
13 R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */
14};
15
16unsigned char sane_ctype[256] = {
17 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */
19 S, 0, 0, 0, R, 0, 0, 0, R, R, G, R, 0, 0, R, 0, /* 32.. 47 */
20 D, D, D, D, D, D, D, D, D, D, 0, 0, 0, 0, 0, G, /* 48.. 63 */
21 0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */
22 A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, 0, /* 80.. 95 */
23 0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */
24 A, A, A, A, A, A, A, A, A, A, A, R, R, 0, 0, 0, /* 112..127 */
25 /* Nothing in the 128.. range */
26};
diff --git a/Documentation/perf_counter/exec_cmd.c b/Documentation/perf_counter/exec_cmd.c
new file mode 100644
index 000000000000..d39292263153
--- /dev/null
+++ b/Documentation/perf_counter/exec_cmd.c
@@ -0,0 +1,165 @@
1#include "cache.h"
2#include "exec_cmd.h"
3#include "quote.h"
4#define MAX_ARGS 32
5
6extern char **environ;
7static const char *argv_exec_path;
8static const char *argv0_path;
9
10const char *system_path(const char *path)
11{
12#ifdef RUNTIME_PREFIX
13 static const char *prefix;
14#else
15 static const char *prefix = PREFIX;
16#endif
17 struct strbuf d = STRBUF_INIT;
18
19 if (is_absolute_path(path))
20 return path;
21
22#ifdef RUNTIME_PREFIX
23 assert(argv0_path);
24 assert(is_absolute_path(argv0_path));
25
26 if (!prefix &&
27 !(prefix = strip_path_suffix(argv0_path, PERF_EXEC_PATH)) &&
28 !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
29 !(prefix = strip_path_suffix(argv0_path, "perf"))) {
30 prefix = PREFIX;
31 fprintf(stderr, "RUNTIME_PREFIX requested, "
32 "but prefix computation failed. "
33 "Using static fallback '%s'.\n", prefix);
34 }
35#endif
36
37 strbuf_addf(&d, "%s/%s", prefix, path);
38 path = strbuf_detach(&d, NULL);
39 return path;
40}
41
42const char *perf_extract_argv0_path(const char *argv0)
43{
44 const char *slash;
45
46 if (!argv0 || !*argv0)
47 return NULL;
48 slash = argv0 + strlen(argv0);
49
50 while (argv0 <= slash && !is_dir_sep(*slash))
51 slash--;
52
53 if (slash >= argv0) {
54 argv0_path = strndup(argv0, slash - argv0);
55 return slash + 1;
56 }
57
58 return argv0;
59}
60
61void perf_set_argv_exec_path(const char *exec_path)
62{
63 argv_exec_path = exec_path;
64 /*
65 * Propagate this setting to external programs.
66 */
67 setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
68}
69
70
71/* Returns the highest-priority, location to look for perf programs. */
72const char *perf_exec_path(void)
73{
74 const char *env;
75
76 if (argv_exec_path)
77 return argv_exec_path;
78
79 env = getenv(EXEC_PATH_ENVIRONMENT);
80 if (env && *env) {
81 return env;
82 }
83
84 return system_path(PERF_EXEC_PATH);
85}
86
87static void add_path(struct strbuf *out, const char *path)
88{
89 if (path && *path) {
90 if (is_absolute_path(path))
91 strbuf_addstr(out, path);
92 else
93 strbuf_addstr(out, make_nonrelative_path(path));
94
95 strbuf_addch(out, PATH_SEP);
96 }
97}
98
99void setup_path(void)
100{
101 const char *old_path = getenv("PATH");
102 struct strbuf new_path = STRBUF_INIT;
103
104 add_path(&new_path, perf_exec_path());
105 add_path(&new_path, argv0_path);
106
107 if (old_path)
108 strbuf_addstr(&new_path, old_path);
109 else
110 strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
111
112 setenv("PATH", new_path.buf, 1);
113
114 strbuf_release(&new_path);
115}
116
117const char **prepare_perf_cmd(const char **argv)
118{
119 int argc;
120 const char **nargv;
121
122 for (argc = 0; argv[argc]; argc++)
123 ; /* just counting */
124 nargv = malloc(sizeof(*nargv) * (argc + 2));
125
126 nargv[0] = "perf";
127 for (argc = 0; argv[argc]; argc++)
128 nargv[argc + 1] = argv[argc];
129 nargv[argc + 1] = NULL;
130 return nargv;
131}
132
133int execv_perf_cmd(const char **argv) {
134 const char **nargv = prepare_perf_cmd(argv);
135
136 /* execvp() can only ever return if it fails */
137 execvp("perf", (char **)nargv);
138
139 free(nargv);
140 return -1;
141}
142
143
144int execl_perf_cmd(const char *cmd,...)
145{
146 int argc;
147 const char *argv[MAX_ARGS + 1];
148 const char *arg;
149 va_list param;
150
151 va_start(param, cmd);
152 argv[0] = cmd;
153 argc = 1;
154 while (argc < MAX_ARGS) {
155 arg = argv[argc++] = va_arg(param, char *);
156 if (!arg)
157 break;
158 }
159 va_end(param);
160 if (MAX_ARGS <= argc)
161 return error("too many args to run %s", cmd);
162
163 argv[argc] = NULL;
164 return execv_perf_cmd(argv);
165}
diff --git a/Documentation/perf_counter/exec_cmd.h b/Documentation/perf_counter/exec_cmd.h
new file mode 100644
index 000000000000..effe25eb1545
--- /dev/null
+++ b/Documentation/perf_counter/exec_cmd.h
@@ -0,0 +1,13 @@
1#ifndef PERF_EXEC_CMD_H
2#define PERF_EXEC_CMD_H
3
4extern void perf_set_argv_exec_path(const char *exec_path);
5extern const char *perf_extract_argv0_path(const char *path);
6extern const char *perf_exec_path(void);
7extern void setup_path(void);
8extern const char **prepare_perf_cmd(const char **argv);
9extern int execv_perf_cmd(const char **argv); /* NULL terminated */
10extern int execl_perf_cmd(const char *cmd, ...);
11extern const char *system_path(const char *path);
12
13#endif /* PERF_EXEC_CMD_H */
diff --git a/Documentation/perf_counter/generate-cmdlist.sh b/Documentation/perf_counter/generate-cmdlist.sh
new file mode 100755
index 000000000000..75c68d948fd3
--- /dev/null
+++ b/Documentation/perf_counter/generate-cmdlist.sh
@@ -0,0 +1,24 @@
1#!/bin/sh
2
3echo "/* Automatically generated by $0 */
4struct cmdname_help
5{
6 char name[16];
7 char help[80];
8};
9
10static struct cmdname_help common_cmds[] = {"
11
12sed -n -e 's/^git-\([^ ]*\)[ ].* common.*/\1/p' command-list.txt |
13sort |
14while read cmd
15do
16 sed -n '
17 /^NAME/,/git-'"$cmd"'/H
18 ${
19 x
20 s/.*git-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/
21 p
22 }' "Documentation/git-$cmd.txt"
23done
24echo "};"
diff --git a/Documentation/perf_counter/help.c b/Documentation/perf_counter/help.c
new file mode 100644
index 000000000000..ec0116721660
--- /dev/null
+++ b/Documentation/perf_counter/help.c
@@ -0,0 +1,366 @@
1#include "cache.h"
2#include "builtin.h"
3#include "exec_cmd.h"
4#include "levenshtein.h"
5#include "help.h"
6
7/* most GUI terminals set COLUMNS (although some don't export it) */
8static int term_columns(void)
9{
10 char *col_string = getenv("COLUMNS");
11 int n_cols;
12
13 if (col_string && (n_cols = atoi(col_string)) > 0)
14 return n_cols;
15
16#ifdef TIOCGWINSZ
17 {
18 struct winsize ws;
19 if (!ioctl(1, TIOCGWINSZ, &ws)) {
20 if (ws.ws_col)
21 return ws.ws_col;
22 }
23 }
24#endif
25
26 return 80;
27}
28
29void add_cmdname(struct cmdnames *cmds, const char *name, int len)
30{
31 struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
32
33 ent->len = len;
34 memcpy(ent->name, name, len);
35 ent->name[len] = 0;
36
37 ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc);
38 cmds->names[cmds->cnt++] = ent;
39}
40
41static void clean_cmdnames(struct cmdnames *cmds)
42{
43 int i;
44 for (i = 0; i < cmds->cnt; ++i)
45 free(cmds->names[i]);
46 free(cmds->names);
47 cmds->cnt = 0;
48 cmds->alloc = 0;
49}
50
51static int cmdname_compare(const void *a_, const void *b_)
52{
53 struct cmdname *a = *(struct cmdname **)a_;
54 struct cmdname *b = *(struct cmdname **)b_;
55 return strcmp(a->name, b->name);
56}
57
58static void uniq(struct cmdnames *cmds)
59{
60 int i, j;
61
62 if (!cmds->cnt)
63 return;
64
65 for (i = j = 1; i < cmds->cnt; i++)
66 if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name))
67 cmds->names[j++] = cmds->names[i];
68
69 cmds->cnt = j;
70}
71
72void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
73{
74 int ci, cj, ei;
75 int cmp;
76
77 ci = cj = ei = 0;
78 while (ci < cmds->cnt && ei < excludes->cnt) {
79 cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name);
80 if (cmp < 0)
81 cmds->names[cj++] = cmds->names[ci++];
82 else if (cmp == 0)
83 ci++, ei++;
84 else if (cmp > 0)
85 ei++;
86 }
87
88 while (ci < cmds->cnt)
89 cmds->names[cj++] = cmds->names[ci++];
90
91 cmds->cnt = cj;
92}
93
94static void pretty_print_string_list(struct cmdnames *cmds, int longest)
95{
96 int cols = 1, rows;
97 int space = longest + 1; /* min 1 SP between words */
98 int max_cols = term_columns() - 1; /* don't print *on* the edge */
99 int i, j;
100
101 if (space < max_cols)
102 cols = max_cols / space;
103 rows = (cmds->cnt + cols - 1) / cols;
104
105 for (i = 0; i < rows; i++) {
106 printf(" ");
107
108 for (j = 0; j < cols; j++) {
109 int n = j * rows + i;
110 int size = space;
111 if (n >= cmds->cnt)
112 break;
113 if (j == cols-1 || n + rows >= cmds->cnt)
114 size = 1;
115 printf("%-*s", size, cmds->names[n]->name);
116 }
117 putchar('\n');
118 }
119}
120
121static int is_executable(const char *name)
122{
123 struct stat st;
124
125 if (stat(name, &st) || /* stat, not lstat */
126 !S_ISREG(st.st_mode))
127 return 0;
128
129#ifdef __MINGW32__
130 /* cannot trust the executable bit, peek into the file instead */
131 char buf[3] = { 0 };
132 int n;
133 int fd = open(name, O_RDONLY);
134 st.st_mode &= ~S_IXUSR;
135 if (fd >= 0) {
136 n = read(fd, buf, 2);
137 if (n == 2)
138 /* DOS executables start with "MZ" */
139 if (!strcmp(buf, "#!") || !strcmp(buf, "MZ"))
140 st.st_mode |= S_IXUSR;
141 close(fd);
142 }
143#endif
144 return st.st_mode & S_IXUSR;
145}
146
147static void list_commands_in_dir(struct cmdnames *cmds,
148 const char *path,
149 const char *prefix)
150{
151 int prefix_len;
152 DIR *dir = opendir(path);
153 struct dirent *de;
154 struct strbuf buf = STRBUF_INIT;
155 int len;
156
157 if (!dir)
158 return;
159 if (!prefix)
160 prefix = "perf-";
161 prefix_len = strlen(prefix);
162
163 strbuf_addf(&buf, "%s/", path);
164 len = buf.len;
165
166 while ((de = readdir(dir)) != NULL) {
167 int entlen;
168
169 if (prefixcmp(de->d_name, prefix))
170 continue;
171
172 strbuf_setlen(&buf, len);
173 strbuf_addstr(&buf, de->d_name);
174 if (!is_executable(buf.buf))
175 continue;
176
177 entlen = strlen(de->d_name) - prefix_len;
178 if (has_extension(de->d_name, ".exe"))
179 entlen -= 4;
180
181 add_cmdname(cmds, de->d_name + prefix_len, entlen);
182 }
183 closedir(dir);
184 strbuf_release(&buf);
185}
186
187void load_command_list(const char *prefix,
188 struct cmdnames *main_cmds,
189 struct cmdnames *other_cmds)
190{
191 const char *env_path = getenv("PATH");
192 const char *exec_path = perf_exec_path();
193
194 if (exec_path) {
195 list_commands_in_dir(main_cmds, exec_path, prefix);
196 qsort(main_cmds->names, main_cmds->cnt,
197 sizeof(*main_cmds->names), cmdname_compare);
198 uniq(main_cmds);
199 }
200
201 if (env_path) {
202 char *paths, *path, *colon;
203 path = paths = strdup(env_path);
204 while (1) {
205 if ((colon = strchr(path, PATH_SEP)))
206 *colon = 0;
207 if (!exec_path || strcmp(path, exec_path))
208 list_commands_in_dir(other_cmds, path, prefix);
209
210 if (!colon)
211 break;
212 path = colon + 1;
213 }
214 free(paths);
215
216 qsort(other_cmds->names, other_cmds->cnt,
217 sizeof(*other_cmds->names), cmdname_compare);
218 uniq(other_cmds);
219 }
220 exclude_cmds(other_cmds, main_cmds);
221}
222
223void list_commands(const char *title, struct cmdnames *main_cmds,
224 struct cmdnames *other_cmds)
225{
226 int i, longest = 0;
227
228 for (i = 0; i < main_cmds->cnt; i++)
229 if (longest < main_cmds->names[i]->len)
230 longest = main_cmds->names[i]->len;
231 for (i = 0; i < other_cmds->cnt; i++)
232 if (longest < other_cmds->names[i]->len)
233 longest = other_cmds->names[i]->len;
234
235 if (main_cmds->cnt) {
236 const char *exec_path = perf_exec_path();
237 printf("available %s in '%s'\n", title, exec_path);
238 printf("----------------");
239 mput_char('-', strlen(title) + strlen(exec_path));
240 putchar('\n');
241 pretty_print_string_list(main_cmds, longest);
242 putchar('\n');
243 }
244
245 if (other_cmds->cnt) {
246 printf("%s available from elsewhere on your $PATH\n", title);
247 printf("---------------------------------------");
248 mput_char('-', strlen(title));
249 putchar('\n');
250 pretty_print_string_list(other_cmds, longest);
251 putchar('\n');
252 }
253}
254
255int is_in_cmdlist(struct cmdnames *c, const char *s)
256{
257 int i;
258 for (i = 0; i < c->cnt; i++)
259 if (!strcmp(s, c->names[i]->name))
260 return 1;
261 return 0;
262}
263
264static int autocorrect;
265static struct cmdnames aliases;
266
267static int perf_unknown_cmd_config(const char *var, const char *value, void *cb)
268{
269 if (!strcmp(var, "help.autocorrect"))
270 autocorrect = perf_config_int(var,value);
271 /* Also use aliases for command lookup */
272 if (!prefixcmp(var, "alias."))
273 add_cmdname(&aliases, var + 6, strlen(var + 6));
274
275 return perf_default_config(var, value, cb);
276}
277
278static int levenshtein_compare(const void *p1, const void *p2)
279{
280 const struct cmdname *const *c1 = p1, *const *c2 = p2;
281 const char *s1 = (*c1)->name, *s2 = (*c2)->name;
282 int l1 = (*c1)->len;
283 int l2 = (*c2)->len;
284 return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
285}
286
287static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
288{
289 int i;
290 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
291
292 for (i = 0; i < old->cnt; i++)
293 cmds->names[cmds->cnt++] = old->names[i];
294 free(old->names);
295 old->cnt = 0;
296 old->names = NULL;
297}
298
299const char *help_unknown_cmd(const char *cmd)
300{
301 int i, n, best_similarity = 0;
302 struct cmdnames main_cmds, other_cmds;
303
304 memset(&main_cmds, 0, sizeof(main_cmds));
305 memset(&other_cmds, 0, sizeof(main_cmds));
306 memset(&aliases, 0, sizeof(aliases));
307
308 perf_config(perf_unknown_cmd_config, NULL);
309
310 load_command_list("perf-", &main_cmds, &other_cmds);
311
312 add_cmd_list(&main_cmds, &aliases);
313 add_cmd_list(&main_cmds, &other_cmds);
314 qsort(main_cmds.names, main_cmds.cnt,
315 sizeof(main_cmds.names), cmdname_compare);
316 uniq(&main_cmds);
317
318 /* This reuses cmdname->len for similarity index */
319 for (i = 0; i < main_cmds.cnt; ++i)
320 main_cmds.names[i]->len =
321 levenshtein(cmd, main_cmds.names[i]->name, 0, 2, 1, 4);
322
323 qsort(main_cmds.names, main_cmds.cnt,
324 sizeof(*main_cmds.names), levenshtein_compare);
325
326 if (!main_cmds.cnt)
327 die ("Uh oh. Your system reports no Git commands at all.");
328
329 best_similarity = main_cmds.names[0]->len;
330 n = 1;
331 while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len)
332 ++n;
333 if (autocorrect && n == 1) {
334 const char *assumed = main_cmds.names[0]->name;
335 main_cmds.names[0] = NULL;
336 clean_cmdnames(&main_cmds);
337 fprintf(stderr, "WARNING: You called a Git program named '%s', "
338 "which does not exist.\n"
339 "Continuing under the assumption that you meant '%s'\n",
340 cmd, assumed);
341 if (autocorrect > 0) {
342 fprintf(stderr, "in %0.1f seconds automatically...\n",
343 (float)autocorrect/10.0);
344 poll(NULL, 0, autocorrect * 100);
345 }
346 return assumed;
347 }
348
349 fprintf(stderr, "perf: '%s' is not a perf-command. See 'perf --help'.\n", cmd);
350
351 if (best_similarity < 6) {
352 fprintf(stderr, "\nDid you mean %s?\n",
353 n < 2 ? "this": "one of these");
354
355 for (i = 0; i < n; i++)
356 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
357 }
358
359 exit(1);
360}
361
362int cmd_version(int argc, const char **argv, const char *prefix)
363{
364 printf("perf version %s\n", perf_version_string);
365 return 0;
366}
diff --git a/Documentation/perf_counter/help.h b/Documentation/perf_counter/help.h
new file mode 100644
index 000000000000..56bc15406ffc
--- /dev/null
+++ b/Documentation/perf_counter/help.h
@@ -0,0 +1,29 @@
1#ifndef HELP_H
2#define HELP_H
3
4struct cmdnames {
5 int alloc;
6 int cnt;
7 struct cmdname {
8 size_t len; /* also used for similarity index in help.c */
9 char name[FLEX_ARRAY];
10 } **names;
11};
12
13static inline void mput_char(char c, unsigned int num)
14{
15 while(num--)
16 putchar(c);
17}
18
19void load_command_list(const char *prefix,
20 struct cmdnames *main_cmds,
21 struct cmdnames *other_cmds);
22void add_cmdname(struct cmdnames *cmds, const char *name, int len);
23/* Here we require that excludes is a sorted list. */
24void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
25int is_in_cmdlist(struct cmdnames *c, const char *s);
26void list_commands(const char *title, struct cmdnames *main_cmds,
27 struct cmdnames *other_cmds);
28
29#endif /* HELP_H */
diff --git a/Documentation/perf_counter/levenshtein.c b/Documentation/perf_counter/levenshtein.c
new file mode 100644
index 000000000000..e521d1516df6
--- /dev/null
+++ b/Documentation/perf_counter/levenshtein.c
@@ -0,0 +1,84 @@
1#include "cache.h"
2#include "levenshtein.h"
3
4/*
5 * This function implements the Damerau-Levenshtein algorithm to
6 * calculate a distance between strings.
7 *
8 * Basically, it says how many letters need to be swapped, substituted,
9 * deleted from, or added to string1, at least, to get string2.
10 *
11 * The idea is to build a distance matrix for the substrings of both
12 * strings. To avoid a large space complexity, only the last three rows
13 * are kept in memory (if swaps had the same or higher cost as one deletion
14 * plus one insertion, only two rows would be needed).
15 *
16 * At any stage, "i + 1" denotes the length of the current substring of
17 * string1 that the distance is calculated for.
18 *
19 * row2 holds the current row, row1 the previous row (i.e. for the substring
20 * of string1 of length "i"), and row0 the row before that.
21 *
22 * In other words, at the start of the big loop, row2[j + 1] contains the
23 * Damerau-Levenshtein distance between the substring of string1 of length
24 * "i" and the substring of string2 of length "j + 1".
25 *
26 * All the big loop does is determine the partial minimum-cost paths.
27 *
28 * It does so by calculating the costs of the path ending in characters
29 * i (in string1) and j (in string2), respectively, given that the last
30 * operation is a substition, a swap, a deletion, or an insertion.
31 *
32 * This implementation allows the costs to be weighted:
33 *
34 * - w (as in "sWap")
35 * - s (as in "Substitution")
36 * - a (for insertion, AKA "Add")
37 * - d (as in "Deletion")
38 *
39 * Note that this algorithm calculates a distance _iff_ d == a.
40 */
41int levenshtein(const char *string1, const char *string2,
42 int w, int s, int a, int d)
43{
44 int len1 = strlen(string1), len2 = strlen(string2);
45 int *row0 = malloc(sizeof(int) * (len2 + 1));
46 int *row1 = malloc(sizeof(int) * (len2 + 1));
47 int *row2 = malloc(sizeof(int) * (len2 + 1));
48 int i, j;
49
50 for (j = 0; j <= len2; j++)
51 row1[j] = j * a;
52 for (i = 0; i < len1; i++) {
53 int *dummy;
54
55 row2[0] = (i + 1) * d;
56 for (j = 0; j < len2; j++) {
57 /* substitution */
58 row2[j + 1] = row1[j] + s * (string1[i] != string2[j]);
59 /* swap */
60 if (i > 0 && j > 0 && string1[i - 1] == string2[j] &&
61 string1[i] == string2[j - 1] &&
62 row2[j + 1] > row0[j - 1] + w)
63 row2[j + 1] = row0[j - 1] + w;
64 /* deletion */
65 if (row2[j + 1] > row1[j + 1] + d)
66 row2[j + 1] = row1[j + 1] + d;
67 /* insertion */
68 if (row2[j + 1] > row2[j] + a)
69 row2[j + 1] = row2[j] + a;
70 }
71
72 dummy = row0;
73 row0 = row1;
74 row1 = row2;
75 row2 = dummy;
76 }
77
78 i = row1[len2];
79 free(row0);
80 free(row1);
81 free(row2);
82
83 return i;
84}
diff --git a/Documentation/perf_counter/levenshtein.h b/Documentation/perf_counter/levenshtein.h
new file mode 100644
index 000000000000..0173abeef52c
--- /dev/null
+++ b/Documentation/perf_counter/levenshtein.h
@@ -0,0 +1,8 @@
1#ifndef LEVENSHTEIN_H
2#define LEVENSHTEIN_H
3
4int levenshtein(const char *string1, const char *string2,
5 int swap_penalty, int substition_penalty,
6 int insertion_penalty, int deletion_penalty);
7
8#endif
diff --git a/Documentation/perf_counter/parse-options.c b/Documentation/perf_counter/parse-options.c
new file mode 100644
index 000000000000..7464f34e5407
--- /dev/null
+++ b/Documentation/perf_counter/parse-options.c
@@ -0,0 +1,495 @@
1#include "util.h"
2#include "parse-options.h"
3#include "cache.h"
4
5#define OPT_SHORT 1
6#define OPT_UNSET 2
7
8static int opterror(const struct option *opt, const char *reason, int flags)
9{
10 if (flags & OPT_SHORT)
11 return error("switch `%c' %s", opt->short_name, reason);
12 if (flags & OPT_UNSET)
13 return error("option `no-%s' %s", opt->long_name, reason);
14 return error("option `%s' %s", opt->long_name, reason);
15}
16
17static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
18 int flags, const char **arg)
19{
20 if (p->opt) {
21 *arg = p->opt;
22 p->opt = NULL;
23 } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) {
24 *arg = (const char *)opt->defval;
25 } else if (p->argc > 1) {
26 p->argc--;
27 *arg = *++p->argv;
28 } else
29 return opterror(opt, "requires a value", flags);
30 return 0;
31}
32
33static int get_value(struct parse_opt_ctx_t *p,
34 const struct option *opt, int flags)
35{
36 const char *s, *arg;
37 const int unset = flags & OPT_UNSET;
38
39 if (unset && p->opt)
40 return opterror(opt, "takes no value", flags);
41 if (unset && (opt->flags & PARSE_OPT_NONEG))
42 return opterror(opt, "isn't available", flags);
43
44 if (!(flags & OPT_SHORT) && p->opt) {
45 switch (opt->type) {
46 case OPTION_CALLBACK:
47 if (!(opt->flags & PARSE_OPT_NOARG))
48 break;
49 /* FALLTHROUGH */
50 case OPTION_BOOLEAN:
51 case OPTION_BIT:
52 case OPTION_SET_INT:
53 case OPTION_SET_PTR:
54 return opterror(opt, "takes no value", flags);
55 default:
56 break;
57 }
58 }
59
60 switch (opt->type) {
61 case OPTION_BIT:
62 if (unset)
63 *(int *)opt->value &= ~opt->defval;
64 else
65 *(int *)opt->value |= opt->defval;
66 return 0;
67
68 case OPTION_BOOLEAN:
69 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
70 return 0;
71
72 case OPTION_SET_INT:
73 *(int *)opt->value = unset ? 0 : opt->defval;
74 return 0;
75
76 case OPTION_SET_PTR:
77 *(void **)opt->value = unset ? NULL : (void *)opt->defval;
78 return 0;
79
80 case OPTION_STRING:
81 if (unset)
82 *(const char **)opt->value = NULL;
83 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
84 *(const char **)opt->value = (const char *)opt->defval;
85 else
86 return get_arg(p, opt, flags, (const char **)opt->value);
87 return 0;
88
89 case OPTION_CALLBACK:
90 if (unset)
91 return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
92 if (opt->flags & PARSE_OPT_NOARG)
93 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
94 if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
95 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
96 if (get_arg(p, opt, flags, &arg))
97 return -1;
98 return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
99
100 case OPTION_INTEGER:
101 if (unset) {
102 *(int *)opt->value = 0;
103 return 0;
104 }
105 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
106 *(int *)opt->value = opt->defval;
107 return 0;
108 }
109 if (get_arg(p, opt, flags, &arg))
110 return -1;
111 *(int *)opt->value = strtol(arg, (char **)&s, 10);
112 if (*s)
113 return opterror(opt, "expects a numerical value", flags);
114 return 0;
115
116 default:
117 die("should not happen, someone must be hit on the forehead");
118 }
119}
120
121static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
122{
123 for (; options->type != OPTION_END; options++) {
124 if (options->short_name == *p->opt) {
125 p->opt = p->opt[1] ? p->opt + 1 : NULL;
126 return get_value(p, options, OPT_SHORT);
127 }
128 }
129 return -2;
130}
131
132static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
133 const struct option *options)
134{
135 const char *arg_end = strchr(arg, '=');
136 const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
137 int abbrev_flags = 0, ambiguous_flags = 0;
138
139 if (!arg_end)
140 arg_end = arg + strlen(arg);
141
142 for (; options->type != OPTION_END; options++) {
143 const char *rest;
144 int flags = 0;
145
146 if (!options->long_name)
147 continue;
148
149 rest = skip_prefix(arg, options->long_name);
150 if (options->type == OPTION_ARGUMENT) {
151 if (!rest)
152 continue;
153 if (*rest == '=')
154 return opterror(options, "takes no value", flags);
155 if (*rest)
156 continue;
157 p->out[p->cpidx++] = arg - 2;
158 return 0;
159 }
160 if (!rest) {
161 /* abbreviated? */
162 if (!strncmp(options->long_name, arg, arg_end - arg)) {
163is_abbreviated:
164 if (abbrev_option) {
165 /*
166 * If this is abbreviated, it is
167 * ambiguous. So when there is no
168 * exact match later, we need to
169 * error out.
170 */
171 ambiguous_option = abbrev_option;
172 ambiguous_flags = abbrev_flags;
173 }
174 if (!(flags & OPT_UNSET) && *arg_end)
175 p->opt = arg_end + 1;
176 abbrev_option = options;
177 abbrev_flags = flags;
178 continue;
179 }
180 /* negated and abbreviated very much? */
181 if (!prefixcmp("no-", arg)) {
182 flags |= OPT_UNSET;
183 goto is_abbreviated;
184 }
185 /* negated? */
186 if (strncmp(arg, "no-", 3))
187 continue;
188 flags |= OPT_UNSET;
189 rest = skip_prefix(arg + 3, options->long_name);
190 /* abbreviated and negated? */
191 if (!rest && !prefixcmp(options->long_name, arg + 3))
192 goto is_abbreviated;
193 if (!rest)
194 continue;
195 }
196 if (*rest) {
197 if (*rest != '=')
198 continue;
199 p->opt = rest + 1;
200 }
201 return get_value(p, options, flags);
202 }
203
204 if (ambiguous_option)
205 return error("Ambiguous option: %s "
206 "(could be --%s%s or --%s%s)",
207 arg,
208 (ambiguous_flags & OPT_UNSET) ? "no-" : "",
209 ambiguous_option->long_name,
210 (abbrev_flags & OPT_UNSET) ? "no-" : "",
211 abbrev_option->long_name);
212 if (abbrev_option)
213 return get_value(p, abbrev_option, abbrev_flags);
214 return -2;
215}
216
217static void check_typos(const char *arg, const struct option *options)
218{
219 if (strlen(arg) < 3)
220 return;
221
222 if (!prefixcmp(arg, "no-")) {
223 error ("did you mean `--%s` (with two dashes ?)", arg);
224 exit(129);
225 }
226
227 for (; options->type != OPTION_END; options++) {
228 if (!options->long_name)
229 continue;
230 if (!prefixcmp(options->long_name, arg)) {
231 error ("did you mean `--%s` (with two dashes ?)", arg);
232 exit(129);
233 }
234 }
235}
236
237void parse_options_start(struct parse_opt_ctx_t *ctx,
238 int argc, const char **argv, int flags)
239{
240 memset(ctx, 0, sizeof(*ctx));
241 ctx->argc = argc - 1;
242 ctx->argv = argv + 1;
243 ctx->out = argv;
244 ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
245 ctx->flags = flags;
246 if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
247 (flags & PARSE_OPT_STOP_AT_NON_OPTION))
248 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
249}
250
251static int usage_with_options_internal(const char * const *,
252 const struct option *, int);
253
254int parse_options_step(struct parse_opt_ctx_t *ctx,
255 const struct option *options,
256 const char * const usagestr[])
257{
258 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
259
260 /* we must reset ->opt, unknown short option leave it dangling */
261 ctx->opt = NULL;
262
263 for (; ctx->argc; ctx->argc--, ctx->argv++) {
264 const char *arg = ctx->argv[0];
265
266 if (*arg != '-' || !arg[1]) {
267 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
268 break;
269 ctx->out[ctx->cpidx++] = ctx->argv[0];
270 continue;
271 }
272
273 if (arg[1] != '-') {
274 ctx->opt = arg + 1;
275 if (internal_help && *ctx->opt == 'h')
276 return parse_options_usage(usagestr, options);
277 switch (parse_short_opt(ctx, options)) {
278 case -1:
279 return parse_options_usage(usagestr, options);
280 case -2:
281 goto unknown;
282 }
283 if (ctx->opt)
284 check_typos(arg + 1, options);
285 while (ctx->opt) {
286 if (internal_help && *ctx->opt == 'h')
287 return parse_options_usage(usagestr, options);
288 switch (parse_short_opt(ctx, options)) {
289 case -1:
290 return parse_options_usage(usagestr, options);
291 case -2:
292 /* fake a short option thing to hide the fact that we may have
293 * started to parse aggregated stuff
294 *
295 * This is leaky, too bad.
296 */
297 ctx->argv[0] = strdup(ctx->opt - 1);
298 *(char *)ctx->argv[0] = '-';
299 goto unknown;
300 }
301 }
302 continue;
303 }
304
305 if (!arg[2]) { /* "--" */
306 if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
307 ctx->argc--;
308 ctx->argv++;
309 }
310 break;
311 }
312
313 if (internal_help && !strcmp(arg + 2, "help-all"))
314 return usage_with_options_internal(usagestr, options, 1);
315 if (internal_help && !strcmp(arg + 2, "help"))
316 return parse_options_usage(usagestr, options);
317 switch (parse_long_opt(ctx, arg + 2, options)) {
318 case -1:
319 return parse_options_usage(usagestr, options);
320 case -2:
321 goto unknown;
322 }
323 continue;
324unknown:
325 if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
326 return PARSE_OPT_UNKNOWN;
327 ctx->out[ctx->cpidx++] = ctx->argv[0];
328 ctx->opt = NULL;
329 }
330 return PARSE_OPT_DONE;
331}
332
333int parse_options_end(struct parse_opt_ctx_t *ctx)
334{
335 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
336 ctx->out[ctx->cpidx + ctx->argc] = NULL;
337 return ctx->cpidx + ctx->argc;
338}
339
340int parse_options(int argc, const char **argv, const struct option *options,
341 const char * const usagestr[], int flags)
342{
343 struct parse_opt_ctx_t ctx;
344
345 parse_options_start(&ctx, argc, argv, flags);
346 switch (parse_options_step(&ctx, options, usagestr)) {
347 case PARSE_OPT_HELP:
348 exit(129);
349 case PARSE_OPT_DONE:
350 break;
351 default: /* PARSE_OPT_UNKNOWN */
352 if (ctx.argv[0][1] == '-') {
353 error("unknown option `%s'", ctx.argv[0] + 2);
354 } else {
355 error("unknown switch `%c'", *ctx.opt);
356 }
357 usage_with_options(usagestr, options);
358 }
359
360 return parse_options_end(&ctx);
361}
362
363#define USAGE_OPTS_WIDTH 24
364#define USAGE_GAP 2
365
366int usage_with_options_internal(const char * const *usagestr,
367 const struct option *opts, int full)
368{
369 if (!usagestr)
370 return PARSE_OPT_HELP;
371
372 fprintf(stderr, "usage: %s\n", *usagestr++);
373 while (*usagestr && **usagestr)
374 fprintf(stderr, " or: %s\n", *usagestr++);
375 while (*usagestr) {
376 fprintf(stderr, "%s%s\n",
377 **usagestr ? " " : "",
378 *usagestr);
379 usagestr++;
380 }
381
382 if (opts->type != OPTION_GROUP)
383 fputc('\n', stderr);
384
385 for (; opts->type != OPTION_END; opts++) {
386 size_t pos;
387 int pad;
388
389 if (opts->type == OPTION_GROUP) {
390 fputc('\n', stderr);
391 if (*opts->help)
392 fprintf(stderr, "%s\n", opts->help);
393 continue;
394 }
395 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
396 continue;
397
398 pos = fprintf(stderr, " ");
399 if (opts->short_name)
400 pos += fprintf(stderr, "-%c", opts->short_name);
401 if (opts->long_name && opts->short_name)
402 pos += fprintf(stderr, ", ");
403 if (opts->long_name)
404 pos += fprintf(stderr, "--%s", opts->long_name);
405
406 switch (opts->type) {
407 case OPTION_ARGUMENT:
408 break;
409 case OPTION_INTEGER:
410 if (opts->flags & PARSE_OPT_OPTARG)
411 if (opts->long_name)
412 pos += fprintf(stderr, "[=<n>]");
413 else
414 pos += fprintf(stderr, "[<n>]");
415 else
416 pos += fprintf(stderr, " <n>");
417 break;
418 case OPTION_CALLBACK:
419 if (opts->flags & PARSE_OPT_NOARG)
420 break;
421 /* FALLTHROUGH */
422 case OPTION_STRING:
423 if (opts->argh) {
424 if (opts->flags & PARSE_OPT_OPTARG)
425 if (opts->long_name)
426 pos += fprintf(stderr, "[=<%s>]", opts->argh);
427 else
428 pos += fprintf(stderr, "[<%s>]", opts->argh);
429 else
430 pos += fprintf(stderr, " <%s>", opts->argh);
431 } else {
432 if (opts->flags & PARSE_OPT_OPTARG)
433 if (opts->long_name)
434 pos += fprintf(stderr, "[=...]");
435 else
436 pos += fprintf(stderr, "[...]");
437 else
438 pos += fprintf(stderr, " ...");
439 }
440 break;
441 default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
442 break;
443 }
444
445 if (pos <= USAGE_OPTS_WIDTH)
446 pad = USAGE_OPTS_WIDTH - pos;
447 else {
448 fputc('\n', stderr);
449 pad = USAGE_OPTS_WIDTH;
450 }
451 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
452 }
453 fputc('\n', stderr);
454
455 return PARSE_OPT_HELP;
456}
457
458void usage_with_options(const char * const *usagestr,
459 const struct option *opts)
460{
461 usage_with_options_internal(usagestr, opts, 0);
462 exit(129);
463}
464
465int parse_options_usage(const char * const *usagestr,
466 const struct option *opts)
467{
468 return usage_with_options_internal(usagestr, opts, 0);
469}
470
471
472/*----- some often used options -----*/
473#include "cache.h"
474
475int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
476 int unset)
477{
478 int *target = opt->value;
479
480 if (unset)
481 /* --no-quiet, --no-verbose */
482 *target = 0;
483 else if (opt->short_name == 'v') {
484 if (*target >= 0)
485 (*target)++;
486 else
487 *target = 1;
488 } else {
489 if (*target <= 0)
490 (*target)--;
491 else
492 *target = -1;
493 }
494 return 0;
495}
diff --git a/Documentation/perf_counter/parse-options.h b/Documentation/perf_counter/parse-options.h
new file mode 100644
index 000000000000..a81c7faff68e
--- /dev/null
+++ b/Documentation/perf_counter/parse-options.h
@@ -0,0 +1,172 @@
1#ifndef PARSE_OPTIONS_H
2#define PARSE_OPTIONS_H
3
4enum parse_opt_type {
5 /* special types */
6 OPTION_END,
7 OPTION_ARGUMENT,
8 OPTION_GROUP,
9 /* options with no arguments */
10 OPTION_BIT,
11 OPTION_BOOLEAN, /* _INCR would have been a better name */
12 OPTION_SET_INT,
13 OPTION_SET_PTR,
14 /* options with arguments (usually) */
15 OPTION_STRING,
16 OPTION_INTEGER,
17 OPTION_CALLBACK,
18};
19
20enum parse_opt_flags {
21 PARSE_OPT_KEEP_DASHDASH = 1,
22 PARSE_OPT_STOP_AT_NON_OPTION = 2,
23 PARSE_OPT_KEEP_ARGV0 = 4,
24 PARSE_OPT_KEEP_UNKNOWN = 8,
25 PARSE_OPT_NO_INTERNAL_HELP = 16,
26};
27
28enum parse_opt_option_flags {
29 PARSE_OPT_OPTARG = 1,
30 PARSE_OPT_NOARG = 2,
31 PARSE_OPT_NONEG = 4,
32 PARSE_OPT_HIDDEN = 8,
33 PARSE_OPT_LASTARG_DEFAULT = 16,
34};
35
36struct option;
37typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
38
39/*
40 * `type`::
41 * holds the type of the option, you must have an OPTION_END last in your
42 * array.
43 *
44 * `short_name`::
45 * the character to use as a short option name, '\0' if none.
46 *
47 * `long_name`::
48 * the long option name, without the leading dashes, NULL if none.
49 *
50 * `value`::
51 * stores pointers to the values to be filled.
52 *
53 * `argh`::
54 * token to explain the kind of argument this option wants. Keep it
55 * homogenous across the repository.
56 *
57 * `help`::
58 * the short help associated to what the option does.
59 * Must never be NULL (except for OPTION_END).
60 * OPTION_GROUP uses this pointer to store the group header.
61 *
62 * `flags`::
63 * mask of parse_opt_option_flags.
64 * PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs)
65 * PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
66 * PARSE_OPT_NONEG: says that this option cannot be negated
67 * PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
68 * the long one.
69 *
70 * `callback`::
71 * pointer to the callback to use for OPTION_CALLBACK.
72 *
73 * `defval`::
74 * default value to fill (*->value) with for PARSE_OPT_OPTARG.
75 * OPTION_{BIT,SET_INT,SET_PTR} store the {mask,integer,pointer} to put in
76 * the value when met.
77 * CALLBACKS can use it like they want.
78 */
79struct option {
80 enum parse_opt_type type;
81 int short_name;
82 const char *long_name;
83 void *value;
84 const char *argh;
85 const char *help;
86
87 int flags;
88 parse_opt_cb *callback;
89 intptr_t defval;
90};
91
92#define OPT_END() { OPTION_END }
93#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
94#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
95#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
96#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
97#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) }
98#define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
99#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) }
100#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
101#define OPT_DATE(s, l, v, h) \
102 { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
103 parse_opt_approxidate_cb }
104#define OPT_CALLBACK(s, l, v, a, h, f) \
105 { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
106
107/* parse_options() will filter out the processed options and leave the
108 * non-option argments in argv[].
109 * Returns the number of arguments left in argv[].
110 */
111extern int parse_options(int argc, const char **argv,
112 const struct option *options,
113 const char * const usagestr[], int flags);
114
115extern NORETURN void usage_with_options(const char * const *usagestr,
116 const struct option *options);
117
118/*----- incremantal advanced APIs -----*/
119
120enum {
121 PARSE_OPT_HELP = -1,
122 PARSE_OPT_DONE,
123 PARSE_OPT_UNKNOWN,
124};
125
126/*
127 * It's okay for the caller to consume argv/argc in the usual way.
128 * Other fields of that structure are private to parse-options and should not
129 * be modified in any way.
130 */
131struct parse_opt_ctx_t {
132 const char **argv;
133 const char **out;
134 int argc, cpidx;
135 const char *opt;
136 int flags;
137};
138
139extern int parse_options_usage(const char * const *usagestr,
140 const struct option *opts);
141
142extern void parse_options_start(struct parse_opt_ctx_t *ctx,
143 int argc, const char **argv, int flags);
144
145extern int parse_options_step(struct parse_opt_ctx_t *ctx,
146 const struct option *options,
147 const char * const usagestr[]);
148
149extern int parse_options_end(struct parse_opt_ctx_t *ctx);
150
151
152/*----- some often used options -----*/
153extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
154extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
155extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
156
157#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
158#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
159#define OPT__VERBOSITY(var) \
160 { OPTION_CALLBACK, 'v', "verbose", (var), NULL, "be more verbose", \
161 PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \
162 { OPTION_CALLBACK, 'q', "quiet", (var), NULL, "be more quiet", \
163 PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }
164#define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run")
165#define OPT__ABBREV(var) \
166 { OPTION_CALLBACK, 0, "abbrev", (var), "n", \
167 "use <n> digits to display SHA-1s", \
168 PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
169
170extern const char *parse_options_fix_filename(const char *prefix, const char *file);
171
172#endif
diff --git a/Documentation/perf_counter/path.c b/Documentation/perf_counter/path.c
new file mode 100644
index 000000000000..891b612ec1a9
--- /dev/null
+++ b/Documentation/perf_counter/path.c
@@ -0,0 +1,392 @@
1/*
2 * I'm tired of doing "vsnprintf()" etc just to open a
3 * file, so here's a "return static buffer with printf"
4 * interface for paths.
5 *
6 * It's obviously not thread-safe. Sue me. But it's quite
7 * useful for doing things like
8 *
9 * f = open(mkpath("%s/%s.perf", base, name), O_RDONLY);
10 *
11 * which is what it's designed for.
12 */
13#include "cache.h"
14
15static char bad_path[] = "/bad-path/";
16/*
17 * Two hacks:
18 */
19
20static char *get_perf_dir(void)
21{
22 return ".";
23}
24
25size_t strlcpy(char *dest, const char *src, size_t size)
26{
27 size_t ret = strlen(src);
28
29 if (size) {
30 size_t len = (ret >= size) ? size - 1 : ret;
31 memcpy(dest, src, len);
32 dest[len] = '\0';
33 }
34 return ret;
35}
36
37
38static char *get_pathname(void)
39{
40 static char pathname_array[4][PATH_MAX];
41 static int index;
42 return pathname_array[3 & ++index];
43}
44
45static char *cleanup_path(char *path)
46{
47 /* Clean it up */
48 if (!memcmp(path, "./", 2)) {
49 path += 2;
50 while (*path == '/')
51 path++;
52 }
53 return path;
54}
55
56char *mksnpath(char *buf, size_t n, const char *fmt, ...)
57{
58 va_list args;
59 unsigned len;
60
61 va_start(args, fmt);
62 len = vsnprintf(buf, n, fmt, args);
63 va_end(args);
64 if (len >= n) {
65 strlcpy(buf, bad_path, n);
66 return buf;
67 }
68 return cleanup_path(buf);
69}
70
71static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
72{
73 const char *perf_dir = get_perf_dir();
74 size_t len;
75
76 len = strlen(perf_dir);
77 if (n < len + 1)
78 goto bad;
79 memcpy(buf, perf_dir, len);
80 if (len && !is_dir_sep(perf_dir[len-1]))
81 buf[len++] = '/';
82 len += vsnprintf(buf + len, n - len, fmt, args);
83 if (len >= n)
84 goto bad;
85 return cleanup_path(buf);
86bad:
87 strlcpy(buf, bad_path, n);
88 return buf;
89}
90
91char *perf_snpath(char *buf, size_t n, const char *fmt, ...)
92{
93 va_list args;
94 va_start(args, fmt);
95 (void)perf_vsnpath(buf, n, fmt, args);
96 va_end(args);
97 return buf;
98}
99
100char *perf_pathdup(const char *fmt, ...)
101{
102 char path[PATH_MAX];
103 va_list args;
104 va_start(args, fmt);
105 (void)perf_vsnpath(path, sizeof(path), fmt, args);
106 va_end(args);
107 return xstrdup(path);
108}
109
110char *mkpath(const char *fmt, ...)
111{
112 va_list args;
113 unsigned len;
114 char *pathname = get_pathname();
115
116 va_start(args, fmt);
117 len = vsnprintf(pathname, PATH_MAX, fmt, args);
118 va_end(args);
119 if (len >= PATH_MAX)
120 return bad_path;
121 return cleanup_path(pathname);
122}
123
124char *perf_path(const char *fmt, ...)
125{
126 const char *perf_dir = get_perf_dir();
127 char *pathname = get_pathname();
128 va_list args;
129 unsigned len;
130
131 len = strlen(perf_dir);
132 if (len > PATH_MAX-100)
133 return bad_path;
134 memcpy(pathname, perf_dir, len);
135 if (len && perf_dir[len-1] != '/')
136 pathname[len++] = '/';
137 va_start(args, fmt);
138 len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
139 va_end(args);
140 if (len >= PATH_MAX)
141 return bad_path;
142 return cleanup_path(pathname);
143}
144
145
146/* perf_mkstemp() - create tmp file honoring TMPDIR variable */
147int perf_mkstemp(char *path, size_t len, const char *template)
148{
149 const char *tmp;
150 size_t n;
151
152 tmp = getenv("TMPDIR");
153 if (!tmp)
154 tmp = "/tmp";
155 n = snprintf(path, len, "%s/%s", tmp, template);
156 if (len <= n) {
157 errno = ENAMETOOLONG;
158 return -1;
159 }
160 return mkstemp(path);
161}
162
163
164static char *user_path(char *buf, char *path, int sz)
165{
166 struct passwd *pw;
167 char *slash;
168 int len, baselen;
169
170 if (!path || path[0] != '~')
171 return NULL;
172 path++;
173 slash = strchr(path, '/');
174 if (path[0] == '/' || !path[0]) {
175 pw = getpwuid(getuid());
176 }
177 else {
178 if (slash) {
179 *slash = 0;
180 pw = getpwnam(path);
181 *slash = '/';
182 }
183 else
184 pw = getpwnam(path);
185 }
186 if (!pw || !pw->pw_dir || sz <= strlen(pw->pw_dir))
187 return NULL;
188 baselen = strlen(pw->pw_dir);
189 memcpy(buf, pw->pw_dir, baselen);
190 while ((1 < baselen) && (buf[baselen-1] == '/')) {
191 buf[baselen-1] = 0;
192 baselen--;
193 }
194 if (slash && slash[1]) {
195 len = strlen(slash);
196 if (sz <= baselen + len)
197 return NULL;
198 memcpy(buf + baselen, slash, len + 1);
199 }
200 return buf;
201}
202
203const char *make_relative_path(const char *abs, const char *base)
204{
205 static char buf[PATH_MAX + 1];
206 int baselen;
207 if (!base)
208 return abs;
209 baselen = strlen(base);
210 if (prefixcmp(abs, base))
211 return abs;
212 if (abs[baselen] == '/')
213 baselen++;
214 else if (base[baselen - 1] != '/')
215 return abs;
216 strcpy(buf, abs + baselen);
217 return buf;
218}
219
220/*
221 * It is okay if dst == src, but they should not overlap otherwise.
222 *
223 * Performs the following normalizations on src, storing the result in dst:
224 * - Ensures that components are separated by '/' (Windows only)
225 * - Squashes sequences of '/'.
226 * - Removes "." components.
227 * - Removes ".." components, and the components the precede them.
228 * Returns failure (non-zero) if a ".." component appears as first path
229 * component anytime during the normalization. Otherwise, returns success (0).
230 *
231 * Note that this function is purely textual. It does not follow symlinks,
232 * verify the existence of the path, or make any system calls.
233 */
234int normalize_path_copy(char *dst, const char *src)
235{
236 char *dst0;
237
238 if (has_dos_drive_prefix(src)) {
239 *dst++ = *src++;
240 *dst++ = *src++;
241 }
242 dst0 = dst;
243
244 if (is_dir_sep(*src)) {
245 *dst++ = '/';
246 while (is_dir_sep(*src))
247 src++;
248 }
249
250 for (;;) {
251 char c = *src;
252
253 /*
254 * A path component that begins with . could be
255 * special:
256 * (1) "." and ends -- ignore and terminate.
257 * (2) "./" -- ignore them, eat slash and continue.
258 * (3) ".." and ends -- strip one and terminate.
259 * (4) "../" -- strip one, eat slash and continue.
260 */
261 if (c == '.') {
262 if (!src[1]) {
263 /* (1) */
264 src++;
265 } else if (is_dir_sep(src[1])) {
266 /* (2) */
267 src += 2;
268 while (is_dir_sep(*src))
269 src++;
270 continue;
271 } else if (src[1] == '.') {
272 if (!src[2]) {
273 /* (3) */
274 src += 2;
275 goto up_one;
276 } else if (is_dir_sep(src[2])) {
277 /* (4) */
278 src += 3;
279 while (is_dir_sep(*src))
280 src++;
281 goto up_one;
282 }
283 }
284 }
285
286 /* copy up to the next '/', and eat all '/' */
287 while ((c = *src++) != '\0' && !is_dir_sep(c))
288 *dst++ = c;
289 if (is_dir_sep(c)) {
290 *dst++ = '/';
291 while (is_dir_sep(c))
292 c = *src++;
293 src--;
294 } else if (!c)
295 break;
296 continue;
297
298 up_one:
299 /*
300 * dst0..dst is prefix portion, and dst[-1] is '/';
301 * go up one level.
302 */
303 dst--; /* go to trailing '/' */
304 if (dst <= dst0)
305 return -1;
306 /* Windows: dst[-1] cannot be backslash anymore */
307 while (dst0 < dst && dst[-1] != '/')
308 dst--;
309 }
310 *dst = '\0';
311 return 0;
312}
313
314/*
315 * path = Canonical absolute path
316 * prefix_list = Colon-separated list of absolute paths
317 *
318 * Determines, for each path in prefix_list, whether the "prefix" really
319 * is an ancestor directory of path. Returns the length of the longest
320 * ancestor directory, excluding any trailing slashes, or -1 if no prefix
321 * is an ancestor. (Note that this means 0 is returned if prefix_list is
322 * "/".) "/foo" is not considered an ancestor of "/foobar". Directories
323 * are not considered to be their own ancestors. path must be in a
324 * canonical form: empty components, or "." or ".." components are not
325 * allowed. prefix_list may be null, which is like "".
326 */
327int longest_ancestor_length(const char *path, const char *prefix_list)
328{
329 char buf[PATH_MAX+1];
330 const char *ceil, *colon;
331 int len, max_len = -1;
332
333 if (prefix_list == NULL || !strcmp(path, "/"))
334 return -1;
335
336 for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
337 for (colon = ceil; *colon && *colon != PATH_SEP; colon++);
338 len = colon - ceil;
339 if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
340 continue;
341 strlcpy(buf, ceil, len+1);
342 if (normalize_path_copy(buf, buf) < 0)
343 continue;
344 len = strlen(buf);
345 if (len > 0 && buf[len-1] == '/')
346 buf[--len] = '\0';
347
348 if (!strncmp(path, buf, len) &&
349 path[len] == '/' &&
350 len > max_len) {
351 max_len = len;
352 }
353 }
354
355 return max_len;
356}
357
358/* strip arbitrary amount of directory separators at end of path */
359static inline int chomp_trailing_dir_sep(const char *path, int len)
360{
361 while (len && is_dir_sep(path[len - 1]))
362 len--;
363 return len;
364}
365
366/*
367 * If path ends with suffix (complete path components), returns the
368 * part before suffix (sans trailing directory separators).
369 * Otherwise returns NULL.
370 */
371char *strip_path_suffix(const char *path, const char *suffix)
372{
373 int path_len = strlen(path), suffix_len = strlen(suffix);
374
375 while (suffix_len) {
376 if (!path_len)
377 return NULL;
378
379 if (is_dir_sep(path[path_len - 1])) {
380 if (!is_dir_sep(suffix[suffix_len - 1]))
381 return NULL;
382 path_len = chomp_trailing_dir_sep(path, path_len);
383 suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
384 }
385 else if (path[--path_len] != suffix[--suffix_len])
386 return NULL;
387 }
388
389 if (path_len && !is_dir_sep(path[path_len - 1]))
390 return NULL;
391 return xstrndup(path, chomp_trailing_dir_sep(path, path_len));
392}
diff --git a/Documentation/perf_counter/perf.c b/Documentation/perf_counter/perf.c
new file mode 100644
index 000000000000..9256f6a16446
--- /dev/null
+++ b/Documentation/perf_counter/perf.c
@@ -0,0 +1,411 @@
1#include "builtin.h"
2#include "exec_cmd.h"
3#include "cache.h"
4//#include "quote.h"
5#include "run-command.h"
6
7const char perf_usage_string[] =
8 "perf [--version] [--exec-path[=PERF_EXEC_PATH]] [--html-path] [-p|--paginate|--no-pager] [--bare] [--perf-dir=PERF_DIR] [--work-tree=PERF_WORK_TREE] [--help] COMMAND [ARGS]";
9
10const char perf_more_info_string[] =
11 "See 'perf help COMMAND' for more information on a specific command.";
12
13static int use_pager = -1;
14struct pager_config {
15 const char *cmd;
16 int val;
17};
18
19static int pager_command_config(const char *var, const char *value, void *data)
20{
21 struct pager_config *c = data;
22 if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd))
23 c->val = perf_config_bool(var, value);
24 return 0;
25}
26
27/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
28int check_pager_config(const char *cmd)
29{
30 struct pager_config c;
31 c.cmd = cmd;
32 c.val = -1;
33 perf_config(pager_command_config, &c);
34 return c.val;
35}
36
37static void commit_pager_choice(void) {
38 switch (use_pager) {
39 case 0:
40 setenv("PERF_PAGER", "cat", 1);
41 break;
42 case 1:
43 /* setup_pager(); */
44 break;
45 default:
46 break;
47 }
48}
49
50static int handle_options(const char*** argv, int* argc, int* envchanged)
51{
52 int handled = 0;
53
54 while (*argc > 0) {
55 const char *cmd = (*argv)[0];
56 if (cmd[0] != '-')
57 break;
58
59 /*
60 * For legacy reasons, the "version" and "help"
61 * commands can be written with "--" prepended
62 * to make them look like flags.
63 */
64 if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
65 break;
66
67 /*
68 * Check remaining flags.
69 */
70 if (!prefixcmp(cmd, "--exec-path")) {
71 cmd += 11;
72 if (*cmd == '=')
73 perf_set_argv_exec_path(cmd + 1);
74 else {
75 puts(perf_exec_path());
76 exit(0);
77 }
78 } else if (!strcmp(cmd, "--html-path")) {
79 puts(system_path(PERF_HTML_PATH));
80 exit(0);
81 } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
82 use_pager = 1;
83 } else if (!strcmp(cmd, "--no-pager")) {
84 use_pager = 0;
85 if (envchanged)
86 *envchanged = 1;
87 } else if (!strcmp(cmd, "--perf-dir")) {
88 if (*argc < 2) {
89 fprintf(stderr, "No directory given for --perf-dir.\n" );
90 usage(perf_usage_string);
91 }
92 setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1);
93 if (envchanged)
94 *envchanged = 1;
95 (*argv)++;
96 (*argc)--;
97 handled++;
98 } else if (!prefixcmp(cmd, "--perf-dir=")) {
99 setenv(PERF_DIR_ENVIRONMENT, cmd + 10, 1);
100 if (envchanged)
101 *envchanged = 1;
102 } else if (!strcmp(cmd, "--work-tree")) {
103 if (*argc < 2) {
104 fprintf(stderr, "No directory given for --work-tree.\n" );
105 usage(perf_usage_string);
106 }
107 setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
108 if (envchanged)
109 *envchanged = 1;
110 (*argv)++;
111 (*argc)--;
112 } else if (!prefixcmp(cmd, "--work-tree=")) {
113 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
114 if (envchanged)
115 *envchanged = 1;
116 } else {
117 fprintf(stderr, "Unknown option: %s\n", cmd);
118 usage(perf_usage_string);
119 }
120
121 (*argv)++;
122 (*argc)--;
123 handled++;
124 }
125 return handled;
126}
127
128static int handle_alias(int *argcp, const char ***argv)
129{
130 int envchanged = 0, ret = 0, saved_errno = errno;
131 int count, option_count;
132 const char** new_argv;
133 const char *alias_command;
134 char *alias_string;
135 int unused_nonperf;
136
137 alias_command = (*argv)[0];
138 alias_string = alias_lookup(alias_command);
139 if (alias_string) {
140 if (alias_string[0] == '!') {
141 if (*argcp > 1) {
142 struct strbuf buf;
143
144 strbuf_init(&buf, PATH_MAX);
145 strbuf_addstr(&buf, alias_string);
146 sq_quote_argv(&buf, (*argv) + 1, PATH_MAX);
147 free(alias_string);
148 alias_string = buf.buf;
149 }
150 ret = system(alias_string + 1);
151 if (ret >= 0 && WIFEXITED(ret) &&
152 WEXITSTATUS(ret) != 127)
153 exit(WEXITSTATUS(ret));
154 die("Failed to run '%s' when expanding alias '%s'",
155 alias_string + 1, alias_command);
156 }
157 count = split_cmdline(alias_string, &new_argv);
158 if (count < 0)
159 die("Bad alias.%s string", alias_command);
160 option_count = handle_options(&new_argv, &count, &envchanged);
161 if (envchanged)
162 die("alias '%s' changes environment variables\n"
163 "You can use '!perf' in the alias to do this.",
164 alias_command);
165 memmove(new_argv - option_count, new_argv,
166 count * sizeof(char *));
167 new_argv -= option_count;
168
169 if (count < 1)
170 die("empty alias for %s", alias_command);
171
172 if (!strcmp(alias_command, new_argv[0]))
173 die("recursive alias: %s", alias_command);
174
175 new_argv = realloc(new_argv, sizeof(char*) *
176 (count + *argcp + 1));
177 /* insert after command name */
178 memcpy(new_argv + count, *argv + 1, sizeof(char*) * *argcp);
179 new_argv[count+*argcp] = NULL;
180
181 *argv = new_argv;
182 *argcp += count - 1;
183
184 ret = 1;
185 }
186
187 errno = saved_errno;
188
189 return ret;
190}
191
192const char perf_version_string[] = PERF_VERSION;
193
194#define RUN_SETUP (1<<0)
195#define USE_PAGER (1<<1)
196/*
197 * require working tree to be present -- anything uses this needs
198 * RUN_SETUP for reading from the configuration file.
199 */
200#define NEED_WORK_TREE (1<<2)
201
202struct cmd_struct {
203 const char *cmd;
204 int (*fn)(int, const char **, const char *);
205 int option;
206};
207
208static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
209{
210 int status;
211 struct stat st;
212 const char *prefix;
213
214 prefix = NULL;
215 if (p->option & RUN_SETUP)
216 prefix = NULL; /* setup_perf_directory(); */
217
218 if (use_pager == -1 && p->option & RUN_SETUP)
219 use_pager = check_pager_config(p->cmd);
220 if (use_pager == -1 && p->option & USE_PAGER)
221 use_pager = 1;
222 commit_pager_choice();
223
224 if (p->option & NEED_WORK_TREE)
225 /* setup_work_tree() */;
226
227 status = p->fn(argc, argv, prefix);
228 if (status)
229 return status & 0xff;
230
231 /* Somebody closed stdout? */
232 if (fstat(fileno(stdout), &st))
233 return 0;
234 /* Ignore write errors for pipes and sockets.. */
235 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
236 return 0;
237
238 /* Check for ENOSPC and EIO errors.. */
239 if (fflush(stdout))
240 die("write failure on standard output: %s", strerror(errno));
241 if (ferror(stdout))
242 die("unknown write failure on standard output");
243 if (fclose(stdout))
244 die("close failed on standard output: %s", strerror(errno));
245 return 0;
246}
247
248static void handle_internal_command(int argc, const char **argv)
249{
250 const char *cmd = argv[0];
251 static struct cmd_struct commands[] = {
252 { "top", cmd_top, 0 },
253 };
254 int i;
255 static const char ext[] = STRIP_EXTENSION;
256
257 if (sizeof(ext) > 1) {
258 i = strlen(argv[0]) - strlen(ext);
259 if (i > 0 && !strcmp(argv[0] + i, ext)) {
260 char *argv0 = strdup(argv[0]);
261 argv[0] = cmd = argv0;
262 argv0[i] = '\0';
263 }
264 }
265
266 /* Turn "perf cmd --help" into "perf help cmd" */
267 if (argc > 1 && !strcmp(argv[1], "--help")) {
268 argv[1] = argv[0];
269 argv[0] = cmd = "help";
270 }
271
272 for (i = 0; i < ARRAY_SIZE(commands); i++) {
273 struct cmd_struct *p = commands+i;
274 if (strcmp(p->cmd, cmd))
275 continue;
276 exit(run_builtin(p, argc, argv));
277 }
278}
279
280static void execv_dashed_external(const char **argv)
281{
282 struct strbuf cmd = STRBUF_INIT;
283 const char *tmp;
284 int status;
285
286 strbuf_addf(&cmd, "perf-%s", argv[0]);
287
288 /*
289 * argv[0] must be the perf command, but the argv array
290 * belongs to the caller, and may be reused in
291 * subsequent loop iterations. Save argv[0] and
292 * restore it on error.
293 */
294 tmp = argv[0];
295 argv[0] = cmd.buf;
296
297 /*
298 * if we fail because the command is not found, it is
299 * OK to return. Otherwise, we just pass along the status code.
300 */
301 status = run_command_v_opt(argv, 0);
302 if (status != -ERR_RUN_COMMAND_EXEC) {
303 if (IS_RUN_COMMAND_ERR(status))
304 die("unable to run '%s'", argv[0]);
305 exit(-status);
306 }
307 errno = ENOENT; /* as if we called execvp */
308
309 argv[0] = tmp;
310
311 strbuf_release(&cmd);
312}
313
314static int run_argv(int *argcp, const char ***argv)
315{
316 int done_alias = 0;
317
318 while (1) {
319 /* See if it's an internal command */
320 handle_internal_command(*argcp, *argv);
321
322 /* .. then try the external ones */
323 execv_dashed_external(*argv);
324
325 /* It could be an alias -- this works around the insanity
326 * of overriding "perf log" with "perf show" by having
327 * alias.log = show
328 */
329 if (done_alias || !handle_alias(argcp, argv))
330 break;
331 done_alias = 1;
332 }
333
334 return done_alias;
335}
336
337
338int main(int argc, const char **argv)
339{
340 const char *cmd;
341
342 cmd = perf_extract_argv0_path(argv[0]);
343 if (!cmd)
344 cmd = "perf-help";
345
346 /*
347 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
348 *
349 * - cannot take flags in between the "perf" and the "xxxx".
350 * - cannot execute it externally (since it would just do
351 * the same thing over again)
352 *
353 * So we just directly call the internal command handler, and
354 * die if that one cannot handle it.
355 */
356 if (!prefixcmp(cmd, "perf-")) {
357 cmd += 4;
358 argv[0] = cmd;
359 handle_internal_command(argc, argv);
360 die("cannot handle %s internally", cmd);
361 }
362
363 /* Look for flags.. */
364 argv++;
365 argc--;
366 handle_options(&argv, &argc, NULL);
367 commit_pager_choice();
368 if (argc > 0) {
369 if (!prefixcmp(argv[0], "--"))
370 argv[0] += 2;
371 } else {
372 /* The user didn't specify a command; give them help */
373 printf("usage: %s\n\n", perf_usage_string);
374 list_common_cmds_help();
375 printf("\n%s\n", perf_more_info_string);
376 exit(1);
377 }
378 cmd = argv[0];
379
380 /*
381 * We use PATH to find perf commands, but we prepend some higher
382 * precidence paths: the "--exec-path" option, the PERF_EXEC_PATH
383 * environment, and the $(perfexecdir) from the Makefile at build
384 * time.
385 */
386 setup_path();
387
388 while (1) {
389 static int done_help = 0;
390 static int was_alias = 0;
391 was_alias = run_argv(&argc, &argv);
392 if (errno != ENOENT)
393 break;
394 if (was_alias) {
395 fprintf(stderr, "Expansion of alias '%s' failed; "
396 "'%s' is not a perf-command\n",
397 cmd, argv[0]);
398 exit(1);
399 }
400 if (!done_help) {
401 cmd = argv[0] = help_unknown_cmd(cmd);
402 done_help = 1;
403 } else
404 break;
405 }
406
407 fprintf(stderr, "Failed to run command '%s': %s\n",
408 cmd, strerror(errno));
409
410 return 1;
411}
diff --git a/Documentation/perf_counter/quote.c b/Documentation/perf_counter/quote.c
new file mode 100644
index 000000000000..7a49fcf69671
--- /dev/null
+++ b/Documentation/perf_counter/quote.c
@@ -0,0 +1,478 @@
1#include "cache.h"
2#include "quote.h"
3
4int quote_path_fully = 1;
5
6/* Help to copy the thing properly quoted for the shell safety.
7 * any single quote is replaced with '\'', any exclamation point
8 * is replaced with '\!', and the whole thing is enclosed in a
9 *
10 * E.g.
11 * original sq_quote result
12 * name ==> name ==> 'name'
13 * a b ==> a b ==> 'a b'
14 * a'b ==> a'\''b ==> 'a'\''b'
15 * a!b ==> a'\!'b ==> 'a'\!'b'
16 */
17static inline int need_bs_quote(char c)
18{
19 return (c == '\'' || c == '!');
20}
21
22void sq_quote_buf(struct strbuf *dst, const char *src)
23{
24 char *to_free = NULL;
25
26 if (dst->buf == src)
27 to_free = strbuf_detach(dst, NULL);
28
29 strbuf_addch(dst, '\'');
30 while (*src) {
31 size_t len = strcspn(src, "'!");
32 strbuf_add(dst, src, len);
33 src += len;
34 while (need_bs_quote(*src)) {
35 strbuf_addstr(dst, "'\\");
36 strbuf_addch(dst, *src++);
37 strbuf_addch(dst, '\'');
38 }
39 }
40 strbuf_addch(dst, '\'');
41 free(to_free);
42}
43
44void sq_quote_print(FILE *stream, const char *src)
45{
46 char c;
47
48 fputc('\'', stream);
49 while ((c = *src++)) {
50 if (need_bs_quote(c)) {
51 fputs("'\\", stream);
52 fputc(c, stream);
53 fputc('\'', stream);
54 } else {
55 fputc(c, stream);
56 }
57 }
58 fputc('\'', stream);
59}
60
61void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
62{
63 int i;
64
65 /* Copy into destination buffer. */
66 strbuf_grow(dst, 255);
67 for (i = 0; argv[i]; ++i) {
68 strbuf_addch(dst, ' ');
69 sq_quote_buf(dst, argv[i]);
70 if (maxlen && dst->len > maxlen)
71 die("Too many or long arguments");
72 }
73}
74
75char *sq_dequote_step(char *arg, char **next)
76{
77 char *dst = arg;
78 char *src = arg;
79 char c;
80
81 if (*src != '\'')
82 return NULL;
83 for (;;) {
84 c = *++src;
85 if (!c)
86 return NULL;
87 if (c != '\'') {
88 *dst++ = c;
89 continue;
90 }
91 /* We stepped out of sq */
92 switch (*++src) {
93 case '\0':
94 *dst = 0;
95 if (next)
96 *next = NULL;
97 return arg;
98 case '\\':
99 c = *++src;
100 if (need_bs_quote(c) && *++src == '\'') {
101 *dst++ = c;
102 continue;
103 }
104 /* Fallthrough */
105 default:
106 if (!next || !isspace(*src))
107 return NULL;
108 do {
109 c = *++src;
110 } while (isspace(c));
111 *dst = 0;
112 *next = src;
113 return arg;
114 }
115 }
116}
117
118char *sq_dequote(char *arg)
119{
120 return sq_dequote_step(arg, NULL);
121}
122
123int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
124{
125 char *next = arg;
126
127 if (!*arg)
128 return 0;
129 do {
130 char *dequoted = sq_dequote_step(next, &next);
131 if (!dequoted)
132 return -1;
133 ALLOC_GROW(*argv, *nr + 1, *alloc);
134 (*argv)[(*nr)++] = dequoted;
135 } while (next);
136
137 return 0;
138}
139
140/* 1 means: quote as octal
141 * 0 means: quote as octal if (quote_path_fully)
142 * -1 means: never quote
143 * c: quote as "\\c"
144 */
145#define X8(x) x, x, x, x, x, x, x, x
146#define X16(x) X8(x), X8(x)
147static signed char const sq_lookup[256] = {
148 /* 0 1 2 3 4 5 6 7 */
149 /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a',
150 /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1,
151 /* 0x10 */ X16(1),
152 /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1,
153 /* 0x28 */ X16(-1), X16(-1), X16(-1),
154 /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1,
155 /* 0x60 */ X16(-1), X8(-1),
156 /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1,
157 /* 0x80 */ /* set to 0 */
158};
159
160static inline int sq_must_quote(char c)
161{
162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
163}
164
165/* returns the longest prefix not needing a quote up to maxlen if positive.
166 This stops at the first \0 because it's marked as a character needing an
167 escape */
168static size_t next_quote_pos(const char *s, ssize_t maxlen)
169{
170 size_t len;
171 if (maxlen < 0) {
172 for (len = 0; !sq_must_quote(s[len]); len++);
173 } else {
174 for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++);
175 }
176 return len;
177}
178
179/*
180 * C-style name quoting.
181 *
182 * (1) if sb and fp are both NULL, inspect the input name and counts the
183 * number of bytes that are needed to hold c_style quoted version of name,
184 * counting the double quotes around it but not terminating NUL, and
185 * returns it.
186 * However, if name does not need c_style quoting, it returns 0.
187 *
188 * (2) if sb or fp are not NULL, it emits the c_style quoted version
189 * of name, enclosed with double quotes if asked and needed only.
190 * Return value is the same as in (1).
191 */
192static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
193 struct strbuf *sb, FILE *fp, int no_dq)
194{
195#undef EMIT
196#define EMIT(c) \
197 do { \
198 if (sb) strbuf_addch(sb, (c)); \
199 if (fp) fputc((c), fp); \
200 count++; \
201 } while (0)
202#define EMITBUF(s, l) \
203 do { \
204 if (sb) strbuf_add(sb, (s), (l)); \
205 if (fp) fwrite((s), (l), 1, fp); \
206 count += (l); \
207 } while (0)
208
209 size_t len, count = 0;
210 const char *p = name;
211
212 for (;;) {
213 int ch;
214
215 len = next_quote_pos(p, maxlen);
216 if (len == maxlen || !p[len])
217 break;
218
219 if (!no_dq && p == name)
220 EMIT('"');
221
222 EMITBUF(p, len);
223 EMIT('\\');
224 p += len;
225 ch = (unsigned char)*p++;
226 if (sq_lookup[ch] >= ' ') {
227 EMIT(sq_lookup[ch]);
228 } else {
229 EMIT(((ch >> 6) & 03) + '0');
230 EMIT(((ch >> 3) & 07) + '0');
231 EMIT(((ch >> 0) & 07) + '0');
232 }
233 }
234
235 EMITBUF(p, len);
236 if (p == name) /* no ending quote needed */
237 return 0;
238
239 if (!no_dq)
240 EMIT('"');
241 return count;
242}
243
244size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
245{
246 return quote_c_style_counted(name, -1, sb, fp, nodq);
247}
248
249void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq)
250{
251 if (quote_c_style(prefix, NULL, NULL, 0) ||
252 quote_c_style(path, NULL, NULL, 0)) {
253 if (!nodq)
254 strbuf_addch(sb, '"');
255 quote_c_style(prefix, sb, NULL, 1);
256 quote_c_style(path, sb, NULL, 1);
257 if (!nodq)
258 strbuf_addch(sb, '"');
259 } else {
260 strbuf_addstr(sb, prefix);
261 strbuf_addstr(sb, path);
262 }
263}
264
265void write_name_quoted(const char *name, FILE *fp, int terminator)
266{
267 if (terminator) {
268 quote_c_style(name, NULL, fp, 0);
269 } else {
270 fputs(name, fp);
271 }
272 fputc(terminator, fp);
273}
274
275extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
276 const char *name, FILE *fp, int terminator)
277{
278 int needquote = 0;
279
280 if (terminator) {
281 needquote = next_quote_pos(pfx, pfxlen) < pfxlen
282 || name[next_quote_pos(name, -1)];
283 }
284 if (needquote) {
285 fputc('"', fp);
286 quote_c_style_counted(pfx, pfxlen, NULL, fp, 1);
287 quote_c_style(name, NULL, fp, 1);
288 fputc('"', fp);
289 } else {
290 fwrite(pfx, pfxlen, 1, fp);
291 fputs(name, fp);
292 }
293 fputc(terminator, fp);
294}
295
296/* quote path as relative to the given prefix */
297char *quote_path_relative(const char *in, int len,
298 struct strbuf *out, const char *prefix)
299{
300 int needquote;
301
302 if (len < 0)
303 len = strlen(in);
304
305 /* "../" prefix itself does not need quoting, but "in" might. */
306 needquote = next_quote_pos(in, len) < len;
307 strbuf_setlen(out, 0);
308 strbuf_grow(out, len);
309
310 if (needquote)
311 strbuf_addch(out, '"');
312 if (prefix) {
313 int off = 0;
314 while (prefix[off] && off < len && prefix[off] == in[off])
315 if (prefix[off] == '/') {
316 prefix += off + 1;
317 in += off + 1;
318 len -= off + 1;
319 off = 0;
320 } else
321 off++;
322
323 for (; *prefix; prefix++)
324 if (*prefix == '/')
325 strbuf_addstr(out, "../");
326 }
327
328 quote_c_style_counted (in, len, out, NULL, 1);
329
330 if (needquote)
331 strbuf_addch(out, '"');
332 if (!out->len)
333 strbuf_addstr(out, "./");
334
335 return out->buf;
336}
337
338/*
339 * C-style name unquoting.
340 *
341 * Quoted should point at the opening double quote.
342 * + Returns 0 if it was able to unquote the string properly, and appends the
343 * result in the strbuf `sb'.
344 * + Returns -1 in case of error, and doesn't touch the strbuf. Though note
345 * that this function will allocate memory in the strbuf, so calling
346 * strbuf_release is mandatory whichever result unquote_c_style returns.
347 *
348 * Updates endp pointer to point at one past the ending double quote if given.
349 */
350int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp)
351{
352 size_t oldlen = sb->len, len;
353 int ch, ac;
354
355 if (*quoted++ != '"')
356 return -1;
357
358 for (;;) {
359 len = strcspn(quoted, "\"\\");
360 strbuf_add(sb, quoted, len);
361 quoted += len;
362
363 switch (*quoted++) {
364 case '"':
365 if (endp)
366 *endp = quoted;
367 return 0;
368 case '\\':
369 break;
370 default:
371 goto error;
372 }
373
374 switch ((ch = *quoted++)) {
375 case 'a': ch = '\a'; break;
376 case 'b': ch = '\b'; break;
377 case 'f': ch = '\f'; break;
378 case 'n': ch = '\n'; break;
379 case 'r': ch = '\r'; break;
380 case 't': ch = '\t'; break;
381 case 'v': ch = '\v'; break;
382
383 case '\\': case '"':
384 break; /* verbatim */
385
386 /* octal values with first digit over 4 overflow */
387 case '0': case '1': case '2': case '3':
388 ac = ((ch - '0') << 6);
389 if ((ch = *quoted++) < '0' || '7' < ch)
390 goto error;
391 ac |= ((ch - '0') << 3);
392 if ((ch = *quoted++) < '0' || '7' < ch)
393 goto error;
394 ac |= (ch - '0');
395 ch = ac;
396 break;
397 default:
398 goto error;
399 }
400 strbuf_addch(sb, ch);
401 }
402
403 error:
404 strbuf_setlen(sb, oldlen);
405 return -1;
406}
407
408/* quoting as a string literal for other languages */
409
410void perl_quote_print(FILE *stream, const char *src)
411{
412 const char sq = '\'';
413 const char bq = '\\';
414 char c;
415
416 fputc(sq, stream);
417 while ((c = *src++)) {
418 if (c == sq || c == bq)
419 fputc(bq, stream);
420 fputc(c, stream);
421 }
422 fputc(sq, stream);
423}
424
425void python_quote_print(FILE *stream, const char *src)
426{
427 const char sq = '\'';
428 const char bq = '\\';
429 const char nl = '\n';
430 char c;
431
432 fputc(sq, stream);
433 while ((c = *src++)) {
434 if (c == nl) {
435 fputc(bq, stream);
436 fputc('n', stream);
437 continue;
438 }
439 if (c == sq || c == bq)
440 fputc(bq, stream);
441 fputc(c, stream);
442 }
443 fputc(sq, stream);
444}
445
446void tcl_quote_print(FILE *stream, const char *src)
447{
448 char c;
449
450 fputc('"', stream);
451 while ((c = *src++)) {
452 switch (c) {
453 case '[': case ']':
454 case '{': case '}':
455 case '$': case '\\': case '"':
456 fputc('\\', stream);
457 default:
458 fputc(c, stream);
459 break;
460 case '\f':
461 fputs("\\f", stream);
462 break;
463 case '\r':
464 fputs("\\r", stream);
465 break;
466 case '\n':
467 fputs("\\n", stream);
468 break;
469 case '\t':
470 fputs("\\t", stream);
471 break;
472 case '\v':
473 fputs("\\v", stream);
474 break;
475 }
476 }
477 fputc('"', stream);
478}
diff --git a/Documentation/perf_counter/quote.h b/Documentation/perf_counter/quote.h
new file mode 100644
index 000000000000..66730f2bff3c
--- /dev/null
+++ b/Documentation/perf_counter/quote.h
@@ -0,0 +1,68 @@
1#ifndef QUOTE_H
2#define QUOTE_H
3
4#include <stddef.h>
5#include <stdio.h>
6
7/* Help to copy the thing properly quoted for the shell safety.
8 * any single quote is replaced with '\'', any exclamation point
9 * is replaced with '\!', and the whole thing is enclosed in a
10 * single quote pair.
11 *
12 * For example, if you are passing the result to system() as an
13 * argument:
14 *
15 * sprintf(cmd, "foobar %s %s", sq_quote(arg0), sq_quote(arg1))
16 *
17 * would be appropriate. If the system() is going to call ssh to
18 * run the command on the other side:
19 *
20 * sprintf(cmd, "git-diff-tree %s %s", sq_quote(arg0), sq_quote(arg1));
21 * sprintf(rcmd, "ssh %s %s", sq_quote(host), sq_quote(cmd));
22 *
23 * Note that the above examples leak memory! Remember to free result from
24 * sq_quote() in a real application.
25 *
26 * sq_quote_buf() writes to an existing buffer of specified size; it
27 * will return the number of characters that would have been written
28 * excluding the final null regardless of the buffer size.
29 */
30
31extern void sq_quote_print(FILE *stream, const char *src);
32
33extern void sq_quote_buf(struct strbuf *, const char *src);
34extern void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
35
36/* This unwraps what sq_quote() produces in place, but returns
37 * NULL if the input does not look like what sq_quote would have
38 * produced.
39 */
40extern char *sq_dequote(char *);
41
42/*
43 * Same as the above, but can be used to unwrap many arguments in the
44 * same string separated by space. "next" is changed to point to the
45 * next argument that should be passed as first parameter. When there
46 * is no more argument to be dequoted, "next" is updated to point to NULL.
47 */
48extern char *sq_dequote_step(char *arg, char **next);
49extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
50
51extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
52extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
53extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
54
55extern void write_name_quoted(const char *name, FILE *, int terminator);
56extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
57 const char *name, FILE *, int terminator);
58
59/* quote path as relative to the given prefix */
60char *quote_path_relative(const char *in, int len,
61 struct strbuf *out, const char *prefix);
62
63/* quoting as a string literal for other languages */
64extern void perl_quote_print(FILE *stream, const char *src);
65extern void python_quote_print(FILE *stream, const char *src);
66extern void tcl_quote_print(FILE *stream, const char *src);
67
68#endif
diff --git a/Documentation/perf_counter/run-command.c b/Documentation/perf_counter/run-command.c
new file mode 100644
index 000000000000..b2f5e854f40a
--- /dev/null
+++ b/Documentation/perf_counter/run-command.c
@@ -0,0 +1,395 @@
1#include "cache.h"
2#include "run-command.h"
3#include "exec_cmd.h"
4
5static inline void close_pair(int fd[2])
6{
7 close(fd[0]);
8 close(fd[1]);
9}
10
11static inline void dup_devnull(int to)
12{
13 int fd = open("/dev/null", O_RDWR);
14 dup2(fd, to);
15 close(fd);
16}
17
18int start_command(struct child_process *cmd)
19{
20 int need_in, need_out, need_err;
21 int fdin[2], fdout[2], fderr[2];
22
23 /*
24 * In case of errors we must keep the promise to close FDs
25 * that have been passed in via ->in and ->out.
26 */
27
28 need_in = !cmd->no_stdin && cmd->in < 0;
29 if (need_in) {
30 if (pipe(fdin) < 0) {
31 if (cmd->out > 0)
32 close(cmd->out);
33 return -ERR_RUN_COMMAND_PIPE;
34 }
35 cmd->in = fdin[1];
36 }
37
38 need_out = !cmd->no_stdout
39 && !cmd->stdout_to_stderr
40 && cmd->out < 0;
41 if (need_out) {
42 if (pipe(fdout) < 0) {
43 if (need_in)
44 close_pair(fdin);
45 else if (cmd->in)
46 close(cmd->in);
47 return -ERR_RUN_COMMAND_PIPE;
48 }
49 cmd->out = fdout[0];
50 }
51
52 need_err = !cmd->no_stderr && cmd->err < 0;
53 if (need_err) {
54 if (pipe(fderr) < 0) {
55 if (need_in)
56 close_pair(fdin);
57 else if (cmd->in)
58 close(cmd->in);
59 if (need_out)
60 close_pair(fdout);
61 else if (cmd->out)
62 close(cmd->out);
63 return -ERR_RUN_COMMAND_PIPE;
64 }
65 cmd->err = fderr[0];
66 }
67
68#ifndef __MINGW32__
69 fflush(NULL);
70 cmd->pid = fork();
71 if (!cmd->pid) {
72 if (cmd->no_stdin)
73 dup_devnull(0);
74 else if (need_in) {
75 dup2(fdin[0], 0);
76 close_pair(fdin);
77 } else if (cmd->in) {
78 dup2(cmd->in, 0);
79 close(cmd->in);
80 }
81
82 if (cmd->no_stderr)
83 dup_devnull(2);
84 else if (need_err) {
85 dup2(fderr[1], 2);
86 close_pair(fderr);
87 }
88
89 if (cmd->no_stdout)
90 dup_devnull(1);
91 else if (cmd->stdout_to_stderr)
92 dup2(2, 1);
93 else if (need_out) {
94 dup2(fdout[1], 1);
95 close_pair(fdout);
96 } else if (cmd->out > 1) {
97 dup2(cmd->out, 1);
98 close(cmd->out);
99 }
100
101 if (cmd->dir && chdir(cmd->dir))
102 die("exec %s: cd to %s failed (%s)", cmd->argv[0],
103 cmd->dir, strerror(errno));
104 if (cmd->env) {
105 for (; *cmd->env; cmd->env++) {
106 if (strchr(*cmd->env, '='))
107 putenv((char*)*cmd->env);
108 else
109 unsetenv(*cmd->env);
110 }
111 }
112 if (cmd->preexec_cb)
113 cmd->preexec_cb();
114 if (cmd->perf_cmd) {
115 execv_perf_cmd(cmd->argv);
116 } else {
117 execvp(cmd->argv[0], (char *const*) cmd->argv);
118 }
119 exit(127);
120 }
121#else
122 int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
123 const char **sargv = cmd->argv;
124 char **env = environ;
125
126 if (cmd->no_stdin) {
127 s0 = dup(0);
128 dup_devnull(0);
129 } else if (need_in) {
130 s0 = dup(0);
131 dup2(fdin[0], 0);
132 } else if (cmd->in) {
133 s0 = dup(0);
134 dup2(cmd->in, 0);
135 }
136
137 if (cmd->no_stderr) {
138 s2 = dup(2);
139 dup_devnull(2);
140 } else if (need_err) {
141 s2 = dup(2);
142 dup2(fderr[1], 2);
143 }
144
145 if (cmd->no_stdout) {
146 s1 = dup(1);
147 dup_devnull(1);
148 } else if (cmd->stdout_to_stderr) {
149 s1 = dup(1);
150 dup2(2, 1);
151 } else if (need_out) {
152 s1 = dup(1);
153 dup2(fdout[1], 1);
154 } else if (cmd->out > 1) {
155 s1 = dup(1);
156 dup2(cmd->out, 1);
157 }
158
159 if (cmd->dir)
160 die("chdir in start_command() not implemented");
161 if (cmd->env) {
162 env = copy_environ();
163 for (; *cmd->env; cmd->env++)
164 env = env_setenv(env, *cmd->env);
165 }
166
167 if (cmd->perf_cmd) {
168 cmd->argv = prepare_perf_cmd(cmd->argv);
169 }
170
171 cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
172
173 if (cmd->env)
174 free_environ(env);
175 if (cmd->perf_cmd)
176 free(cmd->argv);
177
178 cmd->argv = sargv;
179 if (s0 >= 0)
180 dup2(s0, 0), close(s0);
181 if (s1 >= 0)
182 dup2(s1, 1), close(s1);
183 if (s2 >= 0)
184 dup2(s2, 2), close(s2);
185#endif
186
187 if (cmd->pid < 0) {
188 int err = errno;
189 if (need_in)
190 close_pair(fdin);
191 else if (cmd->in)
192 close(cmd->in);
193 if (need_out)
194 close_pair(fdout);
195 else if (cmd->out)
196 close(cmd->out);
197 if (need_err)
198 close_pair(fderr);
199 return err == ENOENT ?
200 -ERR_RUN_COMMAND_EXEC :
201 -ERR_RUN_COMMAND_FORK;
202 }
203
204 if (need_in)
205 close(fdin[0]);
206 else if (cmd->in)
207 close(cmd->in);
208
209 if (need_out)
210 close(fdout[1]);
211 else if (cmd->out)
212 close(cmd->out);
213
214 if (need_err)
215 close(fderr[1]);
216
217 return 0;
218}
219
220static int wait_or_whine(pid_t pid)
221{
222 for (;;) {
223 int status, code;
224 pid_t waiting = waitpid(pid, &status, 0);
225
226 if (waiting < 0) {
227 if (errno == EINTR)
228 continue;
229 error("waitpid failed (%s)", strerror(errno));
230 return -ERR_RUN_COMMAND_WAITPID;
231 }
232 if (waiting != pid)
233 return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
234 if (WIFSIGNALED(status))
235 return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
236
237 if (!WIFEXITED(status))
238 return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
239 code = WEXITSTATUS(status);
240 switch (code) {
241 case 127:
242 return -ERR_RUN_COMMAND_EXEC;
243 case 0:
244 return 0;
245 default:
246 return -code;
247 }
248 }
249}
250
251int finish_command(struct child_process *cmd)
252{
253 return wait_or_whine(cmd->pid);
254}
255
256int run_command(struct child_process *cmd)
257{
258 int code = start_command(cmd);
259 if (code)
260 return code;
261 return finish_command(cmd);
262}
263
264static void prepare_run_command_v_opt(struct child_process *cmd,
265 const char **argv,
266 int opt)
267{
268 memset(cmd, 0, sizeof(*cmd));
269 cmd->argv = argv;
270 cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
271 cmd->perf_cmd = opt & RUN_PERF_CMD ? 1 : 0;
272 cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
273}
274
275int run_command_v_opt(const char **argv, int opt)
276{
277 struct child_process cmd;
278 prepare_run_command_v_opt(&cmd, argv, opt);
279 return run_command(&cmd);
280}
281
282int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
283{
284 struct child_process cmd;
285 prepare_run_command_v_opt(&cmd, argv, opt);
286 cmd.dir = dir;
287 cmd.env = env;
288 return run_command(&cmd);
289}
290
291#ifdef __MINGW32__
292static __stdcall unsigned run_thread(void *data)
293{
294 struct async *async = data;
295 return async->proc(async->fd_for_proc, async->data);
296}
297#endif
298
299int start_async(struct async *async)
300{
301 int pipe_out[2];
302
303 if (pipe(pipe_out) < 0)
304 return error("cannot create pipe: %s", strerror(errno));
305 async->out = pipe_out[0];
306
307#ifndef __MINGW32__
308 /* Flush stdio before fork() to avoid cloning buffers */
309 fflush(NULL);
310
311 async->pid = fork();
312 if (async->pid < 0) {
313 error("fork (async) failed: %s", strerror(errno));
314 close_pair(pipe_out);
315 return -1;
316 }
317 if (!async->pid) {
318 close(pipe_out[0]);
319 exit(!!async->proc(pipe_out[1], async->data));
320 }
321 close(pipe_out[1]);
322#else
323 async->fd_for_proc = pipe_out[1];
324 async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);
325 if (!async->tid) {
326 error("cannot create thread: %s", strerror(errno));
327 close_pair(pipe_out);
328 return -1;
329 }
330#endif
331 return 0;
332}
333
334int finish_async(struct async *async)
335{
336#ifndef __MINGW32__
337 int ret = 0;
338
339 if (wait_or_whine(async->pid))
340 ret = error("waitpid (async) failed");
341#else
342 DWORD ret = 0;
343 if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
344 ret = error("waiting for thread failed: %lu", GetLastError());
345 else if (!GetExitCodeThread(async->tid, &ret))
346 ret = error("cannot get thread exit code: %lu", GetLastError());
347 CloseHandle(async->tid);
348#endif
349 return ret;
350}
351
352int run_hook(const char *index_file, const char *name, ...)
353{
354 struct child_process hook;
355 const char **argv = NULL, *env[2];
356 char index[PATH_MAX];
357 va_list args;
358 int ret;
359 size_t i = 0, alloc = 0;
360
361 if (access(perf_path("hooks/%s", name), X_OK) < 0)
362 return 0;
363
364 va_start(args, name);
365 ALLOC_GROW(argv, i + 1, alloc);
366 argv[i++] = perf_path("hooks/%s", name);
367 while (argv[i-1]) {
368 ALLOC_GROW(argv, i + 1, alloc);
369 argv[i++] = va_arg(args, const char *);
370 }
371 va_end(args);
372
373 memset(&hook, 0, sizeof(hook));
374 hook.argv = argv;
375 hook.no_stdin = 1;
376 hook.stdout_to_stderr = 1;
377 if (index_file) {
378 snprintf(index, sizeof(index), "PERF_INDEX_FILE=%s", index_file);
379 env[0] = index;
380 env[1] = NULL;
381 hook.env = env;
382 }
383
384 ret = start_command(&hook);
385 free(argv);
386 if (ret) {
387 warning("Could not spawn %s", argv[0]);
388 return ret;
389 }
390 ret = finish_command(&hook);
391 if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL)
392 warning("%s exited due to uncaught signal", argv[0]);
393
394 return ret;
395}
diff --git a/Documentation/perf_counter/run-command.h b/Documentation/perf_counter/run-command.h
new file mode 100644
index 000000000000..328289f23669
--- /dev/null
+++ b/Documentation/perf_counter/run-command.h
@@ -0,0 +1,93 @@
1#ifndef RUN_COMMAND_H
2#define RUN_COMMAND_H
3
4enum {
5 ERR_RUN_COMMAND_FORK = 10000,
6 ERR_RUN_COMMAND_EXEC,
7 ERR_RUN_COMMAND_PIPE,
8 ERR_RUN_COMMAND_WAITPID,
9 ERR_RUN_COMMAND_WAITPID_WRONG_PID,
10 ERR_RUN_COMMAND_WAITPID_SIGNAL,
11 ERR_RUN_COMMAND_WAITPID_NOEXIT,
12};
13#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)
14
15struct child_process {
16 const char **argv;
17 pid_t pid;
18 /*
19 * Using .in, .out, .err:
20 * - Specify 0 for no redirections (child inherits stdin, stdout,
21 * stderr from parent).
22 * - Specify -1 to have a pipe allocated as follows:
23 * .in: returns the writable pipe end; parent writes to it,
24 * the readable pipe end becomes child's stdin
25 * .out, .err: returns the readable pipe end; parent reads from
26 * it, the writable pipe end becomes child's stdout/stderr
27 * The caller of start_command() must close the returned FDs
28 * after it has completed reading from/writing to it!
29 * - Specify > 0 to set a channel to a particular FD as follows:
30 * .in: a readable FD, becomes child's stdin
31 * .out: a writable FD, becomes child's stdout/stderr
32 * .err > 0 not supported
33 * The specified FD is closed by start_command(), even in case
34 * of errors!
35 */
36 int in;
37 int out;
38 int err;
39 const char *dir;
40 const char *const *env;
41 unsigned no_stdin:1;
42 unsigned no_stdout:1;
43 unsigned no_stderr:1;
44 unsigned perf_cmd:1; /* if this is to be perf sub-command */
45 unsigned stdout_to_stderr:1;
46 void (*preexec_cb)(void);
47};
48
49int start_command(struct child_process *);
50int finish_command(struct child_process *);
51int run_command(struct child_process *);
52
53extern int run_hook(const char *index_file, const char *name, ...);
54
55#define RUN_COMMAND_NO_STDIN 1
56#define RUN_PERF_CMD 2 /*If this is to be perf sub-command */
57#define RUN_COMMAND_STDOUT_TO_STDERR 4
58int run_command_v_opt(const char **argv, int opt);
59
60/*
61 * env (the environment) is to be formatted like environ: "VAR=VALUE".
62 * To unset an environment variable use just "VAR".
63 */
64int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env);
65
66/*
67 * The purpose of the following functions is to feed a pipe by running
68 * a function asynchronously and providing output that the caller reads.
69 *
70 * It is expected that no synchronization and mutual exclusion between
71 * the caller and the feed function is necessary so that the function
72 * can run in a thread without interfering with the caller.
73 */
74struct async {
75 /*
76 * proc writes to fd and closes it;
77 * returns 0 on success, non-zero on failure
78 */
79 int (*proc)(int fd, void *data);
80 void *data;
81 int out; /* caller reads from here and closes it */
82#ifndef __MINGW32__
83 pid_t pid;
84#else
85 HANDLE tid;
86 int fd_for_proc;
87#endif
88};
89
90int start_async(struct async *async);
91int finish_async(struct async *async);
92
93#endif
diff --git a/Documentation/perf_counter/strbuf.c b/Documentation/perf_counter/strbuf.c
new file mode 100644
index 000000000000..eaba09306802
--- /dev/null
+++ b/Documentation/perf_counter/strbuf.c
@@ -0,0 +1,359 @@
1#include "cache.h"
2
3int prefixcmp(const char *str, const char *prefix)
4{
5 for (; ; str++, prefix++)
6 if (!*prefix)
7 return 0;
8 else if (*str != *prefix)
9 return (unsigned char)*prefix - (unsigned char)*str;
10}
11
12/*
13 * Used as the default ->buf value, so that people can always assume
14 * buf is non NULL and ->buf is NUL terminated even for a freshly
15 * initialized strbuf.
16 */
17char strbuf_slopbuf[1];
18
19void strbuf_init(struct strbuf *sb, size_t hint)
20{
21 sb->alloc = sb->len = 0;
22 sb->buf = strbuf_slopbuf;
23 if (hint)
24 strbuf_grow(sb, hint);
25}
26
27void strbuf_release(struct strbuf *sb)
28{
29 if (sb->alloc) {
30 free(sb->buf);
31 strbuf_init(sb, 0);
32 }
33}
34
35char *strbuf_detach(struct strbuf *sb, size_t *sz)
36{
37 char *res = sb->alloc ? sb->buf : NULL;
38 if (sz)
39 *sz = sb->len;
40 strbuf_init(sb, 0);
41 return res;
42}
43
44void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
45{
46 strbuf_release(sb);
47 sb->buf = buf;
48 sb->len = len;
49 sb->alloc = alloc;
50 strbuf_grow(sb, 0);
51 sb->buf[sb->len] = '\0';
52}
53
54void strbuf_grow(struct strbuf *sb, size_t extra)
55{
56 if (sb->len + extra + 1 <= sb->len)
57 die("you want to use way too much memory");
58 if (!sb->alloc)
59 sb->buf = NULL;
60 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
61}
62
63void strbuf_trim(struct strbuf *sb)
64{
65 char *b = sb->buf;
66 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
67 sb->len--;
68 while (sb->len > 0 && isspace(*b)) {
69 b++;
70 sb->len--;
71 }
72 memmove(sb->buf, b, sb->len);
73 sb->buf[sb->len] = '\0';
74}
75void strbuf_rtrim(struct strbuf *sb)
76{
77 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
78 sb->len--;
79 sb->buf[sb->len] = '\0';
80}
81
82void strbuf_ltrim(struct strbuf *sb)
83{
84 char *b = sb->buf;
85 while (sb->len > 0 && isspace(*b)) {
86 b++;
87 sb->len--;
88 }
89 memmove(sb->buf, b, sb->len);
90 sb->buf[sb->len] = '\0';
91}
92
93void strbuf_tolower(struct strbuf *sb)
94{
95 int i;
96 for (i = 0; i < sb->len; i++)
97 sb->buf[i] = tolower(sb->buf[i]);
98}
99
100struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
101{
102 int alloc = 2, pos = 0;
103 char *n, *p;
104 struct strbuf **ret;
105 struct strbuf *t;
106
107 ret = calloc(alloc, sizeof(struct strbuf *));
108 p = n = sb->buf;
109 while (n < sb->buf + sb->len) {
110 int len;
111 n = memchr(n, delim, sb->len - (n - sb->buf));
112 if (pos + 1 >= alloc) {
113 alloc = alloc * 2;
114 ret = realloc(ret, sizeof(struct strbuf *) * alloc);
115 }
116 if (!n)
117 n = sb->buf + sb->len - 1;
118 len = n - p + 1;
119 t = malloc(sizeof(struct strbuf));
120 strbuf_init(t, len);
121 strbuf_add(t, p, len);
122 ret[pos] = t;
123 ret[++pos] = NULL;
124 p = ++n;
125 }
126 return ret;
127}
128
129void strbuf_list_free(struct strbuf **sbs)
130{
131 struct strbuf **s = sbs;
132
133 while (*s) {
134 strbuf_release(*s);
135 free(*s++);
136 }
137 free(sbs);
138}
139
140int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
141{
142 int len = a->len < b->len ? a->len: b->len;
143 int cmp = memcmp(a->buf, b->buf, len);
144 if (cmp)
145 return cmp;
146 return a->len < b->len ? -1: a->len != b->len;
147}
148
149void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
150 const void *data, size_t dlen)
151{
152 if (pos + len < pos)
153 die("you want to use way too much memory");
154 if (pos > sb->len)
155 die("`pos' is too far after the end of the buffer");
156 if (pos + len > sb->len)
157 die("`pos + len' is too far after the end of the buffer");
158
159 if (dlen >= len)
160 strbuf_grow(sb, dlen - len);
161 memmove(sb->buf + pos + dlen,
162 sb->buf + pos + len,
163 sb->len - pos - len);
164 memcpy(sb->buf + pos, data, dlen);
165 strbuf_setlen(sb, sb->len + dlen - len);
166}
167
168void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
169{
170 strbuf_splice(sb, pos, 0, data, len);
171}
172
173void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
174{
175 strbuf_splice(sb, pos, len, NULL, 0);
176}
177
178void strbuf_add(struct strbuf *sb, const void *data, size_t len)
179{
180 strbuf_grow(sb, len);
181 memcpy(sb->buf + sb->len, data, len);
182 strbuf_setlen(sb, sb->len + len);
183}
184
185void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
186{
187 strbuf_grow(sb, len);
188 memcpy(sb->buf + sb->len, sb->buf + pos, len);
189 strbuf_setlen(sb, sb->len + len);
190}
191
192void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
193{
194 int len;
195 va_list ap;
196
197 if (!strbuf_avail(sb))
198 strbuf_grow(sb, 64);
199 va_start(ap, fmt);
200 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
201 va_end(ap);
202 if (len < 0)
203 die("your vsnprintf is broken");
204 if (len > strbuf_avail(sb)) {
205 strbuf_grow(sb, len);
206 va_start(ap, fmt);
207 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
208 va_end(ap);
209 if (len > strbuf_avail(sb)) {
210 die("this should not happen, your snprintf is broken");
211 }
212 }
213 strbuf_setlen(sb, sb->len + len);
214}
215
216void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
217 void *context)
218{
219 for (;;) {
220 const char *percent;
221 size_t consumed;
222
223 percent = strchrnul(format, '%');
224 strbuf_add(sb, format, percent - format);
225 if (!*percent)
226 break;
227 format = percent + 1;
228
229 consumed = fn(sb, format, context);
230 if (consumed)
231 format += consumed;
232 else
233 strbuf_addch(sb, '%');
234 }
235}
236
237size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
238 void *context)
239{
240 struct strbuf_expand_dict_entry *e = context;
241 size_t len;
242
243 for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
244 if (!strncmp(placeholder, e->placeholder, len)) {
245 if (e->value)
246 strbuf_addstr(sb, e->value);
247 return len;
248 }
249 }
250 return 0;
251}
252
253size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
254{
255 size_t res;
256 size_t oldalloc = sb->alloc;
257
258 strbuf_grow(sb, size);
259 res = fread(sb->buf + sb->len, 1, size, f);
260 if (res > 0)
261 strbuf_setlen(sb, sb->len + res);
262 else if (res < 0 && oldalloc == 0)
263 strbuf_release(sb);
264 return res;
265}
266
267ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
268{
269 size_t oldlen = sb->len;
270 size_t oldalloc = sb->alloc;
271
272 strbuf_grow(sb, hint ? hint : 8192);
273 for (;;) {
274 ssize_t cnt;
275
276 cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
277 if (cnt < 0) {
278 if (oldalloc == 0)
279 strbuf_release(sb);
280 else
281 strbuf_setlen(sb, oldlen);
282 return -1;
283 }
284 if (!cnt)
285 break;
286 sb->len += cnt;
287 strbuf_grow(sb, 8192);
288 }
289
290 sb->buf[sb->len] = '\0';
291 return sb->len - oldlen;
292}
293
294#define STRBUF_MAXLINK (2*PATH_MAX)
295
296int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
297{
298 size_t oldalloc = sb->alloc;
299
300 if (hint < 32)
301 hint = 32;
302
303 while (hint < STRBUF_MAXLINK) {
304 int len;
305
306 strbuf_grow(sb, hint);
307 len = readlink(path, sb->buf, hint);
308 if (len < 0) {
309 if (errno != ERANGE)
310 break;
311 } else if (len < hint) {
312 strbuf_setlen(sb, len);
313 return 0;
314 }
315
316 /* .. the buffer was too small - try again */
317 hint *= 2;
318 }
319 if (oldalloc == 0)
320 strbuf_release(sb);
321 return -1;
322}
323
324int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
325{
326 int ch;
327
328 strbuf_grow(sb, 0);
329 if (feof(fp))
330 return EOF;
331
332 strbuf_reset(sb);
333 while ((ch = fgetc(fp)) != EOF) {
334 if (ch == term)
335 break;
336 strbuf_grow(sb, 1);
337 sb->buf[sb->len++] = ch;
338 }
339 if (ch == EOF && sb->len == 0)
340 return EOF;
341
342 sb->buf[sb->len] = '\0';
343 return 0;
344}
345
346int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
347{
348 int fd, len;
349
350 fd = open(path, O_RDONLY);
351 if (fd < 0)
352 return -1;
353 len = strbuf_read(sb, fd, hint);
354 close(fd);
355 if (len < 0)
356 return -1;
357
358 return len;
359}
diff --git a/Documentation/perf_counter/strbuf.h b/Documentation/perf_counter/strbuf.h
new file mode 100644
index 000000000000..9ee908a3ec5d
--- /dev/null
+++ b/Documentation/perf_counter/strbuf.h
@@ -0,0 +1,137 @@
1#ifndef STRBUF_H
2#define STRBUF_H
3
4/*
5 * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
6 * long, overflow safe strings.
7 *
8 * Strbufs has some invariants that are very important to keep in mind:
9 *
10 * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to
11 * build complex strings/buffers whose final size isn't easily known.
12 *
13 * It is NOT legal to copy the ->buf pointer away.
14 * `strbuf_detach' is the operation that detachs a buffer from its shell
15 * while keeping the shell valid wrt its invariants.
16 *
17 * 2. the ->buf member is a byte array that has at least ->len + 1 bytes
18 * allocated. The extra byte is used to store a '\0', allowing the ->buf
19 * member to be a valid C-string. Every strbuf function ensure this
20 * invariant is preserved.
21 *
22 * Note that it is OK to "play" with the buffer directly if you work it
23 * that way:
24 *
25 * strbuf_grow(sb, SOME_SIZE);
26 * ... Here, the memory array starting at sb->buf, and of length
27 * ... strbuf_avail(sb) is all yours, and you are sure that
28 * ... strbuf_avail(sb) is at least SOME_SIZE.
29 * strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE);
30 *
31 * Of course, SOME_OTHER_SIZE must be smaller or equal to strbuf_avail(sb).
32 *
33 * Doing so is safe, though if it has to be done in many places, adding the
34 * missing API to the strbuf module is the way to go.
35 *
36 * XXX: do _not_ assume that the area that is yours is of size ->alloc - 1
37 * even if it's true in the current implementation. Alloc is somehow a
38 * "private" member that should not be messed with.
39 */
40
41#include <assert.h>
42
43extern char strbuf_slopbuf[];
44struct strbuf {
45 size_t alloc;
46 size_t len;
47 char *buf;
48};
49
50#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
51
52/*----- strbuf life cycle -----*/
53extern void strbuf_init(struct strbuf *, size_t);
54extern void strbuf_release(struct strbuf *);
55extern char *strbuf_detach(struct strbuf *, size_t *);
56extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
57static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
58 struct strbuf tmp = *a;
59 *a = *b;
60 *b = tmp;
61}
62
63/*----- strbuf size related -----*/
64static inline size_t strbuf_avail(const struct strbuf *sb) {
65 return sb->alloc ? sb->alloc - sb->len - 1 : 0;
66}
67
68extern void strbuf_grow(struct strbuf *, size_t);
69
70static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
71 if (!sb->alloc)
72 strbuf_grow(sb, 0);
73 assert(len < sb->alloc);
74 sb->len = len;
75 sb->buf[len] = '\0';
76}
77#define strbuf_reset(sb) strbuf_setlen(sb, 0)
78
79/*----- content related -----*/
80extern void strbuf_trim(struct strbuf *);
81extern void strbuf_rtrim(struct strbuf *);
82extern void strbuf_ltrim(struct strbuf *);
83extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
84extern void strbuf_tolower(struct strbuf *);
85
86extern struct strbuf **strbuf_split(const struct strbuf *, int delim);
87extern void strbuf_list_free(struct strbuf **);
88
89/*----- add data in your buffer -----*/
90static inline void strbuf_addch(struct strbuf *sb, int c) {
91 strbuf_grow(sb, 1);
92 sb->buf[sb->len++] = c;
93 sb->buf[sb->len] = '\0';
94}
95
96extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t);
97extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);
98
99/* splice pos..pos+len with given data */
100extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,
101 const void *, size_t);
102
103extern void strbuf_add(struct strbuf *, const void *, size_t);
104static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
105 strbuf_add(sb, s, strlen(s));
106}
107static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
108 strbuf_add(sb, sb2->buf, sb2->len);
109}
110extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
111
112typedef size_t (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context);
113extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, void *context);
114struct strbuf_expand_dict_entry {
115 const char *placeholder;
116 const char *value;
117};
118extern size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, void *context);
119
120__attribute__((format(printf,2,3)))
121extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
122
123extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
124/* XXX: if read fails, any partial read is undone */
125extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
126extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
127extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
128
129extern int strbuf_getline(struct strbuf *, FILE *, int);
130
131extern void stripspace(struct strbuf *buf, int skip_comments);
132extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
133
134extern int strbuf_branchname(struct strbuf *sb, const char *name);
135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
136
137#endif /* STRBUF_H */
diff --git a/Documentation/perf_counter/usage.c b/Documentation/perf_counter/usage.c
new file mode 100644
index 000000000000..7a10421fe6b4
--- /dev/null
+++ b/Documentation/perf_counter/usage.c
@@ -0,0 +1,80 @@
1/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
6#include "util.h"
7
8static void report(const char *prefix, const char *err, va_list params)
9{
10 char msg[1024];
11 vsnprintf(msg, sizeof(msg), err, params);
12 fprintf(stderr, "%s%s\n", prefix, msg);
13}
14
15static NORETURN void usage_builtin(const char *err)
16{
17 fprintf(stderr, "usage: %s\n", err);
18 exit(129);
19}
20
21static NORETURN void die_builtin(const char *err, va_list params)
22{
23 report("fatal: ", err, params);
24 exit(128);
25}
26
27static void error_builtin(const char *err, va_list params)
28{
29 report("error: ", err, params);
30}
31
32static void warn_builtin(const char *warn, va_list params)
33{
34 report("warning: ", warn, params);
35}
36
37/* If we are in a dlopen()ed .so write to a global variable would segfault
38 * (ugh), so keep things static. */
39static void (*usage_routine)(const char *err) NORETURN = usage_builtin;
40static void (*die_routine)(const char *err, va_list params) NORETURN = die_builtin;
41static void (*error_routine)(const char *err, va_list params) = error_builtin;
42static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
43
44void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN)
45{
46 die_routine = routine;
47}
48
49void usage(const char *err)
50{
51 usage_routine(err);
52}
53
54void die(const char *err, ...)
55{
56 va_list params;
57
58 va_start(params, err);
59 die_routine(err, params);
60 va_end(params);
61}
62
63int error(const char *err, ...)
64{
65 va_list params;
66
67 va_start(params, err);
68 error_routine(err, params);
69 va_end(params);
70 return -1;
71}
72
73void warning(const char *warn, ...)
74{
75 va_list params;
76
77 va_start(params, warn);
78 warn_routine(warn, params);
79 va_end(params);
80}
diff --git a/Documentation/perf_counter/util.h b/Documentation/perf_counter/util.h
new file mode 100644
index 000000000000..13f8bdce7600
--- /dev/null
+++ b/Documentation/perf_counter/util.h
@@ -0,0 +1,394 @@
1#ifndef GIT_COMPAT_UTIL_H
2#define GIT_COMPAT_UTIL_H
3
4#define _FILE_OFFSET_BITS 64
5
6#ifndef FLEX_ARRAY
7/*
8 * See if our compiler is known to support flexible array members.
9 */
10#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
11# define FLEX_ARRAY /* empty */
12#elif defined(__GNUC__)
13# if (__GNUC__ >= 3)
14# define FLEX_ARRAY /* empty */
15# else
16# define FLEX_ARRAY 0 /* older GNU extension */
17# endif
18#endif
19
20/*
21 * Otherwise, default to safer but a bit wasteful traditional style
22 */
23#ifndef FLEX_ARRAY
24# define FLEX_ARRAY 1
25#endif
26#endif
27
28#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
29
30#ifdef __GNUC__
31#define TYPEOF(x) (__typeof__(x))
32#else
33#define TYPEOF(x)
34#endif
35
36#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
37#define HAS_MULTI_BITS(i) ((i) & ((i) - 1)) /* checks if an integer has more than 1 bit set */
38
39/* Approximation of the length of the decimal representation of this type. */
40#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
41
42#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
43#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
44#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
45#endif
46#define _ALL_SOURCE 1
47#define _GNU_SOURCE 1
48#define _BSD_SOURCE 1
49
50#include <unistd.h>
51#include <stdio.h>
52#include <sys/stat.h>
53#include <fcntl.h>
54#include <stddef.h>
55#include <stdlib.h>
56#include <stdarg.h>
57#include <string.h>
58#include <errno.h>
59#include <limits.h>
60#include <sys/param.h>
61#include <sys/types.h>
62#include <dirent.h>
63#include <sys/time.h>
64#include <time.h>
65#include <signal.h>
66#include <fnmatch.h>
67#include <assert.h>
68#include <regex.h>
69#include <utime.h>
70#ifndef __MINGW32__
71#include <sys/wait.h>
72#include <sys/poll.h>
73#include <sys/socket.h>
74#include <sys/ioctl.h>
75#ifndef NO_SYS_SELECT_H
76#include <sys/select.h>
77#endif
78#include <netinet/in.h>
79#include <netinet/tcp.h>
80#include <arpa/inet.h>
81#include <netdb.h>
82#include <pwd.h>
83#include <inttypes.h>
84#if defined(__CYGWIN__)
85#undef _XOPEN_SOURCE
86#include <grp.h>
87#define _XOPEN_SOURCE 600
88#include "compat/cygwin.h"
89#else
90#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
91#include <grp.h>
92#define _ALL_SOURCE 1
93#endif
94#else /* __MINGW32__ */
95/* pull in Windows compatibility stuff */
96#include "compat/mingw.h"
97#endif /* __MINGW32__ */
98
99#ifndef NO_ICONV
100#include <iconv.h>
101#endif
102
103#ifndef NO_OPENSSL
104#include <openssl/ssl.h>
105#include <openssl/err.h>
106#endif
107
108/* On most systems <limits.h> would have given us this, but
109 * not on some systems (e.g. GNU/Hurd).
110 */
111#ifndef PATH_MAX
112#define PATH_MAX 4096
113#endif
114
115#ifndef PRIuMAX
116#define PRIuMAX "llu"
117#endif
118
119#ifndef PRIu32
120#define PRIu32 "u"
121#endif
122
123#ifndef PRIx32
124#define PRIx32 "x"
125#endif
126
127#ifndef PATH_SEP
128#define PATH_SEP ':'
129#endif
130
131#ifndef STRIP_EXTENSION
132#define STRIP_EXTENSION ""
133#endif
134
135#ifndef has_dos_drive_prefix
136#define has_dos_drive_prefix(path) 0
137#endif
138
139#ifndef is_dir_sep
140#define is_dir_sep(c) ((c) == '/')
141#endif
142
143#ifdef __GNUC__
144#define NORETURN __attribute__((__noreturn__))
145#else
146#define NORETURN
147#ifndef __attribute__
148#define __attribute__(x)
149#endif
150#endif
151
152/* General helper functions */
153extern void usage(const char *err) NORETURN;
154extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
155extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
156extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
157
158extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
159
160extern int prefixcmp(const char *str, const char *prefix);
161extern time_t tm_to_time_t(const struct tm *tm);
162
163static inline const char *skip_prefix(const char *str, const char *prefix)
164{
165 size_t len = strlen(prefix);
166 return strncmp(str, prefix, len) ? NULL : str + len;
167}
168
169#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
170
171#ifndef PROT_READ
172#define PROT_READ 1
173#define PROT_WRITE 2
174#define MAP_PRIVATE 1
175#define MAP_FAILED ((void*)-1)
176#endif
177
178#define mmap git_mmap
179#define munmap git_munmap
180extern void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
181extern int git_munmap(void *start, size_t length);
182
183#else /* NO_MMAP || USE_WIN32_MMAP */
184
185#include <sys/mman.h>
186
187#endif /* NO_MMAP || USE_WIN32_MMAP */
188
189#ifdef NO_MMAP
190
191/* This value must be multiple of (pagesize * 2) */
192#define DEFAULT_PACKED_GIT_WINDOW_SIZE (1 * 1024 * 1024)
193
194#else /* NO_MMAP */
195
196/* This value must be multiple of (pagesize * 2) */
197#define DEFAULT_PACKED_GIT_WINDOW_SIZE \
198 (sizeof(void*) >= 8 \
199 ? 1 * 1024 * 1024 * 1024 \
200 : 32 * 1024 * 1024)
201
202#endif /* NO_MMAP */
203
204#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
205#define on_disk_bytes(st) ((st).st_size)
206#else
207#define on_disk_bytes(st) ((st).st_blocks * 512)
208#endif
209
210#define DEFAULT_PACKED_GIT_LIMIT \
211 ((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256))
212
213#ifdef NO_PREAD
214#define pread git_pread
215extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
216#endif
217/*
218 * Forward decl that will remind us if its twin in cache.h changes.
219 * This function is used in compat/pread.c. But we can't include
220 * cache.h there.
221 */
222extern ssize_t read_in_full(int fd, void *buf, size_t count);
223
224#ifdef NO_SETENV
225#define setenv gitsetenv
226extern int gitsetenv(const char *, const char *, int);
227#endif
228
229#ifdef NO_MKDTEMP
230#define mkdtemp gitmkdtemp
231extern char *gitmkdtemp(char *);
232#endif
233
234#ifdef NO_UNSETENV
235#define unsetenv gitunsetenv
236extern void gitunsetenv(const char *);
237#endif
238
239#ifdef NO_STRCASESTR
240#define strcasestr gitstrcasestr
241extern char *gitstrcasestr(const char *haystack, const char *needle);
242#endif
243
244#ifdef NO_STRLCPY
245#define strlcpy gitstrlcpy
246extern size_t gitstrlcpy(char *, const char *, size_t);
247#endif
248
249#ifdef NO_STRTOUMAX
250#define strtoumax gitstrtoumax
251extern uintmax_t gitstrtoumax(const char *, char **, int);
252#endif
253
254#ifdef NO_HSTRERROR
255#define hstrerror githstrerror
256extern const char *githstrerror(int herror);
257#endif
258
259#ifdef NO_MEMMEM
260#define memmem gitmemmem
261void *gitmemmem(const void *haystack, size_t haystacklen,
262 const void *needle, size_t needlelen);
263#endif
264
265#ifdef FREAD_READS_DIRECTORIES
266#ifdef fopen
267#undef fopen
268#endif
269#define fopen(a,b) git_fopen(a,b)
270extern FILE *git_fopen(const char*, const char*);
271#endif
272
273#ifdef SNPRINTF_RETURNS_BOGUS
274#define snprintf git_snprintf
275extern int git_snprintf(char *str, size_t maxsize,
276 const char *format, ...);
277#define vsnprintf git_vsnprintf
278extern int git_vsnprintf(char *str, size_t maxsize,
279 const char *format, va_list ap);
280#endif
281
282#ifdef __GLIBC_PREREQ
283#if __GLIBC_PREREQ(2, 1)
284#define HAVE_STRCHRNUL
285#endif
286#endif
287
288#ifndef HAVE_STRCHRNUL
289#define strchrnul gitstrchrnul
290static inline char *gitstrchrnul(const char *s, int c)
291{
292 while (*s && *s != c)
293 s++;
294 return (char *)s;
295}
296#endif
297
298static inline size_t xsize_t(off_t len)
299{
300 return (size_t)len;
301}
302
303static inline int has_extension(const char *filename, const char *ext)
304{
305 size_t len = strlen(filename);
306 size_t extlen = strlen(ext);
307 return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
308}
309
310/* Sane ctype - no locale, and works with signed chars */
311#undef isascii
312#undef isspace
313#undef isdigit
314#undef isalpha
315#undef isalnum
316#undef tolower
317#undef toupper
318extern unsigned char sane_ctype[256];
319#define GIT_SPACE 0x01
320#define GIT_DIGIT 0x02
321#define GIT_ALPHA 0x04
322#define GIT_GLOB_SPECIAL 0x08
323#define GIT_REGEX_SPECIAL 0x10
324#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
325#define isascii(x) (((x) & ~0x7f) == 0)
326#define isspace(x) sane_istest(x,GIT_SPACE)
327#define isdigit(x) sane_istest(x,GIT_DIGIT)
328#define isalpha(x) sane_istest(x,GIT_ALPHA)
329#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
330#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
331#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
332#define tolower(x) sane_case((unsigned char)(x), 0x20)
333#define toupper(x) sane_case((unsigned char)(x), 0)
334
335static inline int sane_case(int x, int high)
336{
337 if (sane_istest(x, GIT_ALPHA))
338 x = (x & ~0x20) | high;
339 return x;
340}
341
342static inline int strtoul_ui(char const *s, int base, unsigned int *result)
343{
344 unsigned long ul;
345 char *p;
346
347 errno = 0;
348 ul = strtoul(s, &p, base);
349 if (errno || *p || p == s || (unsigned int) ul != ul)
350 return -1;
351 *result = ul;
352 return 0;
353}
354
355static inline int strtol_i(char const *s, int base, int *result)
356{
357 long ul;
358 char *p;
359
360 errno = 0;
361 ul = strtol(s, &p, base);
362 if (errno || *p || p == s || (int) ul != ul)
363 return -1;
364 *result = ul;
365 return 0;
366}
367
368#ifdef INTERNAL_QSORT
369void git_qsort(void *base, size_t nmemb, size_t size,
370 int(*compar)(const void *, const void *));
371#define qsort git_qsort
372#endif
373
374#ifndef DIR_HAS_BSD_GROUP_SEMANTICS
375# define FORCE_DIR_SET_GID S_ISGID
376#else
377# define FORCE_DIR_SET_GID 0
378#endif
379
380#ifdef NO_NSEC
381#undef USE_NSEC
382#define ST_CTIME_NSEC(st) 0
383#define ST_MTIME_NSEC(st) 0
384#else
385#ifdef USE_ST_TIMESPEC
386#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
387#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
388#else
389#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
390#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
391#endif
392#endif
393
394#endif
diff --git a/Documentation/perf_counter/wrapper.c b/Documentation/perf_counter/wrapper.c
new file mode 100644
index 000000000000..6350d65f6d9e
--- /dev/null
+++ b/Documentation/perf_counter/wrapper.c
@@ -0,0 +1,206 @@
1/*
2 * Various trivial helper wrappers around standard functions
3 */
4#include "cache.h"
5
6/*
7 * There's no pack memory to release - but stay close to the Git
8 * version so wrap this away:
9 */
10static inline void release_pack_memory(size_t size, int flag)
11{
12}
13
14char *xstrdup(const char *str)
15{
16 char *ret = strdup(str);
17 if (!ret) {
18 release_pack_memory(strlen(str) + 1, -1);
19 ret = strdup(str);
20 if (!ret)
21 die("Out of memory, strdup failed");
22 }
23 return ret;
24}
25
26void *xmalloc(size_t size)
27{
28 void *ret = malloc(size);
29 if (!ret && !size)
30 ret = malloc(1);
31 if (!ret) {
32 release_pack_memory(size, -1);
33 ret = malloc(size);
34 if (!ret && !size)
35 ret = malloc(1);
36 if (!ret)
37 die("Out of memory, malloc failed");
38 }
39#ifdef XMALLOC_POISON
40 memset(ret, 0xA5, size);
41#endif
42 return ret;
43}
44
45/*
46 * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
47 * "data" to the allocated memory, zero terminates the allocated memory,
48 * and returns a pointer to the allocated memory. If the allocation fails,
49 * the program dies.
50 */
51void *xmemdupz(const void *data, size_t len)
52{
53 char *p = xmalloc(len + 1);
54 memcpy(p, data, len);
55 p[len] = '\0';
56 return p;
57}
58
59char *xstrndup(const char *str, size_t len)
60{
61 char *p = memchr(str, '\0', len);
62 return xmemdupz(str, p ? p - str : len);
63}
64
65void *xrealloc(void *ptr, size_t size)
66{
67 void *ret = realloc(ptr, size);
68 if (!ret && !size)
69 ret = realloc(ptr, 1);
70 if (!ret) {
71 release_pack_memory(size, -1);
72 ret = realloc(ptr, size);
73 if (!ret && !size)
74 ret = realloc(ptr, 1);
75 if (!ret)
76 die("Out of memory, realloc failed");
77 }
78 return ret;
79}
80
81void *xcalloc(size_t nmemb, size_t size)
82{
83 void *ret = calloc(nmemb, size);
84 if (!ret && (!nmemb || !size))
85 ret = calloc(1, 1);
86 if (!ret) {
87 release_pack_memory(nmemb * size, -1);
88 ret = calloc(nmemb, size);
89 if (!ret && (!nmemb || !size))
90 ret = calloc(1, 1);
91 if (!ret)
92 die("Out of memory, calloc failed");
93 }
94 return ret;
95}
96
97void *xmmap(void *start, size_t length,
98 int prot, int flags, int fd, off_t offset)
99{
100 void *ret = mmap(start, length, prot, flags, fd, offset);
101 if (ret == MAP_FAILED) {
102 if (!length)
103 return NULL;
104 release_pack_memory(length, fd);
105 ret = mmap(start, length, prot, flags, fd, offset);
106 if (ret == MAP_FAILED)
107 die("Out of memory? mmap failed: %s", strerror(errno));
108 }
109 return ret;
110}
111
112/*
113 * xread() is the same a read(), but it automatically restarts read()
114 * operations with a recoverable error (EAGAIN and EINTR). xread()
115 * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
116 */
117ssize_t xread(int fd, void *buf, size_t len)
118{
119 ssize_t nr;
120 while (1) {
121 nr = read(fd, buf, len);
122 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
123 continue;
124 return nr;
125 }
126}
127
128/*
129 * xwrite() is the same a write(), but it automatically restarts write()
130 * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
131 * GUARANTEE that "len" bytes is written even if the operation is successful.
132 */
133ssize_t xwrite(int fd, const void *buf, size_t len)
134{
135 ssize_t nr;
136 while (1) {
137 nr = write(fd, buf, len);
138 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
139 continue;
140 return nr;
141 }
142}
143
144ssize_t read_in_full(int fd, void *buf, size_t count)
145{
146 char *p = buf;
147 ssize_t total = 0;
148
149 while (count > 0) {
150 ssize_t loaded = xread(fd, p, count);
151 if (loaded <= 0)
152 return total ? total : loaded;
153 count -= loaded;
154 p += loaded;
155 total += loaded;
156 }
157
158 return total;
159}
160
161ssize_t write_in_full(int fd, const void *buf, size_t count)
162{
163 const char *p = buf;
164 ssize_t total = 0;
165
166 while (count > 0) {
167 ssize_t written = xwrite(fd, p, count);
168 if (written < 0)
169 return -1;
170 if (!written) {
171 errno = ENOSPC;
172 return -1;
173 }
174 count -= written;
175 p += written;
176 total += written;
177 }
178
179 return total;
180}
181
182int xdup(int fd)
183{
184 int ret = dup(fd);
185 if (ret < 0)
186 die("dup failed: %s", strerror(errno));
187 return ret;
188}
189
190FILE *xfdopen(int fd, const char *mode)
191{
192 FILE *stream = fdopen(fd, mode);
193 if (stream == NULL)
194 die("Out of memory? fdopen failed: %s", strerror(errno));
195 return stream;
196}
197
198int xmkstemp(char *template)
199{
200 int fd;
201
202 fd = mkstemp(template);
203 if (fd < 0)
204 die("Unable to create temporary file: %s", strerror(errno));
205 return fd;
206}