The echo Program

The echo program will just echo its arguments. It's a simple extension to hello world that demonstrates using the command line arguments. Here is the program.

structure Main=
struct

    fun main(arg0, argv) =
    (
        case argv of
          [] => ()

        | (first::rest) =>
        (
            print first;
            app (fn arg => (print " "; print arg)) rest;
            print "\n"
        );

        OS.Process.success
    )

    val _ = SMLofNJ.exportFn("echo", main)
end

The name of the program is supplied to the main function as the first argument, arg0 of type string. This is the same as argv[0] in a C main function. The remaining command line arguments are supplied as a list of strings in argv.

The case expression reads as follows. If the argument list is empty then print nothing. Otherwise if it is non-empty then print the first one and then print the rest of them preceded by a single blank. The app applies the function to each of the strings in the list rest. This function prints the blank and then the argument.

Be careful that you only put semicolons between imperative statements. If you were to put a semicolon after the new-line print you would get this error message from the compiler.

echo.sml:14.2 Error: syntax error: inserting  EQUALOP

This is because the parser in the compiler attempts to correct syntax errors in order to continue compiling for as long as possible. Sometimes this works. In this case it decides that it needs another expression after the semicolon and chooses an equals operator to be the expression. The error message points to the line after where the surplus semicolon is, here line 14, character 2. See Appendix B for more information on the compiler's error messages.

For this program I've used a more elaborate run script since there is a bug in the standard one in that it does not pass empty command line arguments through to the SML program. For the echo program to be exactly right we need to see the empty arguments too. This script copies in more of the SML/NJ .run-sml script.


install=.
smlbin=/src/smlnj/current/bin

arg0=$0
cmd=`basename $0`

ARCH_N_OPSYS=`$smlbin/.arch-n-opsys`
if [ "$?" != "0" ]; then
    echo "$cmd: unable to determine architecture/operating system"
    exit 1
fi
eval $ARCH_N_OPSYS
suffix=$ARCH-$OPSYS

exec $smlbin/.run/run.$ARCH-$OPSYS @SMLcommand=$arg0 \
        @SMLload=$install/${cmd}.$HEAP_SUFFIX "$@"