Closed JUNNETWORKS closed 3 years ago
Originally posted by @torus in https://github.com/torus/42-minishell/issues/42#issuecomment-823048679
あ、#27 がこれのつもりでした。展開は t_command_invocation
を作る段階でやっておく必要があります。変数の展開後にスペースが含まれている処理が必要なんですが、これはコマンドの引数の場合とリダイレクトのファイル名の場合で必要な処理が変わります。
たとえば、$A="ABC DEF"
のとき、単に $A
というコマンドラインの場合は、abc
というコマンドと def
という引数に展開されますが、echo > $A
のときにはエラーを発生させる必要があります。
Originally posted by @torus in https://github.com/torus/42-minishell/issues/42#issuecomment-823042722
パースの時点でエラーとなっているっぽくて, そもそもコマンド実行がされない(リダイレクトで指定されたファイルが作られてない)
環境変数の値が空文字列の場合もエラー
環境変数が存在しない場合もエラー
環境変数が空文字列
環境変数が存在しない
環境変数にスペースが含まれている
環境変数にリダイレクト記号がある
リダイレクトの途中でスペース区切りの環境変数が入っている
リダイレクトが複数あり, その中に不正なリダイレクト先が含まれる場合, そのリダイレクト先まではファイルが作られるが, 不正なリダイレクト先移行のリダイレクト先はファイルが作成されない. (画像では $ABC="abc def"
)
ASTからcmdinvoに変換するタイミングか, リダイレクトで指定された各ファイルのopen失敗したタイミングでエラーを返すかがわからん...
ダブルクオーテーションで囲むと正しく動く.
本当にどこでエラーを判定すればよいのだ...
最初にぼくがイメージしていた動作は次のようなものです。これで多分ひととおりカバーできていると思うんですが、ダメなケースはありますかね?
TOKTYPE_EXPANDABLE
と TOKTYPE_EXPANDABLE_QUOTED
に対してのみ行います。
TOKTYPE_EXPANDABLE
に対して ft_split をして、空白が含まれていれば複数の引数に分割します。TOKTYPE_EXPANDABLE_QUOTED
に対しては split してはいけないことに注意してください。例:$A="a b"
のとき
x$A"y z"
は次のトークン列になります:
x$A
)y z
)次に EXPANDABLE の中に $
が含まれているので、展開します。すると次のようになります:
xa b
)y z
)さらに、EXPANDABLE について空白で区切ります。すると 1 個目の EXPANDABLE が 2 個に別れて、最後の要素は次の y z
とくっつきます:
xa
by z
y z
は QUOTED なので、split はしないことに注意してください。
これにより、最終的に 2 個の引数列に展開されます。
ちなみに、変数の展開はパースのあとで行われるので、>
などの文字も特別扱いはしません。
$ export A='>'
$ echo $A
>
$ echo hello > $A
$ ls
'>'
$ cat '>'
hello
$
最初にぼくがイメージしていた動作は次のようなものです。これで多分ひととおりカバーできていると思うんですが、ダメなケースはありますかね?
共通の動作
変数展開は
TOKTYPE_EXPANDABLE
とTOKTYPE_EXPANDABLE_QUOTED
に対してのみ行います。
- 変数がセットされていないときは単なる空文字列に展開します。
- その次に展開済みの
TOKTYPE_EXPANDABLE
に対して ft_split をして、空白が含まれていれば複数の引数に分割します。TOKTYPE_EXPANDABLE_QUOTED
に対しては split してはいけないことに注意してください。例:
$A="a b"
のときx$A"y z"
は次のトークン列になります:
- EXPANDABLE (
x$A
)- EXPANDABLE_QUOTED (
y z
)次に EXPANDABLE の中に
$
が含まれているので、展開します。すると次のようになります:
- EXPANDABLE (
xa b
)- EXPANDABLE_QUOTED (
y z
)さらに、EXPANDABLE について空白で区切ります。すると 1 個目の EXPANDABLE が 2 個に別れて、最後の要素は次の
y z
とくっつきます:
xa
by z
y z
は QUOTED なので、split はしないことに注意してください。これにより、最終的に 2 個の引数列に展開されます。
リダイレクト先の処理
- 展開後の引数の数がちょうど 1 個でない場合(ゼロまたは複数のとき): 「曖昧なリダイレクト」のエラー
- 展開結果がちょうど 1 個のときはファイルをオープンして、失敗したらエラー
以下のケースの場合, 上記のロジックだと上手く行かないと思います.
$ABC=" a b "
で, 入力が $ABC"c d"
. この時出力は
a
b
c d
のようになるはずですが, ひさいさんのおっしゃってたロジックだと
a
bc d
のようになると思います.
おお確かに。ft_split する時に、文字列の先頭と末尾が空白でないか確かめる必要がありますね。
リダイレクションに環境変数が渡されていた場合, コマンドの引数の場合と少し違う挙動をするので別Issueを立てた.