What does the cowsay?

Recall that cowsay is a program with which you can make a cow say something, in ASCII art, via command-line arguments. And it’s pre-installed for you at code.cs50.io. For instance, try executing the below in your terminal window:

cowsay "This is CS50"

cowsay also supports other animals, including a bunny:

cowsay -f bunny "This is CS50"

And an elephant:

cowsay -f elephant "This is CS50"

Even a dragon:

cowsay -f dragon "This is CS50"

The source code for cowsay is publicly available on GitHub, a website for sharing and collaborating on code. In fact, you can view it in this repository.

For this problem, you’ll read the source code for cowsay, written in a language called Perl, and infer how the program works. (Perl was the language in which David implemented that first website for Frosh IMs!) Even though you yourself might not know any Perl, you don’t need to in order to understand the basics!

Open up the cowsay file itself at github.com/tnalpgge/rank-amateur-cowsay/blob/99058032db7cafbc507a3fbe8cae6be2d9f65ee3/cowsay, wherein the main part of cowsay is written. The code might look cryptic at first. (Such is Perl!) But it’s in these lines where the main action happens:

&slurp_input;
$Text::Wrap::columns = $opts{'W'};
@message = ($opts{'n'} ? expand(@message) :
	    split("\n", fill("", "", @message)));
&construct_balloon;
&construct_face;
&get_cow;
print @balloon_lines;
print $the_cow;
  1. (2 points.) Notice how some lines begin with &, which doesn’t have the same meaning in Perl as it has in C. In no more than one sentence, what is the meaning of &?

Next, notice these lines atop the same file:

$version = "3.03";
$progname = basename($0);
$eyes = "oo";
$tongue = "  ";
  1. (2 points.) Notice how those lines (and others) begin with $. In no more than one sentence, what is the meaning of $?

Now, look at these lines:

&display_usage if $opts{'h'};
&list_cowfiles if $opts{'l'};

Try running cowsay with:

cowsay -h

And then with:

cowsay -l
  1. (2 points.) In no more than two sentences, what is the meaning of if $opts{'h'}? What about if $opts{'l'}?
  2. (2 points.) In no more than one sentence, what might happen if we changed &list_cowfiles if $opts{'l'} to &list_cowfiles if $opts{'q'}?

Having explored some of cowsay, let’s return to these lines, to which we’ve added line numbers this time for the sake of discussion:

1  &slurp_input;
2  $Text::Wrap::columns = $opts{'W'};
3  @message = ($opts{'n'} ? expand(@message) :
	      split("\n", fill("", "", @message)));
4  &construct_balloon;
5  &construct_face;
6  &get_cow;
7  print @balloon_lines;
8  print $the_cow;
  1. (4 points.) In no more than eight sentences, one per line, explain—top-to-bottom—what that code does.

Notice how the cows directory contains a variety of .cow files. These .cow files can be used to add a character to the cowsay program.

  1. (2 points.) Based on the information you gather from other .cow files, create your own valid .cow file. You can create anything you’d like, so long as the file would work when installed!

To test your .cow file, you need only specify the “relative path” to the file after cowsay’s -f flag. Suppose that a file called test.cow is located in your present folder—that is, you can see test.cow when you execute ls. To test cowsay with test.cow, you may run:

cowsay -f ./test.cow "Hello, world!"

If you don’t see your file displaying as intended, double check that your terminal and test.cow are indeed in the same folder! Otherwise, it may be an issue with your .cow file itself!

Should you like to install your .cow file officially, you can cp (copy) it to the folder in which the rest of cowsay’s .cow files are stored. First execute

cd

to bring yourself to your home directory.

Next execute

sudo chmod -R 777 /usr/share/cowsay/cows/

to give yourself and others “read, write, and execute permissions” for the files in /usr/share/cowsay/cows—the location at which cowsay’s .cow files are stored.

Next, cd into the folder (if any!) in which you’ve stored your .cow file. Afterwards, run

cp MYCOW.cow /usr/share/cowsay/cows/

to copy your file to the location at which .cow files are to be installed, replacing MYCOW.cow with your own filename. Now, running

cowsay -f MYCOW "Hello, world!"

should work as intended, so long as you substitute the name of your own “cow” for MYCOW!