#!/usr/local/bin/kermit

; UNIX: Change previous line to contain full pathname of C-Kermit 7.0 binary.

COMMENT - File CKEDEMO.KSC
;
; Exercises Kermit's programming constructs.
; Converted to block-structured format, March 1996.
; Updated to C-Kermit 7.0, April 1999.
;
echo If you don't see the message "Proceeding..."
echo on the next line, C-Kermit was not configured for script programming.
check if
echo Proceeding...
echo

switch \v(program) {
  :C-Kermit,
    if ( < \v(version) 70000 ) stop 1 Version 7.0 or later required...
    echo C-Kermit Programming-Constructs Test
    break
  :default
    stop 1 Sorry - this demo only works with C-Kermit 7.0 or later.
}
echo
echo Defining macros:

COMMENT - SPELLNUM macro.
;
echo { SPELLNUM}
define SPELLNUM {
  local \%x \&a[]
  dcl \&a[9] = one two three four five six seven eight nine
  .\&a[0] = zero
  if ( not def \%1 ) end 1
  .\%1 ::= \%1
  if ( < \%1 0 ) {
     .\%x = { minus}
     .\%1 ::= 0-\%1
  }
  if ( > \%1 9 ) end 1 { Sorry, too hard}
  echo \%x \&a[\%1]
}

COMMENT - CALC macro.  "Pocket calculator".  No arguments.
;
echo { CALC}
define CALC {
    echo Press Return to exit		; Say how to exit.
    while 1 {				; Loop until they want to exit
	ask \%1 { expression: }		; Ask for an expression
        if ( not def \%1 ) break
	echo \flpad(\feval(\%1),10)	; Evaluate and print answer
    }
    echo Back to...			; All done
}

