diff --git a/FishsFish.xcodeproj/project.pbxproj b/FishsFish.xcodeproj/project.pbxproj new file mode 100644 index 000000000..26015f3ad --- /dev/null +++ b/FishsFish.xcodeproj/project.pbxproj @@ -0,0 +1,348 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXFileReference section */ + D0A0850313B3ACEE0099B651 /* builtin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = builtin.h; sourceTree = ""; }; + D0A0850413B3ACEE0099B651 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; + D0A0850513B3ACEE0099B651 /* complete.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = complete.h; sourceTree = ""; }; + D0A0850613B3ACEE0099B651 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + D0A0850713B3ACEE0099B651 /* env_universal_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = env_universal_common.h; sourceTree = ""; }; + D0A0850813B3ACEE0099B651 /* env_universal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = env_universal.h; sourceTree = ""; }; + D0A0850913B3ACEE0099B651 /* env.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = env.h; sourceTree = ""; }; + D0A0850A13B3ACEE0099B651 /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = ""; }; + D0A0850B13B3ACEE0099B651 /* exec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exec.h; sourceTree = ""; }; + D0A0850C13B3ACEE0099B651 /* expand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = expand.h; sourceTree = ""; }; + D0A0850D13B3ACEE0099B651 /* fallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fallback.h; sourceTree = ""; }; + D0A0850E13B3ACEE0099B651 /* function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = function.h; sourceTree = ""; }; + D0A0850F13B3ACEE0099B651 /* halloc_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = halloc_util.h; sourceTree = ""; }; + D0A0851013B3ACEE0099B651 /* halloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = halloc.h; sourceTree = ""; }; + D0A0851113B3ACEE0099B651 /* highlight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = highlight.h; sourceTree = ""; }; + D0A0851213B3ACEE0099B651 /* history.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = history.h; sourceTree = ""; }; + D0A0851313B3ACEE0099B651 /* input_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_common.h; sourceTree = ""; }; + D0A0851413B3ACEE0099B651 /* input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input.h; sourceTree = ""; }; + D0A0851513B3ACEE0099B651 /* intern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intern.h; sourceTree = ""; }; + D0A0851613B3ACEE0099B651 /* io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = io.h; sourceTree = ""; }; + D0A0851713B3ACEE0099B651 /* iothread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iothread.h; sourceTree = ""; }; + D0A0851813B3ACEE0099B651 /* kill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kill.h; sourceTree = ""; }; + D0A0851913B3ACEE0099B651 /* mimedb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mimedb.h; sourceTree = ""; }; + D0A0851A13B3ACEE0099B651 /* output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = output.h; sourceTree = ""; }; + D0A0851B13B3ACEE0099B651 /* parse_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse_util.h; sourceTree = ""; }; + D0A0851C13B3ACEE0099B651 /* parser_keywords.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser_keywords.h; sourceTree = ""; }; + D0A0851D13B3ACEE0099B651 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = ""; }; + D0A0851E13B3ACEE0099B651 /* path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = path.h; sourceTree = ""; }; + D0A0851F13B3ACEE0099B651 /* print_help.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = print_help.h; sourceTree = ""; }; + D0A0852013B3ACEE0099B651 /* proc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = proc.h; sourceTree = ""; }; + D0A0852113B3ACEE0099B651 /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; + D0A0852213B3ACEE0099B651 /* sanity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sanity.h; sourceTree = ""; }; + D0A0852313B3ACEE0099B651 /* screen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = screen.h; sourceTree = ""; }; + D0A0852413B3ACEE0099B651 /* signal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = signal.h; sourceTree = ""; }; + D0A0852513B3ACEE0099B651 /* tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tokenizer.h; sourceTree = ""; }; + D0A0852613B3ACEE0099B651 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; + D0A0852713B3ACEE0099B651 /* wgetopt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wgetopt.h; sourceTree = ""; }; + D0A0852813B3ACEE0099B651 /* wildcard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wildcard.h; sourceTree = ""; }; + D0A0852913B3ACEE0099B651 /* wutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wutil.h; sourceTree = ""; }; + D0A0852A13B3ACEE0099B651 /* xdgmime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdgmime.h; sourceTree = ""; }; + D0A0852B13B3ACEE0099B651 /* xdgmimealias.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdgmimealias.h; sourceTree = ""; }; + D0A0852C13B3ACEE0099B651 /* xdgmimeglob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdgmimeglob.h; sourceTree = ""; }; + D0A0852D13B3ACEE0099B651 /* xdgmimeint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdgmimeint.h; sourceTree = ""; }; + D0A0852E13B3ACEE0099B651 /* xdgmimemagic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdgmimemagic.h; sourceTree = ""; }; + D0A0852F13B3ACEE0099B651 /* xdgmimeparent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdgmimeparent.h; sourceTree = ""; }; + D0A0853013B3ACEE0099B651 /* builtin_commandline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtin_commandline.cpp; sourceTree = ""; }; + D0A0853113B3ACEE0099B651 /* builtin_complete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtin_complete.cpp; sourceTree = ""; }; + D0A0853213B3ACEE0099B651 /* builtin_jobs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtin_jobs.cpp; sourceTree = ""; }; + D0A0853313B3ACEE0099B651 /* builtin_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtin_set.cpp; sourceTree = ""; }; + D0A0853413B3ACEE0099B651 /* builtin_ulimit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtin_ulimit.cpp; sourceTree = ""; }; + D0A0853513B3ACEE0099B651 /* builtin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtin.cpp; sourceTree = ""; }; + D0A0853613B3ACEE0099B651 /* common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = common.cpp; sourceTree = ""; }; + D0A0853713B3ACEE0099B651 /* complete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = complete.cpp; sourceTree = ""; }; + D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal_common.cpp; sourceTree = ""; }; + D0A0853913B3ACEE0099B651 /* env_universal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal.cpp; sourceTree = ""; }; + D0A0853A13B3ACEE0099B651 /* env.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env.cpp; sourceTree = ""; }; + D0A0853B13B3ACEE0099B651 /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event.cpp; sourceTree = ""; }; + D0A0853C13B3ACEE0099B651 /* exec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec.cpp; sourceTree = ""; }; + D0A0853D13B3ACEE0099B651 /* expand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = expand.cpp; sourceTree = ""; }; + D0A0853E13B3ACEE0099B651 /* fallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fallback.cpp; sourceTree = ""; }; + D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_indent.cpp; sourceTree = ""; }; + D0A0854013B3ACEE0099B651 /* fish_pager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_pager.cpp; sourceTree = ""; }; + D0A0854113B3ACEE0099B651 /* fish_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_tests.cpp; sourceTree = ""; }; + D0A0854213B3ACEE0099B651 /* fish.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish.cpp; sourceTree = ""; }; + D0A0854313B3ACEE0099B651 /* fishd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fishd.cpp; sourceTree = ""; }; + D0A0854413B3ACEE0099B651 /* function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = function.cpp; sourceTree = ""; }; + D0A0854513B3ACEE0099B651 /* halloc_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = halloc_util.cpp; sourceTree = ""; }; + D0A0854613B3ACEE0099B651 /* halloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = halloc.cpp; sourceTree = ""; }; + D0A0854713B3ACEE0099B651 /* highlight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = highlight.cpp; sourceTree = ""; }; + D0A0854813B3ACEE0099B651 /* history.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = history.cpp; sourceTree = ""; }; + D0A0854913B3ACEE0099B651 /* input_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input_common.cpp; sourceTree = ""; }; + D0A0854A13B3ACEE0099B651 /* input.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input.cpp; sourceTree = ""; }; + D0A0854B13B3ACEE0099B651 /* intern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intern.cpp; sourceTree = ""; }; + D0A0854C13B3ACEE0099B651 /* io.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = io.cpp; sourceTree = ""; }; + D0A0854D13B3ACEE0099B651 /* iothread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iothread.cpp; sourceTree = ""; }; + D0A0854E13B3ACEE0099B651 /* key_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = key_reader.cpp; sourceTree = ""; }; + D0A0854F13B3ACEE0099B651 /* kill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kill.cpp; sourceTree = ""; }; + D0A0855013B3ACEE0099B651 /* mimedb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mimedb.cpp; sourceTree = ""; }; + D0A0855113B3ACEE0099B651 /* output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = output.cpp; sourceTree = ""; }; + D0A0855213B3ACEE0099B651 /* parse_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_util.cpp; sourceTree = ""; }; + D0A0855313B3ACEE0099B651 /* parser_keywords.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser_keywords.cpp; sourceTree = ""; }; + D0A0855413B3ACEE0099B651 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = ""; }; + D0A0855513B3ACEE0099B651 /* path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = path.cpp; sourceTree = ""; }; + D0A0855613B3ACEE0099B651 /* print_help.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = print_help.cpp; sourceTree = ""; }; + D0A0855713B3ACEE0099B651 /* proc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = proc.cpp; sourceTree = ""; }; + D0A0855813B3ACEE0099B651 /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = ""; }; + D0A0855913B3ACEE0099B651 /* sanity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sanity.cpp; sourceTree = ""; }; + D0A0855A13B3ACEE0099B651 /* screen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen.cpp; sourceTree = ""; }; + D0A0855B13B3ACEE0099B651 /* set_color.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = set_color.cpp; sourceTree = ""; }; + D0A0855C13B3ACEE0099B651 /* signal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = signal.cpp; sourceTree = ""; }; + D0A0855D13B3ACEE0099B651 /* tokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tokenizer.cpp; sourceTree = ""; }; + D0A0855E13B3ACEE0099B651 /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = ""; }; + D0A0855F13B3ACEE0099B651 /* wgetopt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wgetopt.cpp; sourceTree = ""; }; + D0A0856013B3ACEE0099B651 /* wildcard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wildcard.cpp; sourceTree = ""; }; + D0A0856113B3ACEE0099B651 /* wutil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wutil.cpp; sourceTree = ""; }; + D0A0856213B3ACEE0099B651 /* xdgmime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmime.cpp; sourceTree = ""; }; + D0A0856313B3ACEE0099B651 /* xdgmimealias.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimealias.cpp; sourceTree = ""; }; + D0A0856413B3ACEE0099B651 /* xdgmimeglob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimeglob.cpp; sourceTree = ""; }; + D0A0856513B3ACEE0099B651 /* xdgmimeint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimeint.cpp; sourceTree = ""; }; + D0A0856613B3ACEE0099B651 /* xdgmimemagic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimemagic.cpp; sourceTree = ""; }; + D0A0856713B3ACEE0099B651 /* xdgmimeparent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimeparent.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXGroup section */ + D0A084F013B3AC130099B651 = { + isa = PBXGroup; + children = ( + D0A0850313B3ACEE0099B651 /* builtin.h */, + D0A0853013B3ACEE0099B651 /* builtin_commandline.cpp */, + D0A0853113B3ACEE0099B651 /* builtin_complete.cpp */, + D0A0853213B3ACEE0099B651 /* builtin_jobs.cpp */, + D0A0853313B3ACEE0099B651 /* builtin_set.cpp */, + D0A0853413B3ACEE0099B651 /* builtin_ulimit.cpp */, + D0A0853513B3ACEE0099B651 /* builtin.cpp */, + D0A0850413B3ACEE0099B651 /* common.h */, + D0A0853613B3ACEE0099B651 /* common.cpp */, + D0A0850513B3ACEE0099B651 /* complete.h */, + D0A0853713B3ACEE0099B651 /* complete.cpp */, + D0A0850613B3ACEE0099B651 /* config.h */, + D0A0850713B3ACEE0099B651 /* env_universal_common.h */, + D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */, + D0A0850813B3ACEE0099B651 /* env_universal.h */, + D0A0853913B3ACEE0099B651 /* env_universal.cpp */, + D0A0850913B3ACEE0099B651 /* env.h */, + D0A0853A13B3ACEE0099B651 /* env.cpp */, + D0A0850A13B3ACEE0099B651 /* event.h */, + D0A0853B13B3ACEE0099B651 /* event.cpp */, + D0A0850B13B3ACEE0099B651 /* exec.h */, + D0A0853C13B3ACEE0099B651 /* exec.cpp */, + D0A0850C13B3ACEE0099B651 /* expand.h */, + D0A0853D13B3ACEE0099B651 /* expand.cpp */, + D0A0850D13B3ACEE0099B651 /* fallback.h */, + D0A0853E13B3ACEE0099B651 /* fallback.cpp */, + D0A0850E13B3ACEE0099B651 /* function.h */, + D0A0854413B3ACEE0099B651 /* function.cpp */, + D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */, + D0A0854013B3ACEE0099B651 /* fish_pager.cpp */, + D0A0854113B3ACEE0099B651 /* fish_tests.cpp */, + D0A0854213B3ACEE0099B651 /* fish.cpp */, + D0A0854313B3ACEE0099B651 /* fishd.cpp */, + D0A0850F13B3ACEE0099B651 /* halloc_util.h */, + D0A0851013B3ACEE0099B651 /* halloc.h */, + D0A0854613B3ACEE0099B651 /* halloc.cpp */, + D0A0854513B3ACEE0099B651 /* halloc_util.cpp */, + D0A0851113B3ACEE0099B651 /* highlight.h */, + D0A0854713B3ACEE0099B651 /* highlight.cpp */, + D0A0851213B3ACEE0099B651 /* history.h */, + D0A0854813B3ACEE0099B651 /* history.cpp */, + D0A0851313B3ACEE0099B651 /* input_common.h */, + D0A0854913B3ACEE0099B651 /* input_common.cpp */, + D0A0851413B3ACEE0099B651 /* input.h */, + D0A0854A13B3ACEE0099B651 /* input.cpp */, + D0A0851513B3ACEE0099B651 /* intern.h */, + D0A0854B13B3ACEE0099B651 /* intern.cpp */, + D0A0851613B3ACEE0099B651 /* io.h */, + D0A0854C13B3ACEE0099B651 /* io.cpp */, + D0A0851713B3ACEE0099B651 /* iothread.h */, + D0A0854D13B3ACEE0099B651 /* iothread.cpp */, + D0A0851813B3ACEE0099B651 /* kill.h */, + D0A0854F13B3ACEE0099B651 /* kill.cpp */, + D0A0854E13B3ACEE0099B651 /* key_reader.cpp */, + D0A0851913B3ACEE0099B651 /* mimedb.h */, + D0A0855013B3ACEE0099B651 /* mimedb.cpp */, + D0A0851A13B3ACEE0099B651 /* output.h */, + D0A0855113B3ACEE0099B651 /* output.cpp */, + D0A0851B13B3ACEE0099B651 /* parse_util.h */, + D0A0855213B3ACEE0099B651 /* parse_util.cpp */, + D0A0851C13B3ACEE0099B651 /* parser_keywords.h */, + D0A0855313B3ACEE0099B651 /* parser_keywords.cpp */, + D0A0851D13B3ACEE0099B651 /* parser.h */, + D0A0855413B3ACEE0099B651 /* parser.cpp */, + D0A0851E13B3ACEE0099B651 /* path.h */, + D0A0855513B3ACEE0099B651 /* path.cpp */, + D0A0851F13B3ACEE0099B651 /* print_help.h */, + D0A0855613B3ACEE0099B651 /* print_help.cpp */, + D0A0852013B3ACEE0099B651 /* proc.h */, + D0A0855713B3ACEE0099B651 /* proc.cpp */, + D0A0852113B3ACEE0099B651 /* reader.h */, + D0A0855813B3ACEE0099B651 /* reader.cpp */, + D0A0852213B3ACEE0099B651 /* sanity.h */, + D0A0855913B3ACEE0099B651 /* sanity.cpp */, + D0A0852313B3ACEE0099B651 /* screen.h */, + D0A0855A13B3ACEE0099B651 /* screen.cpp */, + D0A0852413B3ACEE0099B651 /* signal.h */, + D0A0855C13B3ACEE0099B651 /* signal.cpp */, + D0A0855B13B3ACEE0099B651 /* set_color.cpp */, + D0A0852513B3ACEE0099B651 /* tokenizer.h */, + D0A0855D13B3ACEE0099B651 /* tokenizer.cpp */, + D0A0852613B3ACEE0099B651 /* util.h */, + D0A0855E13B3ACEE0099B651 /* util.cpp */, + D0A0852713B3ACEE0099B651 /* wgetopt.h */, + D0A0855F13B3ACEE0099B651 /* wgetopt.cpp */, + D0A0852813B3ACEE0099B651 /* wildcard.h */, + D0A0856013B3ACEE0099B651 /* wildcard.cpp */, + D0A0852913B3ACEE0099B651 /* wutil.h */, + D0A0856113B3ACEE0099B651 /* wutil.cpp */, + D0A0852A13B3ACEE0099B651 /* xdgmime.h */, + D0A0856213B3ACEE0099B651 /* xdgmime.cpp */, + D0A0852B13B3ACEE0099B651 /* xdgmimealias.h */, + D0A0856313B3ACEE0099B651 /* xdgmimealias.cpp */, + D0A0852C13B3ACEE0099B651 /* xdgmimeglob.h */, + D0A0856413B3ACEE0099B651 /* xdgmimeglob.cpp */, + D0A0852D13B3ACEE0099B651 /* xdgmimeint.h */, + D0A0856513B3ACEE0099B651 /* xdgmimeint.cpp */, + D0A0852E13B3ACEE0099B651 /* xdgmimemagic.h */, + D0A0856613B3ACEE0099B651 /* xdgmimemagic.cpp */, + D0A0852F13B3ACEE0099B651 /* xdgmimeparent.h */, + D0A0856713B3ACEE0099B651 /* xdgmimeparent.cpp */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXLegacyTarget section */ + D0A084F713B3AC130099B651 /* FishsFish */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "-f Makefile.cpp -k ${ACTION}"; + buildConfigurationList = D0A084FA13B3AC130099B651 /* Build configuration list for PBXLegacyTarget "FishsFish" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = FishsFish; + passBuildSettingsInEnvironment = 1; + productName = FishsFish; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXProject section */ + D0A084F213B3AC130099B651 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = D0A084F513B3AC130099B651 /* Build configuration list for PBXProject "FishsFish" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D0A084F013B3AC130099B651; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D0A084F713B3AC130099B651 /* FishsFish */, + ); + }; +/* End PBXProject section */ + +/* Begin XCBuildConfiguration section */ + D0A084F813B3AC130099B651 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + D0A084F913B3AC130099B651 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = macosx; + }; + name = Release; + }; + D0A084FB13B3AC130099B651 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + DEBUGGING_SYMBOLS = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D0A084FC13B3AC130099B651 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D0A084F513B3AC130099B651 /* Build configuration list for PBXProject "FishsFish" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D0A084F813B3AC130099B651 /* Debug */, + D0A084F913B3AC130099B651 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D0A084FA13B3AC130099B651 /* Build configuration list for PBXLegacyTarget "FishsFish" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D0A084FB13B3AC130099B651 /* Debug */, + D0A084FC13B3AC130099B651 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D0A084F213B3AC130099B651 /* Project object */; +} diff --git a/builtin.cpp b/builtin.cpp index 41a952602..181c2cef4 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -83,7 +83,7 @@ #define FG_MSG _( L"Send job %d, '%ls' to foreground\n" ) /** - Datastructure to describe a builtin. + Datastructure to describe a builtin. */ typedef struct builtin_data { @@ -152,7 +152,7 @@ static int builtin_count_args( wchar_t **argv ) return argc; } -/** +/** 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. @@ -162,13 +162,13 @@ static void builtin_wperror( const wchar_t *s) { if( s != 0 ) { - sb_append( sb_err, s, L": ", (void *)0 ); + sb_append( sb_err, s, L": ", NULL ); } char *err = strerror( errno ); wchar_t *werr = str2wcs( err ); if( werr ) { - sb_append( sb_err, werr, L"\n", (void *)0 ); + sb_append( sb_err, werr, L"\n", NULL ); free( werr ); } } @@ -191,7 +191,7 @@ wchar_t *builtin_help_get( const wchar_t *name ) array_list_t lst; string_buffer_t cmd; wchar_t *name_esc; - + /* Because the contents of this buffer is returned by this function, it must not be free'd on exit, so we allocate it @@ -199,10 +199,10 @@ wchar_t *builtin_help_get( const wchar_t *name ) */ static string_buffer_t *out = 0; int i; - + al_init( &lst ); sb_init( &cmd ); - + if( !out ) { out = sb_halloc( global_context ); @@ -214,24 +214,24 @@ wchar_t *builtin_help_get( const wchar_t *name ) name_esc = escape( name, 1 ); sb_printf( &cmd, L"__fish_print_help %ls", name_esc ); - + if( exec_subshell( (wchar_t *)cmd.buff, &lst ) >= 0 ) - { + { for( i=0; ibuff; - + } /** @@ -242,15 +242,15 @@ wchar_t *builtin_help_get( const wchar_t *name ) message is about to be printed to an interactive screen, it may be shortened to fit the screen. - + */ static void builtin_print_help( const wchar_t *cmd, string_buffer_t *b ) { - + const wchar_t *h; int is_short = 0; - + if( b == sb_err ) { sb_append( sb_err, @@ -268,12 +268,12 @@ static void builtin_print_help( const wchar_t *cmd, string_buffer_t *b ) if( b==sb_err ) { - + /* Interactive mode help to screen - only print synopsis if - the rest won't fit + the rest won't fit */ - + int screen_height, lines; screen_height = common_get_height(); @@ -283,24 +283,24 @@ static void builtin_print_help( const wchar_t *cmd, string_buffer_t *b ) wchar_t *pos; int cut=0; int i; - + is_short = 1; - + /* First move down 4 lines */ - + pos = str; for( i=0; (i<4) && pos && *pos; i++ ) { pos = wcschr( pos+1, L'\n' ); } - + if( pos && *pos ) { - - /* - Then find the next empty line + + /* + Then find the next empty line */ for( ; *pos; pos++ ) { @@ -308,12 +308,12 @@ static void builtin_print_help( const wchar_t *cmd, string_buffer_t *b ) { wchar_t *pos2; int is_empty = 1; - + for( pos2 = pos+1; *pos2; pos2++ ) { if( *pos2 == L'\n' ) break; - + if( *pos2 != L'\t' && *pos2 !=L' ' ) { is_empty = 0; @@ -332,7 +332,7 @@ static void builtin_print_help( const wchar_t *cmd, string_buffer_t *b ) } } } - + /* We did not find a good place to cut message to shorten it - so we make sure we don't print @@ -345,13 +345,13 @@ static void builtin_print_help( const wchar_t *cmd, string_buffer_t *b ) } } - + sb_append( b, str ); if( is_short ) { sb_printf( b, _(L"%ls: Type 'help %ls' for related documentation\n\n"), cmd, cmd ); } - + free( str ); } } @@ -401,11 +401,11 @@ static void builtin_missing_argument( const wchar_t *cmd, const wchar_t *opt ) */ -#include "builtin_set.c" -#include "builtin_commandline.c" -#include "builtin_complete.c" -#include "builtin_ulimit.c" -#include "builtin_jobs.c" +#include "builtin_set.cpp" +#include "builtin_commandline.cpp" +#include "builtin_complete.cpp" +#include "builtin_ulimit.cpp" +#include "builtin_jobs.cpp" /** List all current key bindings @@ -414,18 +414,18 @@ static void builtin_bind_list() { array_list_t lst; int i; - - + + al_init( &lst ); input_mapping_get_names( &lst ); - + for( i=0; itype != FUNCTION_CALL && block->type != FUNCTION_CALL_NO_SHADOW ) block = block->outer; @@ -991,15 +991,15 @@ static int builtin_builtin( wchar_t **argv ) al_init( &names ); builtin_get_names( &names ); sort_list( &names ); - + for( i=0; iparam1.param ); break; } - + } } al_destroy( &ev ); - + named = function_get_named_arguments( name ); if( named ) { @@ -1230,7 +1230,7 @@ static void functions_def( wchar_t *name, string_buffer_t *out ) sb_printf( out, L" %ls", (wchar_t *)al_get( named, i ) ); } } - + sb_printf( out, L"\n\t%ls\nend\n", def ); } @@ -1310,10 +1310,10 @@ static int builtin_functions( wchar_t **argv ) 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_printf( sb_err, + BUILTIN_ERR_UNKNOWN, + argv[0], + long_options[opt_index].name ); builtin_print_help( argv[0], sb_err ); @@ -1423,7 +1423,7 @@ static int builtin_functions( wchar_t **argv ) sb_append( &buff, al_get(&names, i), L", ", - (void *)0 ); + NULL ); } write_screen( (wchar_t *)buff.buff, sb_out ); @@ -1436,7 +1436,7 @@ static int builtin_functions( wchar_t **argv ) sb_append( sb_out, al_get(&names, i), L"\n", - (void *)0 ); + NULL ); } } @@ -1509,10 +1509,10 @@ static int builtin_functions( wchar_t **argv ) { if( i != woptind) sb_append( sb_out, L"\n" ); - + functions_def( argv[i], sb_out ); } - } + } } return res; @@ -1534,7 +1534,7 @@ static int builtin_function( wchar_t **argv ) array_list_t *named_arguments=0; wchar_t *name = 0; int shadows = 1; - + woptind=0; parser_push_block( FUNCTION_DEF ); @@ -1629,7 +1629,7 @@ static int builtin_function( wchar_t **argv ) break; } - e = halloc( current_block, sizeof(event_t)); + e = (event_t *)halloc( current_block, sizeof(event_t)); if( !e ) DIE_MEM(); e->type = EVENT_SIGNAL; @@ -1653,7 +1653,7 @@ static int builtin_function( wchar_t **argv ) break; } - e = halloc( current_block, sizeof(event_t)); + e = (event_t *)halloc( current_block, sizeof(event_t)); e->type = EVENT_VARIABLE; e->param1.variable = halloc_wcsdup( current_block, woptarg ); @@ -1666,9 +1666,9 @@ static int builtin_function( wchar_t **argv ) case 'e': { event_t *e; - - e = halloc( current_block, sizeof(event_t)); - + + e = (event_t *)halloc( current_block, sizeof(event_t)); + e->type = EVENT_GENERIC; e->param1.param = halloc_wcsdup( current_block, woptarg ); e->function_name=0; @@ -1683,10 +1683,10 @@ static int builtin_function( wchar_t **argv ) wchar_t *end; event_t *e; - e = halloc( current_block, sizeof(event_t)); + e = (event_t *)halloc( current_block, sizeof(event_t)); if( !e ) DIE_MEM(); - + if( ( opt == 'j' ) && ( wcscasecmp( woptarg, L"caller" ) == 0 ) ) { @@ -1757,15 +1757,15 @@ static int builtin_function( wchar_t **argv ) if( !named_arguments ) named_arguments = al_halloc( current_block ); break; - + case 'S': shadows = 0; break; - + case 'h': builtin_print_help( argv[0], sb_out ); return STATUS_BUILTIN_OK; - + case '?': builtin_unknown_option( argv[0], argv[woptind-1] ); res = 1; @@ -1777,7 +1777,7 @@ static int builtin_function( wchar_t **argv ) if( !res ) { - + if( argc == woptind ) { sb_printf( sb_err, @@ -1808,7 +1808,7 @@ static int builtin_function( wchar_t **argv ) { name = argv[woptind++]; - + if( named_arguments ) { while( woptind < argc ) @@ -1822,7 +1822,7 @@ static int builtin_function( wchar_t **argv ) res = STATUS_BUILTIN_ERROR; break; } - + al_push( named_arguments, halloc_wcsdup( current_block, argv[woptind++] ) ); } } @@ -1833,7 +1833,7 @@ static int builtin_function( wchar_t **argv ) argv[0], argc ); res=1; - + } } } @@ -1864,7 +1864,7 @@ static int builtin_function( wchar_t **argv ) } sb_append( sb_err, - nxt, L" ", (void *)0 ); + nxt, L" ", NULL ); } al_destroy( &names ); sb_append( sb_err, L"\n" ); @@ -1874,14 +1874,14 @@ static int builtin_function( wchar_t **argv ) } else { - function_data_t * d = halloc( current_block, sizeof( function_data_t )); - + function_data_t * d = (function_data_t *)halloc( current_block, sizeof( function_data_t )); + d->name=halloc_wcsdup( current_block, name); d->description=desc?halloc_wcsdup( current_block, desc):0; d->events = events; d->named_arguments = named_arguments; d->shadows = shadows; - + for( i=0; idata = d; - + } - + current_block->tok_pos = parser_get_pos(); current_block->skip = 1; @@ -1906,7 +1906,7 @@ static int builtin_random( wchar_t **argv ) { static int seeded=0; static struct drand48_data seed_buffer; - + int argc = builtin_count_args( argv ); woptind=0; @@ -1967,14 +1967,14 @@ static int builtin_random( wchar_t **argv ) case 0: { long res; - + if( !seeded ) { seeded=1; srand48_r(time(0), &seed_buffer); } lrand48_r( &seed_buffer, &res ); - + sb_printf( sb_out, L"%d\n", abs(res%32767) ); break; } @@ -2021,17 +2021,17 @@ static int builtin_read( wchar_t **argv ) { wchar_t *buff=0; int i, argc = builtin_count_args( argv ); - wchar_t *ifs; + const wchar_t *ifs; int place = ENV_USER; wchar_t *nxt; - wchar_t *prompt = DEFAULT_READ_PROMPT; - wchar_t *commandline = L""; + const wchar_t *prompt = DEFAULT_READ_PROMPT; + const wchar_t *commandline = L""; int exit_res=STATUS_BUILTIN_OK; - wchar_t *mode_name = READ_MODE_NAME; + const wchar_t *mode_name = READ_MODE_NAME; int shell = 0; - + woptind=0; - + while( 1 ) { static const struct woption @@ -2141,7 +2141,7 @@ static int builtin_read( wchar_t **argv ) case 's': shell = 1; break; - + case 'h': builtin_print_help( argv[0], sb_out ); return STATUS_BUILTIN_OK; @@ -2210,7 +2210,7 @@ static int builtin_read( wchar_t **argv ) if( isatty(0) && builtin_stdin == 0 ) { wchar_t *line; - + reader_push( mode_name ); reader_set_prompt( prompt ); if( shell ) @@ -2219,10 +2219,10 @@ static int builtin_read( wchar_t **argv ) reader_set_highlight_function( &highlight_shell ); reader_set_test_function( &reader_shell_test ); } - + reader_set_buffer( commandline, wcslen( commandline ) ); proc_push_interactive( 1 ); - + event_fire_generic(L"fish_prompt"); line = reader_readline( ); proc_pop_interactive(); @@ -2240,9 +2240,9 @@ static int builtin_read( wchar_t **argv ) { string_buffer_t sb; int eof=0; - + sb_init( &sb ); - + while( 1 ) { int finished=0; @@ -2296,32 +2296,32 @@ static int builtin_read( wchar_t **argv ) { exit_res = 1; } - + buff = wcsdup( (wchar_t *)sb.buff ); sb_destroy( &sb ); } if( i != argc && !exit_res ) { - + wchar_t *state; ifs = env_get( L"IFS" ); if( ifs == 0 ) ifs = L""; - + nxt = wcstok( buff, (iparam1.source_dest = fn_intern; - + parse_util_set_argv( (argc>2)?(argv+2):(argv+1), 0); - + res = reader_read( fd, real_io ); - + parser_pop_block(); - + if( res ) { sb_printf( sb_err, @@ -2919,12 +2919,12 @@ static int builtin_source( wchar_t ** argv ) { res = proc_get_last_status(); } - + /* Do not close fd after calling reader_read. reader_read automatically closes it before calling eval. */ - + reader_pop_current_filename(); return res; @@ -2974,7 +2974,7 @@ static int builtin_fg( wchar_t **argv ) */ for( j=first_job; j; j=j->next ) { - if( job_get_flag( j, JOB_CONSTRUCTED ) && (!job_is_completed(j)) && + if( job_get_flag( j, JOB_CONSTRUCTED ) && (!job_is_completed(j)) && ( (job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND)) ) && job_get_flag( j, JOB_CONTROL) ) ) { break; @@ -2999,16 +2999,16 @@ static int builtin_fg( wchar_t **argv ) wchar_t *endptr; int pid; int found_job = 0; - + errno = 0; pid = wcstol( argv[1], &endptr, 10 ); if( !( *endptr || errno ) ) - { + { j = job_get_from_pid( pid ); if( j ) found_job = 1; } - + if( found_job ) { sb_printf( sb_err, @@ -3030,11 +3030,11 @@ static int builtin_fg( wchar_t **argv ) } else { - wchar_t *end; + wchar_t *end; int pid; errno = 0; pid = abs(wcstol( argv[1], &end, 10 )); - + if( *end || errno ) { sb_printf( sb_err, @@ -3159,7 +3159,7 @@ static int builtin_bg( wchar_t **argv ) break; } } - + if( !j ) { sb_printf( sb_err, @@ -3178,7 +3178,7 @@ static int builtin_bg( wchar_t **argv ) int i; int pid; int err = 0; - + for( i=1; argv[i]; i++ ) { errno=0; @@ -3191,7 +3191,7 @@ static int builtin_bg( wchar_t **argv ) argv[i] ); err = 1; break; - } + } } if( !err ) @@ -3203,7 +3203,7 @@ static int builtin_bg( wchar_t **argv ) } } } - + return res; } @@ -3358,7 +3358,7 @@ static int builtin_end( wchar_t **argv ) env_set( current_block->param1.for_variable, val, ENV_LOCAL); current_block->loop_status = LOOP_NORMAL; current_block->skip = 0; - + kill_block = 0; parser_set_pos( current_block->tok_pos ); } @@ -3367,9 +3367,9 @@ static int builtin_end( wchar_t **argv ) case FUNCTION_DEF: { - + function_data_t *d = (function_data_t *)current_block->data; - + if( d ) { /** @@ -3381,13 +3381,13 @@ static int builtin_end( wchar_t **argv ) wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos, parser_get_job_pos()-current_block->tok_pos ); d->definition = def; - - function_add( d ); + + function_add( d ); free( def ); } else { - debug(0, + debug(0, _(L"%ls: Missing function definition information."), argv[0] ); bugreport(); @@ -3496,12 +3496,12 @@ static int builtin_break_continue( wchar_t **argv ) static int builtin_breakpoint( wchar_t **argv ) { - parser_push_block( BREAKPOINT ); - + parser_push_block( BREAKPOINT ); + reader_read( STDIN_FILENO, real_io ); - - parser_pop_block(); - + + parser_pop_block(); + return proc_get_last_status(); } @@ -3546,7 +3546,7 @@ static int builtin_return( wchar_t **argv ) while( (b != 0) && - ( b->type != FUNCTION_CALL && + ( b->type != FUNCTION_CALL && b->type != FUNCTION_CALL_NO_SHADOW) ) { b = b->outer; @@ -3601,7 +3601,7 @@ static int builtin_switch( wchar_t **argv ) current_block->skip=1; current_block->param2.switch_taken=0; } - + return res; } @@ -3614,7 +3614,7 @@ static int builtin_case( wchar_t **argv ) int argc = builtin_count_args( argv ); int i; wchar_t *unescaped=0; - + if( current_block->type != SWITCH ) { sb_printf( sb_err, @@ -3623,22 +3623,22 @@ static int builtin_case( wchar_t **argv ) builtin_print_help( argv[0], sb_err ); return STATUS_BUILTIN_ERROR; } - + current_block->skip = 1; - + if( current_block->param2.switch_taken ) { return STATUS_BUILTIN_OK; } - + for( i=1; iparam1.switch_value, unescaped ); free( unescaped ); - + if( match ) { current_block->skip = 0; @@ -3646,7 +3646,7 @@ static int builtin_case( wchar_t **argv ) break; } } - + return STATUS_BUILTIN_OK; } @@ -3670,15 +3670,15 @@ static const builtin_data_t builtin_data[]= } , { - L"cd", &builtin_cd, N_( L"Change working directory" ) + L"cd", &builtin_cd, N_( L"Change working directory" ) } , { - L"count", &builtin_count, N_( L"Count the number of arguments" ) + L"count", &builtin_count, N_( L"Count the number of arguments" ) } , { - L"contains", &builtin_contains, N_( L"Search for a specified string in a list" ) + L"contains", &builtin_contains, N_( L"Search for a specified string in a list" ) } , { @@ -3690,99 +3690,99 @@ static const builtin_data_t builtin_data[]= } , { - L"function", &builtin_function, N_( L"Define a new function" ) + L"function", &builtin_function, N_( L"Define a new function" ) } , { - L"functions", &builtin_functions, N_( L"List or remove functions" ) + L"functions", &builtin_functions, N_( L"List or remove functions" ) } , { - L"complete", &builtin_complete, N_( L"Edit command specific completions" ) + L"complete", &builtin_complete, N_( L"Edit command specific completions" ) } , { - L"end", &builtin_end, N_( L"End a block of commands" ) + L"end", &builtin_end, N_( L"End a block of commands" ) } , { - L"else", &builtin_else, N_( L"Evaluate block if condition is false" ) + L"else", &builtin_else, N_( L"Evaluate block if condition is false" ) } , { - L"for", &builtin_for, N_( L"Perform a set of commands multiple times" ) + L"for", &builtin_for, N_( L"Perform a set of commands multiple times" ) } , { - L".", &builtin_source, N_( L"Evaluate contents of file" ) + L".", &builtin_source, N_( L"Evaluate contents of file" ) } , { - L"set", &builtin_set, N_( L"Handle environment variables" ) + L"set", &builtin_set, N_( L"Handle environment variables" ) } , { - L"fg", &builtin_fg, N_( L"Send job to foreground" ) + L"fg", &builtin_fg, N_( L"Send job to foreground" ) } , { - L"bg", &builtin_bg, N_( L"Send job to background" ) + L"bg", &builtin_bg, N_( L"Send job to background" ) } , { - L"jobs", &builtin_jobs, N_( L"Print currently running jobs" ) + L"jobs", &builtin_jobs, N_( L"Print currently running jobs" ) } , { - L"read", &builtin_read, N_( L"Read a line of input into variables" ) + L"read", &builtin_read, N_( L"Read a line of input into variables" ) } , { - L"break", &builtin_break_continue, N_( L"Stop the innermost loop" ) + L"break", &builtin_break_continue, N_( L"Stop the innermost loop" ) } , { - L"continue", &builtin_break_continue, N_( L"Skip the rest of the current lap of the innermost loop" ) + L"continue", &builtin_break_continue, N_( L"Skip the rest of the current lap of the innermost loop" ) } , { - L"return", &builtin_return, N_( L"Stop the currently evaluated function" ) + L"return", &builtin_return, N_( L"Stop the currently evaluated function" ) } , { - L"commandline", &builtin_commandline, N_( L"Set or get the commandline" ) + L"commandline", &builtin_commandline, N_( L"Set or get the commandline" ) } , { - L"switch", &builtin_switch, N_( L"Conditionally execute a block of commands" ) + L"switch", &builtin_switch, N_( L"Conditionally execute a block of commands" ) } , { - L"case", &builtin_case, N_( L"Conditionally execute a block of commands" ) + L"case", &builtin_case, N_( L"Conditionally execute a block of commands" ) } , { - L"bind", &builtin_bind, N_( L"Handle fish key bindings" ) + L"bind", &builtin_bind, N_( L"Handle fish key bindings" ) } , { - L"random", &builtin_random, N_( L"Generate random number" ) + L"random", &builtin_random, N_( L"Generate random number" ) } , { - L"status", &builtin_status, N_( L"Return status information about fish" ) + L"status", &builtin_status, N_( L"Return status information about fish" ) } , { - L"ulimit", &builtin_ulimit, N_( L"Set or get the shells resource usage limits" ) + L"ulimit", &builtin_ulimit, N_( L"Set or get the shells resource usage limits" ) } , { - L"begin", &builtin_begin, N_( L"Create a block of code" ) + L"begin", &builtin_begin, N_( L"Create a block of code" ) } , { - L"breakpoint", &builtin_breakpoint, N_( L"Temporarily halt execution of a script and launch an interactive debug prompt" ) + L"breakpoint", &builtin_breakpoint, N_( L"Temporarily halt execution of a script and launch an interactive debug prompt" ) } , @@ -3792,31 +3792,31 @@ static const builtin_data_t builtin_data[]= listings of builtin commands, etc.. */ { - L"command", &builtin_generic, N_( L"Run a program instead of a function or builtin" ) + L"command", &builtin_generic, N_( L"Run a program instead of a function or builtin" ) } , { - L"if", &builtin_generic, N_( L"Evaluate block if condition is true" ) + L"if", &builtin_generic, N_( L"Evaluate block if condition is true" ) } , { - L"while", &builtin_generic, N_( L"Perform a command multiple times" ) + L"while", &builtin_generic, N_( L"Perform a command multiple times" ) } , { - L"not", &builtin_generic, N_( L"Negate exit status of job" ) + L"not", &builtin_generic, N_( L"Negate exit status of job" ) } , { - L"and", &builtin_generic, N_( L"Execute command if previous command suceeded" ) + L"and", &builtin_generic, N_( L"Execute command if previous command suceeded" ) } , { - L"or", &builtin_generic, N_( L"Execute command if previous command failed" ) + L"or", &builtin_generic, N_( L"Execute command if previous command failed" ) } , { - L"exec", &builtin_generic, N_( L"Run command in current process" ) + L"exec", &builtin_generic, N_( L"Run command in current process" ) } , { @@ -3824,13 +3824,13 @@ static const builtin_data_t builtin_data[]= } } ; - + void builtin_init() { - + int i; - + wopterr = 0; al_init( &io_stack ); @@ -3838,7 +3838,7 @@ void builtin_init() for( i=0; builtin_data[i].name; i++ ) { - hash_put( &builtin, builtin_data[i].name, builtin_data[i].func ); + hash_put( &builtin, builtin_data[i].name, (void *)builtin_data[i].func ); intern_static( builtin_data[i].name ); } } @@ -3859,7 +3859,7 @@ void builtin_destroy() int builtin_exists( wchar_t *cmd ) { CHECK( cmd, 0 ); - + return !!hash_get(&builtin, cmd); } @@ -3879,12 +3879,12 @@ int builtin_run( wchar_t **argv, io_data_t *io ) { int (*cmd)(wchar_t **argv)=0; real_io = io; - + CHECK( argv, STATUS_BUILTIN_ERROR ); CHECK( argv[0], STATUS_BUILTIN_ERROR ); - + cmd = (int (*)(wchar_t **))hash_get( &builtin, argv[0] ); - + if( argv[1] != 0 && !internal_help(argv[0]) ) { if( argv[2] == 0 && (parser_is_help( argv[1], 0 ) ) ) @@ -3912,18 +3912,18 @@ int builtin_run( wchar_t **argv, io_data_t *io ) void builtin_get_names( array_list_t *list ) { - CHECK( list, ); + CHECK( list, ); hash_get_keys( &builtin, list ); } const wchar_t *builtin_get_desc( const wchar_t *b ) { CHECK( b, 0 ); - + if( !desc ) { int i; - desc = malloc( sizeof( hash_table_t ) ); + desc = (hash_table_t *)malloc( sizeof( hash_table_t ) ); if( !desc) return 0; @@ -3947,8 +3947,8 @@ void builtin_push_io( int in ) al_push( &io_stack, sb_err ); } builtin_stdin = in; - sb_out = malloc(sizeof(string_buffer_t)); - sb_err = malloc(sizeof(string_buffer_t)); + sb_out = (string_buffer_t *)malloc(sizeof(string_buffer_t)); + sb_err = (string_buffer_t *)malloc(sizeof(string_buffer_t)); sb_init( sb_out ); sb_init( sb_err ); } diff --git a/builtin.h b/builtin.h index 876c5d389..245fe16c1 100644 --- a/builtin.h +++ b/builtin.h @@ -64,7 +64,7 @@ enum #define BUILTIN_FOR_ERR_IN _( L"%ls: Second argument must be 'in'\n" ) /** - Error message for insufficient number of arguments + Error message for insufficient number of arguments */ #define BUILTIN_FOR_ERR_COUNT _( L"%ls: Expected at least two arguments, got %d\n") @@ -108,7 +108,7 @@ extern int builtin_err_redirect; /** - Initialize builtin data. + Initialize builtin data. */ void builtin_init(); @@ -123,11 +123,11 @@ void builtin_destroy(); int builtin_exists( wchar_t *cmd ); /** - Execute a builtin command + Execute a builtin command - \param argv Array containing the command and parameters + \param argv Array containing the command and parameters of the builtin. The list is terminated by a - null pointer. This syntax resembles the syntax + null pointer. This syntax resembles the syntax for exec. \param io the io redirections to perform on this builtin. diff --git a/builtin_commandline.cpp b/builtin_commandline.cpp index f23e1153f..7bbc7796e 100644 --- a/builtin_commandline.cpp +++ b/builtin_commandline.cpp @@ -1,6 +1,6 @@ /** \file builtin_commandline.c Functions defining the commandline builtin -Functions used for implementing the commandline builtin. +Functions used for implementing the commandline builtin. */ #include "config.h" @@ -96,20 +96,20 @@ static void replace_part( const wchar_t *begin, const wchar_t *buff = get_buffer(); string_buffer_t out; int out_pos=get_cursor_pos(); - + sb_init( &out ); sb_append_substring( &out, buff, begin-buff ); - + switch( append_mode) { case REPLACE_MODE: { - + sb_append( &out, insert ); - out_pos = wcslen( insert ) + (begin-buff); + out_pos = wcslen( insert ) + (begin-buff); break; - + } case APPEND_MODE: { @@ -123,7 +123,7 @@ static void replace_part( const wchar_t *begin, sb_append_substring( &out, begin, cursor ); sb_append( &out, insert ); sb_append_substring( &out, begin+cursor, end-begin-cursor ); - out_pos += wcslen( insert ); + out_pos += wcslen( insert ); break; } } @@ -131,7 +131,7 @@ static void replace_part( const wchar_t *begin, reader_set_buffer( (wchar_t *)out.buff, out_pos ); sb_destroy( &out ); } - + /** Output the specified selection. @@ -140,15 +140,15 @@ static void replace_part( const wchar_t *begin, \param cut_at_cursor whether printing should stop at the surrent cursor position \param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens */ -static void write_part( const wchar_t *begin, - const wchar_t *end, - int cut_at_cursor, +static void write_part( const wchar_t *begin, + const wchar_t *end, + int cut_at_cursor, int tokenize ) -{ +{ tokenizer tok; string_buffer_t out; wchar_t *buff; - int pos; + size_t pos; pos = get_cursor_pos()-(begin-get_buffer()); @@ -157,7 +157,7 @@ static void write_part( const wchar_t *begin, buff = wcsndup( begin, end-begin ); // fwprintf( stderr, L"Subshell: %ls, end char %lc\n", buff, *end ); sb_init( &out ); - + for( tok_init( &tok, buff, TOK_ACCEPT_UNFINISHED ); tok_has_next( &tok ); tok_next( &tok ) ) @@ -165,23 +165,23 @@ static void write_part( const wchar_t *begin, if( (cut_at_cursor) && (tok_get_pos( &tok)+wcslen(tok_last( &tok)) >= pos) ) break; - + switch( tok_last_type( &tok ) ) { case TOK_STRING: { wchar_t *tmp = unescape( tok_last( &tok ), UNESCAPE_INCOMPLETE ); - sb_append( &out, tmp, L"\n", (void *)0 ); + sb_append( &out, tmp, L"\n", NULL ); free( tmp ); break; } - - } + + } } sb_append( sb_out, (wchar_t *)out.buff ); - + free( buff ); tok_destroy( &tok ); sb_destroy( &out ); @@ -189,10 +189,10 @@ static void write_part( const wchar_t *begin, else { wchar_t *buff, *esc; - + if( cut_at_cursor ) { - end = begin+pos; + end = begin+pos; } buff = wcsndup( begin, end-begin ); @@ -202,10 +202,10 @@ static void write_part( const wchar_t *begin, sb_append( sb_out, esc ); sb_append( sb_out, L"\n" ); - + free( esc ); free( buff ); - + } } @@ -219,14 +219,14 @@ static int builtin_commandline( wchar_t **argv ) int buffer_part=0; int cut_at_cursor=0; - + int argc = builtin_count_args( argv ); int append_mode=0; int function_mode = 0; - - int tokenize = 0; - + + int tokenize = 0; + int cursor_mode = 0; int line_mode = 0; int search_mode = 0; @@ -254,11 +254,11 @@ static int builtin_commandline( wchar_t **argv ) */ return 1; } - + sb_append( sb_err, argv[0], L": Can not set commandline in non-interactive mode\n", - (void *)0 ); + NULL ); builtin_print_help( argv[0], sb_err ); return 1; } @@ -293,11 +293,11 @@ static int builtin_commandline( wchar_t **argv ) { L"current-token", no_argument, 0, 't' } - , + , { L"current-buffer", no_argument, 0, 'b' } - , + , { L"cut-at-cursor", no_argument, 0, 'c' } @@ -314,7 +314,7 @@ static int builtin_commandline( wchar_t **argv ) L"help", no_argument, 0, 'h' } , - { + { L"input", required_argument, 0, 'I' } , @@ -331,21 +331,21 @@ static int builtin_commandline( wchar_t **argv ) } , { - 0, 0, 0, 0 + 0, 0, 0, 0 } } - ; - + ; + int opt_index = 0; - + int opt = wgetopt_long( argc, - argv, - L"abijpctwforhI:CLS", - long_options, + argv, + L"abijpctwforhI:CLS", + long_options, &opt_index ); if( opt == -1 ) break; - + switch( opt ) { case 0: @@ -358,7 +358,7 @@ static int builtin_commandline( wchar_t **argv ) builtin_print_help( argv[0], sb_err ); return 1; - + case L'a': append_mode = APPEND_MODE; break; @@ -366,8 +366,8 @@ static int builtin_commandline( wchar_t **argv ) case L'b': buffer_part = STRING_MODE; break; - - + + case L'i': append_mode = INSERT_MODE; break; @@ -375,11 +375,11 @@ static int builtin_commandline( wchar_t **argv ) case L'r': append_mode = REPLACE_MODE; break; - + case 'c': cut_at_cursor=1; break; - + case 't': buffer_part = TOKEN_MODE; break; @@ -404,33 +404,33 @@ static int builtin_commandline( wchar_t **argv ) current_buffer = woptarg; current_cursor_pos = wcslen( woptarg ); break; - + case 'C': cursor_mode = 1; break; - + case 'L': line_mode = 1; break; - + case 'S': search_mode = 1; break; - + case 'h': builtin_print_help( argv[0], sb_out ); return 0; case L'?': builtin_unknown_option( argv[0], argv[woptind-1] ); - return 1; + return 1; } - } + } if( function_mode ) { int i; - + /* Check for invalid switch combinations */ @@ -439,18 +439,18 @@ static int builtin_commandline( wchar_t **argv ) sb_printf(sb_err, BUILTIN_ERR_COMBO, argv[0] ); - + builtin_print_help( argv[0], sb_err ); return 1; } - + if( argc == woptind ) { sb_printf( sb_err, BUILTIN_ERR_MISSING, argv[0] ); - + builtin_print_help( argv[0], sb_err ); return 1; } @@ -476,34 +476,34 @@ static int builtin_commandline( wchar_t **argv ) return 1; } } - - return 0; + + return 0; } - + /* Check for invalid switch combinations */ if( (search_mode || line_mode || cursor_mode) && (argc-woptind > 1) ) { - + sb_append( sb_err, argv[0], L": Too many arguments\n", - (void *)0 ); + NULL ); builtin_print_help( argv[0], sb_err ); return 1; } if( (buffer_part || tokenize || cut_at_cursor) && (cursor_mode || line_mode || search_mode) ) - { + { sb_printf( sb_err, BUILTIN_ERR_COMBO, argv[0] ); builtin_print_help( argv[0], sb_err ); return 1; - } - + } + if( (tokenize || cut_at_cursor) && (argc-woptind) ) { @@ -511,7 +511,7 @@ static int builtin_commandline( wchar_t **argv ) BUILTIN_ERR_COMBO2, argv[0], L"--cut-at-cursor and --tokenize can not be used when setting the commandline" ); - + builtin_print_help( argv[0], sb_err ); return 1; @@ -524,7 +524,7 @@ static int builtin_commandline( wchar_t **argv ) argv[0], L"insertion mode switches can not be used when not in insertion mode" ); - builtin_print_help( argv[0], sb_err ); + builtin_print_help( argv[0], sb_err ); return 1; } @@ -535,7 +535,7 @@ static int builtin_commandline( wchar_t **argv ) { append_mode = REPLACE_MODE; } - + if( !buffer_part ) { buffer_part = STRING_MODE; @@ -548,7 +548,7 @@ static int builtin_commandline( wchar_t **argv ) wchar_t *endptr; int new_pos; errno = 0; - + new_pos = wcstol( argv[woptind], &endptr, 10 ); if( *endptr || errno ) { @@ -558,7 +558,7 @@ static int builtin_commandline( wchar_t **argv ) argv[woptind] ); builtin_print_help( argv[0], sb_err ); } - + current_buffer = reader_get_buffer(); new_pos = maxi( 0, mini( new_pos, wcslen( current_buffer ) ) ); reader_set_buffer( current_buffer, new_pos ); @@ -569,98 +569,98 @@ static int builtin_commandline( wchar_t **argv ) sb_printf( sb_out, L"%d\n", reader_get_cursor_pos() ); return 0; } - + } - + if( line_mode ) { int pos = reader_get_cursor_pos(); wchar_t *buff = reader_get_buffer(); sb_printf( sb_out, L"%d\n", parse_util_lineno( buff, pos ) ); return 0; - + } - + if( search_mode ) { return !reader_search_mode(); } - - + + switch( buffer_part ) { case STRING_MODE: - { + { begin = get_buffer(); end = begin+wcslen(begin); - break; + break; } case PROCESS_MODE: { parse_util_process_extent( get_buffer(), get_cursor_pos(), - &begin, + &begin, &end ); break; } - + case JOB_MODE: { parse_util_job_extent( get_buffer(), get_cursor_pos(), &begin, - &end ); - break; + &end ); + break; } - + case TOKEN_MODE: { parse_util_token_extent( get_buffer(), get_cursor_pos(), - &begin, - &end, + &begin, + &end, 0, 0 ); - break; + break; } - + } switch(argc-woptind) { case 0: - { + { write_part( begin, end, cut_at_cursor, tokenize ); break; } - + case 1: { replace_part( begin, end, argv[woptind], append_mode ); break; - } + } default: { string_buffer_t sb; int i; - + sb_init( &sb ); - + sb_append( &sb, argv[woptind] ); - + for( i=woptind+1; iflags & COMPLETE_NO_CASE ) { prepend = L""; @@ -571,7 +573,7 @@ static int builtin_complete( wchar_t **argv ) { prepend = token; } - + if( next->description ) { @@ -582,17 +584,17 @@ static int builtin_complete( wchar_t **argv ) sb_printf( sb_out, L"%ls%ls\n", prepend, next->completion ); } } - + halloc_free( comp ); recursion_level--; } - - temporary_buffer = prev_temporary_buffer; - + + temporary_buffer = prev_temporary_buffer; + } else if( woptind != argc ) { - sb_printf( sb_err, + sb_printf( sb_err, _( L"%ls: Too many arguments\n" ), argv[0] ); builtin_print_help( argv[0], sb_err ); @@ -603,7 +605,7 @@ static int builtin_complete( wchar_t **argv ) { /* No arguments specified, meaning we print the definitions of * all specified completions to stdout.*/ - complete_print( sb_out ); + complete_print( sb_out ); } else { @@ -613,26 +615,26 @@ static int builtin_complete( wchar_t **argv ) &path, (wchar_t *)short_opt.buff, &gnu_opt, - &old_opt ); + &old_opt ); } else { - builtin_complete_add( &cmd, + builtin_complete_add( &cmd, &path, (wchar_t *)short_opt.buff, &gnu_opt, - &old_opt, - result_mode, + &old_opt, + result_mode, authoritative, condition, comp, desc, - flags ); + flags ); } - } + } } - + al_foreach( &cmd, &free ); al_foreach( &path, &free ); diff --git a/builtin_jobs.cpp b/builtin_jobs.cpp index 8d17dba14..02a4c869c 100644 --- a/builtin_jobs.cpp +++ b/builtin_jobs.cpp @@ -101,7 +101,7 @@ static void builtin_jobs_print( job_t *j, int mode, int header ) L"\t", j->command, L"\n", - (void *)0 ); + NULL ); break; } @@ -248,7 +248,7 @@ static int builtin_jobs( wchar_t **argv ) case 'h': builtin_print_help( argv[0], sb_out ); - return 0; + return 0; case '?': builtin_unknown_option( argv[0], argv[woptind-1] ); diff --git a/builtin_set.cpp b/builtin_set.cpp index 7fa41fa97..840fd4b13 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -1,6 +1,6 @@ /** \file builtin_set.c Functions defining the set builtin -Functions used for implementing the set builtin. +Functions used for implementing the set builtin. */ #include "config.h" @@ -61,19 +61,19 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope ) int i; int retcode = 0; wchar_t *val_str=0; - + if( is_path_variable( key ) ) { int error = 0; - + for( i=0; i 64 ) { shorten = 1; @@ -384,12 +384,12 @@ static void print_variables(int include_values, int esc, int scope) DIE_MEM(); } } - + e_value = esc ? expand_escape_variable(value) : wcsdup(value); - - sb_append(sb_out, L" ", e_value, (void *)0); + + sb_append(sb_out, L" ", e_value, NULL); free(e_value); - + if( shorten ) { sb_append(sb_out, L"\u2026"); @@ -398,7 +398,7 @@ static void print_variables(int include_values, int esc, int scope) } } - + sb_append(sb_out, L"\n"); free(e_key); } @@ -411,57 +411,57 @@ static void print_variables(int include_values, int esc, int scope) The set builtin. Creates, updates and erases environment variables and environemnt variable arrays. */ -static int builtin_set( wchar_t **argv ) +static int builtin_set( wchar_t **argv ) { - + /** Variables used for parsing the argument list */ static const struct woption - long_options[] = + long_options[] = { - { - L"export", no_argument, 0, 'x' + { + L"export", no_argument, 0, 'x' } , - { - L"global", no_argument, 0, 'g' + { + L"global", no_argument, 0, 'g' } , - { - L"local", no_argument, 0, 'l' + { + L"local", no_argument, 0, 'l' } , - { - L"erase", no_argument, 0, 'e' + { + L"erase", no_argument, 0, 'e' } , - { - L"names", no_argument, 0, 'n' - } + { + L"names", no_argument, 0, 'n' + } , - { - L"unexport", no_argument, 0, 'u' - } + { + L"unexport", no_argument, 0, 'u' + } , - { - L"universal", no_argument, 0, 'U' - } + { + L"universal", no_argument, 0, 'U' + } , - { - L"query", no_argument, 0, 'q' - } + { + L"query", no_argument, 0, 'q' + } , - { - L"help", no_argument, 0, 'h' - } + { + L"help", no_argument, 0, 'h' + } , - { - 0, 0, 0, 0 + { + 0, 0, 0, 0 } } ; - + const wchar_t *short_options = L"+xglenuUqh"; int argc = builtin_count_args(argv); @@ -469,10 +469,10 @@ static int builtin_set( wchar_t **argv ) /* Flags to set the work mode */ - int local = 0, global = 0, export = 0; + int local = 0, global = 0, exportv = 0; int erase = 0, list = 0, unexport=0; int universal = 0, query=0; - + /* Variables used for performing the actual work @@ -482,22 +482,22 @@ static int builtin_set( wchar_t **argv ) int scope; int slice=0; int i; - + wchar_t *bad_char; - - + + /* Parse options to obtain the requested operation and the modifiers */ woptind = 0; - while (1) + while (1) { int c = wgetopt_long(argc, argv, short_options, long_options, 0); - if (c == -1) + if (c == -1) { break; } - - switch(c) + + switch(c) { case 0: break; @@ -511,7 +511,7 @@ static int builtin_set( wchar_t **argv ) break; case 'x': - export = 1; + exportv = 1; break; case 'l': @@ -556,23 +556,23 @@ static int builtin_set( wchar_t **argv ) also specify scope */ - if( query && (erase || list || global || local || universal || export || unexport ) ) + if( query && (erase || list || global || local || universal || exportv || unexport ) ) { sb_printf(sb_err, BUILTIN_ERR_COMBO, argv[0] ); - + builtin_print_help( argv[0], sb_err ); return 1; } - + /* We can't both list and erase varaibles */ - if( erase && list ) + if( erase && list ) { sb_printf(sb_err, BUILTIN_ERR_COMBO, - argv[0] ); + argv[0] ); builtin_print_help( argv[0], sb_err ); return 1; @@ -581,7 +581,7 @@ static int builtin_set( wchar_t **argv ) /* Variables can only have one scope */ - if( local + global + universal > 1 ) + if( local + global + universal > 1 ) { sb_printf( sb_err, BUILTIN_ERR_GLOCAL, @@ -593,7 +593,7 @@ static int builtin_set( wchar_t **argv ) /* Variables can only have one export status */ - if( export && unexport ) + if( exportv && unexport ) { sb_printf( sb_err, BUILTIN_ERR_EXPUNEXP, @@ -605,7 +605,7 @@ static int builtin_set( wchar_t **argv ) /* 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; + scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (exportv ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER; if( query ) { @@ -621,7 +621,7 @@ static int builtin_set( wchar_t **argv ) if( !(dest = wcsdup(arg))) { - DIE_MEM(); + DIE_MEM(); } if( wcschr( dest, L'[' ) ) @@ -629,18 +629,18 @@ static int builtin_set( wchar_t **argv ) slice = 1; *wcschr( dest, L'[' )=0; } - + if( slice ) { array_list_t indexes; array_list_t result; int j; - + al_init( &result ); al_init( &indexes ); tokenize_variable_array( env_get( dest ), &result ); - + if( !parse_index( &indexes, arg, dest, al_get_count( &result ) ) ) { builtin_print_help( argv[0], sb_err ); @@ -663,32 +663,32 @@ static int builtin_set( wchar_t **argv ) retcode++; } } - + free( dest ); - + } return retcode; } - - if( list ) + + if( list ) { /* Maybe we should issue an error if there are any other arguments? */ print_variables(0, 0, scope); return 0; - } - + } + if( woptind == argc ) { /* Print values of variables */ - if( erase ) + if( erase ) { sb_printf( sb_err, - _(L"%ls: Erase needs a variable name\n%ls\n"), + _(L"%ls: Erase needs a variable name\n%ls\n"), argv[0] ); - + builtin_print_help( argv[0], sb_err ); retcode = 1; } @@ -696,13 +696,13 @@ static int builtin_set( wchar_t **argv ) { print_variables( 1, 1, scope ); } - + return retcode; } if( !(dest = wcsdup(argv[woptind]))) { - DIE_MEM(); + DIE_MEM(); } if( wcschr( dest, L'[' ) ) @@ -710,7 +710,7 @@ static int builtin_set( wchar_t **argv ) slice = 1; *wcschr( dest, L'[' )=0; } - + if( !wcslen( dest ) ) { free( dest ); @@ -718,7 +718,7 @@ static int builtin_set( wchar_t **argv ) builtin_print_help( argv[0], sb_err ); return 1; } - + if( (bad_char = wcsvarname( dest ) ) ) { sb_printf( sb_err, BUILTIN_ERR_VARCHAR, argv[0], *bad_char ); @@ -726,7 +726,7 @@ static int builtin_set( wchar_t **argv ) free( dest ); return 1; } - + if( slice && erase && (scope != ENV_USER) ) { free( dest ); @@ -734,12 +734,12 @@ static int builtin_set( wchar_t **argv ) 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 ) { @@ -750,22 +750,22 @@ static int builtin_set( wchar_t **argv ) 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 ls.rlim_max)) { ls.rlim_cur = ls.rlim_max; - } + } } - + if( setrlimit( resource, &ls ) ) { if( errno == EPERM ) @@ -244,8 +244,8 @@ static int set( int resource, int hard, int soft, rlim_t value ) else builtin_wperror( L"ulimit" ); return 1; - } - return 0; + } + return 0; } /** @@ -256,14 +256,14 @@ static int builtin_ulimit( wchar_t ** argv ) { int hard=0; int soft=0; - + int what = RLIMIT_FSIZE; int report_all = 0; int argc = builtin_count_args( argv ); - + woptind=0; - + while( 1 ) { static const struct woption @@ -321,27 +321,27 @@ static int builtin_ulimit( wchar_t ** argv ) L"virtual-memory-size", no_argument, 0, 'v' } , - { - L"help", no_argument, 0, 'h' - } + { + L"help", no_argument, 0, 'h' + } , { - 0, 0, 0, 0 + 0, 0, 0, 0 } } - ; - + ; + int opt_index = 0; - + int opt = wgetopt_long( argc, - argv, - L"aHScdflmnstuvh", - long_options, + argv, + L"aHScdflmnstuvh", + long_options, &opt_index ); if( opt == -1 ) break; - + switch( opt ) { case 0: @@ -354,7 +354,7 @@ static int builtin_ulimit( wchar_t ** argv ) builtin_print_help( argv[0], sb_err ); return 1; - + case L'a': report_all=1; break; @@ -364,17 +364,17 @@ static int builtin_ulimit( wchar_t ** argv ) break; case L'S': - soft=1; + soft=1; break; case L'c': what=RLIMIT_CORE; break; - + case L'd': what=RLIMIT_DATA; break; - + case L'f': what=RLIMIT_FSIZE; break; @@ -384,45 +384,45 @@ static int builtin_ulimit( wchar_t ** argv ) break; #endif -#ifdef RLIMIT_RSS +#ifdef RLIMIT_RSS case L'm': what=RLIMIT_RSS; break; #endif - + case L'n': what=RLIMIT_NOFILE; break; - + case L's': what=RLIMIT_STACK; break; - + case L't': what=RLIMIT_CPU; break; - -#ifdef RLIMIT_NPROC + +#ifdef RLIMIT_NPROC case L'u': what=RLIMIT_NPROC; break; #endif - -#ifdef RLIMIT_AS + +#ifdef RLIMIT_AS case L'v': what=RLIMIT_AS; break; #endif - + case L'h': - builtin_print_help( argv[0], sb_out ); + builtin_print_help( argv[0], sb_out ); return 0; case L'?': builtin_unknown_option( argv[0], argv[woptind-1] ); - return 1; + return 1; } - } + } if( report_all ) { @@ -435,14 +435,14 @@ static int builtin_ulimit( wchar_t ** argv ) sb_append( sb_err, argv[0], L": Too many arguments\n", - (void *)0 ); + NULL ); builtin_print_help( argv[0], sb_err ); return 1; } return 0; } - + switch( argc - woptind ) { case 0: @@ -453,7 +453,7 @@ static int builtin_ulimit( wchar_t ** argv ) print( what, hard ); break; } - + case 1: { /* @@ -469,7 +469,7 @@ static int builtin_ulimit( wchar_t ** argv ) { hard=soft=1; } - + if( wcscasecmp( argv[woptind], L"unlimited" )==0) { new_limit = RLIM_INFINITY; @@ -484,33 +484,33 @@ static int builtin_ulimit( wchar_t ** argv ) } else { - errno=0; + errno=0; new_limit = wcstol( argv[woptind], &end, 10 ); if( errno || *end ) { - sb_printf( sb_err, - L"%ls: Invalid limit '%ls'\n", - argv[0], + sb_printf( sb_err, + L"%ls: Invalid limit '%ls'\n", + argv[0], argv[woptind] ); builtin_print_help( argv[0], sb_err ); return 1; } new_limit *= get_multiplier( what ); } - + return set( what, hard, soft, new_limit ); } - + default: { sb_append( sb_err, argv[0], L": Too many arguments\n", - (void *)0 ); + NULL ); builtin_print_help( argv[0], sb_err ); return 1; } - + } - return 0; + return 0; } diff --git a/common.cpp b/common.cpp index fa5ce6465..90fe6c197 100644 --- a/common.cpp +++ b/common.cpp @@ -1,5 +1,5 @@ /** \file common.c - + Various functions, mostly string utilities, that are used by most parts of fish. */ @@ -38,11 +38,12 @@ parts of fish. #include #include #include -#include +#include #include #include #include #include +#include #ifdef HAVE_EXECINFO_H #include @@ -83,24 +84,24 @@ parts of fish. #include "wildcard.h" #include "parser.h" -#include "util.c" -#include "halloc.c" -#include "halloc_util.c" -#include "fallback.c" +#include "util.cpp" +#include "halloc.cpp" +#include "halloc_util.cpp" +#include "fallback.cpp" /** - The number of milliseconds to wait between polls when attempting to acquire + The number of milliseconds to wait between polls when attempting to acquire a lockfile */ #define LOCKPOLLINTERVAL 10 -struct termios shell_modes; +struct termios shell_modes; wchar_t ellipsis_char; char *profile=0; -wchar_t *program_name; +const wchar_t *program_name; int debug_level=1; @@ -115,7 +116,7 @@ static struct winsize termsize; static string_buffer_t *setlocale_buff=0; -void show_stackframe() +void show_stackframe() { void *trace[32]; char **messages = (char **)NULL; @@ -138,25 +139,25 @@ void show_stackframe() wchar_t **list_to_char_arr( array_list_t *l ) { - wchar_t ** res = malloc( sizeof(wchar_t *)*(al_get_count( l )+1) ); + wchar_t ** res = (wchar_t **)malloc( sizeof(wchar_t *)*(al_get_count( l )+1) ); int i; if( res == 0 ) { DIE_MEM(); } for( i=0; i= *len ) { int new_len = maxi( 128, (*len)*2); - buff = realloc( buff, sizeof(wchar_t)*new_len ); + buff = (wchar_t *)realloc( buff, sizeof(wchar_t)*new_len ); if( buff == 0 ) { DIE_MEM(); @@ -174,36 +175,36 @@ int fgetws2( wchar_t **b, int *len, FILE *f ) { *len = new_len; *b = buff; - } + } } - - errno=0; - + + errno=0; + c = getwc( f ); - + if( errno == EILSEQ ) { continue; } - + //fwprintf( stderr, L"b\n" ); - + switch( c ) { - /* End of line */ + /* End of line */ case WEOF: case L'\n': case L'\0': buff[i]=L'\0'; - return i; + return i; /* Ignore carriage returns */ case L'\r': break; - + default: buff[i++]=c; break; - } + } } @@ -223,18 +224,28 @@ static int str_cmp( const void *a, const void *b ) void sort_list( array_list_t *comp ) { - qsort( comp->arr, + qsort( comp->arr, al_get_count( comp ), sizeof( void*), &str_cmp ); } +static bool string_sort_predicate(const wcstring& d1, const wcstring& d2) +{ + return wcsfilecmp(d1.c_str(), d2.c_str()) < 0; +} + +void sort_strings( std::vector &strings) +{ + std::sort(strings.begin(), strings.end(), string_sort_predicate); +} + wchar_t *str2wcs( const char *in ) { wchar_t *out; size_t len = strlen(in); - - out = malloc( sizeof(wchar_t)*(len+1) ); + + out = (wchar_t *)malloc( sizeof(wchar_t)*(len+1) ); if( !out ) { @@ -244,6 +255,14 @@ wchar_t *str2wcs( const char *in ) return str2wcs_internal( in, out ); } +wcstring str2wcstring( const char *in ) +{ + wchar_t *tmp = str2wcs(in); + wcstring result = tmp; + free(tmp); + return result; +} + wchar_t *str2wcs_internal( const char *in, wchar_t *out ) { size_t res=0; @@ -254,7 +273,7 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out ) CHECK( in, 0 ); CHECK( out, 0 ); - + len = strlen(in); memset( &state, 0, sizeof(state) ); @@ -274,7 +293,7 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out ) } else { - + switch( res ) { case (size_t)(-2): @@ -285,12 +304,12 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out ) memset( &state, 0, sizeof(state) ); break; } - + case 0: { return out; } - + default: { in_pos += res; @@ -299,18 +318,18 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out ) } out_pos++; } - + } out[out_pos] = 0; - - return out; + + return out; } char *wcs2str( const wchar_t *in ) { - char *out; - - out = malloc( MAX_UTF8_BYTES*wcslen(in)+1 ); + char *out; + + out = (char *)malloc( MAX_UTF8_BYTES*wcslen(in)+1 ); if( !out ) { @@ -320,6 +339,14 @@ char *wcs2str( const wchar_t *in ) return wcs2str_internal( in, out ); } +std::string wcs2string(const wcstring &input) +{ + char *tmp = wcs2str(input.c_str()); + std::string result = tmp; + free(tmp); + return result; +} + char *wcs2str_internal( const wchar_t *in, char *out ) { size_t res=0; @@ -329,9 +356,9 @@ char *wcs2str_internal( const wchar_t *in, char *out ) CHECK( in, 0 ); CHECK( out, 0 ); - + memset( &state, 0, sizeof(state) ); - + while( in[in_pos] ) { if( in[in_pos] == INTERNAL_SEPARATOR ) @@ -345,7 +372,7 @@ char *wcs2str_internal( const wchar_t *in, char *out ) else { res = wcrtomb( &out[out_pos], in[in_pos], &state ); - + if( res == (size_t)(-1) ) { debug( 1, L"Wide character %d has no narrow representation", in[in_pos] ); @@ -359,8 +386,8 @@ char *wcs2str_internal( const wchar_t *in, char *out ) in_pos++; } out[out_pos] = 0; - - return out; + + return out; } char **wcsv2strv( const wchar_t **in ) @@ -370,10 +397,10 @@ char **wcsv2strv( const wchar_t **in ) while( in[count] != 0 ) count++; - char **res = malloc( sizeof( char *)*(count+1)); + char **res = (char **)malloc( sizeof( char *)*(count+1)); if( res == 0 ) { - DIE_MEM(); + DIE_MEM(); } for( i=0; i 2 ) w=1; - - res += w; + + res += w; } return res; } @@ -488,14 +528,14 @@ int my_wcswidth( const wchar_t *c ) wchar_t *quote_end( const wchar_t *pos ) { wchar_t c = *pos; - + while( 1 ) { pos++; - + if( !*pos ) return 0; - + if( *pos == L'\\') { pos++; @@ -511,36 +551,36 @@ wchar_t *quote_end( const wchar_t *pos ) } } return 0; - + } - + const wchar_t *wsetlocale(int category, const wchar_t *locale) { char *lang = locale?wcs2str( locale ):0; char * res = setlocale(category,lang); - + free( lang ); /* Use ellipsis if on known unicode system, otherwise use $ */ - char *ctype = setlocale( LC_CTYPE, (void *)0 ); - ellipsis_char = (strstr( ctype, ".UTF")||strstr( ctype, ".utf") )?L'\u2026':L'$'; - + char *ctype = setlocale( LC_CTYPE, NULL ); + ellipsis_char = (strstr( ctype, ".UTF")||strstr( ctype, ".utf") )?L'\x2026':L'$'; + if( !res ) return 0; - + if( !setlocale_buff ) { setlocale_buff = sb_halloc( global_context); } - + sb_clear( setlocale_buff ); sb_printf( setlocale_buff, L"%s", res ); - - return (wchar_t *)setlocale_buff->buff; + + return (wchar_t *)setlocale_buff->buff; } int contains_internal( const wchar_t *a, ... ) @@ -550,59 +590,59 @@ int contains_internal( const wchar_t *a, ... ) int res = 0; CHECK( a, 0 ); - + va_start( va, a ); - while( (arg=va_arg(va, wchar_t *) )!= 0 ) + while( (arg=va_arg(va, wchar_t *) )!= 0 ) { if( wcscmp( a,arg) == 0 ) { res=1; break; } - + } va_end( va ); - return res; + return res; } int read_blocked(int fd, void *buf, size_t count) { - int res; - sigset_t chldset, oldset; + int res; + sigset_t chldset, oldset; sigemptyset( &chldset ); sigaddset( &chldset, SIGCHLD ); sigprocmask(SIG_BLOCK, &chldset, &oldset); res = read( fd, buf, count ); sigprocmask( SIG_SETMASK, &oldset, 0 ); - return res; + return res; } ssize_t write_loop(int fd, char *buff, size_t count) { ssize_t out=0; ssize_t out_cum=0; - while( 1 ) + while( 1 ) { - out = write( fd, + out = write( fd, &buff[out_cum], count - out_cum ); - if (out == -1) + if (out == -1) { if( errno != EAGAIN && - errno != EINTR ) + errno != EINTR ) { return -1; } - } else + } else { out_cum += out; } - if( out_cum >= count ) + if( out_cum >= count ) { break; } - } + } return out_cum; } @@ -616,26 +656,26 @@ void debug( int level, const wchar_t *msg, ... ) string_buffer_t sb2; int errno_old = errno; - + if( level > debug_level ) return; CHECK( msg, ); - + sb_init( &sb ); sb_init( &sb2 ); sb_printf( &sb, L"%ls: ", program_name ); - va_start( va, msg ); + va_start( va, msg ); sb_vprintf( &sb, msg, va ); - va_end( va ); + va_end( va ); write_screen( (wchar_t *)sb.buff, &sb2 ); - fwprintf( stderr, L"%ls", sb2.buff ); + fwprintf( stderr, L"%ls", sb2.buff ); - sb_destroy( &sb ); - sb_destroy( &sb2 ); + sb_destroy( &sb ); + sb_destroy( &sb2 ); errno = errno_old; } @@ -646,17 +686,17 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff ) int line_width = 0; int tok_width = 0; int screen_width = common_get_width(); - + CHECK( msg, ); CHECK( buff, ); - + if( screen_width ) { start = pos = msg; while( 1 ) { int overflow = 0; - + tok_width=0; /* @@ -664,7 +704,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff ) */ 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. @@ -672,9 +712,9 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff ) if((tok_width + wcwidth(*pos)) > (screen_width-1)) { overflow = 1; - break; + break; } - + tok_width += wcwidth( *pos ); pos++; } @@ -713,7 +753,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff ) free( token ); line_width += (line_width!=0?1:0) + tok_width; } - + /* Break on end of string */ @@ -721,7 +761,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff ) { break; } - + start=pos; } } @@ -741,10 +781,10 @@ static wchar_t *escape_simple( const wchar_t *in ) { wchar_t *out; size_t len = wcslen(in); - out = malloc( sizeof(wchar_t)*(len+3)); + out = (wchar_t *)malloc( sizeof(wchar_t)*(len+3)); if( !out ) DIE_MEM(); - + out[0] = L'\''; wcscpy(&out[1], in ); out[len+1]=L'\''; @@ -752,15 +792,14 @@ static wchar_t *escape_simple( const wchar_t *in ) return out; } - -wchar_t *escape( const wchar_t *in_orig, +wchar_t *escape( const wchar_t *in_orig, int flags ) { const wchar_t *in = in_orig; - + int escape_all = flags & ESCAPE_ALL; int no_quoted = flags & ESCAPE_NO_QUOTED; - + wchar_t *out; wchar_t *pos; @@ -780,14 +819,14 @@ wchar_t *escape( const wchar_t *in_orig, DIE_MEM(); return out; } - - - out = malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1)); + + + out = (wchar_t *)malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1)); pos = out; - + if( !out ) DIE_MEM(); - + while( *in != 0 ) { @@ -796,53 +835,53 @@ wchar_t *escape( const wchar_t *in_orig, { int val = *in - ENCODE_DIRECT_BASE; int tmp; - + *(pos++) = L'\\'; *(pos++) = L'X'; - - tmp = val/16; + + tmp = val/16; *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp; - - tmp = val%16; + + tmp = val%16; *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp; need_escape=need_complex_escape=1; - + } else { - + switch( *in ) { case L'\t': *(pos++) = L'\\'; - *(pos++) = L't'; + *(pos++) = L't'; need_escape=need_complex_escape=1; break; - + case L'\n': *(pos++) = L'\\'; - *(pos++) = L'n'; + *(pos++) = L'n'; need_escape=need_complex_escape=1; break; - + case L'\b': *(pos++) = L'\\'; - *(pos++) = L'b'; + *(pos++) = L'b'; need_escape=need_complex_escape=1; break; - + case L'\r': *(pos++) = L'\\'; - *(pos++) = L'r'; + *(pos++) = L'r'; need_escape=need_complex_escape=1; break; - + case L'\x1b': *(pos++) = L'\\'; - *(pos++) = L'e'; + *(pos++) = L'e'; need_escape=need_complex_escape=1; break; - + case L'\\': case L'\'': @@ -881,7 +920,7 @@ wchar_t *escape( const wchar_t *in_orig, *pos++ = *in; break; } - + default: { if( *in < 32 ) @@ -891,12 +930,12 @@ wchar_t *escape( const wchar_t *in_orig, *(pos++) = L'\\'; *(pos++) = L'c'; *(pos++) = L'a' + *in -1; - + need_escape=need_complex_escape=1; break; - + } - + int tmp = (*in)%16; *pos++ = L'\\'; @@ -913,47 +952,54 @@ wchar_t *escape( const wchar_t *in_orig, } } } - + in++; } *pos = 0; /* Use quoted escaping if possible, since most people find it - easier to read. + easier to read. */ if( !no_quoted && need_escape && !need_complex_escape && escape_all ) { free( out ); out = escape_simple( in_orig ); } - + return out; } +wcstring escape_string( const wcstring &in, int escape_all ) { + wchar_t *tmp = escape(in.c_str(), escape_all); + wcstring result(tmp); + free(tmp); + return result; +} + wchar_t *unescape( const wchar_t * orig, int flags ) { - - int mode = 0; + + int mode = 0; int in_pos, out_pos, len; int c; int bracket_count=0; - wchar_t prev=0; + wchar_t prev=0; wchar_t *in; int unescape_special = flags & UNESCAPE_SPECIAL; int allow_incomplete = flags & UNESCAPE_INCOMPLETE; - + CHECK( orig, 0 ); - + len = wcslen( orig ); in = wcsdup( orig ); if( !in ) DIE_MEM(); - - for( in_pos=0, out_pos=0; - in_pos=0)?in[out_pos]:0), out_pos++, in_pos++ ) { c = in[in_pos]; @@ -969,7 +1015,7 @@ wchar_t *unescape( const wchar_t * orig, int flags ) { switch( in[++in_pos] ) { - + /* A null character after a backslash is an error, return null @@ -982,12 +1028,12 @@ wchar_t *unescape( const wchar_t * orig, int flags ) return 0; } } - + /* Numeric escape sequences. No prefix means octal escape, otherwise hexadecimal. */ - + case L'0': case L'1': case L'2': @@ -1005,10 +1051,10 @@ wchar_t *unescape( const wchar_t * orig, int flags ) long long res=0; int chars=2; int base=16; - + int byte = 0; wchar_t max_val = ASCII_MAX; - + switch( in[in_pos] ) { case L'u': @@ -1017,45 +1063,45 @@ wchar_t *unescape( const wchar_t * orig, int flags ) 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= timeout || elapsed < 0 ) @@ -1670,7 +1723,7 @@ int acquire_lock_file( const char *lockfile, const int timeout, int force ) else { /* - Timed out and final try was unsuccessful or + Timed out and final try was unsuccessful or force was not specified */ debug( 1, L"acquire_lock_file: timed out " @@ -1729,7 +1782,7 @@ void tokenize_variable_array( const wchar_t *val, array_list_t *out ) { if( *pos == ARRAY_SEP ) { - + *pos=0; next = start==cpy?cpy:wcsdup(start); if( !next ) @@ -1746,18 +1799,18 @@ void tokenize_variable_array( const wchar_t *val, array_list_t *out ) } -int create_directory( wchar_t *d ) +int create_directory( const wchar_t *d ) { int ok = 0; struct stat buf; int stat_res = 0; - + while( (stat_res = wstat(d, &buf ) ) != 0 ) { if( errno != EAGAIN ) break; } - + if( stat_res == 0 ) { if( S_ISDIR( buf.st_mode ) ) @@ -1769,19 +1822,17 @@ int create_directory( wchar_t *d ) { if( errno == ENOENT ) { - wchar_t *dir = wcsdup( d ); - dir = wdirname( dir ); - if( !create_directory( dir ) ) + wcstring dir = wdirname(d); + if( !create_directory( dir.c_str() ) ) { if( !wmkdir( d, 0700 ) ) { ok = 1; } } - free(dir); } } - + return ok?0:-1; } @@ -1818,7 +1869,7 @@ void sb_format_size( string_buffer_t *sb, else { int i; - + for( i=0; sz_name[i]; i++ ) { if( sz < (1024*1024) || !sz_name[i+1] ) @@ -1831,19 +1882,19 @@ void sb_format_size( string_buffer_t *sb, break; } sz /= 1024; - + } - } + } } double timef() { int time_res; struct timeval tv; - + time_res = gettimeofday(&tv, 0); - - if( time_res ) + + if( time_res ) { /* Fixme: What on earth is the correct parameter value for NaN? @@ -1854,6 +1905,40 @@ double timef() */ return nan(""); } - + return (double)tv.tv_sec + 0.000001*tv.tv_usec; } + +void append_path_component(wcstring &path, const wcstring &component) +{ + size_t len = path.size(); + if (len == 0) + { + path = component; + } + else + { + if (path[len-1] != L'/') path.push_back(L'/'); + path.append(component); + } +} + +extern "C" { +__attribute__((noinline)) void debug_thread_error(void) {} +} + +void assert_is_main_thread(const char *who) +{ + if (! pthread_main_np()) { + fprintf(stderr, "Warning: %s called off of main thread. Break on debug_thread_error to debug.\n", who); + debug_thread_error(); + } +} + +void assert_is_background_thread(const char *who) +{ + if (pthread_main_np()) { + fprintf(stderr, "Warning: %s called on the main thread (may block!). Break on debug_thread_error to debug.\n", who); + debug_thread_error(); + } +} diff --git a/common.h b/common.h index 24c360880..f23a915c2 100644 --- a/common.h +++ b/common.h @@ -12,9 +12,16 @@ #include #include #include +#include +#include +#include +#include #include "util.h" +/* Common string type */ +typedef std::wstring wcstring; + /** Maximum number of bytes used by a single utf-8 character */ @@ -59,11 +66,15 @@ */ #define ESCAPE_NO_QUOTED 2 - /** + Helper macro for errors + */ +#define VOMIT_ON_FAILURE(a) do { if (0 != (a)) { int err = errno; fprintf(stderr, "%s failed on line %d in file %s: %d (%s)\n", #a, __LINE__, __FILE__, err, strerror(err)); abort(); }} while (0) + +/** Save the shell mode on startup so we can restore them on exit */ -extern struct termios shell_modes; +extern struct termios shell_modes; /** The character to use where the text has been truncated. Is an @@ -86,7 +97,7 @@ extern char *profile; Name of the current program. Should be set at startup. Used by the debug function. */ -extern wchar_t *program_name; +extern const wchar_t *program_name; /** This macro is used to check that an input argument is not null. It @@ -116,7 +127,7 @@ extern wchar_t *program_name; exit_read_count=read( 0, &exit_read_buff, 1 ); \ exit( 1 ); \ } \ - + /** Exit program at once, leaving an error message about running out of memory. @@ -144,26 +155,26 @@ extern wchar_t *program_name; show_stackframe(); \ return retval; \ } - + /** Shorthand for wgettext call */ -#define _(wstr) wgettext(wstr) +#define _(wstr) wgettext((const wchar_t *)wstr) /** Noop, used to tell xgettext that a string should be translated, - even though it is not directly sent to wgettext. + even though it is not directly sent to wgettext. */ #define N_(wstr) wstr /** Check if the specified stringelement is a part of the specified string list */ -#define contains( str,... ) contains_internal( str, __VA_ARGS__, (void *)0 ) +#define contains( str,... ) contains_internal( str, __VA_ARGS__, NULL ) /** Concatenate all the specified strings into a single newly allocated one */ -#define wcsdupcat( str,... ) wcsdupcat_internal( str, __VA_ARGS__, (void *)0 ) +#define wcsdupcat( str,... ) wcsdupcat_internal( str, __VA_ARGS__, NULL ) /** Print a stack trace to stderr @@ -181,7 +192,7 @@ wchar_t **list_to_char_arr( array_list_t *l ); Read a line from the stream f into the buffer buff of length len. If buff is to small, it will be reallocated, and both buff and len will be updated to reflect this. Returns the number of bytes read or -1 - on failiure. + on failiure. If the carriage return character is encountered, it is ignored. fgetws() considers the line to end if reading the file @@ -196,6 +207,8 @@ int fgetws2( wchar_t **buff, int *len, FILE *f ); */ void sort_list( array_list_t *comp ); +void sort_strings( std::vector &strings); + /** Returns a newly allocated wide character string equivalent of the specified multibyte character string @@ -205,6 +218,15 @@ void sort_list( array_list_t *comp ); */ wchar_t *str2wcs( const char *in ); +/** + 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. + */ +wcstring str2wcstring( 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 @@ -223,6 +245,16 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out ); way using the private use area. */ char *wcs2str( const wchar_t *in ); +std::string wcs2string(const wcstring &input); + +void assert_is_main_thread(const char *who); +#define ASSERT_IS_MAIN_THREAD_TRAMPOLINE(x) assert_is_main_thread(x) +#define ASSERT_IS_MAIN_THREAD() ASSERT_IS_MAIN_THREAD_TRAMPOLINE(__FUNCTION__) + +void assert_is_background_thread(const char *who); +#define ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(x) assert_is_background_thread(x) +#define ASSERT_IS_BACKGROUND_THREAD() ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(__FUNCTION__) + /** Converts the wide character string \c in into it's narrow @@ -234,6 +266,67 @@ char *wcs2str( const wchar_t *in ); */ char *wcs2str_internal( const wchar_t *in, char *out ); +/** + Converts some type to a wstring. + */ +template +wcstring format_val(T x) { + std::wstringstream stream; + stream << x; + return stream.str(); +} + +template +T from_string(const wcstring &x) { + T result; + std::wstringstream stream(x); + stream >> result; + return result; +} + +class scoped_lock { + pthread_mutex_t *lock; +public: + scoped_lock(pthread_mutex_t &mutex) : lock(&mutex) { + VOMIT_ON_FAILURE(pthread_mutex_lock(lock)); + } + + ~scoped_lock() { + VOMIT_ON_FAILURE(pthread_mutex_unlock(lock)); + } +}; + +class wcstokenizer { + wchar_t *buffer, *str, *state; + const wcstring sep; + +public: + wcstokenizer(const wcstring &s, const wcstring &separator) : sep(separator) { + wchar_t *wcsdup(const wchar_t *s); + buffer = wcsdup(s.c_str()); + str = buffer; + state = NULL; + } + + bool next(wcstring &result) { + wchar_t *tmp = wcstok(str, sep.c_str(), &state); + str = NULL; + if (tmp) result = tmp; + return tmp != NULL; + } + + ~wcstokenizer() { + free(buffer); + } +}; + +/** + Appends a path component, with a / if necessary + */ +void append_path_component(wcstring &path, const wcstring &component); + +wcstring format_string(const wchar_t *format, ...); + /** Returns a newly allocated wide character string array equivalent of the specified multibyte character string array @@ -258,7 +351,7 @@ __sentinel wchar_t *wcsdupcat_internal( const wchar_t *a, ... ); /** - Test if the given string is a valid variable name. + 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 */ @@ -267,7 +360,7 @@ wchar_t *wcsvarname( const wchar_t *str ); /** - Test if the given string is a valid function name. + Test if the given string is a valid function name. \return null if this is a valid name, and a pointer to the first invalid character otherwise */ @@ -275,7 +368,7 @@ wchar_t *wcsvarname( const wchar_t *str ); wchar_t *wcsfuncname( const wchar_t *str ); /** - Test if the given string is valid in a variable name + Test if the given string is valid in a variable name \return 1 if this is a valid name, 0 otherwise */ @@ -311,14 +404,14 @@ void error_reset(); This function behaves exactly like a wide character equivalent of the C function setlocale, except that it will also try to detect if the user is using a Unicode character set, and if so, use the - unicode ellipsis character as ellipsis, instead of '$'. + unicode ellipsis character as ellipsis, instead of '$'. */ const wchar_t *wsetlocale( int category, const wchar_t *locale ); /** 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 + \param needle the string to search for in the list \return zero if needle is not found, of if needle is null, non-zero otherwise */ @@ -346,9 +439,9 @@ ssize_t write_loop(int fd, char *buff, size_t count); Because debug is often called to tell the user about an error, before using wperror to give a specific error message, debug will never ever modify the value of errno. - + \param level the priority of the message. Lower number means higher priority. Messages with a priority_number higher than \c debug_level will be ignored.. - \param msg the message format string. + \param msg the message format string. Example: @@ -360,7 +453,7 @@ void debug( int level, const wchar_t *msg, ... ); /** Replace special characters with backslash escape sequences. Newline is - replaced with \n, etc. + replaced with \n, etc. \param in The string to be escaped \param escape_all Whether all characters wich hold special meaning in fish (Pipe, semicolon, etc,) should be escaped, or only unprintable characters @@ -368,6 +461,7 @@ void debug( int level, const wchar_t *msg, ... ); */ wchar_t *escape( const wchar_t *in, int escape_all ); +wcstring escape_string( const wcstring &in, int escape_all ); /** Expand backslashed escapes and substitute them with their unescaped @@ -380,21 +474,24 @@ wchar_t *escape( const wchar_t *in, int escape_all ); an invalid sequence is specified, 0 is returned. */ -wchar_t *unescape( const wchar_t * in, +wchar_t *unescape( const wchar_t * in, int escape_special ); +void unescape_string( wcstring &str, + int escape_special ); + /** - Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL - milliseconds between polls and timing out after timeout seconds, + Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL + milliseconds between polls and timing out after timeout seconds, thereafter forcibly attempting to obtain the lock if force is non-zero. Returns 1 on success, 0 on failure. To release the lock the lockfile must be unlinked. - A unique temporary file named by appending characters to the lockfile name + A unique temporary file named by appending characters to the lockfile name is used; any pre-existing file of the same name is subject to deletion. */ int acquire_lock_file( const char *lockfile, const int timeout, int force ); -/** +/** Returns the width of the terminal window, so that not all functions that use these values continually have to keep track of it separately. @@ -428,9 +525,9 @@ 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. + \param out the list in which to place the elements. */ void tokenize_variable_array( const wchar_t *val, array_list_t *out ); @@ -440,7 +537,7 @@ void tokenize_variable_array( const wchar_t *val, array_list_t *out ); \return 0 if, at the time of function return the directory exists, -1 otherwise. */ -int create_directory( wchar_t *d ); +int create_directory( const wchar_t *d ); /** Print a short message about how to file a bug report to stderr diff --git a/complete.cpp b/complete.cpp index 3853e8700..d76a53878 100644 --- a/complete.cpp +++ b/complete.cpp @@ -124,7 +124,7 @@ If either short_opt or long_opt are non-zero, they specify a switch for the command. If \c comp is also not empty, it contains a list of non-switch arguments that may only follow directly after the - specified switch. + specified switch. */ typedef struct complete_entry_opt { @@ -192,7 +192,7 @@ void completion_allocate( array_list_t *context, const wchar_t *desc, int flags ) { - completion_t *res = halloc( context, sizeof( completion_t) ); + completion_t *res = (completion_t *)halloc( context, sizeof( completion_t) ); res->completion = halloc_wcsdup( context, comp ); if( desc ) res->description = halloc_wcsdup( context, desc ); @@ -202,12 +202,12 @@ void completion_allocate( array_list_t *context, int len = wcslen(comp); flags = flags & (~COMPLETE_AUTO_SPACE); - + if( ( len > 0 ) && ( wcschr( L"/=@:", comp[ len - 1 ] ) != 0 ) ) flags |= COMPLETE_NO_SPACE; - + } - + res->flags = flags; al_push( context, res ); } @@ -218,7 +218,7 @@ void completion_allocate( array_list_t *context, static void complete_destroy() { complete_entry_t *i=first_entry, *prev; - + while( i ) { prev = i; @@ -226,9 +226,9 @@ static void complete_destroy() complete_free_entry( prev ); } first_entry = 0; - + parse_util_load_reset( L"fish_complete_path", 0 ); - + } /** @@ -276,7 +276,7 @@ static int condition_test( const wchar_t *condition ) if( !condition_cache ) { - condition_cache = malloc( sizeof( hash_table_t ) ); + condition_cache = (hash_table_t *)malloc( sizeof( hash_table_t ) ); if( !condition_cache ) { DIE_MEM(); @@ -302,7 +302,7 @@ static int condition_test( const wchar_t *condition ) */ } - if( wcscmp( test_res, CC_TRUE ) == 0 ) + if( wcscmp( (const wchar_t *)test_res, CC_TRUE ) == 0 ) { return 1; } @@ -318,7 +318,7 @@ static void complete_free_opt_recursive( complete_entry_opt_t *o ) { if( !o ) return; - + complete_free_opt_recursive( o->next ); halloc_free( o ); } @@ -365,11 +365,11 @@ static complete_entry_t *complete_get_exact_entry( const wchar_t *cmd, if( c == 0 ) { - if( !(c = malloc( sizeof(complete_entry_t) ))) + if( !(c = (complete_entry_t *)malloc( sizeof(complete_entry_t) ))) { DIE_MEM(); } - + c->next = first_entry; first_entry = c; @@ -415,15 +415,15 @@ void complete_add( const wchar_t *cmd, c = complete_get_exact_entry( cmd, cmd_type ); - opt = halloc( 0, sizeof( complete_entry_opt_t ) ); - + opt = (complete_entry_opt_t *)halloc( 0, sizeof( complete_entry_opt_t ) ); + opt->next = c->first_option; c->first_option = opt; if( short_opt != L'\0' ) { int len = 1 + ((result_mode & NO_COMMON) != 0); c->short_opt_str = - realloc( c->short_opt_str, + (wchar_t *)realloc( c->short_opt_str, sizeof(wchar_t)*(wcslen( c->short_opt_str ) + 1 + len) ); wcsncat( c->short_opt_str, &short_opt, 1 ); @@ -432,7 +432,7 @@ void complete_add( const wchar_t *cmd, wcscat( c->short_opt_str, L":" ); } } - + opt->short_opt = short_opt; opt->result_mode = result_mode; opt->old_mode=old_mode; @@ -441,7 +441,7 @@ void complete_add( const wchar_t *cmd, opt->condition = condition?halloc_wcsdup(opt, condition):L""; opt->long_opt = long_opt?halloc_wcsdup(opt, long_opt):L"" ; opt->flags = flags; - + if( desc && wcslen( desc ) ) { opt->desc = halloc_wcsdup( opt, desc ); @@ -450,7 +450,7 @@ void complete_add( const wchar_t *cmd, { opt->desc = L""; } - + } /** @@ -463,7 +463,7 @@ static complete_entry_t *complete_remove_entry( complete_entry_t *e, { complete_entry_opt_t *o, *oprev=0, *onext=0; - + if(( short_opt == 0 ) && (long_opt == 0 ) ) { complete_free_opt_recursive( e->first_option ); @@ -471,11 +471,11 @@ static complete_entry_t *complete_remove_entry( complete_entry_t *e, } else { - + for( o= e->first_option; o; o=onext ) { onext=o->next; - + if( ( short_opt==o->short_opt ) || ( wcscmp( long_opt, o->long_opt ) == 0 ) ) { @@ -496,13 +496,13 @@ static complete_entry_t *complete_remove_entry( complete_entry_t *e, { pos2++; } - + memmove( pos, pos2, sizeof(wchar_t)*wcslen(pos2) ); } } - + if( oprev == 0 ) { e->first_option = o->next; @@ -519,14 +519,14 @@ static complete_entry_t *complete_remove_entry( complete_entry_t *e, } } } - + if( e && (e->first_option == 0) ) { free( e->short_opt_str ); free( e ); e=0; } - + return e; } @@ -540,7 +540,7 @@ void complete_remove( const wchar_t *cmd, complete_entry_t *e, *eprev=0, *enext=0; CHECK( cmd, ); - + for( e = first_entry; e; e=enext ) { enext=e->next; @@ -566,7 +566,7 @@ void complete_remove( const wchar_t *cmd, first_entry = enext; } } - + } } @@ -575,7 +575,7 @@ void complete_remove( const wchar_t *cmd, pointers are allocated using halloc and will be free'd when\c context is halloc_free'd. */ -static void parse_cmd_string( void *context, +static void parse_cmd_string( void *context, const wchar_t *str, wchar_t **pathp, wchar_t **cmdp ) @@ -592,7 +592,7 @@ static void parse_cmd_string( void *context, */ path = halloc_wcsdup( context, L""); } - + /* Make sure the path is not included in the command */ cmd = wcsrchr( str, L'/' ); if( cmd != 0 ) @@ -603,7 +603,7 @@ static void parse_cmd_string( void *context, { cmd = (wchar_t *)str; } - + *pathp=path; *cmdp=cmd; } @@ -627,10 +627,10 @@ int complete_is_valid_option( const wchar_t *str, char *short_validated; void *context; - + CHECK( str, 0 ); CHECK( opt, 0 ); - + /* Check some generic things like -- and - options. */ @@ -642,7 +642,7 @@ int complete_is_valid_option( const wchar_t *str, { return 1; } - + case 2: { if( wcscmp( L"--", opt ) == 0 ) @@ -652,7 +652,7 @@ int complete_is_valid_option( const wchar_t *str, break; } } - + if( opt[0] != L'-' ) { if( errors ) @@ -664,11 +664,11 @@ int complete_is_valid_option( const wchar_t *str, context = halloc( 0, 0 ); - if( !(short_validated = halloc( context, wcslen( opt ) ))) + if( !(short_validated = (char *)halloc( context, wcslen( opt ) ))) { DIE_MEM(); } - + memset( short_validated, 0, wcslen( opt ) ); @@ -690,14 +690,14 @@ int complete_is_valid_option( const wchar_t *str, gnu_opt_len = wcslen(opt)-2; } } - + parse_cmd_string( context, str, &path, &cmd ); /* Make sure completions are loaded for the specified command */ complete_load( cmd, 0 ); - + for( i=first_entry; i; i=i->next ) { wchar_t *match = i->cmd_type?path:cmd; @@ -707,7 +707,7 @@ int complete_is_valid_option( const wchar_t *str, { continue; } - + found_match = 1; if( !i->authoritative ) @@ -726,7 +726,7 @@ int complete_is_valid_option( const wchar_t *str, { continue; } - + if( wcsncmp( &opt[2], o->long_opt, gnu_opt_len )==0) { hash_put( &gnu_match_hash, o->long_opt, L"" ); @@ -845,7 +845,7 @@ int complete_is_valid_option( const wchar_t *str, hash_destroy( &gnu_match_hash ); halloc_free( context ); - + return (authoritative && found_match)?opt_found:1; } @@ -893,7 +893,7 @@ static void complete_strings( array_list_t *comp_out, wc = parse_util_unescape_wildcards( tmp ); free(tmp); - + for( i=0; icompletion) || (c->completion[wcslen(c->completion)-1] != L'/' )) + + if( !wcslen( c->completion) || (c->completion[wcslen(c->completion)-1] != L'/' )) { skip = 0; break; } - + } - + if( skip ) { return; } - + esc = escape( cmd_start, 1 ); @@ -985,7 +985,7 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp ) */ if( exec_subshell( lookup_cmd, &list ) != -1 ) { - + /* Then discard anything that is not a possible completion and put the result into a hashtable with the completion as key and the @@ -997,7 +997,7 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp ) { wchar_t *el = (wchar_t *)al_get( &list, i ); wchar_t *key, *key_end, *val_begin; - + if( !el ) continue; @@ -1006,7 +1006,7 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp ) if( !key_end ) continue; - + *key_end = 0; val_begin = key_end+1; @@ -1016,7 +1016,7 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp ) things. */ val_begin[0]=towupper(val_begin[0]); - + hash_put( &lookup, key, val_begin ); } @@ -1031,19 +1031,19 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp ) { completion_t *c = (completion_t *)al_get( comp, i ); const wchar_t *el = c->completion; - + wchar_t *new_desc; - + new_desc = (wchar_t *)hash_get( &lookup, el ); - + if( new_desc ) { c->description = halloc_wcsdup( comp, new_desc ); } } } - + hash_destroy( &lookup ); al_foreach( &list, &free ); @@ -1095,7 +1095,7 @@ static void complete_cmd( const wchar_t *cmd, if( use_command ) { - + if( expand_string( 0, wcsdup(cmd), comp, @@ -1109,13 +1109,13 @@ static void complete_cmd( const wchar_t *cmd, { if( use_command ) { - + path = env_get(L"PATH"); if( path ) { - + path_cpy = wcsdup( path ); - + for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state ); nxt_path != 0; nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) ) @@ -1124,21 +1124,21 @@ static void complete_cmd( const wchar_t *cmd, int i; int path_len = wcslen(nxt_path); int add_slash; - + if( !path_len ) { continue; } - + add_slash = nxt_path[path_len-1]!=L'/'; nxt_completion = wcsdupcat( nxt_path, add_slash?L"/":L"", cmd ); if( ! nxt_completion ) continue; - + prev_count = al_get_count( comp ); - + if( expand_string( 0, nxt_completion, comp, @@ -1159,7 +1159,7 @@ static void complete_cmd( const wchar_t *cmd, complete_cmd_desc( cmd, comp ); } } - + /* These return the original strings - don't free them */ @@ -1173,7 +1173,7 @@ static void complete_cmd( const wchar_t *cmd, } al_truncate( &possible_comp, 0 ); - + if( use_builtin ) { builtin_get_names( &possible_comp ); @@ -1202,7 +1202,7 @@ static void complete_cmd( const wchar_t *cmd, { continue; } - + if( expand_string( 0, nxt_completion, comp, @@ -1242,7 +1242,7 @@ static void complete_from_args( const wchar_t *str, proc_push_interactive(0); eval_args( args, &possible_comp ); proc_pop_interactive(); - + complete_strings( comp_out, str, desc, 0, &possible_comp, flags ); al_foreach( &possible_comp, &free ); @@ -1355,10 +1355,10 @@ static void complete_load_handler( const wchar_t *cmd ) void complete_load( const wchar_t *name, int reload ) { CHECK( name, ); - parse_util_load( name, + parse_util_load( name, L"fish_complete_path", - &complete_load_handler, - reload ); + &complete_load_handler, + reload ); } /** @@ -1380,7 +1380,7 @@ static int complete_param( const wchar_t *cmd_orig, int use_common=1, use_files=1; void *context = halloc( 0, 0 ); - + parse_cmd_string( context, cmd_orig, &path, &cmd ); complete_load( cmd, 1 ); @@ -1395,11 +1395,11 @@ static int complete_param( const wchar_t *cmd_orig, { continue; } - + use_common=1; if( use_switches ) { - + if( str[0] == L'-' ) { /* Check if we are entering a combined option and argument @@ -1420,7 +1420,7 @@ static int complete_param( const wchar_t *cmd_orig, { /* Set to true if we found a matching old-style switch */ int old_style_match = 0; - + /* If we are using old style long options, check for them first @@ -1438,7 +1438,7 @@ static int complete_param( const wchar_t *cmd_orig, } } } - + /* No old style option matched, or we are not using old style options. We check if any short (or gnu style @@ -1467,7 +1467,7 @@ static int complete_param( const wchar_t *cmd_orig, } } } - + if( use_common ) { @@ -1487,7 +1487,7 @@ static int complete_param( const wchar_t *cmd_orig, use_files &= ((o->result_mode & NO_FILES )==0); complete_from_args( str, o->comp, C_(o->desc), comp_out, o->flags ); } - + if( wcslen(str) > 0 && use_switches ) { /* @@ -1500,7 +1500,7 @@ static int complete_param( const wchar_t *cmd_orig, wchar_t completion[2]; completion[0] = o->short_opt; completion[1] = 0; - + completion_allocate( comp_out, completion, desc, 0 ); } @@ -1511,9 +1511,9 @@ static int complete_param( const wchar_t *cmd_orig, if( o->long_opt[0] != L'\0' ) { int match=0, match_no_case=0; - + string_buffer_t *whole_opt = sb_halloc( context ); - sb_append( whole_opt, o->old_mode?L"-":L"--", o->long_opt, (void *)0 ); + sb_append( whole_opt, o->old_mode?L"-":L"--", o->long_opt, NULL ); match = wcsncmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0; @@ -1521,7 +1521,7 @@ static int complete_param( const wchar_t *cmd_orig, { match_no_case = wcsncasecmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0; } - + if( match || match_no_case ) { int has_arg=0; /* Does this switch have any known arguments */ @@ -1530,7 +1530,7 @@ static int complete_param( const wchar_t *cmd_orig, int offset = 0; int flags = 0; - + if( match ) offset = wcslen( str ); else @@ -1541,7 +1541,7 @@ static int complete_param( const wchar_t *cmd_orig, if( !o->old_mode && ( has_arg && !req_arg ) ) { - + /* Optional arguments to a switch can only be handled using the '=', so we @@ -1555,31 +1555,31 @@ static int complete_param( const wchar_t *cmd_orig, sb_init( &completion ); sb_printf( &completion, - L"%ls=", + L"%ls=", ((wchar_t *)whole_opt->buff)+offset ); - + completion_allocate( comp_out, (wchar_t *)completion.buff, C_(o->desc), - flags ); - + flags ); + sb_destroy( &completion ); - + } - + completion_allocate( comp_out, ((wchar_t *)whole_opt->buff) + offset, C_(o->desc), flags ); - } + } } } } } } - + halloc_free( context ); - + return use_files; } @@ -1592,7 +1592,7 @@ static void complete_param_expand( wchar_t *str, { wchar_t *comp_str; int flags; - + if( (wcsncmp( str, L"--", 2 )) == 0 && (comp_str = wcschr(str, L'=' ) ) ) { comp_str++; @@ -1602,18 +1602,18 @@ static void complete_param_expand( wchar_t *str, comp_str = str; } - flags = EXPAND_SKIP_CMDSUBST | - ACCEPT_INCOMPLETE | + flags = EXPAND_SKIP_CMDSUBST | + ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS); - - if( expand_string( 0, + + if( expand_string( 0, wcsdup(comp_str), comp_out, flags ) == EXPAND_ERROR ) { debug( 3, L"Error while expanding string '%ls'", comp_str ); } - + } @@ -1636,13 +1636,13 @@ static int complete_variable( const wchar_t *whole_var, { wchar_t *name = (wchar_t *)al_get( &names, i ); int namelen = wcslen( name ); - int match=0, match_no_case=0; + int match=0, match_no_case=0; if( varlen > namelen ) continue; match = ( wcsncmp( var, name, varlen) == 0 ); - + if( !match ) { match_no_case = ( wcsncasecmp( var, name, varlen) == 0 ); @@ -1659,11 +1659,11 @@ static int complete_variable( const wchar_t *whole_var, string_buffer_t comp; int flags = 0; int offset = 0; - + sb_init( &comp ); if( match ) { - sb_append( &comp, &name[varlen] ); + sb_append( &comp, &name[varlen] ); offset = varlen; } else @@ -1672,23 +1672,23 @@ static int complete_variable( const wchar_t *whole_var, sb_append( &comp, name ); flags = COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE; } - + value = expand_escape_variable( value_unescaped ); sb_init( &desc ); sb_printf( &desc, COMPLETE_VAR_DESC_VAL, value ); - - completion_allocate( comp_list, + + completion_allocate( comp_list, (wchar_t *)comp.buff, (wchar_t *)desc.buff, flags ); res =1; - + free( value ); sb_destroy( &desc ); sb_destroy( &comp ); } - + } } @@ -1698,7 +1698,7 @@ static int complete_variable( const wchar_t *whole_var, /** Search the specified string for the \$ sign. If found, try to - complete as an environment variable. + complete as an environment variable. \return 0 if unable to complete, 1 otherwise */ @@ -1735,7 +1735,7 @@ static int try_complete_user( const wchar_t *cmd, const wchar_t *first_char=cmd; int res=0; double start_time = timef(); - + if( *first_char ==L'~' && !wcschr(first_char, L'/')) { const wchar_t *user_name = first_char+1; @@ -1744,19 +1744,19 @@ static int try_complete_user( const wchar_t *cmd, { struct passwd *pw; int name_len = wcslen( user_name ); - + setpwent(); - + while((pw=getpwent()) != 0) { double current_time = timef(); wchar_t *pw_name; - if( current_time - start_time > 0.2 ) + if( current_time - start_time > 0.2 ) { return 1; } - + pw_name = str2wcs( pw->pw_name ); if( pw_name ) @@ -1764,26 +1764,26 @@ static int try_complete_user( const wchar_t *cmd, if( wcsncmp( user_name, pw_name, name_len )==0 ) { string_buffer_t desc; - + sb_init( &desc ); sb_printf( &desc, COMPLETE_USER_DESC, pw_name ); - - completion_allocate( comp, + + completion_allocate( comp, &pw_name[name_len], (wchar_t *)desc.buff, COMPLETE_NO_SPACE ); - + res=1; - + sb_destroy( &desc ); } else if( wcsncasecmp( user_name, pw_name, name_len )==0 ) { - string_buffer_t name; - string_buffer_t desc; - + string_buffer_t name; + string_buffer_t desc; + sb_init( &name ); sb_init( &desc ); sb_printf( &name, @@ -1792,16 +1792,16 @@ static int try_complete_user( const wchar_t *cmd, sb_printf( &desc, COMPLETE_USER_DESC, pw_name ); - - completion_allocate( comp, + + completion_allocate( comp, (wchar_t *)name.buff, (wchar_t *)desc.buff, COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE ); res=1; - + sb_destroy( &desc ); sb_destroy( &name ); - + } free( pw_name ); } @@ -1862,9 +1862,9 @@ void complete( const wchar_t *cmd, if( !done ) { pos = cursor_pos-(cmdsubst_begin-cmd); - + buff = wcsndup( cmdsubst_begin, cmdsubst_end-cmdsubst_begin ); - + if( !buff ) done=1; } @@ -1887,7 +1887,7 @@ void complete( const wchar_t *cmd, wchar_t *ncmd = tok_last( &tok ); int is_ddash = (wcscmp( ncmd, L"--" ) == 0) && ( (tok_get_pos( &tok )+2) < pos ); - + if( !had_cmd ) { @@ -1908,17 +1908,17 @@ void complete( const wchar_t *cmd, break; } - + if( !is_ddash || ( (use_command && use_function && use_builtin ) ) ) { int token_end; - + free( current_command ); current_command = wcsdup( ncmd ); - + token_end = tok_get_pos( &tok ) + wcslen( ncmd ); - + on_command = (pos <= token_end ); had_cmd=1; } @@ -1931,10 +1931,10 @@ void complete( const wchar_t *cmd, had_ddash = 1; } } - + break; } - + case TOK_END: case TOK_PIPE: case TOK_BACKGROUND: @@ -1946,20 +1946,20 @@ void complete( const wchar_t *cmd, use_builtin = 1; break; } - + case TOK_ERROR: { end_loop=1; break; } - + } if( tok_get_pos( &tok ) >= pos ) { end_loop=1; } - + tok_next( &tok ); } @@ -1974,7 +1974,7 @@ void complete( const wchar_t *cmd, current_token = wcsndup( tok_begin, cursor_pos-(tok_begin-cmd) ); prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L""); - + // debug( 0, L"on_command: %d, %ls %ls\n", on_command, current_command, current_token ); /* @@ -1983,9 +1983,9 @@ void complete( const wchar_t *cmd, case, complete using the builtins completions, not using a subcommand. */ - + if( (on_command || (wcscmp( current_token, L"--" ) == 0 ) ) && - (current_token[0] == L'-') && + (current_token[0] == L'-') && !(use_command && use_function && use_builtin ) ) { free( current_command ); @@ -1993,11 +1993,11 @@ void complete( const wchar_t *cmd, current_command = wcsdup( L"builtin" ); else current_command = wcsdup( L"command" ); - + had_cmd = 1; on_command = 0; } - + /* Use command completions if in between commands */ @@ -2005,7 +2005,7 @@ void complete( const wchar_t *cmd, { on_command=1; } - + /* We don't want these to be null */ @@ -2014,12 +2014,12 @@ void complete( const wchar_t *cmd, { current_token = wcsdup(L""); } - + if( !current_command ) { current_command = wcsdup(L""); } - + if( !prev_token ) { prev_token = wcsdup(L""); @@ -2036,31 +2036,31 @@ void complete( const wchar_t *cmd, else { int do_file=0; - + wchar_t *current_command_unescape = unescape( current_command, 0 ); wchar_t *prev_token_unescape = unescape( prev_token, 0 ); wchar_t *current_token_unescape = unescape( current_token, UNESCAPE_INCOMPLETE ); - + if( current_token_unescape && prev_token_unescape && current_token_unescape ) { - do_file = complete_param( current_command_unescape, - prev_token_unescape, - current_token_unescape, - !had_ddash, + do_file = complete_param( current_command_unescape, + prev_token_unescape, + current_token_unescape, + !had_ddash, comp ); } - + free( current_command_unescape ); free( prev_token_unescape ); free( current_token_unescape ); - + /* If we have found no command specific completions at all, fall back to using file completions. */ if( !al_get_count( comp ) ) do_file = 1; - + /* This function wants the unescaped string */ @@ -2068,7 +2068,7 @@ void complete( const wchar_t *cmd, } } } - + free( current_token ); free( current_command ); free( prev_token ); diff --git a/complete.h b/complete.h index 36d10e3a0..74c2b5a0d 100644 --- a/complete.h +++ b/complete.h @@ -16,39 +16,39 @@ #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) */ #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 -/** +/** Separator between completion and description */ #define COMPLETE_SEP L'\004' -/** +/** Separator between completion and description */ #define COMPLETE_SEP_STR L"\004" @@ -73,7 +73,7 @@ #define COMPLETE_NO_SPACE 1 /** - This compeltion is case insensitive. + This compeltion is case insensitive. Warning: The contents of the completion_t structure is actually different if this flag is set! Specifically, the completion string @@ -115,7 +115,7 @@ typedef struct const wchar_t *description; /** - Flags determining the completion behaviour. + Flags determining the completion behaviour. Determines whether a space should be inserted after this compeltion if it is the only possible completion using the @@ -132,17 +132,17 @@ typedef struct /** - Add a completion. + Add a completion. All supplied values are copied, they should be freed by or otherwise disposed by the caller. - Examples: - + Examples: + The command 'gcc -o' requires that a file follows it, so the NO_COMMON option is suitable. This can be done using the following line: - + complete -c gcc -s o -r The command 'grep -d' required that one of the strings 'read', @@ -159,7 +159,7 @@ typedef struct will be interpreted as the command name. \param short_opt The single character name of an option. (-a is a short option, --all and -funroll are long options) \param long_opt The multi character name of an option. (-a is a short option, --all and -funroll are long options) - \param long_mode Whether to use old style, single dash long options. + \param long_mode Whether to use old style, single dash long options. \param result_mode Whether to search further completions when this completion has been succesfully matched. If result_mode is SHARED, any other completions may also be used. If result_mode is NO_FILES, @@ -172,16 +172,16 @@ typedef struct \param condition a command to be run to check it this completion should be used. If \c condition is empty, the completion is always used. \param flags A set of completion flags */ -void complete_add( const wchar_t *cmd, - int cmd_type, +void complete_add( const wchar_t *cmd, + int cmd_type, wchar_t short_opt, const wchar_t *long_opt, - int long_mode, - int result_mode, + int long_mode, + int result_mode, const wchar_t *condition, const wchar_t *comp, const wchar_t *desc, - int flags ); + int flags ); /** Sets whether the completion list for this command is complete. If true, any options not matching one of the provided options will be @@ -194,8 +194,8 @@ void complete_set_authoritative( const wchar_t *cmd, /** Remove a previously defined completion */ -void complete_remove( const wchar_t *cmd, - int cmd_type, +void complete_remove( const wchar_t *cmd, + int cmd_type, wchar_t short_opt, const wchar_t *long_opt ); @@ -212,7 +212,7 @@ void complete_remove( const wchar_t *cmd, void complete( const wchar_t *cmd, array_list_t *out ); /** - Print a list of all current completions into the string_buffer_t. + Print a list of all current completions into the string_buffer_t. \param out The string_buffer_t to write completions to */ @@ -221,16 +221,16 @@ void complete_print( string_buffer_t *out ); /** Tests if the specified option is defined for the specified command */ -int complete_is_valid_option( const wchar_t *str, - const wchar_t *opt, +int complete_is_valid_option( const wchar_t *str, + const wchar_t *opt, array_list_t *errors ); /** Tests if the specified argument is valid for the specified option and command */ -int complete_is_valid_argument( const wchar_t *str, - const wchar_t *opt, +int complete_is_valid_argument( const wchar_t *str, + const wchar_t *opt, const wchar_t *arg ); diff --git a/env.cpp b/env.cpp index b7c848e3a..01062ee50 100644 --- a/env.cpp +++ b/env.cpp @@ -12,7 +12,10 @@ #include #include #include +#include #include +#include +#include #if HAVE_NCURSES_H #include @@ -83,11 +86,11 @@ extern char **__environ; */ typedef struct env_node { - /** - Variable table + /** + Variable table */ hash_table_t env; - /** + /** Does this node imply a new variable scope? If yes, all non-global variables below this one in the stack are invisible. If new_scope is set for the global variable node, @@ -97,9 +100,9 @@ typedef struct env_node /** Does this node contain any variables which are exported to subshells */ - int export; - - /** + int exportv; + + /** Pointer to next level */ struct env_node *next; @@ -113,9 +116,9 @@ typedef struct env_node */ typedef struct var_entry { - int export; /**< Whether the variable should be exported */ + int exportv; /**< Whether the variable should be exported */ size_t size; /**< The maximum length (excluding the NULL) that will fit into this var_entry_t */ - + #if __STDC_VERSION__ < 199901L wchar_t val[1]; /**< The value of the variable */ #else @@ -124,6 +127,13 @@ typedef struct var_entry } var_entry_t; +class variable_entry_t { + bool exportv; /**< Whether the variable should be exported */ + wcstring value; /**< Value of the variable */ +}; + +static pthread_mutex_t env_lock = PTHREAD_MUTEX_INITIALIZER; + /** Top node on the function stack */ @@ -143,12 +153,23 @@ static hash_table_t *global; /** Table of variables that may not be set using the set command. */ -static hash_table_t env_read_only; +static std::set env_read_only; + +static bool is_read_only(const wcstring &key) +{ + return env_read_only.find(key) != env_read_only.end(); +} /** Table of variables whose value is dynamically calculated, such as umask, status, etc */ -static hash_table_t env_electric; +static std::set env_electric; + +static bool is_electric(const wcstring &key) +{ + return env_electric.find(key) != env_electric.end(); +} + /** Exported variable array used by execv @@ -197,7 +218,7 @@ static const wchar_t *locale_variable[] = L"LC_MONETARY", L"LC_NUMERIC", L"LC_TIME", - (void *)0 + NULL } ; @@ -206,12 +227,12 @@ static const wchar_t *locale_variable[] = */ static void clear_hash_entry( void *key, void *data ) { - var_entry_t *entry = (var_entry_t *)data; - if( entry->export ) + var_entry_t *entry = (var_entry_t *)data; + if( entry->exportv ) { has_changed = 1; } - + free( (void *)key ); free( (void *)data ); } @@ -227,20 +248,20 @@ static void start_fishd() { string_buffer_t cmd; struct passwd *pw; - + sb_init( &cmd ); pw = getpwuid(getuid()); - + debug( 3, L"Spawning new copy of fishd" ); - + if( !pw ) { debug( 0, _( L"Could not get user information" ) ); return; } - + sb_printf( &cmd, FISHD_CMD, pw->pw_name ); - + eval( (wchar_t *)cmd.buff, 0, TOP ); @@ -282,15 +303,15 @@ static void handle_locale() const wchar_t *lc_all = env_get( L"LC_ALL" ); const wchar_t *lang; int i; - wchar_t *old = wcsdup(wsetlocale( LC_MESSAGES, (void *)0 )); + wchar_t *old = wcsdup(wsetlocale( LC_MESSAGES, NULL )); /* Array of locale constants corresponding to the local variable names defined in locale_variable */ - static const int cat[] = + static const int cat[] = { - 0, - LC_ALL, + 0, + LC_ALL, LC_COLLATE, LC_CTYPE, LC_MESSAGES, @@ -299,7 +320,7 @@ static void handle_locale() LC_TIME } ; - + if( lc_all ) { wsetlocale( LC_ALL, lc_all ); @@ -311,7 +332,7 @@ static void handle_locale() { wsetlocale( LC_ALL, lang ); } - + for( i=2; locale_variable[i]; i++ ) { const wchar_t *val = env_get( locale_variable[i] ); @@ -322,11 +343,11 @@ static void handle_locale() } } } - - if( wcscmp( wsetlocale( LC_MESSAGES, (void *)0 ), old ) != 0 ) + + if( wcscmp( wsetlocale( LC_MESSAGES, NULL ), old ) != 0 ) { - /* + /* Try to make change known to gettext. Both changing _nl_msg_cat_cntr and calling dcgettext might potentially tell some gettext implementation that the translation @@ -338,14 +359,14 @@ static void handle_locale() _nl_msg_cat_cntr++; dcgettext( "fish", "Changing language to English", LC_MESSAGES ); - + if( is_interactive ) { debug( 0, _(L"Changing language to English") ); } } free( old ); - + } @@ -354,16 +375,16 @@ static void handle_locale() proper events are triggered when an event occurs. */ static void universal_callback( int type, - const wchar_t *name, + const wchar_t *name, const wchar_t *val ) { - wchar_t *str=0; - + const wchar_t *str=0; + if( is_locale( name ) ) { handle_locale(); } - + switch( type ) { case SET: @@ -372,29 +393,29 @@ static void universal_callback( int type, str=L"SET"; break; } - + case ERASE: { str=L"ERASE"; break; } } - + if( str ) { event_t ev; - + has_changed=1; - + ev.type=EVENT_VARIABLE; ev.param1.variable=name; ev.function_name=0; - + al_init( &ev.arguments ); al_push( &ev.arguments, L"VARIABLE" ); al_push( &ev.arguments, str ); al_push( &ev.arguments, name ); - event_fire( &ev ); + event_fire( &ev ); al_destroy( &ev.arguments ); } } @@ -405,11 +426,11 @@ static void universal_callback( int type, static void setup_path() { wchar_t *path; - + int i, j; array_list_t l; - const wchar_t *path_el[] = + const wchar_t *path_el[] = { L"/bin", L"/usr/bin", @@ -419,19 +440,19 @@ static void setup_path() ; path = env_get( L"PATH" ); - + al_init( &l ); - + if( path ) { tokenize_variable_array( path, &l ); } - + for( j=0; path_el[j]; j++ ) { int has_el=0; - + for( i=0; ipw_dir ); env_set( L"HOME", dir, ENV_GLOBAL ); - free( dir ); + free( dir ); free( unam_narrow ); - } + } env_set_pwd(); - + } void env_init() @@ -528,55 +549,58 @@ void env_init() wchar_t *uname; wchar_t *version; wchar_t *shlvl; - + sb_init( &dyn_var ); b_init( &export_buffer ); - + /* - These variables can not be altered directly by the user + env_read_only variables can not be altered directly by the user */ - hash_init( &env_read_only, &hash_wcs_func, &hash_wcs_cmp ); - - hash_put( &env_read_only, L"status", L"" ); - hash_put( &env_read_only, L"history", L"" ); - hash_put( &env_read_only, L"version", L"" ); - hash_put( &env_read_only, L"_", L"" ); - hash_put( &env_read_only, L"LINES", L"" ); - hash_put( &env_read_only, L"COLUMNS", L"" ); - hash_put( &env_read_only, L"PWD", L"" ); - hash_put( &env_read_only, L"SHLVL", L"" ); - - /* - Names of all dynamically calculated variables - */ - hash_init( &env_electric, &hash_wcs_func, &hash_wcs_cmp ); - hash_put( &env_electric, L"history", L"" ); - hash_put( &env_electric, L"status", L"" ); - hash_put( &env_electric, L"umask", L"" ); - + + const wchar_t * const ro_keys[] = { + L"status", + L"history", + L"version", + L"_", + L"LINES", + L"COLUMNS", + L"PWD", + L"SHLVL", + }; + for (size_t i=0; i < sizeof ro_keys / sizeof *ro_keys; i++) { + env_read_only.insert(ro_keys[i]); + } + /* HOME and USER should be writeable by root, since this can be a convenient way to install software. */ if( getuid() != 0 ) { - hash_put( &env_read_only, L"HOME", L"" ); - hash_put( &env_read_only, L"USER", L"" ); + env_read_only.insert(L"HOME"); + env_read_only.insert(L"USER"); } - - top = malloc( sizeof(env_node_t) ); + + /* + Names of all dynamically calculated variables + */ + env_electric.insert(L"history"); + env_electric.insert(L"status"); + env_electric.insert(L"umask"); + + top = (env_node_t *)malloc( sizeof(env_node_t) ); top->next = 0; top->new_scope = 0; - top->export=0; + top->exportv=0; hash_init( &top->env, &hash_wcs_func, &hash_wcs_cmp ); global_env = top; - global = &top->env; - + global = &top->env; + /* Now the environemnt variable handling is set up, the next step is to insert valid data */ - + /* Import environment variables */ @@ -584,14 +608,14 @@ void env_init() { wchar_t *key, *val; wchar_t *pos; - + key = str2wcs(*p); if( !key ) { continue; } - + val = wcschr( key, L'=' ); if( val == 0 ) @@ -599,7 +623,7 @@ void env_init() env_set( key, L"", ENV_EXPORT ); } else - { + { *val = L'\0'; val++; pos=val; @@ -614,10 +638,10 @@ void env_init() } env_set( key, val, ENV_EXPORT | ENV_GLOBAL ); - } + } free(key); } - + /* Set up the PATH variable */ @@ -640,8 +664,8 @@ void env_init() version = str2wcs( PACKAGE_VERSION ); env_set( L"version", version, ENV_GLOBAL ); free( version ); - - env_universal_init( env_get( L"FISHD_SOCKET_DIR"), + + env_universal_init( env_get( L"FISHD_SOCKET_DIR"), env_get( L"USER" ), &start_fishd, &universal_callback ); @@ -656,8 +680,8 @@ void env_init() /* add an extra space for digit dump (9+1=10) */ size_t i = wcslen( shlvl ) + 2 * sizeof(wchar_t); - nshlvl = malloc(i); - end_nshlvl = calloc( 1, sizeof(nshlvl) ); + nshlvl = (wchar_t *)malloc(i); + end_nshlvl = (wchar_t **)calloc( 1, sizeof(nshlvl) ); if ( !nshlvl || !end_nshlvl ) DIE_MEM(); @@ -687,26 +711,26 @@ void env_init() void env_destroy() { env_universal_destroy(); - + sb_destroy( &dyn_var ); b_destroy( &export_buffer ); - + while( &top->env != global ) { env_pop(); } + + env_read_only.clear(); + env_electric.clear(); - hash_destroy( &env_read_only ); - - hash_destroy( &env_electric ); - + hash_foreach( global, &clear_hash_entry ); hash_destroy( global ); free( top ); - + free( export_arr ); - + } /** @@ -721,7 +745,7 @@ static env_node_t *env_get_node( const wchar_t *key ) while( env != 0 ) { - res = (var_entry_t *) hash_get( &env->env, + res = (var_entry_t *) hash_get( &env->env, key ); if( res != 0 ) { @@ -732,17 +756,17 @@ static env_node_t *env_get_node( const wchar_t *key ) { env = global_env; } - else + else { env = env->next; } } - + return 0; } -int env_set( const wchar_t *key, - const wchar_t *val, +int env_set( const wchar_t *key, + const wchar_t *val, int var_mode ) { int free_val = 0; @@ -750,14 +774,14 @@ int env_set( const wchar_t *key, env_node_t *node; int has_changed_old = has_changed; int has_changed_new = 0; - var_entry_t *e=0; + var_entry_t *e=0; int done=0; event_t ev; - int is_universal = 0; - + int is_universal = 0; + CHECK( key, ENV_INVALID ); - + if( val && contains( key, L"PWD", L"HOME" ) ) { void *context = halloc( 0, 0 ); @@ -771,12 +795,11 @@ int env_set( const wchar_t *key, halloc_free( context ); } - if( (var_mode & ENV_USER ) && - hash_get( &env_read_only, key ) ) + if( (var_mode & ENV_USER ) && is_read_only(key) ) { return ENV_PERM; } - + if( wcscmp( key, L"umask" ) == 0) { wchar_t *end; @@ -786,10 +809,10 @@ int env_set( const wchar_t *key, Set the new umask */ if( val && wcslen(val) ) - { + { errno=0; mask = wcstol( val, &end, 8 ); - + if( !errno && (!*end) && (mask <= 0777) && (mask >= 0) ) { umask( mask ); @@ -810,41 +833,41 @@ int env_set( const wchar_t *key, { val = ENV_NULL; } - + if( var_mode & ENV_UNIVERSAL ) { - int export = 0; + int exportv = 0; if( !(var_mode & ENV_EXPORT ) && !(var_mode & ENV_UNEXPORT ) ) { env_universal_get_export( key ); } - else + else { - export = (var_mode & ENV_EXPORT ); + exportv = (var_mode & ENV_EXPORT ); } - - env_universal_set( key, val, export ); + + env_universal_set( key, val, exportv ); is_universal = 1; } else { - + node = env_get_node( key ); if( node && &node->env != 0 ) { - e = (var_entry_t *) hash_get( &node->env, + e = (var_entry_t *) hash_get( &node->env, key ); - - if( e->export ) + + if( e->exportv ) { has_changed_new = 1; } } - if( (var_mode & ENV_LOCAL) || + if( (var_mode & ENV_LOCAL) || (var_mode & ENV_GLOBAL) ) { node = ( var_mode & ENV_GLOBAL )?global_env:top; @@ -855,8 +878,8 @@ int env_set( const wchar_t *key, { if( !(var_mode & ENV_EXPORT ) && !(var_mode & ENV_UNEXPORT ) ) - { - var_mode = e->export?ENV_EXPORT:0; + { + var_mode = e->exportv?ENV_EXPORT:0; } } else @@ -866,26 +889,26 @@ int env_set( const wchar_t *key, proc_had_barrier=1; env_universal_barrier(); } - + if( env_universal_get( key ) ) { - int export = 0; - + int exportv = 0; + if( !(var_mode & ENV_EXPORT ) && !(var_mode & ENV_UNEXPORT ) ) { env_universal_get_export( key ); } - else + else { - export = (var_mode & ENV_EXPORT ); + exportv = (var_mode & ENV_EXPORT ); } - - env_universal_set( key, val, export ); + + env_universal_set( key, val, exportv ); is_universal = 1; - + done = 1; - + } else { @@ -893,7 +916,7 @@ int env_set( const wchar_t *key, New variable with unspecified scope. The default scope is the innermost scope that is shadowing, which will be either the current function or the - global scope. + global scope. */ node = top; while( node->next && !node->new_scope ) @@ -903,7 +926,7 @@ int env_set( const wchar_t *key, } } } - + if( !done ) { void *k, *v; @@ -919,61 +942,61 @@ int env_set( const wchar_t *key, { k = wcsdup(key); } - + old_entry = (var_entry_t *)v; if( old_entry && old_entry->size >= val_len ) { entry = old_entry; - - if( !!(var_mode & ENV_EXPORT) || entry->export ) + + if( !!(var_mode & ENV_EXPORT) || entry->exportv ) { - entry->export = !!(var_mode & ENV_EXPORT); - has_changed_new = 1; + entry->exportv = !!(var_mode & ENV_EXPORT); + has_changed_new = 1; } } else { free( v ); - entry = malloc( sizeof( var_entry_t ) + + entry = (var_entry_t *)malloc( sizeof( var_entry_t ) + sizeof(wchar_t )*(val_len+1)); - + if( !entry ) { DIE_MEM(); } - + entry->size = val_len; - + if( var_mode & ENV_EXPORT) { - entry->export = 1; - has_changed_new = 1; + entry->exportv = 1; + has_changed_new = 1; } else { - entry->export = 0; + entry->exportv = 0; } - + } wcscpy( entry->val, val ); - + hash_put( &node->env, k, entry ); - if( entry->export ) + if( entry->exportv ) { - node->export=1; + node->exportv=1; } if( free_val ) { free((void *)val); } - + has_changed = has_changed_old || has_changed_new; } - + } if( !is_universal ) @@ -981,16 +1004,16 @@ int env_set( const wchar_t *key, 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"SET" ); al_push( &ev.arguments, key ); - -// debug( 1, L"env_set: fire events on variable %ls", key ); + +// debug( 1, L"env_set: fire events on variable %ls", key ); event_fire( &ev ); -// debug( 1, L"env_set: return from event firing" ); - al_destroy( &ev.arguments ); +// debug( 1, L"env_set: return from event firing" ); + al_destroy( &ev.arguments ); } if( is_locale( key ) ) @@ -1019,23 +1042,23 @@ static int try_remove( env_node_t *n, { return 0; } - - hash_remove( &n->env, + + hash_remove( &n->env, key, - &old_key_void, + &old_key_void, &old_val_void ); old_key = (wchar_t *)old_key_void; old_val = (wchar_t *)old_val_void; - + if( old_key != 0 ) { var_entry_t * v = (var_entry_t *)old_val; - if( v->export ) + if( v->exportv ) { has_changed = 1; } - + free(old_key); free(old_val); return 1; @@ -1045,7 +1068,7 @@ static int try_remove( env_node_t *n, { return 0; } - + if( n->new_scope ) { return try_remove( global_env, key, var_mode ); @@ -1061,48 +1084,47 @@ 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 ) ) + + if( (var_mode & ENV_USER ) && is_read_only(key) ) { return 2; } - + first_node = top; - + if( ! (var_mode & ENV_UNIVERSAL ) ) { - + 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 ); - + + event_fire( &ev ); + al_destroy( &ev.arguments ); erased = 1; } } - - if( !erased && + + if( !erased && !(var_mode & ENV_GLOBAL) && - !(var_mode & ENV_LOCAL) ) + !(var_mode & ENV_LOCAL) ) { erased = !env_universal_remove( key ); } @@ -1111,33 +1133,143 @@ int env_remove( const wchar_t *key, int var_mode ) { handle_locale(); } - - return !erased; + + return !erased; } +wcstring env_get_string( const wchar_t *key ) +{ + scoped_lock lock(env_lock); + + CHECK( key, 0 ); + if( wcscmp( key, L"history" ) == 0 ) + { + wcstring result; + wchar_t *current; + int i; + int add_current=0; + + current = reader_get_buffer(); + if( current && wcslen( current ) ) + { + add_current=1; + result += current; + } + + for( i=add_current;; i++ ) + { + // PCA This looks bad! + wchar_t *next = history_get( i-add_current ); + if( !next ) + { + break; + } + + if( i!=0) + { + result += ARRAY_SEP_STR; + } + result += next; + } + + return result; + } + else if( wcscmp( key, L"COLUMNS" )==0 ) + { + return format_val((long)common_get_width()); + } + else if( wcscmp( key, L"LINES" )==0 ) + { + return format_val((long)common_get_width()); + } + else if( wcscmp( key, L"status" )==0 ) + { + return format_val((long)proc_get_last_status()); + } + else if( wcscmp( key, L"umask" )==0 ) + { + return format_string(L"0%0.3o", get_umask() ); + } + else { + + var_entry_t *res; + env_node_t *env = top; + wchar_t *item; + wcstring result; + + while( env != 0 ) + { + res = (var_entry_t *) hash_get( &env->env, + key ); + if( res != 0 ) + { + if( wcscmp( res->val, ENV_NULL )==0) + { + return 0; + } + else + { + return res->val; + } + } + + if( env->new_scope ) + { + env = global_env; + } + else + { + env = env->next; + } + } + if( !proc_had_barrier) + { + proc_had_barrier=1; + env_universal_barrier(); + } + + item = env_universal_get( key ); + + if( !item || (wcscmp( item, ENV_NULL )==0)) + { + return 0; + } + else + { + return item; + } + } +} wchar_t *env_get( const wchar_t *key ) { + ASSERT_IS_MAIN_THREAD(); + + if (! pthread_main_np()) + { + fwprintf(stderr, L"env_get(%ls)\n", key); + } + var_entry_t *res; env_node_t *env = top; wchar_t *item; - + CHECK( key, 0 ); if( wcscmp( key, L"history" ) == 0 ) { wchar_t *current; - int i; + int i; int add_current=0; - sb_clear( &dyn_var ); - + sb_clear( &dyn_var ); + current = reader_get_buffer(); if( current && wcslen( current ) ) { add_current=1; sb_append( &dyn_var, current ); } - + for( i=add_current;; i++ ) { wchar_t *next = history_get( i-add_current ); @@ -1145,7 +1277,7 @@ wchar_t *env_get( const wchar_t *key ) { break; } - + if( i!=0) { sb_append( &dyn_var, ARRAY_SEP_STR ); @@ -1158,45 +1290,45 @@ wchar_t *env_get( const wchar_t *key ) } else if( wcscmp( key, L"COLUMNS" )==0 ) { - sb_clear( &dyn_var ); - sb_printf( &dyn_var, L"%d", common_get_width() ); - return (wchar_t *)dyn_var.buff; - } + sb_clear( &dyn_var ); + sb_printf( &dyn_var, L"%d", common_get_width() ); + return (wchar_t *)dyn_var.buff; + } else if( wcscmp( key, L"LINES" )==0 ) { - sb_clear( &dyn_var ); - sb_printf( &dyn_var, L"%d", common_get_height() ); + sb_clear( &dyn_var ); + sb_printf( &dyn_var, L"%d", common_get_height() ); return (wchar_t *)dyn_var.buff; } else if( wcscmp( key, L"status" )==0 ) { - sb_clear( &dyn_var ); - sb_printf( &dyn_var, L"%d", proc_get_last_status() ); - return (wchar_t *)dyn_var.buff; + sb_clear( &dyn_var ); + sb_printf( &dyn_var, L"%d", proc_get_last_status() ); + return (wchar_t *)dyn_var.buff; } else if( wcscmp( key, L"umask" )==0 ) { - sb_clear( &dyn_var ); - sb_printf( &dyn_var, L"0%0.3o", get_umask() ); - return (wchar_t *)dyn_var.buff; + sb_clear( &dyn_var ); + sb_printf( &dyn_var, L"0%0.3o", get_umask() ); + return (wchar_t *)dyn_var.buff; } - + while( env != 0 ) { - res = (var_entry_t *) hash_get( &env->env, + res = (var_entry_t *) hash_get( &env->env, key ); if( res != 0 ) { - if( wcscmp( res->val, ENV_NULL )==0) + if( wcscmp( res->val, ENV_NULL )==0) { return 0; } else { - return res->val; + return res->val; } } - + if( env->new_scope ) { env = global_env; @@ -1205,15 +1337,15 @@ wchar_t *env_get( const wchar_t *key ) { env = env->next; } - } + } if( !proc_had_barrier) { proc_had_barrier=1; env_universal_barrier(); } - + item = env_universal_get( key ); - + if( !item || (wcscmp( item, ENV_NULL )==0)) { return 0; @@ -1231,14 +1363,14 @@ int env_exist( const wchar_t *key, int mode ) 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) ) { - if( hash_get( &env_read_only, key ) || hash_get( &env_electric, key ) ) + if( is_read_only(key) || is_electric(key) ) { return 1; } @@ -1247,21 +1379,21 @@ int env_exist( const wchar_t *key, int mode ) if( ! (mode & ENV_UNIVERSAL) ) { env = (mode & ENV_GLOBAL)?global_env:top; - + while( env != 0 ) { - res = (var_entry_t *) hash_get( &env->env, + 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; @@ -1270,9 +1402,9 @@ int env_exist( const wchar_t *key, int mode ) { env = env->next; } - } + } } - + if( ! (mode & ENV_LOCAL) && ! (mode & ENV_GLOBAL) ) { if( !proc_had_barrier) @@ -1280,9 +1412,9 @@ int env_exist( const wchar_t *key, int mode ) proc_had_barrier=1; env_universal_barrier(); } - + item = env_universal_get( key ); - + } return item != 0; @@ -1293,31 +1425,31 @@ int env_exist( const wchar_t *key, int mode ) */ static int local_scope_exports( env_node_t *n ) { - + if( n==global_env ) return 0; - - if( n->export ) + + if( n->exportv ) return 1; - + if( n->new_scope ) return 0; - + return local_scope_exports( n->next ); } void env_push( int new_scope ) { - env_node_t *node = malloc( sizeof(env_node_t) ); + env_node_t *node = (env_node_t *)malloc( sizeof(env_node_t) ); node->next = top; - node->export=0; + node->exportv=0; hash_init( &node->env, &hash_wcs_func, &hash_wcs_cmp ); node->new_scope=new_scope; if( new_scope ) { has_changed |= local_scope_exports(top); } - top = node; + top = node; } @@ -1328,7 +1460,7 @@ void env_pop() { int i; int locale_changed = 0; - + env_node_t *killme = top; for( i=0; locale_variable[i]; i++ ) @@ -1342,9 +1474,9 @@ void env_pop() if( killme->new_scope ) { - has_changed |= killme->export || local_scope_exports( killme->next ); + has_changed |= killme->exportv || local_scope_exports( killme->next ); } - + top = top->next; hash_foreach( &killme->env, &clear_hash_entry ); hash_destroy( &killme->env ); @@ -1352,14 +1484,14 @@ void env_pop() if( locale_changed ) handle_locale(); - + } else { debug( 0, _( L"Tried to pop empty environment stack." ) ); sanity_lose(); - } + } } @@ -1367,13 +1499,13 @@ void env_pop() Function used with hash_foreach to insert keys of one table into another */ -static void add_key_to_hash( void *key, +static void add_key_to_hash( void *key, void *data, void *aux ) { var_entry_t *e = (var_entry_t *)data; - if( ( e->export && get_names_show_exported) || - ( !e->export && get_names_show_unexported) ) + if( ( e->exportv && get_names_show_exported) || + ( !e->exportv && get_names_show_unexported) ) { hash_put( (hash_table_t *)aux, key, 0 ); } @@ -1389,17 +1521,6 @@ static void add_to_hash( void *k, void *aux ) 0 ); } -/** - Add key to list -*/ -static void add_key_to_list( void * key, - void * val, - void *aux ) -{ - al_push( (array_list_t *)aux, key ); -} - - void env_get_names( array_list_t *l, int flags ) { int show_local = flags & ENV_LOCAL; @@ -1410,10 +1531,10 @@ void env_get_names( array_list_t *l, int flags ) env_node_t *n=top; CHECK( l, ); - - get_names_show_exported = + + get_names_show_exported = flags & ENV_EXPORT|| (!(flags & ENV_UNEXPORT)); - get_names_show_unexported = + get_names_show_unexported = flags & ENV_UNEXPORT|| (!(flags & ENV_EXPORT)); if( !show_local && !show_global && !show_universal ) @@ -1422,58 +1543,61 @@ void env_get_names( array_list_t *l, int flags ) } hash_init( &names, &hash_wcs_func, &hash_wcs_cmp ); - + if( show_local ) { while( n ) { if( n == global_env ) break; - - hash_foreach2( &n->env, + + hash_foreach2( &n->env, add_key_to_hash, &names ); if( n->new_scope ) - break; + break; else n = n->next; } } - + if( show_global ) { - hash_foreach2( &global_env->env, + hash_foreach2( &global_env->env, add_key_to_hash, &names ); - if( get_names_show_unexported ) - hash_foreach2( &env_electric, &add_key_to_list, l ); - + if( get_names_show_unexported ) { + for (std::set::iterator iter = env_electric.begin(); iter != env_electric.end(); iter++) { + al_push( l, iter->c_str() ); + } + } + if( get_names_show_exported ) { al_push( l, L"COLUMNS" ); al_push( l, L"LINES" ); } - + } - + if( show_universal ) { array_list_t uni_list; al_init( &uni_list ); - - env_universal_get_names( &uni_list, + + env_universal_get_names( &uni_list, get_names_show_exported, get_names_show_unexported ); al_foreach2( &uni_list, &add_to_hash, &names ); al_destroy( &uni_list ); } - + hash_get_keys( &names, l ); - hash_destroy( &names ); + hash_destroy( &names ); } /** @@ -1486,11 +1610,11 @@ static void export_func1( void *k, void *v, void *aux ) hash_remove( h, k, 0, 0 ); - if( val_entry->export && wcscmp( val_entry->val, ENV_NULL ) ) - { + if( val_entry->exportv && wcscmp( val_entry->val, ENV_NULL ) ) + { hash_put( h, k, val_entry->val ); } - + } /** @@ -1500,14 +1624,14 @@ static void get_exported( env_node_t *n, hash_table_t *h ) { if( !n ) return; - + if( n->new_scope ) get_exported( global_env, h ); else get_exported( n->next, h ); - hash_foreach2( &n->env, &export_func1, h ); -} + hash_foreach2( &n->env, &export_func1, h ); +} /** @@ -1517,10 +1641,10 @@ static void export_func2( void *k, void *v, void *aux ) { wchar_t *key = (wchar_t *)k; wchar_t *val = (wchar_t *)v; - + char *ks = wcs2str( key ); char *vs = wcs2str( val ); - + char *pos = vs; buffer_t *out = (buffer_t *)aux; @@ -1529,18 +1653,18 @@ static void export_func2( void *k, void *v, void *aux ) { DIE_MEM(); } - + /* Make arrays into colon-separated lists */ while( *pos ) { if( *pos == ARRAY_SEP ) - *pos = ':'; + *pos = ':'; pos++; } int nil = 0; - + b_append( out, ks, strlen(ks) ); b_append( out, "=", 1 ); b_append( out, vs, strlen(vs) ); @@ -1557,21 +1681,21 @@ char **env_export_arr( int recalc ) proc_had_barrier=1; env_universal_barrier(); } - + if( has_changed ) { array_list_t uni; hash_table_t vals; int prev_was_null=1; - int pos=0; + int pos=0; int i; debug( 4, L"env_export_arr() recalc" ); - + hash_init( &vals, &hash_wcs_func, &hash_wcs_cmp ); - + get_exported( top, &vals ); - + al_init( &uni ); env_universal_get_names( &uni, 1, 0 ); for( i=0; i::const_iterator iter = vars.find(key); + return (iter == vars.end() ? NULL : iter->second.c_str()); +} + +const wchar_t * const env_vars::highlighting_keys[] = {L"PATH", L"CDPATH", L"HIGHLIGHT_DELAY", NULL}; diff --git a/env.h b/env.h index 6f2a6b102..f7c57b534 100644 --- a/env.h +++ b/env.h @@ -6,8 +6,10 @@ #define FISH_ENV_H #include +#include #include "util.h" +#include "common.h" /** Flag for local (to the current block) variable @@ -63,7 +65,7 @@ void env_destroy(); /** - Set the value of the environment variable whose name matches key to val. + Set the value of the environment variable whose name matches key to val. Memory policy: All keys and values are copied, the parameters can and should be freed by the caller afterwards @@ -79,7 +81,7 @@ void env_destroy(); * ENV_INVALID, the variable name or mode was invalid */ -int env_set( const wchar_t *key, +int env_set( const wchar_t *key, const wchar_t *val, int mode ); @@ -93,6 +95,11 @@ int env_set( const wchar_t *key, */ wchar_t *env_get( const wchar_t *key ); +/** + Gets the variable with the specified name, or an empty string if it does not exist. + */ +wcstring env_get_string( const wchar_t *key ); + /** Returns 1 if the specified key exists. This can't be reliably done using env_get, since env_get returns null for 0-element arrays @@ -104,7 +111,7 @@ 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. The mode may also specify the scope of the variable that should be erased. @@ -138,5 +145,18 @@ void env_get_names( array_list_t *l, int flags ); */ int env_set_pwd(); +class env_vars { + std::map vars; + +public: + env_vars(const wchar_t * const * keys); + env_vars(void); + + const wchar_t *get(const wchar_t *key) const; + + // vars necessary for highlighting + static const wchar_t * const highlighting_keys[]; +}; + #endif diff --git a/env_universal.cpp b/env_universal.cpp index 410f79527..e3b95b304 100644 --- a/env_universal.cpp +++ b/env_universal.cpp @@ -83,27 +83,27 @@ static int get_socket( int fork_ok ) { int s, len; struct sockaddr_un local; - + char *name; wchar_t *wdir; - wchar_t *wuname; + wchar_t *wuname; char *dir =0, *uname=0; get_socket_count++; wdir = path; wuname = user; - - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { wperror(L"socket"); return -1; } - + if( wdir ) dir = wcs2str(wdir ); else dir = strdup("/tmp"); - + if( wuname ) uname = wcs2str(wuname ); else @@ -112,53 +112,53 @@ static int get_socket( int fork_ok ) pw = getpwuid( getuid() ); uname = strdup( pw->pw_name ); } - - name = malloc( strlen(dir) + - strlen(uname) + - strlen(SOCK_FILENAME) + + + name = (char *)malloc( strlen(dir) + + strlen(uname) + + strlen(SOCK_FILENAME) + 2 ); - + strcpy( name, dir ); strcat( name, "/" ); strcat( name, SOCK_FILENAME ); strcat( name, uname ); - + free( dir ); free( uname ); - + debug( 3, L"Connect to socket %s at fd %2", name, s ); - + local.sun_family = AF_UNIX; strcpy(local.sun_path, name ); free( name ); len = sizeof(local); - - if( connect( s, (struct sockaddr *)&local, len) == -1 ) + + if( connect( s, (struct sockaddr *)&local, len) == -1 ) { close( s ); if( fork_ok && start_fishd ) { debug( 2, L"Could not connect to socket %d, starting fishd", s ); - + start_fishd(); - + return get_socket( 0 ); } - + debug( 1, L"Could not connect to universal variable server, already tried manual restart (or no command supplied). You will not be able to share variable values between fish sessions. Is fish properly installed?" ); return -1; } - - if( (fcntl( s, F_SETFL, O_NONBLOCK ) != 0) || (fcntl( s, F_SETFD, FD_CLOEXEC ) != 0) ) + + if( (fcntl( s, F_SETFL, O_NONBLOCK ) != 0) || (fcntl( s, F_SETFD, FD_CLOEXEC ) != 0) ) { wperror( L"fcntl" ); - close( s ); - + close( s ); + return -1; } debug( 3, L"Connected to fd %d", s ); - + return s; } @@ -166,7 +166,7 @@ static int get_socket( int fork_ok ) Callback function used whenever a new fishd message is recieved */ static void callback( int type, const wchar_t *name, const wchar_t *val ) -{ +{ if( type == BARRIER_REPLY ) { barrier_reply = 1; @@ -174,8 +174,8 @@ static void callback( int type, const wchar_t *name, const wchar_t *val ) else { if( external_callback ) - external_callback( type, name, val ); - } + external_callback( type, name, val ); + } } /** @@ -186,21 +186,21 @@ static void check_connection() { if( !init ) return; - + if( env_universal_server.killme ) { debug( 3, L"Lost connection to universal variable server." ); - + if( close( env_universal_server.fd ) ) { wperror( L"close" ); } - + env_universal_server.fd = -1; env_universal_server.killme=0; - env_universal_server.input.used=0; + env_universal_server.input.used=0; env_universal_read_all(); - } + } } /** @@ -210,10 +210,10 @@ static void env_universal_remove_all() { array_list_t lst; int i; - + al_init( &lst ); - - env_universal_common_get_names( &lst, + + env_universal_common_get_names( &lst, 1, 1 ); @@ -224,7 +224,7 @@ static void env_universal_remove_all() } al_destroy( &lst ); - + } @@ -237,9 +237,9 @@ static void reconnect() { if( get_socket_count >= RECONNECT_COUNT ) return; - + debug( 3, L"Get new fishd connection" ); - + init = 0; env_universal_server.buffer_consumed = env_universal_server.buffer_used = 0; env_universal_server.fd = get_socket(1); @@ -252,22 +252,22 @@ static void reconnect() } -void env_universal_init( wchar_t * p, - wchar_t *u, +void env_universal_init( wchar_t * p, + wchar_t *u, void (*sf)(), void (*cb)( int type, const wchar_t *name, const wchar_t *val )) { path=p; user=u; - start_fishd=sf; + start_fishd=sf; external_callback = cb; connection_init( &env_universal_server, -1 ); - + env_universal_server.fd = get_socket(1); env_universal_common_init( &callback ); - env_universal_read_all(); - init = 1; + env_universal_read_all(); + init = 1; if( env_universal_server.fd >= 0 ) { env_universal_barrier(); @@ -285,7 +285,7 @@ void env_universal_destroy() { wperror( L"fcntl" ); } - try_send_all( &env_universal_server ); + try_send_all( &env_universal_server ); } connection_destroy( &env_universal_server ); @@ -305,22 +305,22 @@ int env_universal_read_all() if( env_universal_server.fd == -1 ) { - reconnect(); + reconnect(); if( env_universal_server.fd == -1 ) - return 0; + return 0; } - + if( env_universal_server.fd != -1 ) { read_message( &env_universal_server ); - check_connection(); + check_connection(); return 1; } else { debug( 2, L"No connection to universal variable server" ); return 0; - } + } } wchar_t *env_universal_get( const wchar_t *name ) @@ -329,7 +329,7 @@ wchar_t *env_universal_get( const wchar_t *name ) return 0; CHECK( name, 0 ); - + return env_universal_common_get( name ); } @@ -339,7 +339,7 @@ int env_universal_get_export( const wchar_t *name ) return 0; CHECK( name, 0 ); - + return env_universal_common_get_export( name ); } @@ -366,19 +366,19 @@ void env_universal_barrier() debug( 3, L"Create barrier" ); while( 1 ) { - try_send_all( &env_universal_server ); - check_connection(); - + try_send_all( &env_universal_server ); + check_connection(); + if( q_empty( &env_universal_server.unsent ) ) break; - + if( env_universal_server.fd == -1 ) { reconnect(); debug( 2, L"barrier interrupted, exiting" ); - return; + return; } - + FD_ZERO( &fds ); FD_SET( env_universal_server.fd, &fds ); select( env_universal_server.fd+1, 0, &fds, 0, 0 ); @@ -394,10 +394,10 @@ void env_universal_barrier() { reconnect(); debug( 2, L"barrier interrupted, exiting (2)" ); - return; - } + return; + } FD_ZERO( &fds ); - FD_SET( env_universal_server.fd, &fds ); + FD_SET( env_universal_server.fd, &fds ); select( env_universal_server.fd+1, &fds, 0, 0, 0 ); env_universal_read_all(); } @@ -405,25 +405,25 @@ void env_universal_barrier() } -void env_universal_set( const wchar_t *name, const wchar_t *value, int export ) +void env_universal_set( const wchar_t *name, const wchar_t *value, int exportv ) { message_t *msg; - + if( !init ) return; CHECK( name, ); - + debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value ); if( is_dead() ) { - env_universal_common_set( name, value, export ); + env_universal_common_set( name, value, exportv ); } else { - msg = create_message( export?SET_EXPORT:SET, - name, + msg = create_message( exportv?SET_EXPORT:SET, + name, value); if( !msg ) @@ -431,7 +431,7 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export ) debug( 1, L"Could not create universal variable message" ); return; } - + msg->count=1; q_put( &env_universal_server.unsent, msg ); env_universal_barrier(); @@ -441,18 +441,18 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export ) int env_universal_remove( const wchar_t *name ) { int res; - + message_t *msg; if( !init ) return 1; - + CHECK( name, 1 ); res = !env_universal_common_get( name ); debug( 3, L"env_universal_remove( \"%ls\" )", name ); - + if( is_dead() ) { env_universal_common_remove( name ); @@ -464,7 +464,7 @@ int env_universal_remove( const wchar_t *name ) q_put( &env_universal_server.unsent, msg ); env_universal_barrier(); } - + return res; } @@ -476,8 +476,8 @@ void env_universal_get_names( array_list_t *l, return; CHECK( l, ); - - env_universal_common_get_names( l, + + env_universal_common_get_names( l, show_exported, - show_unexported ); + show_unexported ); } diff --git a/env_universal.h b/env_universal.h index 25e8fc99f..1ed58fac7 100644 --- a/env_universal.h +++ b/env_universal.h @@ -17,7 +17,10 @@ extern connection_t env_universal_server; /** Initialize the envuni library */ -void env_universal_init(); +void env_universal_init( wchar_t * p, + wchar_t *u, + void (*sf)(), + void (*cb)( int type, const wchar_t *name, const wchar_t *val )); /** Free memory used by envuni */ @@ -37,10 +40,10 @@ int env_universal_get_export( const wchar_t *name ); /** Set the value of a universal variable */ -void env_universal_set( const wchar_t *name, const wchar_t *val, int export ); +void env_universal_set( const wchar_t *name, const wchar_t *val, int exportv ); /** Erase a universal variable - + \return zero if the variable existed, and non-zero if the variable did not exist */ int env_universal_remove( const wchar_t *name ); @@ -52,7 +55,7 @@ int env_universal_read_all(); /** Get the names of all universal variables - + \param l the list to insert the names into \param show_exported whether exported variables should be shown \param show_unexported whether unexported variables should be shown diff --git a/env_universal_common.cpp b/env_universal_common.cpp index 3cd58c0db..296baa5c7 100644 --- a/env_universal_common.cpp +++ b/env_universal_common.cpp @@ -92,7 +92,7 @@ */ typedef struct var_uni_entry { - int export; /**< Whether the variable should be exported */ + int exportv; /**< Whether the variable should be exported */ wchar_t val[1]; /**< The value of the variable */ } var_uni_entry_t; @@ -109,8 +109,8 @@ hash_table_t env_universal_var; /** Callback function, should be called on all events */ -void (*callback)( int type, - const wchar_t *key, +void (*callback)( int type, + const wchar_t *key, const wchar_t *val ); /** @@ -140,8 +140,8 @@ static char *iconv_utf8_names[]= */ static char *iconv_wide_names_unknown[]= { - "wchar_t", "WCHAR_T", - "wchar", "WCHAR", + "wchar_t", "WCHAR_T", + "wchar", "WCHAR", 0 } ; @@ -151,12 +151,12 @@ static char *iconv_wide_names_unknown[]= */ static char *iconv_wide_names_4[]= { - "wchar_t", "WCHAR_T", - "wchar", "WCHAR", - "ucs-4", "UCS-4", - "ucs4", "UCS4", - "utf-32", "UTF-32", - "utf32", "UTF32", + "wchar_t", "WCHAR_T", + "wchar", "WCHAR", + "ucs-4", "UCS-4", + "ucs4", "UCS4", + "utf-32", "UTF-32", + "utf32", "UTF32", 0 } ; @@ -166,12 +166,12 @@ static char *iconv_wide_names_4[]= */ static char *iconv_wide_names_2[]= { - "wchar_t", "WCHAR_T", - "wchar", "WCHAR", - "ucs-2", "UCS-2", - "ucs2", "UCS2", - "utf-16", "UTF-16", - "utf16", "UTF16", + "wchar_t", "WCHAR_T", + "wchar", "WCHAR", + "ucs-2", "UCS-2", + "ucs2", "UCS2", + "utf-16", "UTF-16", + "utf16", "UTF16", 0 } ; @@ -196,7 +196,7 @@ static wchar_t *utf2wcs( const char *in ) switch (sizeof (wchar_t)) { - + case 2: to_name = iconv_wide_names_2; break; @@ -204,15 +204,15 @@ static wchar_t *utf2wcs( const char *in ) case 4: to_name = iconv_wide_names_4; break; - + default: to_name = iconv_wide_names_unknown; break; } - + /* - The line protocol fish uses is always utf-8. + The line protocol fish uses is always utf-8. */ char **from_name = iconv_utf8_names; @@ -220,13 +220,13 @@ static wchar_t *utf2wcs( const char *in ) size_t out_len = sizeof( wchar_t )*(in_len+2); size_t nconv; char *nout; - - out = malloc( out_len ); + + out = (wchar_t *)malloc( out_len ); nout = (char *)out; if( !out ) return 0; - + for( i=0; to_name[i]; i++ ) { for( j=0; from_name[j]; j++ ) @@ -236,7 +236,7 @@ static wchar_t *utf2wcs( const char *in ) if( cd != (iconv_t) -1) { goto start_conversion; - + } } } @@ -246,23 +246,23 @@ static wchar_t *utf2wcs( const char *in ) if (cd == (iconv_t) -1) { /* Something went wrong. */ - debug( 0, L"Could not perform utf-8 conversion" ); + debug( 0, L"Could not perform utf-8 conversion" ); if(errno != EINVAL) wperror( L"iconv_open" ); - + /* Terminate the output string. */ free(out); - return 0; + return 0; } - + nconv = iconv( cd, (char **)&in, &in_len, &nout, &out_len ); - + if (nconv == (size_t) -1) { debug( 0, L"Error while converting from utf string" ); return 0; } - + *((wchar_t *) nout) = L'\0'; /* @@ -281,12 +281,12 @@ static wchar_t *utf2wcs( const char *in ) } free( out_old ); } - - + + if (iconv_close (cd) != 0) wperror (L"iconv_close"); - - return out; + + return out; } /** @@ -296,7 +296,7 @@ static char *wcs2utf( const wchar_t *in ) { iconv_t cd=(iconv_t) -1; int i,j; - + char *char_in = (char *)in; char *out; @@ -310,7 +310,7 @@ static char *wcs2utf( const wchar_t *in ) switch (sizeof (wchar_t)) { - + case 2: from_name = iconv_wide_names_2; break; @@ -318,7 +318,7 @@ static char *wcs2utf( const wchar_t *in ) case 4: from_name = iconv_wide_names_4; break; - + default: from_name = iconv_wide_names_unknown; break; @@ -330,24 +330,24 @@ static char *wcs2utf( const wchar_t *in ) size_t out_len = sizeof( char )*( (MAX_UTF8_BYTES*in_len)+1); size_t nconv; char *nout; - - out = malloc( out_len ); + + out = (char *)malloc( out_len ); nout = (char *)out; in_len *= sizeof( wchar_t ); if( !out ) return 0; - + for( i=0; to_name[i]; i++ ) { for( j=0; from_name[j]; j++ ) { cd = iconv_open ( to_name[i], from_name[j] ); - + if( cd != (iconv_t) -1) { goto start_conversion; - + } } } @@ -357,17 +357,17 @@ static char *wcs2utf( const wchar_t *in ) if (cd == (iconv_t) -1) { /* Something went wrong. */ - debug( 0, L"Could not perform utf-8 conversion" ); + debug( 0, L"Could not perform utf-8 conversion" ); if(errno != EINVAL) wperror( L"iconv_open" ); - + /* Terminate the output string. */ free(out); - return 0; + return 0; } - + nconv = iconv( cd, &char_in, &in_len, &nout, &out_len ); - + if (nconv == (size_t) -1) { @@ -375,13 +375,13 @@ static char *wcs2utf( const wchar_t *in ) debug( 0, L"Error while converting from to string" ); return 0; } - + *nout = '\0'; - + if (iconv_close (cd) != 0) wperror (L"iconv_close"); - - return out; + + return out; } @@ -421,9 +421,9 @@ static int read_byte( connection_t *src ) int res; res = read( src->fd, src->buffer, ENV_UNIVERSAL_BUFFER_SIZE ); - + // debug(4, L"Read chunk '%.*s'", res, src->buffer ); - + if( res < 0 ) { @@ -432,20 +432,20 @@ static int read_byte( connection_t *src ) { return ENV_UNIVERSAL_AGAIN; } - + return ENV_UNIVERSAL_ERROR; } - + if( res == 0 ) { return ENV_UNIVERSAL_EOF; } - + src->buffer_consumed = 0; src->buffer_used = res; } - + return src->buffer[src->buffer_consumed++]; } @@ -455,10 +455,10 @@ void read_message( connection_t *src ) { while( 1 ) { - + int ib = read_byte( src ); char b; - + switch( ib ) { case ENV_UNIVERSAL_AGAIN: @@ -483,43 +483,43 @@ void read_message( connection_t *src ) { char c = 0; b_append( &src->input, &c, 1 ); - debug( 1, - L"Universal variable connection closed while reading command. Partial command recieved: '%s'", + debug( 1, + L"Universal variable connection closed while reading command. Partial command recieved: '%s'", (wchar_t *)src->input.buff ); } return; } } - + b = (char)ib; - + if( b == '\n' ) { wchar_t *msg; - + b = 0; b_append( &src->input, &b, 1 ); - + msg = utf2wcs( src->input.buff ); - + /* Before calling parse_message, we must empty reset everything, since the callback function could potentially call read_message. */ src->input.used=0; - + if( msg ) { - parse_message( msg, src ); + parse_message( msg, src ); } else { debug( 0, _(L"Could not convert message '%s' to wide character string"), src->input.buff ); } - + free( msg ); - + } else { @@ -534,7 +534,7 @@ void read_message( connection_t *src ) void env_universal_common_remove( const wchar_t *name ) { void *k, *v; - hash_remove( &env_universal_var, + hash_remove( &env_universal_var, name, &k, &v ); @@ -553,34 +553,34 @@ static int match( const wchar_t *msg, const wchar_t *cmd ) if( msg[len] && msg[len]!= L' ' && msg[len] != L'\t' ) return 0; - + return 1; } -void env_universal_common_set( const wchar_t *key, const wchar_t *val, int export ) +void env_universal_common_set( const wchar_t *key, const wchar_t *val, int exportv ) { var_uni_entry_t *entry; wchar_t *name; CHECK( key, ); CHECK( val, ); - - entry = malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) ); + + entry = (var_uni_entry_t *)malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) ); name = wcsdup(key); - + if( !entry || !name ) DIE_MEM(); - - entry->export=export; - + + entry->exportv=exportv; + wcscpy( entry->val, val ); env_universal_common_remove( name ); - + hash_put( &env_universal_var, name, entry ); - + if( callback ) { - callback( export?SET_EXPORT:SET, name, val ); + callback( exportv?SET_EXPORT:SET, name, val ); } } @@ -588,67 +588,67 @@ void env_universal_common_set( const wchar_t *key, const wchar_t *val, int expor /** Parse message msg */ -static void parse_message( wchar_t *msg, +static void parse_message( wchar_t *msg, connection_t *src ) { // debug( 3, L"parse_message( %ls );", msg ); - + if( msg[0] == L'#' ) return; - + if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR )) { wchar_t *name, *tmp; - int export = match( msg, SET_EXPORT_STR ); - - name = msg+(export?wcslen(SET_EXPORT_STR):wcslen(SET_STR)); + int exportv = match( msg, SET_EXPORT_STR ); + + name = msg+(exportv?wcslen(SET_EXPORT_STR):wcslen(SET_STR)); while( wcschr( L"\t ", *name ) ) name++; - + tmp = wcschr( name, L':' ); if( tmp ) { wchar_t *key; wchar_t *val; - - key = malloc( sizeof( wchar_t)*(tmp-name+1)); + + key = (wchar_t *)malloc( sizeof( wchar_t)*(tmp-name+1)); memcpy( key, name, sizeof( wchar_t)*(tmp-name)); key[tmp-name]=0; - + val = tmp+1; val = unescape( val, 0 ); - - env_universal_common_set( key, val, export ); - + + env_universal_common_set( key, val, exportv ); + free( val ); free( key ); } else { debug( 1, PARSE_ERR, msg ); - } + } } else if( match( msg, ERASE_STR ) ) { wchar_t *name, *tmp; - + name = msg+wcslen(ERASE_STR); while( wcschr( L"\t ", *name ) ) name++; - + tmp = name; while( iswalnum( *tmp ) || *tmp == L'_') tmp++; - + *tmp = 0; - + if( !wcslen( name ) ) { debug( 1, PARSE_ERR, msg ); } env_universal_common_remove( name ); - + if( callback ) { callback( ERASE, name, 0 ); @@ -671,7 +671,7 @@ static void parse_message( wchar_t *msg, else { debug( 1, PARSE_ERR, msg ); - } + } } /** @@ -684,7 +684,7 @@ static int try_send( message_t *msg, { debug( 3, - L"before write of %d chars to fd %d", strlen(msg->body), fd ); + L"before write of %d chars to fd %d", strlen(msg->body), fd ); int res = write( fd, msg->body, strlen(msg->body) ); @@ -696,26 +696,26 @@ static int try_send( message_t *msg, { debug( 4, L"Failed to write message '%s'", msg->body ); } - + if( res == -1 ) { switch( errno ) { case EAGAIN: return 0; - + default: debug( 2, L"Error while sending universal variable message to fd %d. Closing connection", fd ); if( debug_level > 2 ) wperror( L"write" ); - + return -1; - } + } } msg->count--; - + if( !msg->count ) { free( msg ); @@ -726,7 +726,7 @@ static int try_send( message_t *msg, void try_send_all( connection_t *c ) { /* debug( 3, - L"Send all updates to connection on fd %d", + L"Send all updates to connection on fd %d", c->fd );*/ while( !q_empty( &c->unsent) ) { @@ -735,12 +735,12 @@ void try_send_all( connection_t *c ) case 1: q_get( &c->unsent); break; - + case 0: debug( 4, - L"Socket full, send rest later" ); + L"Socket full, send rest later" ); return; - + case -1: c->killme = 1; return; @@ -779,16 +779,16 @@ static wchar_t *full_escape( const wchar_t *in ) message_t *create_message( int type, - const wchar_t *key_in, + const wchar_t *key_in, const wchar_t *val_in ) { message_t *msg=0; - + char *key=0; size_t sz; // debug( 4, L"Crete message of type %d", type ); - + if( key_in ) { if( wcsvarname( key_in ) ) @@ -796,7 +796,7 @@ message_t *create_message( int type, debug( 0, L"Illegal variable name: '%ls'", key_in ); return 0; } - + key = wcs2utf(key_in); if( !key ) { @@ -806,8 +806,8 @@ message_t *create_message( int type, return 0; } } - - + + switch( type ) { case SET: @@ -817,40 +817,40 @@ message_t *create_message( int type, { val_in=L""; } - + wchar_t *esc = full_escape( val_in ); if( !esc ) break; - + char *val = wcs2utf(esc ); free(esc); - + sz = strlen(type==SET?SET_MBS:SET_EXPORT_MBS) + strlen(key) + strlen(val) + 4; - msg = malloc( sizeof( message_t ) + sz ); - + msg = (message_t *)malloc( sizeof( message_t ) + sz ); + if( !msg ) DIE_MEM(); - + strcpy( msg->body, (type==SET?SET_MBS:SET_EXPORT_MBS) ); strcat( msg->body, " " ); strcat( msg->body, key ); strcat( msg->body, ":" ); strcat( msg->body, val ); strcat( msg->body, "\n" ); - + free( val ); - + break; } case ERASE: { sz = strlen(ERASE_MBS) + strlen(key) + 3; - msg = malloc( sizeof( message_t ) + sz ); + msg = (message_t *)malloc( sizeof( message_t ) + sz ); if( !msg ) DIE_MEM(); - + strcpy( msg->body, ERASE_MBS " " ); strcat( msg->body, key ); strcat( msg->body, "\n" ); @@ -859,24 +859,24 @@ message_t *create_message( int type, case BARRIER: { - msg = malloc( sizeof( message_t ) + + msg = (message_t *)malloc( sizeof( message_t ) + strlen( BARRIER_MBS ) +2); if( !msg ) DIE_MEM(); strcpy( msg->body, BARRIER_MBS "\n" ); break; } - + case BARRIER_REPLY: { - msg = malloc( sizeof( message_t ) + + msg = (message_t *)malloc( sizeof( message_t ) + strlen( BARRIER_REPLY_MBS ) +2); if( !msg ) DIE_MEM(); strcpy( msg->body, BARRIER_REPLY_MBS "\n" ); break; } - + default: { debug( 0, L"create_message: Unknown message type" ); @@ -890,20 +890,20 @@ message_t *create_message( int type, // debug( 4, L"Message body is '%s'", msg->body ); - return msg; + return msg; } /** Function used with hash_foreach to insert keys of one table into another */ -static void add_key_to_hash( void *key, +static void add_key_to_hash( void *key, void *data, void *aux ) { var_uni_entry_t *e = (var_uni_entry_t *)data; - if( ( e->export && get_names_show_exported) || - ( !e->export && get_names_show_unexported) ) + if( ( e->exportv && get_names_show_exported) || + ( !e->exportv && get_names_show_unexported) ) al_push( (array_list_t *)aux, key ); } @@ -913,25 +913,25 @@ void env_universal_common_get_names( array_list_t *l, { get_names_show_exported = show_exported; get_names_show_unexported = show_unexported; - - hash_foreach2( &env_universal_var, + + hash_foreach2( &env_universal_var, add_key_to_hash, l ); } wchar_t *env_universal_common_get( const wchar_t *name ) { - var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name ); + var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name ); if( e ) return e->val; - return 0; + return 0; } int env_universal_common_get_export( const wchar_t *name ) { var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name ); if( e ) - return e->export; + return e->exportv; return 0; } @@ -952,17 +952,17 @@ static void enqueue( void *k, const wchar_t *key = (const wchar_t *)k; const var_uni_entry_t *val = (const var_uni_entry_t *)v; dyn_queue_t *queue = (dyn_queue_t *)q; - - message_t *msg = create_message( val->export?SET_EXPORT:SET, key, val->val ); + + message_t *msg = create_message( val->exportv?SET_EXPORT:SET, key, val->val ); msg->count=1; - + q_put( queue, msg ); } void enqueue_all( connection_t *c ) { hash_foreach2( &env_universal_var, - &enqueue, + &enqueue, (void *)&c->unsent ); try_send_all( c ); } @@ -974,7 +974,7 @@ void connection_init( connection_t *c, int fd ) c->fd = fd; b_init( &c->input ); q_init( &c->unsent ); - c->buffer_consumed = c->buffer_used = 0; + c->buffer_consumed = c->buffer_used = 0; } void connection_destroy( connection_t *c) diff --git a/env_universal_common.h b/env_universal_common.h index ed56b4156..f85b51fe8 100644 --- a/env_universal_common.h +++ b/env_universal_common.h @@ -76,9 +76,9 @@ typedef struct connection newline is encountered, the buffer is parsed and cleared. */ buffer_t input; - + /** - The read buffer. + The read buffer. */ char buffer[ENV_UNIVERSAL_BUFFER_SIZE]; @@ -86,12 +86,12 @@ typedef struct connection Number of bytes that have already been consumed. */ int buffer_consumed; - + /** - Number of bytes that have been read into the buffer. + Number of bytes that have been read into the buffer. */ int buffer_used; - + /** Link to the next connection @@ -103,7 +103,7 @@ typedef struct connection /** A struct representing a message to be sent between client and server */ -typedef struct +typedef struct { /** Number of queues that contain this message. Once this reaches zero, the message should be deleted @@ -160,10 +160,10 @@ void env_universal_common_get_names( array_list_t *l, Do not call this function. Create a message to do it. This function is only to be used when fishd is dead. */ -void env_universal_common_set( const wchar_t *key, const wchar_t *val, int export ); +void env_universal_common_set( const wchar_t *key, const wchar_t *val, int exportv ); /** - Remove the specified variable. + Remove the specified variable. This function operate agains the local copy of all universal variables, it does not communicate with any other process. diff --git a/event.cpp b/event.cpp index 6a53254f0..a3dffa15d 100644 --- a/event.cpp +++ b/event.cpp @@ -44,11 +44,11 @@ typedef struct /** Whether signals have been skipped */ - int overflow; + int overflow; /** Array of signal events */ - int signal[SIG_UNHANDLED_MAX]; + int signal[SIG_UNHANDLED_MAX]; } signal_list_t; @@ -84,52 +84,52 @@ static array_list_t *blocked; they must name the same function. */ -static int event_match( event_t *class, event_t *instance ) +static int event_match( event_t *classv, event_t *instance ) { - if( class->function_name && instance->function_name ) + if( classv->function_name && instance->function_name ) { - if( wcscmp( class->function_name, instance->function_name ) != 0 ) + if( wcscmp( classv->function_name, instance->function_name ) != 0 ) return 0; } - if( class->type == EVENT_ANY ) + if( classv->type == EVENT_ANY ) return 1; - - if( class->type != instance->type ) + + if( classv->type != instance->type ) return 0; + - - switch( class->type ) + switch( classv->type ) { - + case EVENT_SIGNAL: - if( class->param1.signal == EVENT_ANY_SIGNAL ) + if( classv->param1.signal == EVENT_ANY_SIGNAL ) return 1; - return class->param1.signal == instance->param1.signal; - + return classv->param1.signal == instance->param1.signal; + case EVENT_VARIABLE: return wcscmp( instance->param1.variable, - class->param1.variable )==0; - + classv->param1.variable )==0; + case EVENT_EXIT: - if( class->param1.pid == EVENT_ANY_PID ) + if( classv->param1.pid == EVENT_ANY_PID ) return 1; - return class->param1.pid == instance->param1.pid; + return classv->param1.pid == instance->param1.pid; case EVENT_JOB_ID: - return class->param1.job_id == instance->param1.job_id; + return classv->param1.job_id == instance->param1.job_id; case EVENT_GENERIC: return wcscmp( instance->param1.param, - class->param1.param )==0; + classv->param1.param )==0; } - + /** This should never be reached */ - return 0; + return 0; } @@ -139,11 +139,11 @@ static int event_match( event_t *class, event_t *instance ) */ static event_t *event_copy( event_t *event, int copy_arguments ) { - event_t *e = malloc( sizeof( event_t ) ); - + event_t *e = (event_t *)malloc( sizeof( event_t ) ); + if( !e ) DIE_MEM(); - + memcpy( e, event, sizeof(event_t)); if( e->function_name ) @@ -153,7 +153,7 @@ static event_t *event_copy( event_t *event, int copy_arguments ) e->param1.variable = wcsdup( e->param1.variable ); else if( e->type == EVENT_GENERIC ) e->param1.param = wcsdup( e->param1.param ); - + al_init( &e->arguments ); if( copy_arguments ) { @@ -162,9 +162,9 @@ static event_t *event_copy( event_t *event, int copy_arguments ) { al_push( &e->arguments, wcsdup( (wchar_t *)al_get( &event->arguments, i ) ) ); } - + } - + return e; } @@ -175,7 +175,7 @@ static int event_is_blocked( event_t *e ) { block_t *block; event_block_t *eb; - + for( block = current_block; block; block = block->outer ) { for( eb = block->first_event_block; eb; eb=eb->next ) @@ -193,9 +193,9 @@ static int event_is_blocked( event_t *e ) if( eb->type & (1<type) ) return 1; return 1; - + } - + return 0; } @@ -217,18 +217,18 @@ const wchar_t *event_get_desc( event_t *e ) { sb_clear( get_desc_buff ); } - + switch( e->type ) { - + case EVENT_SIGNAL: sb_printf( get_desc_buff, _(L"signal handler for %ls (%ls)"), sig2wcs(e->param1.signal ), signal_get_desc( e->param1.signal ) ); break; - + case EVENT_VARIABLE: sb_printf( get_desc_buff, _(L"handler for variable '%ls'"), e->param1.variable ); break; - + case EVENT_EXIT: if( e->param1.pid > 0 ) { @@ -242,9 +242,9 @@ const wchar_t *event_get_desc( event_t *e ) else sb_printf( get_desc_buff, _(L"exit handler for job with process group %d"), -e->param1.pid ); } - + break; - + case EVENT_JOB_ID: { job_t *j = job_get( e->param1.job_id ); @@ -255,17 +255,17 @@ const wchar_t *event_get_desc( event_t *e ) break; } - + case EVENT_GENERIC: sb_printf( get_desc_buff, _(L"handler for generic event '%ls'"), e->param1.param ); break; - + default: sb_printf( get_desc_buff, _(L"Unknown event type") ); break; - + } - + return (const wchar_t *)get_desc_buff->buff; } @@ -275,7 +275,7 @@ void event_add_handler( event_t *event ) event_t *e; CHECK( event, ); - + e = event_copy( event, 0 ); if( !events ) @@ -285,8 +285,8 @@ void event_add_handler( event_t *event ) { signal_handle( e->param1.signal, 1 ); } - - al_push( events, e ); + + al_push( events, e ); } void event_remove( event_t *criterion ) @@ -294,7 +294,7 @@ void event_remove( event_t *criterion ) int i; array_list_t *new_list=0; event_t e; - + CHECK( criterion, ); /* @@ -305,19 +305,19 @@ void event_remove( event_t *criterion ) that shouldn't be killed to new_list, and then drops the empty events-list. */ - + if( !events ) return; for( i=0; iparam1.signal; e.function_name = 0; - + if( event_get( &e, 0 ) == 1 ) { signal_handle( e.param1.signal, 0 ); - } + } } } else @@ -344,7 +344,7 @@ void event_remove( event_t *criterion ) } } al_destroy( events ); - free( events ); + free( events ); events = new_list; } @@ -352,21 +352,21 @@ int event_get( event_t *criterion, array_list_t *out ) { int i; int found = 0; - + if( !events ) - return 0; + return 0; CHECK( criterion, 0 ); - + for( i=0; ifunction_name ); - + for( j=0; jarguments); j++ ) { - wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 1 ); + wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 1 ); sb_append( b, L" " ); sb_append( b, arg_esc ); - free( arg_esc ); + free( arg_esc ); } // debug( 1, L"Event handler fires command '%ls'", (wchar_t *)b->buff ); - + /* Event handlers are not part of the main flow of code, so they are marked as non-interactive @@ -500,27 +500,27 @@ static void event_fire_internal( event_t *event ) current_block->param1.event = event; eval( (wchar_t *)b->buff, 0, TOP ); parser_pop_block(); - proc_pop_interactive(); + proc_pop_interactive(); proc_set_last_status( prev_status ); } if( b ) { sb_destroy( b ); - free( b ); + free( b ); } - + if( fire ) { al_destroy( fire ); free( fire ); } - + /* Free killed events */ - event_free_kills(); - + event_free_kills(); + } /** @@ -532,7 +532,7 @@ static void event_fire_delayed() int i; /* - If is_event is one, we are running the event-handler non-recursively. + If is_event is one, we are running the event-handler non-recursively. When the event handler has called a piece of code that triggers another event, we do not want to fire delayed events because of @@ -541,7 +541,7 @@ static void event_fire_delayed() if( blocked && is_event==1) { array_list_t *new_blocked = 0; - + for( i=0; i 0 ) { signal_list_t *lst; event_t e; - al_init( &e.arguments ); + al_init( &e.arguments ); /* Switch signal lists @@ -576,47 +576,47 @@ static void event_fire_delayed() active_list=1-active_list; /* - Set up + Set up */ e.type=EVENT_SIGNAL; e.function_name=0; - + lst = &sig_list[1-active_list]; - + if( lst->overflow ) { debug( 0, _( L"Signal list overflow. Signals have been ignored." ) ); } - + /* Send all signals in our private list */ for( i=0; icount; i++ ) { e.param1.signal = lst->signal[i]; - al_set( &e.arguments, 0, sig2wcs( e.param1.signal ) ); + al_set( &e.arguments, 0, sig2wcs( e.param1.signal ) ); if( event_is_blocked( &e ) ) { if( !blocked ) blocked = al_new(); - al_push( blocked, event_copy(&e, 1) ); + al_push( blocked, event_copy(&e, 1) ); } else { event_fire_internal( &e ); } } - + al_destroy( &e.arguments ); - - } + + } } void event_fire( event_t *event ) { is_event++; - + if( event && (event->type == EVENT_SIGNAL) ) { /* @@ -636,14 +636,14 @@ void event_fire( event_t *event ) Fire events triggered by signals */ event_fire_delayed(); - + if( event ) { if( event_is_blocked( event ) ) { if( !blocked ) blocked = al_new(); - + al_push( blocked, event_copy(event, 1) ); } else @@ -651,8 +651,8 @@ void event_fire( event_t *event ) event_fire_internal( event ); } } - - } + + } is_event--; } @@ -668,7 +668,7 @@ void event_destroy() { al_foreach( events, (void (*)(void *))&event_free ); al_destroy( events ); - free( events ); + free( events ); events=0; } @@ -676,9 +676,9 @@ void event_destroy() { al_foreach( killme, (void (*)(void *))&event_free ); al_destroy( killme ); - free( killme ); - killme=0; - } + free( killme ); + killme=0; + } } void event_free( event_t *e ) @@ -711,11 +711,11 @@ void event_fire_generic_internal(const wchar_t *name, ...) wchar_t *arg; CHECK( name, ); - + ev.type = EVENT_GENERIC; ev.param1.param = name; ev.function_name=0; - + al_init( &ev.arguments ); va_start( va, name ); while( (arg=va_arg(va, wchar_t *) )!= 0 ) @@ -723,9 +723,9 @@ void event_fire_generic_internal(const wchar_t *name, ...) al_push( &ev.arguments, arg ); } va_end( va ); - + event_fire( &ev ); } - + diff --git a/event.h b/event.h index 80a46dc12..6d0f91df9 100644 --- a/event.h +++ b/event.h @@ -7,7 +7,7 @@ functions produce output or perform memory allocations, since such functions may not be safely called by signal handlers. - + */ #ifndef FISH_EVENT_H #define FISH_EVENT_H @@ -44,7 +44,7 @@ enum - When used as a parameter to event_add, it represents a class of events, and function_name is the name of the function which will be called whenever an event matching the specified class occurs. This is also how events are stored internally. - When used as a parameter to event_get, event_remove and event_fire, it represents a class of events, and if the function_name field is non-zero, only events which call the specified function will be returned. */ -typedef struct +typedef struct { /** Type of event @@ -78,13 +78,13 @@ typedef struct The parameter describing this generic event */ const wchar_t *param; - + } param1; /** The name of the event handler function */ - const wchar_t *function_name; + const wchar_t *function_name; /** The argument list. Only used when sending a new event using @@ -96,28 +96,28 @@ typedef struct event_t; /** - Add an event handler + Add an event handler May not be called by a signal handler, since it may allocate new memory. */ void event_add_handler( event_t *event ); /** - Remove all events matching the specified criterion. + Remove all events matching the specified criterion. May not be called by a signal handler, since it may free allocated memory. */ void event_remove( event_t *event ); /** - Return all events which match the specified event class + Return all events which match the specified event class This function is safe to call from a signal handler _ONLY_ if the out parameter is null. \param criterion Is the class of events to return. If the criterion has a non-null function_name, only events which trigger the specified function will return. \param out the list to add events to. May be 0, in which case no events will be added, but the result count will still be valid - + \return the number of found matches */ int event_get( event_t *criterion, array_list_t *out ); @@ -164,7 +164,7 @@ const wchar_t *event_get_desc( event_t *e ); /** Fire a generic event with the specified name */ -#define event_fire_generic( ... ) event_fire_generic_internal( __VA_ARGS__, (void *)0 ) +#define event_fire_generic( ... ) event_fire_generic_internal( __VA_ARGS__, NULL ) void event_fire_generic_internal(const wchar_t *name,...); diff --git a/exec.cpp b/exec.cpp index 2f5f8e656..ab347a98e 100644 --- a/exec.cpp +++ b/exec.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef HAVE_SIGINFO_H #include @@ -99,7 +100,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors ); static void exec_write_and_exit( int fd, char *buff, size_t count, int status ) { - if( write_loop(fd, buff, count) == -1 ) + if( write_loop(fd, buff, count) == -1 ) { debug( 0, WRITE_ERROR); wperror( L"write" ); @@ -118,7 +119,7 @@ void exec_close( int fd ) debug( 0, L"Called close on invalid file descriptor " ); return; } - + while( close(fd) == -1 ) { if( errno != EINTR ) @@ -128,7 +129,7 @@ void exec_close( int fd ) break; } } - + if( open_fds ) { for( i=0; iio_mode == IO_BUFFER ) || + + if( ( io->io_mode == IO_BUFFER ) || ( io->io_mode == IO_PIPE ) ) { if( io->param1.pipe_fd[0] == fd || io->param1.pipe_fd[1] == fd ) return 1; } - + return use_fd_in_pipe( fd, io->next ); } @@ -201,14 +202,14 @@ static int use_fd_in_pipe( int fd, io_data_t *io ) Close all fds in open_fds, except for those that are mentioned in 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. */ static void close_unused_internal_pipes( io_data_t *io ) { int i=0; - + if( open_fds ) { for( ;iio_mode == IO_PIPE ) || ( io->io_mode == IO_BUFFER ) ) { int i; @@ -245,9 +246,9 @@ void free_fd( io_data_t *io, int fd ) { if( errno != EINTR ) { - debug( 1, + debug( 1, FD_ERROR, - fd ); + fd ); wperror( L"dup" ); FATAL_EXIT(); } @@ -292,11 +293,11 @@ static int handle_child_io( io_data_t *io ) if( io->fd > 2 ) { /* - Make sure the fd used by this redirection is not used by e.g. a pipe. + Make sure the fd used by this redirection is not used by e.g. a pipe. */ free_fd( io, io->fd ); } - + switch( io->io_mode ) { case IO_CLOSE: @@ -317,19 +318,19 @@ static int handle_child_io( io_data_t *io ) if( ( io->param2.flags & O_EXCL ) && ( errno ==EEXIST ) ) { - debug( 1, + debug( 1, NOCLOB_ERROR, io->param1.filename ); } else { - debug( 1, + debug( 1, FILE_ERROR, io->param1.filename ); - + wperror( L"open" ); } - + return -1; } else if( tmp != io->fd) @@ -339,20 +340,20 @@ static int handle_child_io( io_data_t *io ) this is just a precausion. */ close(io->fd); - + if(dup2( tmp, io->fd ) == -1 ) { - debug( 1, + debug( 1, FD_ERROR, io->fd ); wperror( L"dup2" ); return -1; } exec_close( tmp ); - } + } break; } - + case IO_FD: { /* @@ -363,7 +364,7 @@ static int handle_child_io( io_data_t *io ) if( dup2( io->param1.old_fd, io->fd ) == -1 ) { - debug( 1, + debug( 1, FD_ERROR, io->fd ); wperror( L"dup2" ); @@ -371,17 +372,17 @@ static int handle_child_io( io_data_t *io ) } break; } - + case IO_BUFFER: case IO_PIPE: { int write_pipe; - + write_pipe = !io->is_input; /* debug( 0, - L"%ls %ls on fd %d (%d %d)", - write_pipe?L"write":L"read", + L"%ls %ls on fd %d (%d %d)", + write_pipe?L"write":L"read", (io->io_mode == IO_BUFFER)?L"buffer":L"pipe", io->fd, io->param1.pipe_fd[0], @@ -394,7 +395,7 @@ static int handle_child_io( io_data_t *io ) return -1; } - if( write_pipe ) + if( write_pipe ) { exec_close( io->param1.pipe_fd[0]); exec_close( io->param1.pipe_fd[1]); @@ -405,12 +406,12 @@ static int handle_child_io( io_data_t *io ) } break; } - + } } return 0; - + } /** @@ -432,13 +433,13 @@ static int handle_child_io( io_data_t *io ) static int setup_child_process( job_t *j, process_t *p ) { int res=0; - + if( p ) { res = set_child_group( j, p, 1 ); } - - if( !res ) + + if( !res ) { res = handle_child_io( j->io ); if( p != 0 && res ) @@ -446,18 +447,18 @@ static int setup_child_process( job_t *j, process_t *p ) exit( 1 ); } } - + /* Set the handling for job control signals back to the default. */ if( !res ) { signal_reset_handlers(); } - + /* Remove all signal blocks */ - signal_unblock(); - + signal_unblock(); + return res; - + } /** @@ -484,9 +485,9 @@ static wchar_t *get_interpreter( wchar_t *file ) sb_append_char( &sb, (wchar_t)ch ); } } - + res = (wchar_t *)sb.buff; - + if( !wcsncmp( L"#! /", res, 4 ) ) return res+3; if( !wcsncmp( L"#!/", res, 3 ) ) @@ -494,7 +495,7 @@ static wchar_t *get_interpreter( wchar_t *file ) return 0; } - + /** This function is executed by the child process created by a call to fork(). It should be called after \c setup_child_process. It calls @@ -505,19 +506,19 @@ static void launch_process( process_t *p ) { FILE* f; int err; - + // debug( 1, L"exec '%ls'", p->argv[0] ); char **argv = wcsv2strv( (const wchar_t **) p->argv); char **envv = env_export_arr( 0 ); - - execve ( wcs2str(p->actual_cmd), + + execve ( wcs2str(p->actual_cmd), argv, envv ); - + err = errno; - - /* + + /* Something went wrong with execve, check for a ":", and run /bin/sh if encountered. This is a weird predecessor to the shebang that is still sometimes used since it is supported on Windows. @@ -527,49 +528,49 @@ static void launch_process( process_t *p ) { char begin[1] = {0}; size_t read; - + read = fread(begin, 1, 1, f); fclose( f ); - + if( (read==1) && (begin[0] == ':') ) { int count = 0; int i = 1; wchar_t **res; char **res_real; - + while( p->argv[count] != 0 ) count++; - - res = malloc( sizeof(wchar_t*)*(count+2)); - + + res = (wchar_t **)malloc( sizeof(wchar_t*)*(count+2)); + res[0] = L"/bin/sh"; res[1] = p->actual_cmd; - + for( i=1; p->argv[i]; i++ ){ res[i+1] = p->argv[i]; } - + res[i+1] = 0; p->argv = res; p->actual_cmd = L"/bin/sh"; res_real = wcsv2strv( (const wchar_t **) res); - - execve ( wcs2str(p->actual_cmd), + + execve ( wcs2str(p->actual_cmd), res_real, envv ); } } - + errno = err; - debug( 0, + debug( 0, _( L"Failed to execute process '%ls'. Reason:" ), p->actual_cmd ); - + switch( errno ) { - + case E2BIG: { size_t sz = 0; @@ -577,31 +578,31 @@ static void launch_process( process_t *p ) string_buffer_t sz1; string_buffer_t sz2; - + long arg_max = -1; - + sb_init( &sz1 ); sb_init( &sz2 ); - + for(p=argv; *p; p++) { sz += strlen(*p)+1; } - + for(p=envv; *p; p++) { sz += strlen(*p)+1; } - + sb_format_size( &sz1, sz ); arg_max = sysconf( _SC_ARG_MAX ); - + if( arg_max > 0 ) { - + sb_format_size( &sz2, arg_max ); - + debug( 0, L"The total size of the argument and environment lists (%ls) exceeds the operating system limit of %ls.", (wchar_t *)sz1.buff, @@ -613,21 +614,21 @@ static void launch_process( process_t *p ) L"The total size of the argument and environment lists (%ls) exceeds the operating system limit.", (wchar_t *)sz1.buff); } - - debug( 0, + + debug( 0, L"Try running the command again with fewer arguments."); sb_destroy( &sz1 ); sb_destroy( &sz2 ); - + exit(STATUS_EXEC_FAIL); - + break; } case ENOEXEC: { wperror(L"exec"); - + debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd); exit(STATUS_EXEC_FAIL); } @@ -635,7 +636,7 @@ static void launch_process( process_t *p ) case ENOENT: { wchar_t *interpreter = get_interpreter( p->actual_cmd ); - + if( interpreter && waccess( interpreter, X_OK ) ) { debug(0, L"The file '%ls' specified the interpreter '%ls', which is not an executable command.", p->actual_cmd, interpreter ); @@ -644,7 +645,7 @@ static void launch_process( process_t *p ) { debug(0, L"The file '%ls' or a script or ELF interpreter does not exist, or a shared library needed for file or interpreter cannot be found.", p->actual_cmd); } - + exit(STATUS_EXEC_FAIL); } @@ -657,12 +658,12 @@ static void launch_process( process_t *p ) default: { wperror(L"exec"); - + // debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd); exit(STATUS_EXEC_FAIL); } } - + } @@ -691,7 +692,7 @@ static void io_untransmogrify( io_data_t * in, io_data_t *out ) case IO_FILE: exec_close( out->param1.old_fd ); break; - } + } free(out); } @@ -711,16 +712,16 @@ static io_data_t *io_transmogrify( io_data_t * in ) if( !in ) return 0; - - out = malloc( sizeof( io_data_t ) ); + + out = (io_data_t *)malloc( sizeof( io_data_t ) ); if( !out ) DIE_MEM(); - + out->fd = in->fd; out->io_mode = IO_FD; out->param2.close_old = 1; out->next=0; - + switch( in->io_mode ) { /* @@ -741,23 +742,23 @@ static io_data_t *io_transmogrify( io_data_t * in ) case IO_FILE: { int fd; - + if( (fd=wopen( in->param1.filename, in->param2.flags, OPEN_MASK ) )==-1 ) { - debug( 1, + debug( 1, FILE_ERROR, in->param1.filename ); - + wperror( L"open" ); free( out ); return 0; - } + } out->param1.old_fd = fd; break; } } - + if( in->next) { out->next = io_transmogrify( in->next ); @@ -767,7 +768,7 @@ static io_data_t *io_transmogrify( io_data_t * in ) return 0; } } - + return out; } @@ -780,14 +781,14 @@ static io_data_t *io_transmogrify( io_data_t * in ) \param io the io redirections to be performed on this block */ -static void internal_exec_helper( const wchar_t *def, +static void internal_exec_helper( const wchar_t *def, int block_type, io_data_t *io ) { 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 */ @@ -796,13 +797,13 @@ static void internal_exec_helper( const wchar_t *def, proc_set_last_status( STATUS_EXEC_FAIL ); return; } - + signal_unblock(); - - eval( def, io_internal, block_type ); - + + eval( def, io_internal, block_type ); + signal_block(); - + io_untransmogrify( io, io_internal ); job_reap( 0 ); is_block=is_block_old; @@ -818,24 +819,24 @@ static void internal_exec_helper( const wchar_t *def, exit. The parent process may safely ignore the exit status of this call. - Returns 0 on sucess, -1 on failiure. + Returns 0 on sucess, -1 on failiure. */ static int set_child_group( job_t *j, process_t *p, int print_errors ) { int res = 0; - + if( job_get_flag( j, JOB_CONTROL ) ) { if (!j->pgid) { j->pgid = p->pid; } - + if( setpgid (p->pid, j->pgid) ) { if( getpgid( p->pid) != j->pgid && print_errors ) { - debug( 1, + debug( 1, _( L"Could not send process %d, '%ls' in job %d, '%ls' from group %d to group %d" ), p->pid, p->argv[0], @@ -858,8 +859,8 @@ static int set_child_group( job_t *j, process_t *p, int print_errors ) { if( tcsetpgrp (0, j->pgid) && print_errors ) { - debug( 1, _( L"Could not send job %d ('%ls') to foreground" ), - j->job_id, + debug( 1, _( L"Could not send job %d ('%ls') to foreground" ), + j->job_id, j->command ); wperror( L"tcsetpgrp" ); res = -1; @@ -880,7 +881,7 @@ static pid_t exec_fork() pid_t pid; struct timespec pollint; int i; - + for( i=0; icommand, j->job_id ); - + + debug( 4, L"Exec job '%ls' with id %d", j->command, j->job_id ); + if( block_io ) { if( j->io ) @@ -985,23 +986,23 @@ void exec( job_t *j ) } else { - j->io=io_duplicate( j, block_io); + j->io=io_duplicate( j, block_io); } } - + io_data_t *input_redirect; for( input_redirect = j->io; input_redirect; input_redirect = input_redirect->next ) { - if( (input_redirect->io_mode == IO_BUFFER) && + if( (input_redirect->io_mode == IO_BUFFER) && input_redirect->is_input ) { /* Input redirection - create a new gobetween process to take care of buffering */ - process_t *fake = halloc( j, sizeof(process_t) ); + process_t *fake = (process_t *)halloc( j, sizeof(process_t) ); fake->type = INTERNAL_BUFFER; fake->pipe_write_fd = 1; j->first_process->pipe_read_fd = input_redirect->fd; @@ -1010,7 +1011,7 @@ void exec( job_t *j ) break; } } - + if( j->first_process->type==INTERNAL_EXEC ) { /* @@ -1036,7 +1037,7 @@ void exec( job_t *j ) return; } - } + } pipe_read.fd=0; pipe_write.fd=1; @@ -1050,9 +1051,9 @@ void exec( job_t *j ) pipe_read.next=0; pipe_write.next=0; pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=-1; - + j->io = io_add( j->io, &pipe_write ); - + signal_block(); /* @@ -1064,7 +1065,7 @@ void exec( job_t *j ) continuing in the pipeline, causing the group leader to exit. */ - + if( job_get_flag( j, JOB_CONTROL ) ) { for( p=j->first_process; p; p = p->next ) @@ -1081,12 +1082,12 @@ void exec( job_t *j ) needs_keepalive = 1; break; } - + } - + } } - + if( needs_keepalive ) { keepalive.pid = exec_fork(); @@ -1095,15 +1096,15 @@ void exec( job_t *j ) { keepalive.pid = getpid(); set_child_group( j, &keepalive, 1 ); - pause(); + pause(); exit(0); } else { - set_child_group( j, &keepalive, 0 ); + set_child_group( j, &keepalive, 0 ); } } - + /* This loop loops over every process_t in the job, starting it as appropriate. This turns out to be rather complex, since a @@ -1116,13 +1117,13 @@ void exec( job_t *j ) { mypipe[1]=-1; skip_fork=0; - + pipe_write.fd = p->pipe_write_fd; pipe_read.fd = p->pipe_read_fd; // debug( 0, L"Pipe created from fd %d to fd %d", pipe_write.fd, pipe_read.fd ); + - - /* + /* This call is used so the global environment variable array is regenerated, if needed, before the fork. That way, we avoid a lot of duplicate work where EVERY child would need @@ -1133,21 +1134,21 @@ void exec( job_t *j ) */ if( p->type == EXTERNAL ) env_export_arr( 1 ); - - + + /* - Set up fd:s that will be used in the pipe + Set up fd:s that will be used in the pipe */ - + if( p == j->first_process->next ) { j->io = io_add( j->io, &pipe_read ); } - + if( p->next ) { // debug( 1, L"%ls|%ls" , p->argv[0], p->next->argv[0]); - + if( exec_pipe( mypipe ) == -1 ) { debug( 1, PIPE_ERROR ); @@ -1165,7 +1166,7 @@ void exec( job_t *j ) Remove the io redirection for pipe output. */ j->io = io_remove( j->io, &pipe_write ); - + } switch( p->type ) @@ -1176,7 +1177,7 @@ void exec( job_t *j ) wchar_t * def=0; array_list_t *named_arguments; int shadows; - + /* Calls to function_get_definition might need to @@ -1190,10 +1191,10 @@ void exec( job_t *j ) shadows = function_get_shadows( p->argv[0] ); signal_block(); - + if( orig_def ) { - def = halloc_register( j, wcsdup(orig_def) ); + def = (wchar_t *)halloc_register( j, wcsdup(orig_def) ); } if( def == 0 ) { @@ -1202,10 +1203,10 @@ void exec( job_t *j ) } parser_push_block( shadows?FUNCTION_CALL:FUNCTION_CALL_NO_SHADOW ); - + current_block->param2.function_call_process = p; - current_block->param1.function_call_name = halloc_register( current_block, wcsdup( p->argv[0] ) ); - + current_block->param1.function_call_name = (wchar_t *)halloc_register( current_block, wcsdup( p->argv[0] ) ); + /* set_argv might trigger an event @@ -1215,34 +1216,34 @@ void exec( job_t *j ) signal_unblock(); parse_util_set_argv( p->argv+1, named_arguments ); signal_block(); - + parser_forbid_function( p->argv[0] ); if( p->next ) { - io_buffer = io_buffer_create( 0 ); + io_buffer = io_buffer_create( 0 ); j->io = io_add( j->io, io_buffer ); } - + internal_exec_helper( def, TOP, j->io ); - + parser_allow_function(); parser_pop_block(); - - break; + + break; } - + case INTERNAL_BLOCK: { if( p->next ) { - io_buffer = io_buffer_create( 0 ); + io_buffer = io_buffer_create( 0 ); j->io = io_add( j->io, io_buffer ); } - - internal_exec_helper( p->argv[0], TOP, j->io ); + + internal_exec_helper( p->argv[0], TOP, j->io ); break; - + } case INTERNAL_BUILTIN: @@ -1259,12 +1260,12 @@ 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 ) { - + case IO_FD: { builtin_stdin = in->param1.old_fd; @@ -1275,14 +1276,14 @@ void exec( job_t *j ) builtin_stdin = in->param1.pipe_fd[0]; break; } - + case IO_FILE: { builtin_stdin=wopen( in->param1.filename, in->param2.flags, OPEN_MASK ); if( builtin_stdin == -1 ) { - debug( 1, + debug( 1, FILE_ERROR, in->param1.filename ); wperror( L"open" ); @@ -1291,10 +1292,10 @@ void exec( job_t *j ) { close_stdin = 1; } - + break; } - + case IO_CLOSE: { /* @@ -1317,19 +1318,19 @@ void exec( job_t *j ) handled? */ builtin_stdin = -1; - + break; } - + default: { builtin_stdin=-1; - debug( 1, + debug( 1, _( L"Unknown input redirection type %d" ), in->io_mode); break; } - + } } } @@ -1348,7 +1349,7 @@ void exec( job_t *j ) int old_out = builtin_out_redirect; int old_err = builtin_err_redirect; - /* + /* 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 @@ -1362,24 +1363,24 @@ void exec( job_t *j ) walking the job list, but it seems more robust to make exec handle things. */ - + builtin_push_io( builtin_stdin ); - + builtin_out_redirect = has_fd( j->io, 1 ); - builtin_err_redirect = has_fd( j->io, 2 ); + builtin_err_redirect = has_fd( j->io, 2 ); fg = job_get_flag( j, JOB_FOREGROUND ); job_set_flag( j, JOB_FOREGROUND, 0 ); - + signal_unblock(); - + p->status = builtin_run( p->argv, j->io ); - + builtin_out_redirect=old_out; builtin_err_redirect=old_err; - + signal_block(); - + /* Restore the fg flag, which is temporarily set to false during builtin execution so as not to confuse @@ -1387,7 +1388,7 @@ void exec( job_t *j ) */ job_set_flag( j, JOB_FOREGROUND, fg ); } - + /* If stdin has been redirected, close the redirection stream. @@ -1395,16 +1396,16 @@ void exec( job_t *j ) if( close_stdin ) { exec_close( builtin_stdin ); - } - break; + } + break; } } - + if( exec_error ) { break; } - + switch( p->type ) { @@ -1412,7 +1413,7 @@ void exec( job_t *j ) case INTERNAL_FUNCTION: { int status = proc_get_last_status(); - + /* Handle output from a block or function. This usually means do nothing, but in the case of pipes, we have @@ -1434,39 +1435,39 @@ void exec( job_t *j ) } j->io = io_remove( j->io, io_buffer ); - + io_buffer_read( io_buffer ); - + if( io_buffer->param2.out_buffer->used != 0 ) { pid = exec_fork(); if( pid == 0 ) { - + /* This is the child process. Write out the contents of the pipeline. */ p->pid = getpid(); setup_child_process( j, p ); - exec_write_and_exit(io_buffer->fd, + exec_write_and_exit(io_buffer->fd, io_buffer->param2.out_buffer->buff, io_buffer->param2.out_buffer->used, status); } else { - /* + /* This is the parent process. Store away information on the child, and possibly give it control over the terminal. */ - p->pid = pid; + p->pid = pid; set_child_group( j, p, 0 ); - - } - + + } + } else { @@ -1476,20 +1477,20 @@ void exec( job_t *j ) } p->completed = 1; } - + io_buffer_destroy( io_buffer ); - + io_buffer=0; break; - + } case INTERNAL_BUFFER: { - + pid = exec_fork(); - + if( pid == 0 ) { /* @@ -1498,30 +1499,30 @@ void exec( job_t *j ) */ p->pid = getpid(); setup_child_process( j, p ); - + exec_write_and_exit( 1, - input_redirect->param2.out_buffer->buff, + input_redirect->param2.out_buffer->buff, input_redirect->param2.out_buffer->used, 0); } else { - /* + /* This is the parent process. Store away information on the child, and possibly give it control over the terminal. */ - p->pid = pid; - set_child_group( j, p, 0 ); - } + p->pid = pid; + set_child_group( j, p, 0 ); + } - break; + break; } - + case INTERNAL_BUILTIN: { int skip_fork; - + /* Handle output from builtin commands. In the general case, this means forking of a worker process, that @@ -1539,7 +1540,7 @@ void exec( job_t *j ) ( !sb_out->used ) && ( !sb_err->used ) && ( !p->next ); - + /* If the output of a builtin is to be sent to an internal buffer, there is no need to fork. This helps out the @@ -1548,10 +1549,10 @@ void exec( job_t *j ) io_data_t *io = io_get( j->io, 1 ); int buffer_stdout = io && io->io_mode == IO_BUFFER; - - if( ( !sb_err->used ) && + + if( ( !sb_err->used ) && ( !p->next ) && - ( sb_out->used ) && + ( sb_out->used ) && ( buffer_stdout ) ) { char *res = wcs2str( (wchar_t *)sb_out->buff ); @@ -1567,14 +1568,14 @@ void exec( job_t *j ) skip_fork = 0; } } - + if( skip_fork ) { p->completed=1; if( p->next == 0 ) { debug( 3, L"Set status of %ls to %d using short circut", j->command, p->status ); - + int status = p->status; proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status ); } @@ -1584,7 +1585,7 @@ void exec( job_t *j ) /* Ok, unfortunatly, we have to do a real fork. Bummer. */ - + pid = exec_fork(); if( pid == 0 ) { @@ -1597,45 +1598,45 @@ void exec( job_t *j ) p->pid = getpid(); setup_child_process( j, p ); do_builtin_io( sb_out->used ? (wchar_t *)sb_out->buff : 0, sb_err->used ? (wchar_t *)sb_err->buff : 0 ); - + exit( p->status ); - + } else { - /* + /* This is the parent process. Store away information on the child, and possibly give it control over the terminal. */ p->pid = pid; - + set_child_group( j, p, 0 ); - - } - + + } + break; } - + case EXTERNAL: { pid = exec_fork(); if( pid == 0 ) { /* - This is the child process. + This is the child process. */ p->pid = getpid(); setup_child_process( j, p ); launch_process( p ); - + /* launch_process _never_ returns... */ } else { - /* + /* This is the parent process. Store away information on the child, and possibly fice it control over the terminal. @@ -1643,30 +1644,30 @@ void exec( job_t *j ) p->pid = pid; set_child_group( j, p, 0 ); - + } break; } - + } if( p->type == INTERNAL_BUILTIN ) builtin_pop_io(); - - /* + + /* Close the pipe the current process uses to read from the previous process_t */ if( pipe_read.param1.pipe_fd[0] >= 0 ) exec_close( pipe_read.param1.pipe_fd[0] ); - /* + /* Set up the pipe the next process uses to read from the current process_t */ if( p->next ) pipe_read.param1.pipe_fd[0] = mypipe[0]; - - /* + + /* 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 @@ -1676,7 +1677,7 @@ void exec( job_t *j ) if( p->next ) { exec_close(mypipe[1]); - } + } } /* @@ -1687,8 +1688,8 @@ void exec( job_t *j ) { kill( keepalive.pid, SIGKILL ); } - - signal_unblock(); + + signal_unblock(); debug( 3, L"Job is constructed" ); @@ -1696,7 +1697,7 @@ void exec( job_t *j ) for( tmp = block_io; tmp; tmp=tmp->next ) j->io = io_remove( j->io, tmp ); - + job_set_flag( j, JOB_CONSTRUCTED, 1 ); if( !job_get_flag( j, JOB_FOREGROUND ) ) @@ -1708,10 +1709,25 @@ void exec( job_t *j ) { job_continue (j, 0); } - + } -int exec_subshell( const wchar_t *cmd, +int exec_subshell2( const wcstring &cmd, std::vector &outputs ) +{ + array_list_t lst; + al_init(&lst); + int result = exec_subshell(cmd.c_str(), &lst); + int i, max = al_get_count(&lst); + for (i=0; i < max; i++) { + wchar_t *tmp = (wchar_t *)al_get(&lst, i); + outputs.push_back(tmp); + free(tmp); + } + al_destroy(&lst); + return result; +} + +int exec_subshell( const wchar_t *cmd, array_list_t *lst ) { char *begin, *end; @@ -1721,7 +1737,7 @@ int exec_subshell( const wchar_t *cmd, io_data_t *io_buffer; const wchar_t *ifs; char sep=0; - + CHECK( cmd, -1 ); ifs = env_get(L"IFS"); @@ -1737,14 +1753,14 @@ int exec_subshell( const wchar_t *cmd, sep = 0; debug( 0, L"Warning - invalid command substitution separator '%lc'. Please change the firsta character of IFS", ifs[0] ); } - + } - - is_subshell=1; + + is_subshell=1; io_buffer= io_buffer_create( 0 ); - + prev_status = proc_get_last_status(); - + if( eval( cmd, io_buffer, SUBST ) ) { status = -1; @@ -1753,16 +1769,16 @@ int exec_subshell( const wchar_t *cmd, { status = proc_get_last_status(); } - + io_buffer_read( io_buffer ); - + proc_set_last_status( prev_status ); - + is_subshell = prev_subshell; - + b_append( io_buffer->param2.out_buffer, &z, 1 ); - - begin=end=io_buffer->param2.out_buffer->buff; + + begin=end=io_buffer->param2.out_buffer->buff; if( lst ) { @@ -1781,9 +1797,9 @@ int exec_subshell( const wchar_t *cmd, { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); } - } + } io_buffer_destroy( io_buffer ); - + return status; } else if( *end == sep ) @@ -1804,8 +1820,8 @@ int exec_subshell( const wchar_t *cmd, end++; } } - + io_buffer_destroy( io_buffer ); - return status; + return status; } diff --git a/exec.h b/exec.h index ac051da31..00f7bac95 100644 --- a/exec.h +++ b/exec.h @@ -9,9 +9,11 @@ #define FISH_EXEC_H #include +#include #include "proc.h" #include "util.h" +#include "common.h" /** pipe redirection error message @@ -19,7 +21,7 @@ #define PIPE_ERROR _(L"An error occurred while setting up pipe") /** - Execute the processes specified by j. + Execute the processes specified by j. I've put a fair bit of work into making builtins behave like other programs as far as pipes are concerned. Unlike i.e. bash, builtins @@ -51,9 +53,11 @@ void exec( job_t *j ); \return the status of the last job to exit, or -1 if en error was encountered. */ -__warn_unused int exec_subshell( const wchar_t *cmd, +__warn_unused int exec_subshell( const wchar_t *cmd, array_list_t *l ); +__warn_unused int exec_subshell2( const wcstring &cmd, std::vector &outputs ); + /** Loops over close until thesyscall was run without beeing diff --git a/expand.cpp b/expand.cpp index e871691bf..11bc43172 100644 --- a/expand.cpp +++ b/expand.cpp @@ -1,7 +1,7 @@ /**\file expand.c String expansion functions. These functions perform several kinds of -parameter expansion. +parameter expansion. */ @@ -23,6 +23,7 @@ parameter expansion. #include #include +#include #ifdef SunOS #include @@ -117,6 +118,35 @@ parameter expansion. */ #define UNCLEAN L"$*?\\\"'({})" +/* An adapter class for calling functions that expect a wchar_t * and array_list_t */ +class wcstring_adapter +{ +private: + std::vector *outputs; +public: + wchar_t *str; + array_list_t lst; + + wcstring_adapter(const wcstring &in, std::vector &outs) + { + outputs = &outs; + str = wcsdup(in.c_str()); + al_init(&lst); + } + + ~wcstring_adapter() + { + int i, max = al_get_count(&lst); + for (i=0; i < max; i++) { + wchar_t *tmp = (wchar_t *)al_get(&lst, i); + outputs->push_back(tmp); + free(tmp); + } + al_destroy(&lst); + //str is free'd by the function we called + } +}; + int expand_is_clean( const wchar_t *in ) { @@ -195,7 +225,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 ); @@ -206,7 +236,7 @@ wchar_t *expand_escape_variable( const wchar_t *in ) L"'", el, L"'", - (void *)0 ); + NULL ); } else { @@ -232,7 +262,7 @@ wchar_t *expand_escape_variable( const wchar_t *in ) L"'", el, L"'", - (void *)0 ); + NULL ); } else { @@ -276,14 +306,14 @@ static int match_pid( const wchar_t *cmd, int *offset) { /* Test for direct match */ - + if( wcsncmp( cmd, proc, wcslen( proc ) ) == 0 ) { if( offset ) *offset = 0; return 1; } - + /* Test if the commandline is a path to the command, if so we try to match against only the command part @@ -313,7 +343,7 @@ static int match_pid( const wchar_t *cmd, { if( offset ) *offset = start+1-first_token; - + free( first_token ); return 1; @@ -373,14 +403,14 @@ static int find_process( const wchar_t *proc, if( wcsncmp( proc, jid, wcslen(proc ) )==0 ) { string_buffer_t desc_buff; - + sb_init( &desc_buff ); - - sb_printf( &desc_buff, + + sb_printf( &desc_buff, COMPLETE_JOB_DESC_VAL, j->command ); - - completion_allocate( out, + + completion_allocate( out, jid+wcslen(proc), (wchar_t *)desc_buff.buff, 0 ); @@ -395,7 +425,7 @@ static int find_process( const wchar_t *proc, int jid; wchar_t *end; - + errno = 0; jid = wcstol( proc, &end, 10 ); if( jid > 0 && !errno && !*end ) @@ -403,9 +433,9 @@ static int find_process( const wchar_t *proc, j = job_get( jid ); if( (j != 0) && (j->command != 0 ) ) { - + { - result = malloc(sizeof(wchar_t)*16 ); + result = (wchar_t *)malloc(sizeof(wchar_t)*16 ); swprintf( result, 16, L"%d", j->pgid ); al_push( out, result ); found = 1; @@ -420,22 +450,22 @@ static int find_process( const wchar_t *proc, for( j=first_job; j != 0; j=j->next ) { int offset; - + if( j->command == 0 ) continue; - + if( match_pid( j->command, proc, flags, &offset ) ) { if( flags & ACCEPT_INCOMPLETE ) { - completion_allocate( out, + completion_allocate( out, j->command + offset + wcslen(proc), COMPLETE_JOB_DESC, 0 ); } else { - result = malloc(sizeof(wchar_t)*16 ); + result = (wchar_t *)malloc(sizeof(wchar_t)*16 ); swprintf( result, 16, L"%d", j->pgid ); al_push( out, result ); found = 1; @@ -456,7 +486,7 @@ static int find_process( const wchar_t *proc, for( p=j->first_process; p; p=p->next ) { int offset; - + if( p->actual_cmd == 0 ) continue; @@ -464,14 +494,14 @@ static int find_process( const wchar_t *proc, { if( flags & ACCEPT_INCOMPLETE ) { - completion_allocate( out, + completion_allocate( out, p->actual_cmd + offset + wcslen(proc), COMPLETE_CHILD_PROCESS_DESC, 0 ); } else { - result = malloc(sizeof(wchar_t)*16 ); + result = (wchar_t *)malloc(sizeof(wchar_t)*16 ); swprintf( result, 16, L"%d", p->pid ); al_push( out, result ); found = 1; @@ -493,13 +523,14 @@ static int find_process( const wchar_t *proc, return 1; } - pdir_name = malloc( sizeof(wchar_t)*256 ); - pfile_name = malloc( sizeof(wchar_t)*64 ); + pdir_name = (wchar_t *)malloc( sizeof(wchar_t)*256 ); + pfile_name = (wchar_t *)malloc( sizeof(wchar_t)*64 ); wcscpy( pdir_name, L"/proc/" ); - - while( (next=wreaddir(dir))!=0 ) + + wcstring nameStr; + while (wreaddir(dir, nameStr)) { - wchar_t *name = next->d_name; + const wchar_t *name = nameStr.c_str(); struct stat buf; if( !iswnumeric( name ) ) @@ -533,7 +564,7 @@ static int find_process( const wchar_t *proc, signal_block(); fgetws2( &cmd, &sz, cmdfile ); signal_unblock(); - + fclose( cmdfile ); } else @@ -574,12 +605,12 @@ static int find_process( const wchar_t *proc, if( cmd != 0 ) { int offset; - + if( match_pid( cmd, proc, flags, &offset ) ) { if( flags & ACCEPT_INCOMPLETE ) { - completion_allocate( out, + completion_allocate( out, cmd + offset + wcslen(proc), COMPLETE_PROCESS_DESC, 0 ); @@ -615,7 +646,7 @@ static int expand_pid( wchar_t *in, CHECK( in, 0 ); CHECK( out, 0 ); - + if( *in != PROCESS_EXPAND ) { al_push( out, in ); @@ -626,16 +657,16 @@ static int expand_pid( wchar_t *in, { if( wcsncmp( in+1, SELF_STR, wcslen(in+1) )==0 ) { - completion_allocate( out, + completion_allocate( out, SELF_STR+wcslen(in+1), - COMPLETE_SELF_DESC, + COMPLETE_SELF_DESC, 0 ); } else if( wcsncmp( in+1, LAST_STR, wcslen(in+1) )==0 ) { - completion_allocate( out, - LAST_STR+wcslen(in+1), - COMPLETE_LAST_DESC, + completion_allocate( out, + LAST_STR+wcslen(in+1), + COMPLETE_LAST_DESC, 0 ); } } @@ -643,7 +674,7 @@ static int expand_pid( wchar_t *in, { if( wcscmp( (in+1), SELF_STR )==0 ) { - wchar_t *str= malloc( sizeof(wchar_t)*32); + wchar_t *str= (wchar_t *)malloc( sizeof(wchar_t)*32); free(in); swprintf( str, 32, L"%d", getpid() ); al_push( out, str ); @@ -656,7 +687,7 @@ static int expand_pid( wchar_t *in, if( proc_last_bg_pid > 0 ) { - str = malloc( sizeof(wchar_t)*32); + str = (wchar_t *)malloc( sizeof(wchar_t)*32); free(in); swprintf( str, 32, L"%d", proc_last_bg_pid ); al_push( out, str ); @@ -688,11 +719,17 @@ static int expand_pid( wchar_t *in, return 1; } +static int expand_pid2( const wcstring &in, int flags, std::vector &outputs ) +{ + wcstring_adapter adapter(in, outputs); + return expand_pid(adapter.str, flags, &adapter.lst); +} + void expand_variable_error( const wchar_t *token, int token_pos, int error_pos ) { int stop_pos = token_pos+1; - + switch( token[stop_pos] ) { case BRACKET_BEGIN: @@ -707,13 +744,13 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos ) { post = end+1; *end = 0; - + if( !wcsvarname( name ) ) { is_var = 1; } } - + if( is_var ) { error( SYNTAX_ERROR, @@ -721,7 +758,7 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos ) COMPLETE_VAR_BRACKET_DESC, cpy, name, - post ); + post ); } else { @@ -733,18 +770,18 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos ) L"" ); } free( cpy ); - + break; } - + case INTERNAL_SEPARATOR: { error( SYNTAX_ERROR, error_pos, - COMPLETE_VAR_PARAN_DESC ); + COMPLETE_VAR_PARAN_DESC ); break; } - + case 0: { error( SYNTAX_ERROR, @@ -752,7 +789,7 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos ) COMPLETE_VAR_NULL_DESC ); break; } - + default: { error( SYNTAX_ERROR, @@ -767,30 +804,30 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos ) /** Parse an array slicing specification */ -static int parse_slice( wchar_t *in, wchar_t **end_ptr, array_list_t *idx ) +static int parse_slice( const wchar_t *in, wchar_t **end_ptr, array_list_t *idx ) { - - + + wchar_t *end; - + int pos = 1; // debug( 0, L"parse_slice on '%ls'", in ); - + while( 1 ) { long tmp; - + while( iswspace(in[pos]) || (in[pos]==INTERNAL_SEPARATOR)) - pos++; - + pos++; + if( in[pos] == L']' ) { pos++; break; } - + errno=0; tmp = wcstol( &in[pos], &end, 10 ); if( ( errno ) || ( end == &in[pos] ) ) @@ -798,19 +835,66 @@ static int parse_slice( wchar_t *in, wchar_t **end_ptr, array_list_t *idx ) return 1; } // debug( 0, L"Push idx %d", tmp ); - + al_push_long( idx, tmp ); pos = end-in; } - + if( end_ptr ) { // debug( 0, L"Remainder is '%ls', slice def was %d characters long", in+pos, pos ); - - *end_ptr = in+pos; + + *end_ptr = (wchar_t *)(in+pos); } // debug( 0, L"ok, done" ); + + return 0; +} +static int parse_slice2( const wchar_t *in, wchar_t **end_ptr, std::vector &idx ) +{ + + + wchar_t *end; + + int pos = 1; + + // debug( 0, L"parse_slice on '%ls'", in ); + + + while( 1 ) + { + long tmp; + + while( iswspace(in[pos]) || (in[pos]==INTERNAL_SEPARATOR)) + pos++; + + if( in[pos] == L']' ) + { + pos++; + break; + } + + errno=0; + tmp = wcstol( &in[pos], &end, 10 ); + if( ( errno ) || ( end == &in[pos] ) ) + { + return 1; + } + // debug( 0, L"Push idx %d", tmp ); + + idx.push_back(tmp); + pos = end-in; + } + + if( end_ptr ) + { + // debug( 0, L"Remainder is '%ls', slice def was %d characters long", in+pos, pos ); + + *end_ptr = (wchar_t *)(in+pos); + } + // debug( 0, L"ok, done" ); + return 0; } @@ -843,7 +927,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) CHECK( in, 0 ); CHECK( out, 0 ); - + if( !var_tmp ) { var_tmp = sb_halloc( global_context ); @@ -878,7 +962,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) wchar_t * new_in; int is_single = (c==VARIABLE_EXPAND_SINGLE); int var_name_stop_pos; - + stop_pos = start_pos; while( 1 ) @@ -892,15 +976,15 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) stop_pos++; } var_name_stop_pos = stop_pos; - + /* printf( "Stop for '%c'\n", in[stop_pos]);*/ var_len = stop_pos - start_pos; if( var_len == 0 ) { - expand_variable_error( in, stop_pos-1, -1 ); - + expand_variable_error( in, stop_pos-1, -1 ); + is_ok = 0; break; } @@ -919,17 +1003,17 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) { wchar_t *slice_end; all_vars=0; - + if( parse_slice( &in[stop_pos], &slice_end, var_idx_list ) ) { error( SYNTAX_ERROR, -1, - L"Invalid index value" ); + L"Invalid index value" ); is_ok = 0; - } + } stop_pos = (slice_end-in); - } - + } + if( is_ok ) { tokenize_variable_array( var_val, &var_item_list ); @@ -961,7 +1045,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) else { /* Replace each index in var_idx_list inplace with the string value at the specified index */ - al_set( var_idx_list, j, wcsdup(al_get( &var_item_list, tmp-1 ) ) ); + al_set( var_idx_list, j, wcsdup((const wchar_t *)al_get( &var_item_list, tmp-1 ) ) ); } } /* Free strings in list var_item_list and truncate it */ @@ -974,12 +1058,12 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) if( is_ok ) { - + if( is_single ) { string_buffer_t res; in[i]=0; - + sb_init( &res ); sb_append( &res, in ); sb_append_char( &res, INTERNAL_SEPARATOR ); @@ -987,7 +1071,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) for( j=0; j1 && new_in[start_pos-2]!=VARIABLE_EXPAND) @@ -1032,20 +1116,20 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) } else new_in[start_pos-1]=L'\0'; - + wcscat( new_in, next ); wcscat( new_in, &in[stop_pos] ); - + is_ok &= expand_variables( new_in, out, i ); } } free( next ); } - + } } } - + free(in); al_destroy( &var_item_list ); return is_ok; @@ -1099,6 +1183,12 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx ) return is_ok; } +static int expand_variables2( const wcstring &in, std::vector &outputs, int last_idx ) +{ + wcstring_adapter adapter(in, outputs); + return expand_variables(adapter.str, &adapter.lst, last_idx); +} + /** Perform bracket expansion */ @@ -1116,7 +1206,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out ) CHECK( in, 0 ); CHECK( out, 0 ); - + for( pos=in; (*pos) && !syntax_error; pos++ ) @@ -1138,7 +1228,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out ) { bracket_end = pos; } - + if( bracket_count < 0 ) { syntax_error = 1; @@ -1207,7 +1297,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out ) wchar_t *whole_item; int item_len = pos-item_begin; - whole_item = malloc( sizeof(wchar_t)*(tot_len + item_len + 1) ); + whole_item = (wchar_t *)malloc( sizeof(wchar_t)*(tot_len + item_len + 1) ); wcslcpy( whole_item, in, len1+1 ); wcslcpy( whole_item+len1, item_begin, item_len+1 ); wcscpy( whole_item+len1+item_len, bracket_end+1 ); @@ -1234,6 +1324,12 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out ) return 1; } +static int expand_brackets2( const wcstring &in, int flags, std::vector outputs ) +{ + wcstring_adapter adapter(in, outputs); + return expand_brackets(adapter.str, flags, &adapter.lst); +} + /** Perform cmdsubst expansion */ @@ -1246,12 +1342,12 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out ) array_list_t *sub_res, *tail_expand; int i, j; const wchar_t *item_begin; - wchar_t *tail_begin = 0; + wchar_t *tail_begin = 0; void *context; CHECK( in, 0 ); CHECK( out, 0 ); - + switch( parse_util_locate_cmdsubst(in, @@ -1279,9 +1375,9 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out ) item_begin = paran_begin+1; sub_res = al_halloc( context ); - if( !(subcmd = halloc( context, sizeof(wchar_t)*(paran_end-paran_begin) ))) + if( !(subcmd = (wchar_t *)halloc( context, sizeof(wchar_t)*(paran_end-paran_begin) ))) { - halloc_free( context ); + halloc_free( context ); return 0; } @@ -1300,10 +1396,10 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out ) { array_list_t *slice_idx = al_halloc( context ); wchar_t *slice_end; - + if( parse_slice( tail_begin, &slice_end, slice_idx ) ) { - halloc_free( context ); + halloc_free( context ); error( SYNTAX_ERROR, -1, L"Invalid index value" ); return 0; } @@ -1318,23 +1414,23 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out ) { idx = al_get_count( sub_res ) + idx + 1; } - + if( idx < 1 || idx > al_get_count( sub_res ) ) { halloc_free( context ); error( SYNTAX_ERROR, -1, L"Invalid index value" ); return 0; } - + idx = idx-1; - + al_push( sub_res2, al_get( sub_res, idx ) ); // debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx ); - + al_set( sub_res, idx, 0 ); } al_foreach( sub_res, &free ); - sub_res = sub_res2; + sub_res = sub_res2; } } @@ -1371,16 +1467,148 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out ) sb_append_substring( &whole_item, sub_item2, item_len ); sb_append_char( &whole_item, INTERNAL_SEPARATOR ); sb_append( &whole_item, tail_item ); - + al_push( out, whole_item.buff ); } - + free( sub_item2 ); } free(in); al_foreach( tail_expand, &free ); - halloc_free( context ); + halloc_free( context ); + return 1; +} + +/** + Perform cmdsubst expansion + */ +static int expand_cmdsubst2( const wcstring &input, std::vector &outList ) +{ + wchar_t *paran_begin=0, *paran_end=0; + int len1; + wchar_t prev=0; + std::vector sub_res; + size_t i, j; + const wchar_t *item_begin; + wchar_t *tail_begin = 0; + + const wchar_t * const in = input.c_str(); + + switch( parse_util_locate_cmdsubst(in, + ¶n_begin, + ¶n_end, + 0 ) ) + { + case -1: + error( SYNTAX_ERROR, + -1, + L"Mismatched parans" ); + return 0; + case 0: + outList.push_back(input); + return 1; + case 1: + + break; + } + + len1 = (paran_begin-in); + prev=0; + item_begin = paran_begin+1; + + const wcstring subcmd(paran_begin + 1, paran_end-paran_begin - 1); + + if( exec_subshell2( subcmd, sub_res) == -1 ) + { + error( CMDSUBST_ERROR, -1, L"Unknown error while evaulating command substitution" ); + return 0; + } + + tail_begin = paran_end + 1; + if( *tail_begin == L'[' ) + { + std::vector slice_idx; + wchar_t *slice_end; + + if( parse_slice2( tail_begin, &slice_end, slice_idx ) ) + { + error( SYNTAX_ERROR, -1, L"Invalid index value" ); + return 0; + } + else + { + std::vector sub_res2; + tail_begin = slice_end; + for( i=0; i < slice_idx.size(); i++ ) + { + long idx = slice_idx.at(i); + if( idx < 0 ) + { + idx = sub_res.size() + idx + 1; + } + + if( idx < 1 || (size_t)idx > sub_res.size() ) + { + error( SYNTAX_ERROR, -1, L"Invalid index value" ); + return 0; + } + + idx = idx-1; + + sub_res2.push_back(sub_res.at(idx)); + // debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx ); + //sub_res[idx] = 0; // ?? + } + sub_res = sub_res2; + } + } + + + /* + Recursively call ourselves to expand any remaining command + substitutions. The result of this recursive call using the tail + of the string is inserted into the tail_expand array list + */ + std::vector tail_expand; + expand_cmdsubst2( tail_begin, tail_expand ); + + /* + Combine the result of the current command substitution with the + result of the recursive tail expansion + */ + for( i=0; ipw_dir); - if( !home ) - { - *in = L'~'; - tilde_error = 1; - } + home = str2wcstring(userinfo->pw_dir); } - - free( name_str ); - free(name); } - if( !tilde_error && home && old_in ) - { - new_in = wcsdupcat( home, old_in ); - } - free(home); - free( in ); - return new_in; + if (! tilde_error) + { + input.replace(input.begin(), input.begin() + tail_idx, home); + } } - return in; } -wchar_t *expand_tilde( wchar_t *in) +static wchar_t * expand_tilde_internal_compat( wchar_t *in ) { - CHECK( in, 0 ); + wcstring tmp = in; + expand_tilde_internal(tmp); + free(in); + return wcsdup(tmp.c_str()); +} - if( in[0] == L'~' ) +void expand_tilde( wcstring &input) +{ + if( input[0] == L'~' ) { - in[0] = HOME_DIRECTORY; - return expand_tilde_internal( in ); + input[0] = HOME_DIRECTORY; + expand_tilde_internal( input ); } - return in; +} + +wchar_t * expand_tilde_compat( wchar_t *input ) +{ + if (input[0] == L'~') { + input[0] = HOME_DIRECTORY; + return expand_tilde_internal_compat(input); + } + return input; } /** @@ -1498,7 +1720,7 @@ static void remove_internal_separator( const void *s, int conv ) { wchar_t *in = (wchar_t *)s; wchar_t *out=in; - + CHECK( s, ); while( *in ) @@ -1508,7 +1730,7 @@ static void remove_internal_separator( const void *s, int conv ) case INTERNAL_SEPARATOR: in++; break; - + case ANY_CHAR: in++; *out++ = conv?L'?':ANY_CHAR; @@ -1531,6 +1753,231 @@ static void remove_internal_separator( const void *s, int conv ) *out=0; } +static void remove_internal_separator2( wcstring &s, int conv ) +{ + wchar_t *tmp = wcsdup(s.c_str()); + remove_internal_separator(tmp, conv); + s = tmp; + free(tmp); +} + + +int expand_string2( const wcstring &input, std::vector &output, int flags ) +{ + std::vector list1, list2; + std::vector *in, *out; + + size_t i; + int cmdsubst_ok = 1; + int res = EXPAND_OK; + int start_count = output.size(); + + if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( input.c_str() ) ) + { + output.push_back(input); + return EXPAND_OK; + } + + if( EXPAND_SKIP_CMDSUBST & flags ) + { + wchar_t *begin, *end; + + if( parse_util_locate_cmdsubst( input.c_str(), + &begin, + &end, + 1 ) != 0 ) + { + error( CMDSUBST_ERROR, -1, L"Command substitutions not allowed" ); + return EXPAND_ERROR; + } + list1.push_back(input); + } + else + { + cmdsubst_ok = expand_cmdsubst2(input, list1); + } + + if( !cmdsubst_ok ) + { + return EXPAND_ERROR; + } + else + { + in = &list1; + out = &list2; + + for( i=0; i < in->size(); i++ ) + { + /* + We accept incomplete strings here, since complete uses + expand_string to expand incomplete strings from the + commandline. + */ + int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE; + wcstring next = expand_unescape_string( in->at(i), unescape_flags ); + + if( EXPAND_SKIP_VARIABLES & flags ) + { + for (size_t i=0; i < next.size(); i++) { + if (next.at(i) == VARIABLE_EXPAND) { + next[i] = L'$'; + } + } + out->push_back(next); + } + else + { + if(!expand_variables2( next, *out, next.size() - 1 )) + { + return EXPAND_ERROR; + } + } + } + + in->clear(); + + in = &list2; + out = &list1; + + for( i=0; i < in->size(); i++ ) + { + wcstring next = in->at(i); + + if( !expand_brackets2( next, flags, *out )) + { + return EXPAND_ERROR; + } + } + in->clear(); + + in = &list1; + out = &list2; + + for( i=0; i < in->size(); i++ ) + { + wcstring next = in->at(i); + + expand_tilde_internal(next); + + + if( flags & ACCEPT_INCOMPLETE ) + { + if( next[0] == PROCESS_EXPAND ) + { + /* + If process expansion matches, we are not + interested in other completions, so we + short-circut and return + */ + expand_pid2( next, flags, output ); + return EXPAND_OK; + } + else + { + out->push_back(next); + } + } + else + { + if( !expand_pid2( next, flags, *out ) ) + { + return EXPAND_ERROR; + } + } + } + + in->clear(); + + in = &list2; + out = &list1; + + for( i=0; i < in->size(); i++ ) + { + wcstring next_str = in->at(i); + int wc_res; + + remove_internal_separator2( next_str, EXPAND_SKIP_WILDCARDS & flags ); + const wchar_t *next = next_str.c_str(); + + if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) || + wildcard_has( next, 1 ) ) + { + const wchar_t *start, *rest; + std::vector *list = out; + + if( next[0] == '/' ) + { + start = L"/"; + rest = &next[1]; + } + else + { + start = L""; + rest = next; + } + + if( flags & ACCEPT_INCOMPLETE ) + { + list = &output; + } + + wc_res = wildcard_expand_string(rest, start, flags, *list); + + if( !(flags & ACCEPT_INCOMPLETE) ) + { + + switch( wc_res ) + { + case 0: + { + if( !(flags & ACCEPT_INCOMPLETE) ) + { + if( res == EXPAND_OK ) + res = EXPAND_WILDCARD_NO_MATCH; + break; + } + } + + case 1: + { + size_t j; + res = EXPAND_WILDCARD_MATCH; + sort_strings( *out ); + + for( j=0; j< out->size(); j++ ) + { + wcstring next = out->at(j); + output.push_back(next); + } + out->clear(); + break; + } + + case -1: + { + return EXPAND_ERROR; + } + + } + } + + } + else + { + if( flags & ACCEPT_INCOMPLETE) + { + } + else + { + output.push_back(next); + } + } + + } + } + + return res; +} /** The real expansion function. expand_one is just a wrapper around this one. @@ -1564,7 +2011,7 @@ int expand_string( void *context, if( EXPAND_SKIP_CMDSUBST & flags ) { wchar_t *begin, *end; - + if( parse_util_locate_cmdsubst( str, &begin, &end, @@ -1611,7 +2058,7 @@ int expand_string( void *context, if( !next ) { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); - continue; + continue; } if( EXPAND_SKIP_VARIABLES & flags ) @@ -1645,8 +2092,8 @@ int expand_string( void *context, if( !next ) { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); - continue; - } + continue; + } if( !expand_brackets( next, flags, out )) { @@ -1667,10 +2114,10 @@ int expand_string( void *context, if( !next ) { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); - continue; + continue; } - if( !(next=expand_tilde_internal( next ) ) ) + if( !(next=expand_tilde_internal_compat( next ) ) ) { al_destroy( in ); al_destroy( out ); @@ -1719,11 +2166,11 @@ int expand_string( void *context, if( !next ) { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); - continue; - } + continue; + } remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags ); - + if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) || wildcard_has( next, 1 ) ) { @@ -1745,14 +2192,14 @@ int expand_string( void *context, { list = end_out; } - + wc_res = wildcard_expand( rest, start, flags, list ); free( next ); if( !(flags & ACCEPT_INCOMPLETE) ) { - + switch( wc_res ) { case 0: @@ -1764,7 +2211,7 @@ int expand_string( void *context, break; } } - + case 1: { int j; @@ -1777,8 +2224,8 @@ int expand_string( void *context, if( !next ) { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); - continue; - } + continue; + } al_push( end_out, next ); } al_truncate( out, 0 ); @@ -1792,10 +2239,10 @@ int expand_string( void *context, al_destroy( out ); return EXPAND_ERROR; } - + } } - + } else { @@ -1822,7 +2269,7 @@ int expand_string( void *context, } } - + return res; } @@ -1835,13 +2282,13 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags ) wchar_t *one; CHECK( string, 0 ); - + if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string ) ) { halloc_register( context, string ); return string; } - + al_init( &l ); res = expand_string( 0, string, &l, flags ); if( !res ) diff --git a/expand.h b/expand.h index 3c2cad826..a7dafb6f7 100644 --- a/expand.h +++ b/expand.h @@ -6,7 +6,7 @@ benefit from using a more clever memory allocation scheme, perhaps an evil combination of talloc, string buffers and reference counting. - + */ #ifndef FISH_EXPAND_H @@ -18,6 +18,8 @@ #include #include "util.h" +#include "common.h" +#include /** Flag specifying that cmdsubst expansion should be skipped @@ -70,7 +72,7 @@ enum /** Character represeting process expansion */ PROCESS_EXPAND, - + /** Character representing variable expansion */ VARIABLE_EXPAND, @@ -86,7 +88,7 @@ enum /** Character representing separation between two bracket elements */ BRACKET_SEP, /** - Separate subtokens in a token with this character. + Separate subtokens in a token with this character. */ INTERNAL_SEPARATOR, @@ -128,7 +130,7 @@ enum (\$VAR_NAME becomes the value of the environment variable VAR_NAME), cmdsubst 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. @@ -136,7 +138,7 @@ enum 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_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS @@ -144,6 +146,7 @@ enum \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. */ __warn_unused int expand_string( void *context, wchar_t *in, array_list_t *out, int flag ); +__warn_unused int expand_string2( const wcstring &input, std::list &output, int flag ); /** expand_one is identical to expand_string, except it will fail if in @@ -152,8 +155,8 @@ __warn_unused int expand_string( void *context, wchar_t *in, array_list_t *out, 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 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_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS \return The expanded parameter, or 0 on failiure @@ -168,14 +171,12 @@ wchar_t *expand_one( void *context, wchar_t *in, int flag ); wchar_t *expand_escape_variable( const wchar_t *in ); /** - Perform tilde expansion and nothing else on the specified string. + Perform tilde expansion and nothing else on the specified string, which is modified in place. - 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 + \param input the string to tilde expand */ -wchar_t *expand_tilde(wchar_t *in); +void expand_tilde(wcstring &input); +wchar_t * expand_tilde_compat( wchar_t *input ); /** diff --git a/fallback.cpp b/fallback.cpp index 452ac6643..1b14fad12 100644 --- a/fallback.cpp +++ b/fallback.cpp @@ -60,7 +60,7 @@ int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t)) while( *str ) { fish_putc( *str++ ); - } + } } #endif @@ -81,26 +81,26 @@ char *tparm_solaris_kludge( char *str, ... ) if( ( set_a_foreground && ! strcmp( str, set_a_foreground ) ) || ( set_a_background && ! strcmp( str, set_a_background ) ) - || ( set_foreground && ! strcmp( str, set_foreground ) ) + || ( set_foreground && ! strcmp( str, set_foreground ) ) || ( set_background && ! strcmp( str, set_background ) ) - || ( enter_underline_mode && ! strcmp( str, enter_underline_mode ) ) - || ( exit_underline_mode && ! strcmp( str, exit_underline_mode ) ) - || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) ) - || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) ) - || ( flash_screen && ! strcmp( str, flash_screen ) ) - || ( enter_subscript_mode && ! strcmp( str, enter_subscript_mode ) ) - || ( exit_subscript_mode && ! strcmp( str, exit_subscript_mode ) ) - || ( enter_superscript_mode && ! strcmp( str, enter_superscript_mode ) ) - || ( exit_superscript_mode && ! strcmp( str, exit_superscript_mode ) ) - || ( enter_blink_mode && ! strcmp( str, enter_blink_mode ) ) - || ( enter_italics_mode && ! strcmp( str, enter_italics_mode ) ) - || ( exit_italics_mode && ! strcmp( str, exit_italics_mode ) ) - || ( enter_reverse_mode && ! strcmp( str, enter_reverse_mode ) ) - || ( enter_shadow_mode && ! strcmp( str, enter_shadow_mode ) ) - || ( exit_shadow_mode && ! strcmp( str, exit_shadow_mode ) ) - || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) ) - || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) ) - || ( enter_secure_mode && ! strcmp( str, enter_secure_mode ) ) + || ( enter_underline_mode && ! strcmp( str, enter_underline_mode ) ) + || ( exit_underline_mode && ! strcmp( str, exit_underline_mode ) ) + || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) ) + || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) ) + || ( flash_screen && ! strcmp( str, flash_screen ) ) + || ( enter_subscript_mode && ! strcmp( str, enter_subscript_mode ) ) + || ( exit_subscript_mode && ! strcmp( str, exit_subscript_mode ) ) + || ( enter_superscript_mode && ! strcmp( str, enter_superscript_mode ) ) + || ( exit_superscript_mode && ! strcmp( str, exit_superscript_mode ) ) + || ( enter_blink_mode && ! strcmp( str, enter_blink_mode ) ) + || ( enter_italics_mode && ! strcmp( str, enter_italics_mode ) ) + || ( exit_italics_mode && ! strcmp( str, exit_italics_mode ) ) + || ( enter_reverse_mode && ! strcmp( str, enter_reverse_mode ) ) + || ( enter_shadow_mode && ! strcmp( str, enter_shadow_mode ) ) + || ( exit_shadow_mode && ! strcmp( str, exit_shadow_mode ) ) + || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) ) + || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) ) + || ( enter_secure_mode && ! strcmp( str, enter_secure_mode ) ) || ( enter_bold_mode && ! strcmp ( str, enter_bold_mode ) ) ) { param[0] = va_arg( ap, long int ); @@ -140,11 +140,11 @@ char *tparm_solaris_kludge( char *str, ... ) */ static void pad( void (*writer)(wchar_t), int count) { - + int i; if( count < 0 ) return; - + for( i=0; i= L'0') && (*filter <= L'9')) { width=10*width+(*filter++ - L'0'); - } + } } while( loop ) { - + switch(*filter) { case L'l': @@ -219,9 +219,9 @@ static int vgwprintf( void (*writer)(wchar_t), filter++; pad_left=0; break; - + case L'.': - /* + /* Set precision. */ filter++; @@ -235,10 +235,10 @@ static int vgwprintf( void (*writer)(wchar_t), while( (*filter >= L'0') && (*filter <= L'9')) { precision=10*precision+(*filter++ - L'0'); - } + } } break; - + default: loop=0; break; @@ -253,8 +253,8 @@ static int vgwprintf( void (*writer)(wchar_t), if( (width >= 0) && pad_left ) { - pad( writer, width-1 ); - count += maxi( width-1, 0 ); + pad( writer, width-1 ); + count += maxi( width-1, 0 ); } c = is_long?va_arg(va, wint_t):btowc(va_arg(va, int)); @@ -265,16 +265,16 @@ static int vgwprintf( void (*writer)(wchar_t), if( (width >= 0) && !pad_left ) { pad( writer, width-1 ); - count += maxi( width-1, 0 ); + count += maxi( width-1, 0 ); } - + count++; - + break; } case L's': - { - + { + wchar_t *ss=0; if( is_long ) { @@ -287,41 +287,41 @@ static int vgwprintf( void (*writer)(wchar_t), if( ns ) { ss = str2wcs( ns ); - } + } } - + if( !ss ) { return -1; } - + if( (width >= 0) && pad_left ) { - pad( writer, width-wcslen(ss) ); - count += maxi(width-wcslen(ss), 0); + pad( writer, width-wcslen(ss) ); + count += maxi(width-wcslen(ss), 0); } - + wchar_t *s=ss; int precount = count; - + while( *s ) { if( (precision > 0) && (precision <= (count-precount) ) ) break; - + writer( *(s++) ); count++; } - + if( (width >= 0) && !pad_left ) { - pad( writer, width-wcslen(ss) ); - count += maxi( width-wcslen(ss), 0 ); + pad( writer, width-wcslen(ss) ); + count += maxi( width-wcslen(ss), 0 ); } - + if( !is_long ) free( ss ); - + break; } @@ -336,7 +336,7 @@ static int vgwprintf( void (*writer)(wchar_t), char *pos; char format[16]; int len; - + format[0]=0; strcat( format, "%"); if( precision >= 0 ) @@ -350,7 +350,7 @@ static int vgwprintf( void (*writer)(wchar_t), strcat( format, "l" ); break; } - + len = strlen(format); format[len++]=(char)*filter; format[len]=0; @@ -360,7 +360,7 @@ static int vgwprintf( void (*writer)(wchar_t), case L'd': case L'i': { - + switch( is_long ) { case 0: @@ -370,10 +370,10 @@ static int vgwprintf( void (*writer)(wchar_t), snprintf( str, 32, format, precision, d ); else snprintf( str, 32, format, d ); - + break; } - + case 1: { long d = va_arg( va, long ); @@ -383,7 +383,7 @@ static int vgwprintf( void (*writer)(wchar_t), snprintf( str, 32, format, d ); break; } - + case 2: { long long d = va_arg( va, long long ); @@ -393,21 +393,21 @@ static int vgwprintf( void (*writer)(wchar_t), snprintf( str, 32, format, d ); break; } - + default: debug( 0, L"Invalid length modifier in string %ls\n", filter_org ); return -1; } break; - + } - + case L'u': case L'o': case L'x': case L'X': { - + switch( is_long ) { case 0: @@ -419,7 +419,7 @@ static int vgwprintf( void (*writer)(wchar_t), snprintf( str, 32, format, d ); break; } - + case 1: { unsigned long d = va_arg( va, unsigned long ); @@ -429,7 +429,7 @@ static int vgwprintf( void (*writer)(wchar_t), snprintf( str, 32, format, d ); break; } - + case 2: { unsigned long long d = va_arg( va, unsigned long long ); @@ -439,43 +439,43 @@ static int vgwprintf( void (*writer)(wchar_t), snprintf( str, 32, format, d ); break; } - + default: debug( 0, L"Invalid length modifier in string %ls\n", filter_org ); return -1; } break; - + } - + default: debug( 0, L"Invalid filter %ls in string %ls\n", *filter, filter_org ); return -1; - + } - + if( (width >= 0) && pad_left ) { int l = maxi(width-strlen(str), 0 ); pad( writer, l ); count += l; } - + pos = str; - + while( *pos ) { writer( *(pos++) ); count++; } - + if( (width >= 0) && !pad_left ) { int l = maxi(width-strlen(str), 0 ); pad( writer, l ); count += l; } - + break; } @@ -484,7 +484,7 @@ static int vgwprintf( void (*writer)(wchar_t), char str[32]; char *pos; double val = va_arg( va, double ); - + if( precision>= 0 ) { if( width>= 0 ) @@ -509,21 +509,21 @@ static int vgwprintf( void (*writer)(wchar_t), } pos = str; - + while( *pos ) { writer( *(pos++) ); count++; } - + break; } case L'n': { int *n = va_arg( va, int *); - - *n = count; + + *n = count; break; } case L'%': @@ -564,14 +564,14 @@ sw_data; static void sw_writer( wchar_t c ) { if( sw_data.count < sw_data.max ) - *(sw_data.pos++)=c; + *(sw_data.pos++)=c; sw_data.count++; } int vswprintf( wchar_t *out, size_t n, const wchar_t *filter, va_list va ) { int written; - + sw_data.pos=out; sw_data.max=n; sw_data.count=0; @@ -586,7 +586,7 @@ int vswprintf( wchar_t *out, size_t n, const wchar_t *filter, va_list va ) { written=-1; } - + return written; } @@ -594,7 +594,7 @@ int swprintf( wchar_t *out, size_t n, const wchar_t *filter, ... ) { va_list va; int written; - + va_start( va, filter ); written = vswprintf( out, n, filter, va ); va_end( va ); @@ -624,7 +624,7 @@ int fwprintf( FILE *f, const wchar_t *filter, ... ) { va_list va; int written; - + va_start( va, filter ); written = vfwprintf( f, filter, va ); va_end( va ); @@ -640,7 +640,7 @@ int wprintf( const wchar_t *filter, ... ) { va_list va; int written; - + va_start( va, filter ); written=vwprintf( filter, va ); va_end( va ); @@ -661,16 +661,16 @@ wint_t fgetwc(FILE *stream) { int b = fgetc( stream ); char bb; - + int sz; - + if( b == EOF ) return WEOF; bb=b; - + sz = mbrtowc( &res, &bb, 1, &state ); - + switch( sz ) { case -1: @@ -733,13 +733,13 @@ static size_t fish_wcsspn (const wchar_t *wcs, for (a = accept; *a != L'\0'; ++a) if (*p == *a) break; - + if (*a == L'\0') return count; else ++count; } - return count; + return count; } /* @@ -752,7 +752,7 @@ static wchar_t *fish_wcspbrk (const wchar_t *wcs, const wchar_t *accept) ++wcs; else return (wchar_t *) wcs; - return NULL; + return NULL; } /* @@ -775,18 +775,18 @@ wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr) /* Scan leading delimiters. */ wcs += fish_wcsspn (wcs, delim); - + if (*wcs == L'\0') { - *save_ptr = NULL; + *save_ptr = NULL; return NULL; } /* Find the end of the token. */ result = wcs; - + wcs = fish_wcspbrk (result, delim); - + if (wcs == NULL) { /* This token finishes the string. */ @@ -807,7 +807,7 @@ wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr) wchar_t *wcsdup( const wchar_t *in ) { size_t len=wcslen(in); - wchar_t *out = malloc( sizeof( wchar_t)*(len+1)); + wchar_t *out = (wchar_t *)malloc( sizeof( wchar_t)*(len+1)); if( out == 0 ) { return 0; @@ -815,7 +815,7 @@ wchar_t *wcsdup( const wchar_t *in ) memcpy( out, in, sizeof( wchar_t)*(len+1)); return out; - + } #endif @@ -855,7 +855,7 @@ int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count ) { if( count == 0 ) return 0; - + if( *a == 0 ) { return (*b==0)?0:-1; @@ -886,13 +886,13 @@ int wcwidth( wchar_t c ) #ifndef HAVE_WCSNDUP wchar_t *wcsndup( const wchar_t *in, int c ) { - wchar_t *res = malloc( sizeof(wchar_t)*(c+1) ); + wchar_t *res = (wchar_t *)malloc( sizeof(wchar_t)*(c+1) ); if( res == 0 ) { return 0; } wcslcpy( res, in, c+1 ); - return res; + return res; } #endif @@ -905,22 +905,22 @@ long convert_digit( wchar_t d, int base ) } else if( (d <= L'z') && (d >= L'a') ) { - res = d + 10 - L'a'; + res = d + 10 - L'a'; } else if( (d <= L'Z') && (d >= L'A') ) { - res = d + 10 - L'A'; + res = d + 10 - L'A'; } if( res >= base ) { res = -1; } - + return res; } #ifndef HAVE_WCSTOL -long wcstol(const wchar_t *nptr, +long wcstol(const wchar_t *nptr, wchar_t **endptr, int base) { @@ -943,7 +943,7 @@ long wcstol(const wchar_t *nptr, { errno = EINVAL; } - return res; + return res; } res = (res*base)+nxt; is_set = 1; @@ -985,25 +985,25 @@ long wcstol(const wchar_t *nptr, 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; + 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; + n = siz - dlen; if (n == 0) return(dlen + wcslen(s)); - while (*s != '\0') + while (*s != '\0') { - if (n != 1) + if (n != 1) { *d++ = *s; n--; @@ -1043,12 +1043,12 @@ 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 (n != 0 && --n != 0) + { + do + { if ((*d++ = *s++) == 0) break; } @@ -1056,8 +1056,8 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) } /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) - { + if (n == 0) + { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ @@ -1074,7 +1074,7 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) int lrand48_r(struct drand48_data *buffer, long int *result) { - *result = rand_r( &buffer->seed ); + *result = rand_r( &buffer->seed ); return 0; } @@ -1143,10 +1143,10 @@ int killpg( int pgr, int sig ) #ifndef HAVE_WORKING_GETOPT_LONG -int getopt_long( int argc, +int getopt_long( int argc, char * const argv[], const char *optstring, - const struct option *longopts, + const struct option *longopts, int *longindex ) { return getopt( argc, argv, optstring ); @@ -1181,7 +1181,7 @@ long sysconf(int name) } return -1; - + } #endif diff --git a/fallback.h b/fallback.h index 62175ca5c..e4813fb2f 100644 --- a/fallback.h +++ b/fallback.h @@ -57,12 +57,12 @@ typedef char tputs_arg_t; /** Structure used to get the size of a terminal window */ -struct winsize +struct winsize { /** Number of rows */ - unsigned short ws_row; + unsigned short ws_row; /** Number of columns */ @@ -193,7 +193,7 @@ wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr); /** Return the number of columns used by a character. This is a libc function, but the prototype for this function is missing in some libc - implementations. + implementations. Fish has a fallback implementation in case the implementation is missing altogether. In locales without a native wcwidth, Unicode @@ -320,7 +320,7 @@ size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz ); wcslen(src); if retval >= siz, truncation occurred. This is the OpenBSD strlcpy function, modified for wide characters, - and renamed to reflect this change. + and renamed to reflect this change. */ size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz ); @@ -390,7 +390,7 @@ char * textdomain( const char * domainname ); /** Fallback implementation of dcgettext. Just returns the original string. */ -char * dcgettext ( const char * domainname, +char * dcgettext ( const char * domainname, const char * msgid, int category ); @@ -421,7 +421,7 @@ int killpg( int pgr, int sig ); /** Struct describing a long getopt option */ -struct option +struct option { /** Name of option @@ -438,7 +438,7 @@ struct option /** Return value */ - int val; + int val; } ; @@ -454,10 +454,10 @@ struct option #define optional_argument 2 #endif -int getopt_long(int argc, +int getopt_long(int argc, char * const argv[], const char *optstring, - const struct option *longopts, + const struct option *longopts, int *longindex); #endif diff --git a/fish.cpp b/fish.cpp index 062c9a729..624037fef 100644 --- a/fish.cpp +++ b/fish.cpp @@ -80,7 +80,7 @@ static int read_init() eval( L"builtin . " DATADIR "/fish/config.fish 2>/dev/null", 0, TOP ); eval( L"builtin . " SYSCONFDIR L"/fish/config.fish 2>/dev/null", 0, TOP ); - + /* We need to get the configuration directory before we can source the user configuration file */ @@ -99,9 +99,9 @@ static int read_init() eval( (wchar_t *)eval_buff->buff, 0, TOP ); free( config_dir_escaped ); } - + halloc_free( context ); - + return 1; } @@ -114,83 +114,83 @@ static int fish_parse_opt( int argc, char **argv, char **cmd_ptr ) { int my_optind; int force_interactive=0; - + while( 1 ) { static struct option long_options[] = { { - "command", required_argument, 0, 'c' + "command", required_argument, 0, 'c' } , { - "debug-level", required_argument, 0, 'd' + "debug-level", required_argument, 0, 'd' } , { - "interactive", no_argument, 0, 'i' + "interactive", no_argument, 0, 'i' } , { - "login", no_argument, 0, 'l' + "login", no_argument, 0, 'l' } , { - "no-execute", no_argument, 0, 'n' + "no-execute", no_argument, 0, 'n' } , { - "profile", required_argument, 0, 'p' + "profile", required_argument, 0, 'p' } , { - "help", no_argument, 0, 'h' + "help", no_argument, 0, 'h' } , { - "version", no_argument, 0, 'v' + "version", no_argument, 0, 'v' } , - { - 0, 0, 0, 0 + { + 0, 0, 0, 0 } } ; - + int opt_index = 0; - + int opt = getopt_long( argc, - argv, + argv, GETOPT_STRING, - long_options, + long_options, &opt_index ); - + if( opt == -1 ) break; - + switch( opt ) { case 0: { break; } - - case 'c': + + case 'c': { - *cmd_ptr = optarg; + *cmd_ptr = optarg; is_interactive_session = 0; break; } - - case 'd': + + case 'd': { char *end; int tmp; errno = 0; tmp = strtol(optarg, &end, 10); - + if( tmp >= 0 && tmp <=10 && !*end && !errno ) { debug_level=tmp; @@ -202,65 +202,65 @@ static int fish_parse_opt( int argc, char **argv, char **cmd_ptr ) } break; } - + case 'h': { *cmd_ptr = "__fish_print_help fish"; break; } - + case 'i': { force_interactive = 1; - break; + break; } - + case 'l': { is_login=1; - break; + break; } - + case 'n': { no_exec=1; - break; + break; } - + case 'p': { profile = optarg; - break; + break; } - + case 'v': { - fwprintf( stderr, - _(L"%s, version %s\n"), + fwprintf( stderr, + _(L"%s, version %s\n"), PACKAGE_NAME, PACKAGE_VERSION ); - exit( 0 ); + exit( 0 ); } - + case '?': { exit( 1 ); } - - } + + } } my_optind = optind; - + is_login |= (strcmp( argv[0], "-fish") == 0); - + /* We are an interactive session if we have not been given an explicit command to execute, _and_ stdin is a tty. */ is_interactive_session &= (*cmd_ptr == 0); is_interactive_session &= (my_optind == argc); - is_interactive_session &= isatty(STDIN_FILENO); + is_interactive_session &= isatty(STDIN_FILENO); /* We are also an interactive session if we have are forced- @@ -282,7 +282,7 @@ int main( int argc, char **argv ) char *cmd=0; int my_optind=0; - halloc_util_init(); + halloc_util_init(); wsetlocale( LC_ALL, L"" ); is_interactive_session=1; @@ -299,9 +299,9 @@ int main( int argc, char **argv ) debug( 1, _(L"Can not use the no-execute mode when running an interactive session") ); no_exec = 0; } - - proc_init(); - event_init(); + + proc_init(); + event_init(); wutil_init(); parser_init(); builtin_init(); @@ -327,13 +327,13 @@ int main( int argc, char **argv ) } else { - char **ptr; + char **ptr; char *file = *(argv+(my_optind++)); - int i; + int i; string_buffer_t sb; int fd; wchar_t *rel_filename, *abs_filename; - + if( ( fd = open(file, O_RDONLY) ) == -1 ) { wperror( L"open" ); @@ -343,7 +343,7 @@ int main( int argc, char **argv ) if( *(argv+my_optind)) { sb_init( &sb ); - + for( i=1,ptr = argv+my_optind; *ptr; i++, ptr++ ) { if( i != 1 ) @@ -352,7 +352,7 @@ int main( int argc, char **argv ) sb_append( &sb, val ); free( val ); } - + env_set( L"argv", (wchar_t *)sb.buff, 0 ); sb_destroy( &sb ); } @@ -373,17 +373,17 @@ int main( int argc, char **argv ) if( res ) { - debug( 1, - _(L"Error while reading file %ls\n"), + debug( 1, + _(L"Error while reading file %ls\n"), reader_current_filename()?reader_current_filename(): _(L"Standard input") ); - } + } reader_pop_current_filename(); } } } - + proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res ); - + history_destroy(); proc_destroy(); builtin_destroy(); @@ -392,12 +392,12 @@ int main( int argc, char **argv ) parser_destroy(); wutil_destroy(); event_destroy(); - + halloc_util_destroy(); - + env_destroy(); - + intern_free_all(); - - return res?STATUS_UNKNOWN_COMMAND:proc_get_last_status(); + + return res?STATUS_UNKNOWN_COMMAND:proc_get_last_status(); } diff --git a/fish_indent.cpp b/fish_indent.cpp index 14cf5a6cf..39bd1de05 100644 --- a/fish_indent.cpp +++ b/fish_indent.cpp @@ -64,10 +64,10 @@ static void read_file( FILE *f, string_buffer_t *b ) wperror(L"fgetwc"); exit(1); } - + break; } - + sb_append_char( b, c ); } } @@ -78,12 +78,12 @@ static void read_file( FILE *f, string_buffer_t *b ) static void insert_tabs( string_buffer_t *out, int indent ) { int i; - + for( i=0; i" ); } - sb_append( out, L"| " ); + sb_append( out, L" | " ); is_command = 1; break; } - + case TOK_REDIRECT_OUT: { sb_append( out, L" " ); @@ -186,13 +186,13 @@ static int indent( string_buffer_t *out, wchar_t *in, int flags ) sb_append( out, L"^" ); } else { if ( wcscmp( last, L"1" ) != 0 ) - sb_append( out, last ); - sb_append( out, L">" ); + sb_append( out, last ); + sb_append( out, L"> " ); } - break; + break; } - - case TOK_REDIRECT_APPEND: + + case TOK_REDIRECT_APPEND: { sb_append( out, L" " ); if ( wcscmp( last, L"2" ) == 0 ) { @@ -200,28 +200,28 @@ static int indent( string_buffer_t *out, wchar_t *in, int flags ) } else { if ( wcscmp( last, L"1" ) != 0 ) sb_append( out, last ); - sb_append( out, L">>" ); + sb_append( out, L">> " ); } - break; + break; } - - case TOK_REDIRECT_IN: + + case TOK_REDIRECT_IN: { sb_append( out, L" " ); if ( wcscmp( last, L"0" ) != 0 ) sb_append( out, last ); - sb_append( out, L"<" ); - break; + sb_append( out, L"< " ); + break; } - - case TOK_REDIRECT_FD: + + case TOK_REDIRECT_FD: { sb_append( out, L" " ); if ( wcscmp( last, L"1" ) != 0 ) sb_append( out, last ); - sb_append( out, L">&" ); - break; - } + sb_append( out, L">& " ); + break; + } case TOK_BACKGROUND: { @@ -230,31 +230,31 @@ static int indent( string_buffer_t *out, wchar_t *in, int flags ) is_command = 1; break; } - + case TOK_COMMENT: { if( do_indent && flags) { insert_tabs( out, indent ); } - + sb_printf( out, L"%ls", last ); do_indent = 1; - break; + break; } - + default: { debug( 0, L"Unknown token '%ls'", last ); exit(1); - } + } } - + prev_prev_type = prev_type; prev_type = type; - + } - + tok_destroy( &tok ); return res; @@ -268,27 +268,27 @@ static int indent( string_buffer_t *out, wchar_t *in, int flags ) static wchar_t *trim( wchar_t *in ) { wchar_t *end; - + while( *in == L'\n' ) { in++; } - + end = in + wcslen(in); - + while( 1 ) { if( end < in+2 ) break; end--; - + if( (*end == L'\n' ) && ( *(end-1) == L'\n' ) ) *end=0; else break; } - + return in; } @@ -300,9 +300,9 @@ int main( int argc, char **argv ) { string_buffer_t sb_in; string_buffer_t sb_out; - + int do_indent=1; - + wsetlocale( LC_ALL, L"" ); program_name=L"fish_indent"; @@ -312,55 +312,55 @@ int main( int argc, char **argv ) long_options[] = { { - "no-indent", no_argument, 0, 'i' + "no-indent", no_argument, 0, 'i' } , { - "help", no_argument, 0, 'h' + "help", no_argument, 0, 'h' } , { - "version", no_argument, 0, 'v' + "version", no_argument, 0, 'v' } , - { - 0, 0, 0, 0 + { + 0, 0, 0, 0 } } ; - + int opt_index = 0; - + int opt = getopt_long( argc, - argv, + argv, GETOPT_STRING, - long_options, + long_options, &opt_index ); - + if( opt == -1 ) break; - + switch( opt ) { case 0: { break; } - + case 'h': { print_help( "fish_indent", 1 ); - exit( 0 ); + exit( 0 ); break; } - + case 'v': { - fwprintf( stderr, - _(L"%ls, version %s\n"), + fwprintf( stderr, + _(L"%ls, version %s\n"), program_name, PACKAGE_VERSION ); - exit( 0 ); + exit( 0 ); } case 'i': @@ -368,23 +368,23 @@ int main( int argc, char **argv ) do_indent = 0; break; } - - + + case '?': { exit( 1 ); } - - } + + } } - halloc_util_init(); + halloc_util_init(); sb_init( &sb_in ); sb_init( &sb_out ); read_file( stdin, &sb_in ); - + wutil_init(); if( !indent( &sb_out, (wchar_t *)sb_in.buff, do_indent ) ) @@ -398,7 +398,7 @@ int main( int argc, char **argv ) */ fwprintf( stdout, L"%ls", (wchar_t *)sb_in.buff ); } - + wutil_destroy(); diff --git a/fish_pager.cpp b/fish_pager.cpp index 1ed646126..f0dbd2e9c 100644 --- a/fish_pager.cpp +++ b/fish_pager.cpp @@ -61,7 +61,7 @@ #include "halloc_util.h" #include "print_help.h" -enum +enum { LINE_UP = R_NULL+1, LINE_DOWN, @@ -146,7 +146,7 @@ static buffer_t *pager_buffer; The environment variables used to specify the color of different tokens. */ -static wchar_t *hightlight_var[] = +static wchar_t *hightlight_var[] = { L"fish_pager_color_prefix", L"fish_pager_color_completion", @@ -167,7 +167,7 @@ static FILE *out_file; /** Data structure describing one or a group of related completions */ -typedef struct +typedef struct { /** The list of all completin strings this entry applies to @@ -180,11 +180,11 @@ typedef struct /** On-screen width of the completion string */ - int comp_width; + int comp_width; /** On-screen width of the description information */ - int desc_width; + int desc_width; /** Preffered total width */ @@ -208,20 +208,20 @@ static int get_color( int highlight ) return FISH_COLOR_NORMAL; if( highlight >= (4) ) return FISH_COLOR_NORMAL; - + val = wgetenv( hightlight_var[highlight]); if( !val ) { val = env_universal_get( hightlight_var[highlight]); } - + if( !val ) { return FISH_COLOR_NORMAL; } - - return output_color_code( val ); + + return output_color_code( val ); } /** @@ -236,11 +236,11 @@ static void recalc_width( array_list_t *l, const wchar_t *prefix ) for( i=0; imin_width = mini( c->desc_width, maxi(0,termsize.ws_col/3 - 2)) + mini( c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4; } - + } /** @@ -251,14 +251,14 @@ static int try_sequence( char *seq ) { int j, k; wint_t c=0; - - for( j=0; - seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 )); + + for( j=0; + seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 )); j++ ) ; if( seq[j] == '\0' ) - { + { return 1; } else @@ -281,10 +281,10 @@ static wint_t readch() wint_t bnd; } ; - + struct mapping m[]= { - { + { "\x1b[A", LINE_UP } , @@ -292,7 +292,7 @@ static wint_t readch() key_up, LINE_UP } , - { + { "\x1b[B", LINE_DOWN } , @@ -319,18 +319,18 @@ static wint_t readch() { 0, 0 } - + } ; int i; - + for( i=0; m[i].bnd; i++ ) { if( !m[i].seq ) { continue; } - + if( try_sequence(m[i].seq ) ) return m[i].bnd; } @@ -369,7 +369,7 @@ static int print_max( const wchar_t *str, int max, int has_more ) int written = 0; for( i=0; str[i]; i++ ) { - + if( written + wcwidth(str[i]) > max ) break; if( ( written + wcwidth(str[i]) == max) && (has_more || str[i+1]) ) @@ -378,7 +378,7 @@ static int print_max( const wchar_t *str, int max, int has_more ) written += wcwidth(ellipsis_char ); break; } - + writech( str[i] ); written+= wcwidth( str[i] ); } @@ -393,7 +393,7 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width ) int comp_width=0, desc_width=0; int i; int written=0; - + if( c->pref_width <= width ) { /* @@ -411,7 +411,7 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width ) the description. */ int desc_all = c->desc_width?c->desc_width+4:0; - + comp_width = maxi( mini( c->comp_width, 2*(width-4)/3 ), width - desc_all ); @@ -419,9 +419,9 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width ) desc_width = width-comp_width-4; else c->desc_width=0; - + } - + for( i=0; icomp ); i++ ) { const wchar_t *comp = (const wchar_t *)al_get( c->comp, i ); @@ -455,7 +455,7 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width ) writech( L' '); } } - + } /** @@ -490,14 +490,14 @@ static void completion_print( int cols, comp_t *el; int is_last = (j==(cols-1)); - + if( al_get_count( l ) <= j*rows + i ) continue; el = (comp_t *)al_get( l, j*rows + i ); - + completion_print_item( prefix, el, width[j] - (is_last?0:2) ); - + if( !is_last) writestr( L" " ); } @@ -545,24 +545,24 @@ static int completion_try_print( int cols, Set to one if the list should be printed at this width */ int print=0; - + int i, j; - + int rows = (al_get_count( l )-1)/cols+1; - + int pref_tot_width=0; int min_tot_width = 0; int res=PAGER_RETRY; /* Skip completions on tiny terminals */ - + if( termsize.ws_col < PAGER_MIN_WIDTH ) return PAGER_DONE; - + memset( pref_width, 0, sizeof(pref_width) ); memset( min_width, 0, sizeof(min_width) ); - + /* Calculate how wide the list would be */ for( j = 0; j < cols; j++ ) { @@ -576,7 +576,7 @@ static int completion_try_print( int cols, c = (comp_t *)al_get( l, j*rows + i ); pref = c->pref_width; min = c->min_width; - + if( j != cols-1 ) { pref += 2; @@ -632,7 +632,7 @@ static int completion_try_print( int cols, be helped, but it is not uncommon for the completions to _almost_ fit on one screen. In those cases, it is almost always desirable to 'squeeze' the completions into a - single page. + single page. If we are using N columns and can get everything to fit using squeezing, but everything would also fit @@ -668,7 +668,7 @@ static int completion_try_print( int cols, is_ca_mode = 0; writembs(exit_ca_mode); } - + completion_print( cols, width, 0, rows, prefix, is_quoted, l); pager_flush(); } @@ -687,7 +687,7 @@ static int completion_try_print( int cols, is_ca_mode=1; writembs(enter_ca_mode); } - + completion_print( cols, width, @@ -704,18 +704,18 @@ static int completion_try_print( int cols, { string_buffer_t msg; sb_init( &msg ); - + set_color( FISH_COLOR_BLACK, get_color(HIGHLIGHT_PAGER_PROGRESS) ); sb_printf( &msg, _(L" %d to %d of %d"), pos, - pos+termsize.ws_row-1, + pos+termsize.ws_row-1, rows ); - + sb_printf( &msg, L" \r" ); - + writestr((wchar_t *)msg.buff); sb_destroy( &msg ); set_color( FISH_COLOR_NORMAL, FISH_COLOR_NORMAL ); @@ -817,15 +817,15 @@ static int completion_try_print( int cols, do_loop=0; res=PAGER_RESIZE; break; - + } - + default: { sb_append_char( &out_buff, c ); do_loop = 0; break; - } + } } } writembs(clr_eol); @@ -847,31 +847,31 @@ static void mangle_descriptions( array_list_t *l ) wchar_t *next = (wchar_t *)al_get(l, i); wchar_t *in, *out; skip=1; - + while( *next != COMPLETE_SEP && *next ) next++; - + if( !*next ) continue; - + in=out=(next+1); - + while( *in != 0 ) { if( *in == L' ' || *in==L'\t' || *in<32 ) { if( !skip ) *out++=L' '; - skip=1; + skip=1; } else { - *out++ = *in; + *out++ = *in; skip=0; } in++; } - *out=0; + *out=0; } } @@ -883,7 +883,7 @@ static void join_completions( array_list_t *l ) long i; int in, out; hash_table_t desc_table; - + hash_init( &desc_table, &hash_wcs_func, &hash_wcs_cmp ); for( i=0; icomp = al_halloc( global_context ); - + for( start=end=next; 1; end++ ) { wchar_t c = *end; - + if( (c == COMPLETE_ITEM_SEP) || (c==COMPLETE_SEP) || !c) { *end = 0; wchar_t * str = escape( start, ESCAPE_ALL | ESCAPE_NO_QUOTED ); - + comp->comp_width += my_wcswidth( str ); halloc_register( global_context, str ); al_push( comp->comp, str ); @@ -973,22 +973,22 @@ static void mangle_completions( array_list_t *l, const wchar_t *prefix ) { comp->desc = halloc_wcsdup( global_context, start ); break; - } - + } + if( !c ) break; - + } comp->comp_width += my_wcswidth(prefix)*al_get_count(comp->comp) + 2*(al_get_count(comp->comp)-1); comp->desc_width = comp->desc?my_wcswidth( comp->desc ):0; - + comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0); - + free( next ); al_set( l, i, comp ); } - + recalc_width( l, prefix ); } @@ -1026,10 +1026,10 @@ static void init( int mangle_descriptors, int out ) static struct termios pager_modes; char *term; - + if( mangle_descriptors ) { - + /* Make fd 1 output to screen, and use some other fd for writing the resulting output back to the caller @@ -1042,13 +1042,13 @@ static void init( int mangle_descriptors, int out ) if( (in = open( ttyname(2), O_RDWR )) != -1 ) { if( dup2( 2, 1 ) == -1 ) - { + { debug( 0, _(L"Could not set up output file descriptors for pager") ); exit( 1 ); } - + if( dup2( in, 0 ) == -1 ) - { + { debug( 0, _(L"Could not set up input file descriptors for pager") ); exit( 1 ); } @@ -1059,13 +1059,13 @@ static void init( int mangle_descriptors, int out ) exit( 1 ); } } - + if( !(out_file = fdopen( out, "w" )) ) { debug( 0, _(L"Could not initialize result pipe" ) ); exit( 1 ); } - + /** Init the stringbuffer used to keep any output in @@ -1075,7 +1075,7 @@ static void init( int mangle_descriptors, int out ) env_universal_init( 0, 0, 0, 0); input_common_init( &interrupt_handler ); output_set_writer( &pager_buffered_writer ); - pager_buffer = halloc( global_context, sizeof( buffer_t ) ); + pager_buffer = (buffer_t *)halloc( global_context, sizeof( buffer_t ) ); halloc_register_function( global_context, (void (*)(void *))&b_destroy, pager_buffer ); sigemptyset( & act.sa_mask ); @@ -1088,7 +1088,7 @@ static void init( int mangle_descriptors, int out ) wperror( L"sigaction" ); exit(1); } - + handle_winch( 0 ); /* Set handler for window change events */ tcgetattr(0,&pager_modes); /* get the current terminal modes */ @@ -1102,14 +1102,14 @@ static void init( int mangle_descriptors, int out ) pager_modes.c_cc[VTIME]=0; /* - + */ if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */ { wperror(L"tcsetattr"); exit(1); } - + if( setupterm( 0, STDOUT_FILENO, 0) == ERR ) { @@ -1124,7 +1124,7 @@ static void init( int mangle_descriptors, int out ) output_set_term( wterm ); free( wterm ); } - + } /** @@ -1137,9 +1137,9 @@ static void destroy() wutil_destroy(); if( del_curterm( cur_term ) == ERR ) { - debug( 0, _(L"Error while closing terminfo") ); + debug( 0, _(L"Error while closing terminfo") ); } - + sb_destroy( &out_buff ); fclose( out_file ); } @@ -1164,7 +1164,7 @@ static void read_array( FILE* file, array_list_t *comp ) while( 1 ) { c = getc( file ); - if( c == EOF ) + if( c == EOF ) { break; } @@ -1175,7 +1175,7 @@ static void read_array( FILE* file, array_list_t *comp ) } cc=c; - + b_append( &buffer, &cc, 1 ); } @@ -1183,15 +1183,15 @@ static void read_array( FILE* file, array_list_t *comp ) { cc=0; b_append( &buffer, &cc, 1 ); - + wcs = str2wcs( buffer.buff ); - if( wcs ) + if( wcs ) { unescaped = unescape( wcs, 0 ); if( unescaped ) { al_push( comp, unescaped ); - } + } free( wcs ); } } @@ -1203,9 +1203,9 @@ static void read_array( FILE* file, array_list_t *comp ) static int get_fd( const char *str ) { - char *end; + char *end; long fd; - + errno = 0; fd = strtol( str, &end, 10 ); if( fd < 0 || *end || errno ) @@ -1220,13 +1220,13 @@ static int get_fd( const char *str ) int main( int argc, char **argv ) { int i; - int is_quoted=0; + int is_quoted=0; array_list_t *comp; wchar_t *prefix = 0; int mangle_descriptors = 0; int result_fd = -1; - + /* This initialization is made early, so that the other init code can use global_context for memory managment @@ -1252,69 +1252,69 @@ int main( int argc, char **argv ) /* Third mode */ - + int completion_fd = -1; FILE *completion_file; - + while( 1 ) { static struct option long_options[] = { { - "result-fd", required_argument, 0, 'r' + "result-fd", required_argument, 0, 'r' } , { - "completion-fd", required_argument, 0, 'c' + "completion-fd", required_argument, 0, 'c' } , { - "prefix", required_argument, 0, 'p' + "prefix", required_argument, 0, 'p' } , { - "is-quoted", no_argument, 0, 'q' + "is-quoted", no_argument, 0, 'q' } , { - "help", no_argument, 0, 'h' + "help", no_argument, 0, 'h' } , { - "version", no_argument, 0, 'v' + "version", no_argument, 0, 'v' } , - { - 0, 0, 0, 0 + { + 0, 0, 0, 0 } } ; - + int opt_index = 0; - + int opt = getopt_long( argc, - argv, + argv, GETOPT_STRING, - long_options, + long_options, &opt_index ); - + if( opt == -1 ) break; - + switch( opt ) { case 0: { break; } - + case 'r': { result_fd = get_fd( optarg ); break; } - + case 'c': { completion_fd = get_fd( optarg ); @@ -1330,20 +1330,20 @@ int main( int argc, char **argv ) case 'h': { print_help( argv[0], 1 ); - exit(0); + exit(0); } case 'v': { debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION ); - exit( 0 ); + exit( 0 ); } - + case 'q': { is_quoted = 1; } - + } } @@ -1352,7 +1352,7 @@ int main( int argc, char **argv ) debug( 0, _(L"Unspecified file descriptors") ); exit( 1 ); } - + if( (completion_file = fdopen( completion_fd, "r" ) ) ) { @@ -1370,8 +1370,8 @@ int main( int argc, char **argv ) { prefix = wcsdup( L"" ); } - - + + } else { @@ -1385,7 +1385,7 @@ int main( int argc, char **argv ) forward. A reasonable time frame for removal of the code below has yet to be determined. */ - + if( argc < 3 ) { print_help( argv[0], 1 ); @@ -1394,10 +1394,10 @@ int main( int argc, char **argv ) else { mangle_descriptors = 1; - + prefix = str2wcs( argv[2] ); is_quoted = strcmp( "1", argv[1] )==0; - + if( argc > 3 ) { /* @@ -1420,11 +1420,11 @@ int main( int argc, char **argv ) read_array( stdin, comp ); } } - + } - + // debug( 3, L"prefix is '%ls'", prefix ); - + init( mangle_descriptors, result_fd ); mangle_descriptions( comp ); @@ -1462,9 +1462,9 @@ int main( int argc, char **argv ) i=PAGER_MAX_COLS+1; break; - } + } } - + free(prefix ); fwprintf( out_file, L"%ls", (wchar_t *)out_buff.buff ); @@ -1476,6 +1476,6 @@ int main( int argc, char **argv ) destroy(); halloc_util_destroy(); - + } diff --git a/fish_tests.cpp b/fish_tests.cpp index a5c3d943a..d5ed103ca 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #ifdef HAVE_GETOPT_H #include @@ -80,27 +80,27 @@ static int err_count=0; /** Print formatted output */ -static void say( wchar_t *blah, ... ) +static void say( const wchar_t *blah, ... ) { va_list va; va_start( va, blah ); vwprintf( blah, va ); - va_end( va ); + va_end( va ); wprintf( L"\n" ); } /** Print formatted error string */ -static void err( wchar_t *blah, ... ) +static void err( const wchar_t *blah, ... ) { va_list va; va_start( va, blah ); err_count++; - + wprintf( L"Error: " ); vwprintf( blah, va ); - va_end( va ); + va_end( va ); wprintf( L"\n" ); } @@ -109,7 +109,7 @@ static void err( wchar_t *blah, ... ) */ static int pq_compare( void *e1, void *e2 ) { - return e1-e2; + return (intptr_t)e1-(intptr_t)e2; } /** @@ -119,13 +119,13 @@ static void pq_test( int elements ) { int i; int prev; - - int *count = calloc( sizeof(int), 100 ); - + + int *count = (int *)calloc( sizeof(int), 100 ); + priority_queue_t q; pq_init( &q, pq_compare ); - + for( i=0; i prev ) err( L"Wrong order of elements in priority_queue_t" ); prev = pos; - + } for( i=0; i<100; i++ ) @@ -163,10 +163,10 @@ static int stack_test( int elements ) long i; int res=1; - + array_list_t s; - al_init( &s ); + al_init( &s ); for( i=0; i&1 'nested \"quoted\" '(string containing subshells ){and,brackets}$as[$well (as variable arrays)]"; - const int types[] = + const wchar_t *str = L"string &1 'nested \"quoted\" '(string containing subshells ){and,brackets}$as[$well (as variable arrays)]"; + const int types[] = { TOK_STRING, TOK_REDIRECT_IN, TOK_STRING, TOK_REDIRECT_FD, TOK_STRING, TOK_STRING, TOK_END } ; - int i; - + size_t i; + say( L"Test correct tokenization" ); for( i=0, tok_init( &t, str, 0 ); i<(sizeof(types)/sizeof(int)); i++,tok_next( &t ) ) @@ -603,7 +603,7 @@ static void test_tok() if( types[i] != tok_last_type( &t ) ) { err( L"Tokenization error:"); - wprintf( L"Token number %d of string \n'%ls'\n, expected token type %ls, got token '%ls' of type %ls\n", + wprintf( L"Token number %d of string \n'%ls'\n, expected token type %ls, got token '%ls' of type %ls\n", i+1, str, tok_get_desc(types[i]), @@ -612,9 +612,9 @@ static void test_tok() } } } + - - + } /** @@ -623,8 +623,8 @@ static void test_tok() static void test_parser() { say( L"Testing parser" ); - - + + say( L"Testing null input to parser" ); if( !parser_test( 0, 0, 0, 0 ) ) { @@ -634,51 +634,51 @@ static void test_parser() say( L"Testing block nesting" ); if( !parser_test( L"if; end", 0, 0, 0 ) ) { - err( L"Incomplete if statement undetected" ); + err( L"Incomplete if statement undetected" ); } if( !parser_test( L"if test; echo", 0, 0, 0 ) ) { - err( L"Missing end undetected" ); + err( L"Missing end undetected" ); } if( !parser_test( L"if test; end; end", 0, 0, 0 ) ) { - err( L"Unbalanced end undetected" ); + err( L"Unbalanced end undetected" ); } say( L"Testing detection of invalid use of builtin commands" ); if( !parser_test( L"case foo", 0, 0, 0 ) ) { - err( L"'case' command outside of block context undetected" ); + err( L"'case' command outside of block context undetected" ); } if( !parser_test( L"switch ggg; if true; case foo;end;end", 0, 0, 0 ) ) { - err( L"'case' command outside of switch block context undetected" ); + err( L"'case' command outside of switch block context undetected" ); } if( !parser_test( L"else", 0, 0, 0 ) ) { - err( L"'else' command outside of conditional block context undetected" ); + err( L"'else' command outside of conditional block context undetected" ); } if( !parser_test( L"break", 0, 0, 0 ) ) { - err( L"'break' command outside of loop block context undetected" ); + err( L"'break' command outside of loop block context undetected" ); } if( !parser_test( L"exec ls|less", 0, 0, 0 ) || !parser_test( L"echo|return", 0, 0, 0 )) { - err( L"Invalid pipe command undetected" ); - } + err( L"Invalid pipe command undetected" ); + } say( L"Testing basic evaluation" ); if( !eval( 0, 0, TOP ) ) { err( L"Null input when evaluating undetected" ); - } + } if( !eval( L"ls", 0, WHILE ) ) { err( L"Invalid block mode when evaluating undetected" ); } - + } - + /** Perform parameter expansion and test if the output equals the zero-terminated parameter list supplied. @@ -688,42 +688,42 @@ static void test_parser() static int expand_test( const wchar_t *in, int flags, ... ) { - array_list_t out; + array_list_t out; va_list va; int i=0; int res=1; wchar_t *arg; - + al_init( &out ); if( expand_string( 0, wcsdup(in), &out, flags) ) { - + } - - + + va_start( va, flags ); - while( (arg=va_arg(va, wchar_t *) )!= 0 ) + while( (arg=va_arg(va, wchar_t *) )!= 0 ) { if( al_get_count( &out ) == i ) { res=0; break; } - - if( wcscmp( al_get( &out, i ),arg) != 0 ) + + if( wcscmp( (wchar_t *)al_get( &out, i ),arg) != 0 ) { res=0; break; } - - i++; + + i++; } va_end( va ); - + al_foreach( &out, &free ); return res; - + } /** @@ -732,7 +732,7 @@ static int expand_test( const wchar_t *in, int flags, ... ) static void test_expand() { say( L"Testing parameter expansion" ); - + if( !expand_test( L"foo", 0, L"foo", 0 )) { err( L"Strings do not expand to themselves" ); @@ -747,7 +747,7 @@ static void test_expand() { err( L"Cannot skip wildcard expansion" ); } - + } /** @@ -758,17 +758,17 @@ static void test_path() say( L"Testing path functions" ); void *context = halloc( 0, 0 ); - + wchar_t *can = path_make_canonical( context, L"//foo//////bar/" ); - + if( wcscmp( can, L"/foo/bar" ) ) { err( L"Bug in canonical PATH code" ); } - + halloc_free( context ); - + } @@ -785,72 +785,72 @@ void perf_complete() double t; wchar_t str[3]= { - 0, 0, 0 + 0, 0, 0 } ; int i; - - + + say( L"Testing completion performance" ); al_init( &out ); - + reader_push(L""); say( L"Here we go" ); - + t1 = get_time(); - - + + for( c=L'a'; c<=L'z'; c++ ) { str[0]=c; reader_set_buffer( str, 0 ); - + complete( str, &out ); - + matches += al_get_count( &out ); - + al_foreach( &out, &free ); al_truncate( &out, 0 ); } t2=get_time(); - + t = (double)(t2-t1)/(1000000*26); - + say( L"One letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches ); - + matches=0; t1 = get_time(); for( i=0; ipw_name ); } - name = malloc( strlen(dir)+ strlen(uname)+ strlen(SOCK_FILENAME) + 2 ); + name = (char *)malloc( strlen(dir)+ strlen(uname)+ strlen(SOCK_FILENAME) + 2 ); if( name == NULL ) { wperror( L"get_socket_filename" ); @@ -182,7 +182,7 @@ static char *get_socket_filename() } /** - Signal handler for the term signal. + Signal handler for the term signal. */ static void handle_term( int signal ) { @@ -192,17 +192,17 @@ static void handle_term( int signal ) /** Acquire the lock for the socket - Returns the name of the lock file if successful or + Returns the name of the lock file if successful or NULL if unable to obtain lock. - The returned string must be free()d after unlink()ing the file to release + The returned string must be free()d after unlink()ing the file to release the lock */ static char *acquire_socket_lock( const char *sock_name ) { int len = strlen( sock_name ); - char *lockfile = malloc( len + strlen( LOCKPOSTFIX ) + 1 ); - - if( lockfile == NULL ) + char *lockfile = (char *)malloc( len + strlen( LOCKPOSTFIX ) + 1 ); + + if( lockfile == NULL ) { wperror( L"acquire_socket_lock" ); exit( EXIT_FAILURE ); @@ -237,13 +237,13 @@ static int get_socket() exit( EXIT_FAILURE ); } debug( 4, L"Acquired lockfile: %s", lockfile ); - + local.sun_family = AF_UNIX; strcpy( local.sun_path, sock_name ); len = sizeof(local); - + debug(1, L"Connect to socket at %s", sock_name); - + if( ( s = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) { wperror( L"socket" ); @@ -262,7 +262,7 @@ static int get_socket() exitcode = 0; goto unlock; } - + unlink( local.sun_path ); if( bind( s, (struct sockaddr *)&local, len ) == -1 ) { @@ -288,9 +288,9 @@ unlock: /* End critical section protected by lock */ - + free( lockfile ); - + free( sock_name ); if( doexit ) @@ -311,24 +311,24 @@ static void broadcast( int type, const wchar_t *key, const wchar_t *val ) if( !conn ) return; - + msg = create_message( type, key, val ); - + /* Don't merge these loops, or try_send_all can free the message prematurely */ - + for( c = conn; c; c=c->next ) { msg->count++; q_put( &c->unsent, msg ); - } - + } + for( c = conn; c; c=c->next ) { try_send_all( c ); - } + } } /** @@ -345,7 +345,7 @@ static void daemonize() debug( 0, L"Could not put fishd in background. Quitting" ); wperror( L"fork" ); exit(1); - + case 0: { /* @@ -366,19 +366,19 @@ static void daemonize() sigaction( SIGTERM, &act, 0); break; } - + default: - { + { debug( 0, L"Parent process exiting (This is normal)" ); exit(0); - } + } } - + /* Put ourself in out own processing group */ setsid(); - + /* Close stdin and stdout. We only use stderr, anyway. */ @@ -394,7 +394,7 @@ static wchar_t *fishd_env_get( wchar_t *key ) { char *nres, *nkey; wchar_t *res; - + nkey = wcs2str( key ); nres = getenv( nkey ); free( nkey ); @@ -407,7 +407,7 @@ static wchar_t *fishd_env_get( wchar_t *key ) res = env_universal_common_get( key ); if( res ) res = wcsdup( res ); - + return env_universal_common_get( key ); } } @@ -423,7 +423,7 @@ static wchar_t *fishd_get_config() wchar_t *xdg_dir, *home; int done = 0; wchar_t *res = 0; - + xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" ); if( xdg_dir ) { @@ -439,7 +439,7 @@ static wchar_t *fishd_get_config() free( xdg_dir ); } else - { + { home = fishd_env_get( L"HOME" ); if( home ) { @@ -455,7 +455,7 @@ static wchar_t *fishd_get_config() free( home ); } } - + if( done ) { return res; @@ -465,7 +465,7 @@ static wchar_t *fishd_get_config() debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." )); return 0; } - + } /** @@ -475,23 +475,23 @@ static void load_or_save( int save) { char *name; wchar_t *wdir = fishd_get_config(); - char *dir; + char *dir; char hostname[HOSTNAME_LEN]; connection_t c; int fd; - + if( !wdir ) { return; } - + dir = wcs2str( wdir ); free( wdir ); - + gethostname( hostname, HOSTNAME_LEN ); - - name = malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 ); + + name = (char *)malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 ); strcpy( name, dir ); strcat( name, "/" ); strcat( name, FILE ); @@ -499,20 +499,20 @@ static void load_or_save( int save) free( dir ); - - debug( 4, L"Open file for %s: '%s'", - save?"saving":"loading", + + debug( 4, L"Open file for %s: '%s'", + save?"saving":"loading", name ); - + fd = open( name, save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600); - + free( name ); - + if( fd == -1 ) { debug( 1, L"Could not open load/save file. No previous saves?" ); wperror( L"open" ); - return; + return; } debug( 4, L"File open on fd %d", c.fd ); @@ -520,14 +520,14 @@ static void load_or_save( int save) if( save ) { - + write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) ); enqueue_all( &c ); } else read_message( &c ); - connection_destroy( &c ); + connection_destroy( &c ); } /** @@ -553,10 +553,10 @@ static void init() { sock = get_socket(); - daemonize(); + daemonize(); env_universal_common_init( &broadcast ); - - load(); + + load(); } /** @@ -569,13 +569,13 @@ int main( int argc, char ** argv ) socklen_t t; int max_fd; int update_count=0; - + fd_set read_fd, write_fd; halloc_util_init(); - + program_name=L"fishd"; - wsetlocale( LC_ALL, L"" ); + wsetlocale( LC_ALL, L"" ); /* Parse options @@ -586,57 +586,57 @@ int main( int argc, char ** argv ) long_options[] = { { - "help", no_argument, 0, 'h' + "help", no_argument, 0, 'h' } , { - "version", no_argument, 0, 'v' + "version", no_argument, 0, 'v' } , - { - 0, 0, 0, 0 + { + 0, 0, 0, 0 } } ; - + int opt_index = 0; - + int opt = getopt_long( argc, - argv, + argv, GETOPT_STRING, - long_options, + long_options, &opt_index ); - + if( opt == -1 ) break; - + switch( opt ) { case 0: - break; + break; case 'h': print_help( argv[0], 1 ); - exit(0); - + exit(0); + case 'v': debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION ); - exit( 0 ); - + exit( 0 ); + case '?': return 1; - - } + + } } - + init(); - while(1) + while(1) { connection_t *c; int res; - t = sizeof( remote ); - + t = sizeof( remote ); + FD_ZERO( &read_fd ); FD_ZERO( &write_fd ); FD_SET( sock, &read_fd ); @@ -645,7 +645,7 @@ int main( int argc, char ** argv ) { FD_SET( c->fd, &read_fd ); max_fd = maxi( max_fd, c->fd+1); - + if( ! q_empty( &c->unsent ) ) { FD_SET( c->fd, &write_fd ); @@ -661,22 +661,22 @@ int main( int argc, char ** argv ) save(); exit(0); } - + if( res != -1 ) break; - + if( errno != EINTR ) { wperror( L"select" ); exit(1); } } - + if( FD_ISSET( sock, &read_fd ) ) { - if( (child_socket = - accept( sock, - (struct sockaddr *)&remote, + if( (child_socket = + accept( sock, + (struct sockaddr *)&remote, &t) ) == -1) { wperror( L"accept" ); exit(1); @@ -688,20 +688,20 @@ int main( int argc, char ** argv ) if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 ) { wperror( L"fcntl" ); - close( child_socket ); + close( child_socket ); } else { - connection_t *new = malloc( sizeof(connection_t)); - connection_init( new, child_socket ); - new->next = conn; - send( new->fd, GREETING, strlen(GREETING), MSG_DONTWAIT ); - enqueue_all( new ); - conn=new; + connection_t *newc = (connection_t *)malloc( sizeof(connection_t)); + connection_init( newc, child_socket ); + newc->next = conn; + send( newc->fd, GREETING, strlen(GREETING), MSG_DONTWAIT ); + enqueue_all( newc ); + conn=newc; } } } - + for( c=conn; c; c=c->next ) { if( FD_ISSET( c->fd, &write_fd ) ) @@ -709,7 +709,7 @@ int main( int argc, char ** argv ) try_send_all( c ); } } - + for( c=conn; c; c=c->next ) { if( FD_ISSET( c->fd, &read_fd ) ) @@ -728,10 +728,10 @@ int main( int argc, char ** argv ) } } } - + connection_t *prev=0; c=conn; - + while( c ) { if( c->killme ) @@ -745,7 +745,7 @@ int main( int argc, char ** argv ) if( !msg->count ) free( msg ); } - + connection_destroy( c ); if( prev ) { @@ -755,11 +755,11 @@ int main( int argc, char ** argv ) { conn=c->next; } - + free(c); - + c=(prev?prev->next:conn); - + } else { @@ -771,10 +771,10 @@ int main( int argc, char ** argv ) if( !conn ) { debug( 0, L"No more clients. Quitting" ); - save(); + save(); env_universal_common_destroy(); break; - } + } } halloc_util_destroy(); diff --git a/function.cpp b/function.cpp index 576465a5d..52fc333d5 100644 --- a/function.cpp +++ b/function.cpp @@ -11,10 +11,13 @@ #include #include +#include #include #include #include #include +#include +#include #include "wutil.h" #include "fallback.h" @@ -43,7 +46,7 @@ typedef struct /** Function definition */ wchar_t *definition; /** Function description */ - wchar_t *description; + wchar_t *description; /** File where this function was defined */ @@ -51,14 +54,14 @@ typedef struct /** Line where definition started */ - int definition_offset; - + int definition_offset; + /** List of all named arguments for this function */ array_list_t *named_arguments; - - + + /** Flag for specifying that this function was automatically loaded */ @@ -75,7 +78,37 @@ typedef struct /** Table containing all functions */ -static hash_table_t function; +static hash_table_t functions; + +/* Lock for functions */ +static pthread_mutex_t functions_lock; + +/* Helper macro for vomiting */ +#define VOMIT_ON_FAILURE(a) do { if (0 != (a)) { int err = errno; fprintf(stderr, "%s failed on line %d in file %s: %d (%s)\n", #a, __LINE__, __FILE__, err, strerror(err)); abort(); }} while (0) + +static int kLockDepth = 0; +static char kLockFunction[1024]; + +/** + Lock and unlock the functions hash +*/ +static void lock_functions(const char *func) { + VOMIT_ON_FAILURE(pthread_mutex_lock(&functions_lock)); + if (! kLockDepth++) { + strcat(kLockFunction, func); + } +} + +static void unlock_functions(void) { + if (! --kLockDepth) { + memset(kLockFunction, 0, sizeof kLockFunction); + } + VOMIT_ON_FAILURE(pthread_mutex_unlock(&functions_lock)); +} + +#define LOCK_FUNCTIONS() lock_functions(__FUNCTION__) +#define UNLOCK_FUNCTIONS() unlock_functions() + /** Kludgy flag set by the load function in order to tell function_add @@ -93,11 +126,15 @@ static int load( const wchar_t *name ) int was_autoload = is_autoload; int res; function_internal_data_t *data; - data = (function_internal_data_t *)hash_get( &function, name ); - if( data && !data->is_autoload ) + LOCK_FUNCTIONS(); + data = (function_internal_data_t *)hash_get( &functions, name ); + if( data && !data->is_autoload ) { + UNLOCK_FUNCTIONS(); return 0; - - is_autoload = 1; + } + UNLOCK_FUNCTIONS(); + + is_autoload = 1; res = parse_util_load( name, L"fish_function_path", &function_remove, @@ -113,13 +150,13 @@ static int load( const wchar_t *name ) static void autoload_names( array_list_t *out, int get_hidden ) { int i; - + array_list_t path_list; const wchar_t *path_var = env_get( L"fish_function_path" ); - + if( ! path_var ) return; - + al_init( &path_list ); tokenize_variable_array( path_var, &path_list ); @@ -129,15 +166,15 @@ static void autoload_names( array_list_t *out, int get_hidden ) DIR *dir = wopendir( ndir ); if( !dir ) continue; - - struct wdirent *next; - while( (next=wreaddir(dir))!=0 ) + + wcstring name; + while (wreaddir(dir, name)) { - wchar_t *fn = next->d_name; + const wchar_t *fn = name.c_str(); wchar_t *suffix; if( !get_hidden && fn[0] == L'_' ) continue; - + suffix = wcsrchr( fn, L'.' ); if( suffix && (wcscmp( suffix, L".fish" ) == 0 ) ) { @@ -148,7 +185,7 @@ static void autoload_names( array_list_t *out, int get_hidden ) DIE_MEM(); al_push( out, dup ); } - } + } closedir(dir); } al_foreach( &path_list, &free ); @@ -157,9 +194,15 @@ static void autoload_names( array_list_t *out, int get_hidden ) void function_init() { - hash_init( &function, + hash_init( &functions, &hash_wcs_func, &hash_wcs_cmp ); + + pthread_mutexattr_t a; + VOMIT_ON_FAILURE(pthread_mutexattr_init(&a)); + VOMIT_ON_FAILURE(pthread_mutexattr_settype(&a,PTHREAD_MUTEX_RECURSIVE)); + VOMIT_ON_FAILURE(pthread_mutex_init(&functions_lock, &a)); + VOMIT_ON_FAILURE(pthread_mutexattr_destroy(&a)); } /** @@ -172,8 +215,10 @@ static void clear_entry( void *key, void *value ) void function_destroy() { - hash_foreach( &function, &clear_entry ); - hash_destroy( &function ); + LOCK_FUNCTIONS(); + hash_foreach( &functions, &clear_entry ); + hash_destroy( &functions ); + UNLOCK_FUNCTIONS(); } @@ -182,13 +227,13 @@ void function_add( function_data_t *data ) int i; wchar_t *cmd_end; function_internal_data_t *d; - + CHECK( data->name, ); CHECK( data->definition, ); - + LOCK_FUNCTIONS(); function_remove( data->name ); - - d = halloc( 0, sizeof( function_internal_data_t ) ); + + d = (function_internal_data_t *)halloc( 0, sizeof( function_internal_data_t ) ); d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos )-1; d->definition = halloc_wcsdup( d, data->definition ); @@ -201,21 +246,162 @@ void function_add( function_data_t *data ) al_push( d->named_arguments, halloc_wcsdup( d, (wchar_t *)al_get( data->named_arguments, i ) ) ); } } - + cmd_end = d->definition + wcslen(d->definition)-1; - + d->description = data->description?halloc_wcsdup( d, data->description ):0; d->definition_file = intern(reader_current_filename()); d->is_autoload = is_autoload; d->shadows = data->shadows; - - hash_put( &function, intern(data->name), d ); - + + hash_put( &functions, intern(data->name), d ); + for( i=0; ievents ); i++ ) { event_add_handler( (event_t *)al_get( data->events, i ) ); } + UNLOCK_FUNCTIONS(); +} +static int function_exists_internal( const wchar_t *cmd, int autoload ) +{ + int res; + CHECK( cmd, 0 ); + + if( parser_keywords_is_reserved(cmd) ) + return 0; + + LOCK_FUNCTIONS(); + if ( autoload ) load( cmd ); + res = (hash_get(&functions, cmd) != 0 ); + UNLOCK_FUNCTIONS(); + return res; +} + +int function_exists( const wchar_t *cmd ) +{ + return function_exists_internal( cmd, 1 ); +} + +int function_exists_no_autoload( const wchar_t *cmd ) +{ + return function_exists_internal( cmd, 0 ); +} + +void function_remove( const wchar_t *name ) +{ + void *key; + void *dv; + function_internal_data_t *d; + event_t ev; + + CHECK( name, ); + + LOCK_FUNCTIONS(); + hash_remove( &functions, + name, + &key, + &dv ); + + d=(function_internal_data_t *)dv; + + if( !key ) { + UNLOCK_FUNCTIONS(); + return; + } + + ev.type=EVENT_ANY; + ev.function_name=name; + event_remove( &ev ); + + halloc_free( 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 ); + } + UNLOCK_FUNCTIONS(); +} + +const wchar_t *function_get_definition( const wchar_t *name ) +{ + function_internal_data_t *data; + + CHECK( name, 0 ); + LOCK_FUNCTIONS(); + load( name ); + data = (function_internal_data_t *)hash_get( &functions, name ); + UNLOCK_FUNCTIONS(); + if( data == 0 ) + return 0; + return data->definition; +} + +array_list_t *function_get_named_arguments( const wchar_t *name ) +{ + function_internal_data_t *data; + + CHECK( name, 0 ); + LOCK_FUNCTIONS(); + load( name ); + data = (function_internal_data_t *)hash_get( &functions, name ); + UNLOCK_FUNCTIONS(); + if( data == 0 ) + return 0; + return data->named_arguments; +} + +int function_get_shadows( const wchar_t *name ) +{ + function_internal_data_t *data; + + CHECK( name, 0 ); + LOCK_FUNCTIONS(); + load( name ); + data = (function_internal_data_t *)hash_get( &functions, name ); + UNLOCK_FUNCTIONS(); + if( data == 0 ) + return 0; + return data->shadows; +} + + +const wchar_t *function_get_desc( const wchar_t *name ) +{ + function_internal_data_t *data; + + CHECK( name, 0 ); + + load( name ); + LOCK_FUNCTIONS(); + data = (function_internal_data_t *)hash_get( &functions, name ); + UNLOCK_FUNCTIONS(); + if( data == 0 ) + return 0; + + return _(data->description); +} + +void function_set_desc( const wchar_t *name, const wchar_t *desc ) +{ + function_internal_data_t *data; + + CHECK( name, ); + CHECK( desc, ); + + load( name ); + LOCK_FUNCTIONS(); + data = (function_internal_data_t *)hash_get( &functions, name ); + UNLOCK_FUNCTIONS(); + if( data == 0 ) + return; + + data->description = halloc_wcsdup( data, desc ); } int function_copy( const wchar_t *name, const wchar_t *new_name ) @@ -226,11 +412,11 @@ int function_copy( const wchar_t *name, const wchar_t *new_name ) CHECK( name, 0 ); CHECK( new_name, 0 ); - orig_d = (function_internal_data_t *)hash_get(&function, name); + orig_d = (function_internal_data_t *)hash_get(&functions, name); if( !orig_d ) return 0; - d = halloc(0, sizeof( function_internal_data_t ) ); + d = (function_internal_data_t *)halloc(0, sizeof( function_internal_data_t ) ); d->definition_offset = orig_d->definition_offset; d->definition = halloc_wcsdup( d, orig_d->definition ); if( orig_d->named_arguments ) @@ -249,129 +435,11 @@ int function_copy( const wchar_t *name, const wchar_t *new_name ) d->is_autoload = 0; } - hash_put( &function, intern(new_name), d ); + hash_put( &functions, intern(new_name), d ); return 1; } - -int function_exists( const wchar_t *cmd ) -{ - - CHECK( cmd, 0 ); - - if( parser_keywords_is_reserved(cmd) ) - return 0; - - load( cmd ); - return (hash_get(&function, cmd) != 0 ); -} - -void function_remove( const wchar_t *name ) -{ - void *key; - void *dv; - function_internal_data_t *d; - event_t ev; - - CHECK( name, ); - - hash_remove( &function, - name, - &key, - &dv ); - - d=(function_internal_data_t *)dv; - - if( !key ) - return; - - ev.type=EVENT_ANY; - ev.function_name=name; - event_remove( &ev ); - - halloc_free( 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 *name ) -{ - function_internal_data_t *data; - - CHECK( name, 0 ); - - load( name ); - data = (function_internal_data_t *)hash_get( &function, name ); - if( data == 0 ) - return 0; - return data->definition; -} - -array_list_t *function_get_named_arguments( const wchar_t *name ) -{ - function_internal_data_t *data; - - CHECK( name, 0 ); - - load( name ); - data = (function_internal_data_t *)hash_get( &function, name ); - if( data == 0 ) - return 0; - return data->named_arguments; -} - -int function_get_shadows( const wchar_t *name ) -{ - function_internal_data_t *data; - - CHECK( name, 0 ); - - load( name ); - data = (function_internal_data_t *)hash_get( &function, name ); - if( data == 0 ) - return 0; - return data->shadows; -} - - -const wchar_t *function_get_desc( const wchar_t *name ) -{ - function_internal_data_t *data; - - CHECK( name, 0 ); - - load( name ); - data = (function_internal_data_t *)hash_get( &function, name ); - if( data == 0 ) - return 0; - - return _(data->description); -} - -void function_set_desc( const wchar_t *name, const wchar_t *desc ) -{ - function_internal_data_t *data; - - CHECK( name, ); - CHECK( desc, ); - - load( name ); - data = (function_internal_data_t *)hash_get( &function, name ); - if( data == 0 ) - return; - - data->description = halloc_wcsdup( data, desc ); -} - /** Search arraylist of strings for specified string */ @@ -381,19 +449,19 @@ static int al_contains_str( array_list_t *list, const wchar_t * str ) CHECK( list, 0 ); CHECK( str, 0 ); - + for( i=0; i