HP3000-L Archives

March 2005, Week 5

HP3000-L@RAVEN.UTC.EDU

Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Stan Sieler <[log in to unmask]>
Reply To:
Stan Sieler <[log in to unmask]>
Date:
Tue, 29 Mar 2005 17:02:13 -0800
Content-Type:
text/plain
Parts/Attachments:
text/plain (159 lines)
Re:
> I've not seen SPL before.
> IF < THEN

In addition to the info you found, here's a "gotch" to
watch out for.

   integer
     fid,
     ktr;

   integer array
      my'fids (0 : 9);

    ...

OK uses:

   fid := fopen (...)
   if <> then


   my'fids := fopen (...);
   if <> then
        (BTW, the file ID is stored in my'fids (0))

BAD uses:

   my'fids (ktr) := fopen (...);
   if <> then

   Why should the above be bad?  Because the index operation (using "ktr")
   is done after the fopen ... and loading a value from memory
   changes the condition code accordingly :)

It would be better practice to say:

   fid := fopen (...);
   if fid = 0 then
      ...

Except, sigh, for the stupid use of "0" as a valid file number in Unix ...
Because of them, MPE/iX uses 0 as "stdin", so if you close stdin and then
re-open it, you can legitimately get back 0 as a valid file #.
BTW, I don't blame the MPE lab for starting to use 0 on MPE XL ... because
the larger world was also doing that.  It's just that it's annoying :)
Of course, they could have added an easy-to-call alternate FOPEN that
would return a status parameter, or "-1" for failure :)
(HPFOPEN doesn't quite qualify as 'easy-to-call' in this case.)

There are at least five basic uses of condition codes in SPL:

  1) Checking intrinsic results

     The Intrinsics Manual documents if a given intrinsic sets the
     condition code.  If not documented, don't assume that it uses it!

     As ugly as condition code checking is, at least its implemented
     better than UNIX "errno", where you have to know (for each call)
     whether a particular call always sets errno, or only sets it if there
     is an error.

  2) Checking the stop condition of a SCAN or WHILE statement.

     There are higher level ways of doing this, which take an extra
     instruction or two ... but the cost of those extra instructions is
     negligble...you'll waste more of your time determining how to read
     a CARRY/NOCARRY check after a SCAN/MOVE than you'll *EVER* use
     with the higher level stuff.

     (In this case, CARRY/NOCARRY is the "condition code" (very loose usage
     of the term, of course) that I'm referring to, not literally the
     Classic 3000 architecture's 2-bit condition code field).

     E.g., replace:

          scan p' until " ";        ! stop on blank or null
          (or: scan p' until [8/0, 8/" "])

          if carry then
             ...     *I* don't remember whether this means "hit blank" or
                     "hit 0" (it does mean one of those two :)

       with (as appropriate):

          if p' (scan p' until " ") = " " then
             ...found a blank

          else
             ...found a null

   3) Checking the stopping condition of a byte-array "IF" expression:

         if p' = buf', (20) then
            ... the arrays match

         else if < then
            p' is alphabetically "less" than buf'

         else      ! cc is >
            p' is alphabetically "greater" than buf'

   4) Checking if a variable is negative, 0, or positive:

         tos := i;
         del;
         if < then
            ...i is negative
         else if = then
            ...i is 0
         else
            ...i is positive

       (or:  dummy := i;  if < then ...)

       I replace those with:

          if i < 0 then
             ...
          else if i = 0 then
             ...
          else
             ...

        Sure...that takes an extra load/compare, but WHO CARES?  It's far
        more efficient when you take into account the time it took to write the
        code in the first place, and the time used in later reading of the
        code.

   5. Getting a non-functional / non-parameter result back from a procedure

      (Intrinsic results are one example, of course.)

      Some programmers have chosen to use the same *bad* mechanism as
      some intrinsics: using a condition code.

      Example:

           procedure my'proc;
              begin
              logical my'status = q - 1;
              ...
              I want to return CCL:
                 my'status.(06:02) := 1;   ! 1 is CCL

           call:

              ...
              my'proc;
              if < then
                 ...

Hope that's of interest.

Stan

* To join/leave the list, search archives, change list settings, *
* etc., please visit http://raven.utc.edu/archives/hp3000-l.html *

ATOM RSS1 RSS2