echo { ADDINGMACHINE}
define ADDINGMACHINE {
    local total \%s \%x
    echo Type numbers (one per line) or press Return to quit...
    assign total 0			; Initialize the sum
    while true {			; Loop till done
	askq \%s			; Wait for a number
	if ( not def \%s ) break	; Return quits loop
	.\%x ::= \%s
        if ( not def \%x ) { echo "\%s" invalid - try again, continue }
	increment total \%x		; Add it to the sum
	if fail { echo Can't add "\%s", continue }
	xecho \flpad(\%s,10)\flpad(\m(total),10) ; Print number and subtotal
    }
    echo Total\flpad(\m(total),15,.)
}

COMMENT - SMALLEST macro, recursive.  Arguments:
; 1 = a number or expression
; 2 = a number or expression
; 3 = a number or expression
; Prints the smallest of the three.
;
echo { SMALLEST}
def SMALLEST {
    local \%a \%i \&a[]
    dcl \&a[3]
    if ( != \v(argc) 4 ) end 1 { Sorry - three numbers required.}
    for \%i 1 3 1 {
        .\&a[\%i] ::= \&_[\%i]
        if not numeric \&a[\%i] end 1 { Bad number or expression }
    }
    if ( < \&a[1] \&a[2] ) {		; Compare first two arguments
	echo \&a[1] is less than \&a[2]	; The first one is smaller
	if ( < \&a[1] \&a[3] ) {	; Compare it with the third
  	    echo \&a[1] is less than \&a[3] ; The first one is smaller
	    .\%a := \&a[1]		; Copy it to \%a
	} else {                        ; The third is smaller
	    echo \&a[1] is not less than \&a[3]
	    .\%a := \&a[3]		; Copy it to \%a
        }
    } else {				; Otherwise
	echo \&a[1] is not less than \&a[2] ; The second is smaller
	if ( < \&a[2] \&a[3] ) {	; Compare it with the third
	    echo \&a[2] is less than \&a[3] ; The second is smaller
	    .\%a := \&a[2]		; Copy it to \%a
	} else {                        ; The third is smaller
	    echo \&a[2] is not less than \&a[3]
	    .\%a := \&a[3]		; Copy it to \%a
	}
    }
    echo So the smallest is \%a.	; Announce the winner
}

ec Spelling some numbers...
for \%i -5 9 1 { spellnum \%i }

echo Calculator demo...
calc

echo Adding machine demo - Enter an empty line to quit...
addingmachine

COMMENT - SUM macro, recursive.  Argument:
; 1 = limit of sum, a positive number.
; Returns sum of 1 through the number.
;
echo { SUM}
def SUM {
    if not def \%1 return		; Make sure there is an argument
    if not numeric \%1 return		; Make sure argument is numeric
    if not > \%1 0 return		; Make sure argument is positive
    if = \%1 1 return 1			; If argument is 1, the sum is 1
    else return \feval(\%1+\fexecute(sum,\feval(\%1-1)))
}

COMMENT - ADDEMUP macro, for calling SUM.
;
echo { ADDEMUP}
def ADDEMUP {
    local total
    assign total \fexec(sum,\%1)
    if def total echo SUM(\%1) = \m(total)
    else echo SUM doesn't work for \%1
}

addemup 1
addemup 2
addemup 3
addemup 4
addemup 5
addemup 10
addemup 20

:SMALLEST

while true {
    ask \%x { Type 3 numbers separated by spaces or an empty line to quit:  }
    if not def \%x break
    smallest \%x
}

echo WHILE-LOOP TEST...
echo You should see:
echo { 0 1 2 3 4}
def \%a 0
while < \%a 5 { xecho { \%a}, incr \%a }
echo

echo NESTED WHILE-LOOP TEST...
echo You should see:
echo { 0:0 0:1 0:2 1:0 1:1 1:2 2:0 2:1 2:2}
def \%a 0
while ( < \%a 3 ) {
    def \%b 0
    while ( < \%b 3 ) {
      xecho { \%a:\%b}
      incr \%b
    }
    incr \%a
}
echo

echo FOR-LOOP INSIDE WHILE-LOOP
echo You should see:
echo { 1:1 1:2 1:3 2:1 2:2 2:3 3:1 3:2 3:3}
def \%a 1
while ( < \%a 4 ) {
    for \%i 1 3 1 { xecho { \%a:\%i} }
    inc \%a
}
echo

echo WHILE-LOOP INSIDE FOR-LOOP
echo You should see:
echo { 1:1 1:2 1:3 2:1 2:2 2:3 3:1 3:2 3:3}
for \%i 1 3 1 {
  .\%a = 1
  while < \%a 4 {
      xecho { \%i:\%a}
      incr \%a
  }
}
echo

echo NESTED FOR LOOP TEST
echo You should see:
echo { 1:1 1:2 1:3 2:2 2:3 3:3}
for \%i 1 3 1 {
    for \%j \%i 3 1 {
        xecho { \%i:\%j}
    }
}
echo

echo NESTED FOR/WHILE/BREAK/CONTINUE TEST
echo You should see:
echo { 1:1 1:3 3:1 3:3}
for \%i 1 4 1 {
    if = \%i 2 continue
    else if = \%i 4 break
    asg \%j 0
    while < \%j 4 {
	incr \%j
	if = \%j 2 continue
	else if = \%j 4 break
	xecho { \%i:\%j}
    }
}
echo

echo END from inside nested FOR loops
echo You should see:
echo { 1:1 1:2 1:3 2:1 2:2 2:3 3:1}
define xx {
    for \%i 1 3 1 {
	for \%j 1 3 1 {
            xecho { \%i:\%j}
	    if = \%i 3 if = \%j 1 end
	}
    }
}
do xx
echo

echo RETURN from inside nested FOR loops
echo You should see "IT WORKS":
define xx {
    local \%i \%j
    for \%i 1 3 1 {
	for \%j 1 3 1 {
	    if = \%i 3 if = \%j 1 return IT \%1
	}
    }
    echo YOU SHOULD NOT SEE THIS
}
echo "\fexec(xx WORKS)"

:IFENDTEST
echo END message from inside IF
echo You should see "IT WORKS"
def xx if = 1 1 { end 0 "IT \%1"}
xx WORKS

echo Grouping of words in IF EQUAL
echo You should see "IT WORKS":
def \%a one two three
if equal {\%a} {one two three} echo "IT WORKS"
else echo It doesn't work, foo.
ec

echo Use of expressions and braces in FOR-loop variables
echo You should see "1 2 3":
def \%a 2
for \%i 1 { 1 + \%a } 1 { xecho {\%i } }
echo

echo A macro that echoes its arguments
def XX {
  local \%i
    for \%i 1 { \v(argc) - 1 } 1 {
      echo \%i. "\&_[\%i]"
    }
}
while true {
    ask \%a {Type some words (or just carriage return to quit): }
    if not def \%a break
    xx \%a
}
echo

if not eq {\v(connection)} {remote} forward arrays

ec MINPUT test...
ec Please type one of the following (without the number):
ec {  1. ab cd}
ec {  2. abcd}
ec {  3. xyz}
ec You have 10 seconds...
minput 10 {ab cd} abcd xyz
if success { echo, echo You typed Number \v(minput).}
else { echo, echo You did not type any of them within the time limit.}
echo

:ARRAYS
echo ARRAY TEST I (SLOW)...
; Note that there are much better ways to do this.
; Here we're just testing subscript evaluation, looping, etc.
;
declare \&a[26]
local \%i \%j \%t                    ; Local variables
assign \%i 1
asg \&a[\%i] zebra
incr \%i
asg \&a[\%i] x-ray
incr \%i 1
asg \&a[\%i] baker
incr \%i 3-2
asg \&a[\%i] able
decr \%i -1
asg \&a[\%i] charlie
asg \&a[\%i+1] easy
asg \&a[\%i+2] george
asg \&a[\%i+3] dog
asg \%n \%i+2+8/4
asg \&a[\%n] fox
echo Sorting ...
for \%i 1 (\%n)-1 1 {                ; Outer loop: i from 1 to n-1
    for \%j \%i \%n 1 {              ; Inner loop: j from i to n
	if lgt \&a[\%i] \&a[\%j] {   ; Compare array elements
	    asg \%t \&a[\%i]         ; If out of order,
	    asg \&a[\%i] \&a[\%j]    ; exchange them
	    asg \&a[\%j] \%t
	}
    }
}
echo You should see \feval(\%n) words in alphabetical order:
for \%i 1 \%n 1 { echo {  \%i. \&a[\%i]} }    ; All sorted - print them

echo
echo ARRAY TEST II (FAST)...
;
; Same thing again the easy (and fast) way...
;
declare \&a[] = alpha beta gamma delta epsilon zeta eta theta iota
echo Sorting ...
sort a
echo You should see \fdimension(&a) words in alphabetical order:
show array a
echo
exit 0 End of \v(cmdfile)
