CS253: Software Development with C++

Spring 2021

HW 6

CS253 HW6: Recursion!                

Batman #8, 1942

Changes                

Updates to the assignment will be noted here. None yet!                 

Description                

Remember composition of functions? In mathematics, if you want to define z as the square root of the sine of x, you don’t have to do all this:                 

y = sin x
z = sqrt y

Instead, you simply write z = sqrt sin x . We all understand that this applies the sine function to x, and then applies the square root function to that result.                 

We’re going to do a similar thing with commands. We’re going to feed the output of one or more commands into another command, feed that output into another command, and so on.                 

For this assignment, you will improve your work from HW4. Instead of merely running a single command with arguments, you will run several commands, and feed the output of the inner commands to the output commands, nested to an arbitrary depth.                 

For example, this input:                 

    sort(echo(beta) echo(delta) echo(alpha))

would execute echo(beta), producing beta. Similarly, echo(delta) and echo(alpha) would produce delta and alpha. The output of those echo commands would be placed into temporary files. Then, sort would be executed, with the three temporary files as arguments, and would produce the standard output:                 

    alpha
    beta
    delta

Each argument to a program can be either a word, as defined in HW4, or another program. It it’s a program, run that program with its arguments (which might themselves be programs), put its output into a temporary file, and use the temporary file as an argument to the upper program.                 

Temporary files                

You may create as many temporary files as you wish, but all temporary files must be cleaned up by calling remove(). However, if the program terminates with an error (e.g., from an improperly-formatted input line) then it’s ok (but not admirable) to leave temporary files.                 

Temporary files must be in the current directory, and must be of the form tempnumber.tmp. For example, temp1.tmp, temp0177777.tmp, and temp3276799.tmp are all valid temporary file names.                 

New execute() function                

The file ~cs253/Example/execute2.cc provides a new version of the function execute:                 

    bool execute(vector<string> command, string outfile="");

It is identical to the previous version, except for the optional additional argument. If that argument is provided, it must be the path of an output file, and the standard output of the command will be written to that file. If the file does not exist, it will be created. If it already exists, it will be overwritten.                 

You may copy this function into your code, modify it as you wish, or ignore it completely.                 

This is the Colorado State University CS253 web page https://www.cs.colostate.edu/~cs253/Spring21/HW6 fetched by unknown <unknown> with Linux UID 65535 at 2024-04-20T00:29:04 from IP address 18.117.182.179. Registered CSU students are permitted to copy this web page for personal use, but it is forbidden to repost the information from this web page to the internet. Doing so is a violation of the rules in the CS253 syllabus, will be considered cheating, and will get you an F in CS253.

Sample Runs                

Here are sample runs, where % is my prompt.                 

% cat data1
cat(/etc/hostname)
echo(===)
sort(date() /etc/hostname)
% ./hw6 data1
beethoven
===
beethoven
Sun Apr  4 23:35:29 MDT 2021
% cat data2
cat(sort(cat(sort(cat(sort(echo(f\oo)))))))
% ./hw6 <data2
foo
% cat data3
sort(echo(Zeta) sed(s/[0-9]/*/g date()))
ps(-H)
% ./hw6 data3
Sun Apr  * **:**:** MDT ****
Zeta
    PID TTY          TIME CMD
 194269 pts/0    00:00:00 bash
 195829 pts/0    00:00:00   hw6
 195834 pts/0    00:00:00     ps

Hints                

For my implementation, I wrote a recursive function called command:                 

    void command(Words w,		// input line broken into words
        	 size_t start,		// where to start looking
        	 size_t end,		// where to stop looking
        	 bool verbose,		// from the -v argument
        	 size_t max_args,	// from the -m argument
        	 string outfile = "");	// optional output file

This function handles an entire input line, already parsed into a Words object. It accumulates arguments and calls execute(). If an argument is of the form word(), then it’s a sub-process, handled by a recursive call to command().                 

For example, given this input line of 7 words:                 

    sort(/etc/hostname date())

The initial call to command might be:                 

    command(Words, 0, 7, …)

This would generate a recursive call to parse & execute date(), and place the output, “Sat Apr 20 00:29:04 MDT 2024” in temp1.tmp:                 

    command(Words, 3, 6, …, temp1.tmp)

This would, effectively, rewrite the input line as:                 

    sort(/etc/hostname temp1.tmp)

Then, it would execute sort with the arguments /etc/hostname and temp1.tmp, producing this output (your computer name will vary):                 

    beethoven
    Sat Apr 20 00:29:04 MDT 2024

You may copy this technique, or ignore it completely.                 

Debugging                

If you encounter “STACK FRAME LINK OVERFLOW”, then try this:

    export STACK_FRAME_LINK_OVERRIDE=ffff-ad921d60486366258809553a3db49a4a

Requirements                

All requirements from HW4 still apply, plus:

Tar file                

    cmake . && make

How to submit your work:                

In Canvas, check in the file hw6.tar to the assignment “HW6”. 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.