[comp.sys.amiga.tech] Solution for EXECUTE: No K Directive

erk@americ.UUCP (Erick Parsons) (07/31/89)

From: dlarson@blake.acs.washington.edu (Dale Larson) Message-ID: <3020@blake.acs.washington.edu>

>>Thanks to hcobb@walt.cc.utexas.edu, I solved the problem which was causing
>>my script to bomb with the error "EXECUTE: No K Directive"  The solution
>>was to begin the file with two lines: ".bra {" and ".ket }".  
>
>I still do not understand two things about this problem:  First, and most
>importantly, why could I find no reference whatsoever to this error message
>in any description of EXECUTE or on any page listed under "error" in the
>index of any Amiga documentation?  (Maybe I forgot to put on my glasses :-)
>Second, why was it that I got the error message if the script was called
>from my startup-sequence, but not if it was called from the CLI the 
>startup-sequence bombed into???

I've had this same exact problem but only after I ran one of a few PD
programs that I downloaded from a BBS. (Sorry don't KNOW which). My 
Startup-sequence worked flawlessly for at least a month without change
and all of a sudden *BANG* No K directive errors aborting the rest of
the SS. Extremely frustrating. As you say, there is very little if no
information in the manuals concerning this problem (that I could find).

What *I* finally ended up doing was to reformat my HD (GVP 40Q) and
restore it. THAT fixed my problem. I haven't seen it rear its ugly
head since. Maybe some programmers idea of a joke ? dunno. Being the
cautious type I renamed my execute command and wrote a short alias to 
refer the execute keyword to the proper abbreviation. This happened 
at about the same time the dreaded IRQ virus was revealed. Just made
me think VIRUS !


--
 ------------------ // -----------Cut-Here----------------------------------
  Erick Parsons    //    Words for the wise:   *If it works don't fix it.*
  Sacramento Ca   //        mail to:   ...pacbell!sactoh0!americ!erk
 ------------- \\// --------------------------------------------------------

dlarson@blake.acs.washington.edu (Dale Larson) (07/31/89)

[Not that the first line really matters anyway]

Thanks to hcobb@walt.cc.utexas.edu, I solved the problem which was causing
my script to bomb with the error "EXECUTE: No K Directive"  The solution
was to begin the file with two lines: ".bra {" and ".ket }".  

I still do not understand two things about this problem:  First, and most
importantly, why could I find no reference whatsoever to this error message
in any description of EXECUTE or on any page listed under "error" in the
index of any Amiga documentation?  (Maybe I forgot to put on my glasses :-)
Second, why was it that I got the error message if the script was called
from my startup-sequence, but not if it was called from the CLI the 
startup-sequence bombed into???

-- 
 dTb                                                                       dTb
      I know enough about epistemology to know that I don't know anything  
                      about programming OR epistemology!
           Digital Teddy Bear      dlarson@blake.acs.washington.edu

fgd3@jc3b21.UUCP (Fabbian G. Dufoe) (08/01/89)

From article <3020@blake.acs.washington.edu>, by dlarson@blake.acs.washington.edu (Dale Larson):
> I still do not understand two things about this problem:  First, and most
> importantly, why could I find no reference whatsoever to this error message
> in any description of EXECUTE or on any page listed under "error" in the
> index of any Amiga documentation?  (Maybe I forgot to put on my glasses :-)
> Second, why was it that I got the error message if the script was called
> from my startup-sequence, but not if it was called from the CLI the 
> startup-sequence bombed into???

     To answer your first question, the Amiga's documentation isn't very
good.  The manuals aren't organized very well for finding answers to
problems.  They're organized for reading straight through.  Even then lots
of important things are omitted and others are mentioned at the wrong time.
It would be nice to have perfect documentation, but I don't expect to see
it real soon now.

     In response to your second question I'd hazard a guess that the
offending line in the startup sequence file contained redirection of
standard input or standard output.  Execute uses the redirection symbols (<
and >) as brackets to surround parameters.  The ".bra {" and ".ket }" lines
told it to use "{" and "}" instead.

--Fabbian Dufoe
  350 Ling-A-Mor Terrace South
  St. Petersburg, Florida  33705
  813-823-2350

UUCP: ...uunet!pdn!jc3b21!fgd3

rap@peck.ardent.com (Rob Peck) (08/02/89)

In article <696@jc3b21.UUCP> fgd3@jc3b21.UUCP (Fabbian G. Dufoe) writes:
>From article <3020@blake.acs.washington.edu>, by dlarson@blake.acs.washington.edu (Dale Larson):

>> importantly, why could I find no reference whatsoever to this error message
>> in any description of EXECUTE or on any page listed under "error" in the
>> index of any Amiga documentation?  (Maybe I forgot to put on my glasses :-)

It was suggested in an earlier answer that just using the .bra and .ket
as the first two lines of your file would make the "No K directive" error
go away.  For some reason, this did not work for me, and I finally put
a ".key dummy" as the very first line.  This got rid of the error.
AmigaDOS seemed to be telling me that if I was doing ANY variable substitution
(in a test script, I was using the {$$} stuff, similar to that described
below) but no OTHER variable substitution in a much smaller script,
and I still got the error.  The AmigaDOS manual says that if you want
to do any variable substitution, that the first line of the script
must start with a ".", so the use of .bra {     and    .ket }   should
have been enough.  But it was not.  I dont have the machine here, but
I THINK this is all I was doing:

     .bra {
     .ket }
     echo "The CLI Process that is running me is: {$$}"

and IT generated this error (NO K Directive), so I added .key dummy
as the first line and it went away.  Hmmm.  Ah well, thats MY solution.


If you want a tutorial approach writing of scripts that can be EXECUTEd,
I put a whole chapter on that topic into the Amiga Companion, and even
included an explanation of the startup-sequence, in English so to speak.
Anyone who has tried to decipher the example for "EVAL" in the 1.3
enhancer docs will also appreciate the new explanation that is in the
Second Edition of the Companion.  I found that the example itself is
very clever and contains a couple of useful tricks, but with no documentation
to support it, it took a while to figure it out.  For those who have not
seen the Companion yet, here is what I tell folks about EVAL (starts on
page 161 and runs to page 165 of the second edition)

Note that this is the "UNEDITED" version of the material.  It is as
submitted to Amiga World as the "Please insert this material into
the first edition of the Companion to create the second edition." So
they may have trimmed a few words but told me that the concepts and
examples have remained intact.



========================
Using EVAL To Aid Decision Making

The EVAL command has been added to 1.3 to let you do simple
arithmetic.  EVAL is like IF, but where IF compares strings,
EVAL compares strings-as-numbers.  The command template for
EVAL is:

	VALUE1/A,OP,VALUE2,TO,LFORMAT/K:

which means that you MUST provide at least one parameter
If no operation or other parameter is specified,
the answer evaluates to that of the first parameter.

	1> EVAL 695
	695
	1>

   EVAL works with integer values (whole numbers) only, and
you can specify an operation to perform on two integer values.
You specify the operation by using a particular symbol, as
contained in the table below.  Eval accepts the symbol either
by its expected position (between the two values, as with normal
arithmetic) or by the keyword method (common to most if not
all AmigaDOS commands).

	1> EVAL 4 * 6
	24
	1> EVAL VALUE1 4 VALUE2 6 OP *
	24
	1>

    Here are all of the available operations that EVAL can perform,
along with the "operator" that EVAL recognizes for this operation:

	Operation       Operator      Result
        =========       ========      =========================
	Addition            +         Value1 + Value2
	Subtraction         -	      Value1 - Value2
	Multiplication      *	      Value1 * Value2
	Division            /         Value1 / Value2
	Modulo              mod       Remainder after Value1/Value2
	AND                 &	      Bits in both Value1 and Value2
	OR                  |         Bits in either Value1 or Value2
	NOT                 ~         Zero bits become one bits and VV.
	Left Shift          <<        Shift the Value1 bits left by 
				        Value2 bit positions
	Right Shift         >>	      Shift the Value1 bits right by
					Value2 bit positions
	Negation            -         Placed before any value, that
					value is treated as negative
	  (unary minus)
	Exclusive OR        xor	      Exclusive-OR function
	Bitwise Equivalence eqv       Equivalence function

   Many of these operations are performed by programmers.  If you 
want more information about the operations other than the simple
arithmetic, I'd suggest you look into a book on logic programming
or programming in C.

   The TO keyword lets you redirect the output of the EVAL command to
a file.  This can be quite useful in command scripts because the contents
of the file can be read later and used to make operating decisions.
An example:

	1> EVAL 12 mod 7 TO ENV:remainder
	1> GETENV remainder
	5
	1>
	    
   The other keyword, LFORMAT, lets you tell EVAL how to output its
answer.  You provide a format string, and EVAL will put the answer
out using that format.  For example the number can be formatted as
decimal (specify %N somewhere in the output string), or in hexadecimal
(specify %X), or in octal (specify %O).  When using other than
decimal, you can also tell EVAL how many digits to output by specifying
the number of digits following the specification.  For example,
to use 8 hexadecimal digits, specify %X8.  There is also a special
character sequence that EVAL recognizes (*N) to place a newline
into your output string:

	1> EVAL 256 LFORMAT "256 decimal = %X8 hexadecimal*N"
	256 decimal = 00000100 hexadecimal
	1>

Without the *N in there, it has the same effect as the NOLINE
switch to the ECHO command.  The next output simply appears on
the same line, in the next available character position.

   The default input integer values are decimal, but if you
tell EVAL that a number is hexadecimal (by prepending "0x" or "#x" to
it), or octal (by prepending a leading zero or a #-sign to it), 
EVAL correctly interprets the value:

	1> EVAL 127 + 1
	128
	1> EVAL 0x7F + 1 ;hexadecimal
	128
	1> EVAL 0177 + 1 ;octal
	128
	1> EVAL #x7f + 1 ;hex again
	128
	1> EVAL #177 + 1 ;octal
	128
	1>

   Now that you know what EVAL can do, lets look, line by line,
at an example command script that was provided with the AmigaDOS
1.3 Enhancer kit.  What you'll see here is a slight revision
of the original script.

   The script file that uses EVAL to form a loop.  I commented each
line but you can leave out the comments if you try it.  Remember
that at least the .key statement and any other dot-statement
should start in column 1:

	.key command/a,howmany/a
	;    Both parameters are needed
	.bra {
	.ket }
	;    Allow left/right arrows for redirection
	;    so give EXECUTE an alternate for enclosing
	;    its parameters (alternate BRA(c)KET(s))
	ECHO >ENV:loop {howmany}
	;    Incoming loop value stored in environment
	;    variable so that we can read it later and
	;    test its value.
	;
	LAB BEGIN
	;
	;    The start of a loop
	;    Execute command NOW, assumes at least ONE pass.
	;
	ECHO "This is loop number " NOLINE
	GETENV loop
	;
	;    Now we are going to modify the loop value by using
	;    EVAL to do it.  Get the value, change it (subtract
	;    one), then put it back and loop to BEGIN if the
	;    value still has not reached zero.
	;
	EVAL <ENV:loop >NIL: TO T:junk{$$} VALUE2 1 OP - ?
	;
	;    This one is just a little tough to explain, but
	;    here goes:
	;
	;    1. The specification "<EVAL:loop" says that we are
	;       using AmigaDOS I/O redirection to take the input
	;       for the command from a file (ENV:loop) instead
	;       of from the user directly.
	;
	;    2. The "?" at the end of the line tells EVAL that
	;	it should accept some input from somewhere, and
	;       because of the input redirection, that somewhere
	;       is the contents of the environment variable (file)
	;       named "loop".  This file contains not only the
	;       value itself, but also a linefeed character which
	;       has the same effect as the user pressing return
	;       after typing some command followed by a question
	;       mark.
	;
	;    3. The parameter ">NIL:" is a command to redirect
	;       the output of the command to a file instead of
	;       to the screen.  This prevents the command template
	;       from being printed to the screen.
	;
	;    4. The parameter spec "TO T:junk{$$}" says to take
	;       the real output (the answer) of EVAL, and put it
	;       into a file and that file should have a unique
	;       name.  If running from CLI 1, then the file name
	;       will be T:junk1; if running from CLI 2, the file
	;       name will be T:junk2 and so on.
	;
	;    5. Finally positional parameters are used to tell
	;       EVAL what it is supposed to do.  We establish
	;       VALUE2=1 and OP=-, in other words, whatever we
	;       read from ENV:loop will have 1 subtracted from
	;       it and the result goes into a uniquely named
	;       temporary file.
	;
	;	This complicated method had to be used because
	;	EVAL does not know how to read environment
	;       variable values (IF knows how) directly, so we
	;       have to take advantage of the "?" capability to
	;       fool EVAL into reading the value from the file.
	;
	TYPE >ENV:loop T:junk{$$}
	;
	;       Why not say: 
	;           COPY FROM T:junk{$$} TO ENV:loop
	;       
	;	Well, TYPE always puts a newline character as the
	;       final character output, but COPY copies only what
	;       is there.  EVAL may or may not (depending on whether
	;       LFORMAT is used).  So this is a just-in-case so
	;       that we can guarantee that there will be at least
	;	one newline in the file for EVAL to read on the
	;       next loop around.
	;
	IF val $loop GT 0
	;
	;	Test the present value of loop counter, may exit.
	;
	SKIP BEGIN BACK
	;
	;       If the test is true, go back and restart script.
	;
	ENDIF
	;
	DELETE T:temp{$$} T:temp2{$$} T:doit{$$}
	ECHO "Done"


Bug Alert (SKIP Command)
---------
If one command script calls the EXECUTE function from within 
the script, the SKIP command, even though told to skip BACK, 
can no longer find the target label for the SKIP.  (This deficiency
is actually built into EXECUTE.)   So if your command file needs
to use the BACK option of switch, do not call EXECUTE from within
the script.  If you need to call EXECUTE, then follow the menu
script example instead, and make the script call itself as it
exits.

==========================


I don't know who at CATS actually supplied the example for the use of
EVAL in the 1.3 enhancer docs, but I really DO think it is clever and
its one of those things that is a "forehead slapper" when you realize
"hey, that's a real neat way to do it", specifically EVAL <ENV:loop.
Based on the knowledge that Andy Finkel did the Menu example that I
explained and expanded on for the first edition of the Amiga Companion,
I 'suspect' that he did this one too.  But my congradulations to WHOEVER
at CATS did this example.

Actually, one seldom thinks of using the '?' feature at all.  Normally
when trying to get user input, you automatically think of using the
ASK command, and you only have a chance to get Y/N answers, and SKIP
to something on that basis.   However, using the '?' with the SKIP
command lets you get any kind of answer and as long as what the user
enters matches a particular label and you tell the user what the labels
are, it gives added flexibility.  That idea WAS Andy's and we acknowledged
it in the first edition of the Companion, in the Menu example.

AREXX is fun and more flexible than the commands that you have now on 1.3,
but it seems now WITH 1.3's command set, that there are at least more
chances to workaround problems and more possibilities to solve problems
than ever.

Thanks, CATS.  I'm having fun just learning to use the latest features.
Once I "know it all", I guess I'll be ready for 1.4.  :-)


Rob Peck

hcobb@walt.cc.utexas.edu (Henry J. Cobb) (08/02/89)

	Execute can get confused about when it should be in the automagic 
'literal mode'.  So in every script that uses i/o redirection you should place

.bra	{
.ket	}

as the first two lines of the file.  Except for Startup-Sequence, and in SS you
should be sure and assign T: to a subdirectory of some sort of ram disk.

	Henry J. Cobb	hcobb@walt.cc.utexas.edu

jms@tardis.Tymnet.COM (Joe Smith) (08/02/89)

From article <3020@blake.acs.washington.edu>, by dlarson@blake.acs.washington.edu (Dale Larson):
> Second, why was it that I got the error message if the script was called
> from my startup-sequence, but not if it was called from the CLI the 
> startup-sequence bombed into???

There are two ways to execute a script.  One way is to give the file name
as the "FROM" argument to a new CLI, as in:
	NewCLI CON:0/0/640/200 FROM S:startup-sequence
which is in effect what happens when the system is booted.

The second way is to use the Execute command, as in:
	Execute s:startup-sequence
(or the equivalent, just typing the name of a file that has the "S" bit
set in the file protection).

The difference is that Execute looks for variables to substitute whereas
NewCLI does not.  

In article <696@jc3b21.UUCP> fgd3@jc3b21.UUCP (Fabbian G. Dufoe) writes:
>     In response to your second question I'd hazard a guess that the
>offending line in the startup sequence file contained redirection of
>standard input or standard output.  Execute uses the redirection symbols (<
>and >) as brackets to surround parameters.  The ".bra {" and ".ket }" lines
>told it to use "{" and "}" instead.

This has tripped me up many a time.  Particularly when using something like:
	run <nil: >nil: program <nil: >nil:
which looks like a request for the variable "<nil:>" to be substituted.

-- 
Joe Smith (408)922-6220 | SMTP: JMS@F74.TYMNET.COM or jms@tymix.tymnet.com
McDonnell Douglas FSCO  | UUCP: ...!{ames,pyramid}!oliveb!tymix!tardis!jms
PO Box 49019, MS-D21    | PDP-10 support: My car's license plate is "POPJ P,"
San Jose, CA 95161-9019 | narrator.device: "I didn't say that, my Amiga did!"

staatsvr@asdcds.cds.wpafb.af.mil (Vern Staats; ASD/SCED;) (08/03/89)

In article <3020@blake.acs.washington.edu> dlarson@blake.acs.washington.edu (Dale Larson) writes:
>Thanks to hcobb@walt.cc.utexas.edu, I solved the problem which was causing
>my script to bomb with the error "EXECUTE: No K Directive"  The solution
>was to begin the file with two lines: ".bra {" and ".ket }".  
>
  I recently installed a hard drive on my A1000 and got the same error message
when the startup-sequence on the slow file system partition tried to execute
the startup-sequence on the fsf partition.  I too could execute the offending
script "manually" with no problem.  After lots and lots of test cases &
reboots I found that if I deleted a big chunk of comments in the startup-seq
the problem went away.  Looks to me like there's a limit to how many ;comment
lines execute can handle.

Boolean orthogonal(char *my_opinions, char *employer_opinions)  {return(TRUE);}
INET:  staatsvr@asd.wpafb.af.mil                          ///    Honey, I
UUCP:  nap1!asd!staatsvr                              \\\///   dereferenced
Vern Staats, ASD/SCED, WPAFB OH 45433, 513-255-2714    \XX/      the kids