CS253 HW2: Shell                
Changes                
The output of the last example was previously truncated.
                
Description                
For this assignment, you will write a primitive shell that
will read & execute commands using functional notation, sort of like
sin(x ) in
math.
                
Input                
Read & execute commands from each filename argument.
If no arguments are given, read & execute commands from standard input.
                
Input format                
The input will be a series of lines. Each line will consist of a number
of whitespace-separated words. The first word in a line will be the
command, the following words will be arguments. Ignore lines that
contain no words.
                
A backslash escapes the next character, making it not special. The
backslash itself does not become part of the word. For example,
foo\ bar
is treated as the seven-character word foo bar
,
S\pock\(o\)
is treated as the eight-character word Spock(o)
,
\ Kirk\
is treated as the six-character word Kirk
, and
Bo\nes
is treated as the five-letter word Bones
. The
effect of a backslash as the last character of a line is undefined.
Unlike C++, \n
and \t
are not translated into newline and
tab. In the examples below, the echo program is doing that
translation, not hw2
.
                
(
and )
are always words by themselves, even if they occur
next to other text, unless escaped.
                
A non-empty input line must be of this form:
command(
optional arguments)
for example:
echo(hi there)
If an input line is not of this form,
produce an error message and stop the program.
                
No special shell syntax is recognized. For example,
the characters #*[];'"><|&~
have no particular significance.
                
Language                
I call “(
” and “)
” parentheses, or parens.
Some people call them brackets.
                
Executing commands                
The file
~cs253/Example/execute.cc
contains this function:
                
bool execute(vector<string> command);
It executes a command with arguments, returning true
iff it succeeds. It also contains a main() that
you should exclude from your program. You may copy code from this file
and add it to your main.cc
.
                
Of course, execute()
doesn’t want those opening and closing parens.
They shouldn’t be in the vector that you pass to execute()
.
If the input command is echo(alpha beta\ gamma delta)
,
then the vector passed to execute()
should contain:
-
echo
alpha
beta gamma
delta
Sample Runs                
Here are sample runs, where “%
” is my prompt.
% cat CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(hw2)
# Are we in the wrong directory?
if(CMAKE_SOURCE_DIR MATCHES "[Hh][Ww]([0-9])$")
if(PROJECT_NAME MATCHES "[^${CMAKE_MATCH_1}]$")
message(FATAL_ERROR "Building ${PROJECT_NAME} in ${CMAKE_SOURCE_DIR}")
endif()
endif()
# Using -Wall is required:
add_compile_options(-Wall)
# These compile flags are highly recommended, but not required:
add_compile_options(-Wextra -Wpedantic)
# Optional super-strict mode:
add_compile_options(-fmessage-length=80 -fno-diagnostics-show-option
-fstack-protector-all -g -O3 -std=c++17 -Walloc-zero -Walloca
-Wctor-dtor-privacy -Wduplicated-cond -Wduplicated-branches
-Werror -Wextra-semi -Wfatal-errors -Winit-self -Wlogical-op
-Wold-style-cast -Wshadow -Wunused-const-variable=1
-Wzero-as-null-pointer-constant)
# add_compile_options must be BEFORE add_executable.
# Create the executable from the source file main.cc:
add_executable(${PROJECT_NAME} main.cc)
# Create a tar file every time:
add_custom_target(${PROJECT_NAME}.tar ALL COMMAND
tar -cf ${PROJECT_NAME}.tar *.cc CMakeLists.txt)
% cmake . && make
… cmake output appears here …
… make output appears here …
% cat data
date()
echo(Good so far.)
echo ( \ 1 < 2 * 3 + 177777 &\& 44 > 5 )
echo(-e 1\) dogs\\n2\) cats)
sync()
echo(-e supercali\\n\\t\(fragilistic\)\\n\\t\\texpialidocious)
date(+%F\ %T)
goofy(this will not work)
echo(1111111111111111)
% ./hw2 <data
Wed Feb 17 16:34:28 MST 2021
Good so far.
1 < 2 * 3 + 177777 && 44 > 5
1) dogs
2) cats
supercali
(fragilistic)
expialidocious
2021-02-17 16:34:28
./hw2: can’t run: goofy(this will not work)
% cat d1
date ( )
% cat d2
echo(Hello from d2!)
% ./hw2 d1 d2
Wed Feb 17 16:34:28 MST 2021
Hello from d2!
% echo -e ' \n\r\techo\f(\talpha\fbeta\v1114111) ' | ./hw2
alpha beta 1114111
Debugging                
If you encounter “STACK FRAME LINK OVERFLOW”, then try this:
export STACK_FRAME_LINK_OVERRIDE=ffff-ad921d60486366258809553a3db49a4a
Requirements                
- Error messages:
- go to standard error
- include the program name as given by
argv[0]
.
- Produce an error message and stop the program if:
- second word is not an open paren
- last word is not a closing paren
- unescaped parentheses anywhere but a left paren as the
second word and a right paren as the last word
- a filename argument can’t be opened for reading
(the error message must contain the offending filename)
execute()
indicates a problem
(the error message must also contain the entire original bad line).
- You may not use C-style I/O facilities,
such as printf(), scanf(), fopen(), and getchar().
- You may not use dynamic memory via new, delete,
malloc(), calloc(), realloc(), free(), strdup(), etc.
- It’s ok to implicitly use dynamic memory via containers
such as string or vector.
- You may not use the istream::eof() method.
- No global variables.
- Except for an optional single global string called
program_name
containing argv[0]
.
- For readability, don’t use ASCII int constants (
65
)
instead of char constants ('A'
) for printable characters.
- We will compile your program like this:
cmake . && make
- If that generates warnings, you will lose a point.
- If that generates errors, you will lose all points.
- There is no automated testing/pre-grading/re-grading.
- Test your code yourself. It’s your job.
- Even if you only change it a little bit.
- Even if all you do is add a comment.
- Test with the CSU compilers, not just your laptop’s compiler.
If you have any questions about the requirements, ask.
In the real world, your programming tasks will almost always be
vague and incompletely specified. Same here.
                
Tar file                
- For each assignment this semester, you will create a tar file,
and turn it in.
- The tar file for this assignment must be called:
hw2.tar
- It must contain:
- source files (
*.cc
)
- header files (
*.h
) (if any)
CMakeLists.txt
- This command must produce the program
hw2
(note the dot):
cmake . && make
- At least
-Wall
must be used every time g++ runs.
How to submit your work:                
In Canvas, check in the
file
hw2.tar
to the assignment “HW2”.
It’s due 10:00:00ᴘᴍ MT Saturday, with a 24-hour late period for a 25% penalty.
                
How to receive negative points:                
Turn in someone else’s work.