; ckermit-selftest.ksc -- the scripting half of 60-ckermit.test, written in the ; language it tests. Driven by tests/60-ckermit.test as ; ; CK_WORK= kermit -y /dev/null -C "take , exit" ; ; and every assertion is a tagged line the .test greps out and compares: ; ; R- ; ; The final ALL-CKERMIT-OK is the whole-payload gate. Nothing here touches a ; connection -- the network side is driven from the .test, where socat lives. ; ; Every expected value below was scored against a native x86_64 C-Kermit 3.02 ; built from the same tarball with the same flag list, so a mismatch on target ; is a target finding rather than a mis-written assertion. No two expected ; values are equal for a reason: an interpreter stuck on one answer would ; otherwise pass a whole block of arithmetic cases. ; ; ASSIGN, NOT DEFINE, for anything built out of \$() or \m(): DEFINE stores its ; argument literally and expands it at use, so `define path \$(CK_WORK)/f` hands ; FOPEN a path with a backslash in it. That is how this file found the crash the ; port patches -- see ckermit_%.bbappend. ; --- variables and arithmetic ------------------------------------------------- define answer 42 echo R01-define \m(answer) .product ::= 6 * 7 echo R02-arith-mul \m(product) .diff ::= 100 - 58 echo R03-arith-sub \m(diff) .quot ::= 903 / 21 echo R04-arith-div \m(quot) .rem ::= 100 % 42 echo R05-arith-mod \m(rem) ; \%a..\%z are the single-character variables; INCREMENT/DECREMENT act on them ; in place, which is the idiom every loop below uses. define \%n 40 increment \%n 7 echo R06-increment \%n decrement \%n 5 echo R07-decrement \%n ; --- control flow ------------------------------------------------------------- ; WHILE with BREAK: sum 1..5 and stop by predicate, not by loop bound. define \%i 0 define sum 0 while true { increment \%i if > \%i 5 break .sum ::= sum + \%i } echo R08-while-sum \m(sum) ; CONTINUE: sum only the even values of 1..10. define \%i 0 define evens 0 while < \%i 10 { increment \%i .mod2 ::= \%i % 2 if = \m(mod2) 1 continue .evens ::= evens + \%i } echo R09-while-continue \m(evens) ; FOR over a range with an explicit step: 1+3+5+7+9. define fsum 0 for \%j 1 9 2 { .fsum ::= fsum + \%j } echo R10-for-step \m(fsum) ; IF / ELSE on a numeric comparison, and string equality separately. if > \m(answer) 40 { echo R11-if-then greater } else { echo R11-if-then not-greater } if equal "kermit" "kermit" echo R12-if-streq equal if not equal "kermit" "wermit" echo R13-if-strneq differs ; SWITCH, taken and defaulted. define \%s two switch \%s { :one, echo R14-switch one, break :two, echo R14-switch two, break :default, echo R14-switch other, break } define \%s nine switch \%s { :one, echo R15-switch-default one, break :two, echo R15-switch-default two, break :default, echo R15-switch-default other, break } ; --- macros ------------------------------------------------------------------- ; A macro with arguments that RETURNs a value, called through \fexecute(). define triple { .\%r ::= \%1 * 3 return \%r } echo R16-macro-return \fexecute(triple,14) ; A macro called with DO for its effect, reading a global and its own argument. define shout { echo R17-macro-do \fupper(\m(answer)-\%1) } do shout ok ; A macro calling a macro: the returned value of the inner call is an operand ; of the outer one's arithmetic, which is the composition an unattended script ; is built out of. (SELF-recursion through \fexecute() does NOT work in this ; version -- the inner call's return value comes back as the outer's; the ; design doc records it. Nesting two DIFFERENT macros does, and is what a ; script needs.) define addone { .\%r ::= \%1 + 1 return \%r } define tentimes { .\%s ::= \fexecute(addone,\%1) * 10 return \%s } echo R18-macro-nested \fexecute(tentimes,4) ; The same composition written as a loop inside a macro, with LOCAL scoping the ; accumulator: 6! by iteration. define fact { local i acc assign acc 1 define \%i 0 while < \%i \%1 { increment \%i .acc ::= acc * \%i } return \m(acc) } echo R18b-macro-loop \fexecute(fact,6) ; --- arrays ------------------------------------------------------------------- declare \&a[5] define \%i 0 while < \%i 5 { increment \%i .\&a[\%i] ::= \%i * \%i } echo R19-array-elem \&a[4] echo R20-array-dim \fdim(&a) ; --- string and number functions ---------------------------------------------- echo R21-flength \flength(kermit-on-wasm32) echo R22-fupper \fupper(MixedCase) echo R23-flower \flower(MixedCase) echo R24-fsubstring \fsubstring(communications,1,6) echo R25-findex \findex(wasm,linux-in-the-wasm-browser) echo R26-frepeat \frepeat(ab,4) echo R27-fword \fword(alpha beta gamma delta,3) echo R28-fmax \fmax(17,71) echo R29-fmin \fmin(17,71) echo R30-feval \feval(2+3*4) echo R31-fcharacter \fcharacter(65) echo R32-fcode \fcode(A) ; --- channel file i/o --------------------------------------------------------- ; FOPEN/FWRITE/FREAD/FCLOSE is the package this image has no other spelling of: ; a script that writes a file, reads it back and counts what it read, without a ; shell and without a second process. assign path \$(CK_WORK)/ck-io.txt fopen /write \%c \m(path) if fail { echo R33-fopen-write FAILED echo ALL-CKERMIT-NO-WORKDIR exit 1 } echo R33-fopen-write ok fwrite /line \%c alpha fwrite /line \%c beta fwrite /line \%c gamma fclose \%c fopen /read \%d \m(path) if fail { echo R34-fopen-read FAILED } else { echo R34-fopen-read ok } define lines 0 define last none while true { fread /line \%d \%l if fail break increment lines assign last \%l } fclose \%d echo R35-fread-count \m(lines) echo R36-fread-last \m(last) ; The file exists on the filesystem with the size those three lines imply -- ; asserted through the file functions rather than the channel that wrote it, so ; a channel that reported success while writing nothing is visible. echo R37-fsize \fsize(\m(path)) if exist \m(path) echo R38-if-exist present ; --- environment and version -------------------------------------------------- ; \$() reads the process environment; this is how the .test hands the work ; directory in, so a green here is also what proves that path was honoured. if not equal "\$(CK_WORK)" "" echo R39-environ set echo R40-version-major \fsubstring(\v(version),1,1) echo ALL-CKERMIT-OK exit 0