Please send questions to
st10@humboldt.edu .
#!/usr/bin/perl -w
#######################################################
# expr_play
#
# try to permit a CS 131 student to "play" with simple
# C++ expressions including calls to functions they have
# already written and compiled.
#
# written by: Sharon M. Tuttle, st10@humboldt.edu
# last modified: 6-05-05 - emailing portion commented out
# (remove #email# comments if you would
# LIKE an e-mailed record of each student's
# sessions using this tool --- changing
# st10\@humboldt.edu
# to YOUR desired e-mail address)
# 9-17-03 - NOW HANDLES BOOL EXPR'S BETTER!
#######################################################
#----------------------------------------------------------
# subroutine to ensure that a y or n answer is given
#----------------------------------------------------------
sub get_y_or_n
{
chomp(my $response = <STDIN>);
while (($response ne "y") && ($response ne "n"))
{
print "please respond with y or n: ";
chomp($response = <STDIN>);
}
return $response;
}
#------------------------------------------------------------------
# subroutine to finish up the mail message (record of student's
# use of this tool) and send it to me;
# (1 parameter: a message you'd like to add to the end of the
# student's record before it is sent)
#------------------------------------------------------------------
sub finish_record
{
my($closing_note) = @_;
print RECORD "\n";
print RECORD " $closing_note\n";
print RECORD "\n";
chomp(my $end_time = `date`);
print RECORD " (end time: $end_time)\n";
print RECORD "\n";
close RECORD;
# thanks to Jeremy Miller for the how-to-email-in-Perl example...
open (MAIL, "|/usr/lib/sendmail st10\@humboldt.edu")
|| &HTMLdie("Couldn't send the mail!");
open RECORD, "< expr_play_record"
or die "Cannot open expr_play_record for reading: $!";
while (<RECORD>)
{
chomp(my $line = $_);
print MAIL "$line\n";
}
close (RECORD);
close (MAIL);
unlink expr_play_record;
}
#-----
# [email portions commented out 6-5-05, using #email#]
# PART 1: setting up the beginning of an e-mailed record
# of the student's use of this script;
#-----
use File::Basename;
print "----------------------------------------------\n";
print "Welcome to the REVISED version of expr_play!\n";
print " (circa 6-05-05)\n";
print "----------------------------------------------\n";
# grab info about who, where, and when for this execution ---
# to be included in email to me...
chomp(my $who = `whoami`);
chomp(my $where_path = `pwd`);
my $where = basename $where_path;
# create a file to eventually be mailed to me with a "record"
# of this student's attempts
#email#open RECORD, "> expr_play_record"
#email# or die "Cannot open expr_play_record for writing: $!";
#email#print RECORD "Subject: [cs131] expr_play from $who\n";
#email#print RECORD "\n";
#email#print RECORD "$who is running 9-17-03 expr_play in directory: $where\n";
#email#print RECORD " (whole path: $where_path)\n";
chomp(my $start_time = `date`);
#email#print RECORD " (start time: $start_time)\n";
#email#print RECORD "\n";
#-----
# PART 2: set up initial variables to help with compiling
# the eventual test program to be generated
#-----
# at this point, I know that certain #include's will be necessary for
# the eventual test program generated by this Perl script. I'll start
# these here, so that I can add to it if the user wants to use
# functions they've defined previously in the new function.
my $include_stmts = "#include <iostream>\n#include <cmath>\nusing namespace std;\n\n";
# for debugging purposes...
#print "initial \#include statements:\n";
#print "--------------------------\n";
#print "$include_stmts";
#print "--------------------------\n";
# Will additional .o files be needed for the compilation of the eventual
# test program? Just in case, start that empty string here;
my $addl_obj_files = "";
# for debugging purposes...
#print "initial .o files:\n";
#print "--------------------------\n";
#print "$addl_obj_files\n";
#print "--------------------------\n";
#-----
# PART 3: Are there any existing functions (currently limited
# to the current working directory) that the student wishes to
# be able to use in his/her new function? If so, get their names
# from the student, and set up what is required for their use
# in the new function to come.
#-----
print "\n";
print "Are there any already-created C++ functions (in the current \n";
print " working directory) which you would like to be able to use\n";
print " within C++ expressions?\n";
print " (type y if so, n if not)\n";
print "your answer: ";
my $reply = &get_y_or_n();
# get the names of already-created functions, set up for their use in
# the new function to come
my $other_desired_funct_names = "";
if ($reply eq "y")
{
print "\n";
print "*********************************************************\n";
print "NOTE: to test a function A, you need to give the names\n";
print " of ALL functions that A uses, as well as those that\n";
print " THEY use --- otherwise, the tests will fail.\n";
print "(that is, you may have to give all functions in the \n";
print " PROGRAM...)\n";
print "**********************************************************\n";
print "\n";
print "Enter the name of an already-created function (created in the\n";
print " current directory), or q to quit:\n";
print "function name: ";
chomp(my $old_funct = <STDIN>);
while ($old_funct ne "q")
{
my $old_funct_source = "${old_funct}\.cpp";
my $old_funct_hdr = "${old_funct}\.h";
# make sure that the source code for this function exists
if (! -e $old_funct_source)
{
print "\n";
print " There is no source code file $old_funct_source\n";
print " for function $old_funct; this function cannot\n";
print " be used in your new function.\n";
print "\n";
}
# make sure that the header file for this function exists
elsif (! -e $old_funct_hdr)
{
print "\n";
print " There is no header file $old_funct_hdr\n";
print " for function $old_funct; this function cannot\n";
print " be used in your new function.\n";
print "\n";
}
else
{
# if reach here, BOTH the .cpp and .h files exist for
# this function;
# IF there is not currently a .o file for this function,
# attempt to create one;
if (! -e "${old_funct}\.o")
{
my $ret_val = system("g++ -c $old_funct_source");
if (($ret_val != 0) || (! -e "${old_funct}\.o"))
{
print "\n";
print "Beware --- there was a problem trying to create\n";
print " a .o file for $old_funct.\n";
print "\n";
}
}
# at this point, either a .o file exists for this
# function, or we have attempted to create one;
# add #include for this function to those for eventual
# test program for new function
$include_stmts .= "#include \"$old_funct_hdr\"\n";
# add object file for this function for use in eventual
# compilation of eventual test program for new function
$addl_obj_files .= "${old_funct}\.o ";
# add name for this function for use to list in possible-
# functions when testing later
$other_desired_funct_names .= "\n$old_funct";
# print CONTENTS of .cpp, .h files to mail record;
#email# print RECORD "\n FUNCTION INCLUDED:\n";
#email# print RECORD "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
#email# $header_guts = `cat ${old_funct}.h`;
#email# print RECORD "$header_guts\n";
#email# print RECORD "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
#email# $funct_guts = `cat ${old_funct}.cpp`;
#email# print RECORD "$funct_guts\n";
#email# print RECORD "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
}
print "\n";
print "Enter the next name of an already-created function (created\n";
print " in the current directory), or q to quit:\n";
print "function name: ";
chomp($old_funct = <STDIN>);
}
}
# print statements verifying that DID build desired #includes and .o
# based on old functions student wants new function to be able to use
#
#print "\n";
#print "AFTER old-funct loop, here are the resulting include statements\n";
#print "and object files:\n";
#
#print "newest set of \#include statements:\n";
#print "--------------------------\n";
#print "$include_stmts";
#print "--------------------------\n";
#
#print "newest set of .o files:\n";
#print "--------------------------\n";
#print "$addl_obj_files\n";
#print "--------------------------\n";
#-----
# PART 6: enter desired expressions? OR build a program that asks for
# each parameter, and then dynamically calls? (Might the latter be more
# efficient? Each new "expr" using the function then wouldn't require
# another recompile! But, gotta parse out # of arguments --- that's
# for next version, I think.)
#-----
#
# question: actually include the function within the main(), or #include
# a .h file for it? But for the latter, I'd need to create a .h as well
# as a .cpp for each function, and then change the compilation command
# accordingly; hmm.
#
# hm; first, let's just paste the raw code in.
# to do this, I can solicit the header and body, put it in a .cpp file
# named based on the function name, and then use the header to build
# the function definition, and the .cpp file to build the function
# declaration after main() --- right?
# (wonder how slow this'll be? shudder...)
#
# (and I may just #include it, after all, after looking at multi-file
# example in c++_reference directory. Hmm.)
#
# IF they give me a header --- CAN a function declaration include parameter
# names? Can a .h file? (Is this not required, or not allowed?)
# the student must enter the purpose statement for their function
# first --- might this get them into the habit of coming up
# with a purpose statement early on? It's worth a shot...
# now that all is set up --- permit expressions to be
# entered for evaluation (hopefully including some
# involving the newly-created functions!)
print "\n";
print "Enter a C++ expression involving:" .
"$other_desired_funct_names" .
"\n...and type enter\n";
print " (or type q to quit):\n";
chomp(my $expr = <STDIN>);
# shall we create each expression's program in a separate file,
# or not? Hmm... For now, yes.
my $expr_ct = 0;
# keep handling expressions until the user wishes to quit
while ($expr ne 'q')
{
print "\n";
$expr_ct++;
# create a C++ program to execute this expression
open TESTER, "> try_expr$expr_ct.cpp"
or die "Cannot open try_expr$expr_ct.cpp for writing: $!";
# this will include other functions they've mentioned wanting
# to use --- is that okay? THEN need to tack new function's
# .h file, too!
print TESTER "$include_stmts";
print TESTER "\n";
print TESTER "int main()\n";
print TESTER "{\n";
# be careful if this is a string expression...!
if ($expr =~ /".*"/)
{
print TESTER " cout << \"value of \" << $expr
<< \": \" << endl;\n";
}
else
{
print TESTER " cout << \"value of $expr: \" << endl;\n";
}
print TESTER " cout << ($expr) << endl;\n";
print TESTER "}\n";
print TESTER "\n";
close TESTER;
# this need to include .o file for new function, doesn't it?
my $ret_val = system("g++ -o try_expr$expr_ct try_expr$expr_ct.cpp " .
"$addl_obj_files");
# I am hoping very hard that a return value of 0 means the compilation
# was successful;
if ($ret_val == 0)
{
system("try_expr$expr_ct");
}
else
{
print "*****************************************************\n";
print "Are you sure that $expr is truly a C++ arithmetic\n";
print " expression (with no variables)?\n";
print "Chances are good that it is not; the above are C++\n";
print " compiler messages. Save them and show them to \n";
print " your prof if you have questions.\n";
print "*****************************************************\n";
#email# print RECORD "THE FOLLOWING ATTEMPT'S TEST FILE DID NOT COMPILE:\n";
}
# save a record of this attempt (to be emailed to me at the
# end of this loop...)
my $when = `date`;
#email# print RECORD " tried expression #$expr_ct: $expr at $when\n";
# clean up --- remove latest expression's C++ files
unlink "try_expr$expr_ct.cpp";
if ($ret_val == 0)
{
unlink "try_expr$expr_ct";
}
print "\nEnter next C++ expression and type enter\n";
print " (or type q to quit):\n";
chomp($expr = <STDIN>);
}
#email#&finish_record("reached end of expr_play script");
print "\nQuitting expr_play ... goodbye.\n\n";
# end of expr_play