This is a minishell, a 42 school project that reproduce a basic shell (CLI).
We use an AST! (Abstract Syntax Tree)
We did all the bonuses except the HERE_DOCUMENT
(<<
operator).
# Compile minishell with the Makefile
make -j4
# Start the shell
./minishell
-
Line editing (← / →)
-
History (↑ / ↓)
-
Copy (start: CTRL+K | stop : CTRL+K)
-
Past (CTRL+P)
-
Cut (start: CTRL+K | stop : CTRL+L)
-
Built-ins
echo
-n
flag
cd
(absolute/relative path + ~/-)pwd
export
unset
env
exit
-
Launch binaries from
$PATH
(of course) -
Semicolons (
;
) -
Pipes (
|
) -
Quotes (
"
,'
) -
Redirections (
>
,>>
,<
) -
Signals (
CTRL-C
/CTRL-\
/CTRL-D
) -
AND
operator (&&
),OR
operator (||
) -
Parenthesis priority, creates a subshell (
(cmd)
) -
Environment variables (ex:
$PATH
) +$?
-
Go start of line (CTRL+A or HOME)
-
Go end of line (CTRL+E or END)
-
Navigate between words (CTRL+← and CTRL+→)
-
Navigate between lines (CTRL+↑ and CTRL+↓)
-
Multiline (giving a line with unclosed quote (
"
,'
) or backslash (\
) prints a PS2 until the line is finished) -
Pathname expansion. Wildcard
*
(unquoted) -
Update
SHLVL
, the promptsPS1
andPS2
-
Ambiguous Redirections
I] Get the next command line:
- The terminal is put in raw mode in order to have an exact bash-like input interface.
II] Tokenisation (aka Lexing):
- Create tokens with the Lexer (lexical analizer).
If the user's input isn't finished (unmatching quotes or parenthesis, backslash): prompt a PS2 until it's ok.
- Categorizing the tokens as we create them from left to right.
III] Parsing:
- Process the tokens according to a grammar and builds an AST of all the commands to run.
Thanks to the operators, we can identify the beginning and end of jobs.
IV] Word expansion:
- Tild expansion (
~
) is done at the beginning of a potential path, or after the first '=' sign that is in between a label=value pattern:
$ echo salut=~:~/Projects:~/hey # => salut=/HOME/charmstr:/HOME/charmstr/Projects:/HOME/charmstr/hey
-
Parameter expansion. ex:
$PWD
becomes/home/...
-
Field splitting, applied to the parameter expansion, only if in an unquoted section of text.
$ export foo="one two"
$ echo $foo # Spaces are removed, expansion got split in two: one two
$ echo "$foo" # Spaces aren't removed. still one unique string: one two
note: new strings that comes from an expansion are marked as protected against late quote removal.
- Pathname expansion
$ ls # foo foobar foobar2
$ echo fo* # -> foo foobar foobar2
note: it only applies if the *
is unquoted, unescaped, etc.
- Quote removal
V] Redirections are performed if necessary.
- They are separated from the argv, but kept in the order of appearance. Redirecting stdin and stdout.
VI] Commands are executed. A new prompt is displayed.