From ae44c879e8f57afea9511c084f4485842fdfd237 Mon Sep 17 00:00:00 2001 From: Yann Regis-Gianas Date: Wed, 27 Mar 2019 20:54:41 +0100 Subject: [PATCH] Fix #88. --- src/CST.ml | 1 + src/prelexerState.ml | 1 + src/tildePrefix.ml | 63 ++++++++++++++ .../2.6.1-tilde-prefix/login.sh | 2 + .../2.6.1-tilde-prefix/login.sh.expected | 87 +++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 src/tildePrefix.ml create mode 100644 tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh create mode 100644 tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh.expected diff --git a/src/CST.ml b/src/CST.ml index 9185869d..6befa775 100644 --- a/src/CST.ml +++ b/src/CST.ml @@ -325,6 +325,7 @@ and word_component = | WordAssignmentWord of assignment_word | WordDoubleQuoted of word | WordSingleQuoted of word + | WordTildePrefix of string | WordLiteral of string | WordVariable of variable | WordGlobAll (* asterisk *) diff --git a/src/prelexerState.ml b/src/prelexerState.ml index f0a9940f..ed5f870d 100644 --- a/src/prelexerState.ml +++ b/src/prelexerState.ml @@ -384,6 +384,7 @@ let return ?(with_newline=false) lexbuf (current : prelexer_state) tokens = | QuotingMark _ -> [] ) (buffer current))) in + let csts = TildePrefix.recognize csts in [Pretoken.PreWord (w, csts)] in let tokens = if with_newline then tokens @ [Pretoken.NEWLINE] else tokens in diff --git a/src/tildePrefix.ml b/src/tildePrefix.ml new file mode 100644 index 00000000..73955636 --- /dev/null +++ b/src/tildePrefix.ml @@ -0,0 +1,63 @@ +(**************************************************************************) +(* -*- tuareg -*- *) +(* *) +(* Copyright (C) 2017,2018,2019 Yann RĂ©gis-Gianas, Nicolas Jeannerod, *) +(* Ralf Treinen. *) +(* *) +(* This is free software: you can redistribute it and/or modify it *) +(* under the terms of the GNU General Public License, version 3. *) +(* *) +(* Additional terms apply, due to the reproduction of portions of *) +(* the POSIX standard. Please refer to the file COPYING for details. *) +(**************************************************************************) + +(*specification + + A "tilde-prefix" consists of an unquoted character at the + beginning of a word, followed by all of the characters preceding + the first unquoted in the word, or all the characters in + the word if there is no . In an assignment (see XBD Variable + Assignment), multiple tilde-prefixes can be used: at the beginning + of the word (that is, following the of the + assignment), following any unquoted , or both. A + tilde-prefix in an assignment is terminated by the first unquoted + or . If none of the characters in the tilde-prefix + are quoted, the characters in the tilde-prefix following the + are treated as a possible login name from the user + database. A portable login name cannot contain characters outside + the set given in the description of the LOGNAME environment + variable in XBD Other Environment Variables. If the login name is + null (that is, the tilde-prefix contains only the tilde), the + tilde-prefix is replaced by the value of the variable HOME. If HOME + is unset, the results are unspecified. Otherwise, the tilde-prefix + shall be replaced by a pathname of the initial working directory + associated with the login name obtained using the getpwnam() + function as defined in the System Interfaces volume of + POSIX.1-2017. If the system does not recognize the login name, the + results are undefined. + +*) +open CST + +let find_login s = + match Str.(split (regexp "/") s) with + | login :: rem -> [WordTildePrefix login; WordLiteral (String.concat "/" rem)] + | _ -> assert false (* Because there is slash, or not. *) + +let rec make_tilde_prefix_explicit rhs_assignment = function + | (WordLiteral s) as cst when s <> "" -> + if s.[0] = '~' then ( + if rhs_assignment then + let s = Str.(split (regexp ":") s) in + List.(flatten (map find_login s)) + else + find_login s + ) else [cst] + | WordAssignmentWord (name, Word (s, csts)) -> + let csts = recognize ~rhs_assignment:true csts in + [WordAssignmentWord (name, Word (s, csts))] + | cst -> + [cst] + +and recognize ?(rhs_assignment=false) csts = + List.(flatten (map (make_tilde_prefix_explicit rhs_assignment) csts)) diff --git a/tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh b/tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh new file mode 100644 index 00000000..5f12c607 --- /dev/null +++ b/tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh @@ -0,0 +1,2 @@ +echo ~knuth/foo/bar +X=~kn:~/bin:~darkvador/secret diff --git a/tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh.expected b/tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh.expected new file mode 100644 index 00000000..246a633f --- /dev/null +++ b/tests/good/2.6-word-expansions/2.6.1-tilde-prefix/login.sh.expected @@ -0,0 +1,87 @@ +[ + "Program_LineBreak_CompleteCommands_LineBreak", + [ "LineBreak_Empty" ], + [ + "CompleteCommands_CompleteCommands_NewlineList_CompleteCommand", + [ + "CompleteCommands_CompleteCommand", + [ + "CompleteCommand_CList", + [ + "CList_AndOr", + [ + "AndOr_Pipeline", + [ + "Pipeline_PipeSequence", + [ + "PipeSequence_Command", + [ + "Command_SimpleCommand", + [ + "SimpleCommand_CmdName_CmdSuffix", + [ + "CmdName_Word", + [ "Word", "echo", [ [ "WordName", "echo" ] ] ] + ], + [ + "CmdSuffix_Word", + [ + "Word", + "~knuth/foo/bar", + [ + [ "WordTildePrefix", "~knuth" ], + [ "WordLiteral", "foo/bar" ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ], + [ "NewLineList_NewLine" ], + [ + "CompleteCommand_CList", + [ + "CList_AndOr", + [ + "AndOr_Pipeline", + [ + "Pipeline_PipeSequence", + [ + "PipeSequence_Command", + [ + "Command_SimpleCommand", + [ + "SimpleCommand_CmdPrefix", + [ + "CmdPrefix_AssignmentWord", + [ + [ "Name", "X" ], + [ + "Word", + "~kn:~/bin:~darkvador/secret", + [ + [ "WordTildePrefix", "~kn" ], + [ "WordLiteral", "" ], + [ "WordTildePrefix", "~" ], + [ "WordLiteral", "bin" ], + [ "WordTildePrefix", "~darkvador" ], + [ "WordLiteral", "secret" ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ], + [ "LineBreak_Empty" ] +] \ No newline at end of file