mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-10 18:11:13 -03:00
Compare commits
198 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0122e35cb6 | ||
|
|
c96382152c | ||
|
|
af0bd61fb5 | ||
|
|
4a87c9895d | ||
|
|
036cc4e0fa | ||
|
|
9e304fa734 | ||
|
|
6d9631d0d0 | ||
|
|
bb04df2ac9 | ||
|
|
746a602515 | ||
|
|
a41fd8f759 | ||
|
|
ba9fbc67da | ||
|
|
ac40a3bcd0 | ||
|
|
942dcd7d54 | ||
|
|
9830bf985a | ||
|
|
7bb070d817 | ||
|
|
d56ab1d365 | ||
|
|
38175cdd30 | ||
|
|
436b1e10c6 | ||
|
|
e59cb1da5d | ||
|
|
e42198b7c8 | ||
|
|
2076944268 | ||
|
|
407c96e943 | ||
|
|
bf333f2a84 | ||
|
|
3ddd5e5981 | ||
|
|
b016438c08 | ||
|
|
7268a4a4e0 | ||
|
|
51c6c5ea49 | ||
|
|
5688035680 | ||
|
|
43b6b703ff | ||
|
|
e007a5c203 | ||
|
|
f836bd41c0 | ||
|
|
c9e98c2eef | ||
|
|
e94803152c | ||
|
|
07ff8a6c03 | ||
|
|
9f10dd377e | ||
|
|
6e0e7e0996 | ||
|
|
907b2f8462 | ||
|
|
d2869d5140 | ||
|
|
587e91d0c1 | ||
|
|
aad3249b79 | ||
|
|
081ab955af | ||
|
|
9a9d84c58a | ||
|
|
94d1322fc1 | ||
|
|
eed8b61a9e | ||
|
|
40558c2eb9 | ||
|
|
d677b468db | ||
|
|
4e38d3bc8c | ||
|
|
36ae253a29 | ||
|
|
f673b06dd2 | ||
|
|
e9e0643817 | ||
|
|
358f412abb | ||
|
|
a983798295 | ||
|
|
52a0149e4f | ||
|
|
8fdc46a105 | ||
|
|
63b02e308d | ||
|
|
7c97095bca | ||
|
|
b62beaf47d | ||
|
|
b2b1ec27d8 | ||
|
|
6aa682755d | ||
|
|
2bc49b3291 | ||
|
|
cea3dfd0cb | ||
|
|
d7d2c82a82 | ||
|
|
58aa1e75c1 | ||
|
|
0361423469 | ||
|
|
9aee2b7c9c | ||
|
|
2c95e087b2 | ||
|
|
5d5ee87a59 | ||
|
|
c60b62de73 | ||
|
|
2e5821c17d | ||
|
|
f46145a6b3 | ||
|
|
c61f6ceea6 | ||
|
|
d32751df13 | ||
|
|
038dcca143 | ||
|
|
d79e8c7f62 | ||
|
|
af8cb6fe87 | ||
|
|
5855f78010 | ||
|
|
f7118e769f | ||
|
|
93ae00e8e5 | ||
|
|
d7eb084b9d | ||
|
|
6e1548b821 | ||
|
|
5381c6cf93 | ||
|
|
20e5d298a0 | ||
|
|
39e9974e71 | ||
|
|
d2bd3e4919 | ||
|
|
04b142208d | ||
|
|
cf35a8e3a5 | ||
|
|
e7e3e8ee74 | ||
|
|
6fd69bdda8 | ||
|
|
a85f4cc1c4 | ||
|
|
07af5f4832 | ||
|
|
446272eee6 | ||
|
|
48ca253097 | ||
|
|
da2a757dff | ||
|
|
6fada015b6 | ||
|
|
a1a2773cbf | ||
|
|
67f216fa55 | ||
|
|
8986e05b94 | ||
|
|
7c016c56e3 | ||
|
|
0602044723 | ||
|
|
4ffd2afccd | ||
|
|
ec58ffa641 | ||
|
|
2c44ecb4a3 | ||
|
|
2eebb6e7ed | ||
|
|
1a3ab8a189 | ||
|
|
4722ddc373 | ||
|
|
25365dbc54 | ||
|
|
6a5f11879b | ||
|
|
b028e41f7f | ||
|
|
86593cd6a2 | ||
|
|
6cae5c8b0a | ||
|
|
29cd62ab6e | ||
|
|
4c7e06e752 | ||
|
|
433169dca4 | ||
|
|
d46dade284 | ||
|
|
79b466441b | ||
|
|
9f14d50974 | ||
|
|
990803009e | ||
|
|
6dfd629fc5 | ||
|
|
d97f8f3fde | ||
|
|
95ca3d1c69 | ||
|
|
c8b04f70cf | ||
|
|
bffff77d17 | ||
|
|
6bdb0cde8b | ||
|
|
42a260f1e6 | ||
|
|
148cb68700 | ||
|
|
18c185c256 | ||
|
|
b5b49e7a4d | ||
|
|
28ea5ce732 | ||
|
|
eccba7626d | ||
|
|
79d3207d51 | ||
|
|
d6bf879675 | ||
|
|
051f557e8f | ||
|
|
17171c3277 | ||
|
|
18a59291ed | ||
|
|
29e86254d0 | ||
|
|
b746a803a9 | ||
|
|
07e14ed7a8 | ||
|
|
df5cc6f858 | ||
|
|
409a407ca0 | ||
|
|
1c2cbb00bc | ||
|
|
bbf2a3836f | ||
|
|
1aa1ab540e | ||
|
|
27c9eb8758 | ||
|
|
e6b1035ddc | ||
|
|
9f6aba38d6 | ||
|
|
b52fe0feb6 | ||
|
|
db459f869a | ||
|
|
763a6b8351 | ||
|
|
4a06821d99 | ||
|
|
22f3dcfd35 | ||
|
|
dbb66e1895 | ||
|
|
5a7a264b96 | ||
|
|
3d601bd751 | ||
|
|
c9deea2237 | ||
|
|
32e54fd719 | ||
|
|
9ebdc16be6 | ||
|
|
92ecc01baa | ||
|
|
ff1c5e058f | ||
|
|
3d192a8e93 | ||
|
|
f5c6306bde | ||
|
|
524e0aa174 | ||
|
|
94abb30f94 | ||
|
|
af8e053896 | ||
|
|
633e2f498f | ||
|
|
4932538c74 | ||
|
|
786144ba86 | ||
|
|
e3dd94f272 | ||
|
|
b110a0ae21 | ||
|
|
48d9c38d1e | ||
|
|
51f8272ebd | ||
|
|
77f35c1b41 | ||
|
|
06668bfacb | ||
|
|
df59b8498f | ||
|
|
92fde30c0c | ||
|
|
d690a15b29 | ||
|
|
445f6539cf | ||
|
|
13a7269378 | ||
|
|
fd2644ce49 | ||
|
|
508de57459 | ||
|
|
de2405b35a | ||
|
|
a7f977836a | ||
|
|
f59e4a88c6 | ||
|
|
c755bd0358 | ||
|
|
536523ffd7 | ||
|
|
ca82fc2f03 | ||
|
|
d1411c42d6 | ||
|
|
9d770af5f4 | ||
|
|
d1ff6a323a | ||
|
|
112ea1759a | ||
|
|
76bafbef2a | ||
|
|
1947ec88f1 | ||
|
|
d0956f1e43 | ||
|
|
6996c7718e | ||
|
|
45d56d8e05 | ||
|
|
53295d38b7 | ||
|
|
bd9c843fd1 | ||
|
|
f812b9b26c | ||
|
|
52851a3ba4 |
@@ -93,7 +93,7 @@ DISABLE_INDEX = YES
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
GENERATE_LATEX = YES
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
249
Makefile.in
249
Makefile.in
@@ -23,7 +23,7 @@
|
||||
#
|
||||
# Makefile for the fish shell. Can build fish and associated
|
||||
# applications, install them, recalculate dependencies and also create
|
||||
# binary distributions in tar.bz2 tar.gz and rpm formats.
|
||||
# binary distributions in tar.bz2, tar.gz and rpm formats.
|
||||
#
|
||||
|
||||
#
|
||||
@@ -56,44 +56,36 @@ ETC_DIR_INSTALL = etc/fish_interactive.fish
|
||||
# Set to 1 if we have gettext
|
||||
HAVE_GETTEXT=@HAVE_GETTEXT@
|
||||
|
||||
CORE_OBJS := util.o common.o halloc.o halloc_util.o fallback.o
|
||||
#Additional .c files used by common.o. These also have a corresponding
|
||||
#.h file.
|
||||
COMMON_FILES := util.c halloc.c halloc_util.c fallback.c
|
||||
|
||||
# All objects used by fish, that are compiled from an ordinary .c file
|
||||
# using an ordinary .h file.
|
||||
COMMON_OBJS := function.o builtin.o complete.o env.o exec.o \
|
||||
# All objects that the system needs to build fish, except main.o
|
||||
FISH_OBJS := function.o builtin.o complete.o env.o exec.o \
|
||||
expand.o highlight.o history.o kill.o parser.o proc.o reader.o \
|
||||
sanity.o tokenizer.o wildcard.o wgetopt.o wutil.o input.o \
|
||||
output.o intern.o env_universal.o env_universal_common.o \
|
||||
input_common.o event.o signal.o io.o translate.o parse_util.o \
|
||||
$(CORE_OBJS)
|
||||
input_common.o event.o signal.o io.o translate.o parse_util.o common.o \
|
||||
|
||||
# builtin_help.h exists, but builtin_help.c is autogenerated
|
||||
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
||||
|
||||
# main.c exists, but main.h does not, etc.
|
||||
COMMON_OBJS_WITH_CODE := builtin_set.o builtin_commandline.o \
|
||||
builtin_ulimit.o builtin_complete.o
|
||||
|
||||
# All objects that the system needs to build fish
|
||||
FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
|
||||
$(COMMON_OBJS_WITH_HEADER) main.o
|
||||
# Additional files used by builtin.o
|
||||
BUILTIN_FILES := builtin_help.c builtin_set.c builtin_commandline.c \
|
||||
builtin_ulimit.c builtin_complete.c builtin_jobs.c
|
||||
|
||||
# All objects that the system needs to build fish_pager
|
||||
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \
|
||||
tokenizer.o input_common.o env_universal.o env_universal_common.o \
|
||||
translate.o $(CORE_OBJS)
|
||||
translate.o common.o
|
||||
|
||||
# All objects that the system needs to build fish_tests
|
||||
FISH_TESTS_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
|
||||
$(COMMON_OBJS_WITH_HEADER) fish_tests.o
|
||||
FISH_TESTS_OBJS := $(FISH_OBJS) fish_tests.o
|
||||
|
||||
# All objects that the system needs to build fishd
|
||||
FISHD_OBJS := fishd.o env_universal_common.o wutil.o \
|
||||
doc_src/fishd.o $(CORE_OBJS)
|
||||
doc_src/fishd.o common.o
|
||||
|
||||
# All objects needed to build mimedb
|
||||
MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
|
||||
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o $(CORE_OBJS)
|
||||
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o common.o
|
||||
|
||||
#
|
||||
# Files containing documentation for builtins. Should be listed
|
||||
@@ -150,14 +142,14 @@ DOC_SRC_DIR_FILES := doc_src/Doxyfile.in doc_src/doc.hdr \
|
||||
$(BUILTIN_DOC_SRC) $(CMD_DOC_SRC) doc_src/fish.1.in
|
||||
|
||||
# Files in ./
|
||||
MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
|
||||
configure.ac config.h.in install-sh set_color.c count.c \
|
||||
key_reader.c gen_hdr.sh gen_hdr2.c $(MIME_OBJS:.o=.h) \
|
||||
$(MIME_OBJS:.o=.c) $(COMMON_OBJS_WITH_HEADER:.o=.h) \
|
||||
$(COMMON_OBJS:.o=.h) $(COMMON_OBJS_WITH_CODE:.o=.c) \
|
||||
$(COMMON_OBJS:.o=.c) builtin_help.hdr fish.spec.in INSTALL README \
|
||||
user_doc.head.html xsel-0.9.6.tar ChangeLog config.sub \
|
||||
config.guess fish_tests.c main.c fish_pager.c fishd.c seq.in
|
||||
MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
|
||||
configure.ac config.h.in install-sh set_color.c count.c \
|
||||
key_reader.c gen_hdr.sh gen_hdr2.c $(MIME_OBJS:.o=.h) \
|
||||
$(MIME_OBJS:.o=.c) $(FISH_OBJS:.o=.h) $(BUILTIN_FILES) \
|
||||
$(COMMON_FILES) $(COMMON_FILES:.c=.h) $(FISH_OBJS:.o=.c) \
|
||||
builtin_help.hdr fish.spec.in INSTALL README user_doc.head.html \
|
||||
xsel-0.9.6.tar ChangeLog config.sub config.guess fish_tests.c \
|
||||
main.c fish_pager.c fishd.c seq.in
|
||||
|
||||
# Files in ./etc/
|
||||
ETC_DIR_FILES :=etc/fish.in etc/fish_inputrc \
|
||||
@@ -208,8 +200,10 @@ debug:
|
||||
.PHONY: debug
|
||||
|
||||
# User documentation, describing the features of the fish shell.
|
||||
user_doc: doc.h Doxyfile.user user_doc.head.html
|
||||
user_doc: doc_src/doc.hdr Doxyfile.user user_doc.head.html
|
||||
$(MAKE) doc.h # Depend on the source (doc.hdr) and manually make the intermediate as needed
|
||||
doxygen Doxyfile.user
|
||||
touch user_doc
|
||||
|
||||
# Source code documentation. Also includes user documentation.
|
||||
doc: *.h *.c doc.h Doxyfile builtin_help.c
|
||||
@@ -283,6 +277,10 @@ messages.pot: *.c *.h etc/*.in share/fish share/completions/*.fish share/functio
|
||||
fi; \
|
||||
fi
|
||||
|
||||
builtin.o: $(BUILTIN_FILES)
|
||||
|
||||
common.o: $(COMMON_FILES)
|
||||
|
||||
# Generate the internal help functions by making doxygen create
|
||||
# man-pages which are then converted into C code. The convertion path
|
||||
# looks like this:
|
||||
@@ -315,15 +313,24 @@ messages.pot: *.c *.h etc/*.in share/fish share/completions/*.fish share/functio
|
||||
# Which is an awful, clunky and ugly way of producing
|
||||
# documentation. There ought to be something simpler.
|
||||
|
||||
builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh builtin_help.hdr $(CMD_DOC_HDR)
|
||||
cd doc_src; doxygen; cd ..;
|
||||
doc_src/builtin_doc: $(BUILTIN_DOC_SRC) doc_src/count.txt builtin_help.hdr $(CMD_DOC_SRC)
|
||||
for i in $(BUILTIN_DOC_SRC) $(CMD_DOC_SRC); do \
|
||||
FILE=doc_src/`basename $$i .txt`.doxygen; \
|
||||
echo "/** \page" `basename $$i .txt` >$$FILE; \
|
||||
cat $$i >>$$FILE; \
|
||||
echo "*/" >>$$FILE; \
|
||||
done
|
||||
cd doc_src; doxygen; cd ..;
|
||||
touch doc_src/builtin_doc
|
||||
|
||||
builtin_help.c: doc_src/builtin_doc gen_hdr.sh
|
||||
$(MAKE) gen_hdr2 # Don't depend on gen_hdr2, because then we would need to rebuild the docs whenever we use a fresh tarball
|
||||
cp builtin_help.hdr builtin_help.c;
|
||||
chmod 755 gen_hdr.sh
|
||||
if ! test -x gen_hdr.sh; then chmod 755 gen_hdr.sh; fi
|
||||
for i in $(BUILTIN_DOC_HDR) doc_src/count.doxygen ; do \
|
||||
echo ' hash_put( &tbl, L"'`basename $$i .doxygen`'",' >>$@; \
|
||||
echo ' hash_put( &tbl, L"'`basename $$i .doxygen`'",' >>$@; \
|
||||
./gen_hdr.sh $$i >>$@; \
|
||||
echo " );" >>$@; \
|
||||
echo >>$@; \
|
||||
printf " );\n\n" >>$@; \
|
||||
done;
|
||||
echo "}" >>builtin_help.c
|
||||
|
||||
@@ -332,7 +339,8 @@ builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh bui
|
||||
# mimedb. Depends on builtin_help.c to make sure doxygen gets run to
|
||||
# generate the man files.
|
||||
#
|
||||
%.c : %.doxygen gen_hdr2 builtin_help.c
|
||||
%.c : %.doxygen
|
||||
$(MAKE) gen_hdr2 builtin_help.c # These should really be filed as dependencis for %.c above instead, but that seems to confuse make
|
||||
echo "// This file was automatically generated, do not edit" >$@
|
||||
echo "#include <stdlib.h>" >>$@
|
||||
echo "#include <stdio.h>" >>$@
|
||||
@@ -344,7 +352,6 @@ builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh bui
|
||||
./gen_hdr.sh $*.doxygen >>$@
|
||||
echo ");" >>$@
|
||||
echo "}" >>$@
|
||||
#man -- doc_src/builtin_doc/man/man1/`basename $@ .c`.1 | cat -s | ./gen_hdr2 >>$@
|
||||
|
||||
#
|
||||
# The build rules for installing/uninstalling fish
|
||||
@@ -413,7 +420,7 @@ install-force: all install-translations
|
||||
@echo \* use the command \'chsh -s $(DESTDIR)$(bindir)/fish\'.
|
||||
@echo
|
||||
@echo Have fun!
|
||||
.PHONY: force-install
|
||||
.PHONY: install-force
|
||||
|
||||
|
||||
# Uninstall this fish version
|
||||
@@ -455,6 +462,7 @@ uninstall-legacy: uninstall
|
||||
rmdir $(DESTDIR)$(sysconfdir)/fish.d/completions; true
|
||||
rmdir $(DESTDIR)$(sysconfdir)/fish.d; true
|
||||
@echo The previous fish installation has been removed.
|
||||
.PHONY: uninstall-legacy
|
||||
|
||||
install-translations: $(TRANSLATIONS)
|
||||
if test $(HAVE_GETTEXT) = 1; then \
|
||||
@@ -478,8 +486,8 @@ uninstall-translations:
|
||||
# The build rules for all the commands
|
||||
#
|
||||
|
||||
fish: $(FISH_OBJS)
|
||||
$(CC) $(FISH_OBJS) $(LDFLAGS) -o $@
|
||||
fish: $(FISH_OBJS) main.o
|
||||
$(CC) $(FISH_OBJS) main.o $(LDFLAGS) -o $@
|
||||
|
||||
fish_pager: $(FISH_PAGER_OBJS)
|
||||
$(CC) $(FISH_PAGER_OBJS) $(LDFLAGS) -o $@
|
||||
@@ -490,20 +498,24 @@ fishd: $(FISHD_OBJS)
|
||||
fish_tests: $(FISH_TESTS_OBJS)
|
||||
$(CC) $(FISH_TESTS_OBJS) $(LDFLAGS) -o $@
|
||||
|
||||
|
||||
# mimedb does not need any libraries, so we don't use LDFLAGS here
|
||||
mimedb: $(MIME_OBJS) doc_src/mimedb.o
|
||||
$(CC) ${MIME_OBJS} doc_src/mimedb.o $(LDFLAGS) -o $@
|
||||
$(CC) $(MIME_OBJS) doc_src/mimedb.o -o $@
|
||||
|
||||
set_color: set_color.o doc_src/set_color.o
|
||||
$(CC) set_color.o doc_src/set_color.o $(LDFLAGS) -o $@
|
||||
# count does not need any libraries, so we don't use LDFLAGS here
|
||||
count: count.o
|
||||
$(CC) count.o -o $@
|
||||
|
||||
set_color: set_color.o doc_src/set_color.o fallback.o
|
||||
$(CC) set_color.o doc_src/set_color.o fallback.o $(LDFLAGS) -o $@
|
||||
|
||||
# Test program for the tokenizer library
|
||||
tokenizer_test: tokenizer.c tokenizer.h util.o wutil.o common.o
|
||||
$(CC) ${CFLAGS} tokenizer.c util.o wutil.o common.o -D TOKENIZER_TEST $(LDFLAGS) -o $@
|
||||
tokenizer_test: tokenizer.c tokenizer.h wutil.o common.o
|
||||
$(CC) ${CFLAGS} tokenizer.c wutil.o common.o -D TOKENIZER_TEST $(LDFLAGS) -o $@
|
||||
|
||||
# Neat little program to show output from terminal
|
||||
key_reader: key_reader.o input_common.o $(CORE_OBJS) env_universal.o env_universal_common.o wutil.o
|
||||
$(CC) key_reader.o input_common.o $(CORE_OBJS) env_universal.o env_universal_common.o wutil.o $(LDFLAGS) -o $@
|
||||
key_reader: key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o
|
||||
$(CC) key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o $(LDFLAGS) -o $@
|
||||
|
||||
#
|
||||
# Update dependencies
|
||||
@@ -519,10 +531,11 @@ depend:
|
||||
#
|
||||
# Uses install instead of mkdir so build won't fail if the directory
|
||||
# exists
|
||||
fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(ETC_DIR_FILES) $(TEST_DIR_FILES) $(SHARE_DIR_FILES) $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog
|
||||
fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(ETC_DIR_FILES) $(TEST_DIR_FILES) $(SHARE_DIR_FILES) $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog user_doc doc_src/builtin_doc
|
||||
rm -rf fish-@PACKAGE_VERSION@
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/doc_src
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/user_doc
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/etc
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/share
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/share/completions
|
||||
@@ -537,6 +550,8 @@ fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(ETC_DIR_FIL
|
||||
cp -f $(FUNCTIONS_DIR_FILES) fish-@PACKAGE_VERSION@/share/functions/
|
||||
cp -f $(TESTS_DIR_FILES) fish-@PACKAGE_VERSION@/tests/
|
||||
cp -f $(TRANSLATIONS_SRC) fish-@PACKAGE_VERSION@/po/
|
||||
cp -rf user_doc fish-@PACKAGE_VERSION@/
|
||||
cp -rf doc_src/builtin_doc fish-@PACKAGE_VERSION@/doc_src/
|
||||
tar -c fish-@PACKAGE_VERSION@ >fish-@PACKAGE_VERSION@.tar
|
||||
rm -rf fish-@PACKAGE_VERSION@
|
||||
|
||||
@@ -579,7 +594,7 @@ distclean: clean
|
||||
.PHONY: distclean
|
||||
|
||||
clean:
|
||||
rm -f *.o doc.h doc_src/*.doxygen doc_src/*.c builtin_help.c
|
||||
rm -f *.o doc.h doc_src/*.doxygen doc_src/*.c builtin_help.c doc_src/*.o
|
||||
rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt
|
||||
rm -f tokenizer_test fish key_reader set_color gen_hdr2 mimedb
|
||||
rm -f fishd fish_pager count fish_tests
|
||||
@@ -596,112 +611,116 @@ clean:
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
builtin.o: config.h fallback.h common.h util.h wutil.h builtin.h function.h
|
||||
builtin.o: complete.h proc.h io.h parser.h event.h reader.h env.h wgetopt.h
|
||||
builtin.o: sanity.h tokenizer.h builtin_help.h wildcard.h input_common.h
|
||||
builtin.o: input.h intern.h signal.h translate.h halloc.h halloc_util.h
|
||||
builtin.o: parse_util.h expand.h
|
||||
builtin_commandline.o: signal.h config.h fallback.h common.h util.h wutil.h
|
||||
builtin_commandline.o: builtin.h wgetopt.h reader.h proc.h io.h parser.h
|
||||
builtin.o: config.h fallback.h util.h wutil.h builtin.h function.h complete.h
|
||||
builtin.o: proc.h io.h parser.h event.h reader.h env.h common.h wgetopt.h
|
||||
builtin.o: sanity.h tokenizer.h wildcard.h input_common.h input.h intern.h
|
||||
builtin.o: signal.h translate.h halloc.h halloc_util.h parse_util.h expand.h
|
||||
builtin.o: builtin_help.c builtin_set.c builtin_commandline.c
|
||||
builtin.o: builtin_complete.c builtin_ulimit.c builtin_jobs.c
|
||||
builtin_commandline.o: signal.h config.h fallback.h util.h wutil.h builtin.h
|
||||
builtin_commandline.o: common.h wgetopt.h reader.h proc.h io.h parser.h
|
||||
builtin_commandline.o: event.h tokenizer.h input_common.h input.h translate.h
|
||||
builtin_commandline.o: parse_util.h
|
||||
builtin_complete.o: signal.h config.h fallback.h common.h util.h wutil.h
|
||||
builtin_complete.o: builtin.h complete.h wgetopt.h parser.h proc.h io.h
|
||||
builtin_complete.o: signal.h config.h fallback.h util.h wutil.h builtin.h
|
||||
builtin_complete.o: common.h complete.h wgetopt.h parser.h proc.h io.h
|
||||
builtin_complete.o: event.h reader.h translate.h
|
||||
builtin_help.o: config.h util.h common.h builtin_help.h
|
||||
builtin_set.o: signal.h config.h fallback.h common.h util.h wutil.h builtin.h
|
||||
builtin_set.o: env.h expand.h wgetopt.h proc.h io.h parser.h event.h
|
||||
builtin_help.o: config.h util.h common.h halloc_util.h
|
||||
builtin_jobs.o: config.h fallback.h util.h wutil.h builtin.h proc.h io.h
|
||||
builtin_jobs.o: parser.h event.h common.h wgetopt.h translate.h
|
||||
builtin_set.o: signal.h config.h fallback.h util.h wutil.h builtin.h env.h
|
||||
builtin_set.o: expand.h common.h wgetopt.h proc.h io.h parser.h event.h
|
||||
builtin_set.o: translate.h
|
||||
builtin_ulimit.o: config.h fallback.h common.h util.h builtin.h wgetopt.h
|
||||
builtin_ulimit.o: config.h fallback.h util.h builtin.h common.h wgetopt.h
|
||||
builtin_ulimit.o: translate.h
|
||||
common.o: config.h fallback.h common.h util.h wutil.h expand.h proc.h io.h
|
||||
common.o: wildcard.h parser.h event.h
|
||||
complete.o: signal.h config.h fallback.h common.h util.h tokenizer.h
|
||||
complete.o: wildcard.h proc.h io.h parser.h event.h function.h complete.h
|
||||
complete.o: builtin.h env.h exec.h expand.h reader.h history.h intern.h
|
||||
complete.o: translate.h parse_util.h halloc_util.h wutil.h
|
||||
dragon.o: signal.h
|
||||
env.o: config.h signal.h fallback.h common.h util.h wutil.h proc.h io.h env.h
|
||||
common.o: config.h fallback.h util.h wutil.h common.h expand.h proc.h io.h
|
||||
common.o: wildcard.h parser.h event.h util.c halloc.c halloc.h halloc_util.c
|
||||
common.o: fallback.c
|
||||
complete.o: signal.h config.h fallback.h util.h tokenizer.h wildcard.h proc.h
|
||||
complete.o: io.h parser.h event.h function.h complete.h builtin.h env.h
|
||||
complete.o: exec.h expand.h common.h reader.h history.h intern.h translate.h
|
||||
complete.o: parse_util.h halloc.h halloc_util.h wutil.h
|
||||
env.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h env.h
|
||||
env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h
|
||||
env.o: env_universal_common.h input_common.h translate.h complete.h
|
||||
env_universal.o: config.h signal.h fallback.h common.h util.h wutil.h
|
||||
env_universal.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
env_universal.o: env_universal_common.h env_universal.h
|
||||
env_universal_common.o: config.h signal.h fallback.h common.h util.h wutil.h
|
||||
env_universal_common.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
env_universal_common.o: env_universal_common.h
|
||||
event.o: signal.h config.h fallback.h common.h util.h wutil.h function.h
|
||||
event.o: proc.h io.h parser.h event.h translate.h halloc_util.h
|
||||
exec.o: signal.h config.h fallback.h common.h util.h wutil.h proc.h io.h
|
||||
event.o: signal.h config.h fallback.h util.h wutil.h function.h proc.h io.h
|
||||
event.o: parser.h event.h common.h translate.h halloc_util.h
|
||||
exec.o: signal.h config.h fallback.h util.h common.h wutil.h proc.h io.h
|
||||
exec.o: exec.h parser.h event.h builtin.h function.h env.h wildcard.h
|
||||
exec.o: sanity.h expand.h env_universal.h env_universal_common.h translate.h
|
||||
exec.o: halloc.h halloc_util.h parse_util.h
|
||||
expand.o: signal.h config.h fallback.h common.h util.h wutil.h env.h proc.h
|
||||
expand.o: signal.h config.h fallback.h util.h common.h wutil.h env.h proc.h
|
||||
expand.o: io.h parser.h event.h expand.h wildcard.h exec.h tokenizer.h
|
||||
expand.o: complete.h translate.h parse_util.h halloc_util.h
|
||||
fallback.o: config.h common.h util.h
|
||||
fishd.o: config.h signal.h fallback.h common.h util.h wutil.h
|
||||
fallback.o: config.h fallback.h util.h
|
||||
fishd.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
fishd.o: env_universal_common.h
|
||||
fish_pager.o: config.h signal.h fallback.h common.h util.h wutil.h complete.h
|
||||
fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h
|
||||
fish_pager.o: output.h input_common.h env_universal.h env_universal_common.h
|
||||
fish_pager.o: halloc.h halloc_util.h
|
||||
fish_tests.o: config.h signal.h fallback.h common.h util.h proc.h io.h
|
||||
fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h
|
||||
fish_tests.o: reader.h builtin.h function.h complete.h wutil.h env.h expand.h
|
||||
fish_tests.o: parser.h event.h tokenizer.h output.h exec.h halloc_util.h
|
||||
function.o: signal.h config.h wutil.h fallback.h common.h util.h function.h
|
||||
function.o: proc.h io.h translate.h parser.h event.h intern.h reader.h
|
||||
function.o: signal.h config.h wutil.h fallback.h util.h function.h proc.h
|
||||
function.o: io.h translate.h parser.h event.h common.h intern.h reader.h
|
||||
function.o: parse_util.h env.h expand.h
|
||||
halloc.o: config.h fallback.h common.h util.h halloc.h
|
||||
halloc_util.o: config.h fallback.h common.h util.h halloc.h
|
||||
highlight.o: signal.h config.h fallback.h common.h util.h wutil.h highlight.h
|
||||
halloc.o: config.h fallback.h util.h common.h halloc.h
|
||||
halloc_util.o: config.h fallback.h util.h common.h halloc.h
|
||||
highlight.o: signal.h config.h fallback.h util.h wutil.h highlight.h
|
||||
highlight.o: tokenizer.h proc.h io.h parser.h event.h parse_util.h builtin.h
|
||||
highlight.o: function.h env.h expand.h sanity.h complete.h output.h
|
||||
history.o: config.h fallback.h common.h util.h wutil.h history.h reader.h
|
||||
highlight.o: function.h env.h expand.h sanity.h common.h complete.h output.h
|
||||
highlight.o: halloc.h halloc_util.h
|
||||
history.o: config.h fallback.h util.h wutil.h history.h common.h reader.h
|
||||
history.o: env.h sanity.h signal.h
|
||||
input.o: config.h signal.h fallback.h common.h util.h wutil.h reader.h proc.h
|
||||
input.o: io.h sanity.h input_common.h input.h parser.h event.h env.h expand.h
|
||||
input.o: translate.h output.h
|
||||
input_common.o: config.h fallback.h common.h util.h wutil.h input_common.h
|
||||
input.o: config.h signal.h fallback.h util.h wutil.h reader.h proc.h io.h
|
||||
input.o: common.h sanity.h input_common.h input.h parser.h event.h env.h
|
||||
input.o: expand.h translate.h output.h
|
||||
input_common.o: config.h fallback.h util.h common.h wutil.h input_common.h
|
||||
input_common.o: env_universal.h env_universal_common.h
|
||||
intern.o: config.h fallback.h common.h util.h wutil.h intern.h
|
||||
io.o: config.h fallback.h common.h util.h wutil.h exec.h proc.h io.h
|
||||
intern.o: config.h fallback.h util.h wutil.h common.h intern.h
|
||||
io.o: config.h fallback.h util.h wutil.h exec.h proc.h io.h common.h
|
||||
io.o: translate.h halloc.h
|
||||
key_reader.o: fallback.h common.h util.h input_common.h
|
||||
kill.o: signal.h config.h fallback.h common.h util.h wutil.h kill.h proc.h
|
||||
kill.o: io.h sanity.h env.h exec.h parser.h event.h
|
||||
main.o: config.h signal.h fallback.h common.h util.h reader.h builtin.h
|
||||
key_reader.o: config.h fallback.h input_common.h
|
||||
kill.o: signal.h config.h fallback.h util.h wutil.h kill.h proc.h io.h
|
||||
kill.o: sanity.h common.h env.h exec.h parser.h event.h halloc.h
|
||||
main.o: config.h signal.h fallback.h util.h common.h reader.h builtin.h
|
||||
main.o: function.h complete.h wutil.h env.h sanity.h proc.h io.h parser.h
|
||||
main.o: event.h expand.h intern.h exec.h output.h translate.h halloc_util.h
|
||||
mimedb.o: config.h xdgmime.h fallback.h common.h util.h
|
||||
output.o: config.h signal.h fallback.h common.h util.h wutil.h expand.h
|
||||
main.o: history.h
|
||||
mimedb.o: config.h xdgmime.h fallback.h util.h
|
||||
output.o: config.h signal.h fallback.h util.h wutil.h expand.h common.h
|
||||
output.o: output.h halloc_util.h highlight.h
|
||||
parser.o: signal.h config.h fallback.h common.h util.h wutil.h proc.h io.h
|
||||
parser.o: signal.h config.h fallback.h util.h common.h wutil.h proc.h io.h
|
||||
parser.o: parser.h event.h tokenizer.h exec.h wildcard.h function.h builtin.h
|
||||
parser.o: builtin_help.h env.h expand.h reader.h sanity.h env_universal.h
|
||||
parser.o: env.h expand.h reader.h sanity.h env_universal.h
|
||||
parser.o: env_universal_common.h translate.h intern.h parse_util.h halloc.h
|
||||
parser.o: halloc_util.h
|
||||
parse_util.o: config.h fallback.h common.h util.h wutil.h tokenizer.h
|
||||
parse_util.o: config.h fallback.h util.h wutil.h common.h tokenizer.h
|
||||
parse_util.o: parse_util.h expand.h intern.h exec.h proc.h io.h env.h
|
||||
parse_util.o: wildcard.h halloc_util.h
|
||||
proc.o: config.h signal.h fallback.h common.h util.h wutil.h proc.h io.h
|
||||
proc.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h
|
||||
proc.o: reader.h sanity.h env.h parser.h event.h translate.h halloc.h
|
||||
proc.o: halloc_util.h output.h
|
||||
reader.o: config.h signal.h fallback.h common.h util.h wutil.h highlight.h
|
||||
reader.o: reader.h proc.h io.h parser.h event.h complete.h history.h sanity.h
|
||||
reader.o: config.h signal.h fallback.h util.h wutil.h highlight.h reader.h
|
||||
reader.o: proc.h io.h parser.h event.h complete.h history.h common.h sanity.h
|
||||
reader.o: env.h exec.h expand.h tokenizer.h kill.h input_common.h input.h
|
||||
reader.o: function.h output.h translate.h parse_util.h
|
||||
refcount.o: config.h fallback.h common.h util.h wutil.h refcount.h
|
||||
sanity.o: signal.h config.h fallback.h common.h util.h sanity.h proc.h io.h
|
||||
sanity.o: signal.h config.h fallback.h util.h common.h sanity.h proc.h io.h
|
||||
sanity.o: history.h reader.h kill.h wutil.h translate.h
|
||||
set_color.o: config.h
|
||||
signal.o: config.h signal.h common.h util.h fallback.h wutil.h event.h
|
||||
signal.o: reader.h proc.h io.h translate.h
|
||||
tokenizer.o: config.h fallback.h common.h util.h wutil.h tokenizer.h
|
||||
tokenizer.o: config.h fallback.h util.h wutil.h tokenizer.h common.h
|
||||
tokenizer.o: wildcard.h translate.h
|
||||
translate.o: config.h common.h util.h fallback.h halloc_util.h
|
||||
util.o: config.h fallback.h common.h util.h wutil.h
|
||||
wgetopt.o: config.h wgetopt.h wutil.h fallback.h common.h util.h translate.h
|
||||
wildcard.o: config.h fallback.h common.h util.h wutil.h complete.h wildcard.h
|
||||
util.o: config.h fallback.h util.h common.h wutil.h
|
||||
wgetopt.o: config.h wgetopt.h wutil.h fallback.h translate.h
|
||||
wildcard.o: config.h fallback.h util.h wutil.h complete.h common.h wildcard.h
|
||||
wildcard.o: reader.h expand.h translate.h
|
||||
wutil.o: config.h fallback.h common.h util.h wutil.h
|
||||
wutil.o: config.h fallback.h util.h common.h wutil.h
|
||||
xdgmimealias.o: xdgmimealias.h xdgmime.h xdgmimeint.h
|
||||
xdgmime.o: xdgmime.h xdgmimeint.h xdgmimeglob.h xdgmimemagic.h xdgmimealias.h
|
||||
xdgmime.o: xdgmimeparent.h
|
||||
|
||||
56
builtin.h
56
builtin.h
@@ -57,6 +57,16 @@ enum
|
||||
*/
|
||||
#define BUILTIN_ERR_VARNAME_ZERO _( L"%ls: Variable name can not be the empty string\n" )
|
||||
|
||||
/**
|
||||
Error message when second argument to for isn't 'in'
|
||||
*/
|
||||
#define BUILTIN_FOR_ERR_IN _( L"%ls: Second argument must be 'in'\n" )
|
||||
|
||||
/**
|
||||
Error message when too many arguments are supplied to a builtin
|
||||
*/
|
||||
#define BUILTIN_ERR_TOO_MANY_ARGUMENTS _( L"%ls: Too many arguments\n" )
|
||||
|
||||
/**
|
||||
Stringbuffer used to represent standard output
|
||||
*/
|
||||
@@ -126,46 +136,22 @@ void builtin_pop_io();
|
||||
*/
|
||||
const wchar_t *builtin_get_desc( const wchar_t *b );
|
||||
|
||||
/**
|
||||
Counts the number of non null pointers in the specified array
|
||||
*/
|
||||
int builtin_count_args( wchar_t **argv );
|
||||
|
||||
/**
|
||||
Print help for the specified builtin. If \c b is sb_err, also print the line information
|
||||
Slightly kludgy function used with 'complete -C' in order to make
|
||||
the commandline builtin operate on the string to complete instead
|
||||
of operating on whatever is to be completed.
|
||||
*/
|
||||
void builtin_print_help( wchar_t *cmd, string_buffer_t *b );
|
||||
|
||||
|
||||
/**
|
||||
The set builtin, used for setting variables. Defined in builtin_set.c.
|
||||
*/
|
||||
int builtin_set(wchar_t **argv);
|
||||
|
||||
/**
|
||||
The commandline builtin, used for setting and getting the contents of the commandline. Defined in builtin_commandline.c.
|
||||
*/
|
||||
int builtin_commandline(wchar_t **argv);
|
||||
|
||||
/**
|
||||
The ulimit builtin, used for setting resource limits. Defined in builtin_ulimit.c.
|
||||
*/
|
||||
int builtin_ulimit(wchar_t **argv);
|
||||
|
||||
/**
|
||||
The complete builtin. Used for specifying programmable
|
||||
tab-completions. Calls the functions in complete.c for any heavy
|
||||
lifting.
|
||||
*/
|
||||
int builtin_complete(wchar_t **argv);
|
||||
|
||||
const wchar_t *builtin_complete_get_temporary_buffer();
|
||||
|
||||
/**
|
||||
This function works like wperror, but it prints its result into
|
||||
the sb_err string_buffer_t instead of to stderr. Used by the builtin
|
||||
commands.
|
||||
|
||||
/**
|
||||
Return the help text for the specified builtin command. Use
|
||||
non-wide characters since wide characters have some issues with
|
||||
string formating escape sequences sometimes.
|
||||
|
||||
\param cmd The command for which to obtain help text
|
||||
*/
|
||||
void builtin_wperror( const wchar_t *s);
|
||||
char *builtin_help_get( const wchar_t *cmd );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -63,6 +63,9 @@ static const wchar_t *get_buffer()
|
||||
return buff;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the position of the cursor
|
||||
*/
|
||||
static int get_cursor_pos()
|
||||
{
|
||||
const wchar_t *buff = builtin_complete_get_temporary_buffer();
|
||||
@@ -195,7 +198,7 @@ static void write_part( const wchar_t *begin,
|
||||
The commandline builtin. It is used for specifying a new value for
|
||||
the commandline.
|
||||
*/
|
||||
int builtin_commandline( wchar_t **argv )
|
||||
static int builtin_commandline( wchar_t **argv )
|
||||
{
|
||||
|
||||
int buffer_part=0;
|
||||
@@ -265,6 +268,10 @@ int builtin_commandline( wchar_t **argv )
|
||||
L"tokenize", no_argument, 0, 'o'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
@@ -275,7 +282,7 @@ int builtin_commandline( wchar_t **argv )
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"aijpctwfor",
|
||||
L"aijpctwforh",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
@@ -330,6 +337,10 @@ int builtin_commandline( wchar_t **argv )
|
||||
tokenize=1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
case L'?':
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
@@ -453,13 +464,13 @@ int builtin_commandline( wchar_t **argv )
|
||||
buffer_part = STRING_MODE;
|
||||
}
|
||||
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *begin, *end;
|
||||
|
||||
switch( buffer_part )
|
||||
{
|
||||
case STRING_MODE:
|
||||
{
|
||||
begin = get_buffer();
|
||||
begin = (wchar_t *)get_buffer();
|
||||
end = begin+wcslen(begin);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -25,14 +25,23 @@ Functions used for implementing the complete builtin.
|
||||
#include "reader.h"
|
||||
#include "translate.h"
|
||||
|
||||
/**
|
||||
Internal storage for the builtin_get_temporary_buffer() function.
|
||||
*/
|
||||
const static wchar_t *temporary_buffer;
|
||||
|
||||
/*
|
||||
builtin_complete_* are a set of rather silly looping functions that
|
||||
make sure that all the proper combinations of complete_add or
|
||||
complete_remove get called.
|
||||
complete_remove get called. This is needed since complete allows you
|
||||
to specify multiple switches on a single commandline, like 'complete
|
||||
-s a -s b -s c', but the complete_add function only accepts one
|
||||
short switch and one long switch.
|
||||
*/
|
||||
|
||||
/**
|
||||
Silly function
|
||||
*/
|
||||
static void builtin_complete_add2( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
const wchar_t *short_opt,
|
||||
@@ -104,6 +113,9 @@ static void builtin_complete_add2( const wchar_t *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Silly function
|
||||
*/
|
||||
static void builtin_complete_add( array_list_t *cmd,
|
||||
array_list_t *path,
|
||||
const wchar_t *short_opt,
|
||||
@@ -147,6 +159,9 @@ static void builtin_complete_add( array_list_t *cmd,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Silly function
|
||||
*/
|
||||
static void builtin_complete_remove3( wchar_t *cmd,
|
||||
int cmd_type,
|
||||
wchar_t short_opt,
|
||||
@@ -163,6 +178,9 @@ static void builtin_complete_remove3( wchar_t *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Silly function
|
||||
*/
|
||||
static void builtin_complete_remove2( wchar_t *cmd,
|
||||
int cmd_type,
|
||||
const wchar_t *short_opt,
|
||||
@@ -211,6 +229,9 @@ static void builtin_complete_remove2( wchar_t *cmd,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Silly function
|
||||
*/
|
||||
static void builtin_complete_remove( array_list_t *cmd,
|
||||
array_list_t *path,
|
||||
const wchar_t *short_opt,
|
||||
@@ -246,7 +267,12 @@ const wchar_t *builtin_complete_get_temporary_buffer()
|
||||
return temporary_buffer;
|
||||
}
|
||||
|
||||
int builtin_complete( wchar_t **argv )
|
||||
/**
|
||||
The complete builtin. Used for specifying programmable
|
||||
tab-completions. Calls the functions in complete.c for any heavy
|
||||
lifting. Defined in builtin_complete.c
|
||||
*/
|
||||
static int builtin_complete( wchar_t **argv )
|
||||
{
|
||||
int res=0;
|
||||
int argc=0;
|
||||
@@ -341,6 +367,10 @@ int builtin_complete( wchar_t **argv )
|
||||
L"do-complete", required_argument, 0, 'C'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
@@ -351,7 +381,7 @@ int builtin_complete( wchar_t **argv )
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"a:c:p:s:l:o:d:frxeun:C:",
|
||||
L"a:c:p:s:l:o:d:frxeun:C::h",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
@@ -369,7 +399,7 @@ int builtin_complete( wchar_t **argv )
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
|
||||
res = 1;
|
||||
@@ -388,12 +418,20 @@ int builtin_complete( wchar_t **argv )
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
al_push( &cmd, unescape( woptarg, 1));
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
al_push( &cmd, unescape( woptarg, 1) );
|
||||
{
|
||||
wchar_t *a = unescape( woptarg, 1);
|
||||
if( a )
|
||||
{
|
||||
al_push( (opt=='p'?&path:&cmd), a );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_printf( sb_err, L"%ls: Invalid token '%ls'\n", argv[0], woptarg );
|
||||
res = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd':
|
||||
desc = woptarg;
|
||||
@@ -431,10 +469,14 @@ int builtin_complete( wchar_t **argv )
|
||||
do_complete = woptarg?woptarg:reader_get_buffer();
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
case '?':
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
res = 1;
|
||||
break;
|
||||
@@ -443,6 +485,42 @@ int builtin_complete( wchar_t **argv )
|
||||
|
||||
}
|
||||
|
||||
if( !res )
|
||||
{
|
||||
if( condition && wcslen( condition ) )
|
||||
{
|
||||
if( parser_test( condition, 0, 0 ) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
L"%ls: Condition '%ls' contained a syntax error\n",
|
||||
argv[0],
|
||||
condition );
|
||||
|
||||
parser_test( condition, sb_err, argv[0] );
|
||||
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !res )
|
||||
{
|
||||
if( comp && wcslen( comp ) )
|
||||
{
|
||||
if( parser_test_args( comp, 0, 0 ) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
L"%ls: Completion '%ls' contained a syntax error\n",
|
||||
argv[0],
|
||||
comp );
|
||||
|
||||
parser_test_args( comp, sb_err, argv[0] );
|
||||
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !res )
|
||||
{
|
||||
if( do_complete )
|
||||
@@ -470,7 +548,7 @@ int builtin_complete( wchar_t **argv )
|
||||
sb_printf( sb_out, L"%ls\n", next );
|
||||
}
|
||||
|
||||
al_foreach( &comp, (void (*)(const void *))&free );
|
||||
al_foreach( &comp, &free );
|
||||
al_destroy( &comp );
|
||||
recursion_level--;
|
||||
}
|
||||
@@ -485,7 +563,7 @@ int builtin_complete( wchar_t **argv )
|
||||
argv[0] );
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
res = 1;
|
||||
}
|
||||
@@ -522,8 +600,8 @@ int builtin_complete( wchar_t **argv )
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &cmd, (void (*)(const void *))&free );
|
||||
al_foreach( &path, (void (*)(const void *))&free );
|
||||
al_foreach( &cmd, &free );
|
||||
al_foreach( &path, &free );
|
||||
|
||||
al_destroy( &cmd );
|
||||
al_destroy( &path );
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/** \file builtin_help.h
|
||||
|
||||
Prototypes for functions for printing usage information of builtin commands. The
|
||||
corresponding .c file is automatically generated by combining the
|
||||
builtin_help.hdr file with doxygen output.
|
||||
*/
|
||||
|
||||
#ifndef FISH_BUILTIN_HELP_H
|
||||
#define FISH_BUILTIN_HELP_H
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
/**
|
||||
Return the help text for the specified builtin command. Use
|
||||
non-wide characters since wide characters have some issues with
|
||||
string formating escape sequences sometimes.
|
||||
|
||||
\param cmd The command for which to obtain help text
|
||||
*/
|
||||
char *builtin_help_get( wchar_t *cmd );
|
||||
|
||||
/**
|
||||
Initialize builtin help data
|
||||
*/
|
||||
void builtin_help_init();
|
||||
|
||||
/**
|
||||
Destory builtin help data
|
||||
*/
|
||||
void builtin_help_destroy();
|
||||
|
||||
#endif
|
||||
@@ -14,24 +14,31 @@
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
#include "builtin_help.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Hashtable storing the help text
|
||||
*/
|
||||
static hash_table_t tbl;
|
||||
|
||||
char *builtin_help_get( wchar_t *cmd )
|
||||
static void builtin_help_init();
|
||||
|
||||
char *builtin_help_get( const wchar_t *cmd )
|
||||
{
|
||||
builtin_help_init();
|
||||
|
||||
return (char *)hash_get( &tbl, (void *)cmd );
|
||||
}
|
||||
|
||||
void builtin_help_destroy()
|
||||
{
|
||||
hash_destroy( &tbl );
|
||||
}
|
||||
|
||||
|
||||
void builtin_help_init()
|
||||
/**
|
||||
Initialize help hash table. Don't invoke it manually,
|
||||
it is called by builtin_help_get automatically.
|
||||
*/
|
||||
static void builtin_help_init()
|
||||
{
|
||||
static int is_help_init = 0;
|
||||
if( is_help_init )
|
||||
return;
|
||||
is_help_init=1;
|
||||
halloc_register_function( global_context, (void (*)(void *))&hash_destroy, &tbl );
|
||||
hash_init( &tbl, &hash_wcs_func, &hash_wcs_cmp );
|
||||
|
||||
352
builtin_jobs.c
Normal file
352
builtin_jobs.c
Normal file
@@ -0,0 +1,352 @@
|
||||
/** \file builtin_jobs.c
|
||||
Functions for executing the jobs builtin.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "fallback.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "wutil.h"
|
||||
#include "builtin.h"
|
||||
#include "proc.h"
|
||||
#include "parser.h"
|
||||
#include "common.h"
|
||||
#include "wgetopt.h"
|
||||
#include "translate.h"
|
||||
|
||||
/**
|
||||
Print modes for the jobs builtin
|
||||
*/
|
||||
enum
|
||||
{
|
||||
JOBS_DEFAULT, /**< Print lots of general info */
|
||||
JOBS_PRINT_PID, /**< Print pid of each process in job */
|
||||
JOBS_PRINT_COMMAND, /**< Print command name of each process in job */
|
||||
JOBS_PRINT_GROUP, /**< Print group id of job */
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE__PROC_SELF_STAT
|
||||
/**
|
||||
Calculates the cpu usage (in percent) of the specified job.
|
||||
*/
|
||||
static int cpu_use( job_t *j )
|
||||
{
|
||||
double u=0;
|
||||
process_t *p;
|
||||
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
struct timeval t;
|
||||
int jiffies;
|
||||
gettimeofday( &t, 0 );
|
||||
jiffies = proc_get_jiffies( p );
|
||||
|
||||
double t1 = 1000000.0*p->last_time.tv_sec+p->last_time.tv_usec;
|
||||
double t2 = 1000000.0*t.tv_sec+t.tv_usec;
|
||||
|
||||
/* fwprintf( stderr, L"t1 %f t2 %f p1 %d p2 %d\n",
|
||||
t1, t2, jiffies, p->last_jiffies );
|
||||
*/
|
||||
|
||||
u += ((double)(jiffies-p->last_jiffies))/(t2-t1);
|
||||
}
|
||||
return u*1000000;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Print information about the specified job
|
||||
*/
|
||||
static void builtin_jobs_print( job_t *j, int mode, int header )
|
||||
{
|
||||
process_t *p;
|
||||
switch( mode )
|
||||
{
|
||||
case JOBS_DEFAULT:
|
||||
{
|
||||
|
||||
if( header )
|
||||
{
|
||||
/*
|
||||
Print table header before first job
|
||||
*/
|
||||
sb_append( sb_out, _( L"Job\tGroup\t" ));
|
||||
#ifdef HAVE__PROC_SELF_STAT
|
||||
sb_append( sb_out, _( L"CPU\t" ) );
|
||||
#endif
|
||||
sb_append( sb_out, _( L"State\tCommand\n" ) );
|
||||
}
|
||||
|
||||
sb_printf( sb_out, L"%d\t%d\t", j->job_id, j->pgid );
|
||||
|
||||
#ifdef HAVE__PROC_SELF_STAT
|
||||
sb_printf( sb_out, L"%d%%\t", cpu_use(j) );
|
||||
#endif
|
||||
sb_append2( sb_out,
|
||||
job_is_stopped(j)?_(L"stopped"):_(L"running"),
|
||||
L"\t",
|
||||
j->command,
|
||||
L"\n",
|
||||
(void *)0 );
|
||||
break;
|
||||
}
|
||||
|
||||
case JOBS_PRINT_GROUP:
|
||||
{
|
||||
if( header )
|
||||
{
|
||||
/*
|
||||
Print table header before first job
|
||||
*/
|
||||
sb_append( sb_out, _( L"Group\n" ));
|
||||
}
|
||||
sb_printf( sb_out, L"%d\n", j->pgid );
|
||||
break;
|
||||
}
|
||||
|
||||
case JOBS_PRINT_PID:
|
||||
{
|
||||
if( header )
|
||||
{
|
||||
/*
|
||||
Print table header before first job
|
||||
*/
|
||||
sb_append( sb_out, _( L"Procces\n" ));
|
||||
}
|
||||
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
sb_printf( sb_out, L"%d\n", p->pid );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JOBS_PRINT_COMMAND:
|
||||
{
|
||||
if( header )
|
||||
{
|
||||
/*
|
||||
Print table header before first job
|
||||
*/
|
||||
sb_append( sb_out, _( L"Command\n" ));
|
||||
}
|
||||
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
sb_printf( sb_out, L"%ls\n", p->argv[0] );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
The jobs builtin. Used fopr printing running jobs. Defined in builtin_jobs.c.
|
||||
*/
|
||||
static int builtin_jobs( wchar_t **argv )
|
||||
{
|
||||
int argc=0;
|
||||
int found=0;
|
||||
int mode=JOBS_DEFAULT;
|
||||
int print_last = 0;
|
||||
job_t *j;
|
||||
|
||||
argc = builtin_count_args( argv );
|
||||
woptind=0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
const static struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
L"pid", no_argument, 0, 'p'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"command", no_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"group", no_argument, 0, 'g'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"last", no_argument, 0, 'l'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"pclgh",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
if(long_options[opt_index].flag != 0)
|
||||
break;
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_UNKNOWN,
|
||||
argv[0],
|
||||
long_options[opt_index].name );
|
||||
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
case 'p':
|
||||
mode=JOBS_PRINT_PID;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
mode=JOBS_PRINT_COMMAND;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
mode=JOBS_PRINT_GROUP;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
{
|
||||
print_last = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
case '?':
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Do not babble if not interactive
|
||||
*/
|
||||
if( builtin_out_redirect )
|
||||
{
|
||||
found=1;
|
||||
}
|
||||
|
||||
if( print_last )
|
||||
{
|
||||
/*
|
||||
Ignore unconstructed jobs, i.e. ourself.
|
||||
*/
|
||||
for( j=first_job; j; j=j->next )
|
||||
{
|
||||
if( j->constructed && !job_is_completed(j) )
|
||||
{
|
||||
builtin_jobs_print( j, mode, !found );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( woptind < argc )
|
||||
{
|
||||
int i;
|
||||
|
||||
found = 1;
|
||||
|
||||
for( i=woptind; i<argc; i++ )
|
||||
{
|
||||
long pid;
|
||||
wchar_t *end;
|
||||
errno=0;
|
||||
pid=wcstol( argv[i], &end, 10 );
|
||||
if( errno || *end )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: '%ls' is not a job\n" ),
|
||||
argv[0],
|
||||
argv[i] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
j = job_get_from_pid( pid );
|
||||
|
||||
if( j && !job_is_completed( j ) )
|
||||
{
|
||||
builtin_jobs_print( j, mode, !found );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: No suitable job: %d\n" ),
|
||||
argv[0],
|
||||
pid );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( j= first_job; j; j=j->next )
|
||||
{
|
||||
/*
|
||||
Ignore unconstructed jobs, i.e. ourself.
|
||||
*/
|
||||
if( j->constructed && !job_is_completed(j) )
|
||||
{
|
||||
builtin_jobs_print( j, mode, !found );
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !found )
|
||||
{
|
||||
sb_printf( sb_out,
|
||||
_( L"%ls: There are no jobs\n" ),
|
||||
argv[0] );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
713
builtin_set.c
713
builtin_set.c
@@ -26,46 +26,173 @@ Functions used for implementing the set builtin.
|
||||
#include "parser.h"
|
||||
#include "translate.h"
|
||||
|
||||
/**
|
||||
Extract the name from a destination argument of the form name[index1 index2...]
|
||||
/**
|
||||
Error message for invalid path operations
|
||||
*/
|
||||
static int parse_fill_name( string_buffer_t *name,
|
||||
const wchar_t *src)
|
||||
#define BUILTIN_SET_PATH_ERROR L"%ls: Could not add component %ls to %ls.\n"
|
||||
|
||||
/**
|
||||
Hint for invalid path operation with a colon
|
||||
*/
|
||||
#define BUILTIN_SET_PATH_HINT L"%ls: Did you mean 'set %ls $%ls %ls'?\n"
|
||||
|
||||
/**
|
||||
Error for mismatch between index count and elements
|
||||
*/
|
||||
#define BUILTIN_SET_ARG_COUNT L"%ls: The number of variable indexes does not match the number of values\n"
|
||||
|
||||
/**
|
||||
Test if the specified variable should be subject to path validation
|
||||
*/
|
||||
static int is_path_variable( const wchar_t *env )
|
||||
{
|
||||
|
||||
if (src == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (iswalnum(*src) || *src == L'_')
|
||||
{
|
||||
sb_append_char(name, *src++);
|
||||
}
|
||||
|
||||
if (*src != L'[' && *src != L'\0')
|
||||
{
|
||||
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, L"set", *src );
|
||||
sb_append2(sb_err, parser_current_line(), L"\n", (void *)0 );
|
||||
// builtin_print_help( L"set", sb_err );
|
||||
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return contains_str( env,
|
||||
L"PATH",
|
||||
L"CDPATH",
|
||||
(void *)0 );
|
||||
}
|
||||
|
||||
/**
|
||||
Call env_set. If this is a path variable, e.g. PATH, validate the
|
||||
elements. On error, print a description of the problem to stderr.
|
||||
*/
|
||||
static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
|
||||
{
|
||||
string_buffer_t sb;
|
||||
int i;
|
||||
int retcode = 0;
|
||||
wchar_t *val_str=0;
|
||||
|
||||
if( is_path_variable( key ) )
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
for( i=0; i<al_get_count( val ); i++ )
|
||||
{
|
||||
int show_perror = 0;
|
||||
int show_hint = 0;
|
||||
|
||||
struct stat buff;
|
||||
wchar_t *dir = (wchar_t *)al_get( val, i );
|
||||
|
||||
if( wstat( dir, &buff ) )
|
||||
{
|
||||
error = 1;
|
||||
show_perror = 1;
|
||||
}
|
||||
|
||||
if( !( S_IFDIR & buff.st_mode ) )
|
||||
{
|
||||
error = 1;
|
||||
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
wchar_t *colon;
|
||||
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_ERROR),
|
||||
L"set",
|
||||
dir,
|
||||
key );
|
||||
|
||||
colon = wcschr( dir, L':' );
|
||||
|
||||
if( colon && *(colon+1) )
|
||||
{
|
||||
show_hint = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( show_perror )
|
||||
{
|
||||
builtin_wperror( L"set" );
|
||||
}
|
||||
|
||||
if( show_hint )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_HINT),
|
||||
L"set",
|
||||
key,
|
||||
key,
|
||||
wcschr( dir, L':' )+1);
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sb_init( &sb );
|
||||
|
||||
if( al_get_count( val ) )
|
||||
{
|
||||
for( i=0; i<al_get_count( val ); i++ )
|
||||
{
|
||||
sb_append( &sb, (wchar_t *)al_get( val, i ) );
|
||||
if( i<al_get_count( val )-1 )
|
||||
{
|
||||
sb_append( &sb, ARRAY_SEP_STR );
|
||||
}
|
||||
}
|
||||
val_str = (wchar_t *)sb.buff;
|
||||
|
||||
}
|
||||
|
||||
switch( env_set( key, val_str, scope | ENV_USER ) )
|
||||
{
|
||||
case ENV_PERM:
|
||||
{
|
||||
sb_printf( sb_err, _(L"%ls: Tried to change the read-only variable '%ls'\n"), L"set", key );
|
||||
retcode=1;
|
||||
break;
|
||||
}
|
||||
|
||||
case ENV_INVALID:
|
||||
{
|
||||
sb_printf( sb_err, _(L"%ls: Unknown error"), L"set" );
|
||||
retcode=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sb_destroy( &sb );
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/**
|
||||
Extract indexes from a destination argument of the form name[index1 index2...]
|
||||
*/
|
||||
static int parse_fill_indexes( array_list_t *indexes,
|
||||
const wchar_t *src)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
\param indexes the list to insert the new indexes into
|
||||
\param src the source string to parse
|
||||
\param name the name of the element. Return null if the name in \c src does not match this name
|
||||
\param var_count the number of elements in the array to parse.
|
||||
|
||||
\return the total number of indexes parsed, or -1 on error
|
||||
*/
|
||||
static int parse_index( array_list_t *indexes,
|
||||
const wchar_t *src,
|
||||
const wchar_t *name,
|
||||
int var_count )
|
||||
{
|
||||
int len;
|
||||
|
||||
int count = 0;
|
||||
const wchar_t *src_orig = src;
|
||||
|
||||
if (src == 0)
|
||||
{
|
||||
return 0;
|
||||
@@ -76,16 +203,27 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
src++;
|
||||
}
|
||||
|
||||
if (*src == L'\0')
|
||||
if (*src != L'[')
|
||||
{
|
||||
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), L"set" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*src++ != L'[')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
len = src-src_orig;
|
||||
|
||||
if( (wcsncmp( src_orig, name, len )!=0) || (wcslen(name) != (len)) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Multiple variable names specified in single call (%ls and %.*ls)\n"),
|
||||
L"set",
|
||||
name,
|
||||
len,
|
||||
src_orig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
src++;
|
||||
|
||||
while (iswspace(*src))
|
||||
{
|
||||
src++;
|
||||
@@ -95,13 +233,20 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
{
|
||||
wchar_t *end;
|
||||
long l_ind = wcstol(src, &end, 10);
|
||||
int *ind;
|
||||
|
||||
if (end == src)
|
||||
{
|
||||
sb_printf(sb_err, _(L"%ls: Invalid index starting at '%ls'\n"), L"set", src);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int *ind = (int *) calloc(1, sizeof(int));
|
||||
if( l_ind < 0 )
|
||||
{
|
||||
l_ind = var_count+l_ind+1;
|
||||
}
|
||||
|
||||
ind = (int *) calloc(1, sizeof(int));
|
||||
*ind = (int) l_ind;
|
||||
al_push(indexes, ind);
|
||||
src = end;
|
||||
@@ -114,7 +259,12 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
|
||||
|
||||
/**
|
||||
Update a list by writing the specified values at the specified indexes
|
||||
Update a list \c list by writing copies (using wcsdup) of the
|
||||
values specified by \c values to the indexes specified by \c
|
||||
indexes. The previous entries at the specidied position will be
|
||||
free'd.
|
||||
|
||||
\return 0 if the operation was successfull, non-zero otherwise
|
||||
*/
|
||||
static int update_values( array_list_t *list,
|
||||
array_list_t *indexes,
|
||||
@@ -122,20 +272,21 @@ static int update_values( array_list_t *list,
|
||||
{
|
||||
int i;
|
||||
|
||||
//fwprintf(stderr, L"Scan complete\n");
|
||||
/* Replace values where needed */
|
||||
for( i = 0; i < al_get_count(indexes); i++ )
|
||||
{
|
||||
int ind = *(int *) al_get(indexes, i) - 1;
|
||||
void *new = (void *) al_get(values, i);
|
||||
if (al_get(list, ind) != 0)
|
||||
if( ind <= 0 )
|
||||
{
|
||||
free((void *) al_get(list, ind));
|
||||
return 1;
|
||||
}
|
||||
|
||||
free((void *) al_get(list, ind));
|
||||
al_set(list, ind, new != 0 ? wcsdup(new) : wcsdup(L""));
|
||||
}
|
||||
|
||||
return al_get_count(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +302,7 @@ static int al_contains_int( array_list_t *list,
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
{
|
||||
int *current = (int *) al_get(list, i);
|
||||
if (current != 0 && *current == val)
|
||||
if( current != 0 && *current == val )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -164,13 +315,11 @@ static int al_contains_int( array_list_t *list,
|
||||
/**
|
||||
Erase from a list values at specified indexes
|
||||
*/
|
||||
static int erase_values(array_list_t *list, array_list_t *indexes)
|
||||
static void erase_values(array_list_t *list, array_list_t *indexes)
|
||||
{
|
||||
int i;
|
||||
array_list_t result;
|
||||
|
||||
//fwprintf(stderr, L"Starting with %d\n", al_get_count(list));
|
||||
|
||||
al_init(&result);
|
||||
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
@@ -188,33 +337,6 @@ static int erase_values(array_list_t *list, array_list_t *indexes)
|
||||
al_truncate(list,0);
|
||||
al_push_all( list, &result );
|
||||
al_destroy(&result);
|
||||
|
||||
//fwprintf(stderr, L"Remaining: %d\n", al_get_count(&result));
|
||||
|
||||
return al_get_count(list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Fill a string buffer with values from a list, using ARRAY_SEP_STR to separate them
|
||||
*/
|
||||
static int fill_buffer_from_list(string_buffer_t *sb, array_list_t *list)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
{
|
||||
wchar_t *v = (wchar_t *) al_get(list, i);
|
||||
if (v != 0)
|
||||
{
|
||||
// fwprintf(stderr, L".\n");
|
||||
// fwprintf(stderr, L"Collecting %ls from %d\n", v, i);
|
||||
sb_append(sb, v);
|
||||
}
|
||||
if (i < al_get_count(list) - 1)
|
||||
sb_append(sb, ARRAY_SEP_STR);
|
||||
}
|
||||
return al_get_count(list);
|
||||
}
|
||||
|
||||
|
||||
@@ -254,46 +376,64 @@ static void print_variables(int include_values, int esc, int scope)
|
||||
al_destroy(&names);
|
||||
}
|
||||
|
||||
/**
|
||||
The set builtin. Creates, updates and erases environment variables and environemnt variable arrays.
|
||||
*/
|
||||
|
||||
int builtin_set( wchar_t **argv )
|
||||
|
||||
/**
|
||||
The set builtin. Creates, updates and erases environment variables
|
||||
and environemnt variable arrays.
|
||||
*/
|
||||
static int builtin_set( wchar_t **argv )
|
||||
{
|
||||
|
||||
/**
|
||||
Variables used for parsing the argument list
|
||||
*/
|
||||
const static struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
L"export", no_argument, 0, 'x'
|
||||
},
|
||||
}
|
||||
,
|
||||
{
|
||||
L"global", no_argument, 0, 'g'
|
||||
},
|
||||
}
|
||||
,
|
||||
{
|
||||
L"local", no_argument, 0, 'l'
|
||||
},
|
||||
}
|
||||
,
|
||||
{
|
||||
L"erase", no_argument, 0, 'e'
|
||||
},
|
||||
}
|
||||
,
|
||||
{
|
||||
L"names", no_argument, 0, 'n'
|
||||
} ,
|
||||
}
|
||||
,
|
||||
{
|
||||
L"unexport", no_argument, 0, 'u'
|
||||
} ,
|
||||
}
|
||||
,
|
||||
{
|
||||
L"universal", no_argument, 0, 'U'
|
||||
} ,
|
||||
}
|
||||
,
|
||||
{
|
||||
L"query", no_argument, 0, 'q'
|
||||
} ,
|
||||
}
|
||||
,
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
wchar_t short_options[] = L"+xglenuUq";
|
||||
const wchar_t *short_options = L"+xglenuUqh";
|
||||
|
||||
int argc = builtin_count_args(argv);
|
||||
|
||||
@@ -309,14 +449,12 @@ int builtin_set( wchar_t **argv )
|
||||
Variables used for performing the actual work
|
||||
*/
|
||||
wchar_t *dest = 0;
|
||||
array_list_t values;
|
||||
string_buffer_t name_sb;
|
||||
int retcode=0;
|
||||
wchar_t *name;
|
||||
array_list_t indexes;
|
||||
int retval;
|
||||
|
||||
|
||||
int scope;
|
||||
int slice=0;
|
||||
int i;
|
||||
|
||||
|
||||
/* Parse options to obtain the requested operation and the modifiers */
|
||||
woptind = 0;
|
||||
while (1)
|
||||
@@ -332,37 +470,61 @@ int builtin_set( wchar_t **argv )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
erase = 1;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
list = 1;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
export = 1;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
local = 1;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
global = 1;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
unexport = 1;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
universal = 1;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
query = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
case '?':
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Ok, all arguments have been parsed, let's validate them
|
||||
*/
|
||||
|
||||
/*
|
||||
If we are checking the existance of a variable (-q) we can not
|
||||
also specify scope
|
||||
*/
|
||||
|
||||
if( query && (erase || list || global || local || universal || export || unexport ) )
|
||||
{
|
||||
sb_printf(sb_err,
|
||||
@@ -375,7 +537,7 @@ int builtin_set( wchar_t **argv )
|
||||
}
|
||||
|
||||
|
||||
/* Check operation and modifiers sanity */
|
||||
/* We can't both list and erase varaibles */
|
||||
if( erase && list )
|
||||
{
|
||||
sb_printf(sb_err,
|
||||
@@ -387,6 +549,9 @@ int builtin_set( wchar_t **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Variables can only have one scope
|
||||
*/
|
||||
if( local + global + universal > 1 )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
@@ -397,6 +562,9 @@ int builtin_set( wchar_t **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Variables can only have one export status
|
||||
*/
|
||||
if( export && unexport )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
@@ -407,205 +575,228 @@ int builtin_set( wchar_t **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate the scope value for variable assignement
|
||||
*/
|
||||
scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (export ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
|
||||
|
||||
if( query )
|
||||
{
|
||||
/*
|
||||
Query mode. Return number of specified variables that do not exist.
|
||||
Query mode. Return the number of variables that do not exist
|
||||
out of the specified variables.
|
||||
*/
|
||||
int i;
|
||||
for( i=woptind; i<argc; i++ )
|
||||
{
|
||||
if( !env_exist( argv[i] ) )
|
||||
if( !env_exist( argv[i], scope ) )
|
||||
{
|
||||
retcode++;
|
||||
}
|
||||
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
|
||||
/* Parse destination */
|
||||
if( woptind < argc )
|
||||
if( woptind == argc )
|
||||
{
|
||||
dest = wcsdup(argv[woptind++]);
|
||||
//fwprintf(stderr, L"Dest: %ls\n", dest);
|
||||
/*
|
||||
Print values of variables
|
||||
*/
|
||||
|
||||
if( !wcslen( dest ) )
|
||||
if( erase )
|
||||
{
|
||||
free( dest );
|
||||
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse values */
|
||||
// wchar_t **values = woptind < argc ? (wchar_t **) calloc(argc - woptind, sizeof(wchar_t *)) : 0;
|
||||
|
||||
al_init(&values);
|
||||
while( woptind < argc )
|
||||
{
|
||||
al_push(&values, argv[woptind++]);
|
||||
// fwprintf(stderr, L"Val: %ls\n", argv[woptind - 1]);
|
||||
}
|
||||
|
||||
/* Extract variable name and indexes */
|
||||
|
||||
sb_init(&name_sb);
|
||||
retval = parse_fill_name(&name_sb, dest);
|
||||
|
||||
|
||||
if( retval < 0 )
|
||||
retcode=1;
|
||||
|
||||
if( !retcode )
|
||||
{
|
||||
name = (wchar_t *) name_sb.buff;
|
||||
//fwprintf(stderr, L"Name is %ls\n", name);
|
||||
|
||||
al_init(&indexes);
|
||||
retval = parse_fill_indexes(&indexes, dest);
|
||||
if (retval < 0)
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Erase needs a variable name\n%ls\n"),
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
}
|
||||
|
||||
if( !retcode )
|
||||
{
|
||||
|
||||
int i;
|
||||
int finished=0;
|
||||
|
||||
/* Do the actual work */
|
||||
int scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (export ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
|
||||
if( list )
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Maybe we should issue an error if there are any other arguments */
|
||||
print_variables(0, 0, scope);
|
||||
finished=1;
|
||||
}
|
||||
|
||||
if( (!finished ) &&
|
||||
(name == 0 || wcslen(name) == 0))
|
||||
{
|
||||
/* No arguments -- display name & value for all variables in scope */
|
||||
if( erase )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Erase needs a variable name\n%ls\n"),
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_variables( 1, 1, scope );
|
||||
}
|
||||
|
||||
finished=1;
|
||||
}
|
||||
|
||||
|
||||
if( !finished )
|
||||
{
|
||||
if( al_get_count( &values ) == 0 &&
|
||||
al_get_count( &indexes ) == 0 &&
|
||||
!erase &&
|
||||
!list )
|
||||
{
|
||||
env_set( name, 0, scope );
|
||||
finished = 1;
|
||||
}
|
||||
print_variables( 1, 1, scope );
|
||||
}
|
||||
|
||||
if( !finished )
|
||||
return retcode;
|
||||
}
|
||||
|
||||
if( list )
|
||||
{
|
||||
/* Maybe we should issue an error if there are any other arguments? */
|
||||
print_variables(0, 0, scope);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !(dest = wcsdup(argv[woptind])))
|
||||
{
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
if( wcschr( dest, L'[' ) )
|
||||
{
|
||||
slice = 1;
|
||||
*wcschr( dest, L'[' )=0;
|
||||
}
|
||||
|
||||
if( !wcslen( dest ) )
|
||||
{
|
||||
free( dest );
|
||||
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( slice && erase && (scope != ENV_USER) )
|
||||
{
|
||||
free( dest );
|
||||
sb_printf( sb_err, _(L"%ls: Can not specify scope when erasing array slice\n"), argv[0] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
set assignment can work in two modes, either using slices or
|
||||
using the whole array. We detect which mode is used here.
|
||||
*/
|
||||
|
||||
if( slice )
|
||||
{
|
||||
|
||||
/*
|
||||
Slice mode
|
||||
*/
|
||||
int idx_count, val_count;
|
||||
array_list_t values;
|
||||
array_list_t indexes;
|
||||
array_list_t result;
|
||||
|
||||
al_init(&values);
|
||||
al_init(&indexes);
|
||||
al_init(&result);
|
||||
|
||||
tokenize_variable_array( env_get(dest), &result );
|
||||
|
||||
for( ; woptind<argc; woptind++ )
|
||||
{
|
||||
if( !parse_index( &indexes, argv[woptind], dest, al_get_count( &result ) ) )
|
||||
{
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
val_count = argc-woptind-1;
|
||||
idx_count = al_get_count( &indexes );
|
||||
|
||||
if( !erase )
|
||||
{
|
||||
if( val_count < idx_count )
|
||||
{
|
||||
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), argv[0] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode=1;
|
||||
break;
|
||||
}
|
||||
if( val_count == idx_count )
|
||||
{
|
||||
woptind++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !retcode )
|
||||
{
|
||||
/* There are some arguments, we have at least a variable name */
|
||||
if( erase && al_get_count(&values) != 0 )
|
||||
/*
|
||||
Slice indexes have been calculated, do the actual work
|
||||
*/
|
||||
|
||||
if( erase )
|
||||
{
|
||||
erase_values(&result, &indexes);
|
||||
my_env_set( dest, &result, scope);
|
||||
}
|
||||
else
|
||||
{
|
||||
array_list_t value;
|
||||
al_init(&value);
|
||||
|
||||
while( woptind < argc )
|
||||
{
|
||||
al_push(&value, argv[woptind++]);
|
||||
}
|
||||
|
||||
if( update_values( &result,
|
||||
&indexes,
|
||||
&value ) )
|
||||
{
|
||||
sb_printf( sb_err, L"%ls: ", argv[0] );
|
||||
sb_printf( sb_err, ARRAY_BOUNDS_ERR );
|
||||
sb_append( sb_err, L"\n" );
|
||||
}
|
||||
|
||||
my_env_set(dest,
|
||||
&result,
|
||||
scope);
|
||||
|
||||
al_destroy( &value );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &result, &free );
|
||||
al_destroy( &result );
|
||||
|
||||
al_foreach( &indexes, &free );
|
||||
al_destroy(&indexes);
|
||||
al_destroy(&values);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
woptind++;
|
||||
|
||||
/*
|
||||
No slicing
|
||||
*/
|
||||
if( erase )
|
||||
{
|
||||
if( woptind != argc )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Values cannot be specfied with erase\n%ls\n"),
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
}
|
||||
retcode=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All ok, we can alter the specified variable */
|
||||
array_list_t val_l;
|
||||
al_init(&val_l);
|
||||
|
||||
void *old=0;
|
||||
|
||||
if (al_get_count(&indexes) == 0)
|
||||
{
|
||||
/* We will act upon the entire variable */
|
||||
|
||||
al_push( &val_l, wcsdup(L"") );
|
||||
old = val_l.arr;
|
||||
|
||||
/* Build indexes for all variable or all new values */
|
||||
int end_index = erase ? al_get_count(&val_l) : al_get_count(&values);
|
||||
for (i = 0; i < end_index; i++)
|
||||
{
|
||||
int *ind = (int *) calloc(1, sizeof(int));
|
||||
*ind = i + 1;
|
||||
al_push(&indexes, ind);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We will act upon some specific indexes */
|
||||
expand_variable_array( env_get(name), &val_l );
|
||||
}
|
||||
|
||||
string_buffer_t result_sb;
|
||||
sb_init(&result_sb);
|
||||
if (erase)
|
||||
{
|
||||
int rem = erase_values(&val_l, &indexes);
|
||||
if (rem == 0)
|
||||
{
|
||||
env_remove(name, ENV_USER);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_buffer_from_list(&result_sb, &val_l);
|
||||
env_set(name, (wchar_t *) result_sb.buff, scope);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
update_values( &val_l,
|
||||
&indexes,
|
||||
&values );
|
||||
|
||||
fill_buffer_from_list( &result_sb,
|
||||
&val_l );
|
||||
|
||||
env_set(name,
|
||||
(wchar_t *) result_sb.buff,
|
||||
scope);
|
||||
}
|
||||
|
||||
al_foreach( &val_l, (void (*)(const void *))&free );
|
||||
al_destroy(&val_l);
|
||||
sb_destroy(&result_sb);
|
||||
{
|
||||
retcode = env_remove( dest, scope );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array_list_t val;
|
||||
al_init( &val );
|
||||
|
||||
for( i=woptind; i<argc; i++ )
|
||||
{
|
||||
al_push( &val, argv[i] );
|
||||
}
|
||||
|
||||
al_foreach( &indexes, (void (*)(const void *))&free );
|
||||
al_destroy(&indexes);
|
||||
retcode = my_env_set( dest, &val, scope );
|
||||
|
||||
al_destroy( &val );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Common cleanup */
|
||||
//fwprintf(stderr, L"Cleanup\n");
|
||||
free(dest);
|
||||
sb_destroy(&name_sb);
|
||||
al_destroy( &values );
|
||||
free( dest );
|
||||
|
||||
return retcode;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -63,13 +63,13 @@ const static struct resource_t resource_arr[] =
|
||||
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
|
||||
}
|
||||
,
|
||||
#if HAVE_RLIMIT_MEMLOCK
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
{
|
||||
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#if HAVE_RLIMIT_RSS
|
||||
#ifdef RLIMIT_RSS
|
||||
{
|
||||
RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
|
||||
}
|
||||
@@ -87,13 +87,13 @@ const static struct resource_t resource_arr[] =
|
||||
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
|
||||
}
|
||||
,
|
||||
#if HAVE_RLIMIT_NPROC
|
||||
#ifdef RLIMIT_NPROC
|
||||
{
|
||||
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#if HAVE_RLIMIT_AS
|
||||
#ifdef RLIMIT_AS
|
||||
{
|
||||
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
|
||||
}
|
||||
@@ -257,7 +257,11 @@ static int set_all( int hard, int soft, rlim_t value )
|
||||
return res;
|
||||
}
|
||||
|
||||
int builtin_ulimit( wchar_t ** argv )
|
||||
/**
|
||||
The ulimit builtin, used for setting resource limits. Defined in
|
||||
builtin_ulimit.c.
|
||||
*/
|
||||
static int builtin_ulimit( wchar_t ** argv )
|
||||
{
|
||||
int hard=0;
|
||||
int soft=0;
|
||||
@@ -326,6 +330,10 @@ int builtin_ulimit( wchar_t ** argv )
|
||||
L"virtual-memory-size", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
@@ -337,7 +345,7 @@ int builtin_ulimit( wchar_t ** argv )
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"aHScdflmnptuv",
|
||||
L"aHScdflmnptuvh",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
@@ -379,13 +387,13 @@ int builtin_ulimit( wchar_t ** argv )
|
||||
case L'f':
|
||||
what=RLIMIT_FSIZE;
|
||||
break;
|
||||
#if HAVE_RLIMIT_MEMLOCK
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
case L'l':
|
||||
what=RLIMIT_MEMLOCK;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAVE_RLIMIT_RSS
|
||||
#ifdef RLIMIT_RSS
|
||||
case L'm':
|
||||
what=RLIMIT_RSS;
|
||||
break;
|
||||
@@ -403,18 +411,22 @@ int builtin_ulimit( wchar_t ** argv )
|
||||
what=RLIMIT_CPU;
|
||||
break;
|
||||
|
||||
#if HAVE_RLIMIT_NPROC
|
||||
#ifdef RLIMIT_NPROC
|
||||
case L'u':
|
||||
what=RLIMIT_NPROC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAVE_RLIMIT_AS
|
||||
#ifdef RLIMIT_AS
|
||||
case L'v':
|
||||
what=RLIMIT_AS;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case L'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
case L'?':
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
|
||||
455
common.c
455
common.c
@@ -61,10 +61,10 @@ parts of fish.
|
||||
#include "wildcard.h"
|
||||
#include "parser.h"
|
||||
|
||||
/**
|
||||
The maximum number of minor errors to report. Further errors will be omitted.
|
||||
*/
|
||||
#define ERROR_MAX_COUNT 1
|
||||
#include "util.c"
|
||||
#include "halloc.c"
|
||||
#include "halloc_util.c"
|
||||
#include "fallback.c"
|
||||
|
||||
/**
|
||||
The number of milliseconds to wait between polls when attempting to acquire
|
||||
@@ -74,8 +74,6 @@ parts of fish.
|
||||
|
||||
struct termios shell_modes;
|
||||
|
||||
int error_max=1;
|
||||
|
||||
wchar_t ellipsis_char;
|
||||
|
||||
char *profile=0;
|
||||
@@ -94,27 +92,13 @@ static struct winsize termsize;
|
||||
*/
|
||||
static string_buffer_t *setlocale_buff=0;
|
||||
|
||||
void common_destroy()
|
||||
{
|
||||
|
||||
if( setlocale_buff )
|
||||
{
|
||||
sb_destroy( setlocale_buff );
|
||||
free( setlocale_buff );
|
||||
}
|
||||
}
|
||||
|
||||
void common_init()
|
||||
{
|
||||
}
|
||||
|
||||
wchar_t **list_to_char_arr( array_list_t *l )
|
||||
{
|
||||
wchar_t ** res = malloc( sizeof(wchar_t *)*(al_get_count( l )+1) );
|
||||
int i;
|
||||
if( res == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
for( i=0; i<al_get_count( l ); i++ )
|
||||
{
|
||||
@@ -131,12 +115,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
|
||||
|
||||
wchar_t *buff = *b;
|
||||
|
||||
/*
|
||||
This is a kludge: We block SIGCHLD while reading, since I can't
|
||||
get getwc to perform reliably when signals are flying. Even when
|
||||
watching for EINTR errors, bytes are lost.
|
||||
*/
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
/* Reallocate the buffer if necessary */
|
||||
@@ -146,7 +124,7 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
|
||||
buff = realloc( buff, sizeof(wchar_t)*new_len );
|
||||
if( buff == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -218,7 +196,7 @@ wchar_t *str2wcs( const char *in )
|
||||
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
return str2wcs_internal( in, out );
|
||||
@@ -230,8 +208,13 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out )
|
||||
int in_pos=0;
|
||||
int out_pos = 0;
|
||||
mbstate_t state;
|
||||
size_t len = strlen(in);
|
||||
|
||||
size_t len;
|
||||
|
||||
CHECK( in, 0 );
|
||||
CHECK( out, 0 );
|
||||
|
||||
len = strlen(in);
|
||||
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
while( in[in_pos] )
|
||||
@@ -242,12 +225,12 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out )
|
||||
{
|
||||
case (size_t)(-2):
|
||||
case (size_t)(-1):
|
||||
{
|
||||
out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
|
||||
in_pos++;
|
||||
memset( &state, 0, sizeof(state) );
|
||||
break;
|
||||
}
|
||||
{
|
||||
out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
|
||||
in_pos++;
|
||||
memset( &state, 0, sizeof(state) );
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
{
|
||||
@@ -275,7 +258,7 @@ char *wcs2str( const wchar_t *in )
|
||||
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
return wcs2str_internal( in, out );
|
||||
@@ -287,6 +270,10 @@ char *wcs2str_internal( const wchar_t *in, char *out )
|
||||
int in_pos=0;
|
||||
int out_pos = 0;
|
||||
mbstate_t state;
|
||||
|
||||
CHECK( in, 0 );
|
||||
CHECK( out, 0 );
|
||||
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
while( in[in_pos] )
|
||||
@@ -327,7 +314,7 @@ char **wcsv2strv( const wchar_t **in )
|
||||
char **res = malloc( sizeof( char *)*(count+1));
|
||||
if( res == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
for( i=0; i<count; i++ )
|
||||
@@ -341,7 +328,7 @@ char **wcsv2strv( const wchar_t **in )
|
||||
|
||||
wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b )
|
||||
{
|
||||
return wcsdupcat2( a, b, 0 );
|
||||
return wcsdupcat2( a, b, (void *)0 );
|
||||
}
|
||||
|
||||
wchar_t *wcsdupcat2( const wchar_t *a, ... )
|
||||
@@ -362,7 +349,7 @@ wchar_t *wcsdupcat2( const wchar_t *a, ... )
|
||||
wchar_t *res = malloc( sizeof(wchar_t)*(len +1 ));
|
||||
if( res == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
wcscpy( res, a );
|
||||
@@ -388,7 +375,7 @@ wchar_t **strv2wcsv( const char **in )
|
||||
wchar_t **res = malloc( sizeof( wchar_t *)*(count+1));
|
||||
if( res == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
for( i=0; i<count; i++ )
|
||||
@@ -400,119 +387,22 @@ wchar_t **strv2wcsv( const char **in )
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size_t
|
||||
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
{
|
||||
|
||||
register wchar_t *d = dst;
|
||||
register const wchar_t *s = src;
|
||||
register size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + wcslen(s));
|
||||
|
||||
while (*s != '\0')
|
||||
{
|
||||
if (n != 1)
|
||||
{
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src));
|
||||
/* count does not include NUL */
|
||||
}
|
||||
|
||||
/*$OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size_t
|
||||
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
{
|
||||
register wchar_t *d = dst;
|
||||
register const wchar_t *s = src;
|
||||
register size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((*d++ = *s++) == 0)
|
||||
break;
|
||||
}
|
||||
while (--n != 0);
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0)
|
||||
{
|
||||
if (siz != 0)
|
||||
*d = '\0';
|
||||
/* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
return(s - src - 1);
|
||||
/* count does not include NUL */
|
||||
}
|
||||
|
||||
int wcsvarname( wchar_t *str )
|
||||
wchar_t *wcsvarname( wchar_t *str )
|
||||
{
|
||||
while( *str )
|
||||
{
|
||||
if( (!iswalnum(*str)) && (*str != L'_' ) )
|
||||
{
|
||||
return 0;
|
||||
return str;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wcsvarchr( wchar_t chr )
|
||||
{
|
||||
return ( (iswalnum(chr)) || (chr == L'_' ));
|
||||
}
|
||||
|
||||
|
||||
@@ -535,26 +425,28 @@ int my_wcswidth( const wchar_t *c )
|
||||
return res;
|
||||
}
|
||||
|
||||
const wchar_t *quote_end( const wchar_t *pos )
|
||||
wchar_t *quote_end( const wchar_t *pos )
|
||||
{
|
||||
wchar_t c = *pos;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
pos++;
|
||||
|
||||
|
||||
if( !*pos )
|
||||
return 0;
|
||||
|
||||
if( *pos == L'\\')
|
||||
{
|
||||
pos++;
|
||||
if( !*pos )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *pos == c )
|
||||
{
|
||||
return pos;
|
||||
return (wchar_t *)pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -582,8 +474,7 @@ const wchar_t *wsetlocale(int category, const wchar_t *locale)
|
||||
|
||||
if( !setlocale_buff )
|
||||
{
|
||||
setlocale_buff = malloc( sizeof(string_buffer_t) );
|
||||
sb_init( setlocale_buff);
|
||||
setlocale_buff = sb_halloc( global_context);
|
||||
}
|
||||
|
||||
sb_clear( setlocale_buff );
|
||||
@@ -597,6 +488,8 @@ int contains_str( const wchar_t *a, ... )
|
||||
wchar_t *arg;
|
||||
va_list va;
|
||||
int res = 0;
|
||||
|
||||
CHECK( a, 0 );
|
||||
|
||||
va_start( va, a );
|
||||
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
||||
@@ -625,45 +518,43 @@ int read_blocked(int fd, void *buf, size_t count)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void die_mem()
|
||||
{
|
||||
/*
|
||||
Do not translate this message, and do not send it through the
|
||||
usual channels. This increases the odds that the message gets
|
||||
through correctly, even if we are out of memory.
|
||||
*/
|
||||
fwprintf( stderr, L"Out of memory, shutting down fish.\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void debug( int level, const wchar_t *msg, ... )
|
||||
{
|
||||
va_list va;
|
||||
string_buffer_t sb;
|
||||
string_buffer_t sb2;
|
||||
|
||||
CHECK( msg, );
|
||||
|
||||
if( level > debug_level )
|
||||
return;
|
||||
|
||||
sb_init( &sb );
|
||||
va_start( va, msg );
|
||||
|
||||
sb_init( &sb2 );
|
||||
|
||||
sb_printf( &sb, L"%ls: ", program_name );
|
||||
|
||||
va_start( va, msg );
|
||||
sb_vprintf( &sb, msg, va );
|
||||
va_end( va );
|
||||
|
||||
write_screen( (wchar_t *)sb.buff );
|
||||
write_screen( (wchar_t *)sb.buff, &sb2 );
|
||||
fwprintf( stderr, L"%ls", sb2.buff );
|
||||
|
||||
sb_destroy( &sb );
|
||||
sb_destroy( &sb2 );
|
||||
}
|
||||
|
||||
void write_screen( const wchar_t *msg )
|
||||
void write_screen( const wchar_t *msg, string_buffer_t *buff )
|
||||
{
|
||||
const wchar_t *start, *pos;
|
||||
int line_width = 0;
|
||||
int tok_width = 0;
|
||||
int screen_width = common_get_width();
|
||||
|
||||
CHECK( msg, );
|
||||
CHECK( buff, );
|
||||
|
||||
if( screen_width )
|
||||
{
|
||||
start = pos = msg;
|
||||
@@ -678,7 +569,7 @@ void write_screen( const wchar_t *msg )
|
||||
*/
|
||||
while( *pos && ( !wcschr( L" \n\r\t", *pos ) ) )
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
Check is token is wider than one line.
|
||||
If so we mark it as an overflow and break the token.
|
||||
@@ -703,12 +594,12 @@ void write_screen( const wchar_t *msg )
|
||||
else if( overflow )
|
||||
{
|
||||
/*
|
||||
In case of overflow, we print a newline, except if we alreade are at position 0
|
||||
In case of overflow, we print a newline, except if we already are at position 0
|
||||
*/
|
||||
wchar_t *token = wcsndup( start, pos-start );
|
||||
if( line_width != 0 )
|
||||
putwc( L'\n', stderr );
|
||||
fwprintf( stderr, L"%ls-\n", token );
|
||||
sb_append_char( buff, L'\n' );
|
||||
sb_printf( buff, L"%ls-\n", token );
|
||||
free( token );
|
||||
line_width=0;
|
||||
}
|
||||
@@ -720,36 +611,49 @@ void write_screen( const wchar_t *msg )
|
||||
wchar_t *token = wcsndup( start, pos-start );
|
||||
if( (line_width + (line_width!=0?1:0) + tok_width) > screen_width )
|
||||
{
|
||||
putwc( L'\n', stderr );
|
||||
sb_append_char( buff, L'\n' );
|
||||
line_width=0;
|
||||
}
|
||||
fwprintf( stderr, L"%ls%ls", line_width?L" ":L"", token );
|
||||
sb_printf( buff, L"%ls%ls", line_width?L" ":L"", token );
|
||||
free( token );
|
||||
line_width += (line_width!=0?1:0) + tok_width;
|
||||
}
|
||||
|
||||
/*
|
||||
Break on end of string
|
||||
*/
|
||||
if( !*pos )
|
||||
{
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
start=pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fwprintf( stderr, L"%ls", msg );
|
||||
sb_printf( buff, L"%ls", msg );
|
||||
}
|
||||
putwc( L'\n', stderr );
|
||||
sb_append_char( buff, L'\n' );
|
||||
}
|
||||
|
||||
wchar_t *escape( const wchar_t *in,
|
||||
int escape_all )
|
||||
{
|
||||
wchar_t *out = malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1));
|
||||
wchar_t *pos=out;
|
||||
wchar_t *out;
|
||||
wchar_t *pos;
|
||||
|
||||
if( !in )
|
||||
{
|
||||
debug( 0, L"%s called with null input", __func__ );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
out = malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1));
|
||||
pos = out;
|
||||
|
||||
if( !out )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
while( *in != 0 )
|
||||
{
|
||||
@@ -773,74 +677,80 @@ wchar_t *escape( const wchar_t *in,
|
||||
else
|
||||
{
|
||||
|
||||
switch( *in )
|
||||
{
|
||||
case L'\t':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L't';
|
||||
break;
|
||||
switch( *in )
|
||||
{
|
||||
case L'\t':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L't';
|
||||
break;
|
||||
|
||||
case L'\n':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'n';
|
||||
break;
|
||||
case L'\n':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'n';
|
||||
break;
|
||||
|
||||
case L'\b':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'b';
|
||||
break;
|
||||
case L'\b':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'b';
|
||||
break;
|
||||
|
||||
case L'\r':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'r';
|
||||
break;
|
||||
case L'\r':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'r';
|
||||
break;
|
||||
|
||||
case L'\e':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'e';
|
||||
break;
|
||||
case L'\e':
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'e';
|
||||
break;
|
||||
|
||||
case L'\\':
|
||||
case L'&':
|
||||
case L'$':
|
||||
case L' ':
|
||||
case L'#':
|
||||
case L'^':
|
||||
case L'<':
|
||||
case L'>':
|
||||
case L'(':
|
||||
case L')':
|
||||
case L'[':
|
||||
case L']':
|
||||
case L'{':
|
||||
case L'}':
|
||||
case L'?':
|
||||
case L'*':
|
||||
case L'|':
|
||||
case L';':
|
||||
case L':':
|
||||
case L'\'':
|
||||
case L'"':
|
||||
case L'%':
|
||||
case L'~':
|
||||
if( escape_all )
|
||||
*pos++ = L'\\';
|
||||
*pos++ = *in;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( *in < 32 )
|
||||
case L'\\':
|
||||
case L'&':
|
||||
case L'$':
|
||||
case L' ':
|
||||
case L'#':
|
||||
case L'^':
|
||||
case L'<':
|
||||
case L'>':
|
||||
case L'(':
|
||||
case L')':
|
||||
case L'[':
|
||||
case L']':
|
||||
case L'{':
|
||||
case L'}':
|
||||
case L'?':
|
||||
case L'*':
|
||||
case L'|':
|
||||
case L';':
|
||||
case L':':
|
||||
case L'\'':
|
||||
case L'"':
|
||||
case L'%':
|
||||
case L'~':
|
||||
{
|
||||
int tmp = (*in)%16;
|
||||
*pos++ = L'\\';
|
||||
*pos++ = L'x';
|
||||
*pos++ = ((*in>15)? L'1' : L'0');
|
||||
*pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
|
||||
}
|
||||
else
|
||||
if( escape_all )
|
||||
*pos++ = L'\\';
|
||||
*pos++ = *in;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if( *in < 32 )
|
||||
{
|
||||
int tmp = (*in)%16;
|
||||
*pos++ = L'\\';
|
||||
*pos++ = L'x';
|
||||
*pos++ = ((*in>15)? L'1' : L'0');
|
||||
*pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pos++ = *in;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in++;
|
||||
@@ -854,13 +764,19 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
{
|
||||
|
||||
int mode = 0;
|
||||
int in_pos, out_pos, len = wcslen( orig );
|
||||
int in_pos, out_pos, len;
|
||||
int c;
|
||||
int bracket_count=0;
|
||||
wchar_t prev=0;
|
||||
wchar_t *in = wcsdup(orig);
|
||||
wchar_t *in;
|
||||
|
||||
CHECK( orig, 0 );
|
||||
|
||||
len = wcslen( orig );
|
||||
in = wcsdup( orig );
|
||||
|
||||
if( !in )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
for( in_pos=0, out_pos=0;
|
||||
in_pos<len;
|
||||
@@ -934,14 +850,14 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
int base=16;
|
||||
|
||||
int byte = 0;
|
||||
int max_val = 127;
|
||||
wchar_t max_val = ASCII_MAX;
|
||||
|
||||
switch( in[in_pos] )
|
||||
{
|
||||
case L'u':
|
||||
{
|
||||
chars=4;
|
||||
max_val = 35535;
|
||||
max_val = UCS2_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -960,7 +876,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
case L'X':
|
||||
{
|
||||
byte=1;
|
||||
max_val = 255;
|
||||
max_val = BYTE_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -986,7 +902,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
res=(res*base)|d;
|
||||
}
|
||||
|
||||
if( (res > 0) && (res <= max_val) )
|
||||
if( (res <= max_val) )
|
||||
{
|
||||
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
|
||||
}
|
||||
@@ -1368,13 +1284,13 @@ static char *gen_unique_nfs_filename( const char *filename )
|
||||
pidlen = sprint_pid_t( getpid(), newname + orglen + 1 + hnlen + 1 );
|
||||
newname[orglen + 1 + hnlen + 1 + pidlen] = '\0';
|
||||
/* debug( 1, L"gen_unique_nfs_filename returning with: newname = \"%s\"; "
|
||||
L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; "
|
||||
L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d",
|
||||
newname, (int)HOST_NAME_MAX, hnlen, orglen,
|
||||
(int)sizeof(pid_t),
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1),
|
||||
(int)(orglen + 1 + hnlen + 1 +
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */
|
||||
L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; "
|
||||
L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d",
|
||||
newname, (int)HOST_NAME_MAX, hnlen, orglen,
|
||||
(int)sizeof(pid_t),
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1),
|
||||
(int)(orglen + 1 + hnlen + 1 +
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */
|
||||
return newname;
|
||||
}
|
||||
|
||||
@@ -1401,6 +1317,9 @@ int acquire_lock_file( const char *lockfile, const int timeout, int force )
|
||||
debug( 1, L"acquire_lock_file: open: %s", strerror( errno ) );
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
Don't need to check exit status of close on read-only file descriptors
|
||||
*/
|
||||
close( fd );
|
||||
if( stat( linkfile, &statbuf ) != 0 )
|
||||
{
|
||||
@@ -1500,3 +1419,29 @@ int common_get_height()
|
||||
return termsize.ws_row;
|
||||
}
|
||||
|
||||
void tokenize_variable_array( const wchar_t *val, array_list_t *out )
|
||||
{
|
||||
if( val )
|
||||
{
|
||||
wchar_t *cpy = wcsdup( val );
|
||||
wchar_t *pos, *start;
|
||||
|
||||
if( !cpy )
|
||||
{
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
for( start=pos=cpy; *pos; pos++ )
|
||||
{
|
||||
if( *pos == ARRAY_SEP )
|
||||
{
|
||||
*pos=0;
|
||||
al_push( out, start==cpy?cpy:wcsdup(start) );
|
||||
start=pos+1;
|
||||
}
|
||||
}
|
||||
al_push( out, start==cpy?cpy:wcsdup(start) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
164
common.h
164
common.h
@@ -20,22 +20,26 @@
|
||||
*/
|
||||
#define MAX_UTF8_BYTES 6
|
||||
|
||||
/**
|
||||
Color code for set_color. Does not update the color.
|
||||
*/
|
||||
|
||||
#define FISH_COLOR_IGNORE -1
|
||||
|
||||
/**
|
||||
Color code for set_color. Sets the default color.
|
||||
*/
|
||||
#define FISH_COLOR_RESET -2
|
||||
|
||||
/**
|
||||
This is in the unicode private use area.
|
||||
*/
|
||||
#define ENCODE_DIRECT_BASE 0xf100
|
||||
|
||||
/**
|
||||
Highest legal ascii value
|
||||
*/
|
||||
#define ASCII_MAX 127u
|
||||
|
||||
/**
|
||||
Highest legal 16-bit unicode value
|
||||
*/
|
||||
#define UCS2_MAX 0xffffu
|
||||
|
||||
/**
|
||||
Highest legal byte value
|
||||
*/
|
||||
#define BYTE_MAX 0xffu
|
||||
|
||||
/**
|
||||
Save the shell mode on startup so we can restore them on exit
|
||||
*/
|
||||
@@ -47,11 +51,6 @@ extern struct termios shell_modes;
|
||||
*/
|
||||
extern wchar_t ellipsis_char;
|
||||
|
||||
/**
|
||||
The maximum number of charset convertion errors to report
|
||||
*/
|
||||
extern int error_max;
|
||||
|
||||
/**
|
||||
The verbosity of fish
|
||||
*/
|
||||
@@ -68,6 +67,35 @@ extern char *profile;
|
||||
*/
|
||||
extern wchar_t *program_name;
|
||||
|
||||
/**
|
||||
This macro is used to check that an input argument is not null. It
|
||||
is a bit lika a non-fatal form of assert. Instead of exit-ing on
|
||||
failiure, the current function is ended at once. The second
|
||||
parameter is the exit status of the current function on failiure.
|
||||
*/
|
||||
#define CHECK( arg, retval ) \
|
||||
if( !(arg) ) \
|
||||
{ \
|
||||
debug( 1, \
|
||||
L"function %s called with null value for argument %s. " \
|
||||
L"This is a bug. " \
|
||||
L"If you can reproduce it, please send a bug report to %s.", \
|
||||
__func__, \
|
||||
#arg, \
|
||||
PACKAGE_BUGREPORT ); \
|
||||
return retval; \
|
||||
} \
|
||||
|
||||
|
||||
/**
|
||||
Exit program at once, leaving an error message about running out of memory
|
||||
*/
|
||||
#define DIE_MEM() \
|
||||
{ \
|
||||
fwprintf( stderr, L"fish: Out of memory on line %d of file %s, shutting down fish\n", __LINE__, __FILE__ ); \
|
||||
exit(1); \
|
||||
} \
|
||||
|
||||
/**
|
||||
Take an array_list_t containing wide strings and converts them to a
|
||||
single null-terminated wchar_t **. The array is allocated using
|
||||
@@ -91,24 +119,47 @@ wchar_t **list_to_char_arr( array_list_t *l );
|
||||
int fgetws2( wchar_t **buff, int *len, FILE *f );
|
||||
|
||||
/**
|
||||
Sorts a list of wide strings according to the wcsfilecmp-function
|
||||
from the util library
|
||||
Sorts an array_list of wide strings according to the
|
||||
wcsfilecmp-function from the util library
|
||||
*/
|
||||
void sort_list( array_list_t *comp );
|
||||
|
||||
/**
|
||||
Returns a newly allocated wide character string equivalent of the
|
||||
specified multibyte character string
|
||||
|
||||
This function encodes illegal character sequences in a reversible
|
||||
way using the private use area.
|
||||
*/
|
||||
wchar_t *str2wcs( const char *in );
|
||||
|
||||
/**
|
||||
Converts the narrow character string \c in into it's wide
|
||||
equivalent, stored in \c out. \c out must have enough space to fit
|
||||
the entire string.
|
||||
|
||||
This function encodes illegal character sequences in a reversible
|
||||
way using the private use area.
|
||||
*/
|
||||
wchar_t *str2wcs_internal( const char *in, wchar_t *out );
|
||||
|
||||
/**
|
||||
Returns a newly allocated multibyte character string equivalent of
|
||||
the specified wide character string
|
||||
|
||||
This function decodes illegal character sequences in a reversible
|
||||
way using the private use area.
|
||||
*/
|
||||
char *wcs2str( const wchar_t *in );
|
||||
|
||||
/**
|
||||
Converts the wide character string \c in into it's narrow
|
||||
equivalent, stored in \c out. \c out must have enough space to fit
|
||||
the entire string.
|
||||
|
||||
This function decodes illegal character sequences in a reversible
|
||||
way using the private use area.
|
||||
*/
|
||||
char *wcs2str_internal( const wchar_t *in, char *out );
|
||||
|
||||
/**
|
||||
@@ -134,35 +185,26 @@ wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
|
||||
*/
|
||||
wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
||||
|
||||
|
||||
/**
|
||||
Appends src to string dst of size siz (unlike wcsncat, siz is the
|
||||
full size of dst, not space left). At most siz-1 characters will be
|
||||
copied. Always NUL terminates (unless siz <= wcslen(dst)). Returns
|
||||
wcslen(src) + MIN(siz, wcslen(initial dst)). If retval >= siz,
|
||||
truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcat function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
|
||||
*/
|
||||
size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
/**
|
||||
Copy src to string dst of size siz. At most siz-1 characters will
|
||||
be copied. Always NUL terminates (unless siz == 0). Returns
|
||||
wcslen(src); if retval >= siz, truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcpy function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
*/
|
||||
size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
/**
|
||||
Test if the given string is a valid variable name
|
||||
*/
|
||||
|
||||
int wcsvarname( wchar_t *str );
|
||||
|
||||
/**
|
||||
Test if the given string is a valid variable name.
|
||||
|
||||
\return null if this is a valid name, and a pointer to the first invalid character otherwise
|
||||
*/
|
||||
|
||||
wchar_t *wcsvarname( wchar_t *str );
|
||||
|
||||
/**
|
||||
Test if the given string is valid in a variable name
|
||||
|
||||
\return 1 if this is a valid name, 0 otherwise
|
||||
*/
|
||||
|
||||
int wcsvarchr( wchar_t chr );
|
||||
|
||||
|
||||
/**
|
||||
@@ -177,7 +219,7 @@ int my_wcswidth( const wchar_t *c );
|
||||
|
||||
\param in the position of the opening quote
|
||||
*/
|
||||
const wchar_t *quote_end( const wchar_t *in );
|
||||
wchar_t *quote_end( const wchar_t *in );
|
||||
|
||||
/**
|
||||
A call to this function will reset the error counter. Some
|
||||
@@ -198,9 +240,11 @@ void error_reset();
|
||||
const wchar_t *wsetlocale( int category, const wchar_t *locale );
|
||||
|
||||
/**
|
||||
Checks if \c needle is included in the list of strings specified
|
||||
Checks if \c needle is included in the list of strings specified. A warning is printed if needle is zero.
|
||||
|
||||
\param needle the string to search for in the list
|
||||
|
||||
\return zero is needle is not found, of if needle is null, non-zero otherwise
|
||||
*/
|
||||
int contains_str( const wchar_t *needle, ... );
|
||||
|
||||
@@ -210,20 +254,6 @@ int contains_str( const wchar_t *needle, ... );
|
||||
*/
|
||||
int read_blocked(int fd, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
Exit program at once, leaving an error message about running out of memory
|
||||
*/
|
||||
void die_mem();
|
||||
|
||||
/**
|
||||
Create global_context using halloc
|
||||
*/
|
||||
void common_init();
|
||||
|
||||
/**
|
||||
Free global_context using halloc_free
|
||||
*/
|
||||
void common_destroy();
|
||||
|
||||
/**
|
||||
Issue a debug message with printf-style string formating and
|
||||
@@ -302,10 +332,20 @@ int common_get_height();
|
||||
void common_handle_winch( int signal );
|
||||
|
||||
/**
|
||||
Write paragraph of output to screen. Ignore newlines in message and
|
||||
perform internal line-breaking.
|
||||
Write paragraph of output to the specified stringbuffer, and redo
|
||||
the linebreaks to fit the current screen.
|
||||
*/
|
||||
void write_screen( const wchar_t *msg );
|
||||
void write_screen( const wchar_t *msg, string_buffer_t *buff );
|
||||
|
||||
/**
|
||||
Tokenize the specified string into the specified array_list_t.
|
||||
Each new element is allocated using malloc and must be freed by the
|
||||
caller.
|
||||
|
||||
\param val the input string. The contents of this string is not changed.
|
||||
\param out the list in which to place the elements.
|
||||
*/
|
||||
void tokenize_variable_array( const wchar_t *val, array_list_t *out );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
179
complete.c
179
complete.c
@@ -41,6 +41,7 @@
|
||||
#include "intern.h"
|
||||
#include "translate.h"
|
||||
#include "parse_util.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
#include "wutil.h"
|
||||
|
||||
@@ -152,6 +153,14 @@
|
||||
*/
|
||||
#define CC_FALSE L"false"
|
||||
|
||||
/**
|
||||
The special cased translation macro for completions. The empty
|
||||
string needs to be special cased, since it can occur, and should
|
||||
not be translated. (Gettext returns the version information as the
|
||||
response)
|
||||
*/
|
||||
#define C_(wstr) ((wstr==L"")?L"":wgettext(wstr))
|
||||
|
||||
/**
|
||||
Struct describing a completion option entry.
|
||||
|
||||
@@ -224,7 +233,6 @@ static hash_table_t *condition_cache=0;
|
||||
*/
|
||||
static string_buffer_t *get_desc_buff=0;
|
||||
|
||||
|
||||
/**
|
||||
This command clears the cache of condition tests created by \c condition_test().
|
||||
*/
|
||||
@@ -259,7 +267,7 @@ static int condition_test( const wchar_t *condition )
|
||||
condition_cache = malloc( sizeof( hash_table_t ) );
|
||||
if( !condition_cache )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
}
|
||||
|
||||
@@ -315,7 +323,7 @@ static void complete_free_entry( complete_entry *c )
|
||||
/**
|
||||
Free hash key and hash value
|
||||
*/
|
||||
static void clear_hash_entry( const void *key, const void *data )
|
||||
static void clear_hash_entry( void *key, void *data )
|
||||
{
|
||||
free( (void *)key );
|
||||
free( (void *)data );
|
||||
@@ -345,7 +353,7 @@ void complete_destroy()
|
||||
suffix_hash=0;
|
||||
}
|
||||
|
||||
parse_util_load_reset(L"fish_complete_path");
|
||||
parse_util_load_reset( L"fish_complete_path", 0 );
|
||||
|
||||
}
|
||||
|
||||
@@ -377,15 +385,18 @@ void complete_add( const wchar_t *cmd,
|
||||
const wchar_t *comp,
|
||||
const wchar_t *desc )
|
||||
{
|
||||
complete_entry *c =
|
||||
complete_find_exact_entry( cmd, cmd_type );
|
||||
complete_entry *c;
|
||||
complete_entry_opt *opt;
|
||||
|
||||
CHECK( cmd, );
|
||||
|
||||
c = complete_find_exact_entry( cmd, cmd_type );
|
||||
|
||||
if( c == 0 )
|
||||
{
|
||||
if( !(c = malloc( sizeof(complete_entry) )))
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
c->next = first_entry;
|
||||
@@ -400,7 +411,7 @@ void complete_add( const wchar_t *cmd,
|
||||
|
||||
if( !(opt = malloc( sizeof( complete_entry_opt ) )))
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
opt->next = c->first_option;
|
||||
@@ -445,6 +456,8 @@ void complete_remove( const wchar_t *cmd,
|
||||
{
|
||||
complete_entry *e, *eprev=0, *enext=0;
|
||||
|
||||
CHECK( cmd, );
|
||||
|
||||
for( e = first_entry; e; e=enext )
|
||||
{
|
||||
enext=e->next;
|
||||
@@ -536,18 +549,19 @@ void complete_remove( const wchar_t *cmd,
|
||||
}
|
||||
|
||||
/**
|
||||
Find the full path and commandname from a command string. the
|
||||
result of \c pathp must be freed by the caller, the result of \c
|
||||
cmdp must not be freed by the caller.
|
||||
Find the full path and commandname from a command string. Both
|
||||
pointers are allocated using halloc and will be free'd when\c
|
||||
context is halloc_free'd.
|
||||
*/
|
||||
static void parse_cmd_string( const wchar_t *str,
|
||||
static void parse_cmd_string( void *context,
|
||||
const wchar_t *str,
|
||||
wchar_t **pathp,
|
||||
wchar_t **cmdp )
|
||||
{
|
||||
wchar_t *cmd, *path;
|
||||
|
||||
/* Get the path of the command */
|
||||
path = get_filename( str );
|
||||
path = parser_get_filename( context, str );
|
||||
if( path == 0 )
|
||||
{
|
||||
/**
|
||||
@@ -590,6 +604,11 @@ int complete_is_valid_option( const wchar_t *str,
|
||||
int gnu_opt_len=0;
|
||||
char *short_validated;
|
||||
|
||||
void *context;
|
||||
|
||||
CHECK( str, 0 );
|
||||
CHECK( opt, 0 );
|
||||
|
||||
/*
|
||||
Check some generic things like -- and - options.
|
||||
*/
|
||||
@@ -625,11 +644,15 @@ int complete_is_valid_option( const wchar_t *str,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !(short_validated = malloc( wcslen( opt ) )))
|
||||
context = halloc( 0, 0 );
|
||||
|
||||
if( !(short_validated = halloc( context, wcslen( opt ) )))
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
|
||||
|
||||
memset( short_validated, 0, wcslen( opt ) );
|
||||
|
||||
hash_init( &gnu_match_hash,
|
||||
@@ -650,7 +673,7 @@ int complete_is_valid_option( const wchar_t *str,
|
||||
}
|
||||
}
|
||||
|
||||
parse_cmd_string( str, &path, &cmd );
|
||||
parse_cmd_string( context, str, &path, &cmd );
|
||||
|
||||
/*
|
||||
Make sure completions are loaded for the specified command
|
||||
@@ -749,7 +772,6 @@ int complete_is_valid_option( const wchar_t *str,
|
||||
}
|
||||
}
|
||||
}
|
||||
free( path );
|
||||
|
||||
if( authorative )
|
||||
{
|
||||
@@ -803,8 +825,9 @@ int complete_is_valid_option( const wchar_t *str,
|
||||
}
|
||||
|
||||
hash_destroy( &gnu_match_hash );
|
||||
free( short_validated );
|
||||
|
||||
halloc_free( context );
|
||||
|
||||
return (authorative && found_match)?opt_found:1;
|
||||
}
|
||||
|
||||
@@ -836,7 +859,7 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
|
||||
{
|
||||
suffix_hash = malloc( sizeof( hash_table_t) );
|
||||
if( !suffix_hash )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
hash_init( suffix_hash, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
||||
@@ -883,7 +906,7 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_foreach( &l, &free );
|
||||
al_destroy( &l );
|
||||
}
|
||||
|
||||
@@ -907,6 +930,8 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
CHECK( filename, 0 );
|
||||
|
||||
if( !get_desc_buff )
|
||||
{
|
||||
get_desc_buff = sb_halloc( global_context);
|
||||
@@ -1182,11 +1207,14 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
|
||||
|
||||
hash_destroy( &lookup );
|
||||
al_foreach( &list,
|
||||
(void(*)(const void *))&free );
|
||||
&free );
|
||||
al_destroy( &list );
|
||||
free( lookup_cmd );
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a description for the specified function
|
||||
*/
|
||||
static const wchar_t *complete_function_desc( const wchar_t *fn )
|
||||
{
|
||||
const wchar_t *res = function_get_desc( fn );
|
||||
@@ -1413,7 +1441,7 @@ static void complete_from_args( const wchar_t *str,
|
||||
|
||||
copy_strings_with_prefix( comp_out, str, desc, 0, &possible_comp );
|
||||
|
||||
al_foreach( &possible_comp, (void (*)(const void *))&free );
|
||||
al_foreach( &possible_comp, &free );
|
||||
al_destroy( &possible_comp );
|
||||
}
|
||||
|
||||
@@ -1507,6 +1535,14 @@ static int short_ok( wchar_t *arg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
This is an event handler triggered when the definition of a
|
||||
specifiec function is changed. It automatcally removes the
|
||||
specified function.
|
||||
|
||||
This is to make sure that the function disappears if the file is
|
||||
removed or if ti contains a syntax error.
|
||||
*/
|
||||
static void complete_load_handler( const wchar_t *cmd )
|
||||
{
|
||||
complete_remove( cmd, COMMAND, 0, 0 );
|
||||
@@ -1514,7 +1550,10 @@ static void complete_load_handler( const wchar_t *cmd )
|
||||
|
||||
void complete_load( const wchar_t *name, int reload )
|
||||
{
|
||||
parse_util_load( name, L"fish_complete_path", &complete_load_handler, reload );
|
||||
parse_util_load( name,
|
||||
L"fish_complete_path",
|
||||
&complete_load_handler,
|
||||
reload );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1534,13 +1573,14 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
wchar_t *cmd, *path;
|
||||
int use_common=1, use_files=1;
|
||||
|
||||
parse_cmd_string( cmd_orig, &path, &cmd );
|
||||
void *context = halloc( 0, 0 );
|
||||
|
||||
parse_cmd_string( context, cmd_orig, &path, &cmd );
|
||||
|
||||
complete_load( cmd, 1 );
|
||||
|
||||
al_init( &matches );
|
||||
|
||||
|
||||
for( i=first_entry; i; i=i->next )
|
||||
{
|
||||
wchar_t *match = i->cmd_type?path:cmd;
|
||||
@@ -1560,7 +1600,7 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
{
|
||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( arg, o->comp, _(o->desc), comp_out );
|
||||
complete_from_args( arg, o->comp, C_(o->desc), comp_out );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1584,7 +1624,7 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
found_old = 1;
|
||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( str, o->comp, _(o->desc), comp_out );
|
||||
complete_from_args( str, o->comp, C_(o->desc), comp_out );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1610,7 +1650,7 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
{
|
||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( str, o->comp, _(o->desc), comp_out );
|
||||
complete_from_args( str, o->comp, C_(o->desc), comp_out );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1634,7 +1674,7 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
|
||||
{
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( str, o->comp, _(o->desc), comp_out );
|
||||
complete_from_args( str, o->comp, C_(o->desc), comp_out );
|
||||
}
|
||||
|
||||
if( wcslen(str) > 0 )
|
||||
@@ -1645,11 +1685,11 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
if( o->short_opt != L'\0' &&
|
||||
short_ok( str, o->short_opt, i->short_opt_str ) )
|
||||
{
|
||||
const wchar_t *desc = _(o->desc );
|
||||
const wchar_t *desc = C_(o->desc );
|
||||
wchar_t *next_opt =
|
||||
malloc( sizeof(wchar_t)*(3 + wcslen(desc)));
|
||||
if( !next_opt )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
next_opt[0]=o->short_opt;
|
||||
next_opt[1]=COMPLETE_SEP;
|
||||
@@ -1663,11 +1703,10 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
*/
|
||||
if( o->long_opt[0] != L'\0' )
|
||||
{
|
||||
string_buffer_t whole_opt;
|
||||
sb_init( &whole_opt );
|
||||
sb_append2( &whole_opt, o->old_mode?L"-":L"--", o->long_opt, (void *)0 );
|
||||
string_buffer_t *whole_opt = sb_halloc( context );
|
||||
sb_append2( whole_opt, o->old_mode?L"-":L"--", o->long_opt, (void *)0 );
|
||||
|
||||
if( wcsncmp( str, (wchar_t *)whole_opt.buff, wcslen(str) )==0)
|
||||
if( wcsncmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0)
|
||||
{
|
||||
/*
|
||||
If the option requires arguments, add
|
||||
@@ -1680,29 +1719,30 @@ static int complete_param( wchar_t *cmd_orig,
|
||||
if( o->old_mode || !(o->result_mode & NO_COMMON ) )
|
||||
{
|
||||
al_push( comp_out,
|
||||
wcsdupcat2( &((wchar_t *)whole_opt.buff)[wcslen(str)],
|
||||
wcsdupcat2( &((wchar_t *)whole_opt->buff)[wcslen(str)],
|
||||
COMPLETE_SEP_STR,
|
||||
_(o->desc),
|
||||
C_(o->desc),
|
||||
(void *)0) );
|
||||
}
|
||||
|
||||
if( !o->old_mode && ( wcslen(o->comp) || (o->result_mode & NO_COMMON ) ) )
|
||||
{
|
||||
al_push( comp_out,
|
||||
wcsdupcat2( &((wchar_t *)whole_opt.buff)[wcslen(str)],
|
||||
wcsdupcat2( &((wchar_t *)whole_opt->buff)[wcslen(str)],
|
||||
L"=",
|
||||
COMPLETE_SEP_STR,
|
||||
_(o->desc),
|
||||
C_(o->desc),
|
||||
(void *)0) );
|
||||
}
|
||||
}
|
||||
sb_destroy( &whole_opt );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free( path );
|
||||
|
||||
halloc_free( context );
|
||||
|
||||
return use_files;
|
||||
}
|
||||
|
||||
@@ -1723,12 +1763,12 @@ static void complete_param_expand( wchar_t *str,
|
||||
{
|
||||
comp_str = str;
|
||||
}
|
||||
|
||||
/*
|
||||
debug( 3,
|
||||
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
|
||||
comp_str,
|
||||
do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
|
||||
|
||||
*/
|
||||
expand_string( 0,
|
||||
wcsdup(comp_str),
|
||||
comp_out,
|
||||
@@ -1913,20 +1953,21 @@ static int try_complete_user( const wchar_t *cmd,
|
||||
void complete( const wchar_t *cmd,
|
||||
array_list_t *comp )
|
||||
{
|
||||
const wchar_t *begin, *end, *prev_begin, *prev_end;
|
||||
wchar_t *begin, *end, *prev_begin, *prev_end;
|
||||
wchar_t *buff;
|
||||
tokenizer tok;
|
||||
wchar_t *current_token=0, *current_command=0, *prev_token=0;
|
||||
|
||||
int on_command=0;
|
||||
int pos;
|
||||
|
||||
int old_error_max = error_max;
|
||||
int done=0;
|
||||
int cursor_pos;
|
||||
|
||||
int cursor_pos = wcslen(cmd );
|
||||
CHECK( cmd, );
|
||||
CHECK( comp, );
|
||||
|
||||
error_max=0;
|
||||
// debug( 1, L"Complete '%ls'", cmd );
|
||||
|
||||
cursor_pos = wcslen(cmd );
|
||||
|
||||
/**
|
||||
If we are completing a variable name or a tilde expansion user
|
||||
@@ -1983,7 +2024,8 @@ void complete( const wchar_t *cmd,
|
||||
{
|
||||
if( parser_is_subcommand( tok_last( &tok ) ) )
|
||||
break;
|
||||
|
||||
|
||||
free( current_command );
|
||||
current_command = wcsdup( tok_last( &tok ) );
|
||||
|
||||
on_command = (pos <= tok_get_pos( &tok) + wcslen( tok_last( &tok ) ) );
|
||||
@@ -2022,9 +2064,28 @@ void complete( const wchar_t *cmd,
|
||||
current_token = wcsndup( begin, cursor_pos-(begin-cmd) );
|
||||
|
||||
prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L"");
|
||||
|
||||
// fwprintf( stderr, L"on_command: %d, %ls %ls\n", on_command, current_compmand, current_token );
|
||||
|
||||
|
||||
// debug( 0, L"on_command: %d, %ls %ls\n", on_command, current_command, current_token );
|
||||
if( !had_cmd )
|
||||
{
|
||||
on_command=1;
|
||||
}
|
||||
|
||||
if( !current_token )
|
||||
{
|
||||
current_token = wcsdup(L"");
|
||||
}
|
||||
|
||||
if( !current_command )
|
||||
{
|
||||
current_command = wcsdup(L"");
|
||||
}
|
||||
|
||||
if( !prev_token )
|
||||
{
|
||||
prev_token = wcsdup(L"");
|
||||
}
|
||||
|
||||
if( current_token && current_command && prev_token )
|
||||
{
|
||||
if( on_command )
|
||||
@@ -2044,18 +2105,18 @@ void complete( const wchar_t *cmd,
|
||||
*/
|
||||
|
||||
int do_file;
|
||||
|
||||
|
||||
do_file = complete_param( current_command, prev_token, current_token, comp );
|
||||
complete_param_expand( current_token, comp, do_file );
|
||||
}
|
||||
}
|
||||
|
||||
free( current_token );
|
||||
free( current_command );
|
||||
free( prev_token );
|
||||
}
|
||||
|
||||
free( current_token );
|
||||
free( current_command );
|
||||
free( prev_token );
|
||||
|
||||
error_max=old_error_max;
|
||||
condition_cache_clear();
|
||||
|
||||
}
|
||||
@@ -2120,7 +2181,7 @@ void complete_print( string_buffer_t *out )
|
||||
|
||||
append_switch( out,
|
||||
L"description",
|
||||
_(o->desc) );
|
||||
C_(o->desc) );
|
||||
|
||||
append_switch( out,
|
||||
L"arguments",
|
||||
|
||||
46
complete.h
46
complete.h
@@ -1,10 +1,12 @@
|
||||
/** \file complete.h
|
||||
Prototypes for functions related to tab-completion.
|
||||
|
||||
These functions are used for storing and retrieving tab-completion data, as well as for performing tab-completion.
|
||||
These functions are used for storing and retrieving tab-completion
|
||||
data, as well as for performing tab-completion.
|
||||
*/
|
||||
|
||||
#ifndef FISH_COMPLETE_H
|
||||
|
||||
/**
|
||||
Header guard
|
||||
*/
|
||||
@@ -14,29 +16,53 @@
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/** Use all completions */
|
||||
/**
|
||||
Use all completions
|
||||
*/
|
||||
#define SHARED 0
|
||||
/** Do not use file completion */
|
||||
/**
|
||||
Do not use file completion
|
||||
*/
|
||||
#define NO_FILES 1
|
||||
/** Require a parameter after completion */
|
||||
/**
|
||||
Require a parameter after completion
|
||||
*/
|
||||
#define NO_COMMON 2
|
||||
/** Only use the argument list specifies with completion after option. This is the same as (NO_FILES & NO_COMMON) */
|
||||
/**
|
||||
Only use the argument list specifies with completion after
|
||||
option. This is the same as (NO_FILES & NO_COMMON)
|
||||
*/
|
||||
#define EXCLUSIVE 3
|
||||
|
||||
/** Command is a path */
|
||||
/**
|
||||
Command is a path
|
||||
*/
|
||||
#define PATH 1
|
||||
/** Command is not a path */
|
||||
/**
|
||||
Command is not a path
|
||||
*/
|
||||
#define COMMAND 0
|
||||
|
||||
/** Separateor between completion and description*/
|
||||
/**
|
||||
Separator between completion and description
|
||||
*/
|
||||
#define COMPLETE_SEP L'\004'
|
||||
/** Separateor between completion and description*/
|
||||
|
||||
/**
|
||||
Separator between completion and description
|
||||
*/
|
||||
#define COMPLETE_SEP_STR L"\004"
|
||||
|
||||
/**
|
||||
Separator between completion items in fish_pager. This is used for
|
||||
completion grouping, e.g. when putting completions with the same
|
||||
descriptions on the same line.
|
||||
*/
|
||||
#define COMPLETE_ITEM_SEP L'\uf500'
|
||||
|
||||
/**
|
||||
Character that separates the completion and description on programmable completions
|
||||
Character that separates the completion and description on
|
||||
programmable completions
|
||||
*/
|
||||
#define PROG_COMPLETE_SEP L'\t'
|
||||
|
||||
|
||||
71
configure.ac
71
configure.ac
@@ -1,5 +1,5 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(fish,1.21.4,fish-users@lists.sf.net)
|
||||
AC_INIT(fish,1.21.9,fish-users@lists.sf.net)
|
||||
|
||||
# If needed, run autoconf to regenerate the configure file
|
||||
AC_MSG_CHECKING([if autoconf needs to be run])
|
||||
@@ -12,7 +12,7 @@ if test configure -ot configure.ac; then
|
||||
if autoconf; then
|
||||
./configure "$@"
|
||||
fi
|
||||
exit
|
||||
exit
|
||||
else
|
||||
AC_MSG_ERROR( [cannot find the autoconf program in your path.
|
||||
This program needs to be run whenever the configure.ac file is modified.
|
||||
@@ -85,7 +85,7 @@ AC_PROG_INSTALL
|
||||
# Check for doxygen, which is needed to build
|
||||
AC_CHECK_PROG( has_doxygen, [doxygen], "true")
|
||||
|
||||
if ! test $has_doxygen = "true"; then
|
||||
if ! test "$has_doxygen" = "true"; then
|
||||
AC_MSG_ERROR( [cannot find the Doxygen program in your path.
|
||||
This program is needed to build fish.
|
||||
Please install it and try again.])
|
||||
@@ -276,7 +276,7 @@ AC_CHECK_HEADER([regex.h],
|
||||
# Check for presense of various functions
|
||||
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp gettext fwprintf )
|
||||
AC_CHECK_FUNCS( futimes wcwidth wcswidth getopt_long wcstok fputwc fgetwc )
|
||||
AC_CHECK_FUNCS( wcstol dcgettext )
|
||||
AC_CHECK_FUNCS( wcstol dcgettext wcslcat wcslcpy lrand48_r)
|
||||
|
||||
# Here follows a list of small programs used to test for various
|
||||
# features that Autoconf doesn't tell us about
|
||||
@@ -326,53 +326,6 @@ if test "$ac_cv_func_fwprintf" = yes; then
|
||||
|
||||
fi
|
||||
|
||||
# Check for RLIMIT_NPROC in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_NPROC in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
[int tmp; tmp=RLIMIT_NPROC;], have_rlimit_as=yes, have_rlimit_as=no)
|
||||
if test "$have_rlimit_as" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_RLIMIT_NPROC], [1],
|
||||
[Define to 1 if HAVE_RLIMIT_NPROC is defined in <sys/resource.h>.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for RLIMIT_AS in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_AS in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
[int tmp; tmp=RLIMIT_AS;], have_rlimit_as=yes, have_rlimit_as=no)
|
||||
if test "$have_rlimit_as" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_RLIMIT_AS], [1],
|
||||
[Define to 1 if HAVE_RLIMIT_AS is defined in <sys/resource.h>.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for RLIMIT_MEMLOCK in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_MEMLOCK in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
[int tmp; tmp=RLIMIT_MEMLOCK;], have_rlimit_as=yes, have_rlimit_as=no)
|
||||
if test "$have_rlimit_as" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_RLIMIT_MEMLOCK], [1],
|
||||
[Define to 1 if HAVE_RLIMIT_MEMLOCK is defined in <sys/resource.h>.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for RLIMIT_RSS in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_RSS in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
[int tmp; tmp=RLIMIT_RSS;], have_rlimit_as=yes, have_rlimit_as=no)
|
||||
if test "$have_rlimit_as" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_RLIMIT_RSS], [1],
|
||||
[Define to 1 if HAVE_RLIMIT_RSS is defined in <sys/resource.h>.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for _nl_msg_cat_cntr symbol
|
||||
AC_MSG_CHECKING([for _nl_msg_cat_cntr symbol])
|
||||
@@ -389,9 +342,23 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check if we are using basic BSD curses - in that case we redefine
|
||||
# del_curterm as a no-op, to avoid a double-free
|
||||
|
||||
AC_MSG_CHECKING([If we are using BSD curses])
|
||||
case $target_os in
|
||||
*bsd*)
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_CHECK_LIB( ncurses, del_curterm, true, [AC_DEFINE([HAVE_BROKEN_DEL_CURTERM],[1],[We are using basic BSD curses, redefine del_curterm to a no-op to avoid a double-free bug])])
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT(no)
|
||||
;;
|
||||
esac
|
||||
|
||||
# Tell the world what we know
|
||||
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile etc/fish etc/fish_interactive.fish share/fish seq])
|
||||
AC_OUTPUT
|
||||
|
||||
echo "fish is now configured."
|
||||
echo "Use 'make' and 'make install' to built and install fish."
|
||||
echo "Use 'make' and 'make install' to build and install fish."
|
||||
|
||||
@@ -2,16 +2,23 @@
|
||||
\section and and - Conditionally execute a command
|
||||
|
||||
\subsection and-synopsis Synopsis
|
||||
<tt>COMMAND1; and COMMAND2</tt>
|
||||
<tt>COMMAND1; and COMMAND2</tt>
|
||||
|
||||
\subsection and-description Description
|
||||
|
||||
The \c and builtin is used to execute a command if the current exit status (as set by the last previous command) is zero
|
||||
The \c and builtin is used to execute a command if the current exit
|
||||
status (as set by the last previous command) is zero
|
||||
|
||||
The and command does not change the current exit status.
|
||||
|
||||
\subsection and-example Example
|
||||
|
||||
The following code runs the \c make command to build a program, and if it succeeds, it runs <tt>make install</tt>, which installs the program.
|
||||
The following code runs the \c make command to build a program, if the
|
||||
build succceds, the program is installed. If either step fails,
|
||||
<tt>make clean</tt> is run, which removes the files created by the
|
||||
build process
|
||||
|
||||
<pre>
|
||||
make; and make install
|
||||
make; and make install; or make clean
|
||||
</pre>
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ into a block. The reason for this is usually either to introduce a new
|
||||
variable scope or to redirect the input to output of this set of
|
||||
commands as a group.
|
||||
|
||||
The \c begin command does not change the current exit status.
|
||||
|
||||
\subsection begin-example Example
|
||||
|
||||
The following code sets a number of variables inside of a block
|
||||
|
||||
@@ -11,6 +11,22 @@ wildcarded values. The \c case statement is used together with the \c
|
||||
switch statement in order to determine which block should be
|
||||
performed.
|
||||
|
||||
Each \c case command is given one or more parameter. The first \c case
|
||||
command with a parameter that matches the string specified in the
|
||||
switch command will be evaluated. \c case parameters may contain
|
||||
wildcards. These need to be escaped or quoted in order to avoid
|
||||
regular wildcard expansion using filenames.
|
||||
|
||||
Note that fish does not fall through on case statements. Though the
|
||||
syntax may look a bit like C switch statements, it behaves more like
|
||||
the case stamantes of traditional shells.
|
||||
|
||||
Also note that command substitutions in a case statement will be
|
||||
evaluated even if it's body is not taken. This may seem
|
||||
counterintuitive at first, but it is unavoidable, since it would be
|
||||
impossible to know if a case command will evaluate to true before all
|
||||
forms of parameter expansion have been performed for the case command.
|
||||
|
||||
\subsection case-example Example
|
||||
|
||||
If the variable \$animal contains the name of an animal, the following
|
||||
@@ -27,9 +43,11 @@ switch $animal
|
||||
echo bird
|
||||
case shark trout stingray
|
||||
echo fish
|
||||
case '*'
|
||||
echo I have no idea what a $animal is
|
||||
end
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
If the above code was run with \$animal set to \c whale, the output would be \c mammal.
|
||||
If the above code was run with \c \$animal set to \c whale, the output would be \c mammal.
|
||||
</p>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
\subsection count-description Description
|
||||
|
||||
<tt>count</tt> returns the number of arguments that were passed to
|
||||
<tt>count</tt> prints the number of arguments that were passed to
|
||||
it. This is usually used to find out how many elements an environment
|
||||
variable array contains, but this is not the only potential usage for
|
||||
the count command.
|
||||
@@ -18,6 +18,9 @@ count program, and if the user uses a help option, this help page is
|
||||
displayed, but if a help option is contained inside of a variable or
|
||||
is the result of expansion, it will be passed on to the count program.
|
||||
|
||||
Count exits with a non-zero exit status if no arguments where passed
|
||||
to it, with zero otherwise.
|
||||
|
||||
\subsection count-example Example
|
||||
|
||||
<pre>
|
||||
|
||||
158
doc_src/doc.hdr
158
doc_src/doc.hdr
@@ -49,12 +49,12 @@ has to be used.
|
||||
Here is a list of some useful commands:
|
||||
|
||||
- \c cd, change the current directory
|
||||
- \c ls, list the contents of a directory
|
||||
- \c man, print a manual page
|
||||
- \c mv, move files
|
||||
- \c ls, list files and directories
|
||||
- \c man, display a manual page on the screen
|
||||
- \c mv, move (rename) files
|
||||
- \c cp, copy files
|
||||
- \c open, open files with the default application associated with each filetype
|
||||
- \c less, read the contents of files
|
||||
- \c less, list the contents of files
|
||||
|
||||
Commands and parameters are separated by the space character
|
||||
( ). Every command ends with either a newline (i.e. by pressing
|
||||
@@ -68,10 +68,10 @@ and directories in the current working directory, but by using the \c
|
||||
-l switch, the behaviour of ls is changed to not only display the
|
||||
filename, but also the size, permissions, owner and modification time
|
||||
of each file. Switches differ between commands and are documented in
|
||||
the manual page for each command. Some switches are very common
|
||||
though, for example '--help' will usually display a help text, '-i'
|
||||
will often turn on interactive prompting before taking action, while
|
||||
'-f' will turn it off.
|
||||
the manual page for each command. Some switches are common to most
|
||||
command though, for example '--help' will usually display a help text,
|
||||
'-i' will often turn on interactive prompting before taking action,
|
||||
while '-f' will turn it off.
|
||||
|
||||
\subsection quotes Quotes
|
||||
|
||||
@@ -116,6 +116,7 @@ these characters, so called escape sequences are provided. These are:
|
||||
- <code>'\\*'</code>, escapes the star character
|
||||
- <code>'\\?'</code>, escapes the question mark character
|
||||
- <code>'\\~'</code>, escapes the tilde character
|
||||
- <code>'\\%'</code>, escapes the percent character
|
||||
- <code>'\\#'</code>, escapes the hash character
|
||||
- <code>'\\('</code>, escapes the left parenthesis character
|
||||
- <code>'\\)'</code>, escapes the right parenthesis character
|
||||
@@ -144,7 +145,7 @@ a number called a file descriptor (FD). These are:
|
||||
The reason for providing for two output file descriptors is to allow
|
||||
separation of errors and warnings from regular program output.
|
||||
|
||||
Any file descriptor can be directed to a different output than it's
|
||||
Any file descriptor can be directed to a different output than its
|
||||
default through a simple mechanism called a redirection.
|
||||
|
||||
An example of a file redirection is <code> echo hello \>output.txt</code>,
|
||||
@@ -267,8 +268,8 @@ searches through any directories in the array variable
|
||||
loaded when needed. A function definition file must have a filename
|
||||
consisting of the name of the function plus the suffix '.fish'.
|
||||
|
||||
The default value for \$fish_function_path is ~/.fish.d/functions,
|
||||
/etc/fish.d/functions /usr/share/fish/functions. The exact path to the
|
||||
The default value for \$fish_function_path is \c ~/.fish.d/functions
|
||||
\c /etc/fish.d/functions \c /usr/share/fish/functions. The exact path to the
|
||||
last two of these may be slighly different depending on what install
|
||||
path prefix was chosen at configuration time. The rationale behind
|
||||
having three different directories is that the first one is for user
|
||||
@@ -488,7 +489,7 @@ becomes explicitly NOT a part of the variable name, even if it happens
|
||||
to be a legal variable name character. That's why '{$USER}san' looks
|
||||
for the variable '$USER' and not for the variable '$USERsan'. It's
|
||||
simply a case of one syntax lending itself nicely to solving an
|
||||
unrelated problem in it's spare time.
|
||||
unrelated problem in its spare time.
|
||||
|
||||
Variable expansion is the only type of expansion performed on double
|
||||
quoted strings. There is, however, an important difference in how
|
||||
@@ -618,8 +619,8 @@ Variables can be explicitly set to be universal with the \c -U or \c
|
||||
local with the \c -l or \c --local switch. The scoping rules when
|
||||
creating or updating a variable are:
|
||||
|
||||
-# If a variable is explicitly set to either universal, global or local, that setting will be honored
|
||||
-# If a variable is not explicitly set to be either universal, global or local, but has been previously defined, the variable scope is not changed
|
||||
-# If a variable is explicitly set to either universal, global or local, that setting will be honored. If a variable of the same name exists in a different scope, that variable will not be changed.
|
||||
-# If a variable is not explicitly set to be either universal, global or local, but has been previously defined, the variable scope is not changed.
|
||||
-# If a variable is not explicitly set to be either universal, global or local and has never before been defined, the variable will be local to the currently executing functions. If no function is executing, the variable will be global.
|
||||
|
||||
There may be many variables with the same name, but different scopes.
|
||||
@@ -644,7 +645,7 @@ echo $pirate
|
||||
\subsection variables-universal More on universal variables
|
||||
|
||||
Universal variables are variables that are shared between all the
|
||||
users fish sessions on the computer. Fish stores many of it's
|
||||
users fish sessions on the computer. Fish stores many of its
|
||||
configuration options as universal variables. This means that in order
|
||||
to change fish settings, all you have to do is change the variable
|
||||
value once, and it will be automatically updated for all sessions, and
|
||||
@@ -695,9 +696,9 @@ Variables can be explicitly set to be exported with the \c -x or \c
|
||||
switch. The exporting rules when creating or updating a variable are
|
||||
identical to the scoping rules for variables:
|
||||
|
||||
-# If a variable is explicitly set to either be exported or not exported, that setting will be honored
|
||||
-# If a variable is not explicitly set to be exported or not exported, but has been previously defined, the previous exporting rule for the variable is kept
|
||||
-# If a variable is not explicitly set to be either global or local and has never before been defined, the variable will not be exported
|
||||
-# If a variable is explicitly set to either be exported or not exported, that setting will be honored.
|
||||
-# If a variable is not explicitly set to be exported or not exported, but has been previously defined, the previous exporting rule for the variable is kept.
|
||||
-# If a variable is not explicitly set to be either global or local and has never before been defined, the variable will not be exported.
|
||||
|
||||
|
||||
\subsection variables-arrays Arrays
|
||||
@@ -745,6 +746,10 @@ set -e smurf[1]
|
||||
echo $smurf
|
||||
</pre>
|
||||
|
||||
If you specify a negative index when expanding or assigning to an
|
||||
array variable, the index will be calculated from the end of the
|
||||
array. For example, the index -1 means the last index of an array.
|
||||
|
||||
\subsection variables-special Special variables
|
||||
|
||||
The user can change the settings of \c fish by changing the values of
|
||||
@@ -752,28 +757,68 @@ certain environment variables.
|
||||
|
||||
- \c BROWSER, which is the users preferred web browser. If this variable is set, fish will use the specified browser instead of the system default browser to display the fish documentation.
|
||||
- \c CDPATH, which is an array of directories in which to search for the new directory for the \c cd builtin.
|
||||
- \c fish_color_normal, \c fish_color_command, \c fish_color_substitution, \c fish_color_redirection, \c fish_color_end, \c fish_color_error, \c fish_color_param, \c fish_color_comment, \c fish_color_match, \c fish_color_search_match, \c fish_color_cwd, \c fish_pager_color_prefix, \c fish_pager_color_completion, \c fish_pager_color_description and \c fish_pager_color_progress are used to change the color of various elements in \c fish. These variables are universal, i.e. when changing them, their new value will be used by all running fish sessions. The new value will also be retained when restarting fish.
|
||||
- A large number of variable starting with the prefixes \c fish_color and \c fish_pager_color. See <a href='#variables-color'>Variables for changing highlighting colors</a> for more information.
|
||||
- \c LANG, \c LC_ALL, \c LC_COLLATE, \c LC_CTYPE, \c LC_MESSAGES, \c LC_MONETARY, \c LC_NUMERIC and \c LC_TIME set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
|
||||
- \c PATH, which is an array of directories in which to search for commands
|
||||
- \c umask, which is the current file creation mask. The preferred way to change the umask variable is through the <a href="commands.html#umask">umask shellscript function</a>. An attempt to set umask to an invalid value will always fail.
|
||||
|
||||
\c fish also sends additional information to the user through the
|
||||
values of certain environment variables. The user can not change the
|
||||
values of these variables. They are:
|
||||
values of most of these variables.
|
||||
|
||||
- \c _, which is the name of the currently running command.
|
||||
- \c argv, which is an array of arguments to the shell or function. \c argv is only defined when inside a function call, or if fish was invoked with a list of arguments, like 'fish myscript.fish foo bar'. This variable can be changed by the user.
|
||||
- \c history, which is an array containing the last commands that where entered.
|
||||
- \c HOME, which is the users home directory. This variable can only be changed by the root user.
|
||||
- \c PWD, which is the current working directory.
|
||||
- \c status, which is the exit status of the last foreground job to exit. If a job contains pipelines, the status of the last command in the pipeline is the status for the job.
|
||||
- \c USER, which is the username. This variable can only be changed by the root user.
|
||||
- \c LANG, \c LC_ALL, \c LC_COLLATE, \c LC_CTYPE, \c LC_MESSAGES, \c LC_MONETARY, \c LC_NUMERIC and \c LC_TIME set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
|
||||
|
||||
Variables whose name are in uppercase are exported to the commands
|
||||
started by fish. This rule is not enforced by fish, but it is good
|
||||
coding practice to use casing to distinguish between exported and
|
||||
unexported variables. \c fish also uses several variables
|
||||
internally. Such variables are prefixed with the string __FISH or
|
||||
__fish. These should be ignored by the user.
|
||||
started by fish, those in lowercase are not exported. This rule is not
|
||||
enforced by fish, but it is good coding practice to use casing to
|
||||
distinguish between exported and unexported variables. \c fish also
|
||||
uses several variables internally. Such variables are prefixed with
|
||||
the string __FISH or __fish. These should be ignored by the user.
|
||||
|
||||
\subsection variables-color Variables for changing highlighting colors
|
||||
|
||||
The colors used by fish for syntax highlighting can be configured by
|
||||
changing the values of a various variables. The value of these
|
||||
variables can be one of the colors accepted by the <a
|
||||
href='commands.html#set_color'>set_color</a> command. The \c --bold
|
||||
or \c -b switches accepted by \c set_color are also accepted.
|
||||
|
||||
The following variables are available to change the highligting colors
|
||||
in fish:
|
||||
|
||||
- \c fish_color_normal, the default color
|
||||
- \c fish_color_command, the color for commands
|
||||
- \c fish_color_quote, the color for quoted blocks of text
|
||||
- \c fish_color_redirection, the color for IO redirections
|
||||
- \c fish_color_end, the color for process separators like ';' and '&'
|
||||
- \c fish_color_error, the color used to highlight potential errors
|
||||
- \c fish_color_param, the color for regular command parameters
|
||||
- \c fish_color_comment, the color used for code comments
|
||||
- \c fish_color_match, the color used to highlight matching parenthesis
|
||||
- \c fish_color_search_match, the color used to highlight history search matches
|
||||
- \c fish_color_operator, the color for parameter expansion operators like '*' and '~'
|
||||
- \c fish_color_escape, the color used to highlight character escapes like '\\n' and '\\x70'
|
||||
- \c fish_color_cwd, the color used for the current working directory in the default prompt
|
||||
|
||||
Additionally, the following variables are available to change the
|
||||
highlighting in the completion pager:
|
||||
|
||||
- \c fish_pager_color_prefix, the color of the prefix string, i.e. the string that is to be completed
|
||||
- \c fish_pager_color_completion, the color of the completion itself
|
||||
- \c fish_pager_color_description, the color of the completion description
|
||||
- \c fish_pager_color_progress, the color of the progress bar at the bottom left corner
|
||||
|
||||
Example:
|
||||
|
||||
To make errors highlighted and red, use:
|
||||
|
||||
<code>set fish_color_error red --bold</code>
|
||||
|
||||
\subsection variables-locale Locale variables
|
||||
|
||||
@@ -797,7 +842,7 @@ Many other shells have a large library of builtin commands. Most of
|
||||
these commands are also available as standalone commands, but have
|
||||
been implemented in the shell anyway for whatever reason. To avoid
|
||||
code duplication, and to avoid the confusion of subtly differing
|
||||
versions of the same command, \c fish only implementing builtins for
|
||||
versions of the same command, \c fish only implements builtins for
|
||||
actions which cannot be performed by a regular command.
|
||||
|
||||
\section bundle Commands bundled with fish
|
||||
@@ -1025,7 +1070,7 @@ Detected errors include:
|
||||
- Mismatched parenthesis
|
||||
|
||||
When the cursor is over a parenthesis or a quote, \c fish also
|
||||
highlights it's matching quote or parenthesis.
|
||||
highlights its matching quote or parenthesis.
|
||||
|
||||
To customize the syntax highlighting, you can set the environment
|
||||
variables \c fish_color_normal, \c fish_color_command, \c
|
||||
@@ -1116,7 +1161,7 @@ command.
|
||||
|
||||
If you install fish in your home directory, fish will not work
|
||||
correctly for any other user than yourself. This is because fish needs
|
||||
it's initalization files to function properly. To solve this
|
||||
its initalization files to function properly. To solve this
|
||||
problem, either copy the initialization files to each fish users home
|
||||
directory, or install them in /etc.
|
||||
|
||||
@@ -1176,7 +1221,7 @@ msgstr "%ls: Inget passande jobb\n"
|
||||
placeholders. These will be replaced by a value by fish at
|
||||
runtime. You must always take care to use exactly the same
|
||||
placeholders in the same order in your translation. (Actually, there
|
||||
are ways to avoid this, but they are to complicated for this short
|
||||
are ways to avoid this, but they are too complicated for this short
|
||||
introduction. See the full manual for the printf C function for more
|
||||
information.)
|
||||
|
||||
@@ -1190,16 +1235,14 @@ href='fish-users@lists.sf.net'>fish-users@lists.sf.net</a>.
|
||||
- Complete vi-mode key bindings
|
||||
- More completions (for example xterm, vim,
|
||||
konsole, gnome-terminal, dcop, cron,
|
||||
rlogin, telnet, rsync, arch, finger, nice, locate,
|
||||
rlogin, rsync, arch, finger, nice, locate,
|
||||
bibtex, aspell, xpdf,
|
||||
compress, wine, xmms, dig, wine, batch, cron,
|
||||
g++, javac, java, gcj, lpr, doxygen, whois, find)
|
||||
- Undo support
|
||||
- Check keybinding commands for output - if nothing has happened, don't repaint to reduce flicker
|
||||
- The jobs builtin should be able to give information on a specific job, such as the pids of the processes in the job
|
||||
- Syntax highlighting should mark cd to non-existing directories as an error
|
||||
- wait shellscript
|
||||
- Signal handler to save the history file before exiting from a signal
|
||||
- Support for the screen clipboard
|
||||
|
||||
|
||||
@@ -1218,7 +1261,6 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
|
||||
- Inclusion guards for the init files to make them evaluate only once, even if the user has installed fish both in /etc and in $HOME
|
||||
- Do not actually load/parse .fish_history, only mmap it and use some clever string handling. Should save ~150 kB of memory permanently, but is very hard to implement.
|
||||
- command specific wildcarding (use case * instead of case '*', etc.)
|
||||
- show the whole list of commands on using tab on an empty commandline
|
||||
- Map variables. (export only the values. When expanding with no key specified, expand to all values.)
|
||||
- Descriptions for variables using 'set -d'.
|
||||
- Parse errors should when possible honor IO redirections
|
||||
@@ -1242,9 +1284,6 @@ Older versions of Doxygen has bugs in the man-page generation which
|
||||
cause the builtin help to render incorrectly. Version 1.2.14 is known
|
||||
to have this problem.
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
/** \page design Design document
|
||||
|
||||
@@ -1284,7 +1323,7 @@ Examples:
|
||||
|
||||
- Here documents are too similar to using echo inside of a pipeline.
|
||||
- Subshells, command substitution and process substitution are strongly related. \c fish only supports command substitution, the others can be achived either using a block or the psub shellscript function.
|
||||
- Having both aliases and functions is confusing, especially since both of them have limitations and problems. \c fish sunctions have none of the drawbacks of either syntax.
|
||||
- Having both aliases and functions is confusing, especially since both of them have limitations and problems. \c fish functions have none of the drawbacks of either syntax.
|
||||
- The many Posix quoting styles are silly, especially \$''.
|
||||
|
||||
|
||||
@@ -1377,14 +1416,14 @@ Examples:
|
||||
|
||||
\subsection disc The law of discoverability
|
||||
|
||||
The shell should implement it's features in a way that makes them as
|
||||
easy as possible for the user to discover for her/himself.
|
||||
A program should be designed to make its features as
|
||||
easy as possible to discover for the user.
|
||||
|
||||
Rationale:
|
||||
|
||||
A program whose features are discoverable makes a new user into an
|
||||
expert in a shorter span of time, since the user will learn how to use
|
||||
the program simply by using it.
|
||||
A program whose features are discoverable turns a new user into an
|
||||
expert in a shorter span of time, since the user will become an expert
|
||||
on the program simply by using it.
|
||||
|
||||
The main benefit of a graphical program over a command line-based
|
||||
program is discoverability. In a graphical program, one can discover
|
||||
@@ -2398,14 +2437,15 @@ DAMAGES.
|
||||
- <a href='#faq-cd-autocomplete'>Why does the cd command autocompletion list the subdirectories of my home directory as completions?</a>
|
||||
- <a href='#faq-cd-implicit'>I accidentally entered a directory path and fish changed directory. What happened?</a>
|
||||
- <a href='#faq-open'>The open command doesn't work.</a>
|
||||
- <a href='#faq-default'>How do I make fish my default shell?</a>
|
||||
|
||||
<hr>
|
||||
|
||||
\section faq-cwd-symlink Why does cd, pwd and other fish commands always resolve symlinked directories to their canonical path?
|
||||
\section faq-cwd-symlink Why does cd, $PWD and and various fish commands always resolve symlinked directories to their canonical path?
|
||||
|
||||
<i>
|
||||
For example if I have the directory ~/images which is a symlink to
|
||||
~/Documents,/Images if I write 'cd doc', my prompt will say
|
||||
~/D/Images, not ~/images.
|
||||
For example if ~/images is a symlink to ~/Documents/Images, if I write
|
||||
'cd images', my prompt will say ~/D/Images, not ~/images.
|
||||
</i>
|
||||
|
||||
Because it is impossible to consistently keep symlinked directories
|
||||
@@ -2436,9 +2476,9 @@ silently fails in shells that don't resolve symlinked paths.
|
||||
|
||||
Because they are completions. In fish, if you specify a relative
|
||||
directory to the cd command, i.e. any path that does not start with
|
||||
'.' or '/', the environment variable CD_PATH will be examined, and any
|
||||
either './' or '/', the environment variable CDPATH will be examined, and any
|
||||
directories in this path is used as a base direcotry. To disable this
|
||||
feature, use the command <code>set CD_PATH .</code>.
|
||||
feature, write <code>set CDPATH .</code> on the commandline.
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -2462,5 +2502,25 @@ in a nonstandard location. Please contact the <a
|
||||
href='mailto:fish-users@lists.sf.net'>fish mailing list</a>, and
|
||||
hopefully this can be resolved.
|
||||
|
||||
\section faq-default How do I make fish my default shell?
|
||||
|
||||
If you installed fish manually (e.g. by compiling it, not by using a
|
||||
package manager), you first need to add fish to the list of shells by
|
||||
executing the following command (assuming you installed fish in
|
||||
/usr/local) as root:
|
||||
|
||||
<code>echo /usr/local/bin/fish >>/etc/shells</code>
|
||||
|
||||
If you installed a prepackaged version of fish, the package manager
|
||||
should have already done this for you.
|
||||
|
||||
In order to change your default shell, type:
|
||||
|
||||
<code>chsh -s /usr/bin/fish</code>
|
||||
|
||||
You may need to adjust the above path to e.g. /usr/local/bin/fish.
|
||||
|
||||
You will need to log out and back in again for the change to take
|
||||
effect.
|
||||
|
||||
*/
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
if CONDITION; COMMAND_TRUE [else; COMMAND_FALSE] end
|
||||
while CONDITION; COMMANDS; end
|
||||
switch VALUE; [case [WILDCARD...]; [COMMANDS...];...] end
|
||||
begin; [COMMANDS...] end
|
||||
</pre>
|
||||
|
||||
\subsection end-description Description
|
||||
<tt>end</tt> ends a block of commands. For more information, read the
|
||||
documentation for the block constructs, such as \c if, \c for and \
|
||||
while.
|
||||
|
||||
The \c end command does not change the current exit status.
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
The <tt>exit</tt> builtin causes fish to exit. If <tt>STATUS</tt> is
|
||||
supplied, it will be converted to an integer and used as the exit
|
||||
code. Otherwise the exit code will be 0.
|
||||
code. Otherwise the exit code will be that of the last command executed.
|
||||
|
||||
If exit is called while sourcing a file (using the <a
|
||||
href="#source">.</a> builtin) the rest of the file will be skipped,
|
||||
but the shell will not exit.
|
||||
but the shell itself will not exit.
|
||||
|
||||
@@ -20,6 +20,12 @@ When no clients are connected, fishd will automatically shut down.
|
||||
|
||||
~/.fishd.HOSTNAME permanent storage location for universal variable
|
||||
data. The data is stored as a set of \c set and \c set_export commands
|
||||
such as would be parsed by fishd. If an instance of fishd is running
|
||||
such as would be parsed by fishd. If an instance of fishd is running
|
||||
(which is generally the case), manual modifications to ~/.fishd.HOSTNAME
|
||||
will be lost.
|
||||
will be lost. Do NOT edit this file manually!
|
||||
|
||||
/tmp/fishd.socket.USERNAME the socket which fishd uses to communicate
|
||||
with all clients.
|
||||
|
||||
/tmp/fishd.log.USERNAME the fishd log file
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
\section function function - create a function
|
||||
|
||||
\subsection function-synopsis Synopsis
|
||||
<tt>function [OPTIONS] NAME; BODY; end </tt>
|
||||
<code>function [OPTIONS] NAME; BODY; end </code>
|
||||
|
||||
\subsection function-description Description
|
||||
|
||||
- \c -b or \c --key-binding specifies that the function is a key biding. Key binding functions work exactly like regular functions except that they can not be tab-completed, and may contain the '-' character.
|
||||
- <tt>-d DESCRIPTION</tt> or \c --description=DESCRIPTION is a description of what the function does, suitable as a completion description
|
||||
- <tt>-j PID</tt> or <tt> --on-job-exit PID</tt> tells fish to run this function when the job with group id PID exits
|
||||
- <tt>-p PID</tt> or <tt> --on-process-exit PID</tt> tells fish to run this function when the fish child process with process id PID exits
|
||||
- <tt>-s</tt> or <tt>--on-signal SIGSPEC</tt> tells fish to run this function when the signal SIGSPEC is delivered. SIGSPEC can be a signal number, or the signal name, such as SIGHUP (or just HUP)
|
||||
- <tt>-v</tt> or <tt>--on-variable VARIABLE_NAME</tt> tells fish to run this function when the variable VARIABLE_NAME changes value
|
||||
- <code>-d DESCRIPTION</code> or \c --description=DESCRIPTION is a description of what the function does, suitable as a completion description
|
||||
- <code>-j PID</code> or <code> --on-job-exit PID</code> tells fish to run this function when the job with group id PID exits. Instead of PID, the string 'caller' can be specified. This is only legal when in a command substitution, and will result in the handler being triggered by the exit of the job which created this command substitution.
|
||||
- <code>-p PID</code> or <code> --on-process-exit PID</code> tells fish to run this function when the fish child process with process id PID exits
|
||||
- <code>-s</code> or <code>--on-signal SIGSPEC</code> tells fish to run this function when the signal SIGSPEC is delivered. SIGSPEC can be a signal number, or the signal name, such as SIGHUP (or just HUP)
|
||||
- <code>-v</code> or <code>--on-variable VARIABLE_NAME</code> tells fish to run this function when the variable VARIABLE_NAME changes value
|
||||
|
||||
This builtin command is used to create a new function. A Function is a
|
||||
list of commands that will be executed when the name of the function
|
||||
@@ -22,7 +22,7 @@ function hi
|
||||
end
|
||||
</pre>
|
||||
|
||||
will write <tt>hello</tt> whenever the user enters \c hi.
|
||||
will write <code>hello</code> whenever the user enters \c hi.
|
||||
|
||||
If the user enters any additional arguments after the function, they
|
||||
are inserted into the environment variable <a href="index.html#variables-arrays">array</a> argv.
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
\section functions functions - print or erase functions
|
||||
|
||||
\subsection function-synopsis Synopsis
|
||||
<tt>functions [-e] FUNCTIONS...</tt>
|
||||
<code>functions [-e] FUNCTIONS...</code>
|
||||
|
||||
\subsection functions-description Description
|
||||
|
||||
This builtin command is used to print or erase functions.
|
||||
|
||||
- <tt>-e</tt> or <tt>--erase</tt> causes the specified functions to be erased.
|
||||
- <tt>-n</tt> or <tt>--names</tt> List only the names of all defined functions
|
||||
- <code>-a</code> or <code>--all</code> list all functions, even those whose name start with an underscore.
|
||||
- <code>-d DESCRIPTION</code> or <code>--description=DESCRIPTION</code> change the description of this function
|
||||
- <code>-e</code> or <code>--erase</code> causes the specified functions to be erased.
|
||||
- <code>-h</code> or <code>--help</code> display a help message and exit
|
||||
- <code>-n</code> or <code>--names</code> list only the names of all defined functions
|
||||
- <code>-q</code> or <code>--query</code> test if the specified functions exist. Does not output anything, but the builtins exit status is the number of functions specified that were not defined.
|
||||
|
||||
If \c functions is called with no arguments, the names and definition
|
||||
of all functions are printed, otherwise, the specified function
|
||||
definitions will be printed.
|
||||
The default behavior of \c functions when called with no arguments,
|
||||
is to print the names and definitions of all defined functions. If any
|
||||
non-switch parameters are given, only the definition of the specified
|
||||
functions are printed.
|
||||
|
||||
Automatically loaded functions can not be removed using functions
|
||||
-e. Either remove the definition file or change the
|
||||
$fish_function_path variable to remove autoloaded functions.
|
||||
|
||||
The exit status of the functions builtin is the number functions
|
||||
specified in the argument list that do not exist.
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
\section jobs jobs - print currently running jobs
|
||||
|
||||
\subsection jobs-synopsis
|
||||
<tt>jobs [OPTIONS] [PID]</tt>
|
||||
<code>jobs [OPTIONS] [PID]</code>
|
||||
|
||||
\subsection jobs-description Description
|
||||
The <tt>jobs</tt> builtin causes fish to print a list of the currently
|
||||
The <code>jobs</code> builtin causes fish to print a list of the currently
|
||||
running jobs and their status.
|
||||
|
||||
jobs accepts the following switches:
|
||||
|
||||
- <tt>-c</tt> or <tt>--command</tt> print the command name for each process in jobs
|
||||
- <tt>-g</tt> or <tt>--group</tt> only print the group id of each job
|
||||
- <tt>-l</tt> or <tt>--last</tt> only the last job to be started is printed
|
||||
- <tt>-p</tt> or <tt>--process</tt> print the process id for each process in all jobs
|
||||
- <code>-c</code> or <code>--command</code> print the command name for each process in jobs
|
||||
- <code>-g</code> or <code>--group</code> only print the group id of each job
|
||||
- <code>-h</code> or <code>--help</code> display a help message and exit
|
||||
- <code>-l</code> or <code>--last</code> only the last job to be started is printed
|
||||
- <code>-p</code> or <code>--pid</code> print the process id for each process in all jobs
|
||||
|
||||
On systems that supports this feature, jobs will print the CPU usage
|
||||
of each job since the last command was executed. The CPU usage is
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
- \c -f, \c --output-description the output will be the description of each mimetype
|
||||
- \c -a, \c --output-action the output will be the default action of each mimetype
|
||||
- \c -l, \c --launch launch the default action for the specified file(s)
|
||||
- \c -h, \c --help Display a help message and exit
|
||||
- \c -v, \c --version Display version number and exit
|
||||
- \c -h, \c --help display a help message and exit
|
||||
- \c -v, \c --version display version number and exit
|
||||
|
||||
The mimedb command is used to query the mimetype database and the
|
||||
.desktop files installed on the system in order to find information on
|
||||
a file. The information that mimedb can retrive includes the mimetype
|
||||
for a file, a description of the type and what its default action
|
||||
is. mimedb can also be used to launch the default action for this
|
||||
file.
|
||||
|
||||
|
||||
@@ -8,10 +8,16 @@
|
||||
|
||||
The \c or builtin is used to execute a command if the current exit status (as set by the last previous command) is non-zero
|
||||
|
||||
The or command does not change the current exit status.
|
||||
|
||||
\subsection or-example Example
|
||||
|
||||
The following code runs the \c make command to build a program, or if it fails, it runs <tt>make clean</tt>, which removes the files created by the build process
|
||||
The following code runs the \c make command to build a program, if the
|
||||
build succceds, the program is installed. If either step fails,
|
||||
<tt>make clean</tt> is run, which removes the files created by the
|
||||
build process
|
||||
|
||||
<pre>
|
||||
make; or make clean
|
||||
make; and make install; or make clean
|
||||
</pre>
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
The <tt>read</tt> builtin causes fish to read one line from standard
|
||||
input and store the result in one or more environment variables.
|
||||
|
||||
- <tt>-c CMD</tt> or <tt>--command=CMD</tt> specifies that the initial string in the interactive mode command buffer should be CMD.
|
||||
- <tt>-e</tt> or <tt>--export</tt> specifies that the variables will be exported to subshells.
|
||||
- <tt>-g</tt> or <tt>--global</tt> specifies that the variables will be made global.
|
||||
- <tt>-pPROMPT_CMD</tt> or <tt>--prompt=PROMPT_CMD</tt> specifies that the output of the shell command PROMPT_CMD should be used as the prompt for the interactive mode prompt. The default prompt command is <tt>set_color green; echo read; set_color normal; echo "> "</tt>.
|
||||
- <tt>-cCMD</tt> or <tt>--command=CMD</tt> specifies that the initial string in the interactive mode command buffer should be CMD.
|
||||
- <tt>-p PROMPT_CMD</tt> or <tt>--prompt=PROMPT_CMD</tt> specifies that the output of the shell command PROMPT_CMD should be used as the prompt for the interactive mode prompt. The default prompt command is <tt>set_color green; echo read; set_color normal; echo "> "</tt>.
|
||||
- <code>-u</code> or <code>--unexport</code> causes the specified environment not to be exported to child processes
|
||||
- <code>-U</code> or <code>--universal</code> causes the specified environment variable to be made universal. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
|
||||
- <code>-x</code> or <code>--export</code> causes the specified environment variable to be exported to child processes
|
||||
|
||||
Read starts by reading a single line of input from stdin, the line is
|
||||
then tokenized using the <tt>IFS</tt> environment variable. Each variable
|
||||
|
||||
@@ -2,18 +2,21 @@
|
||||
\section return return - Stop the innermost currently evaluated function
|
||||
|
||||
\subsection return-synopsis Synopsis
|
||||
<tt>function NAME; [COMMANDS...] break [STATUS]; [COMMANDS...] end</tt>
|
||||
<tt>function NAME; [COMMANDS...] return [STATUS]; [COMMANDS...] end</tt>
|
||||
|
||||
\subsection return-description Description The \c return builtin is
|
||||
used to halt a currently running function. It is usually added inside
|
||||
of a conditional block such as an <a href="#if">if</a> statement or a
|
||||
<a href="#switch">switch</a> statement to conditionally stop the
|
||||
executing function and return to the caller.
|
||||
\subsection return-description Description
|
||||
|
||||
- \c STATUS is the return status of the function. If unspecified, the status is set to 0.
|
||||
The \c return builtin is used to halt a currently running function. It
|
||||
is usually added inside of a conditional block such as an <a
|
||||
href="#if">if</a> statement or a <a href="#switch">switch</a>
|
||||
statement to conditionally stop the executing function and return to
|
||||
the caller, but it can also be used to specify the exit status of a
|
||||
function.
|
||||
|
||||
- \c STATUS is the return status of the function. If unspecified, the status is unchanged.
|
||||
|
||||
\subsection return-example Example
|
||||
The following code is an implementation of the false program as a fish builtin
|
||||
The following code is an implementation of the false command as a fish function
|
||||
<p>
|
||||
<pre>function false
|
||||
return 1
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
\section set set - Handle environment variables.
|
||||
|
||||
\subsection set-synopsis Synopsis
|
||||
<code>set [OPTIONS] [VARIABLE_NAME [VALUES...]]</code>
|
||||
<pre>set [SCOPE_OPTIONS]
|
||||
set [OPTIONS] VARIABLE_NAME VALUES...
|
||||
set [OPTIONS] VARIABLE_NAME[INDICES]... VALUES...
|
||||
set (-q | --query) [SCOPE_OPTIONS] VARIABLE_NAMES...
|
||||
set (-e | --erase) [SCOPE_OPTIONS] VARIABLE_NAME
|
||||
set (-e | --erase) [SCOPE_OPTIONS] VARIABLE_NAME[INDICES]... </pre>
|
||||
|
||||
The <code>set</code> builtin causes fish to assign the variable <code>VARIABLE_NAME</code> the values <code>VALUES...</code>.
|
||||
|
||||
\subsection set-description Description
|
||||
- <code>-e</code> or <code>--erase</code> causes the specified environment variable to be erased
|
||||
- <code>-g</code> or <code>--global</code> causes the specified environment variable to be made global. If this option is not supplied, the specified variable will disappear when the current block ends
|
||||
- <code>-l</code> or <code>--local</code> forces the specified environment variable to be made local to the current block, even if the variable already exists and is non-local
|
||||
- <code>-l</code> or <code>--local</code> forces the specified environment variable to be given a scope that is local to the current block, even if a variable with the given name exists and is non-local
|
||||
- <code>-g</code> or <code>--global</code> causes the specified environment variable to be given a global scope. Non-global variables disappear when the block they belong to ends
|
||||
- <code>-U</code> or <code>--universal</code> causes the specified environment variable to be given a universal scope. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
|
||||
- <code>-n</code> or <code>--names</code> List only the names of all defined variables
|
||||
- <code>-q</code> or <code>--query</code> test if the specified variable names are defined. Does not output anything, but the builtins exit status is the number of variables specified that were not defined.
|
||||
- <code>-u</code> or <code>--unexport</code> causes the specified environment not to be exported to child processes
|
||||
- <code>-U</code> or <code>--universal</code> causes the specified environment variable to be made universal. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
|
||||
- <code>-x</code> or <code>--export</code> causes the specified environment variable to be exported to child processes
|
||||
|
||||
If set is called with no arguments, the names and values of all
|
||||
@@ -20,22 +25,54 @@ environment variables are printed. If some of the scope or export
|
||||
flags have been given, only the variables matching the specified scope
|
||||
are printed.
|
||||
|
||||
If the \c -e or \c --erase option is specified, the variable
|
||||
specified by the following arguments will be erased
|
||||
|
||||
If a variable is set to more than one value, the variable will be an
|
||||
array with the specified elements. If a variable is set to zero
|
||||
elements, it will become an array with zero elements.
|
||||
|
||||
If the variable name is one or more array elements, such as
|
||||
<code>PATH[1 3 7]</code>, only those array elements specified will be
|
||||
changed.
|
||||
changed. When array indices are specified to set, multiple arguments
|
||||
may be used to specify additional indexes, e.g. <code>set PATH[1]
|
||||
PATH[4] /bin /sbin</code>. If you specify a negative index when
|
||||
expanding or assigning to an array variable, the index will be
|
||||
calculated from the end of the array. For example, the index -1 means
|
||||
the last index of an array.
|
||||
|
||||
The scoping rules when creating or updating a variable are:
|
||||
|
||||
-# If a variable is explicitly set to either universal, global or local, that setting will be honored. If a variable of the same name exists in a different scope, that variable will not be changed.
|
||||
-# If a variable is not explicitly set to be either universal, global or local, but has been previously defined, the previos variable scope is used.
|
||||
-# If a variable is not explicitly set to be either universal, global or local and has never before been defined, the variable will be local to the currently executing functions. If no function is executing, the variable will be global.
|
||||
|
||||
The exporting rules when creating or updating a variable are identical
|
||||
to the scoping rules for variables:
|
||||
|
||||
-# If a variable is explicitly set to either be exported or not exported, that setting will be honored.
|
||||
-# If a variable is not explicitly set to be exported or not exported, but has been previously defined, the previous exporting rule for the variable is kept.
|
||||
-# If a variable is not explicitly set to be either global or local and has never before been defined, the variable will not be exported.
|
||||
|
||||
In query mode, the scope to be examined can be specified.
|
||||
|
||||
In erase mode, if variable indices are specified, only the specified
|
||||
slices of the array variable will be erased. When erasing an entire
|
||||
variable (i.e. no slicing), the scope of the variable to be erased can
|
||||
be specified. That way, a global variable can be erased even if a
|
||||
local variable with the same name exists. Scope can not be specified
|
||||
when erasing a slice of an array. The innermost scope is always used.
|
||||
|
||||
The set command requires all switch arguments to come before any
|
||||
non-switch arguments. For example, <code>set flags -l</code> will have
|
||||
the effect of setting the value of the variable <code>flags</code> to
|
||||
'-l', not making the variable local.
|
||||
|
||||
In assignment mode, set exits with an exit status of zero it the
|
||||
variable assignments where sucessfully performed, with a non-zero exit
|
||||
status otherwise. In query mode, the exit status is the number of
|
||||
variables that where not found. In erase mode, set exits with a zero
|
||||
exit status in case of success, with a non-zero exit status if the
|
||||
commandline was invalid, if the variable was write-protected or if the
|
||||
variable did not exist.
|
||||
|
||||
\subsection set-example Example
|
||||
|
||||
<code>set -xg</code> will print all global, exported variables.
|
||||
|
||||
@@ -10,10 +10,11 @@ Change the foreground and/or background color of the terminal.
|
||||
COLOR is one of black, red, green, brown, yellow, blue, magenta,
|
||||
purple, cyan, white and normal.
|
||||
|
||||
- \c -c, \c --print-colors Prints a list of all valid color names
|
||||
- \c -b, \c --background Set the background color
|
||||
- \c -o, \c --bold Set bold or extra bright mode
|
||||
- \c -c, \c --print-colors Prints a list of all valid color names
|
||||
- \c -h, \c --help Display help message and exit
|
||||
- \c -o, \c --bold Set bold or extra bright mode
|
||||
- \c -u, \c --underline Set underlined mode
|
||||
- \c -v, \c --version Display version and exit
|
||||
|
||||
|
||||
@@ -25,3 +26,6 @@ color set. On such terminals, <code>set_color white</code> will result
|
||||
in a grey font color, while <code>set_color --bold white</code> will
|
||||
result in a white font color.
|
||||
|
||||
Not all terminal emulators support all these features. This is not a
|
||||
bug in set_color but a missing feature in the terminal emulator.
|
||||
|
||||
|
||||
@@ -8,7 +8,19 @@
|
||||
|
||||
The \c switch statement is used to perform one of several blocks of
|
||||
commands depending on whether a specified value equals one of several
|
||||
wildcarded values.
|
||||
wildcarded values. The \c case statement is used together with the \c
|
||||
switch statement in order to determine which block should be
|
||||
performed.
|
||||
|
||||
Each \c case command is given one or more parameter. The first \c case
|
||||
command with a parameter that matches the string specified in the
|
||||
switch command will be evaluated. \c case parameters may contain
|
||||
wildcards. These need to be escaped or quoted in order to avoid
|
||||
regular wildcard expansion using filenames.
|
||||
|
||||
Note that fish does not fall through on case statements. Though the
|
||||
syntax may look a bit like C switch statements, it behaves more like
|
||||
the case stamantes of traditional shells.
|
||||
|
||||
\subsection switch-example Example
|
||||
|
||||
@@ -26,12 +38,14 @@ switch $animal
|
||||
echo bird
|
||||
case shark trout stingray
|
||||
echo fish
|
||||
case '*'
|
||||
echo I have no idea what a $animal is
|
||||
end
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
If the above code was run with \$animal set to \c whale, the output
|
||||
If the above code was run with \c \$animal set to \c whale, the output
|
||||
would be \c mammal.
|
||||
|
||||
</p>
|
||||
|
||||
@@ -15,6 +15,9 @@ With no options, indicate how each name would be interpreted if used as a comman
|
||||
- \c -p or \c --path either return the name of the disk file that would be executed if name were specified as a command name, or nothing if 'type -t name' would not return 'file'
|
||||
- \c -P or \c --force-path either return the name of the disk file that would be executed if name were specified as a command name, or nothing no file with the specified name could be found in the PATH
|
||||
|
||||
\c type returns a zero exit status if the specified command was found,
|
||||
otherwise the exit status is one.
|
||||
|
||||
\subsection type-example Example
|
||||
|
||||
<tt>type fg</tt> outputs the string 'fg is a shell builtin'.
|
||||
|
||||
196
env.c
196
env.c
@@ -55,7 +55,7 @@
|
||||
/**
|
||||
Command used to start fishd
|
||||
*/
|
||||
#define FISHD_CMD L"if which fishd >/dev/null; fishd ^/tmp/fishd.%s.log; end"
|
||||
#define FISHD_CMD L"if which fishd >/dev/null; fishd ^/tmp/fishd.log.%s; end"
|
||||
|
||||
/**
|
||||
Value denoting a null string
|
||||
@@ -104,7 +104,11 @@ typedef struct env_node
|
||||
typedef struct var_entry
|
||||
{
|
||||
int export; /**< Whether the variable should be exported */
|
||||
wchar_t val[0]; /**< The value of the variable */
|
||||
#if __STDC_VERSION__ < 199901L
|
||||
wchar_t val[1]; /**< The value of the variable */
|
||||
#else
|
||||
wchar_t val[]; /**< The value of the variable */
|
||||
#endif
|
||||
}
|
||||
var_entry_t;
|
||||
|
||||
@@ -188,7 +192,7 @@ static const wchar_t *locale_variable[] =
|
||||
/**
|
||||
Free hash key and hash value
|
||||
*/
|
||||
static void clear_hash_entry( const void *key, const void *data )
|
||||
static void clear_hash_entry( void *key, void *data )
|
||||
{
|
||||
var_entry_t *entry = (var_entry_t *)data;
|
||||
if( entry->export )
|
||||
@@ -313,9 +317,6 @@ static void handle_locale()
|
||||
|
||||
if( is_interactive )
|
||||
{
|
||||
complete_destroy();
|
||||
complete_init();
|
||||
|
||||
debug( 0, _(L"Changing language to English") );
|
||||
}
|
||||
}
|
||||
@@ -396,7 +397,7 @@ static void setup_path()
|
||||
al_init( &l );
|
||||
|
||||
if( path )
|
||||
expand_variable_array( path, &l );
|
||||
tokenize_variable_array( path, &l );
|
||||
|
||||
for( j=0; path_el[j]; j++ )
|
||||
{
|
||||
@@ -435,14 +436,14 @@ static void setup_path()
|
||||
|
||||
sb_destroy( &b );
|
||||
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_foreach( &l, &free );
|
||||
path = env_get( L"PATH" );
|
||||
al_truncate( &l, 0 );
|
||||
expand_variable_array( path, &l );
|
||||
tokenize_variable_array( path, &l );
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_foreach( &l, &free );
|
||||
al_destroy( &l );
|
||||
}
|
||||
|
||||
@@ -608,9 +609,9 @@ static env_node_t *env_get_node( const wchar_t *key )
|
||||
return 0;
|
||||
}
|
||||
|
||||
void env_set( const wchar_t *key,
|
||||
const wchar_t *val,
|
||||
int var_mode )
|
||||
int env_set( const wchar_t *key,
|
||||
const wchar_t *val,
|
||||
int var_mode )
|
||||
{
|
||||
int free_val = 0;
|
||||
var_entry_t *entry;
|
||||
@@ -623,10 +624,12 @@ void env_set( const wchar_t *key,
|
||||
event_t ev;
|
||||
int is_universal = 0;
|
||||
|
||||
CHECK( key, ENV_INVALID );
|
||||
|
||||
if( (var_mode & ENV_USER ) &&
|
||||
hash_get( &env_read_only, key ) )
|
||||
{
|
||||
return;
|
||||
return ENV_PERM;
|
||||
}
|
||||
|
||||
if( wcscmp( key, L"umask" ) == 0)
|
||||
@@ -650,7 +653,7 @@ void env_set( const wchar_t *key,
|
||||
/*
|
||||
Do not actually create a umask variable, on env_get, it will be calculated dynamically
|
||||
*/
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -749,7 +752,7 @@ void env_set( const wchar_t *key,
|
||||
node = top;
|
||||
while( node->next && !node->new_scope )
|
||||
node = node->next;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -757,7 +760,7 @@ void env_set( const wchar_t *key,
|
||||
if( !done )
|
||||
{
|
||||
void *k, *v;
|
||||
hash_remove( &node->env, key, (const void **)&k, (const void **)&v );
|
||||
hash_remove( &node->env, key, &k, &v );
|
||||
free( k );
|
||||
free( v );
|
||||
|
||||
@@ -797,6 +800,7 @@ void env_set( const wchar_t *key,
|
||||
|
||||
al_init( &ev.arguments );
|
||||
al_push( &ev.arguments, L"VARIABLE" );
|
||||
al_push( &ev.arguments, L"SET" );
|
||||
al_push( &ev.arguments, key );
|
||||
|
||||
// debug( 1, L"env_set: fire events on variable %ls", key );
|
||||
@@ -809,19 +813,24 @@ void env_set( const wchar_t *key,
|
||||
{
|
||||
handle_locale();
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Attempt to remove/free the specified key/value pair from the
|
||||
specified hash table.
|
||||
|
||||
\return zero if the variable was not found, non-zero otherwise
|
||||
*/
|
||||
static int try_remove( env_node_t *n,
|
||||
const wchar_t *key )
|
||||
const wchar_t *key,
|
||||
int var_mode )
|
||||
{
|
||||
const void *old_key_void, *old_val_void;
|
||||
void *old_key_void, *old_val_void;
|
||||
wchar_t *old_key, *old_val;
|
||||
|
||||
if( n == 0 )
|
||||
return 0;
|
||||
|
||||
@@ -846,29 +855,72 @@ static int try_remove( env_node_t *n,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( var_mode & ENV_LOCAL )
|
||||
return 0;
|
||||
|
||||
if( n->new_scope )
|
||||
return try_remove( global_env, key );
|
||||
return try_remove( global_env, key, var_mode );
|
||||
else
|
||||
return try_remove( n->next, key );
|
||||
return try_remove( n->next, key, var_mode );
|
||||
}
|
||||
|
||||
|
||||
void env_remove( const wchar_t *key, int var_mode )
|
||||
int env_remove( const wchar_t *key, int var_mode )
|
||||
{
|
||||
env_node_t *first_node;
|
||||
int erased = 0;
|
||||
|
||||
CHECK( key, 1 );
|
||||
|
||||
if( (var_mode & ENV_USER ) &&
|
||||
hash_get( &env_read_only, key ) )
|
||||
{
|
||||
return;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if( !try_remove( top, key ) )
|
||||
first_node = top;
|
||||
|
||||
if( ! (var_mode & ENV_UNIVERSAL ) )
|
||||
{
|
||||
env_universal_remove( key );
|
||||
|
||||
if( var_mode & ENV_GLOBAL )
|
||||
{
|
||||
first_node = global_env;
|
||||
}
|
||||
|
||||
if( try_remove( first_node, key, var_mode ) )
|
||||
{
|
||||
event_t ev;
|
||||
|
||||
ev.type=EVENT_VARIABLE;
|
||||
ev.param1.variable=key;
|
||||
ev.function_name=0;
|
||||
|
||||
al_init( &ev.arguments );
|
||||
al_push( &ev.arguments, L"VARIABLE" );
|
||||
al_push( &ev.arguments, L"ERASE" );
|
||||
al_push( &ev.arguments, key );
|
||||
|
||||
event_fire( &ev );
|
||||
|
||||
al_destroy( &ev.arguments );
|
||||
erased = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( !erased &&
|
||||
!(var_mode & ENV_GLOBAL) &&
|
||||
!(var_mode & ENV_LOCAL) )
|
||||
{
|
||||
erased = !env_universal_remove( key );
|
||||
}
|
||||
|
||||
if( is_locale( key ) )
|
||||
{
|
||||
handle_locale();
|
||||
|
||||
}
|
||||
|
||||
return !erased;
|
||||
}
|
||||
|
||||
|
||||
@@ -878,6 +930,8 @@ wchar_t *env_get( const wchar_t *key )
|
||||
env_node_t *env = top;
|
||||
wchar_t *item;
|
||||
|
||||
CHECK( key, 0 );
|
||||
|
||||
if( wcscmp( key, L"history" ) == 0 )
|
||||
{
|
||||
wchar_t *current;
|
||||
@@ -970,40 +1024,62 @@ wchar_t *env_get( const wchar_t *key )
|
||||
return item;
|
||||
}
|
||||
|
||||
int env_exist( const wchar_t *key )
|
||||
int env_exist( const wchar_t *key, int mode )
|
||||
{
|
||||
var_entry_t *res;
|
||||
env_node_t *env = top;
|
||||
wchar_t *item;
|
||||
|
||||
if( hash_get( &env_read_only, key ) || hash_get( &env_electric, key ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
while( env != 0 )
|
||||
env_node_t *env;
|
||||
wchar_t *item=0;
|
||||
|
||||
CHECK( key, 0 );
|
||||
|
||||
/*
|
||||
Read only variables all exist, and they are all global. A local
|
||||
version can not exist.
|
||||
*/
|
||||
if( ! (mode & ENV_LOCAL) && ! (mode & ENV_UNIVERSAL) )
|
||||
{
|
||||
res = (var_entry_t *) hash_get( &env->env,
|
||||
key );
|
||||
if( res != 0 )
|
||||
if( hash_get( &env_read_only, key ) || hash_get( &env_electric, key ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( env->new_scope )
|
||||
env = global_env;
|
||||
else
|
||||
env = env->next;
|
||||
}
|
||||
if( !proc_had_barrier)
|
||||
}
|
||||
|
||||
if( ! (mode & ENV_UNIVERSAL) )
|
||||
{
|
||||
proc_had_barrier=1;
|
||||
env_universal_barrier();
|
||||
env = (mode & ENV_GLOBAL)?global_env:top;
|
||||
|
||||
while( env != 0 )
|
||||
{
|
||||
res = (var_entry_t *) hash_get( &env->env,
|
||||
key );
|
||||
if( res != 0 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( mode & ENV_LOCAL )
|
||||
break;
|
||||
|
||||
if( env->new_scope )
|
||||
env = global_env;
|
||||
else
|
||||
env = env->next;
|
||||
}
|
||||
}
|
||||
|
||||
item = env_universal_get( key );
|
||||
if( ! (mode & ENV_LOCAL) && ! (mode & ENV_GLOBAL) )
|
||||
{
|
||||
if( !proc_had_barrier)
|
||||
{
|
||||
proc_had_barrier=1;
|
||||
env_universal_barrier();
|
||||
}
|
||||
|
||||
item = env_universal_get( key );
|
||||
|
||||
}
|
||||
return item != 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1085,8 +1161,8 @@ void env_pop()
|
||||
Function used with hash_foreach to insert keys of one table into
|
||||
another
|
||||
*/
|
||||
static void add_key_to_hash( const void *key,
|
||||
const void *data,
|
||||
static void add_key_to_hash( void *key,
|
||||
void *data,
|
||||
void *aux )
|
||||
{
|
||||
var_entry_t *e = (var_entry_t *)data;
|
||||
@@ -1100,7 +1176,7 @@ static void add_key_to_hash( const void *key,
|
||||
/**
|
||||
Add key to hashtable
|
||||
*/
|
||||
static void add_to_hash( const void *k, void *aux )
|
||||
static void add_to_hash( void *k, void *aux )
|
||||
{
|
||||
hash_put( (hash_table_t *)aux,
|
||||
k,
|
||||
@@ -1110,8 +1186,8 @@ static void add_to_hash( const void *k, void *aux )
|
||||
/**
|
||||
Add key to list
|
||||
*/
|
||||
static void add_key_to_list( const void * key,
|
||||
const void * val,
|
||||
static void add_key_to_list( void * key,
|
||||
void * val,
|
||||
void *aux )
|
||||
{
|
||||
al_push( (array_list_t *)aux, key );
|
||||
@@ -1127,6 +1203,8 @@ void env_get_names( array_list_t *l, int flags )
|
||||
hash_table_t names;
|
||||
env_node_t *n=top;
|
||||
|
||||
CHECK( l, );
|
||||
|
||||
get_names_show_exported =
|
||||
flags & ENV_EXPORT|| (!(flags & ENV_UNEXPORT));
|
||||
get_names_show_unexported =
|
||||
@@ -1195,7 +1273,7 @@ void env_get_names( array_list_t *l, int flags )
|
||||
/**
|
||||
Function used by env_export_arr to iterate over hashtable of variables
|
||||
*/
|
||||
static void export_func1( const void *k, const void *v, void *aux )
|
||||
static void export_func1( void *k, void *v, void *aux )
|
||||
{
|
||||
var_entry_t *val_entry = (var_entry_t *)v;
|
||||
if( val_entry->export )
|
||||
@@ -1211,7 +1289,7 @@ static void export_func1( const void *k, const void *v, void *aux )
|
||||
/**
|
||||
Function used by env_export_arr to iterate over hashtable of variables
|
||||
*/
|
||||
static void export_func2( const void *k, const void *v, void *aux )
|
||||
static void export_func2( void *k, void *v, void *aux )
|
||||
{
|
||||
wchar_t *key = (wchar_t *)k;
|
||||
wchar_t *val = (wchar_t *)v;
|
||||
@@ -1225,7 +1303,7 @@ static void export_func2( const void *k, const void *v, void *aux )
|
||||
|
||||
if( !ks || !vs )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1248,7 +1326,7 @@ static void export_func2( const void *k, const void *v, void *aux )
|
||||
free( vs );
|
||||
}
|
||||
|
||||
char **env_export_arr( int recalc)
|
||||
char **env_export_arr( int recalc )
|
||||
{
|
||||
if( recalc && !proc_had_barrier)
|
||||
{
|
||||
|
||||
29
env.h
29
env.h
@@ -41,6 +41,16 @@
|
||||
*/
|
||||
#define ENV_UNIVERSAL 32
|
||||
|
||||
/**
|
||||
Error code for trying to alter read-only variable
|
||||
*/
|
||||
enum{
|
||||
ENV_PERM = 1,
|
||||
ENV_INVALID
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/**
|
||||
Initialize environment variable data
|
||||
*/
|
||||
@@ -61,9 +71,15 @@ void env_destroy();
|
||||
\param val The value
|
||||
\param mode The type of the variable. Can be any combination of ENV_GLOBAL, ENV_LOCAL, ENV_EXPORT and ENV_USER. If mode is zero, the current variable space is searched and the current mode is used. If no current variable with the same name is found, ENV_LOCAL is assumed.
|
||||
|
||||
\returns 0 on suicess or an error code on failiure.
|
||||
|
||||
The current error codes are:
|
||||
|
||||
* ENV_PERM, can only be returned when setting as a user, e.g. ENV_USER is set. This means that the user tried to change a read-only variable.
|
||||
* ENV_INVALID, the variable name or mode was invalid
|
||||
*/
|
||||
|
||||
void env_set( const wchar_t *key,
|
||||
int env_set( const wchar_t *key,
|
||||
const wchar_t *val,
|
||||
int mode );
|
||||
|
||||
@@ -80,16 +96,21 @@ wchar_t *env_get( const wchar_t *key );
|
||||
/**
|
||||
Returns 1 if the specified key exists. This can't be reliable done
|
||||
using env_get, since env_get returns null for 0-element arrays
|
||||
|
||||
\param key The name of the variable to remove
|
||||
\param mode the scope to search in. All scopes are searched if unset
|
||||
*/
|
||||
int env_exist( const wchar_t *key );
|
||||
int env_exist( const wchar_t *key, int mode );
|
||||
|
||||
/**
|
||||
Remove environemnt variable
|
||||
|
||||
\param key The name of the variable to remove
|
||||
\param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If this is a user request, read-only variables can not be removed.
|
||||
\param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If this is a user request, read-only variables can not be removed. The mode may also specify the scope of the variable that should be erased.
|
||||
|
||||
\return zero if the variable existed, and non-zero if the variable did not exist
|
||||
*/
|
||||
void env_remove( const wchar_t *key, int mode );
|
||||
int env_remove( const wchar_t *key, int mode );
|
||||
|
||||
/**
|
||||
Push the variable stack. Used for implementing local variables for functions and for-loops.
|
||||
|
||||
@@ -182,7 +182,12 @@ static void check_connection()
|
||||
if( env_universal_server.killme )
|
||||
{
|
||||
debug( 3, L"Lost connection to universal variable server." );
|
||||
close( env_universal_server.fd );
|
||||
|
||||
if( close( env_universal_server.fd ) )
|
||||
{
|
||||
wperror( L"close" );
|
||||
}
|
||||
|
||||
env_universal_server.fd = -1;
|
||||
env_universal_server.killme=0;
|
||||
sb_clear( &env_universal_server.input );
|
||||
@@ -252,7 +257,12 @@ void env_universal_destroy()
|
||||
}
|
||||
try_send_all( &env_universal_server );
|
||||
}
|
||||
close( env_universal_server.fd );
|
||||
|
||||
if( close( env_universal_server.fd ) )
|
||||
{
|
||||
wperror( L"close" );
|
||||
}
|
||||
|
||||
env_universal_server.fd =-1;
|
||||
q_destroy( &env_universal_server.unsent );
|
||||
sb_destroy( &env_universal_server.input );
|
||||
@@ -295,16 +305,20 @@ wchar_t *env_universal_get( const wchar_t *name )
|
||||
{
|
||||
if( !init)
|
||||
return 0;
|
||||
|
||||
if( !name )
|
||||
return 0;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
debug( 3, L"env_universal_get( \"%ls\" )", name );
|
||||
return env_universal_common_get( name );
|
||||
}
|
||||
|
||||
int env_universal_get_export( const wchar_t *name )
|
||||
{
|
||||
if( !init)
|
||||
return 0;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
debug( 3, L"env_universal_get_export()" );
|
||||
return env_universal_common_get_export( name );
|
||||
}
|
||||
@@ -377,7 +391,9 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
|
||||
|
||||
if( !init )
|
||||
return;
|
||||
|
||||
|
||||
CHECK( name, );
|
||||
|
||||
debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value );
|
||||
|
||||
msg = create_message( export?SET_EXPORT:SET,
|
||||
@@ -395,11 +411,17 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
|
||||
env_universal_barrier();
|
||||
}
|
||||
|
||||
void env_universal_remove( const wchar_t *name )
|
||||
int env_universal_remove( const wchar_t *name )
|
||||
{
|
||||
int res;
|
||||
|
||||
message_t *msg;
|
||||
if( !init )
|
||||
return;
|
||||
return 1;
|
||||
|
||||
CHECK( name, 1 );
|
||||
|
||||
res = !env_universal_common_get( name );
|
||||
|
||||
debug( 3,
|
||||
L"env_universal_remove( \"%ls\" )",
|
||||
@@ -409,12 +431,17 @@ void env_universal_remove( const wchar_t *name )
|
||||
msg->count=1;
|
||||
q_put( &env_universal_server.unsent, msg );
|
||||
env_universal_barrier();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void env_universal_get_names( array_list_t *l,
|
||||
int show_exported,
|
||||
int show_unexported )
|
||||
{
|
||||
if( !init )
|
||||
return;
|
||||
|
||||
env_universal_common_get_names( l,
|
||||
show_exported,
|
||||
show_unexported );
|
||||
|
||||
@@ -40,8 +40,10 @@ int env_universal_get_export( const wchar_t *name );
|
||||
void env_universal_set( const wchar_t *name, const wchar_t *val, int export );
|
||||
/**
|
||||
Erase a universal variable
|
||||
|
||||
\return zero if the variable existed, and non-zero if the variable did not exist
|
||||
*/
|
||||
void env_universal_remove( const wchar_t *name );
|
||||
int env_universal_remove( const wchar_t *name );
|
||||
|
||||
/**
|
||||
Read all available messages from the server.
|
||||
|
||||
@@ -116,8 +116,8 @@ void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const w
|
||||
/**
|
||||
Free both key and data
|
||||
*/
|
||||
static void erase( const void *key,
|
||||
const void *data )
|
||||
static void erase( void *key,
|
||||
void *data )
|
||||
{
|
||||
free( (void *)key );
|
||||
free( (void *)data );
|
||||
@@ -205,8 +205,8 @@ static void remove_entry( wchar_t *name )
|
||||
void *k, *v;
|
||||
hash_remove( &env_universal_var,
|
||||
name,
|
||||
(const void **)&k,
|
||||
(const void **)&v );
|
||||
&k,
|
||||
&v );
|
||||
free( k );
|
||||
free( v );
|
||||
}
|
||||
@@ -261,7 +261,7 @@ static void parse_message( wchar_t *msg,
|
||||
var_uni_entry_t *entry =
|
||||
malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) );
|
||||
if( !entry )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
entry->export=export;
|
||||
|
||||
wcscpy( entry->val, val );
|
||||
@@ -433,7 +433,7 @@ message_t *create_message( int type,
|
||||
msg = malloc( sizeof( message_t ) + sz );
|
||||
|
||||
if( !msg )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
strcpy( msg->body, (type==SET?SET_MBS:SET_EXPORT_MBS) );
|
||||
strcat( msg->body, " " );
|
||||
@@ -453,7 +453,7 @@ message_t *create_message( int type,
|
||||
msg = malloc( sizeof( message_t ) + sz );
|
||||
|
||||
if( !msg )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
strcpy( msg->body, ERASE_MBS " " );
|
||||
strcat( msg->body, key );
|
||||
@@ -466,7 +466,7 @@ message_t *create_message( int type,
|
||||
msg = malloc( sizeof( message_t ) +
|
||||
strlen( BARRIER_MBS ) +2);
|
||||
if( !msg )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
strcpy( msg->body, BARRIER_MBS "\n" );
|
||||
break;
|
||||
}
|
||||
@@ -476,7 +476,7 @@ message_t *create_message( int type,
|
||||
msg = malloc( sizeof( message_t ) +
|
||||
strlen( BARRIER_REPLY_MBS ) +2);
|
||||
if( !msg )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
strcpy( msg->body, BARRIER_REPLY_MBS "\n" );
|
||||
break;
|
||||
}
|
||||
@@ -498,8 +498,8 @@ message_t *create_message( int type,
|
||||
Function used with hash_foreach to insert keys of one table into
|
||||
another
|
||||
*/
|
||||
static void add_key_to_hash( const void *key,
|
||||
const void *data,
|
||||
static void add_key_to_hash( void *key,
|
||||
void *data,
|
||||
void *aux )
|
||||
{
|
||||
var_uni_entry_t *e = (var_uni_entry_t *)data;
|
||||
@@ -546,8 +546,8 @@ int env_universal_common_get_export( const wchar_t *name )
|
||||
\param v the variable value
|
||||
\param q the queue to add the message to
|
||||
*/
|
||||
static void enqueue( const void *k,
|
||||
const void *v,
|
||||
static void enqueue( void *k,
|
||||
void *v,
|
||||
void *q)
|
||||
{
|
||||
const wchar_t *key = (const wchar_t *)k;
|
||||
|
||||
@@ -68,8 +68,12 @@ end
|
||||
set_default fish_color_normal normal
|
||||
set_default fish_color_command green
|
||||
set_default fish_color_redirection normal
|
||||
set_default fish_color_comment brown
|
||||
set_default fish_color_error red
|
||||
set_default fish_color_comment red
|
||||
set_default fish_color_error red --bold
|
||||
set_default fish_color_escape cyan
|
||||
set_default fish_color_operator cyan
|
||||
set_default fish_color_quote brown
|
||||
set_default fish_color_valid_path --underline
|
||||
|
||||
set_default fish_color_cwd green
|
||||
|
||||
|
||||
34
event.c
34
event.c
@@ -57,7 +57,7 @@ typedef struct
|
||||
active, which is the one that new events is written to. The inactive
|
||||
one contains the events that are currently beeing performed.
|
||||
*/
|
||||
static signal_list_t sig_list[2];
|
||||
static signal_list_t sig_list[]={{0,0},{0,0}};
|
||||
|
||||
/**
|
||||
The index of sig_list that is the list of signals currently written to
|
||||
@@ -140,7 +140,7 @@ static event_t *event_copy( event_t *event, int copy_arguments )
|
||||
{
|
||||
event_t *e = malloc( sizeof( event_t ) );
|
||||
if( !e )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
memcpy( e, event, sizeof(event_t));
|
||||
|
||||
if( e->function_name )
|
||||
@@ -196,6 +196,9 @@ static int event_is_blocked( event_t *e )
|
||||
|
||||
const wchar_t *event_get_desc( event_t *e )
|
||||
{
|
||||
|
||||
CHECK( e, 0 );
|
||||
|
||||
if( !get_desc_buff )
|
||||
{
|
||||
get_desc_buff=sb_halloc( global_context );
|
||||
@@ -253,6 +256,8 @@ void event_add_handler( event_t *event )
|
||||
{
|
||||
event_t *e;
|
||||
|
||||
CHECK( event, );
|
||||
|
||||
e = event_copy( event, 0 );
|
||||
|
||||
if( !events )
|
||||
@@ -272,14 +277,19 @@ void event_remove( event_t *criterion )
|
||||
array_list_t *new_list=0;
|
||||
event_t e;
|
||||
|
||||
CHECK( criterion, );
|
||||
|
||||
/*
|
||||
Because of concurrency issues, env_remove does not actually free
|
||||
any events - instead it simply moves all events that should be
|
||||
removed from the event list to the killme list.
|
||||
Because of concurrency issues (env_remove could remove an event
|
||||
that is currently being executed), env_remove does not actually
|
||||
free any events - instead it simply moves all events that should
|
||||
be removed from the event list to the killme list, and the ones
|
||||
that shouldn't be killed to new_list, and then drops the empty
|
||||
events-list.
|
||||
*/
|
||||
|
||||
if( !events )
|
||||
return;
|
||||
return;
|
||||
|
||||
for( i=0; i<al_get_count( events); i++ )
|
||||
{
|
||||
@@ -327,6 +337,8 @@ int event_get( event_t *criterion, array_list_t *out )
|
||||
|
||||
if( !events )
|
||||
return 0;
|
||||
|
||||
CHECK( criterion, 0 );
|
||||
|
||||
for( i=0; i<al_get_count( events); i++ )
|
||||
{
|
||||
@@ -617,7 +629,6 @@ void event_fire( event_t *event )
|
||||
|
||||
void event_init()
|
||||
{
|
||||
sig_list[active_list].count=0;
|
||||
}
|
||||
|
||||
void event_destroy()
|
||||
@@ -625,7 +636,7 @@ void event_destroy()
|
||||
|
||||
if( events )
|
||||
{
|
||||
al_foreach( events, (void (*)(const void *))&event_free );
|
||||
al_foreach( events, (void (*)(void *))&event_free );
|
||||
al_destroy( events );
|
||||
free( events );
|
||||
events=0;
|
||||
@@ -633,7 +644,7 @@ void event_destroy()
|
||||
|
||||
if( killme )
|
||||
{
|
||||
al_foreach( killme, (void (*)(const void *))&event_free );
|
||||
al_foreach( killme, (void (*)(void *))&event_free );
|
||||
al_destroy( killme );
|
||||
free( killme );
|
||||
killme=0;
|
||||
@@ -642,10 +653,12 @@ void event_destroy()
|
||||
|
||||
void event_free( event_t *e )
|
||||
{
|
||||
CHECK( e, );
|
||||
|
||||
/*
|
||||
When apropriate, we clear the argument vector
|
||||
*/
|
||||
al_foreach( &e->arguments, (void (*)(const void *))&free );
|
||||
al_foreach( &e->arguments, &free );
|
||||
al_destroy( &e->arguments );
|
||||
|
||||
free( (void *)e->function_name );
|
||||
@@ -653,3 +666,4 @@ void event_free( event_t *e )
|
||||
free( (void *)e->param1.variable );
|
||||
free( e );
|
||||
}
|
||||
|
||||
|
||||
153
exec.c
153
exec.c
@@ -86,9 +86,10 @@ void exec_close( int fd )
|
||||
{
|
||||
debug( 1, FD_ERROR, fd );
|
||||
wperror( L"close" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( open_fds )
|
||||
{
|
||||
for( i=0; i<al_get_count( open_fds ); i++ )
|
||||
@@ -126,7 +127,7 @@ int exec_pipe( int fd[2])
|
||||
|
||||
if( open_fds == 0 )
|
||||
{
|
||||
open_fds = al_new();
|
||||
open_fds = al_halloc( global_context );
|
||||
}
|
||||
|
||||
al_push( open_fds, (void *)(long)fd[0] );
|
||||
@@ -164,7 +165,8 @@ static int use_fd_in_pipe( int fd, io_data_t *io )
|
||||
the redirection list io. This should make sure that there are no
|
||||
stray opened file descriptors in the child.
|
||||
|
||||
\param io the list of io redirections for this job. Pipes mentioned here should not be closed.
|
||||
\param io the list of io redirections for this job. Pipes mentioned
|
||||
here should not be closed.
|
||||
*/
|
||||
static void close_unused_internal_pipes( io_data_t *io )
|
||||
{
|
||||
@@ -185,20 +187,6 @@ static void close_unused_internal_pipes( io_data_t *io )
|
||||
}
|
||||
}
|
||||
|
||||
void exec_init()
|
||||
{
|
||||
}
|
||||
|
||||
void exec_destroy()
|
||||
{
|
||||
if( open_fds )
|
||||
{
|
||||
al_destroy( open_fds );
|
||||
free( open_fds );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Make sure the fd used by this redirection is not used by i.e. a pipe.
|
||||
*/
|
||||
@@ -273,7 +261,11 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
switch( io->io_mode )
|
||||
{
|
||||
case IO_CLOSE:
|
||||
close(io->fd);
|
||||
if( close(io->fd) )
|
||||
{
|
||||
debug( 0, _(L"Failed to close file descriptor %d"), io->fd );
|
||||
wperror( L"close" );
|
||||
}
|
||||
break;
|
||||
case IO_FILE:
|
||||
{
|
||||
@@ -296,8 +288,12 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
}
|
||||
else if( tmp != io->fd)
|
||||
{
|
||||
/*
|
||||
This call will sometimes fail, but that is ok,
|
||||
this is just a precausion.
|
||||
*/
|
||||
close(io->fd);
|
||||
|
||||
|
||||
if(dup2( tmp, io->fd ) == -1 )
|
||||
{
|
||||
debug( 1,
|
||||
@@ -320,6 +316,10 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
|
||||
case IO_FD:
|
||||
{
|
||||
/*
|
||||
This call will sometimes fail, but that is ok,
|
||||
this is just a precausion.
|
||||
*/
|
||||
close(io->fd);
|
||||
|
||||
if( dup2( io->param1.old_fd, io->fd ) == -1 )
|
||||
@@ -345,6 +345,10 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
{
|
||||
int fd_to_dup = io->fd;
|
||||
|
||||
/*
|
||||
This call will sometimes fail, but that is ok,
|
||||
this is just a precausion.
|
||||
*/
|
||||
close(io->fd);
|
||||
|
||||
if( dup2( io->param1.pipe_fd[fd_to_dup?1:0], io->fd ) == -1 )
|
||||
@@ -491,7 +495,7 @@ static io_data_t *io_transmogrify( io_data_t * in )
|
||||
|
||||
out = malloc( sizeof( io_data_t ) );
|
||||
if( !out )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
out->fd = in->fd;
|
||||
out->io_mode = IO_FD;
|
||||
@@ -564,7 +568,7 @@ static void internal_exec_helper( const wchar_t *def,
|
||||
io_data_t *io_internal = io_transmogrify( io );
|
||||
int is_block_old=is_block;
|
||||
is_block=1;
|
||||
|
||||
|
||||
/*
|
||||
Did the transmogrification fail - if so, set error status and return
|
||||
*/
|
||||
@@ -575,7 +579,7 @@ static void internal_exec_helper( const wchar_t *def,
|
||||
}
|
||||
|
||||
signal_unblock();
|
||||
|
||||
|
||||
eval( def, io_internal, block_type );
|
||||
|
||||
signal_block();
|
||||
@@ -665,6 +669,8 @@ void exec( job_t *j )
|
||||
*/
|
||||
int exec_error=0;
|
||||
|
||||
CHECK( j, );
|
||||
|
||||
if( no_exec )
|
||||
return;
|
||||
|
||||
@@ -681,7 +687,7 @@ void exec( job_t *j )
|
||||
signal_block();
|
||||
|
||||
/*
|
||||
setup_child_process make sure signals are properly set
|
||||
setup_child_process makes sure signals are properly set
|
||||
up. It will also call signal_unblock
|
||||
*/
|
||||
if( !setup_child_process( j, 0 ) )
|
||||
@@ -770,22 +776,12 @@ void exec( job_t *j )
|
||||
break;
|
||||
}
|
||||
|
||||
/* fwprintf( stderr,
|
||||
L"Make pipe from %ls to %ls using fds %d and %d\n",
|
||||
p->actual_cmd,
|
||||
p->next->actual_cmd,
|
||||
mypipe[0],
|
||||
mypipe[1] );
|
||||
*/
|
||||
memcpy( pipe_write.param1.pipe_fd, mypipe, sizeof(int)*2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
This is the last element of the pipeline.
|
||||
*/
|
||||
|
||||
/*
|
||||
Remove the io redirection for pipe output.
|
||||
*/
|
||||
j->io = io_remove( j->io, &pipe_write );
|
||||
@@ -798,7 +794,6 @@ void exec( job_t *j )
|
||||
{
|
||||
|
||||
wchar_t * def = halloc_register( j, wcsdup( function_get_definition( p->argv[0] )));
|
||||
//fwprintf( stderr, L"run function %ls\n", argv[0] );
|
||||
if( def == 0 )
|
||||
{
|
||||
debug( 0, _( L"Unknown function '%ls'" ), p->argv[0] );
|
||||
@@ -816,7 +811,6 @@ void exec( job_t *j )
|
||||
|
||||
if( p->next )
|
||||
{
|
||||
// fwprintf( stderr, L"Function %ls\n", def );
|
||||
io_buffer = io_buffer_create();
|
||||
j->io = io_add( j->io, io_buffer );
|
||||
}
|
||||
@@ -833,11 +827,10 @@ void exec( job_t *j )
|
||||
{
|
||||
if( p->next )
|
||||
{
|
||||
// fwprintf( stderr, L"Block %ls\n", p->argv[0] );
|
||||
io_buffer = io_buffer_create();
|
||||
j->io = io_add( j->io, io_buffer );
|
||||
}
|
||||
|
||||
|
||||
internal_exec_helper( p->argv[0], TOP, j->io );
|
||||
break;
|
||||
|
||||
@@ -852,6 +845,7 @@ void exec( job_t *j )
|
||||
if( p == j->first_process )
|
||||
{
|
||||
io_data_t *in = io_get( j->io, 0 );
|
||||
|
||||
if( in )
|
||||
{
|
||||
switch( in->io_mode )
|
||||
@@ -860,11 +854,6 @@ void exec( job_t *j )
|
||||
case IO_FD:
|
||||
{
|
||||
builtin_stdin = in->param1.old_fd;
|
||||
/* fwprintf( stderr,
|
||||
L"Input redirection for builtin '%ls' from fd %d\n",
|
||||
p->argv[0],
|
||||
in->old_fd );
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case IO_PIPE:
|
||||
@@ -875,11 +864,6 @@ void exec( job_t *j )
|
||||
|
||||
case IO_FILE:
|
||||
{
|
||||
/*
|
||||
fwprintf( stderr,
|
||||
L"Input redirection for builtin from file %ls\n",
|
||||
in->filename);
|
||||
*/
|
||||
builtin_stdin=wopen( in->param1.filename,
|
||||
in->param2.flags, 0777 );
|
||||
if( builtin_stdin == -1 )
|
||||
@@ -919,40 +903,37 @@ void exec( job_t *j )
|
||||
exec_error=1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
builtin_push_io( builtin_stdin );
|
||||
|
||||
/*
|
||||
Since this may be the foreground job, and since a
|
||||
builtin may execute another foreground job, we need to
|
||||
pretend to suspend this job while running the builtin.
|
||||
*/
|
||||
|
||||
builtin_out_redirect = has_fd( j->io, 1 );
|
||||
builtin_err_redirect = has_fd( j->io, 2 );
|
||||
fg = j->fg;
|
||||
j->fg = 0;
|
||||
|
||||
signal_unblock();
|
||||
|
||||
p->status = builtin_run( p->argv );
|
||||
|
||||
signal_block();
|
||||
|
||||
/*
|
||||
Restore the fg flag, which is temporarily set to
|
||||
false during builtin execution so as not to confuse
|
||||
some job-handling builtins.
|
||||
*/
|
||||
j->fg = fg;
|
||||
}
|
||||
|
||||
builtin_push_io( builtin_stdin );
|
||||
|
||||
/*
|
||||
Since this may be the foreground job, and since a
|
||||
builtin may execute another foreground job, we need to
|
||||
pretend to suspend this job while running the builtin.
|
||||
*/
|
||||
|
||||
builtin_out_redirect = has_fd( j->io, 1 );
|
||||
builtin_err_redirect = has_fd( j->io, 2 );
|
||||
fg = j->fg;
|
||||
j->fg = 0;
|
||||
|
||||
signal_unblock();
|
||||
|
||||
p->status = builtin_run( p->argv );
|
||||
|
||||
signal_block();
|
||||
|
||||
/*
|
||||
Restore the fg flag, which is temporarily set to
|
||||
false during builtin execution so as not to confuse
|
||||
some job-handling builtins.
|
||||
*/
|
||||
j->fg = fg;
|
||||
|
||||
|
||||
/* if( is_interactive )
|
||||
fwprintf( stderr, L"Builtin '%ls' finished\n", j->command );
|
||||
*/
|
||||
if( close_stdin )
|
||||
{
|
||||
// fwprintf( stderr, L"Close builtin_stdin\n" );
|
||||
exec_close( builtin_stdin );
|
||||
}
|
||||
break;
|
||||
@@ -1071,7 +1052,6 @@ void exec( job_t *j )
|
||||
( sb_out->used ) &&
|
||||
( buffer_stdout ) )
|
||||
{
|
||||
// fwprintf( stderr, L"Skip fork of %ls\n", j->command );
|
||||
char *res = wcs2str( (wchar_t *)sb_out->buff );
|
||||
b_append( io->param2.out_buffer, res, strlen( res ) );
|
||||
skip_fork = 1;
|
||||
@@ -1094,9 +1074,13 @@ void exec( job_t *j )
|
||||
pid = fork();
|
||||
if( pid == 0 )
|
||||
{
|
||||
|
||||
/*
|
||||
This is the child process.
|
||||
This is the child process. Setup redirections,
|
||||
print correct output to stdout and stderr, and
|
||||
then exit.
|
||||
*/
|
||||
|
||||
p->pid = getpid();
|
||||
setup_child_process( j, p );
|
||||
if( sb_out->used )
|
||||
@@ -1118,7 +1102,7 @@ void exec( job_t *j )
|
||||
{
|
||||
/*
|
||||
This is the parent process. Store away
|
||||
information on the child, and possibly fice
|
||||
information on the child, and possibly give
|
||||
it control over the terminal.
|
||||
*/
|
||||
p->pid = pid;
|
||||
@@ -1185,8 +1169,11 @@ void exec( job_t *j )
|
||||
pipe_read.param1.pipe_fd[0] = mypipe[0];
|
||||
|
||||
/*
|
||||
If there is a next process, close the output end of the
|
||||
pipe (the child subprocess already has a copy of the pipe).
|
||||
If there is a next process in the pipeline, close the
|
||||
output end of the current pipe (the surrent child
|
||||
subprocess already has a copy of the pipe - this makes sure
|
||||
we don't leak file descriptors either in the shell or in
|
||||
the children).
|
||||
*/
|
||||
if( p->next )
|
||||
{
|
||||
|
||||
11
exec.h
11
exec.h
@@ -18,17 +18,6 @@
|
||||
*/
|
||||
#define PIPE_ERROR _(L"An error occurred while setting up pipe")
|
||||
|
||||
/**
|
||||
Initialize the exec library
|
||||
*/
|
||||
void exec_init();
|
||||
|
||||
/**
|
||||
Destroy dynamically allocated data and other resources used by the
|
||||
exec library
|
||||
*/
|
||||
void exec_destroy();
|
||||
|
||||
/**
|
||||
Execute the processes specified by j.
|
||||
|
||||
|
||||
271
expand.c
271
expand.c
@@ -76,27 +76,6 @@ parameter expansion.
|
||||
*/
|
||||
#define COMPLETE_LAST_DESC _( L"Last background job")
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean {$VARIABLE}? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
|
||||
|
||||
|
||||
/**
|
||||
String in process expansion denoting ourself
|
||||
*/
|
||||
@@ -117,19 +96,13 @@ parameter expansion.
|
||||
*/
|
||||
#define UNCLEAN L"$*?\\\"'({})"
|
||||
|
||||
/**
|
||||
Test if the specified argument is clean, i.e. it does not contain
|
||||
any tokens which need to be expanded or otherwise altered. Clean
|
||||
strings can be passed through expand_string and expand_one without
|
||||
changing them. About 90% of all strings are clean, so skipping
|
||||
expansion on them actually does save a small amount of time, since
|
||||
it avoids multiple memory allocations during the expansion process.
|
||||
*/
|
||||
static int is_clean( const wchar_t *in )
|
||||
int expand_is_clean( const wchar_t *in )
|
||||
{
|
||||
|
||||
const wchar_t * str = in;
|
||||
|
||||
CHECK( in, 1 );
|
||||
|
||||
/*
|
||||
Test characters that have a special meaning in the first character position
|
||||
*/
|
||||
@@ -159,32 +132,6 @@ static wchar_t *expand_var( wchar_t *in )
|
||||
return env_get( in );
|
||||
}
|
||||
|
||||
void expand_variable_array( const wchar_t *val, array_list_t *out )
|
||||
{
|
||||
if( val )
|
||||
{
|
||||
wchar_t *cpy = wcsdup( val );
|
||||
wchar_t *pos, *start;
|
||||
|
||||
if( !cpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
for( start=pos=cpy; *pos; pos++ )
|
||||
{
|
||||
if( *pos == ARRAY_SEP )
|
||||
{
|
||||
*pos=0;
|
||||
al_push( out, start==cpy?cpy:wcsdup(start) );
|
||||
start=pos+1;
|
||||
}
|
||||
}
|
||||
al_push( out, start==cpy?cpy:wcsdup(start) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test if the specified string does not contain character which can
|
||||
not be used inside a quoted string.
|
||||
@@ -216,8 +163,10 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
array_list_t l;
|
||||
string_buffer_t buff;
|
||||
|
||||
CHECK( in, 0 );
|
||||
|
||||
al_init( &l );
|
||||
expand_variable_array( in, &l );
|
||||
tokenize_variable_array( in, &l );
|
||||
sb_init( &buff );
|
||||
|
||||
switch( al_get_count( &l) )
|
||||
@@ -225,7 +174,7 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
case 0:
|
||||
sb_append( &buff, L"''");
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
{
|
||||
wchar_t *el = (wchar_t *)al_get( &l, 0 );
|
||||
@@ -281,28 +230,19 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Tests if all characters in the string are numeric
|
||||
*/
|
||||
static int isnumeric( const char *n )
|
||||
{
|
||||
if( *n == '\0' )
|
||||
return 1;
|
||||
if( *n < '0' || *n > '9' )
|
||||
return 0;
|
||||
return isnumeric( n+1 );
|
||||
}
|
||||
|
||||
/**
|
||||
Tests if all characters in the wide string are numeric
|
||||
*/
|
||||
static int iswnumeric( const wchar_t *n )
|
||||
{
|
||||
if( *n == L'\0' )
|
||||
return 1;
|
||||
if( *n < L'0' || *n > L'9' )
|
||||
return 0;
|
||||
return iswnumeric( n+1 );
|
||||
for( ; *n; n++ )
|
||||
{
|
||||
if( *n < L'0' || *n > L'9' )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,9 +317,9 @@ static int find_process( const wchar_t *proc,
|
||||
array_list_t *out )
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *next;
|
||||
char *pdir_name;
|
||||
char *pfile_name;
|
||||
struct wdirent *next;
|
||||
wchar_t *pdir_name;
|
||||
wchar_t *pfile_name;
|
||||
wchar_t *cmd=0;
|
||||
int sz=0;
|
||||
int found = 0;
|
||||
@@ -421,17 +361,18 @@ static int find_process( const wchar_t *proc,
|
||||
{
|
||||
|
||||
int jid = wcstol( proc, 0, 10 );
|
||||
|
||||
j = job_get( jid );
|
||||
if( (j != 0) && (j->command != 0 ) )
|
||||
if( jid > 0 )
|
||||
{
|
||||
|
||||
j = job_get( jid );
|
||||
if( (j != 0) && (j->command != 0 ) )
|
||||
{
|
||||
result = malloc(sizeof(wchar_t)*16 );
|
||||
swprintf( result, 16, L"%d", j->pgid );
|
||||
//fwprintf( stderr, L"pid %d %ls\n", j->pgid, result );
|
||||
al_push( out, result );
|
||||
found = 1;
|
||||
|
||||
{
|
||||
result = malloc(sizeof(wchar_t)*16 );
|
||||
swprintf( result, 16, L"%d", j->pgid );
|
||||
al_push( out, result );
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -441,12 +382,9 @@ static int find_process( const wchar_t *proc,
|
||||
|
||||
for( j=first_job; j != 0; j=j->next )
|
||||
{
|
||||
// fwprintf( stderr, L"..." );
|
||||
if( j->command == 0 )
|
||||
continue;
|
||||
|
||||
// fwprintf( stderr, L"match '%ls' '%ls'\n\n\n", j->command, proc );
|
||||
|
||||
if( match_pid( j->command, proc, flags ) )
|
||||
{
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
@@ -455,8 +393,6 @@ static int find_process( const wchar_t *proc,
|
||||
COMPLETE_SEP_STR,
|
||||
COMPLETE_JOB_DESC,
|
||||
(void *)0 );
|
||||
// fwprintf( stderr, L"Woot %ls\n", res );
|
||||
|
||||
al_push( out, res );
|
||||
}
|
||||
else
|
||||
@@ -482,12 +418,9 @@ static int find_process( const wchar_t *proc,
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
|
||||
// fwprintf( stderr, L"..." );
|
||||
if( p->actual_cmd == 0 )
|
||||
continue;
|
||||
|
||||
// fwprintf( stderr, L"match '%ls' '%ls'\n\n\n", j->command, proc );
|
||||
|
||||
if( match_pid( p->actual_cmd, proc, flags ) )
|
||||
{
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
@@ -522,20 +455,20 @@ static int find_process( const wchar_t *proc,
|
||||
return 1;
|
||||
}
|
||||
|
||||
pdir_name = malloc( 256 );
|
||||
pfile_name = malloc( 64 );
|
||||
strcpy( pdir_name, "/proc/" );
|
||||
|
||||
while( (next=readdir(dir))!=0 )
|
||||
pdir_name = malloc( sizeof(wchar_t)*256 );
|
||||
pfile_name = malloc( sizeof(wchar_t)*64 );
|
||||
wcscpy( pdir_name, L"/proc/" );
|
||||
|
||||
while( (next=wreaddir(dir))!=0 )
|
||||
{
|
||||
char *name = next->d_name;
|
||||
wchar_t *name = next->d_name;
|
||||
struct stat buf;
|
||||
|
||||
if( !isnumeric( name ) )
|
||||
if( !iswnumeric( name ) )
|
||||
continue;
|
||||
|
||||
strcpy( pdir_name + 6, name );
|
||||
if( stat( pdir_name, &buf ) )
|
||||
wcscpy( pdir_name + 6, name );
|
||||
if( wstat( pdir_name, &buf ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -543,17 +476,17 @@ static int find_process( const wchar_t *proc,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
strcpy( pfile_name, pdir_name );
|
||||
strcat( pfile_name, "/cmdline" );
|
||||
wcscpy( pfile_name, pdir_name );
|
||||
wcscat( pfile_name, L"/cmdline" );
|
||||
|
||||
if( !stat( pfile_name, &buf ) )
|
||||
if( !wstat( pfile_name, &buf ) )
|
||||
{
|
||||
/*
|
||||
the 'cmdline' file exists, it should contain the commandline
|
||||
*/
|
||||
FILE *cmdfile;
|
||||
|
||||
if((cmdfile=fopen( pfile_name, "r" ))==0)
|
||||
if((cmdfile=wfopen( pfile_name, "r" ))==0)
|
||||
{
|
||||
wperror( L"fopen" );
|
||||
continue;
|
||||
@@ -568,15 +501,15 @@ static int find_process( const wchar_t *proc,
|
||||
else
|
||||
{
|
||||
#ifdef SunOS
|
||||
strcpy( pfile_name, pdir_name );
|
||||
strcat( pfile_name, "/psinfo" );
|
||||
if( !stat( pfile_name, &buf ) )
|
||||
wcscpy( pfile_name, pdir_name );
|
||||
wcscat( pfile_name, L"/psinfo" );
|
||||
if( !wstat( pfile_name, &buf ) )
|
||||
{
|
||||
psinfo_t info;
|
||||
|
||||
FILE *psfile;
|
||||
|
||||
if((psfile=fopen( pfile_name, "r" ))==0)
|
||||
if((psfile=wfopen( pfile_name, "r" ))==0)
|
||||
{
|
||||
wperror( L"fopen" );
|
||||
continue;
|
||||
@@ -615,7 +548,7 @@ static int find_process( const wchar_t *proc,
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *res = str2wcs(name);
|
||||
wchar_t *res = wcsdup(name);
|
||||
if( res )
|
||||
al_push( out, res );
|
||||
}
|
||||
@@ -641,6 +574,13 @@ static int expand_pid( wchar_t *in,
|
||||
int flags,
|
||||
array_list_t *out )
|
||||
{
|
||||
|
||||
if( !in || !out)
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( *in != PROCESS_EXPAND )
|
||||
{
|
||||
al_push( out, in );
|
||||
@@ -687,27 +627,22 @@ static int expand_pid( wchar_t *in,
|
||||
}
|
||||
}
|
||||
|
||||
// fwprintf( stderr, L"expand_pid() %ls\n", in );
|
||||
int prev = al_get_count( out );
|
||||
if( !find_process( in+1, flags, out ) )
|
||||
return 0;
|
||||
|
||||
if( prev == al_get_count( out ) )
|
||||
{
|
||||
// fwprintf( stderr, L"no match\n" );
|
||||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
free( in );
|
||||
else
|
||||
{
|
||||
*in = L'%';
|
||||
// fwprintf( stderr, L"return %ls\n", in );
|
||||
al_push( out, in );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// fwprintf( stderr, L"match\n" );
|
||||
free( in );
|
||||
}
|
||||
|
||||
@@ -739,11 +674,17 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
static string_buffer_t *var_tmp = 0;
|
||||
static array_list_t *var_idx_list = 0;
|
||||
|
||||
if( !in || !out)
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !var_tmp )
|
||||
{
|
||||
var_tmp = sb_halloc( global_context );
|
||||
if( !var_tmp )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -754,7 +695,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
{
|
||||
var_idx_list = al_halloc( global_context );
|
||||
if( !var_idx_list )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -816,8 +757,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
-1,
|
||||
COMPLETE_VAR_NULL_DESC,
|
||||
in[stop_pos] );
|
||||
COMPLETE_VAR_NULL_DESC );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -855,7 +795,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
stop_pos++;
|
||||
while( 1 )
|
||||
{
|
||||
int tmp;
|
||||
long tmp;
|
||||
|
||||
while( iswspace(in[stop_pos]) || (in[stop_pos]==INTERNAL_SEPARATOR))
|
||||
stop_pos++;
|
||||
@@ -885,18 +825,23 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
expand_variable_array( var_val, &var_item_list );
|
||||
tokenize_variable_array( var_val, &var_item_list );
|
||||
if( !all_vars )
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<al_get_count( var_idx_list ); j++)
|
||||
{
|
||||
int tmp = (int)al_get( var_idx_list, j );
|
||||
long tmp = (long)al_get( var_idx_list, j );
|
||||
if( tmp < 0 )
|
||||
{
|
||||
tmp = al_get_count( &var_item_list)+tmp+1;
|
||||
}
|
||||
|
||||
if( tmp < 1 || tmp > al_get_count( &var_item_list ) )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
-1,
|
||||
L"Array index out of bounds" );
|
||||
ARRAY_BOUNDS_ERR );
|
||||
is_ok=0;
|
||||
al_truncate( var_idx_list, j );
|
||||
break;
|
||||
@@ -909,7 +854,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
}
|
||||
}
|
||||
/* Free remaining strings in list l and truncate it */
|
||||
al_foreach( &var_item_list, (void (*)(const void *))&free );
|
||||
al_foreach( &var_item_list, &free );
|
||||
al_truncate( &var_item_list, 0 );
|
||||
/* Add items from list idx back to list l */
|
||||
al_push_all( &var_item_list, var_idx_list );
|
||||
@@ -962,12 +907,12 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
|
||||
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
wcsncpy( new_in, in, start_pos-1 );
|
||||
wcslcpy( new_in, in, start_pos );
|
||||
|
||||
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
|
||||
{
|
||||
@@ -980,7 +925,6 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
wcscat( new_in, next );
|
||||
wcscat( new_in, &in[stop_pos] );
|
||||
|
||||
// fwprintf( stderr, L"New value %ls\n", new_in );
|
||||
is_ok &= expand_variables( new_in, out, i );
|
||||
}
|
||||
}
|
||||
@@ -1058,20 +1002,22 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
|
||||
wchar_t *item_begin;
|
||||
int len1, len2, tot_len;
|
||||
|
||||
// fwprintf( stderr, L"expand %ls\n", in );
|
||||
|
||||
|
||||
if( !in || !out)
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( pos=in;
|
||||
(!bracket_end) && (*pos) && !syntax_error;
|
||||
(*pos) && !syntax_error;
|
||||
pos++ )
|
||||
{
|
||||
switch( *pos )
|
||||
{
|
||||
case BRACKET_BEGIN:
|
||||
{
|
||||
if(( bracket_count == 0)&&(bracket_begin==0))
|
||||
bracket_begin = pos;
|
||||
bracket_begin = pos;
|
||||
|
||||
bracket_count++;
|
||||
break;
|
||||
@@ -1080,9 +1026,11 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
case BRACKET_END:
|
||||
{
|
||||
bracket_count--;
|
||||
if( (bracket_count == 0) && (bracket_end == 0) )
|
||||
if( bracket_end < bracket_begin )
|
||||
{
|
||||
bracket_end = pos;
|
||||
|
||||
}
|
||||
|
||||
if( bracket_count < 0 )
|
||||
{
|
||||
syntax_error = 1;
|
||||
@@ -1100,7 +1048,9 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
if( bracket_count > 0 )
|
||||
{
|
||||
if( !(flags & ACCEPT_INCOMPLETE) )
|
||||
{
|
||||
syntax_error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1118,9 +1068,6 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
sb_append_char( &mod, BRACKET_END );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return expand_brackets( (wchar_t*)mod.buff, 1, out );
|
||||
}
|
||||
}
|
||||
@@ -1153,8 +1100,8 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
int item_len = pos-item_begin;
|
||||
|
||||
whole_item = malloc( sizeof(wchar_t)*(tot_len + item_len + 1) );
|
||||
wcsncpy( whole_item, in, len1 );
|
||||
wcsncpy( whole_item+len1, item_begin, item_len );
|
||||
wcslcpy( whole_item, in, len1+1 );
|
||||
wcslcpy( whole_item+len1, item_begin, item_len+1 );
|
||||
wcscpy( whole_item+len1+item_len, bracket_end+1 );
|
||||
|
||||
expand_brackets( whole_item, flags, out );
|
||||
@@ -1184,7 +1131,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
*/
|
||||
static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
{
|
||||
const wchar_t *paran_begin=0, *paran_end=0;
|
||||
wchar_t *paran_begin=0, *paran_end=0;
|
||||
int len1, len2;
|
||||
wchar_t prev=0;
|
||||
wchar_t *subcmd;
|
||||
@@ -1192,18 +1139,12 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
int i, j;
|
||||
const wchar_t *item_begin;
|
||||
|
||||
if( !in )
|
||||
if( !in || !out)
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !out )
|
||||
{
|
||||
debug( 2, L"Got null pointer on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch( parse_util_locate_cmdsubst(in,
|
||||
¶n_begin,
|
||||
¶n_end,
|
||||
@@ -1234,12 +1175,12 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
return 0;
|
||||
}
|
||||
|
||||
wcsncpy( subcmd, paran_begin+1, paran_end-paran_begin-1 );
|
||||
wcslcpy( subcmd, paran_begin+1, paran_end-paran_begin );
|
||||
subcmd[ paran_end-paran_begin-1]=0;
|
||||
|
||||
if( exec_subshell( subcmd, &sub_res)==-1 )
|
||||
{
|
||||
al_foreach( &sub_res, (void (*)(const void *))&free );
|
||||
al_foreach( &sub_res, &free );
|
||||
al_destroy( &sub_res );
|
||||
free( subcmd );
|
||||
return 0;
|
||||
@@ -1278,14 +1219,16 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
|
||||
al_destroy( &sub_res );
|
||||
|
||||
al_foreach( &tail_expand, (void (*)(const void *))&free );
|
||||
al_foreach( &tail_expand, &free );
|
||||
al_destroy( &tail_expand );
|
||||
|
||||
free( subcmd );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Wrapper around unescape funtion. Issues an error() on failiure.
|
||||
*/
|
||||
static wchar_t *expand_unescape( const wchar_t * in, int escape_special )
|
||||
{
|
||||
wchar_t *res = unescape( in, escape_special );
|
||||
@@ -1310,7 +1253,6 @@ static wchar_t * expand_tilde_internal( wchar_t *in )
|
||||
wchar_t *new_in=0;
|
||||
wchar_t *old_in=0;
|
||||
|
||||
// fwprintf( stderr, L"Tilde expand ~%ls\n", (*ptr)+1 );
|
||||
if( in[1] == '/' || in[1] == '\0' )
|
||||
{
|
||||
/* Current users home directory */
|
||||
@@ -1378,6 +1320,8 @@ static wchar_t * expand_tilde_internal( wchar_t *in )
|
||||
|
||||
wchar_t *expand_tilde( wchar_t *in)
|
||||
{
|
||||
CHECK( in, 0 );
|
||||
|
||||
if( in[0] == L'~' )
|
||||
{
|
||||
in[0] = HOME_DIRECTORY;
|
||||
@@ -1420,7 +1364,6 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
*out=0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The real expansion function. expand_one is just a wrapper around this one.
|
||||
*/
|
||||
@@ -1437,10 +1380,10 @@ int expand_string( void *context,
|
||||
int res = EXPAND_OK;
|
||||
int start_count = al_get_count( end_out );
|
||||
|
||||
// debug( 1, L"Expand %ls", str );
|
||||
CHECK( str, EXPAND_ERROR );
|
||||
CHECK( end_out, EXPAND_ERROR );
|
||||
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( str ) )
|
||||
{
|
||||
halloc_register( context, str );
|
||||
al_push( end_out, str );
|
||||
@@ -1452,7 +1395,7 @@ int expand_string( void *context,
|
||||
|
||||
if( EXPAND_SKIP_SUBSHELL & flags )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *begin, *end;
|
||||
|
||||
if( parse_util_locate_cmdsubst( str,
|
||||
&begin,
|
||||
@@ -1686,7 +1629,9 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
|
||||
int res;
|
||||
wchar_t *one;
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( string ) )
|
||||
CHECK( string, 0 );
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string ) )
|
||||
{
|
||||
halloc_register( context, string );
|
||||
return string;
|
||||
@@ -1711,7 +1656,7 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &l, (void(*)(const void *))&free );
|
||||
al_foreach( &l, &free );
|
||||
al_destroy( &l );
|
||||
|
||||
halloc_register( context, one );
|
||||
|
||||
62
expand.h
62
expand.h
@@ -112,23 +112,52 @@ enum
|
||||
/** String containing the character for separating two array elements */
|
||||
#define ARRAY_SEP_STR L"\x1e"
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean {$VARIABLE}? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
|
||||
|
||||
/**
|
||||
Error issued on invalid variable name
|
||||
*/
|
||||
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
|
||||
|
||||
/**
|
||||
Error issued on array out of bounds
|
||||
*/
|
||||
#define ARRAY_BOUNDS_ERR _(L"Array index out of bounds")
|
||||
|
||||
|
||||
/**
|
||||
Perform various forms of expansion on in, such as tilde expansion
|
||||
(~USER becomes the users home directory), variable expansion
|
||||
($VAR_NAME becomes the value of the environment variable VAR_NAME),
|
||||
(\~USER becomes the users home directory), variable expansion
|
||||
(\$VAR_NAME becomes the value of the environment variable VAR_NAME),
|
||||
subshell expansion and wildcard expansion. The results are inserted
|
||||
into the list out.
|
||||
|
||||
If the parameter does not need expansion, it is copied into the list
|
||||
out. If expansion is performed, the original parameter is freed and
|
||||
newly allocated strings are inserted into the list out.
|
||||
|
||||
|
||||
If \c context is non-null, all the strings contained in the
|
||||
array_list_t \c out will be registered to be free'd when context is
|
||||
free'd.
|
||||
|
||||
\param context the halloc context to use for automatic deallocation
|
||||
\param in The parameter to expand
|
||||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
\param out The list to which the result will be appended.
|
||||
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH
|
||||
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH. EXPAND_WILDCARD_NO_MATCH and EXPAND_WILDCARD_MATCH are normal exit conditions used only on strings containing wildcards to tell if the wildcard produced any matches.
|
||||
*/
|
||||
int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
|
||||
|
||||
@@ -137,6 +166,10 @@ int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
|
||||
expands to more than one string. This is used for expanding command
|
||||
names.
|
||||
|
||||
If \c context is non-null, the returning string ill be registered
|
||||
to be free'd when context is free'd.
|
||||
|
||||
\param context the halloc context to use for automatic deallocation
|
||||
\param in The parameter to expand
|
||||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
\return The expanded parameter, or 0 on failiure
|
||||
@@ -145,6 +178,8 @@ wchar_t *expand_one( void *context, wchar_t *in, int flag );
|
||||
|
||||
/**
|
||||
Convert the variable value to a human readable form, i.e. escape things, handle arrays, etc. Suitable for pretty-printing.
|
||||
|
||||
\param in the value to escape
|
||||
*/
|
||||
wchar_t *expand_escape_variable( const wchar_t *in );
|
||||
|
||||
@@ -153,18 +188,23 @@ wchar_t *expand_escape_variable( const wchar_t *in );
|
||||
|
||||
If tilde expansion is needed, the original string is freed and a
|
||||
new string, allocated using malloc, is returned.
|
||||
|
||||
\param in the string to tilde expand
|
||||
*/
|
||||
wchar_t *expand_tilde(wchar_t *in);
|
||||
|
||||
|
||||
/**
|
||||
Tokenize the specified string into the specified array_list_t.
|
||||
Each new element is allocated using malloc and must be freed by the
|
||||
caller.
|
||||
|
||||
\param val the input string. The contents of this string is not changed.
|
||||
\param out the list in which to place the elements.
|
||||
Test if the specified argument is clean, i.e. it does not contain
|
||||
any tokens which need to be expanded or otherwise altered. Clean
|
||||
strings can be passed through expand_string and expand_one without
|
||||
changing them. About two thirds of all strings are clean, so
|
||||
skipping expansion on them actually does save a small amount of
|
||||
time, since it avoids multiple memory allocations during the
|
||||
expansion process.
|
||||
|
||||
\param in the string to test
|
||||
*/
|
||||
void expand_variable_array( const wchar_t *val, array_list_t *out );
|
||||
int expand_is_clean( const wchar_t *in );
|
||||
|
||||
#endif
|
||||
|
||||
145
fallback.c
145
fallback.c
@@ -818,8 +818,7 @@ wchar_t *wcsndup( const wchar_t *in, int c )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
wcsncpy( res, in, c+1 );
|
||||
res[c] = L'\0';
|
||||
wcslcpy( res, in, c+1 );
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -888,6 +887,148 @@ long wcstol(const wchar_t *nptr,
|
||||
nptr++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifndef HAVE_WCSLCAT
|
||||
|
||||
/*$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size_t
|
||||
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
{
|
||||
|
||||
register wchar_t *d = dst;
|
||||
register const wchar_t *s = src;
|
||||
register size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + wcslen(s));
|
||||
|
||||
while (*s != '\0')
|
||||
{
|
||||
if (n != 1)
|
||||
{
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src));
|
||||
/* count does not include NUL */
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifndef HAVE_WCSLCPY
|
||||
|
||||
/*$OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size_t
|
||||
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
{
|
||||
register wchar_t *d = dst;
|
||||
register const wchar_t *s = src;
|
||||
register size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((*d++ = *s++) == 0)
|
||||
break;
|
||||
}
|
||||
while (--n != 0);
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0)
|
||||
{
|
||||
if (siz != 0)
|
||||
*d = '\0';
|
||||
/* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
return(s - src - 1);
|
||||
/* count does not include NUL */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_DEL_CURTERM
|
||||
|
||||
int del_curterm(TERMINAL *oterm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LRAND48_R
|
||||
|
||||
int lrand48_r(struct drand48_data *buffer, long int *result)
|
||||
{
|
||||
*result = rand_r( &buffer->seed );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int srand48_r(long int seedval, struct drand48_data *buffer)
|
||||
{
|
||||
buffer->seed = (int)seedval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FUTIMES
|
||||
|
||||
int futimes(int fd, const struct timeval *times)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
97
fallback.h
97
fallback.h
@@ -3,10 +3,32 @@
|
||||
#define FISH_FALLBACK_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
#include "common.h"
|
||||
#include <limits.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifndef WCHAR_MAX
|
||||
/**
|
||||
This _should_ be defined by wchar.h, but e.g. OpenBSD doesn't.
|
||||
*/
|
||||
#define WCHAR_MAX INT_MAX
|
||||
#endif
|
||||
|
||||
/**
|
||||
Make sure __func__ is defined to some string. In C99, this should
|
||||
be the currently compiled function. If we aren't using C99 or
|
||||
later, older versions of GCC had __FUNCTION__.
|
||||
*/
|
||||
#if __STDC_VERSION__ < 199901L
|
||||
# if __GNUC__ >= 2
|
||||
# define __func__ __FUNCTION__
|
||||
# else
|
||||
# define __func__ "<unknown>"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
Under curses, tputs expects an int (*func)(char) as its last
|
||||
@@ -213,7 +235,8 @@ wchar_t *wcsndup( const wchar_t *in, int c );
|
||||
|
||||
/**
|
||||
Converts from wide char to digit in the specified base. If d is not
|
||||
a valid digit in the specified base, return -1.
|
||||
a valid digit in the specified base, return -1. This is a helper
|
||||
function for wcstol, but it is useful itself, so it is exported.
|
||||
*/
|
||||
long convert_digit( wchar_t d, int base );
|
||||
|
||||
@@ -232,5 +255,75 @@ long wcstol(const wchar_t *nptr,
|
||||
int base);
|
||||
|
||||
#endif
|
||||
#ifndef HAVE_WCSLCAT
|
||||
|
||||
/**
|
||||
Appends src to string dst of size siz (unlike wcsncat, siz is the
|
||||
full size of dst, not space left). At most siz-1 characters will be
|
||||
copied. Always NUL terminates (unless siz <= wcslen(dst)). Returns
|
||||
wcslen(src) + MIN(siz, wcslen(initial dst)). If retval >= siz,
|
||||
truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcat function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
|
||||
*/
|
||||
size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
#endif
|
||||
#ifndef HAVE_WCSLCPY
|
||||
|
||||
/**
|
||||
Copy src to string dst of size siz. At most siz-1 characters will
|
||||
be copied. Always NUL terminates (unless siz == 0). Returns
|
||||
wcslen(src); if retval >= siz, truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcpy function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
*/
|
||||
size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_DEL_CURTERM
|
||||
|
||||
/**
|
||||
BSD del_curterm seems to do a double-free. We redefine it as a no-op
|
||||
*/
|
||||
int del_curterm(TERMINAL *oterm);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LRAND48_R
|
||||
|
||||
/**
|
||||
Datastructure for the lrand48_r fallback implementation.
|
||||
*/
|
||||
struct drand48_data
|
||||
{
|
||||
/**
|
||||
Seed value
|
||||
*/
|
||||
unsigned int seed;
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Fallback implementation of lrand48_r. Internally uses rand_r, so it is pretty weak.
|
||||
*/
|
||||
int lrand48_r(struct drand48_data *buffer, long int *result);
|
||||
|
||||
/**
|
||||
Fallback implementation of srand48_r, the seed function for lrand48_r.
|
||||
*/
|
||||
int srand48_r(long int seedval, struct drand48_data *buffer);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FUTIMES
|
||||
|
||||
int futimes(int fd, const struct timeval *times);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ URL: http://roo.no-ip.org/fish/
|
||||
Source0: http://roo.no-ip.org/%{name}/files/%{version}/%{name}-%{version}.tar.bz2
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: doxygen ncurses-devel
|
||||
BuildRequires: ncurses-devel
|
||||
BuildRequires: %{xinclude}/X11/StringDefs.h, %{xinclude}/X11/Xlib.h
|
||||
BuildRequires: %{xinclude}/X11/Intrinsic.h, %{xinclude}/X11/Xatom.h
|
||||
|
||||
|
||||
31
fish_pager.c
31
fish_pager.c
@@ -97,13 +97,34 @@ static wchar_t *hightlight_var[] =
|
||||
static string_buffer_t out_buff;
|
||||
static FILE *out_file;
|
||||
|
||||
/**
|
||||
Data structure describing one or a group of related completions
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
The list of all completin strings this entry applies to
|
||||
*/
|
||||
array_list_t *comp;
|
||||
/**
|
||||
The description
|
||||
*/
|
||||
wchar_t *desc;
|
||||
/**
|
||||
On-screen width of the completion string
|
||||
*/
|
||||
int comp_width;
|
||||
/**
|
||||
On-screen width of the description information
|
||||
*/
|
||||
int desc_width;
|
||||
/**
|
||||
Preffered total width
|
||||
*/
|
||||
int pref_width;
|
||||
/**
|
||||
Minimum acceptable width
|
||||
*/
|
||||
int min_width;
|
||||
}
|
||||
comp_t;
|
||||
@@ -719,7 +740,8 @@ static void mangle_descriptions( array_list_t *l )
|
||||
*/
|
||||
static void join_completions( array_list_t *l )
|
||||
{
|
||||
int i, in, out;
|
||||
long i;
|
||||
int in, out;
|
||||
hash_table_t desc_table;
|
||||
|
||||
hash_init( &desc_table, &hash_wcs_func, &hash_wcs_cmp );
|
||||
@@ -760,8 +782,6 @@ static void join_completions( array_list_t *l )
|
||||
al_set( l, i, 0 );
|
||||
}
|
||||
|
||||
// debug( 1, L"WOOT WOOT %ls är släkt med %ls", item, al_get( l, prev_idx ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -990,9 +1010,12 @@ int main( int argc, char **argv )
|
||||
|
||||
fwprintf( out_file, L"%ls", (wchar_t *)out_buff.buff );
|
||||
if( is_ca_mode )
|
||||
{
|
||||
writembs(exit_ca_mode);
|
||||
pager_flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
31
fish_tests.c
31
fish_tests.c
@@ -51,6 +51,11 @@
|
||||
*/
|
||||
#define LAPS 50
|
||||
|
||||
/**
|
||||
The result of one of the test passes
|
||||
*/
|
||||
#define NUM_ANS L"-7 99999999 1234567 deadbeef DEADBEEFDEADBEEF"
|
||||
|
||||
/**
|
||||
Number of encountered errors
|
||||
*/
|
||||
@@ -102,7 +107,7 @@ static int pq_compare( void *e1, void *e2 )
|
||||
/**
|
||||
Test priority queue functionality
|
||||
*/
|
||||
static int pq_test( int elements )
|
||||
static void pq_test( int elements )
|
||||
{
|
||||
int i;
|
||||
int prev;
|
||||
@@ -290,7 +295,7 @@ static int hash_test( int elements )
|
||||
/**
|
||||
Arraylist test
|
||||
*/
|
||||
static int al_test( int sz)
|
||||
static void al_test( int sz)
|
||||
{
|
||||
int i;
|
||||
array_list_t l;
|
||||
@@ -345,8 +350,6 @@ static void sb_test()
|
||||
|
||||
sb_clear( &b );
|
||||
|
||||
#define NUM_ANS L"-7 99999999 1234567 deadbeef DEADBEEFDEADBEEF"
|
||||
|
||||
sb_printf( &b, L"%d %u %o %x %llX", -7, 99999999, 01234567, 0xdeadbeef, 0xdeadbeefdeadbeefll );
|
||||
if( wcscmp( (wchar_t *)b.buff, NUM_ANS) != 0 )
|
||||
{
|
||||
@@ -483,43 +486,43 @@ static void test_parser()
|
||||
|
||||
|
||||
say( L"Testing null input to parser" );
|
||||
if( !parser_test( 0, 0 ) )
|
||||
if( !parser_test( 0, 0, 0 ) )
|
||||
{
|
||||
err( L"Null input to parser_test undetected" );
|
||||
}
|
||||
|
||||
say( L"Testing block nesting" );
|
||||
if( !parser_test( L"if; end", 0 ) )
|
||||
if( !parser_test( L"if; end", 0, 0 ) )
|
||||
{
|
||||
err( L"Incomplete if statement undetected" );
|
||||
}
|
||||
if( !parser_test( L"if test; echo", 0 ) )
|
||||
if( !parser_test( L"if test; echo", 0, 0 ) )
|
||||
{
|
||||
err( L"Missing end undetected" );
|
||||
}
|
||||
if( !parser_test( L"if test; end; end", 0 ) )
|
||||
if( !parser_test( L"if test; end; end", 0, 0 ) )
|
||||
{
|
||||
err( L"Unbalanced end undetected" );
|
||||
}
|
||||
|
||||
say( L"Testing detection of invalid use of builtin commands" );
|
||||
if( !parser_test( L"case foo", 0 ) )
|
||||
if( !parser_test( L"case foo", 0, 0 ) )
|
||||
{
|
||||
err( L"'case' command outside of block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"switch ggg; if true; case foo;end;end", 0 ) )
|
||||
if( !parser_test( L"switch ggg; if true; case foo;end;end", 0, 0 ) )
|
||||
{
|
||||
err( L"'case' command outside of switch block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"else", 0 ) )
|
||||
if( !parser_test( L"else", 0, 0 ) )
|
||||
{
|
||||
err( L"'else' command outside of conditional block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"break", 0 ) )
|
||||
if( !parser_test( L"break", 0, 0 ) )
|
||||
{
|
||||
err( L"'break' command outside of loop block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"exec ls|less", 0 ) || !parser_test( L"echo|return", 0 ))
|
||||
if( !parser_test( L"exec ls|less", 0, 0 ) || !parser_test( L"echo|return", 0, 0 ))
|
||||
{
|
||||
err( L"Invalid pipe command undetected" );
|
||||
}
|
||||
@@ -690,7 +693,6 @@ int main( int argc, char **argv )
|
||||
proc_init();
|
||||
halloc_util_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
parser_init();
|
||||
function_init();
|
||||
builtin_init();
|
||||
@@ -718,7 +720,6 @@ int main( int argc, char **argv )
|
||||
builtin_destroy();
|
||||
complete_destroy();
|
||||
wutil_destroy();
|
||||
exec_destroy();
|
||||
event_destroy();
|
||||
proc_destroy();
|
||||
halloc_util_destroy();
|
||||
|
||||
34
fishd.c
34
fishd.c
@@ -6,7 +6,7 @@ variables from ~/.fishd, and takes care of communication between fish
|
||||
instances. When no clients are running, fishd will automatically shut
|
||||
down and save.
|
||||
|
||||
\subsection fishd-commands Commands
|
||||
\section fishd-commands Commands
|
||||
|
||||
Fishd works by sending and receiving commands. Each command is ended
|
||||
with a newline. These are the commands supported by fishd:
|
||||
@@ -88,7 +88,12 @@ time the original barrier request was sent have been received.
|
||||
/**
|
||||
Small greeting to show that fishd is running
|
||||
*/
|
||||
#define GREETING "#Fish universal variable daemon\n"
|
||||
#define GREETING "# Fish universal variable daemon\n"
|
||||
|
||||
/**
|
||||
Small not about not editing ~/.fishd manually. Inserted at the top of all .fishd files.
|
||||
*/
|
||||
#define SAVE_MSG "# This file is automatically generated by the fishd universal variable daemon.\n# Do NOT edit it directly, your changes will be overwritten.\n"
|
||||
|
||||
/**
|
||||
The name of the save file. The hostname is appended to this.
|
||||
@@ -110,6 +115,11 @@ time the original barrier request was sent have been received.
|
||||
*/
|
||||
#define LOCKTIMEOUT 1
|
||||
|
||||
/**
|
||||
Getopt short switches for fishd
|
||||
*/
|
||||
#define GETOPT_STRING "hv"
|
||||
|
||||
/**
|
||||
The list of connections to clients
|
||||
*/
|
||||
@@ -225,7 +235,7 @@ static int get_socket()
|
||||
debug( 0, L"Unable to obtain lock on socket, exiting" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
debug( 1, L"Acquired lockfile: %s", lockfile );
|
||||
debug( 4, L"Acquired lockfile: %s", lockfile );
|
||||
|
||||
local.sun_family = AF_UNIX;
|
||||
strcpy( local.sun_path, sock_name );
|
||||
@@ -273,7 +283,7 @@ static int get_socket()
|
||||
|
||||
unlock:
|
||||
(void)unlink( lockfile );
|
||||
debug( 1, L"Released lockfile: %s", lockfile );
|
||||
debug( 4, L"Released lockfile: %s", lockfile );
|
||||
/*
|
||||
End critical section protected by lock
|
||||
*/
|
||||
@@ -401,7 +411,7 @@ void load_or_save( int save)
|
||||
strcat( name, FILE );
|
||||
strcat( name, hostname );
|
||||
|
||||
debug( 1, L"Open file for %s: '%s'",
|
||||
debug( 4, L"Open file for %s: '%s'",
|
||||
save?"saving":"loading",
|
||||
name );
|
||||
|
||||
@@ -414,14 +424,18 @@ void load_or_save( int save)
|
||||
wperror( L"open" );
|
||||
return;
|
||||
}
|
||||
debug( 1, L"File open on fd %d", c.fd );
|
||||
debug( 4, L"File open on fd %d", c.fd );
|
||||
|
||||
sb_init( &c.input );
|
||||
memset (&c.wstate, '\0', sizeof (mbstate_t));
|
||||
q_init( &c.unsent );
|
||||
|
||||
if( save )
|
||||
{
|
||||
|
||||
write( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
|
||||
enqueue_all( &c );
|
||||
}
|
||||
else
|
||||
read_message( &c );
|
||||
|
||||
@@ -502,14 +516,14 @@ int main( int argc, char ** argv )
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"hv",
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"hv" );
|
||||
GETOPT_STRING );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
@@ -587,7 +601,7 @@ int main( int argc, char ** argv )
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 1, L"Connected with new child on fd %d", child_socket );
|
||||
debug( 4, L"Connected with new child on fd %d", child_socket );
|
||||
|
||||
if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 )
|
||||
{
|
||||
@@ -644,7 +658,7 @@ int main( int argc, char ** argv )
|
||||
{
|
||||
if( c->killme )
|
||||
{
|
||||
debug( 1, L"Close connection %d", c->fd );
|
||||
debug( 4, L"Close connection %d", c->fd );
|
||||
|
||||
close(c->fd );
|
||||
sb_destroy( &c->input );
|
||||
|
||||
116
function.c
116
function.c
@@ -36,9 +36,22 @@ typedef struct
|
||||
wchar_t *cmd;
|
||||
/** Function description */
|
||||
wchar_t *desc;
|
||||
/**
|
||||
File where this function was defined
|
||||
*/
|
||||
const wchar_t *definition_file;
|
||||
/**
|
||||
Line where definition started
|
||||
*/
|
||||
int definition_offset;
|
||||
/**
|
||||
Flag for specifying functions which are actually key bindings
|
||||
*/
|
||||
int is_binding;
|
||||
|
||||
/**
|
||||
Flag for specifying that this function was automatically loaded
|
||||
*/
|
||||
int is_autoload;
|
||||
}
|
||||
function_data_t;
|
||||
@@ -47,6 +60,12 @@ typedef struct
|
||||
Table containing all functions
|
||||
*/
|
||||
static hash_table_t function;
|
||||
|
||||
/**
|
||||
Kludgy flag set by the load function in order to tell function_add
|
||||
that the function being defined is autoloaded. There should be a
|
||||
better way to do this...
|
||||
*/
|
||||
static int is_autoload = 0;
|
||||
|
||||
/**
|
||||
@@ -87,7 +106,7 @@ static void autoload_names( array_list_t *out, int get_hidden )
|
||||
|
||||
al_init( &path_list );
|
||||
|
||||
expand_variable_array( path_var, &path_list );
|
||||
tokenize_variable_array( path_var, &path_list );
|
||||
for( i=0; i<al_get_count( &path_list ); i++ )
|
||||
{
|
||||
wchar_t *ndir = (wchar_t *)al_get( &path_list, i );
|
||||
@@ -110,13 +129,13 @@ static void autoload_names( array_list_t *out, int get_hidden )
|
||||
*suffix = 0;
|
||||
dup = intern( fn );
|
||||
if( !dup )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
al_push( out, dup );
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
al_foreach( &path_list, (void (*)(const void *))&free );
|
||||
al_foreach( &path_list, &free );
|
||||
al_destroy( &path_list );
|
||||
}
|
||||
|
||||
@@ -124,8 +143,8 @@ static void autoload_names( array_list_t *out, int get_hidden )
|
||||
/**
|
||||
Free all contents of an entry to the function hash table
|
||||
*/
|
||||
static void clear_function_entry( const void *key,
|
||||
const void *data )
|
||||
static void clear_function_entry( void *key,
|
||||
void *data )
|
||||
{
|
||||
function_data_t *d = (function_data_t *)data;
|
||||
free( (void *)d->cmd );
|
||||
@@ -157,10 +176,13 @@ void function_add( const wchar_t *name,
|
||||
wchar_t *cmd_end;
|
||||
function_data_t *d;
|
||||
|
||||
CHECK( name, );
|
||||
CHECK( val, );
|
||||
|
||||
function_remove( name );
|
||||
|
||||
d = malloc( sizeof( function_data_t ) );
|
||||
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos );
|
||||
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos )-1;
|
||||
d->cmd = wcsdup( val );
|
||||
|
||||
cmd_end = d->cmd + wcslen(d->cmd)-1;
|
||||
@@ -185,6 +207,9 @@ void function_add( const wchar_t *name,
|
||||
|
||||
int function_exists( const wchar_t *cmd )
|
||||
{
|
||||
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
if( parser_is_reserved(cmd) )
|
||||
return 0;
|
||||
|
||||
@@ -195,13 +220,15 @@ int function_exists( const wchar_t *cmd )
|
||||
void function_remove( const wchar_t *name )
|
||||
{
|
||||
void *key;
|
||||
const void *dv;
|
||||
void *dv;
|
||||
function_data_t *d;
|
||||
event_t ev;
|
||||
|
||||
CHECK( name, );
|
||||
|
||||
hash_remove( &function,
|
||||
name,
|
||||
(const void **) &key,
|
||||
&key,
|
||||
&dv );
|
||||
|
||||
d=(function_data_t *)dv;
|
||||
@@ -214,11 +241,24 @@ void function_remove( const wchar_t *name )
|
||||
event_remove( &ev );
|
||||
|
||||
clear_function_entry( key, d );
|
||||
|
||||
/*
|
||||
Notify the autoloader that the specified function is erased, but
|
||||
only if this call to fish_remove is not made by the autoloader
|
||||
itself.
|
||||
*/
|
||||
if( !is_autoload )
|
||||
{
|
||||
parse_util_unload( name, L"fish_function_path", 0 );
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *function_get_definition( const wchar_t *argv )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
CHECK( argv, 0 );
|
||||
|
||||
load( argv );
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
if( data == 0 )
|
||||
@@ -229,6 +269,9 @@ const wchar_t *function_get_definition( const wchar_t *argv )
|
||||
const wchar_t *function_get_desc( const wchar_t *argv )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
CHECK( argv, 0 );
|
||||
|
||||
load( argv );
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
if( data == 0 )
|
||||
@@ -240,6 +283,10 @@ const wchar_t *function_get_desc( const wchar_t *argv )
|
||||
void function_set_desc( const wchar_t *name, const wchar_t *desc )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
CHECK( name, );
|
||||
CHECK( desc, );
|
||||
|
||||
load( name );
|
||||
data = (function_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
@@ -248,34 +295,76 @@ void function_set_desc( const wchar_t *name, const wchar_t *desc )
|
||||
data->desc =wcsdup(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
Search arraylist of strings for specified string
|
||||
*/
|
||||
static int al_contains_str( array_list_t *list, const wchar_t * str )
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<al_get_count( list ); i++ )
|
||||
{
|
||||
if( wcscmp( al_get( list, i ), str) == 0 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function for removing hidden functions
|
||||
*/
|
||||
static void get_names_internal( const void *key,
|
||||
const void *val,
|
||||
static void get_names_internal( void *key,
|
||||
void *val,
|
||||
void *aux )
|
||||
{
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
function_data_t *f = (function_data_t *)val;
|
||||
|
||||
if( name[0] != L'_' && !f->is_binding)
|
||||
if( name[0] != L'_' && !f->is_binding && !al_contains_str( (array_list_t *)aux, name ) )
|
||||
{
|
||||
al_push( (array_list_t *)aux, name );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function for removing hidden functions
|
||||
*/
|
||||
static void get_names_internal_all( void *key,
|
||||
void *val,
|
||||
void *aux )
|
||||
{
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
|
||||
if( !al_contains_str( (array_list_t *)aux, name ) )
|
||||
{
|
||||
al_push( (array_list_t *)aux, name );
|
||||
}
|
||||
}
|
||||
|
||||
void function_get_names( array_list_t *list, int get_hidden )
|
||||
{
|
||||
CHECK( list, );
|
||||
|
||||
autoload_names( list, get_hidden );
|
||||
|
||||
if( get_hidden )
|
||||
hash_get_keys( &function, list );
|
||||
{
|
||||
hash_foreach2( &function, &get_names_internal_all, list );
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_foreach2( &function, &get_names_internal, list );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const wchar_t *function_get_definition_file( const wchar_t *argv )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
CHECK( argv, 0 );
|
||||
|
||||
load( argv );
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
if( data == 0 )
|
||||
@@ -288,6 +377,9 @@ const wchar_t *function_get_definition_file( const wchar_t *argv )
|
||||
int function_get_definition_offset( const wchar_t *argv )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
CHECK( argv, -1 );
|
||||
|
||||
load( argv );
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
if( data == 0 )
|
||||
|
||||
57
halloc.c
57
halloc.c
@@ -18,37 +18,92 @@
|
||||
#include "common.h"
|
||||
#include "halloc.h"
|
||||
|
||||
/**
|
||||
Extra size to allocate whenever doing a halloc, in order to fill uyp smaller halloc calls
|
||||
*/
|
||||
#define HALLOC_BLOCK_SIZE 128
|
||||
|
||||
/**
|
||||
Maximum size of trailing halloc space to refuse to discard
|
||||
*/
|
||||
#define HALLOC_SCRAP_SIZE 16
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
/**
|
||||
Debug statistic parameter
|
||||
*/
|
||||
static int child_count=0;
|
||||
/**
|
||||
Debug statistic parameter
|
||||
*/
|
||||
static int child_size=0;
|
||||
/**
|
||||
Debug statistic parameter
|
||||
*/
|
||||
static int alloc_count =0;
|
||||
/**
|
||||
Debug statistic parameter
|
||||
*/
|
||||
static int alloc_spill = 0;
|
||||
/**
|
||||
Debug statistic parameter
|
||||
*/
|
||||
static pid_t pid=0;
|
||||
/**
|
||||
Debug statistic parameter
|
||||
*/
|
||||
static int parent_count=0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
The main datastructure for a main halloc context
|
||||
*/
|
||||
typedef struct halloc
|
||||
{
|
||||
/**
|
||||
List of all addresses and functions to call on them
|
||||
*/
|
||||
array_list_t children;
|
||||
/**
|
||||
Memory scratch area used to fullfil smaller memory allocations
|
||||
*/
|
||||
void *scratch;
|
||||
/**
|
||||
Amount of free space in the scratch area
|
||||
*/
|
||||
size_t scratch_free;
|
||||
long long data[0];
|
||||
#if __STDC_VERSION__ < 199901L
|
||||
/**
|
||||
The actual data. MAde to be of type long long to make sure memory alignment is in order.
|
||||
*/
|
||||
long long data[1]; // Waste one byte on non-C99 compilers... :-(
|
||||
#else
|
||||
long long data[];
|
||||
#endif
|
||||
}
|
||||
halloc_t;
|
||||
|
||||
/**
|
||||
Get the offset of the halloc structure before a data block
|
||||
*/
|
||||
static halloc_t *halloc_from_data( void *data )
|
||||
{
|
||||
return (halloc_t *)(((char *)data) - sizeof( halloc_t ) );
|
||||
}
|
||||
|
||||
/**
|
||||
A function that does nothing
|
||||
*/
|
||||
static void late_free( void *data)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
/**
|
||||
Debug function, called at exit when in debug mode. Prints usage
|
||||
statistics, like number of allocations and number of internal calls
|
||||
to malloc.
|
||||
*/
|
||||
static void woot()
|
||||
{
|
||||
if( getpid() == pid )
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** \file halloc.c
|
||||
/** \file halloc_util.c
|
||||
|
||||
A hierarchical memory allocation system. Works just like talloc
|
||||
used in Samba, except that an arbitrary block allocated with
|
||||
@@ -35,7 +35,7 @@ array_list_t *al_halloc( void *context )
|
||||
{
|
||||
array_list_t *res = halloc( context, sizeof( array_list_t ) );
|
||||
if( !res )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
al_init( res );
|
||||
halloc_register_function( context, (void (*)(void *)) &al_destroy, res );
|
||||
return res;
|
||||
@@ -45,12 +45,15 @@ string_buffer_t *sb_halloc( void *context )
|
||||
{
|
||||
string_buffer_t *res = halloc( context, sizeof( string_buffer_t ) );
|
||||
if( !res )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
sb_init( res );
|
||||
halloc_register_function( context, (void (*)(void *)) &sb_destroy, res );
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
A function that takes a single parameter, which is a function pointer, and calls it.
|
||||
*/
|
||||
static void halloc_passthrough( void *f )
|
||||
{
|
||||
void (*func)() = (void (*)() )f;
|
||||
@@ -71,14 +74,14 @@ void *halloc_register( void *context, void *data )
|
||||
return data;
|
||||
}
|
||||
|
||||
wchar_t *halloc_wcsdup( void *context, wchar_t *in )
|
||||
wchar_t *halloc_wcsdup( void *context, const wchar_t *in )
|
||||
{
|
||||
size_t len=wcslen(in);
|
||||
wchar_t *out = halloc( context, sizeof( wchar_t)*(len+1));
|
||||
|
||||
if( out == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
memcpy( out, in, sizeof( wchar_t)*(len+1));
|
||||
return out;
|
||||
@@ -89,7 +92,7 @@ wchar_t *halloc_wcsndup( void * context, const wchar_t *in, int c )
|
||||
wchar_t *res = halloc( context, sizeof(wchar_t)*(c+1) );
|
||||
if( res == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
wcslcpy( res, in, c+1 );
|
||||
res[c] = L'\0';
|
||||
|
||||
@@ -55,7 +55,7 @@ void *halloc_register( void *context, void *data );
|
||||
Make a copy of the specified string using memory allocated using
|
||||
halloc and the specified context
|
||||
*/
|
||||
wchar_t *halloc_wcsdup( void *context, wchar_t *str );
|
||||
wchar_t *halloc_wcsdup( void *context, const wchar_t *str );
|
||||
|
||||
/**
|
||||
Make a copy of the specified substring using memory allocated using
|
||||
|
||||
637
highlight.c
637
highlight.c
@@ -30,6 +30,13 @@
|
||||
#include "common.h"
|
||||
#include "complete.h"
|
||||
#include "output.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Number of elements in the highlight_var array
|
||||
*/
|
||||
#define VAR_COUNT ( sizeof(highlight_var)/sizeof(wchar_t *) )
|
||||
|
||||
static void highlight_universal_internal( wchar_t * buff,
|
||||
int *color,
|
||||
@@ -40,43 +47,474 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
/**
|
||||
The environment variables used to specify the color of different tokens.
|
||||
*/
|
||||
static wchar_t *hightlight_var[] =
|
||||
static wchar_t *highlight_var[] =
|
||||
{
|
||||
L"fish_color_normal",
|
||||
L"fish_color_command",
|
||||
L"fish_color_subshell",
|
||||
L"fish_color_redirection",
|
||||
L"fish_color_end",
|
||||
L"fish_color_error",
|
||||
L"fish_color_command",
|
||||
L"fish_color_end",
|
||||
L"fish_color_param",
|
||||
L"fish_color_comment",
|
||||
L"fish_color_match",
|
||||
L"fish_color_search_match",
|
||||
L"fish_color_pager_prefix",
|
||||
L"fish_color_pager_completion",
|
||||
L"fish_color_pager_description",
|
||||
L"fish_color_pager_progress"
|
||||
L"fish_color_operator",
|
||||
L"fish_color_escape",
|
||||
L"fish_color_quote",
|
||||
L"fish_color_redirection",
|
||||
L"fish_color_valid_path"
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Tests if the specified string is the prefix of any valid path in the system.
|
||||
|
||||
\return zero it this is not a valid prefix, non-zero otherwise
|
||||
*/
|
||||
static int is_potential_path( const wchar_t *path )
|
||||
{
|
||||
wchar_t *tilde, *unescaped;
|
||||
wchar_t *in, *out;
|
||||
int has_magic = 0;
|
||||
int res = 0;
|
||||
|
||||
void *context = halloc( 0, 0 );
|
||||
|
||||
tilde = expand_tilde( wcsdup(path) );
|
||||
if( tilde )
|
||||
{
|
||||
halloc_register( context, tilde );
|
||||
|
||||
unescaped = unescape( tilde, 1 );
|
||||
if( unescaped )
|
||||
{
|
||||
|
||||
// debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
|
||||
|
||||
halloc_register( context, unescaped );
|
||||
|
||||
for( in = out = unescaped; *in; in++ )
|
||||
{
|
||||
switch( *in )
|
||||
{
|
||||
case PROCESS_EXPAND:
|
||||
case VARIABLE_EXPAND:
|
||||
case VARIABLE_EXPAND_SINGLE:
|
||||
case BRACKET_BEGIN:
|
||||
case BRACKET_END:
|
||||
case BRACKET_SEP:
|
||||
{
|
||||
has_magic = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case INTERNAL_SEPARATOR:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
*(out++) = *in;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
*out = 0;
|
||||
|
||||
if( !has_magic && wcslen( unescaped ) )
|
||||
{
|
||||
int must_be_dir = 0;
|
||||
DIR *dir;
|
||||
must_be_dir = unescaped[wcslen(unescaped)-1] == L'/';
|
||||
if( must_be_dir )
|
||||
{
|
||||
dir = wopendir( unescaped );
|
||||
res = !!dir;
|
||||
closedir( dir );
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *dir_name, *base;
|
||||
struct wdirent *ent;
|
||||
|
||||
dir_name = wdirname( halloc_wcsdup(context, unescaped) );
|
||||
base = wbasename( halloc_wcsdup(context, unescaped) );
|
||||
|
||||
if( (wcscmp( dir_name, L"/" ) == 0 ) &&
|
||||
(wcscmp( base, L"/" ) == 0 ) )
|
||||
{
|
||||
res = 1;
|
||||
}
|
||||
else if( (dir = wopendir( dir_name )) )
|
||||
{
|
||||
|
||||
while( (ent = wreaddir( dir )) )
|
||||
{
|
||||
if( wcsncmp( ent->d_name, base, wcslen(base) ) == 0 )
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir( dir );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
halloc_free( context );
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int highlight_get_color( int highlight )
|
||||
{
|
||||
int i;
|
||||
int idx=0;
|
||||
int result = 0;
|
||||
|
||||
if( highlight < 0 )
|
||||
return FISH_COLOR_NORMAL;
|
||||
if( highlight >= (12) )
|
||||
if( highlight >= (1<<VAR_COUNT) )
|
||||
return FISH_COLOR_NORMAL;
|
||||
|
||||
wchar_t *val = env_get( hightlight_var[highlight]);
|
||||
if( val == 0 )
|
||||
val = env_get( hightlight_var[HIGHLIGHT_NORMAL]);
|
||||
|
||||
if( val == 0 )
|
||||
|
||||
for( i=0; i<(VAR_COUNT-1); i++ )
|
||||
{
|
||||
return FISH_COLOR_NORMAL;
|
||||
if( highlight & (1<<i ))
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t *val = env_get( highlight_var[idx]);
|
||||
|
||||
// debug( 1, L"%d -> %d -> %ls", highlight, idx, val );
|
||||
|
||||
return output_color_code( val );
|
||||
if( val == 0 )
|
||||
val = env_get( highlight_var[0]);
|
||||
|
||||
if( val )
|
||||
result = output_color_code( val );
|
||||
|
||||
if( highlight & HIGHLIGHT_VALID_PATH )
|
||||
{
|
||||
wchar_t *val2 = env_get( L"fish_color_valid_path" );
|
||||
int result2 = output_color_code( val2 );
|
||||
if( result == FISH_COLOR_NORMAL )
|
||||
result = result2;
|
||||
else
|
||||
{
|
||||
if( result2 & FISH_COLOR_BOLD )
|
||||
result |= FISH_COLOR_BOLD;
|
||||
if( result2 & FISH_COLOR_UNDERLINE )
|
||||
result |= FISH_COLOR_UNDERLINE;
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Highligt operators (such as $, ~, %, as well as escaped characters.
|
||||
*/
|
||||
static void highlight_param( const wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
array_list_t *error )
|
||||
{
|
||||
|
||||
|
||||
int mode = 0;
|
||||
int in_pos, len = wcslen( buff );
|
||||
int bracket_count=0;
|
||||
wchar_t c;
|
||||
int normal_status = *color;
|
||||
|
||||
for( in_pos=0;
|
||||
in_pos<len;
|
||||
in_pos++ )
|
||||
{
|
||||
c = buff[in_pos];
|
||||
switch( mode )
|
||||
{
|
||||
|
||||
/*
|
||||
Mode 0 means unquoted string
|
||||
*/
|
||||
case 0:
|
||||
{
|
||||
if( c == L'\\' )
|
||||
{
|
||||
int start_pos = in_pos;
|
||||
in_pos++;
|
||||
|
||||
if( wcschr( L"~%", buff[in_pos] ) )
|
||||
{
|
||||
if( in_pos == 1 )
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
}
|
||||
else if( buff[in_pos]==L',' )
|
||||
{
|
||||
if( bracket_count )
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
}
|
||||
else if( wcschr( L"nrtbe*?$(){}'\"<>^ \\#;|&", buff[in_pos] ) )
|
||||
{
|
||||
color[start_pos]=HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1]=normal_status;
|
||||
}
|
||||
else if( wcschr( L"uUxX01234567", buff[in_pos] ) )
|
||||
{
|
||||
int i;
|
||||
long long res=0;
|
||||
int chars=2;
|
||||
int base=16;
|
||||
|
||||
int byte = 0;
|
||||
wchar_t max_val = ASCII_MAX;
|
||||
|
||||
switch( buff[in_pos] )
|
||||
{
|
||||
case L'u':
|
||||
{
|
||||
chars=4;
|
||||
max_val = UCS2_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'U':
|
||||
{
|
||||
chars=8;
|
||||
max_val = WCHAR_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'x':
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case L'X':
|
||||
{
|
||||
byte=1;
|
||||
max_val = BYTE_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
base=8;
|
||||
chars=3;
|
||||
in_pos--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i<chars; i++ )
|
||||
{
|
||||
int d = convert_digit( buff[++in_pos],base);
|
||||
|
||||
if( d < 0 )
|
||||
{
|
||||
in_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
res=(res*base)|d;
|
||||
}
|
||||
|
||||
if( (res <= max_val) )
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ERROR;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( buff[in_pos]){
|
||||
case L'~':
|
||||
case L'%':
|
||||
{
|
||||
if( in_pos == 0 )
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_OPERATOR;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'$':
|
||||
{
|
||||
wchar_t n = buff[in_pos+1];
|
||||
color[in_pos] = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
|
||||
color[in_pos+1] = normal_status;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'*':
|
||||
case L'?':
|
||||
case L'(':
|
||||
case L')':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_OPERATOR;
|
||||
color[in_pos+1] = normal_status;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'{':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_OPERATOR;
|
||||
color[in_pos+1] = normal_status;
|
||||
bracket_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'}':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_OPERATOR;
|
||||
color[in_pos+1] = normal_status;
|
||||
bracket_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
case L',':
|
||||
{
|
||||
if( bracket_count )
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_OPERATOR;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case L'\'':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_QUOTE;
|
||||
mode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'\"':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_QUOTE;
|
||||
mode = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Mode 1 means single quoted string, i.e 'foo'
|
||||
*/
|
||||
case 1:
|
||||
{
|
||||
if( c == L'\\' )
|
||||
{
|
||||
int start_pos = in_pos;
|
||||
switch( buff[++in_pos] )
|
||||
{
|
||||
case '\\':
|
||||
case L'\'':
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1] = HIGHLIGHT_QUOTE;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( c == L'\'' )
|
||||
{
|
||||
mode = 0;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Mode 2 means double quoted string, i.e. "foo"
|
||||
*/
|
||||
case 2:
|
||||
{
|
||||
switch( c )
|
||||
{
|
||||
case '"':
|
||||
{
|
||||
mode = 0;
|
||||
color[in_pos+1] = normal_status;
|
||||
break;
|
||||
}
|
||||
|
||||
case '\\':
|
||||
{
|
||||
int start_pos = in_pos;
|
||||
switch( buff[++in_pos] )
|
||||
{
|
||||
case L'\0':
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
case '\\':
|
||||
case L'$':
|
||||
case '"':
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1] = HIGHLIGHT_QUOTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case '$':
|
||||
{
|
||||
wchar_t n = buff[in_pos+1];
|
||||
color[in_pos] = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
|
||||
color[in_pos+1] = HIGHLIGHT_QUOTE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,11 +528,21 @@ void highlight_shell( wchar_t * buff,
|
||||
int i;
|
||||
int last_val;
|
||||
wchar_t *last_cmd=0;
|
||||
int len = wcslen(buff);
|
||||
int len;
|
||||
|
||||
void *context;
|
||||
wchar_t *cmd=0;
|
||||
|
||||
CHECK( buff, );
|
||||
CHECK( color, );
|
||||
|
||||
len = wcslen(buff);
|
||||
|
||||
if( !len )
|
||||
return;
|
||||
|
||||
context = halloc( 0, 0 );
|
||||
|
||||
for( i=0; buff[i] != 0; i++ )
|
||||
color[i] = -1;
|
||||
|
||||
@@ -105,6 +553,7 @@ void highlight_shell( wchar_t * buff,
|
||||
int last_type = tok_last_type( &tok );
|
||||
int prev_argc=0;
|
||||
|
||||
|
||||
switch( last_type )
|
||||
{
|
||||
case TOK_STRING:
|
||||
@@ -125,6 +574,27 @@ void highlight_shell( wchar_t * buff,
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_PARAM;
|
||||
}
|
||||
|
||||
if( cmd && (wcscmp( cmd, L"cd" ) == 0) )
|
||||
{
|
||||
wchar_t *dir = expand_one( context,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_SUBSHELL );
|
||||
if( dir )
|
||||
{
|
||||
if( !parser_cdpath_get( context, dir ) )
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
highlight_param( param,
|
||||
&color[tok_get_pos( &tok )],
|
||||
pos-tok_get_pos( &tok ),
|
||||
error );
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -133,9 +603,9 @@ void highlight_shell( wchar_t * buff,
|
||||
/*
|
||||
Command. First check that the command actually exists.
|
||||
*/
|
||||
wchar_t *cmd = expand_one( 0,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
|
||||
cmd = expand_one( context,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
|
||||
|
||||
if( cmd == 0 )
|
||||
{
|
||||
@@ -143,7 +613,6 @@ void highlight_shell( wchar_t * buff,
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *tmp;
|
||||
int is_cmd = 0;
|
||||
int is_subcommand = 0;
|
||||
int mark = tok_get_pos( &tok );
|
||||
@@ -152,8 +621,9 @@ void highlight_shell( wchar_t * buff,
|
||||
if( parser_is_subcommand( cmd ) )
|
||||
{
|
||||
tok_next( &tok );
|
||||
if(( wcscmp( L"-h", tok_last( &tok ) ) == 0 ) ||
|
||||
( wcscmp( L"--help", tok_last( &tok ) ) == 0 ) )
|
||||
if( ( ! parser_is_block( cmd ) ) &&
|
||||
( ( wcscmp( L"-h", tok_last( &tok ) ) == 0 ) ||
|
||||
( wcsncmp( L"--help", tok_last( &tok ), wcslen( tok_last( &tok ) ) ) == 0 && wcslen( tok_last( &tok ) ) >= 3 ) ) )
|
||||
{
|
||||
/*
|
||||
The builtin and command builtins
|
||||
@@ -172,31 +642,37 @@ void highlight_shell( wchar_t * buff,
|
||||
|
||||
if( !is_subcommand )
|
||||
{
|
||||
wchar_t *tmp;
|
||||
/*
|
||||
OK, this is a command, it has been
|
||||
successfully expanded and everything
|
||||
looks ok. Lets check if the command
|
||||
exists.
|
||||
*/
|
||||
|
||||
/*
|
||||
First check if it is a builtin or
|
||||
function, since we don't have to stat
|
||||
any files for that
|
||||
*/
|
||||
is_cmd |= builtin_exists( cmd );
|
||||
is_cmd |= function_exists( cmd );
|
||||
is_cmd |= (tmp=get_filename( cmd )) != 0;
|
||||
|
||||
/*
|
||||
Moving on to expensive tests
|
||||
*/
|
||||
|
||||
/*
|
||||
Check if this is a regular command
|
||||
*/
|
||||
is_cmd |= !!(tmp=parser_get_filename( context, cmd ));
|
||||
|
||||
/*
|
||||
Could not find the command. Maybe it is a path for a implicit cd command.
|
||||
Lets check!
|
||||
Could not find the command. Maybe it is
|
||||
a path for a implicit cd command.
|
||||
*/
|
||||
if( !is_cmd )
|
||||
{
|
||||
wchar_t *pp = parser_cdpath_get( cmd );
|
||||
if( pp )
|
||||
{
|
||||
free( pp );
|
||||
is_cmd = 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
is_cmd |= !!(tmp=parser_cdpath_get( context, cmd ));
|
||||
|
||||
if( is_cmd )
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMAND;
|
||||
@@ -209,15 +685,11 @@ void highlight_shell( wchar_t * buff,
|
||||
}
|
||||
had_cmd = 1;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
if( had_cmd )
|
||||
{
|
||||
if( last_cmd )
|
||||
free( last_cmd );
|
||||
last_cmd = wcsdup( tok_last( &tok ) );
|
||||
}
|
||||
|
||||
last_cmd = halloc_wcsdup( context, tok_last( &tok ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -250,7 +722,7 @@ void highlight_shell( wchar_t * buff,
|
||||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
target = expand_one( 0, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
|
||||
target = expand_one( context, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
|
||||
/*
|
||||
Redirect filename may contain a subshell.
|
||||
If so, it will be ignored/not flagged.
|
||||
@@ -268,7 +740,7 @@ void highlight_shell( wchar_t * buff,
|
||||
|
||||
if( target != 0 )
|
||||
{
|
||||
wchar_t *dir = wcsdup( target );
|
||||
wchar_t *dir = halloc_wcsdup( context, target );
|
||||
wchar_t *dir_end = wcsrchr( dir, L'/' );
|
||||
struct stat buff;
|
||||
/*
|
||||
@@ -284,9 +756,8 @@ void highlight_shell( wchar_t * buff,
|
||||
if( error )
|
||||
al_push( error, wcsdupcat2( L"Directory \'", dir, L"\' does not exist", 0 ) );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
free( dir );
|
||||
|
||||
/*
|
||||
If the file is read from or appended to, check
|
||||
@@ -302,7 +773,6 @@ void highlight_shell( wchar_t * buff,
|
||||
al_push( error, wcsdupcat2( L"File \'", target, L"\' does not exist", 0 ) );
|
||||
}
|
||||
}
|
||||
free( target );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -352,16 +822,13 @@ void highlight_shell( wchar_t * buff,
|
||||
}
|
||||
}
|
||||
|
||||
if( last_cmd )
|
||||
free( last_cmd );
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
/*
|
||||
Locate and syntax highlight subshells recursively
|
||||
*/
|
||||
|
||||
wchar_t *buffcpy = wcsdup( buff );
|
||||
wchar_t *buffcpy = halloc_wcsdup( context, buff );
|
||||
wchar_t *subpos=buffcpy;
|
||||
int done=0;
|
||||
|
||||
@@ -370,8 +837,8 @@ void highlight_shell( wchar_t * buff,
|
||||
wchar_t *begin, *end;
|
||||
|
||||
if( parse_util_locate_cmdsubst( subpos,
|
||||
(const wchar_t **)&begin,
|
||||
(const wchar_t **)&end,
|
||||
&begin,
|
||||
&end,
|
||||
1) <= 0)
|
||||
{
|
||||
break;
|
||||
@@ -383,7 +850,7 @@ void highlight_shell( wchar_t * buff,
|
||||
*end=0;
|
||||
|
||||
highlight_shell( begin+1, color +(begin-buffcpy)+1, -1, error );
|
||||
color[end-buffcpy]=HIGHLIGHT_PARAM;
|
||||
color[end-buffcpy]=HIGHLIGHT_OPERATOR;
|
||||
|
||||
if( done )
|
||||
break;
|
||||
@@ -391,9 +858,11 @@ void highlight_shell( wchar_t * buff,
|
||||
subpos = end+1;
|
||||
|
||||
}
|
||||
free( buffcpy);
|
||||
|
||||
|
||||
/*
|
||||
The highlighting code only changes the first element when the
|
||||
color changes. This fills in the rest.
|
||||
*/
|
||||
last_val=0;
|
||||
for( i=0; buff[i] != 0; i++ )
|
||||
{
|
||||
@@ -403,6 +872,32 @@ void highlight_shell( wchar_t * buff,
|
||||
color[i] = last_val;
|
||||
}
|
||||
|
||||
/*
|
||||
Color potentially valid paths in a special path color if they
|
||||
are the current token.
|
||||
*/
|
||||
|
||||
if( pos >= 0 && pos <= len )
|
||||
{
|
||||
|
||||
wchar_t *tok_begin, *tok_end;
|
||||
wchar_t *token;
|
||||
|
||||
parse_util_token_extent( buff, pos, &tok_begin, &tok_end, 0, 0 );
|
||||
if( tok_begin && tok_end )
|
||||
{
|
||||
token = halloc_wcsndup( context, tok_begin, tok_end-tok_begin );
|
||||
|
||||
if( is_potential_path( token ) )
|
||||
{
|
||||
for( i=tok_begin-buff; i < (tok_end-buff); i++ )
|
||||
{
|
||||
color[i] |= HIGHLIGHT_VALID_PATH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
highlight_universal_internal( buff, color, pos, error );
|
||||
|
||||
@@ -416,6 +911,9 @@ void highlight_shell( wchar_t * buff,
|
||||
color[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
halloc_free( context );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,15 +963,15 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
{
|
||||
if( prev_q == *str )
|
||||
{
|
||||
int pos1, pos2;
|
||||
long pos1, pos2;
|
||||
|
||||
level--;
|
||||
pos1 = (int)al_pop( &l );
|
||||
pos1 = (long)al_pop( &l );
|
||||
pos2 = str-buff;
|
||||
if( pos1==pos || pos2==pos )
|
||||
{
|
||||
color[pos1]|=HIGHLIGHT_MATCH<<8;
|
||||
color[pos2]|=HIGHLIGHT_MATCH<<8;
|
||||
color[pos1]|=HIGHLIGHT_MATCH<<16;
|
||||
color[pos2]|=HIGHLIGHT_MATCH<<16;
|
||||
match_found = 1;
|
||||
|
||||
}
|
||||
@@ -498,7 +996,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
al_destroy( &l );
|
||||
|
||||
if( !match_found )
|
||||
color[pos] = HIGHLIGHT_ERROR<<8;
|
||||
color[pos] = HIGHLIGHT_ERROR<<16;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -511,8 +1009,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
wchar_t inc_char = buff[pos];
|
||||
int level = 0;
|
||||
wchar_t *str = &buff[pos];
|
||||
int match_found=0;
|
||||
|
||||
int match_found=0;
|
||||
|
||||
while( (str >= buff) && *str)
|
||||
{
|
||||
@@ -523,8 +1020,8 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
if( level == 0 )
|
||||
{
|
||||
int pos2 = str-buff;
|
||||
color[pos]|=HIGHLIGHT_MATCH<<8;
|
||||
color[pos2]|=HIGHLIGHT_MATCH<<8;
|
||||
color[pos]|=HIGHLIGHT_MATCH<<16;
|
||||
color[pos2]|=HIGHLIGHT_MATCH<<16;
|
||||
match_found=1;
|
||||
break;
|
||||
}
|
||||
@@ -532,7 +1029,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
}
|
||||
|
||||
if( !match_found )
|
||||
color[pos] = HIGHLIGHT_ERROR<<8;
|
||||
color[pos] = HIGHLIGHT_ERROR<<16;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,7 +1041,7 @@ void highlight_universal( wchar_t * buff,
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; buff[i] != 0; i++ )
|
||||
for( i=0; buff[i]; i++ )
|
||||
color[i] = 0;
|
||||
|
||||
highlight_universal_internal( buff, color, pos, error );
|
||||
|
||||
53
highlight.h
53
highlight.h
@@ -9,6 +9,59 @@
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
Internal value representing highlighting of normal text
|
||||
*/
|
||||
#define HIGHLIGHT_NORMAL 0x1
|
||||
/**
|
||||
Internal value representing highlighting of an error
|
||||
*/
|
||||
#define HIGHLIGHT_ERROR 0x2
|
||||
/**
|
||||
Internal value representing highlighting of a command
|
||||
*/
|
||||
#define HIGHLIGHT_COMMAND 0x4
|
||||
/**
|
||||
Internal value representing highlighting of a process separator
|
||||
*/
|
||||
#define HIGHLIGHT_END 0x8
|
||||
/**
|
||||
Internal value representing highlighting of a regular command parameter
|
||||
*/
|
||||
#define HIGHLIGHT_PARAM 0x10
|
||||
/**
|
||||
Internal value representing highlighting of a comment
|
||||
*/
|
||||
#define HIGHLIGHT_COMMENT 0x20
|
||||
/**
|
||||
Internal value representing highlighting of a matching parenteses, etc.
|
||||
*/
|
||||
#define HIGHLIGHT_MATCH 0x40
|
||||
/**
|
||||
Internal value representing highlighting of a search match
|
||||
*/
|
||||
#define HIGHLIGHT_SEARCH_MATCH 0x80
|
||||
/**
|
||||
Internal value representing highlighting of an operator
|
||||
*/
|
||||
#define HIGHLIGHT_OPERATOR 0x100
|
||||
/**
|
||||
Internal value representing highlighting of an escape sequence
|
||||
*/
|
||||
#define HIGHLIGHT_ESCAPE 0x200
|
||||
/**
|
||||
Internal value representing highlighting of a quoted string
|
||||
*/
|
||||
#define HIGHLIGHT_QUOTE 0x400
|
||||
/**
|
||||
Internal value representing highlighting of an IO redirection
|
||||
*/
|
||||
#define HIGHLIGHT_REDIRECTION 0x800
|
||||
/**
|
||||
Internal value representing highlighting a potentially valid path
|
||||
*/
|
||||
#define HIGHLIGHT_VALID_PATH 0x1000
|
||||
|
||||
/**
|
||||
Perform syntax highlighting for the shell commands in buff. The result is
|
||||
stored in the color array as a color_code from the HIGHLIGHT_ enum
|
||||
|
||||
101
history.c
101
history.c
@@ -41,15 +41,20 @@ typedef struct
|
||||
Number of entries
|
||||
*/
|
||||
int count;
|
||||
|
||||
/**
|
||||
Last history item
|
||||
*/
|
||||
ll_node_t *last;
|
||||
|
||||
/**
|
||||
The last item loaded from file
|
||||
*/
|
||||
ll_node_t *last_loaded;
|
||||
|
||||
/**
|
||||
Set to one if the file containing the saved history has been loaded
|
||||
*/
|
||||
int is_loaded;
|
||||
}
|
||||
history_data;
|
||||
@@ -79,7 +84,9 @@ static int past_end =1;
|
||||
static int history_count=0;
|
||||
|
||||
/**
|
||||
The name of the current history list. The name is used to switch between history lists for different commands as sell as for deciding the name of the file to save the history in.
|
||||
The name of the current history list. The name is used to switch
|
||||
between history lists for different commands as sell as for
|
||||
deciding the name of the file to save the history in.
|
||||
*/
|
||||
static wchar_t *mode_name;
|
||||
|
||||
@@ -91,18 +98,24 @@ static hash_table_t history_table;
|
||||
/**
|
||||
Flag, set to 1 once the history file has been loaded
|
||||
*/
|
||||
static int is_loaded;
|
||||
static int is_loaded=0;
|
||||
|
||||
/**
|
||||
Load history from file
|
||||
*/
|
||||
static void history_load()
|
||||
static int history_load()
|
||||
{
|
||||
wchar_t *fn;
|
||||
wchar_t *buff=0;
|
||||
int buff_len=0;
|
||||
FILE *in_stream;
|
||||
hash_table_t used;
|
||||
int res = 0;
|
||||
|
||||
if( !mode_name )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
is_loaded = 1;
|
||||
|
||||
@@ -129,7 +142,7 @@ static void history_load()
|
||||
free( fn );
|
||||
free( buff );
|
||||
signal_unblock();
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -147,7 +160,7 @@ static void history_load()
|
||||
history_current = malloc( sizeof( ll_node_t ) );
|
||||
if( !history_current )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
}
|
||||
|
||||
@@ -175,6 +188,8 @@ static void history_load()
|
||||
{
|
||||
debug( 1, L"The following non-fatal error occurred while reading command history from \'%ls\':", mode_name );
|
||||
wperror( L"fopen" );
|
||||
res = -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -186,6 +201,8 @@ static void history_load()
|
||||
free( fn );
|
||||
last_loaded = history_last;
|
||||
signal_unblock();
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
void history_init()
|
||||
@@ -202,6 +219,10 @@ static void history_to_hash()
|
||||
{
|
||||
history_data *d;
|
||||
|
||||
if( !mode_name )
|
||||
return;
|
||||
|
||||
|
||||
d = (history_data *)hash_get( &history_table,
|
||||
mode_name );
|
||||
|
||||
@@ -225,12 +246,22 @@ void history_set_mode( wchar_t *name )
|
||||
|
||||
if( mode_name )
|
||||
{
|
||||
/*
|
||||
Move the current history to the hashtable
|
||||
*/
|
||||
history_to_hash();
|
||||
}
|
||||
|
||||
/*
|
||||
See if the new history already exists
|
||||
*/
|
||||
curr = (history_data *)hash_get( &history_table,
|
||||
name );
|
||||
if( curr )
|
||||
{
|
||||
/*
|
||||
Yes. Restore it.
|
||||
*/
|
||||
mode_name = (wchar_t *)hash_get_key( &history_table,
|
||||
name );
|
||||
history_current = history_last = curr->last;
|
||||
@@ -240,6 +271,9 @@ void history_set_mode( wchar_t *name )
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Nope. Create a new history list.
|
||||
*/
|
||||
history_count=0;
|
||||
history_last = history_current = last_loaded=0;
|
||||
mode_name = wcsdup( name );
|
||||
@@ -291,7 +325,9 @@ static void history_save()
|
||||
history_count=0;
|
||||
past_end=1;
|
||||
|
||||
history_load();
|
||||
if( !history_load() )
|
||||
{
|
||||
|
||||
if( real_pos != 0 )
|
||||
{
|
||||
/*
|
||||
@@ -349,6 +385,8 @@ static void history_save()
|
||||
}
|
||||
free( fn );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -356,7 +394,7 @@ static void history_save()
|
||||
Save the specified mode to file
|
||||
*/
|
||||
|
||||
static void history_destroy_mode( const void *name, const void *link )
|
||||
static void history_destroy_mode( void *name, void *link )
|
||||
{
|
||||
mode_name = (wchar_t *)name;
|
||||
history_data *d = (history_data *)link;
|
||||
@@ -366,7 +404,7 @@ static void history_destroy_mode( const void *name, const void *link )
|
||||
past_end=1;
|
||||
|
||||
// fwprintf( stderr, L"Destroy history mode \'%ls\'\n", mode_name );
|
||||
|
||||
|
||||
if( history_last )
|
||||
{
|
||||
history_save();
|
||||
@@ -385,11 +423,12 @@ static void history_destroy_mode( const void *name, const void *link )
|
||||
|
||||
void history_destroy()
|
||||
{
|
||||
|
||||
/**
|
||||
Make sure current mode is in table
|
||||
*/
|
||||
history_to_hash();
|
||||
|
||||
|
||||
/**
|
||||
Save all modes in table
|
||||
*/
|
||||
@@ -408,7 +447,13 @@ void history_destroy()
|
||||
static ll_node_t *history_find( ll_node_t *n, const wchar_t *s )
|
||||
{
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
{
|
||||
if( history_load() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( n == 0 )
|
||||
return 0;
|
||||
@@ -427,7 +472,13 @@ void history_add( const wchar_t *str )
|
||||
ll_node_t *old_node;
|
||||
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
{
|
||||
if( history_load() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( wcslen( str ) == 0 )
|
||||
return;
|
||||
@@ -478,13 +529,19 @@ static int history_test( const wchar_t *needle, const wchar_t *haystack )
|
||||
/*
|
||||
return wcsncmp( haystack, needle, wcslen(needle) )==0;
|
||||
*/
|
||||
return (int)wcsstr( haystack, needle );
|
||||
return !!wcsstr( haystack, needle );
|
||||
}
|
||||
|
||||
const wchar_t *history_prev_match( const wchar_t *str )
|
||||
{
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
{
|
||||
if( history_load() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( history_current == 0 )
|
||||
return str;
|
||||
@@ -508,7 +565,13 @@ const wchar_t *history_prev_match( const wchar_t *str )
|
||||
const wchar_t *history_next_match( const wchar_t *str)
|
||||
{
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
{
|
||||
if( history_load() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( history_current == 0 )
|
||||
return str;
|
||||
@@ -546,9 +609,15 @@ wchar_t *history_get( int idx )
|
||||
{
|
||||
ll_node_t *n;
|
||||
int i;
|
||||
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
|
||||
{
|
||||
if( history_load() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
n = history_last;
|
||||
|
||||
if( idx<0)
|
||||
|
||||
69
input.c
69
input.c
@@ -1,5 +1,5 @@
|
||||
/** \file input.c
|
||||
|
||||
a
|
||||
Functions for reading a character of input from stdin, using the
|
||||
inputrc information for key bindings.
|
||||
|
||||
@@ -61,6 +61,7 @@ implementation in fish is as of yet incomplete.
|
||||
#include "signal.h"
|
||||
#include "translate.h"
|
||||
#include "output.h"
|
||||
#include "intern.h"
|
||||
|
||||
static void input_read_inputrc( wchar_t *fn );
|
||||
|
||||
@@ -71,9 +72,9 @@ static void input_read_inputrc( wchar_t *fn );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wchar_t *seq; /**< Character sequence which generates this event */
|
||||
wchar_t *seq_desc; /**< Description of the character sequence suitable for printing on-screen */
|
||||
wchar_t *command; /**< command that should be evaluated by this mapping */
|
||||
const wchar_t *seq; /**< Character sequence which generates this event */
|
||||
const wchar_t *seq_desc; /**< Description of the character sequence suitable for printing on-screen */
|
||||
const wchar_t *command; /**< command that should be evaluated by this mapping */
|
||||
|
||||
}
|
||||
mapping;
|
||||
@@ -90,7 +91,7 @@ typedef struct
|
||||
/**
|
||||
Names of all the readline functions supported
|
||||
*/
|
||||
const wchar_t *name_arr[] =
|
||||
static const wchar_t *name_arr[] =
|
||||
{
|
||||
L"beginning-of-line",
|
||||
L"end-of-line",
|
||||
@@ -119,14 +120,16 @@ const wchar_t *name_arr[] =
|
||||
L"history-token-search-backward",
|
||||
L"history-token-search-forward",
|
||||
L"self-insert",
|
||||
L"null"
|
||||
L"null",
|
||||
L"eof"
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Description of each supported readline function
|
||||
*/
|
||||
const wchar_t *desc_arr[] =
|
||||
/*
|
||||
static const wchar_t *desc_arr[] =
|
||||
{
|
||||
L"Move to beginning of line",
|
||||
L"Move to end of line",
|
||||
@@ -155,14 +158,15 @@ const wchar_t *desc_arr[] =
|
||||
L"Search backward through list of previous commands for matching token",
|
||||
L"Search forward through list of previous commands for matching token",
|
||||
L"Insert the pressed key",
|
||||
L"Do nothing"
|
||||
L"Do nothing",
|
||||
L"End of file"
|
||||
}
|
||||
;
|
||||
|
||||
*/
|
||||
/**
|
||||
Internal code for each supported readline function
|
||||
*/
|
||||
const wchar_t code_arr[] =
|
||||
static const wchar_t code_arr[] =
|
||||
{
|
||||
R_BEGINNING_OF_LINE,
|
||||
R_END_OF_LINE,
|
||||
@@ -191,7 +195,8 @@ const wchar_t code_arr[] =
|
||||
R_HISTORY_TOKEN_SEARCH_BACKWARD,
|
||||
R_HISTORY_TOKEN_SEARCH_FORWARD,
|
||||
R_SELF_INSERT,
|
||||
R_NULL
|
||||
R_NULL,
|
||||
R_EOF
|
||||
}
|
||||
;
|
||||
|
||||
@@ -228,9 +233,12 @@ static int inputrc_block_count=0;
|
||||
*/
|
||||
static int inputrc_error = 0;
|
||||
|
||||
/**
|
||||
Set to one when the input subsytem has been initialized.
|
||||
*/
|
||||
static int is_init = 0;
|
||||
|
||||
wchar_t input_get_code( wchar_t *name )
|
||||
wchar_t input_get_code( const wchar_t *name )
|
||||
{
|
||||
|
||||
int i;
|
||||
@@ -333,18 +341,16 @@ void add_mapping( const wchar_t *mode,
|
||||
mapping *m = (mapping *)al_get( mappings, i );
|
||||
if( wcscmp( m->seq, s ) == 0 )
|
||||
{
|
||||
free( m->command );
|
||||
free( m->seq_desc );
|
||||
m->seq_desc = wcsdup(d );
|
||||
m->command=wcsdup(c);
|
||||
m->seq_desc = intern(d);
|
||||
m->command = intern(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mapping *m = malloc( sizeof( mapping ) );
|
||||
m->seq = wcsdup( s );
|
||||
m->seq_desc = wcsdup(d );
|
||||
m->command=wcsdup(c);
|
||||
m->seq = intern( s );
|
||||
m->seq_desc = intern(d );
|
||||
m->command = intern(c);
|
||||
al_push( mappings, m );
|
||||
}
|
||||
|
||||
@@ -1125,6 +1131,9 @@ static void input_read_inputrc( wchar_t *fn )
|
||||
}
|
||||
}
|
||||
free( buff );
|
||||
/*
|
||||
Don't need to check exit status of fclose on read-only stream
|
||||
*/
|
||||
fclose( rc );
|
||||
}
|
||||
signal_unblock();
|
||||
@@ -1267,7 +1276,14 @@ static void add_emacs_bindings()
|
||||
add_escaped_mapping( L"emacs", (L"\\C-h"), L"Control-h", L"backward-delete-char" );
|
||||
add_escaped_mapping( L"emacs", (L"\\C-e"), L"Control-e", L"end-of-line" );
|
||||
add_escaped_mapping( L"emacs", (L"\\C-w"), L"Control-w", L"backward-kill-word" );
|
||||
add_escaped_mapping( L"emacs", (L"\\C-p"), L"Control-p", L"history-search-backward" );
|
||||
add_escaped_mapping( L"emacs", (L"\\C-n"), L"Control-n", L"history-search-forward" );
|
||||
add_escaped_mapping( L"emacs", (L"\\C-f"), L"Control-f", L"forward-char" );
|
||||
add_escaped_mapping( L"emacs", (L"\\C-b"), L"Control-b", L"backward-char" );
|
||||
add_escaped_mapping( L"emacs", (L"\e\x7f"), L"Alt-backspace", L"backward-kill-word" );
|
||||
add_escaped_mapping( L"emacs", (L"\eb"), L"Alt-b", L"backward-word" );
|
||||
add_escaped_mapping( L"emacs", (L"\ef"), L"Alt-f", L"forward-word" );
|
||||
add_escaped_mapping( L"emacs", (L"\ed"), L"Alt-d", L"forward-kill-word" );
|
||||
add_terminfo_mapping( L"emacs", (key_ppage), L"Page Up", L"beginning-of-history" );
|
||||
add_terminfo_mapping( L"emacs", (key_npage), L"Page Down", L"end-of-history" );
|
||||
}
|
||||
@@ -1408,22 +1424,13 @@ int input_init()
|
||||
/**
|
||||
Free memory used by the specified mapping
|
||||
*/
|
||||
static void destroy_mapping( const void *key, const void *val )
|
||||
static void destroy_mapping( void *key, void *val )
|
||||
{
|
||||
int i;
|
||||
array_list_t *mappings = (array_list_t *)val;
|
||||
|
||||
for( i=0; i<al_get_count( mappings ); i++ )
|
||||
{
|
||||
mapping *m = (mapping *)al_get( mappings, i );
|
||||
free( m->seq );
|
||||
free( m->seq_desc );
|
||||
|
||||
free( m->command );
|
||||
free(m );
|
||||
}
|
||||
|
||||
al_foreach( mappings, &free );
|
||||
al_destroy( mappings );
|
||||
|
||||
free((void *)key);
|
||||
free((void *)val);
|
||||
}
|
||||
|
||||
4
input.h
4
input.h
@@ -17,7 +17,7 @@ inputrc information for key bindings.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
R_BEGINNING_OF_LINE = R_NULL+1,
|
||||
R_BEGINNING_OF_LINE = R_NULL+10, /* This give input_common ten slots for lowlevel keycodes */
|
||||
R_END_OF_LINE,
|
||||
R_FORWARD_CHAR,
|
||||
R_BACKWARD_CHAR,
|
||||
@@ -111,6 +111,6 @@ void input_parse_inputrc_line( wchar_t *cmd );
|
||||
/**
|
||||
Returns the function for the given function name.
|
||||
*/
|
||||
wchar_t input_get_code( wchar_t *name );
|
||||
wchar_t input_get_code( const wchar_t *name );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -64,7 +64,7 @@ static wint_t readb()
|
||||
{
|
||||
unsigned char arr[1];
|
||||
int do_loop = 0;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
fd_set fd;
|
||||
@@ -93,17 +93,21 @@ static wint_t readb()
|
||||
{
|
||||
int res = interrupt_handler();
|
||||
if( res )
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
do_loop = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
debug( 0, L"Error while reading input from keyboard, shutting down" );
|
||||
wperror(L"read");
|
||||
exit(1);
|
||||
/*
|
||||
The teminal has been closed. Save and exit.
|
||||
*/
|
||||
return R_EOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,17 +119,17 @@ static wint_t readb()
|
||||
{
|
||||
debug( 3, L"Wake up on universal variable event" );
|
||||
env_universal_read_all();
|
||||
debug( 3, L"Return R_NULL" );
|
||||
return R_NULL;
|
||||
do_loop = 1;
|
||||
}
|
||||
}
|
||||
if( FD_ISSET( 0, &fd ) )
|
||||
{
|
||||
if( read_blocked( 0, arr, 1 ) == -1 )
|
||||
if( read_blocked( 0, arr, 1 ) != 1 )
|
||||
{
|
||||
debug( 0, L"Error while reading input from keyboard, shutting down" );
|
||||
wperror(L"read");
|
||||
exit(1);
|
||||
/*
|
||||
The teminal has been closed. Save and exit.
|
||||
*/
|
||||
return R_EOF;
|
||||
}
|
||||
do_loop = 0;
|
||||
}
|
||||
@@ -180,8 +184,8 @@ wchar_t input_common_readch( int timed )
|
||||
|
||||
int sz;
|
||||
|
||||
if( b == R_NULL )
|
||||
return R_NULL;
|
||||
if( (b == R_NULL) || (b == R_EOF) )
|
||||
return b;
|
||||
|
||||
bb=b;
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ enum
|
||||
requested but none could be delivered, or when an exception
|
||||
happened.
|
||||
*/
|
||||
R_NULL = INPUT_COMMON_RESERVED
|
||||
R_NULL = INPUT_COMMON_RESERVED,
|
||||
R_EOF
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
8
intern.c
8
intern.c
@@ -40,7 +40,7 @@ const wchar_t *intern( const wchar_t *in )
|
||||
intern_table = malloc( sizeof( hash_table_t ) );
|
||||
if( !intern_table )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
hash_init( intern_table, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
@@ -59,7 +59,7 @@ const wchar_t *intern( const wchar_t *in )
|
||||
res = wcsdup( in );
|
||||
if( !res )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
hash_put( intern_table, res, res );
|
||||
@@ -81,7 +81,7 @@ const wchar_t *intern_static( const wchar_t *in )
|
||||
intern_static_table = malloc( sizeof( hash_table_t ) );
|
||||
if( !intern_static_table )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
hash_init( intern_static_table, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
@@ -100,7 +100,7 @@ const wchar_t *intern_static( const wchar_t *in )
|
||||
/**
|
||||
Free the specified key/value pair. Should only be called by intern_free_all at shutdown
|
||||
*/
|
||||
static void clear_value( const void *key, const void *data )
|
||||
static void clear_value( void *key, void *data )
|
||||
{
|
||||
debug( 3, L"interned string: '%ls'", data );
|
||||
free( (void *)data );
|
||||
|
||||
19
io.c
19
io.c
@@ -189,7 +189,7 @@ io_data_t *io_duplicate( void *context, io_data_t *l )
|
||||
|
||||
if( !res )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
}
|
||||
|
||||
@@ -213,37 +213,34 @@ io_data_t *io_get( io_data_t *io, int fd )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
static void io_print( io_data_t *io )
|
||||
|
||||
void io_print( io_data_t *io )
|
||||
{
|
||||
if( !io )
|
||||
{
|
||||
fwprintf( stderr, L"\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fwprintf( stderr, L"IO fd %d, type ",
|
||||
debug( 1, L"IO fd %d, type ",
|
||||
io->fd );
|
||||
switch( io->io_mode )
|
||||
{
|
||||
case IO_PIPE:
|
||||
fwprintf(stderr, L"PIPE, data %d\n", io->pipe_fd[io->fd?1:0] );
|
||||
debug( 1, L"PIPE, data %d", io->param1.pipe_fd[io->fd?1:0] );
|
||||
break;
|
||||
|
||||
case IO_FD:
|
||||
fwprintf(stderr, L"FD, copy %d\n", io->old_fd );
|
||||
debug( 1, L"FD, copy %d", io->param1.old_fd );
|
||||
break;
|
||||
|
||||
case IO_BUFFER:
|
||||
fwprintf( stderr, L"BUFFER\n" );
|
||||
debug( 1, L"BUFFER" );
|
||||
break;
|
||||
|
||||
default:
|
||||
fwprintf( stderr, L"OTHER\n" );
|
||||
debug( 1, L"OTHER" );
|
||||
}
|
||||
|
||||
io_print( io->next );
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
5
io.h
5
io.h
@@ -89,4 +89,9 @@ io_data_t *io_buffer_create();
|
||||
*/
|
||||
void io_buffer_read( io_data_t *d );
|
||||
|
||||
/**
|
||||
Print debug information about the specified IO redirection chain to stderr.
|
||||
*/
|
||||
void io_print( io_data_t *io );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
Type ^C to exit the program.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
16
kill.c
16
kill.c
@@ -30,6 +30,7 @@
|
||||
#include "env.h"
|
||||
#include "exec.h"
|
||||
#include "parser.h"
|
||||
#include "halloc.h"
|
||||
|
||||
/**
|
||||
Maximum entries in killring
|
||||
@@ -48,14 +49,11 @@ static wchar_t *cut_buffer=0;
|
||||
*/
|
||||
static int has_xsel()
|
||||
{
|
||||
wchar_t *path = get_filename( L"xsel" );
|
||||
if( path)
|
||||
{
|
||||
free(path);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
void *context = halloc(0, 0);
|
||||
wchar_t *path = parser_get_filename( context, L"xsel" );
|
||||
int res = !!path;
|
||||
halloc_free( context );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +179,7 @@ static void kill_check_x_buffer()
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &list, (void (*)(const void *))&free );
|
||||
al_foreach( &list, &free );
|
||||
al_destroy( &list );
|
||||
}
|
||||
}
|
||||
|
||||
43
main.c
43
main.c
@@ -3,8 +3,7 @@ Copyright (C) 2005 Axel Liljencrantz
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -61,7 +60,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#include "output.h"
|
||||
#include "translate.h"
|
||||
#include "halloc_util.h"
|
||||
#include "history.h"
|
||||
|
||||
/**
|
||||
The string describing the single-character options accepted by the main fish binary
|
||||
*/
|
||||
#define GETOPT_STRING "hilnvc:p:d:"
|
||||
|
||||
/**
|
||||
Parse init files
|
||||
@@ -79,15 +83,16 @@ static int read_init()
|
||||
|
||||
env_set( L"__fish_help_dir", DOCDIR, 0);
|
||||
|
||||
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd 2>/dev/null;. .fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; and . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd 2>/dev/null; and . .fish 2>/dev/null", 0, TOP );
|
||||
|
||||
if( chdir( cwd ) == -1 )
|
||||
{
|
||||
// fwprintf( stderr, L"Invalid directory: %s\n", cwd );
|
||||
// wperror( L"chdir" );
|
||||
// return 0;
|
||||
/*
|
||||
If we can't change back to previos directory, we'll stay in
|
||||
~. Should be a sane default behavior.
|
||||
*/
|
||||
}
|
||||
wcwd = str2wcs( cwd );
|
||||
if( wcwd )
|
||||
@@ -112,6 +117,8 @@ int main( int argc, char **argv )
|
||||
|
||||
char *cmd=0;
|
||||
|
||||
halloc_util_init();
|
||||
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
is_interactive_session=1;
|
||||
program_name=L"fish";
|
||||
@@ -164,14 +171,14 @@ int main( int argc, char **argv )
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"hilnvc:p:d:",
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"hilnvc:p:d:" );
|
||||
GETOPT_STRING );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
@@ -253,12 +260,9 @@ int main( int argc, char **argv )
|
||||
no_exec = 0;
|
||||
}
|
||||
|
||||
common_init();
|
||||
halloc_util_init();
|
||||
|
||||
proc_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
wutil_init();
|
||||
parser_init();
|
||||
builtin_init();
|
||||
@@ -266,6 +270,7 @@ int main( int argc, char **argv )
|
||||
env_init();
|
||||
complete_init();
|
||||
reader_init();
|
||||
history_init();
|
||||
|
||||
if( read_init() )
|
||||
{
|
||||
@@ -274,7 +279,7 @@ int main( int argc, char **argv )
|
||||
wchar_t *cmd_wcs = str2wcs( cmd );
|
||||
res = eval( cmd_wcs, 0, TOP );
|
||||
free(cmd_wcs);
|
||||
reader_exit(0);
|
||||
reader_exit(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -297,10 +302,10 @@ int main( int argc, char **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
sb_init( &sb );
|
||||
|
||||
if( *(argv+2))
|
||||
{
|
||||
sb_init( &sb );
|
||||
|
||||
for( i=1,ptr = argv+2; *ptr; i++, ptr++ )
|
||||
{
|
||||
if( i != 1 )
|
||||
@@ -336,7 +341,8 @@ int main( int argc, char **argv )
|
||||
}
|
||||
|
||||
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
|
||||
|
||||
|
||||
history_destroy();
|
||||
complete_destroy();
|
||||
proc_destroy();
|
||||
env_destroy();
|
||||
@@ -345,12 +351,11 @@ int main( int argc, char **argv )
|
||||
reader_destroy();
|
||||
parser_destroy();
|
||||
wutil_destroy();
|
||||
exec_destroy();
|
||||
event_destroy();
|
||||
|
||||
common_destroy();
|
||||
halloc_util_destroy();
|
||||
intern_free_all();
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
14
mimedb.c
14
mimedb.c
@@ -88,6 +88,11 @@ license. Read the source code of the library for more information.
|
||||
*/
|
||||
#define MIMEDB "mimedb"
|
||||
|
||||
/**
|
||||
Getopt short switches for mimedb
|
||||
*/
|
||||
#define GETOPT_STRING "tfimdalhv"
|
||||
|
||||
/**
|
||||
All types of input and output possible
|
||||
*/
|
||||
@@ -543,6 +548,9 @@ static char *get_description( const char *mimetype )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Don't need to check exit status of close on read-only file descriptors
|
||||
*/
|
||||
close( fd );
|
||||
free( fn );
|
||||
|
||||
@@ -1115,7 +1123,7 @@ static void launch( char *filter, array_list_t *files, int fileno )
|
||||
/**
|
||||
Clean up one entry from the hash table of launch files
|
||||
*/
|
||||
static void clear_entry( const void *key, const void *val )
|
||||
static void clear_entry( void *key, void *val )
|
||||
{
|
||||
/*
|
||||
The key is a mime value, either from the libraries internal hash
|
||||
@@ -1216,14 +1224,14 @@ int main (int argc, char *argv[])
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"tfimdalhv",
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"tfimdalhv" );
|
||||
GETOPT_STRING );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
146
output.c
146
output.c
@@ -113,6 +113,9 @@ static char *writestr_buff = 0;
|
||||
|
||||
static int (*out)(char c) = &writeb_internal;
|
||||
|
||||
/**
|
||||
Cleanup function. Run automatically through halloc
|
||||
*/
|
||||
static void output_destroy()
|
||||
{
|
||||
free( writestr_buff );
|
||||
@@ -120,6 +123,7 @@ static void output_destroy()
|
||||
|
||||
void output_set_writer( int (*writer)(char) )
|
||||
{
|
||||
CHECK( writer, );
|
||||
out = writer;
|
||||
}
|
||||
|
||||
@@ -128,9 +132,23 @@ void set_color( int c, int c2 )
|
||||
{
|
||||
static int last_color = FISH_COLOR_NORMAL;
|
||||
static int last_color2 = FISH_COLOR_NORMAL;
|
||||
static int was_bold=0;
|
||||
static int was_underline=0;
|
||||
int bg_set=0, last_bg_set=0;
|
||||
char *fg = 0, *bg=0;
|
||||
|
||||
int is_bold = 0;
|
||||
int is_underline = 0;
|
||||
|
||||
is_bold |= (c&FISH_COLOR_BOLD)!=0;
|
||||
is_bold |= (c2&FISH_COLOR_BOLD)!=0;
|
||||
|
||||
is_underline |= (c&FISH_COLOR_UNDERLINE)!=0;
|
||||
is_underline |= (c2&FISH_COLOR_UNDERLINE)!=0;
|
||||
|
||||
c = c&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE));
|
||||
c2 = c2&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE));
|
||||
|
||||
if( (set_a_foreground != 0) && (strlen( set_a_foreground) != 0 ) )
|
||||
{
|
||||
fg = set_a_foreground;
|
||||
@@ -145,14 +163,33 @@ void set_color( int c, int c2 )
|
||||
if( (c == FISH_COLOR_RESET) || (c2 == FISH_COLOR_RESET))
|
||||
{
|
||||
c = c2 = FISH_COLOR_NORMAL;
|
||||
was_bold=0;
|
||||
was_underline=0;
|
||||
if( fg )
|
||||
{
|
||||
/*
|
||||
If we exit attibute mode, we must first set a color, or
|
||||
previously coloured text might lose it's
|
||||
color. Terminals are weird...
|
||||
*/
|
||||
writembs( tparm( fg, 0 ) );
|
||||
}
|
||||
writembs( exit_attribute_mode );
|
||||
return;
|
||||
}
|
||||
|
||||
if( was_bold && !is_bold )
|
||||
{
|
||||
/*
|
||||
Only way to exit bold mode is a reset of all attributes.
|
||||
*/
|
||||
writembs( exit_attribute_mode );
|
||||
last_color = FISH_COLOR_NORMAL;
|
||||
last_color2 = FISH_COLOR_NORMAL;
|
||||
was_bold=0;
|
||||
was_underline=0;
|
||||
}
|
||||
|
||||
if( last_color2 != FISH_COLOR_NORMAL &&
|
||||
last_color2 != FISH_COLOR_RESET &&
|
||||
last_color2 != FISH_COLOR_IGNORE )
|
||||
@@ -164,7 +201,6 @@ void set_color( int c, int c2 )
|
||||
}
|
||||
|
||||
if( c2 != FISH_COLOR_NORMAL &&
|
||||
c2 != FISH_COLOR_RESET &&
|
||||
c2 != FISH_COLOR_IGNORE )
|
||||
{
|
||||
/*
|
||||
@@ -180,7 +216,8 @@ void set_color( int c, int c2 )
|
||||
{
|
||||
/*
|
||||
Background color changed and is set, so we enter bold
|
||||
mode to make reading easier
|
||||
mode to make reading easier. This means bold mode is
|
||||
_always_ on when the background color is set.
|
||||
*/
|
||||
writembs( enter_bold_mode );
|
||||
}
|
||||
@@ -191,6 +228,8 @@ void set_color( int c, int c2 )
|
||||
exit bold mode
|
||||
*/
|
||||
writembs( exit_attribute_mode );
|
||||
was_bold=0;
|
||||
was_underline=0;
|
||||
/*
|
||||
We don't know if exit_attribute_mode resets colors, so
|
||||
we set it to something known.
|
||||
@@ -214,6 +253,8 @@ void set_color( int c, int c2 )
|
||||
writembs( exit_attribute_mode );
|
||||
|
||||
last_color2 = FISH_COLOR_NORMAL;
|
||||
was_bold=0;
|
||||
was_underline=0;
|
||||
}
|
||||
else if( ( c >= 0 ) && ( c < FISH_COLOR_NORMAL ) )
|
||||
{
|
||||
@@ -241,6 +282,8 @@ void set_color( int c, int c2 )
|
||||
writembs( tparm( fg, last_color ) );
|
||||
}
|
||||
|
||||
was_bold=0;
|
||||
was_underline=0;
|
||||
last_color2 = c2;
|
||||
}
|
||||
else if ( ( c2 >= 0 ) && ( c2 < FISH_COLOR_NORMAL ) )
|
||||
@@ -252,8 +295,33 @@ void set_color( int c, int c2 )
|
||||
last_color2 = c2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Lastly, we set bold mode and underline mode correctly
|
||||
*/
|
||||
if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set )
|
||||
{
|
||||
if( is_bold && !was_bold )
|
||||
{
|
||||
writembs( tparm( enter_bold_mode ) );
|
||||
}
|
||||
was_bold = is_bold;
|
||||
}
|
||||
|
||||
if( was_underline && !is_underline )
|
||||
{
|
||||
writembs( exit_underline_mode );
|
||||
}
|
||||
|
||||
if( !was_underline && is_underline )
|
||||
{
|
||||
writembs( enter_underline_mode );
|
||||
}
|
||||
was_underline = is_underline;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
perm_left_cursor and parm_right_cursor don't seem to be properly
|
||||
emulated by many terminal emulators, so we only use plain
|
||||
@@ -281,6 +349,9 @@ void move_cursor( int steps )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Default output method, simply calls write() on stdout
|
||||
*/
|
||||
static int writeb_internal( char c )
|
||||
{
|
||||
write( 1, &c, 1 );
|
||||
@@ -295,6 +366,8 @@ int writeb( tputs_arg_t b )
|
||||
|
||||
int writembs( char *str )
|
||||
{
|
||||
CHECK( str, 1 );
|
||||
|
||||
return tputs(str,1,&writeb)==ERR?1:0;
|
||||
}
|
||||
|
||||
@@ -335,6 +408,8 @@ int writech( wint_t ch )
|
||||
void writestr( const wchar_t *str )
|
||||
{
|
||||
char *pos;
|
||||
|
||||
CHECK( str, );
|
||||
|
||||
// while( *str )
|
||||
// writech( *str++ );
|
||||
@@ -365,7 +440,7 @@ void writestr( const wchar_t *str )
|
||||
writestr_buff = realloc( writestr_buff, len );
|
||||
if( !writestr_buff )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
writestr_buff_sz = len;
|
||||
}
|
||||
@@ -390,7 +465,11 @@ void writestr( const wchar_t *str )
|
||||
void writestr_ellipsis( const wchar_t *str, int max_width )
|
||||
{
|
||||
int written=0;
|
||||
int tot = my_wcswidth(str);
|
||||
int tot;
|
||||
|
||||
CHECK( str, );
|
||||
|
||||
tot = my_wcswidth(str);
|
||||
|
||||
if( tot <= max_width )
|
||||
{
|
||||
@@ -422,11 +501,16 @@ void writestr_ellipsis( const wchar_t *str, int max_width )
|
||||
int write_escaped_str( const wchar_t *str, int max_len )
|
||||
{
|
||||
|
||||
wchar_t *out = escape( str, 1 );
|
||||
wchar_t *out;
|
||||
int i;
|
||||
int len = my_wcswidth( out );
|
||||
int len;
|
||||
int written=0;
|
||||
|
||||
CHECK( str, 0 );
|
||||
|
||||
out = escape( str, 1 );
|
||||
len = my_wcswidth( out );
|
||||
|
||||
if( max_len && (max_len < len))
|
||||
{
|
||||
for( i=0; (written+wcwidth(out[i]))<=(max_len-1); i++ )
|
||||
@@ -475,23 +559,41 @@ int writespace( int c )
|
||||
|
||||
int output_color_code( const wchar_t *val )
|
||||
{
|
||||
int i, color=-1;
|
||||
int j, i, color=FISH_COLOR_NORMAL;
|
||||
array_list_t el;
|
||||
int is_bold=0;
|
||||
int is_underline=0;
|
||||
|
||||
for( i=0; i<COLORS; i++ )
|
||||
{
|
||||
if( wcscasecmp( col[i], val ) == 0 )
|
||||
{
|
||||
color = col_idx[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( color >= 0 )
|
||||
{
|
||||
return color;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !val )
|
||||
return FISH_COLOR_NORMAL;
|
||||
|
||||
al_init( &el );
|
||||
tokenize_variable_array( val, &el );
|
||||
|
||||
for( j=0; j<al_get_count( &el ); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &el, j );
|
||||
|
||||
is_bold |= (wcsncmp( next, L"--bold", wcslen(next) ) == 0 ) && wcslen(next)>=3;
|
||||
is_bold |= wcscmp( next, L"-o" ) == 0;
|
||||
|
||||
is_underline |= (wcsncmp( next, L"--underline", wcslen(next) ) == 0 ) && wcslen(next)>=3;
|
||||
is_underline |= wcscmp( next, L"-u" ) == 0;
|
||||
|
||||
for( i=0; i<COLORS; i++ )
|
||||
{
|
||||
if( wcscasecmp( col[i], next ) == 0 )
|
||||
{
|
||||
color = col_idx[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
al_foreach( &el, &free );
|
||||
al_destroy( &el );
|
||||
|
||||
return color | (is_bold?FISH_COLOR_BOLD:0) | (is_underline?FISH_COLOR_UNDERLINE:0);
|
||||
|
||||
}
|
||||
|
||||
29
output.h
29
output.h
@@ -10,21 +10,6 @@
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
enum
|
||||
{
|
||||
HIGHLIGHT_NORMAL,
|
||||
HIGHLIGHT_COMMAND,
|
||||
HIGHLIGHT_SUBSHELL,
|
||||
HIGHLIGHT_REDIRECTION,
|
||||
HIGHLIGHT_END,
|
||||
HIGHLIGHT_ERROR,
|
||||
HIGHLIGHT_PARAM,
|
||||
HIGHLIGHT_COMMENT,
|
||||
HIGHLIGHT_MATCH,
|
||||
HIGHLIGHT_SEARCH_MATCH,
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Constants for various colors as used by the set_color function.
|
||||
*/
|
||||
@@ -39,10 +24,20 @@ enum
|
||||
FISH_COLOR_CYAN,
|
||||
FISH_COLOR_WHITE,
|
||||
/** The default fg color of the terminal */
|
||||
FISH_COLOR_NORMAL
|
||||
FISH_COLOR_NORMAL,
|
||||
FISH_COLOR_IGNORE,
|
||||
FISH_COLOR_RESET
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/**
|
||||
The value to send to set_color to tell it to use a bold font
|
||||
*/
|
||||
#define FISH_COLOR_BOLD 0x80
|
||||
/**
|
||||
The value to send to set_color to tell it to underline the text
|
||||
*/
|
||||
#define FISH_COLOR_UNDERLINE 0x100
|
||||
|
||||
/**
|
||||
Sets the fg and bg color. May be called as often as you like, since
|
||||
|
||||
330
parse_util.c
330
parse_util.c
@@ -29,9 +29,36 @@
|
||||
#include "intern.h"
|
||||
#include "exec.h"
|
||||
#include "env.h"
|
||||
#include "translate.h"
|
||||
#include "wildcard.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
A structure representing the autoload state for a specific variable, e.g. fish_complete_path
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
A table containing the modification times of all loaded
|
||||
files. Failed loads (non-existing files) have modification time
|
||||
0.
|
||||
*/
|
||||
hash_table_t load_time;
|
||||
/**
|
||||
A string containg the path used to find any files to load. If
|
||||
this differs from the current environment variable, the
|
||||
autoloader needs to drop all loaded files and reload them.
|
||||
*/
|
||||
wchar_t *old_path;
|
||||
/**
|
||||
A table containing all the files that are currently being
|
||||
loaded. This is here to help prevent recursion.
|
||||
*/
|
||||
hash_table_t is_loading;
|
||||
}
|
||||
autoload_t;
|
||||
|
||||
|
||||
/**
|
||||
Set of files which have been autoloaded
|
||||
*/
|
||||
@@ -42,22 +69,25 @@ int parse_util_lineno( const wchar_t *str, int len )
|
||||
/**
|
||||
First cached state
|
||||
*/
|
||||
static const wchar_t *prev_str = 0;
|
||||
static wchar_t *prev_str = 0;
|
||||
static int i=0;
|
||||
static int res = 1;
|
||||
|
||||
/**
|
||||
Second cached state
|
||||
*/
|
||||
static const wchar_t *prev_str2 = 0;
|
||||
static wchar_t *prev_str2 = 0;
|
||||
static int i2 = 0;
|
||||
static int res2 = 1;
|
||||
|
||||
CHECK( str, 0 );
|
||||
|
||||
|
||||
if( str != prev_str || i>len )
|
||||
{
|
||||
if( prev_str2 == str && i2 <= len )
|
||||
{
|
||||
const wchar_t *tmp_str = prev_str;
|
||||
wchar_t *tmp_str = prev_str;
|
||||
int tmp_i = i;
|
||||
int tmp_res = res;
|
||||
prev_str = prev_str2;
|
||||
@@ -74,7 +104,7 @@ int parse_util_lineno( const wchar_t *str, int len )
|
||||
i2 = i;
|
||||
res2=res;
|
||||
|
||||
prev_str = str;
|
||||
prev_str = (wchar_t *)str;
|
||||
i=0;
|
||||
res=1;
|
||||
}
|
||||
@@ -89,30 +119,34 @@ int parse_util_lineno( const wchar_t *str, int len )
|
||||
}
|
||||
|
||||
int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
const wchar_t **begin,
|
||||
const wchar_t **end,
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
int allow_incomplete )
|
||||
{
|
||||
const wchar_t *pos;
|
||||
wchar_t *pos;
|
||||
wchar_t prev=0;
|
||||
int syntax_error=0;
|
||||
int paran_count=0;
|
||||
|
||||
const wchar_t *paran_begin=0, *paran_end=0;
|
||||
wchar_t *paran_begin=0, *paran_end=0;
|
||||
|
||||
for( pos=in; *pos; pos++ )
|
||||
CHECK( in, 0 );
|
||||
|
||||
for( pos = (wchar_t *)in; *pos; pos++ )
|
||||
{
|
||||
if( prev != '\\' )
|
||||
{
|
||||
if( wcschr( L"\'\"", *pos ) )
|
||||
{
|
||||
const wchar_t *end = quote_end( pos );
|
||||
if( end && *end)
|
||||
wchar_t *q_end = quote_end( pos );
|
||||
if( q_end && *q_end)
|
||||
{
|
||||
pos=end;
|
||||
pos=q_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -141,7 +175,6 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
prev = *pos;
|
||||
}
|
||||
|
||||
@@ -161,7 +194,7 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
if( begin )
|
||||
*begin = paran_begin;
|
||||
if( end )
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
*end = paran_count?(wchar_t *)in+wcslen(in):paran_end;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -169,55 +202,58 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
|
||||
void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
wchar_t **a,
|
||||
wchar_t **b )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
const wchar_t *pos;
|
||||
wchar_t *begin, *end;
|
||||
wchar_t *pos;
|
||||
const wchar_t *cursor = buff + cursor_pos;
|
||||
|
||||
CHECK( buff, );
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
*a = (wchar_t *)buff;
|
||||
if( b )
|
||||
*b = 0;
|
||||
|
||||
if( !buff )
|
||||
return;
|
||||
|
||||
pos = buff;
|
||||
*b = (wchar_t *)buff+wcslen(buff);
|
||||
|
||||
pos = (wchar_t *)buff;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
int bc, ec;
|
||||
|
||||
if( parse_util_locate_cmdsubst( pos,
|
||||
&begin,
|
||||
&end,
|
||||
1 ) <= 0)
|
||||
{
|
||||
begin=buff;
|
||||
end = buff + wcslen(buff);
|
||||
/*
|
||||
No subshell found
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if( !end )
|
||||
{
|
||||
end = buff + wcslen(buff);
|
||||
end = (wchar_t *)buff + wcslen(buff);
|
||||
}
|
||||
|
||||
bc = begin-buff;
|
||||
ec = end-buff;
|
||||
|
||||
if(( bc < cursor_pos ) && (ec >= cursor_pos) )
|
||||
if(( begin < cursor ) && (end >= cursor) )
|
||||
{
|
||||
begin++;
|
||||
if( a )
|
||||
*a = begin;
|
||||
if( b )
|
||||
*b = end;
|
||||
break;
|
||||
}
|
||||
|
||||
if( !*end )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pos = end+1;
|
||||
}
|
||||
if( a )
|
||||
*a = begin;
|
||||
if( b )
|
||||
*b = end;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,17 +261,19 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
*/
|
||||
static void job_or_process_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b,
|
||||
wchar_t **a,
|
||||
wchar_t **b,
|
||||
int process )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
int finished=0;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
CHECK( buff, );
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
@@ -261,7 +299,7 @@ static void job_or_process_extent( const wchar_t *buff,
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
@@ -284,12 +322,12 @@ static void job_or_process_extent( const wchar_t *buff,
|
||||
{
|
||||
finished=1;
|
||||
if( b )
|
||||
*b = buff + tok_begin;
|
||||
*b = (wchar_t *)buff + tok_begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( a )
|
||||
*a = buff + tok_begin+1;
|
||||
*a = (wchar_t *)buff + tok_begin+1;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -305,16 +343,16 @@ static void job_or_process_extent( const wchar_t *buff,
|
||||
|
||||
void parse_util_process_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
wchar_t **a,
|
||||
wchar_t **b )
|
||||
{
|
||||
job_or_process_extent( buff, pos, a, b, 1 );
|
||||
}
|
||||
|
||||
void parse_util_job_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
wchar_t **a,
|
||||
wchar_t **b )
|
||||
{
|
||||
job_or_process_extent( buff,pos,a, b, 0 );
|
||||
}
|
||||
@@ -322,18 +360,22 @@ void parse_util_job_extent( const wchar_t *buff,
|
||||
|
||||
void parse_util_token_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **tok_begin,
|
||||
const wchar_t **tok_end,
|
||||
const wchar_t **prev_begin,
|
||||
const wchar_t **prev_end )
|
||||
wchar_t **tok_begin,
|
||||
wchar_t **tok_end,
|
||||
wchar_t **prev_begin,
|
||||
wchar_t **prev_end )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
const wchar_t *a, *b, *pa, *pb;
|
||||
wchar_t *a, *b, *pa, *pb;
|
||||
|
||||
CHECK( buff, );
|
||||
|
||||
assert( cursor_pos >= 0 );
|
||||
|
||||
|
||||
a = b = pa = pb = 0;
|
||||
@@ -342,24 +384,24 @@ void parse_util_token_extent( const wchar_t *buff,
|
||||
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
|
||||
pos = cursor_pos - (begin - buff);
|
||||
|
||||
a = buff + pos;
|
||||
|
||||
a = (wchar_t *)buff + pos;
|
||||
b = a;
|
||||
pa = buff + pos;
|
||||
pa = (wchar_t *)buff + pos;
|
||||
pb = pa;
|
||||
|
||||
|
||||
assert( begin >= buff );
|
||||
assert( begin <= (buff+wcslen(buff) ) );
|
||||
assert( end >= begin );
|
||||
assert( end <= (buff+wcslen(buff) ) );
|
||||
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
@@ -382,7 +424,7 @@ void parse_util_token_extent( const wchar_t *buff,
|
||||
*/
|
||||
if( tok_begin > pos )
|
||||
{
|
||||
a = b = buff + pos;
|
||||
a = b = (wchar_t *)buff + pos;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -433,20 +475,32 @@ void parse_util_token_extent( const wchar_t *buff,
|
||||
/**
|
||||
Free hash value, but not hash key
|
||||
*/
|
||||
static void clear_hash_value( const void *key, const void *data )
|
||||
static void clear_hash_value( void *key, void *data, void *aux )
|
||||
{
|
||||
if( aux )
|
||||
{
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
void (*handler)(const wchar_t *)= (void (*)(const wchar_t *))aux;
|
||||
handler( name );
|
||||
}
|
||||
|
||||
free( (void *)data );
|
||||
}
|
||||
|
||||
/**
|
||||
Part of the autoloader cleanup
|
||||
*/
|
||||
static void clear_loaded_entry( const void *key, const void *data )
|
||||
static void clear_loaded_entry( void *key,
|
||||
void *data,
|
||||
void *handler )
|
||||
{
|
||||
hash_table_t *loaded = (hash_table_t *)data;
|
||||
hash_foreach( loaded,
|
||||
&clear_hash_value );
|
||||
hash_destroy( loaded );
|
||||
autoload_t *loaded = (autoload_t *)data;
|
||||
hash_foreach2( &loaded->load_time,
|
||||
&clear_hash_value,
|
||||
handler );
|
||||
hash_destroy( &loaded->load_time );
|
||||
|
||||
free( loaded->old_path );
|
||||
free( loaded );
|
||||
free( (void *)key );
|
||||
}
|
||||
@@ -460,8 +514,9 @@ static void parse_util_destroy()
|
||||
{
|
||||
if( all_loaded )
|
||||
{
|
||||
hash_foreach( all_loaded,
|
||||
&clear_loaded_entry );
|
||||
hash_foreach2( all_loaded,
|
||||
&clear_loaded_entry,
|
||||
0 );
|
||||
|
||||
hash_destroy( all_loaded );
|
||||
free( all_loaded );
|
||||
@@ -469,18 +524,61 @@ static void parse_util_destroy()
|
||||
}
|
||||
}
|
||||
|
||||
void parse_util_load_reset( const wchar_t *path_var )
|
||||
void parse_util_load_reset( const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) )
|
||||
{
|
||||
wchar_t *path_var;
|
||||
|
||||
CHECK( path_var_name, );
|
||||
path_var = env_get( path_var_name );
|
||||
|
||||
if( !path_var )
|
||||
return;
|
||||
|
||||
if( all_loaded )
|
||||
{
|
||||
void *key, *data;
|
||||
hash_remove( all_loaded, path_var, (const void **)&key, (const void **)&data );
|
||||
hash_remove( all_loaded, path_var_name, &key, &data );
|
||||
if( key )
|
||||
clear_loaded_entry( key, data );
|
||||
clear_loaded_entry( key, data, (void *)on_load );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int parse_util_unload( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) )
|
||||
{
|
||||
autoload_t *loaded;
|
||||
void *val;
|
||||
|
||||
CHECK( path_var_name, 0 );
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
if( !all_loaded )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( !loaded )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
hash_remove( &loaded->load_time, cmd, 0, &val );
|
||||
if( val )
|
||||
{
|
||||
if( on_load )
|
||||
{
|
||||
on_load( (wchar_t *)val );
|
||||
}
|
||||
free( val );
|
||||
}
|
||||
|
||||
return !!val;
|
||||
}
|
||||
|
||||
int parse_util_load( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
@@ -493,16 +591,22 @@ int parse_util_load( const wchar_t *cmd,
|
||||
int i;
|
||||
time_t *tm;
|
||||
int reloaded = 0;
|
||||
hash_table_t *loaded;
|
||||
autoload_t *loaded;
|
||||
|
||||
const wchar_t *path_var = env_get( path_var_name );
|
||||
wchar_t *path_var;
|
||||
|
||||
CHECK( path_var_name, 0 );
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
path_var = env_get( path_var_name );
|
||||
|
||||
/*
|
||||
Do we know where to look
|
||||
*/
|
||||
|
||||
if( !path_var )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !all_loaded )
|
||||
{
|
||||
@@ -510,28 +614,57 @@ int parse_util_load( const wchar_t *cmd,
|
||||
halloc_register_function_void( global_context, &parse_util_destroy );
|
||||
if( !all_loaded )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
hash_init( all_loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
||||
loaded = (hash_table_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( !loaded )
|
||||
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( loaded )
|
||||
{
|
||||
loaded = malloc( sizeof( hash_table_t ) );
|
||||
if( hash_get( &loaded->is_loading, cmd ) )
|
||||
{
|
||||
debug( 0, _(L"Could not autoload item %ls, it is already being autoloaded. This is a circular dependency in the autoloading scripts, please remove it."), cmd );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Check if the lookup path has changed. If so, drop all loaded
|
||||
files and start from scratch.
|
||||
*/
|
||||
if( wcscmp( path_var, loaded->old_path ) != 0 )
|
||||
{
|
||||
parse_util_load_reset( path_var_name, on_load);
|
||||
reload = parse_util_load( cmd, path_var_name, on_load, reload );
|
||||
return reload;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
We have never tried to autoload using this name before, set up initial data
|
||||
*/
|
||||
loaded = malloc( sizeof( autoload_t ) );
|
||||
if( !loaded )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_init( &loaded->load_time, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_put( all_loaded, wcsdup(path_var_name), loaded );
|
||||
|
||||
hash_init( &loaded->is_loading, &hash_wcs_func, &hash_wcs_cmp );
|
||||
|
||||
loaded->old_path = wcsdup( path_var );
|
||||
}
|
||||
|
||||
hash_put( &loaded->is_loading, cmd, cmd );
|
||||
|
||||
|
||||
/*
|
||||
Get modification time of file
|
||||
*/
|
||||
tm = (time_t *)hash_get( loaded, cmd );
|
||||
tm = (time_t *)hash_get( &loaded->load_time, cmd );
|
||||
|
||||
/*
|
||||
Did we just check this?
|
||||
@@ -540,6 +673,7 @@ int parse_util_load( const wchar_t *cmd,
|
||||
{
|
||||
if(time(0)-tm[1]<=1)
|
||||
{
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -548,7 +682,10 @@ int parse_util_load( const wchar_t *cmd,
|
||||
Return if already loaded and we are skipping reloading
|
||||
*/
|
||||
if( !reload && tm )
|
||||
{
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !path_list )
|
||||
path_list = al_halloc( global_context);
|
||||
@@ -558,7 +695,7 @@ int parse_util_load( const wchar_t *cmd,
|
||||
else
|
||||
sb_clear( path );
|
||||
|
||||
expand_variable_array( path_var, path_list );
|
||||
tokenize_variable_array( path_var, path_list );
|
||||
|
||||
/*
|
||||
Iterate over path searching for suitable completion files
|
||||
@@ -581,12 +718,12 @@ int parse_util_load( const wchar_t *cmd,
|
||||
{
|
||||
tm = malloc(sizeof(time_t)*2);
|
||||
if( !tm )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
tm[0] = buf.st_mtime;
|
||||
tm[1] = time(0);
|
||||
hash_put( loaded,
|
||||
hash_put( &loaded->load_time,
|
||||
intern( cmd ),
|
||||
tm );
|
||||
|
||||
@@ -615,16 +752,17 @@ int parse_util_load( const wchar_t *cmd,
|
||||
{
|
||||
tm = malloc(sizeof(time_t)*2);
|
||||
if( !tm )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
tm[0] = 0;
|
||||
tm[1] = time(0);
|
||||
hash_put( loaded, intern( cmd ), tm );
|
||||
hash_put( &loaded->load_time, intern( cmd ), tm );
|
||||
}
|
||||
|
||||
al_foreach( path_list, (void (*)(const void *))&free );
|
||||
al_foreach( path_list, &free );
|
||||
al_truncate( path_list, 0 );
|
||||
|
||||
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return reloaded;
|
||||
}
|
||||
|
||||
@@ -655,10 +793,14 @@ void parse_util_set_argv( wchar_t **argv )
|
||||
wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
|
||||
{
|
||||
wchar_t *in, *out;
|
||||
wchar_t *unescaped = wcsdup(str);
|
||||
wchar_t *unescaped;
|
||||
|
||||
CHECK( str, 0 );
|
||||
|
||||
unescaped = wcsdup(str);
|
||||
|
||||
if( !unescaped )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
for( in=out=unescaped; *in; in++ )
|
||||
{
|
||||
|
||||
70
parse_util.h
70
parse_util.h
@@ -20,12 +20,16 @@
|
||||
*/
|
||||
|
||||
int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
const wchar_t **begin,
|
||||
const wchar_t **end,
|
||||
int allow_incomplete );
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
int flags );
|
||||
|
||||
/**
|
||||
Find the beginning and end of the command substitution under the cursor
|
||||
Find the beginning and end of the command substitution under the
|
||||
cursor. If no subshell is found, the entire string is returned. If
|
||||
the current command substitution is not ended, i.e. the closing
|
||||
parenthesis is missing, then the string from the beginning of the
|
||||
substitution to the end of the string is returned.
|
||||
|
||||
\param buff the string to search for subshells
|
||||
\param cursor_pos the position of the cursor
|
||||
@@ -34,8 +38,8 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
*/
|
||||
void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
wchar_t **a,
|
||||
wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and end of the process definition under the cursor
|
||||
@@ -47,8 +51,8 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
*/
|
||||
void parse_util_process_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
wchar_t **a,
|
||||
wchar_t **b );
|
||||
|
||||
|
||||
/**
|
||||
@@ -61,23 +65,27 @@ void parse_util_process_extent( const wchar_t *buff,
|
||||
*/
|
||||
void parse_util_job_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
wchar_t **a,
|
||||
wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and end of the token under the cursor
|
||||
Find the beginning and end of the token under the cursor and the
|
||||
toekn before the current token. Any combination of tok_begin,
|
||||
tok_end, prev_begin and prev_end may be null.
|
||||
|
||||
\param buff the string to search for subshells
|
||||
\param cursor_pos the position of the cursor
|
||||
\param a the start of the searched string
|
||||
\param b the end of the searched string
|
||||
\param tok_begin the start of the current token
|
||||
\param tok_end the end of the current token
|
||||
\param prev_begin the start o the token before the current token
|
||||
\param prev_end the end of the token before the current token
|
||||
*/
|
||||
void parse_util_token_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **tok_begin,
|
||||
const wchar_t **tok_end,
|
||||
const wchar_t **prev_begin,
|
||||
const wchar_t **prev_end );
|
||||
wchar_t **tok_begin,
|
||||
wchar_t **tok_end,
|
||||
wchar_t **prev_begin,
|
||||
wchar_t **prev_end );
|
||||
|
||||
|
||||
/**
|
||||
@@ -87,10 +95,11 @@ int parse_util_lineno( const wchar_t *str, int len );
|
||||
|
||||
/**
|
||||
Autoload the specified file, if it exists in the specified path. Do
|
||||
not load it multiple times unless it's timestamp changes.
|
||||
not load it multiple times unless it's timestamp changes or
|
||||
parse_util_unload is called.
|
||||
|
||||
\param cmd the filename to search for. The suffix '.fish' is always added to this name
|
||||
\param path_var_name the name of an environment variable containing a search path
|
||||
\param path_var_name the environment variable giving the search path
|
||||
\param on_load a callback function to run if a suitable file is found, which has not already been run
|
||||
\param reload wheter to recheck file timestamps on already loaded files
|
||||
*/
|
||||
@@ -100,9 +109,28 @@ int parse_util_load( const wchar_t *cmd,
|
||||
int reload );
|
||||
|
||||
/**
|
||||
Reset the loader for the specified path variable
|
||||
Reset the loader for the specified path variable. This will cause
|
||||
all information on loaded files in the specified directory to be
|
||||
reset.
|
||||
|
||||
\param path_var_name the environment variable giving the search path
|
||||
\param on_load the callback function to use when a file is reloaded
|
||||
\param on_load the callback function to call if the file has been previously loaded
|
||||
*/
|
||||
void parse_util_load_reset( const wchar_t *path_var );
|
||||
void parse_util_load_reset( const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) );
|
||||
|
||||
/**
|
||||
Tell the autoloader that the specified file, in the specified path,
|
||||
is no longer loaded.
|
||||
|
||||
\param cmd the filename to search for. The suffix '.fish' is always added to this name
|
||||
\param path_var_name the environment variable giving the search path
|
||||
\return non-zero if the file was removed, zero if the file had not yet been loaded
|
||||
*/
|
||||
int parse_util_unload( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) );
|
||||
|
||||
/**
|
||||
Set the argv environment variable to the specified null-terminated
|
||||
|
||||
25
parser.h
25
parser.h
@@ -191,10 +191,6 @@ extern block_t *current_block;
|
||||
/** Global event blocks */
|
||||
extern event_block_t *global_event_block;
|
||||
|
||||
|
||||
/** The current error code */
|
||||
extern int error_code;
|
||||
|
||||
/**
|
||||
Current block level io redirections
|
||||
*/
|
||||
@@ -204,9 +200,10 @@ extern io_data_t *block_io;
|
||||
Finds the full path of an executable in a newly allocated string.
|
||||
|
||||
\param cmd The name of the executable.
|
||||
\param context the halloc context to use for memory allocations
|
||||
\return 0 if the command can not be found, the path of the command otherwise.
|
||||
*/
|
||||
wchar_t *get_filename( const wchar_t *cmd );
|
||||
wchar_t *parser_get_filename( void *context, const wchar_t *cmd );
|
||||
|
||||
/**
|
||||
Evaluate the expressions contained in cmd.
|
||||
@@ -315,10 +312,20 @@ const wchar_t *parser_get_block_desc( int block );
|
||||
|
||||
|
||||
/**
|
||||
Test if the specified string can be parsed, or if more bytes need to be read first.
|
||||
The result has the first bit set if the string contains errors, and the second bit is set if the string contains an unclosed block.
|
||||
Test if the specified string can be parsed, or if more bytes need
|
||||
to be read first. The result has the first bit set if the string
|
||||
contains errors, and the second bit is set if the string contains
|
||||
an unclosed block.
|
||||
*/
|
||||
int parser_test( wchar_t * buff, int babble );
|
||||
int parser_test( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
|
||||
|
||||
/**
|
||||
Test if the specified string can be parsed as an argument list,
|
||||
e.g. sent to eval_args. The result has the first bit set if the
|
||||
string contains errors, and the second bit is set if the string
|
||||
contains an unclosed block.
|
||||
*/
|
||||
int parser_test_args( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
|
||||
|
||||
/**
|
||||
Returns the full path of the specified directory. If the \c in is a
|
||||
@@ -327,7 +334,7 @@ int parser_test( wchar_t * buff, int babble );
|
||||
directories i the CDPATH, the full path is returned. If no
|
||||
directory can be found, 0 is returned.
|
||||
*/
|
||||
wchar_t *parser_cdpath_get( wchar_t *in );
|
||||
wchar_t *parser_cdpath_get( void *context, wchar_t *in );
|
||||
|
||||
/**
|
||||
Tell the parser that the specified function may not be run if not
|
||||
|
||||
28
proc.c
28
proc.c
@@ -108,6 +108,9 @@ static string_buffer_t event_pid;
|
||||
*/
|
||||
static string_buffer_t event_status;
|
||||
|
||||
/**
|
||||
A stack containing the values of is_interactive. Used by proc_push_interactive and proc_pop_interactive.
|
||||
*/
|
||||
static array_list_t *interactive_stack;
|
||||
|
||||
void proc_init()
|
||||
@@ -171,6 +174,7 @@ void proc_destroy()
|
||||
|
||||
void proc_set_last_status( int s )
|
||||
{
|
||||
|
||||
last_status = s;
|
||||
// fwprintf( stderr, L"Set last status to %d\n", s );
|
||||
}
|
||||
@@ -182,7 +186,7 @@ int proc_get_last_status()
|
||||
|
||||
job_t *job_create()
|
||||
{
|
||||
int free_id=0;
|
||||
int free_id=1;
|
||||
job_t *res;
|
||||
|
||||
while( job_get( free_id ) != 0 )
|
||||
@@ -204,7 +208,7 @@ job_t *job_create()
|
||||
job_t *job_get( int id )
|
||||
{
|
||||
job_t *res = first_job;
|
||||
if( id == -1 )
|
||||
if( id <= 0 )
|
||||
{
|
||||
return res;
|
||||
}
|
||||
@@ -253,7 +257,7 @@ int job_is_stopped( const job_t *j )
|
||||
|
||||
|
||||
/*
|
||||
Return true if all processes in the job have completed.
|
||||
Return true if the last processes in the job has completed.
|
||||
|
||||
\param j the job to test
|
||||
*/
|
||||
@@ -261,14 +265,11 @@ int job_is_completed( const job_t *j )
|
||||
{
|
||||
process_t *p;
|
||||
|
||||
for (p = j->first_process; p; p = p->next)
|
||||
{
|
||||
if (!p->completed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
for (p = j->first_process; p->next; p = p->next)
|
||||
;
|
||||
|
||||
return p->completed;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,6 +692,10 @@ unsigned long proc_get_jiffies( process_t *p )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Don't need to check exit status of fclose on read-only streams
|
||||
*/
|
||||
fclose( f );
|
||||
return utime+stime+cutime+cstime;
|
||||
|
||||
@@ -1005,6 +1010,7 @@ void job_continue (job_t *j, int cont)
|
||||
signal_unblock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void proc_sanity_check()
|
||||
|
||||
13
proc.h
13
proc.h
@@ -261,7 +261,7 @@ job_t *job_create();
|
||||
|
||||
/**
|
||||
Return the job with the specified job id.
|
||||
If id is -1, return the last job used.
|
||||
If id is 0 or less, return the last job used.
|
||||
*/
|
||||
job_t *job_get(int id);
|
||||
|
||||
@@ -276,7 +276,7 @@ job_t *job_get_from_pid(int pid);
|
||||
int job_is_stopped( const job_t *j );
|
||||
|
||||
/**
|
||||
Tests if the job has completed
|
||||
Tests if the job has completed, i.e. if the last process of the pipeline has ended.
|
||||
*/
|
||||
int job_is_completed( const job_t *j );
|
||||
|
||||
@@ -291,15 +291,15 @@ int job_is_completed( const job_t *j );
|
||||
void job_continue( job_t *j, int cont );
|
||||
|
||||
/**
|
||||
Notify user of nog events. Notify the user about stopped or
|
||||
terminated jobs. Delete terminated jobs from the active job list.
|
||||
Notify the user about stopped or terminated jobs. Delete terminated
|
||||
jobs from the job list.
|
||||
|
||||
\param interactive whether interactive jobs should be reaped as well
|
||||
*/
|
||||
int job_reap( int interactive );
|
||||
|
||||
/**
|
||||
Signal handler for SIGCHLD. Mark any processes with relevant
|
||||
Signal handler for SIGCHLD. Mark any processes with relevant
|
||||
information.
|
||||
*/
|
||||
void job_handle_signal( int signal, siginfo_t *info, void *con );
|
||||
@@ -328,7 +328,8 @@ void proc_update_jiffies();
|
||||
void proc_sanity_check();
|
||||
|
||||
/**
|
||||
Send of an process/job exit event notification. This function is a conveniance wrapper around event_fire().
|
||||
Send a process/job exit event notification. This function is a
|
||||
conveniance wrapper around event_fire().
|
||||
*/
|
||||
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status );
|
||||
|
||||
|
||||
203
reader.c
203
reader.c
@@ -232,6 +232,11 @@ typedef struct reader_data
|
||||
When this is true, the reader will exit
|
||||
*/
|
||||
int end_loop;
|
||||
/**
|
||||
If this is true, exit reader even if there are running
|
||||
jobs. This happens if we press e.g. ^D twice.
|
||||
*/
|
||||
int prev_end_loop;
|
||||
|
||||
/**
|
||||
Pointer to previous reader_data
|
||||
@@ -299,6 +304,11 @@ static void reader_save_status();
|
||||
static void reader_check_status();
|
||||
static void reader_super_highlight_me_plenty( wchar_t * buff, int *color, int pos, array_list_t *error );
|
||||
|
||||
/**
|
||||
Variable to keep track of forced exits - see \c reader_exit_forced();
|
||||
*/
|
||||
static int exit_forced;
|
||||
|
||||
|
||||
/**
|
||||
Give up control of terminal
|
||||
@@ -370,6 +380,12 @@ static int room_for_usec(struct stat *st)
|
||||
return res;
|
||||
}
|
||||
|
||||
int reader_exit_forced()
|
||||
{
|
||||
return exit_forced;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
string_buffer used as temporary storage for the reader_readline function
|
||||
*/
|
||||
@@ -433,7 +449,7 @@ static int check_size()
|
||||
data->color==0 ||
|
||||
data->new_color == 0 )
|
||||
{
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -593,8 +609,8 @@ static void remove_duplicates( array_list_t *l )
|
||||
*/
|
||||
static void set_color_translated( int c )
|
||||
{
|
||||
set_color( highlight_get_color( c & 0xff ),
|
||||
highlight_get_color( (c>>8)&0xff ) );
|
||||
set_color( highlight_get_color( c & 0xffff ),
|
||||
highlight_get_color( (c>>16)&0xffff ) );
|
||||
}
|
||||
|
||||
int reader_interupted()
|
||||
@@ -644,7 +660,7 @@ void reader_write_title()
|
||||
}
|
||||
proc_pop_interactive();
|
||||
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_foreach( &l, &free );
|
||||
al_destroy( &l );
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
}
|
||||
@@ -696,7 +712,8 @@ static int calc_prompt_width( array_list_t *arr )
|
||||
int found = 0;
|
||||
|
||||
/*
|
||||
Test these color escapes with parameter value 0..7
|
||||
Detect these terminfo color escapes with parameter
|
||||
value 0..7, all of which don't move the cursor
|
||||
*/
|
||||
char * esc[] =
|
||||
{
|
||||
@@ -708,7 +725,8 @@ static int calc_prompt_width( array_list_t *arr )
|
||||
;
|
||||
|
||||
/*
|
||||
Test these regular escapes without any parameter values
|
||||
Detect these semi-common terminfo escapes without any
|
||||
parameter values, all of which don't move the cursor
|
||||
*/
|
||||
char *esc2[] =
|
||||
{
|
||||
@@ -718,7 +736,20 @@ static int calc_prompt_width( array_list_t *arr )
|
||||
exit_underline_mode,
|
||||
enter_standout_mode,
|
||||
exit_standout_mode,
|
||||
flash_screen
|
||||
flash_screen,
|
||||
enter_subscript_mode,
|
||||
exit_subscript_mode,
|
||||
enter_superscript_mode,
|
||||
exit_superscript_mode,
|
||||
enter_blink_mode,
|
||||
enter_italics_mode,
|
||||
exit_italics_mode,
|
||||
enter_reverse_mode,
|
||||
enter_shadow_mode,
|
||||
exit_shadow_mode,
|
||||
enter_standout_mode,
|
||||
exit_standout_mode,
|
||||
enter_secure_mode
|
||||
}
|
||||
;
|
||||
|
||||
@@ -750,7 +781,7 @@ static int calc_prompt_width( array_list_t *arr )
|
||||
*/
|
||||
len = maxi( try_sequence( tparm(esc2[l]), &next[j] ),
|
||||
try_sequence( esc2[l], &next[j] ));
|
||||
|
||||
|
||||
if( len )
|
||||
{
|
||||
j += (len-1);
|
||||
@@ -758,6 +789,10 @@ static int calc_prompt_width( array_list_t *arr )
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( next[j] == L'\t' )
|
||||
{
|
||||
res=(res+8)&~7;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
@@ -765,7 +800,6 @@ static int calc_prompt_width( array_list_t *arr )
|
||||
*/
|
||||
res += wcwidth( next[j] );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -788,7 +822,7 @@ static void write_prompt()
|
||||
if( data->exec_prompt )
|
||||
{
|
||||
|
||||
al_foreach( &prompt_list, (void (*)(const void *))&free );
|
||||
al_foreach( &prompt_list, &free );
|
||||
al_truncate( &prompt_list, 0 );
|
||||
|
||||
if( data->prompt )
|
||||
@@ -798,7 +832,7 @@ static void write_prompt()
|
||||
if( exec_subshell( data->prompt, &prompt_list ) == -1 )
|
||||
{
|
||||
/* If executing the prompt fails, make sure we at least don't print any junk */
|
||||
al_foreach( &prompt_list, (void (*)(const void *))&free );
|
||||
al_foreach( &prompt_list, &free );
|
||||
al_destroy( &prompt_list );
|
||||
al_init( &prompt_list );
|
||||
}
|
||||
@@ -869,11 +903,14 @@ void reader_destroy()
|
||||
}
|
||||
|
||||
|
||||
void reader_exit( int do_exit )
|
||||
void reader_exit( int do_exit, int forced )
|
||||
{
|
||||
if( data )
|
||||
data->end_loop=do_exit;
|
||||
end_loop=do_exit;
|
||||
if( forced )
|
||||
exit_forced = 1;
|
||||
|
||||
}
|
||||
|
||||
void repaint()
|
||||
@@ -898,7 +935,7 @@ void repaint()
|
||||
if( steps )
|
||||
move_cursor( -steps );
|
||||
|
||||
set_color( FISH_COLOR_NORMAL, -1 );
|
||||
set_color( FISH_COLOR_NORMAL, FISH_COLOR_IGNORE );
|
||||
reader_save_status();
|
||||
}
|
||||
|
||||
@@ -925,7 +962,6 @@ static void check_colors()
|
||||
static void reader_save_status()
|
||||
{
|
||||
|
||||
#ifdef HAVE_FUTIMES
|
||||
/*
|
||||
This futimes call tries to trick the system into using st_mtime
|
||||
as a tampering flag. This of course only works on systems where
|
||||
@@ -946,9 +982,13 @@ static void reader_save_status()
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
Don't check return value on these. We don't care if they fail,
|
||||
really. This is all just to make the prompt look ok, which is
|
||||
impossible to do 100% reliably. We try, at least.
|
||||
*/
|
||||
futimes( 1, t );
|
||||
futimes( 2, t );
|
||||
#endif
|
||||
|
||||
fstat( 1, &prev_buff_1 );
|
||||
fstat( 2, &prev_buff_2 );
|
||||
@@ -1125,7 +1165,7 @@ static int insert_char( int c )
|
||||
}
|
||||
else
|
||||
writech(c);
|
||||
set_color( FISH_COLOR_NORMAL, -1 );
|
||||
set_color( FISH_COLOR_NORMAL, FISH_COLOR_IGNORE );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1631,7 +1671,6 @@ static void reader_interactive_init()
|
||||
|
||||
|
||||
al_init( &prompt_list );
|
||||
history_init();
|
||||
|
||||
common_handle_winch(0);
|
||||
|
||||
@@ -1656,9 +1695,8 @@ static void reader_interactive_init()
|
||||
static void reader_interactive_destroy()
|
||||
{
|
||||
kill_destroy();
|
||||
al_foreach( &prompt_list, (void (*)(const void *))&free );
|
||||
al_foreach( &prompt_list, &free );
|
||||
al_destroy( &prompt_list );
|
||||
history_destroy();
|
||||
|
||||
writestr( L"\n" );
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
@@ -1680,7 +1718,7 @@ void reader_sanity_check()
|
||||
void reader_replace_current_token( wchar_t *new_token )
|
||||
{
|
||||
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *begin, *end;
|
||||
string_buffer_t sb;
|
||||
int new_pos;
|
||||
|
||||
@@ -1747,7 +1785,7 @@ static int contains( const wchar_t *needle,
|
||||
*/
|
||||
static void reset_token_history()
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *begin, *end;
|
||||
|
||||
parse_util_token_extent( data->buff, data->buff_pos, &begin, &end, 0, 0 );
|
||||
if( begin )
|
||||
@@ -1759,7 +1797,7 @@ static void reset_token_history()
|
||||
|
||||
data->token_history_pos = -1;
|
||||
data->search_pos=0;
|
||||
al_foreach( &data->search_prev, (void (*)(const void *))&free );
|
||||
al_foreach( &data->search_prev, &free );
|
||||
al_truncate( &data->search_prev, 0 );
|
||||
al_push( &data->search_prev, wcsdup( data->search_buff ) );
|
||||
}
|
||||
@@ -2045,7 +2083,7 @@ int reader_get_cursor_pos()
|
||||
}
|
||||
|
||||
|
||||
void reader_run_command( wchar_t *cmd )
|
||||
void reader_run_command( const wchar_t *cmd )
|
||||
{
|
||||
|
||||
wchar_t *ft;
|
||||
@@ -2065,7 +2103,7 @@ void reader_run_command( wchar_t *cmd )
|
||||
|
||||
term_steal();
|
||||
|
||||
env_set( L"_", L"fish", ENV_GLOBAL );
|
||||
env_set( L"_", program_name, ENV_GLOBAL );
|
||||
|
||||
#ifdef HAVE__PROC_SELF_STAT
|
||||
proc_update_jiffies();
|
||||
@@ -2082,7 +2120,18 @@ void reader_run_command( wchar_t *cmd )
|
||||
|
||||
static int shell_test( wchar_t *b )
|
||||
{
|
||||
return !wcslen(b);
|
||||
if( parser_test( b, 0, 0 ) )
|
||||
{
|
||||
string_buffer_t sb;
|
||||
sb_init( &sb );
|
||||
|
||||
writech( L'\n' );
|
||||
parser_test( b, &sb, L"fish" );
|
||||
fwprintf( stderr, L"%ls", sb.buff );
|
||||
sb_destroy( &sb );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2144,7 +2193,7 @@ void reader_pop()
|
||||
/*
|
||||
Clean up after history search
|
||||
*/
|
||||
al_foreach( &n->search_prev, (void (*)(const void *))&free );
|
||||
al_foreach( &n->search_prev, &free );
|
||||
al_destroy( &n->search_prev );
|
||||
free( (void *)n->token_history_buff);
|
||||
|
||||
@@ -2210,7 +2259,7 @@ static void reader_super_highlight_me_plenty( wchar_t * buff, int *color, int po
|
||||
*/
|
||||
if( color[start+i]>>8 == 0 )
|
||||
{
|
||||
color[start+i] |= HIGHLIGHT_SEARCH_MATCH<<8;
|
||||
color[start+i] |= HIGHLIGHT_SEARCH_MATCH<<16;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2232,7 +2281,6 @@ int exit_status()
|
||||
*/
|
||||
static int read_i()
|
||||
{
|
||||
int prev_end_loop=0;
|
||||
|
||||
reader_push(L"fish");
|
||||
reader_set_complete_function( &complete );
|
||||
@@ -2240,6 +2288,7 @@ static int read_i()
|
||||
reader_set_test_function( &shell_test );
|
||||
|
||||
data->prompt_width=60;
|
||||
data->prev_end_loop=0;
|
||||
|
||||
while( (!data->end_loop) && (!sanity_check()) )
|
||||
{
|
||||
@@ -2256,12 +2305,7 @@ static int read_i()
|
||||
during evaluation.
|
||||
*/
|
||||
|
||||
tmp = wcsdup( reader_readline() );
|
||||
|
||||
data->buff_pos=data->buff_len=0;
|
||||
data->buff[data->buff_len]=L'\0';
|
||||
reader_run_command( tmp );
|
||||
free( tmp );
|
||||
tmp = reader_readline();
|
||||
|
||||
if( data->end_loop)
|
||||
{
|
||||
@@ -2277,17 +2321,24 @@ static int read_i()
|
||||
}
|
||||
}
|
||||
|
||||
if( !prev_end_loop && has_job )
|
||||
if( !reader_exit_forced() && !data->prev_end_loop && has_job )
|
||||
{
|
||||
writestr(_( L"There are stopped jobs\n" ));
|
||||
write_prompt();
|
||||
data->end_loop = 0;
|
||||
prev_end_loop=1;
|
||||
data->prev_end_loop=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_end_loop=0;
|
||||
tmp = wcsdup( tmp );
|
||||
|
||||
data->buff_pos=data->buff_len=0;
|
||||
data->buff[data->buff_len]=L'\0';
|
||||
reader_run_command( tmp );
|
||||
free( tmp );
|
||||
|
||||
data->prev_end_loop=0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2408,7 +2459,7 @@ wchar_t *reader_readline()
|
||||
|
||||
if( (last_char == R_COMPLETE) && (c != R_COMPLETE) && (!comp_empty) )
|
||||
{
|
||||
al_foreach( &comp, (void (*)(const void *))&free );
|
||||
al_foreach( &comp, &free );
|
||||
al_truncate( &comp, 0 );
|
||||
comp_empty = 1;
|
||||
}
|
||||
@@ -2444,6 +2495,13 @@ wchar_t *reader_readline()
|
||||
break;
|
||||
}
|
||||
|
||||
case R_EOF:
|
||||
{
|
||||
exit_forced = 1;
|
||||
data->end_loop=1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* complete */
|
||||
case R_COMPLETE:
|
||||
{
|
||||
@@ -2457,8 +2515,8 @@ wchar_t *reader_readline()
|
||||
|
||||
if( comp_empty )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
const wchar_t *token_begin, *token_end;
|
||||
wchar_t *begin, *end;
|
||||
wchar_t *token_begin, *token_end;
|
||||
wchar_t *buffcpy;
|
||||
int len;
|
||||
int cursor_steps;
|
||||
@@ -2466,11 +2524,12 @@ wchar_t *reader_readline()
|
||||
parse_util_cmdsubst_extent( data->buff, data->buff_pos, &begin, &end );
|
||||
|
||||
parse_util_token_extent( begin, data->buff_pos - (begin-data->buff), &token_begin, &token_end, 0, 0 );
|
||||
|
||||
cursor_steps = token_end - data->buff- data->buff_pos;
|
||||
data->buff_pos += cursor_steps;
|
||||
move_cursor( cursor_steps );
|
||||
|
||||
len = data->buff_pos - (data->buff - begin);
|
||||
|
||||
len = data->buff_pos - (begin-data->buff);
|
||||
buffcpy = wcsndup( begin, len );
|
||||
|
||||
reader_save_status();
|
||||
@@ -2486,7 +2545,7 @@ wchar_t *reader_readline()
|
||||
if( (comp_empty =
|
||||
handle_completions( &comp ) ) )
|
||||
{
|
||||
al_foreach( &comp, (void (*)(const void *))&free );
|
||||
al_foreach( &comp, &free );
|
||||
al_truncate( &comp, 0 );
|
||||
}
|
||||
|
||||
@@ -2509,7 +2568,7 @@ wchar_t *reader_readline()
|
||||
{
|
||||
wchar_t *str = wcsndup( data->buff, data->buff_pos );
|
||||
if( !str )
|
||||
die_mem();
|
||||
DIE_MEM();
|
||||
|
||||
kill_add( str );
|
||||
free( str );
|
||||
@@ -2805,13 +2864,11 @@ wchar_t *reader_readline()
|
||||
else
|
||||
{
|
||||
/*
|
||||
Carriage returns happen - they are usually a
|
||||
sign of an incorrectly set terminal, but there
|
||||
really isn't very much we can do at this point,
|
||||
so we ignore them.
|
||||
Low priority debug message. These can happen if
|
||||
the user presses an unefined control
|
||||
sequnece. No reason to report.
|
||||
*/
|
||||
if( c != 13 )
|
||||
debug( 0, _( L"Unknown keybinding %d" ), c );
|
||||
debug( 2, _( L"Unknown keybinding %d" ), c );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2835,14 +2892,17 @@ wchar_t *reader_readline()
|
||||
}
|
||||
|
||||
al_destroy( &comp );
|
||||
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
||||
{
|
||||
wperror(L"tcsetattr");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
|
||||
if( !reader_exit_forced() )
|
||||
{
|
||||
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
||||
{
|
||||
wperror(L"tcsetattr");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
}
|
||||
|
||||
return data->buff;
|
||||
}
|
||||
|
||||
@@ -2909,18 +2969,21 @@ static int read_ni( int fd )
|
||||
|
||||
if( str )
|
||||
{
|
||||
if( !parser_test( str, 1 ) )
|
||||
{
|
||||
eval( str, 0, TOP );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
No error reporting - parser_test did that for us
|
||||
*/
|
||||
res = 1;
|
||||
}
|
||||
free( str );
|
||||
string_buffer_t sb;
|
||||
sb_init( &sb );
|
||||
|
||||
if( !parser_test( str, &sb, L"fish" ) )
|
||||
{
|
||||
eval( str, 0, TOP );
|
||||
}
|
||||
else
|
||||
{
|
||||
fwprintf( stderr, L"%ls", sb.buff );
|
||||
res = 1;
|
||||
}
|
||||
sb_destroy( &sb );
|
||||
|
||||
free( str );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
9
reader.h
9
reader.h
@@ -21,7 +21,7 @@ int reader_read( int fd);
|
||||
/**
|
||||
Tell the shell that it should exit after the currently running command finishes.
|
||||
*/
|
||||
void reader_exit( int do_exit );
|
||||
void reader_exit( int do_exit, int force );
|
||||
|
||||
/**
|
||||
Check that the reader is in a sane state
|
||||
@@ -72,7 +72,7 @@ void repaint();
|
||||
Run the specified command with the correct terminal modes, and
|
||||
while taking care to perform job notification, set the title, etc.
|
||||
*/
|
||||
void reader_run_command( wchar_t *buff );
|
||||
void reader_run_command( const wchar_t *buff );
|
||||
|
||||
/**
|
||||
Get the string of character currently entered into the command
|
||||
@@ -162,5 +162,10 @@ void reader_replace_current_token( wchar_t *new_token );
|
||||
*/
|
||||
void reader_handle_int( int signal );
|
||||
|
||||
/**
|
||||
This function returns true if fish is exiting by force, i.e. because stdin died
|
||||
*/
|
||||
int reader_exit_forced();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
2
sanity.c
2
sanity.c
@@ -60,7 +60,7 @@ void validate_pointer( const void *ptr, const wchar_t *err, int null_ok )
|
||||
Test if the pointer data crosses a segment boundary.
|
||||
*/
|
||||
|
||||
if( (0x00000003 & (int)ptr) != 0 )
|
||||
if( (0x00000003l & (long)ptr) != 0 )
|
||||
{
|
||||
debug( 0, _(L"The pointer '%ls' is invalid"), err );
|
||||
sanity_lose();
|
||||
|
||||
4
seq.in
4
seq.in
@@ -34,14 +34,14 @@ switch (count $argv)
|
||||
|
||||
case '*'
|
||||
printf (_ "%s: Expected 1, 2 or 3 arguments, got %d\n") seq (count $argv)
|
||||
return 1
|
||||
exit 1
|
||||
|
||||
end
|
||||
|
||||
for i in $from $step $to
|
||||
if not echo $i | grep '^-\?[0-9]*\(\|.[0-9]\+\)$' >/dev/null
|
||||
printf (_ "%s: '%s' is not a number\n") seq $i
|
||||
return 1
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
54
set_color.c
54
set_color.c
@@ -36,6 +36,8 @@
|
||||
#include <libintl.h>
|
||||
#endif
|
||||
|
||||
#include "fallback.h"
|
||||
|
||||
/*
|
||||
Small utility for setting the color.
|
||||
Usage: set_color COLOR
|
||||
@@ -49,6 +51,11 @@
|
||||
*/
|
||||
#define SET_COLOR "set_color"
|
||||
|
||||
/**
|
||||
Getopt short switches for set_color
|
||||
*/
|
||||
#define GETOPT_STRING "b:hvocu"
|
||||
|
||||
#if HAVE_GETTEXT
|
||||
#define _(string) gettext(string)
|
||||
#else
|
||||
@@ -147,9 +154,9 @@ int main( int argc, char **argv )
|
||||
char *fgcolor=0;
|
||||
int fg, bg;
|
||||
int bold=0;
|
||||
|
||||
|
||||
|
||||
int underline=0;
|
||||
char *bg_seq, *fg_seq;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
@@ -168,6 +175,10 @@ int main( int argc, char **argv )
|
||||
"bold", no_argument, 0, 'o'
|
||||
}
|
||||
,
|
||||
{
|
||||
"underline", no_argument, 0, 'u'
|
||||
}
|
||||
,
|
||||
{
|
||||
"version", no_argument, 0, 'v'
|
||||
}
|
||||
@@ -186,13 +197,13 @@ int main( int argc, char **argv )
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"b:hvoc",
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"b:hvoc" );
|
||||
GETOPT_STRING );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
@@ -213,6 +224,10 @@ int main( int argc, char **argv )
|
||||
bold=1;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
underline=1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
check_locale_init();
|
||||
fprintf( stderr, _("%s, version %s\n"), SET_COLOR, PACKAGE_VERSION );
|
||||
@@ -246,7 +261,7 @@ int main( int argc, char **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( !fgcolor && !bgcolor && !bold )
|
||||
if( !fgcolor && !bgcolor && !bold && !underline )
|
||||
{
|
||||
check_locale_init();
|
||||
fprintf( stderr, _("%s: Expected an argument\n"), SET_COLOR );
|
||||
@@ -272,16 +287,28 @@ int main( int argc, char **argv )
|
||||
|
||||
setupterm( 0, STDOUT_FILENO, 0);
|
||||
|
||||
fg_seq = set_a_foreground?set_a_foreground:set_foreground;
|
||||
bg_seq = set_a_background?set_a_background:set_background;
|
||||
|
||||
|
||||
if( bold )
|
||||
{
|
||||
putp( enter_bold_mode );
|
||||
if( enter_bold_mode )
|
||||
putp( enter_bold_mode );
|
||||
}
|
||||
|
||||
if( underline )
|
||||
{
|
||||
if( enter_underline_mode )
|
||||
putp( enter_underline_mode );
|
||||
}
|
||||
|
||||
if( bgcolor )
|
||||
{
|
||||
if( bg == 8 )
|
||||
{
|
||||
putp( tparm( set_a_background, 0) );
|
||||
if( bg_seq )
|
||||
putp( tparm( bg_seq, 0) );
|
||||
putp( tparm(exit_attribute_mode) );
|
||||
}
|
||||
}
|
||||
@@ -290,12 +317,14 @@ int main( int argc, char **argv )
|
||||
{
|
||||
if( fg == 8 )
|
||||
{
|
||||
putp( tparm( set_a_foreground, 0) );
|
||||
if( fg_seq )
|
||||
putp( tparm( fg_seq, 0) );
|
||||
putp( tparm(exit_attribute_mode) );
|
||||
}
|
||||
else
|
||||
{
|
||||
putp( tparm( set_a_foreground, fg) );
|
||||
if( fg_seq )
|
||||
putp( tparm( fg_seq, fg) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,8 +332,11 @@ int main( int argc, char **argv )
|
||||
{
|
||||
if( bg != 8 )
|
||||
{
|
||||
putp( tparm( set_a_background, bg) );
|
||||
if( bg_seq )
|
||||
putp( tparm( bg_seq, bg) );
|
||||
}
|
||||
}
|
||||
|
||||
del_curterm( cur_term );
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
function __fish_complete_apropos
|
||||
if test (commandline -ct)
|
||||
set str (commandline -ct)
|
||||
apropos $str|sed -e "s/^\(.*$str\([^ ]*\).*\)$/$str\2"\t"\1/"
|
||||
apropos $str|sed -e "s/^\(.*$str\([^ ]*\).*\)\$/$str\2"\t"\1/"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ complete -f -c apt-proxy-import -s V -l version -d (N_ 'Display version and exit
|
||||
complete -f -c apt-proxy-import -s v -l verbose -d (N_ 'Verbose mode')
|
||||
complete -f -c apt-proxy-import -s q -l quiet -d (N_ 'No message to STDOUT')
|
||||
complete -f -c apt-proxy-import -s r -l recursive -d (N_ 'Recurse into subdir')
|
||||
complete -r -c apt-proxy-import -s i -l import-dir -a '(ls -Fp|grep /$)' -d (N_ 'Dir to import')
|
||||
complete -r -c apt-proxy-import -s i -l import-dir -a '(ls -Fp|grep /\$)' -d (N_ 'Dir to import')
|
||||
complete -r -c apt-proxy-import -s u -l user -a '(__fish_complete_users)' -d (N_ 'Change to user')
|
||||
complete -r -c apt-proxy-import -s d -l debug -d (N_ 'Debug level[default 0]')
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
complete -c apt-show-source -s h -l help -d (N_ 'Display help and exit')
|
||||
complete -r -c apt-show-source -l status-file -d (N_ 'Read package from file') -f
|
||||
complete -r -c apt-show-source -o stf -d (N_ 'Read package from file') -f
|
||||
complete -r -c apt-show-source -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
complete -r -c apt-show-source -o ld -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
complete -r -c apt-show-source -l list-dir -a '(ls -Fp .|grep /\$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
complete -r -c apt-show-source -o ld -a '(ls -Fp .|grep /\$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
complete -r -c apt-show-source -s p -l package -a '(apt-cache pkgnames)' -d (N_ 'List PKG info')
|
||||
complete -f -c apt-show-source -l version-only -d (N_ 'Display version and exit')
|
||||
complete -f -c apt-show-source -s a -l all -d (N_ 'Print all source packages with version')
|
||||
|
||||
@@ -9,6 +9,6 @@ complete -f -c apt-show-versions -s v -l verbose -d (N_ 'Print verbose info')
|
||||
complete -f -c apt-show-versions -s i -l initialize -d (N_ 'Init or update cache only')
|
||||
complete -r -c apt-show-versions -l status-file -d (N_ 'Read package from file')
|
||||
complete -r -c apt-show-versions -o stf -d (N_ 'Read package from file')
|
||||
complete -r -c apt-show-versions -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
complete -r -c apt-show-versions -o ld -a '(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
complete -r -c apt-show-versions -l list-dir -a '(ls -Fp .|grep /\$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
complete -r -c apt-show-versions -o ld -a '(ls -Fp .|grep /\$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')
|
||||
|
||||
|
||||
@@ -1,39 +1,2 @@
|
||||
|
||||
function __fish_complete_cd -d "Completions for the cd command"
|
||||
|
||||
#
|
||||
# We can't simply use __fish_complete_directory because of the CDPATH
|
||||
#
|
||||
|
||||
set -- wd $PWD
|
||||
set -- owd $OLDPWD
|
||||
|
||||
# Check if CDPATH is set
|
||||
|
||||
set -l mycdpath
|
||||
|
||||
if test -z $CDPATH[1]
|
||||
set mycdpath .
|
||||
else
|
||||
set mycdpath $CDPATH
|
||||
end
|
||||
|
||||
if echo (commandline -ct)|grep '^/\|./' >/dev/null
|
||||
# This is an absolute search path
|
||||
eval printf '\%s\\tDirectory\\n' (commandline -ct)\*/
|
||||
else
|
||||
# This is a relative search path
|
||||
# Iterate over every directory in CDPATH and check for possible completions
|
||||
for i in $mycdpath
|
||||
# Move to the initial directory first, in case the CDPATH directory is relative
|
||||
builtin cd $wd
|
||||
builtin cd $i
|
||||
eval printf '"%s\tDirectory in "'$i'"\n"' (commandline -ct)\*/
|
||||
end
|
||||
end
|
||||
|
||||
builtin cd $wd
|
||||
set -- OLDPWD $owd
|
||||
end
|
||||
|
||||
complete -x -c cd -a "(__fish_complete_cd)"
|
||||
|
||||
@@ -12,3 +12,4 @@ complete -c complete -s u -l unauthorative -d (N_ "Option list is not complete")
|
||||
complete -c complete -s e -l erase -d (N_ "Remove completion")
|
||||
complete -c complete -s h -l help -d (N_ "Display help and exit")
|
||||
complete -c complete -s C -l do-complete -d (N_ "Print all completions for the specified commandline")
|
||||
complete -c complete -s n -l complete -d (N_ "The completion should only be used if the specified command has a zero exit status") -r
|
||||
|
||||
28
share/completions/cp.fish
Normal file
28
share/completions/cp.fish
Normal file
@@ -0,0 +1,28 @@
|
||||
complete -c cp -s a -l archive -d (N_ "Same as -dpR")
|
||||
complete -c cp -s b -l backup -d (N_ "Make backup of each existing destination file") -a "none off numbered t existing nil simple never"
|
||||
complete -c cp -l copy-contents -d (N_ "Copy contents of special files when recursive")
|
||||
complete -c cp -s d -d (N_ "Same as --no-dereference --preserve=link")
|
||||
complete -c cp -s f -l force -d (N_ "Do not prompt before overwriting")
|
||||
complete -c cp -s i -l interactive -d (N_ "Prompt before overwrite")
|
||||
complete -c cp -s H -d (N_ "Follow command-line symbolic links")
|
||||
complete -c cp -s l -l link -d (N_ "Link files instead of copying")
|
||||
complete -c cp -l strip-trailing-slashes -d (N_ "Remove trailing slashes from source")
|
||||
complete -c cp -s S -l suffix -r -d (N_ "Backup suffix")
|
||||
complete -c cp -s t -l target-directory -d (N_ "Target directory") -x -a "(__fish_complete_directory (commandline -ct) 'Target directory')"
|
||||
complete -c cp -s u -l update -d (N_ "Do not overwrite newer files")
|
||||
complete -c cp -s v -l verbose -d (N_ "Verbose mode")
|
||||
complete -c cp -l help -d (N_ "Display help and exit")
|
||||
complete -c cp -l version -d (N_ "Display version and exit")
|
||||
complete -c cp -s L -l dereference -d (N_ "Always follow symbolic links")
|
||||
complete -c cp -s P -l no-dereference -d (N_ "Never follow symbolic links")
|
||||
complete -c cp -s p -d (N_ "Same as --preserve=mode,ownership,timestamps")
|
||||
complete -c cp -l preserve -d (N_ "Preserve the specified attributes and security contexts, if possible") -a "mode ownership timestamps links all"
|
||||
complete -c cp -l no-preserve -r -d (N_ "Don't preserve the specified attributes") -a "mode ownership timestamps links all"
|
||||
complete -c cp -l parents -d (N_ "Use full source file name under DIRECTORY")
|
||||
complete -c cp -s r -s R -l recursive -d (N_ "Copy directories recursively")
|
||||
complete -c cp -l remove-destination -d (N_ "Remove each existing destination file before attempting to open it (contrast with --force)")
|
||||
complete -c cp -l sparse -r -d (N_ "Control creation of sparse files") -a "always auto never"
|
||||
complete -c cp -s s -l symbolic-link -d (N_ "Make symbolic links instead of copying")
|
||||
complete -c cp -s T -l no-target-directory -d (N_ "Treat DEST as a normal file")
|
||||
complete -c cp -s x -l one-file-system -d (N_ "Stay on this file system")
|
||||
complete -c cp -s X -l context -r -d (N_ "Set security context of copy to CONTEXT")
|
||||
@@ -3,4 +3,4 @@ complete -c functions -xa "(functions -na)" -d (N_ "Function")
|
||||
complete -c functions -s a -l all -d (N_ "Show hidden functions")
|
||||
complete -c functions -s h -l help -d (N_ "Display help and exit")
|
||||
complete -c functions -s d -l description -d (N_ "Set function description") -x
|
||||
|
||||
complete -c functions -s q -l query -d (N_ "Test if function is defined")
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
complete -c fusermount -d (N_ "Mount point") -x -a '
|
||||
(
|
||||
cat /etc/mtab | grep "^sshfs" | cut -d " " -f 1-2|tr " " \n|sed -e "s/[0-9\.]*:\//\//"|grep "^/"
|
||||
cat /etc/mtab | grep "^fuseiso" | cut -d " " -f 1-2|tr " " \n|sed -e "s/[0-9\.]*:\//\//"|grep "^/"
|
||||
)
|
||||
'
|
||||
|
||||
@@ -15,3 +16,4 @@ complete -c fusermount -s o -x -d (N_ "Mount options")
|
||||
complete -c fusermount -s u -d (N_ "Unmount")
|
||||
complete -c fusermount -s q -d (N_ "Quiet")
|
||||
complete -c fusermount -s z -d (N_ "Lazy unmount")
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ for i in (builtin -n)
|
||||
complete -c help -x -a $i -d (N_ "Help for the specified builtin")
|
||||
end
|
||||
|
||||
for i in count dirh dirs help mimedb nextd open popd prevd pushd set_color psub umask type
|
||||
for i in case (sed -n < $__fish_help_dir/commands.html -e "s/.*<h2><a class=\"anchor\" name=\"\([^\"]*\)\">.*/\1/p")
|
||||
complete -c help -x -a $i -d (N_ "Help for the specified command")
|
||||
end
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ complete -c mv -l strip-trailing-slashes -d (N_ "Remove trailing slashes from so
|
||||
complete -c mv -s S -l suffix -r -d (N_ "Backup suffix")
|
||||
complete -c mv -l target-directory -d (N_ "Target directory") -x -a "(__fish_complete_directory (commandline -ct) 'Target directory')"
|
||||
complete -c mv -s u -l update -d (N_ "Do not overwrite newer files")
|
||||
complete -c mv -s v -l vervose -d (N_ "Verbose mode")
|
||||
complete -c mv -s v -l verbose -d (N_ "Verbose mode")
|
||||
complete -c mv -l help -d (N_ "Display help and exit")
|
||||
complete -c mv -l version -d (N_ "Display version and exit")
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#Completions for patch
|
||||
# Completions for patch
|
||||
#
|
||||
|
||||
complete -c patch -s b -l backup -d (N_ "Make backup files, when patching a file, rename or copy the original instead of removing it")
|
||||
@@ -24,7 +24,7 @@ complete -c patch -s N -l forward -d (N_ "Ignore patches that seem to be reverse
|
||||
complete -c patch -s o -l output -r -f -d (N_ "Send output to outfile instead of patching files in place")
|
||||
complete -c patch -s p -l strip -r -f -d (N_ "Strip the smallest prefix containing num leading slashes from each file name found in the patch file")
|
||||
complete -c patch -l posix -d (N_ "Conform more strictly to the POSIX standard")
|
||||
complete -c patch -l quoting-style -r -f -d (N_ "Use style word to quote output names")
|
||||
complete -c patch -l quoting-style -r -f -d (N_ "Use style word to quote output names") -a "literal shell shell-always c escape"
|
||||
complete -c patch -s r -l reject-file -r -f -d (N_ "Put rejects into rejectfile instead of the default .rej file")
|
||||
complete -c patch -s R -l reverse -d (N_ "Assume that this patch was created with the old and new files swapped")
|
||||
complete -c patch -s s -l silent -l quiet -d (N_ "Work silently, unless an error occurs")
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
complete -c set_color -x -d (N_ "Color") -a '(set_color --print-colors)'
|
||||
complete -c set_color -s b -l background -x -a '(set_color --print-colors)' -d (N_ "Change background color")
|
||||
complete -c set_color -s o -l bold -d (N_ 'Make font bold')
|
||||
complete -c set_color -s u -l underline -d (N_ 'Underline text')
|
||||
complete -c set_color -s v -l version -d (N_ 'Display version and exit')
|
||||
complete -c set_color -s h -l help -d (N_ 'Display help and exit')
|
||||
complete -c set_color -s c -l print-colors -d (N_ 'Print a list of all accepted color names')
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ complete -x -c ssh -s b -d (N_ "Interface to transmit from") -a "
|
||||
)
|
||||
"
|
||||
|
||||
complete -x -c ssh -s e -d (N_ "Escape character") -a "^ none"
|
||||
complete -x -c ssh -s e -d (N_ "Escape character") -a "\^ none"
|
||||
complete -c ssh -s f -d (N_ "Go to background")
|
||||
complete -c ssh -s g -d (N_ "Allow remote host to connect to local forwarded ports")
|
||||
complete -c ssh -s I -d (N_ "Smartcard device")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user