home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
newsgrp
/
group91b.txt
< prev
next >
Wrap
Internet Message Format
|
1991-06-13
|
436KB
From icon-group-request@arizona.edu Mon Apr 1 15:58:46 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 1 Apr 91 15:58:46 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA27326; Mon, 1 Apr 91 15:58:43 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Mon, 1 Apr
1991 15:58 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA10724; Mon, 1 Apr 91 05:45:50
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 1 Apr 1991 15:58 MST
Date: 1 Apr 91 08:09:44 GMT
From: haven!ni.umd.edu!uc780.umd.edu!cs450a03@ames.arc.nasa.gov
Subject: RE: Survey Results : Perl vs Icon vs .... (> 500 line
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <C2D5FA28FC605A14@Arizona.edu>
Message-Id: <1APR91.08094454@uc780.umd.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: The University of Maryland University College
References: <BEVAN.91Mar29162211@panda.cs.man.ac.uk>,
<1991Apr1.043321.11251@midway.uchicago.edu>
Richard Goerwitz writes:
>I'm curious why it is that you would see any advantage in run-time
>loading other than decreased in-core mem. reqs. If you were to use the
>Icon compiler (i.e. Icon->C translator), you wouldn't even have to
>worry about adding any code to any run-time system.
Well, I don't Icon, but I'm willing to put my foot in my mouth
anyways...
(1) If you compile an entire application, you lose the
maintainability that the {Icon} environment provides.
(2) If you have some method of adding new primitives (accessible as
proper objects of your system) you suddenly make it possible to use
{Icon} for commercial applications (e.g. where speed is important).
Also note that it should be considered in good taste to provide, along
with any object code, the {Icon} work-alike "source" so that a year or
two down the road when somebody else wants to know what this thing is
doing they can figure it out. If you GPL, you'd want to keep around
the intermidiate language source as well.
Raul Rockwell
From icon-group-request@arizona.edu Mon Apr 1 16:03:25 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 1 Apr 91 16:03:25 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA27431; Mon, 1 Apr 91 16:03:22 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Mon, 1 Apr
1991 16:02 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA02529; Sun, 31 Mar 91
22:06:28 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 1 Apr 1991 16:03 MST
Date: 1 Apr 91 04:33:21 GMT
From: midway!ellis.uchicago.edu!goer@mimsy.umd.edu (Richard L. Goerwitz)
Subject: RE: Survey Results : Perl vs Icon vs .... (> 500 lines)
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <C380C6385C60481C@Arizona.edu>
Message-Id: <1991Apr1.043321.11251@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <BEVAN.91Mar29162211@panda.cs.man.ac.uk>
We've seen an excellent summary of Icon's benefits and deficits, and I
think it is a good one (especially considering that the person in
question was only doing an initial survey). Let me comment on some of
the conclusions reached in efforts to refine them, and ask some
question of my own.
In <BEVAN.91Mar29162211@panda.cs.man.ac.uk> Stephen J Bevan writes (re-
garding Icon), that it has
> - no packages. Everything is in one namespace. However ...
The "however" is for Idol, I gather. For people who don't want to add
yet another level of indirection to their Icon programs, though, naming
conflicts remain a problem.
>- no exceptions.
Have you looked at the Icon "error conversion" capability? Normally,
run-time errors will result in program termination. You can, however,
turn off this feature, and catch the errors yourself, either passing
them through an exception handler, or else passing them back to the
normal termination routine via runerr(). It's not an elegant system,
since every expression that might normally cause error termination has
to be checked individually. I wonder if there are plans to expand
this feature.
> + Object oriented features.
> An extension to the language called Idol is included.
> This converts Idol into standard Icon.
> Idol itself looks (to me) like Smalltalk.
> + has records. Other types include :- sets, lists, strings, tables
> + unlimited line length when reading
> (Note. the newline is discarded)
> ! The only language that has enough facilities to be able to re-write
> some of my Lex/Yacc code.
> + stack trace on error.
> + C interface is good. Can extend the language by building `personal
> interpreter'. No dynamic linking.
> + extensive documentation
> 9 technical reports in all (PostScript and ASCII)
> - Unix interface is quite primitive.
> If you just want to use a command, you can use `callout', anything
> more complicated requires building a personal interpreter (not as
> difficult as it may sound)
It is quite true that Icon does not provide a good low-level interface
with the operating system. Moreover this is unlikely to change, since
one of the great aims of Icon has been to keep it portable. Luckily,
customization (as you note) is not as difficult as it might seem.
> + extensive test suite
> + Usenet group exists specifically for it - comp.lang.icon
>
> - Unless you use Idol, all procedures are at the same level
> i.e. one scope.
> - regular expressions not supported.
> However, in many cases, you can use an Icon functions `find',
> `match', `many' and `upto' instead.
"In many cases" ain't so. ANY pattern representable by regular
expressions can also be represented via Icon's builtin string
processing control structures and functions.
I note, though, that many still want regular expressions. The
reason usually given for NOT including them is that they lack
sufficient power. In point of fact, they represent a miniscule subset
of the range of patterns that can be specified using Icon's native
facilities. The advantage they would bring is that they would allow
far greater recognition speed for those patterns which can be
recognized via regular expressions, and that they would allow much
more compact expression of these patterns than can be achieved with
Icon's intrinsic functions.
Until someone does it *right*, I've written a prototype findre()
function, which is in one of the more recent IPL updates. It
essentially combines Icon's find() function with an egrep-style
FSTN-description language. Ideally, someone should write this in C.
Let's fool with the prototype for a while until we know exactly what
we want, and then let's try to talk some poor soul into coding it up
as part of the Icon run-time system. A matchre() function should also
be added as well.
> + Can trace execution.
> * Pascal/C-like syntax
> i.e. uses {} but has a few more keywords than C.
> + lots of example programs included.
> + can define your own iterators
> i.e. your own procedures for iterating through arbitrary structures.
> + co-expressions. Powerful tool, hard to explain briefly. See
> chapter 13 of the Icon Programming Language.
> - co-expressions haven't been implemented on Sun 4s (the type of
> machine I use)
Please correct me if I'm wrong, but I believe I saw the coexpression
code for the Sun4 posted almost a year ago.
> + has an `initial' section in procedures that is only ever executed
> once and allows you to initialise C like static variables with the
> result of other functions (unlike C).
> + arbitrary precision integers.
Wish list:
> E.2.4 Add a regular expression data type. Modify the functions find
> and match to perate appropriately when their first argument is a
> regular expression.
I'd modify this to say, add findre() and matchre() to the list of
builtin functions. Most C libraries have regexp routines that can be
drafted to serve in these capacities. I know that regular expression
don't fit into the traditional image of what Icon string processing
has always been. Practical advantages of speed and compactness,
though, far outweigh this supposed disadvantage, and would make Icon
much more useful for many real-world tasks.
> E.2.5 \ All of these suggest extending
> E.5.4 | the string scanning facilities to
> E.5.5 / cope with files and strings in a uniform way.
Not sure what you mean.
> E.12.1 Provide a way to load functions (written in C) at runtime
My impression is that inclusion of this feature would be
hopelessly implementation dependent, and would dramatically increase
the complexity of maintaining the many implementations that exist.
I'm curious why it is that you would see any advantage in run-time
loading other than decreased in-core mem. reqs. If you were to use the
Icon compiler (i.e. Icon->C translator), you wouldn't even have to
worry about adding any code to any run-time system.
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From icon-group-request@arizona.edu Mon Apr 1 22:27:16 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 1 Apr 91 22:27:16 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA01885; Mon, 1 Apr 91 22:27:14 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Mon, 1 Apr
1991 22:26 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA09229; Mon, 1 Apr 91 21:22:58
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 1 Apr 1991 22:26 MST
Date: 1 Apr 91 11:50:48 GMT
From: mcsun!ukc!mucs!m1!bevan@uunet.uu.net (Stephen J Bevan)
Subject: Icon (was Re: Survey Results : Perl vs Icon vs ... ))
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F91C0DDB8C6046B1@Arizona.edu>
Message-Id: <BEVAN.91Apr1125048@panda.cs.man.ac.uk>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Department of Computer Science, University of Manchester
References: <BEVAN.91Mar29162211@panda.cs.man.ac.uk>
In <1991Apr1.043321.11251@midway.uchicago.edu> Richard L. Goerwitz
writes :-
>> - no packages. Everything is in one namespace. However ...
>
>The "however" is for Idol, I gather. For people who don't want to add
>yet another level of indirection to their Icon programs, though, naming
>conflicts remain a problem.
I was thinking about the indirection stuff myself, however I received
a message from Clinton Jeffery <cjeffery@cs.arizona.edu> about Idol
and in it he says :-
``... its method lookup is a constant time operation unlike Smalltalk's''
I'm not exactly sure how this is achieved, but maybe it removes some
of the worries about slow execution.
>>- no exceptions.
>
>Have you looked at the Icon "error conversion" capability?
No this one slipped me by.
>> - regular expressions not supported.
>> However, in many cases, you can use an Icon functions `find',
>> `match', `many' and `upto' instead.
>
>"In many cases" ain't so. ANY pattern representable by regular
>expressions can also be represented via Icon's builtin string
>processing control structures and functions.
Excuse the poor phrasing on my part. I didn't mean to imply that Icon
couldn't handle the expressions. What I meant was that in a lot of
cases, you can replace a regexp with one of the above functions, and
in all cases, you can replace it with a combination of the above.
>> - co-expressions haven't been implemented on Sun 4s (the type of
>> machine I use)
>
>Please correct me if I'm wrong, but I believe I saw the coexpression
>code for the Sun4 posted almost a year ago.
You are right, I've only been reading comp.lang.icon for about month
and so wasn't aware of it. All I can say is that the copy of Icon v8
I retrieved, explicitly mentioned the fact that co-expressions didn't
work on Sun4s. I assume the code will be in the next release.
>> E.2.4 Add a regular expression data type. Modify the functions find
>> and match to perate appropriately when their first argument is a
>> regular expression.
>
>I'd modify this to say, add findre() and matchre() to the list of
>builtin functions. Most C libraries have regexp routines that can be
>drafted to serve in these capacities.
Well after spending a day adding regular expressions to ELK, I
wouldn't be so sure about the regexp facilies of C libraries. For
example the regexp library with SunOS 4.1 only has ed/grep style
regular expression, not egrep ones. I therefore used the GNU regexp
code which implements Emacs like regexps i.e. egrep standard, but with
different quoting conventions. This works well for me as I've written
more Emacs Lisp code than egrep/awk code. If you prefer the standard
egrep style, I'd recommend Henry Spencer's regexp code. (This is used
by both Python and TCL, in slightly modified forms)
>> E.2.5 \ All of these suggest extending
>> E.5.4 | the string scanning facilities to
>> E.5.5 / cope with files and strings in a uniform way.
>
>Not sure what you mean.
Well to quote ``The Implementation of the Icon Programming Language''
by Ralph E. Griswold and Madge T. Griswold :-
E.2.5
``Unify string and file data types so that string operations can be
performed on files.''
E.4.1 (this is E.5.4 refered to above. There is a typo in the book
which refers to E.4 as 5.4. This was somehow further mangled by me to
produce E.5.4!)
``Many problems that should be easy to deal with using string scanning
are complicated by the fact that the data to be processed is contained
in a file that consists of a sequence of lines that logically
constitute a single string. ...''
E.4.2 (this was E.5.5, reason as above)
``Extend string scanning to apply to files''
This topic is also mentioned in a recent post by David Gudeman in
alt.lang.cfutures
>> E.12.1 Provide a way to load functions (written in C) at runtime
>I'm curious why it is that you would see any advantage in run-time
>loading other than decreased in-core mem. reqs.
Maybe you should ask Madge or Ralph Griswold, it's in their book!
Personally, I thought it would be useful for the reason you mention
i.e. you only load what you need. However given the following I
don't think it is necessary :-
>If you were to use the Icon compiler (i.e. Icon->C translator), you
>wouldn't even have to worry about adding any code to any run-time
>system.
I knew that an Icon compiler was been developed, but I didn't actually
know that it was available until after I posted. Personally I
wouldn't be looking for an increase in speed (although its alway
welcome, even on a SPARCstation!), I'd be more interested in the C
interface i.e. how easy would it be to add extensions like, for
example, dbm support? (note. that was a rhetorical question)
Stephen J. Bevan bevan@cs.man.ac.uk
From icon-group-request@arizona.edu Wed Apr 3 06:12:10 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 3 Apr 91 06:12:10 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Osprey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA19634; Wed, 3 Apr 91 06:12:08 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 3 Apr
1991 06:11 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA29165; Wed, 3 Apr 91 04:55:54
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 3 Apr 1991 06:11 MST
Date: 3 Apr 91 09:27:21 GMT
From: eru!hagbard!sunic!mcsun!hp4nl!charon!guido@bloom-beacon.mit.edu (Guido
van Rossum)
Subject: RE: Survey Results : Perl vs Icon vs .... (> 500 lines)
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <033A8C3E54400F82@Arizona.edu>
Message-Id: <3252@charon.cwi.nl>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <BEVAN.91Mar29162211@panda.cs.man.ac.uk>,
<1991Apr1.043321.11251@midway.uchicago.edu>
Richard L. Goerwitz replies to Stephen Bevan, regarding Icon:
Bevan:
>> - Unix interface is quite primitive.
>> If you just want to use a command, you can use `callout', anything
>> more complicated requires building a personal interpreter (not as
>> difficult as it may sound)
Goerwitz:
>It is quite true that Icon does not provide a good low-level interface
>with the operating system. Moreover this is unlikely to change, since
>one of the great aims of Icon has been to keep it portable. Luckily,
>customization (as you note) is not as difficult as it might seem.
I don't buy the argument that you can't provide a good Unix interface
because of portability.
Python is designed to be just as portable as Icon (runs on the Mac,
for starters) but its Unix interface is quite good (and will improve).
The trick is that all the Unix dependencies are encapsulated in a
separate module. Unix dependent applications won't run on non-Unix
systems, but then they are probably not needed there either. Many
applications and library modules can be (and are!) written without the
use of explicit Unix features. Of course, the standard I/O interface
exists on all systems.
There is no excuse for not providing a decent Unix interface for a
language that runs under Unix. Leaving it up to local initiative
("customization") is fatal for portability.
--Guido van Rossum, CWI, Amsterdam <guido@cwi.nl>
"Life's gotta be more than meeting pretty faces and sitting on them"
From icon-group-request@arizona.edu Wed Apr 3 11:44:25 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 3 Apr 91 11:44:25 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Osprey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00221; Wed, 3 Apr 91 11:44:22 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 3 Apr
1991 11:43 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA07914; Wed, 3 Apr 91 10:35:38
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 3 Apr 1991 11:43 MST
Date: 3 Apr 91 15:11:53 GMT
From: midway!ellis.uchicago.edu!goer@mimsy.umd.edu (Richard L. Goerwitz)
Subject: RE: Survey Results : Perl vs Icon vs .... (> 500 lines)
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <319D8DEC04401141@Arizona.edu>
Message-Id: <1991Apr3.151153.3447@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <BEVAN.91Mar29162211@panda.cs.man.ac.uk>,
<1991Apr1.043321.11251@midway.uchicago.edu>, <3252@charon.cwi.nl>
In article <3252@charon.cwi.nl> guido@cwi.nl (Guido van Rossum) writes:
>
>>> - [the Icon-]Unix interface is quite primitive.
>>> If you just want to use a command, you can use `callout', anything
>>> more complicated requires building a personal interpreter (not as
>>> difficult as it may sound)
>
>Goerwitz:
>>It is quite true that Icon does not provide a good low-level interface
>>with the operating system. Moreover this is unlikely to change, since
>>one of the great aims of Icon has been to keep it portable....
>
>I don't buy the argument that you can't provide a good Unix interface
>because of portability.
>
>Python is designed to be just as portable as Icon (runs on the Mac,
>for starters) but its Unix interface is quite good (and will improve).
>The trick is that all the Unix dependencies are encapsulated in a
>separate module. Unix dependent applications won't run on non-Unix
>systems, but then they are probably not needed there either.
What is portability? Portability doesn't just involve the compiler or
interpreter itself. It's a property of code written for it as well.
Why? Because the code is as important as the language tools themselves.
What good is it, say, to be make it easy to reimplement a compiler for
more than one system when code written for that compiler will present
a horrendous problem?
Portability is also not just a theoretical thing. The proof is in the
pudding. How many platforms is Python actively used on? Here's a list
for Icon. Note that most programs will run practically unaltered on
each of the listed platforms. Do you know of any language for which a
similar claim could be made for so many machines and operating systems?
MS-DOS
OS/2
Mac (MPW and standalone)
Atari
Apollo (AEGIS)
IBM 370 (MVS/XA and VM/CMS)
Amiga
DEC VAX (8650, running VMS)
And for Unix-oids:
BSD 4.3
SunOS 4.0
Ultrix
AIX
Xenix
Mach (on the NeXT)
SYSVR3 (4 also?)
This is just what I can think of offhand. There are probably others as
well.
>There is no excuse for not providing a decent Unix interface for a
>language that runs under Unix. Leaving it up to local initiative
>("customization") is fatal for portability.
I'm not sure, but I think you've got this backwards. Customization
*creates* nonportability. Still, I think you are right that languages
need a good OS interface in order to be useful for certain types of
tasks. The question is, "What features would you regard as vital for
work in a Unix environment?" I'll be curious to see your answer.
Mine would be:
ability to call C functions
ability to store C pointers for calls to C functions
built-in support for conversion from Icon to C types
intrinsic fork()/exec()/wait() ability
intrinsic ability to work with pipes
intrinsic system() function
These would be the basic things I'd want. Icon has three of them. It
lacks the other two. Yet another it partially implements, but the inter-
face is nontrivial for complex objects (I'm talking about Icon->C type
conversions).
-Richard (goer@sophist.uchicago.edu)
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From @um.cc.umich.edu:Paul_Abrahams@MTS.cc.Wayne.edu Wed Apr 3 19:02:53 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 3 Apr 91 19:02:53 MST
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00116; Wed, 3 Apr 91 19:02:49 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA22765; Wed, 3 Apr 91 18:26:36 -0500
Received: from MTS.cc.Wayne.edu by um.cc.umich.edu via MTS-Net; Wed, 3 Apr 91 18:20:17 EST
Date: Wed, 3 Apr 91 18:20:20 EST
From: Paul_Abrahams@MTS.cc.Wayne.edu
To: icon-group@cs.arizona.edu
Message-Id: <315814@MTS.cc.Wayne.edu>
Subject: Using the ``map'' function
In doing the index for my latest book, I need to sort the entries using a
nonstandard collating sequence. I therefore need a ``keytrans'' function
that transforms a sorting key to a key that uses the correct collating
sequence. Here's the obvious way to do it in Icon:
procedure keytrans(key)
static collator
initial {collator := ...} # printable chars in collating sequence order
return map(key, collator, &ascii[33:128])
end
This is simple but slow since the map must be regenerated for each key.
Here's the other way:
procedure keytrans(key)
static collator, lookup
initial {
collator := ...
lookup = map(&ascii[33:128], collator, &ascii[33:128])
}
local c, retval
retval := ""
every c := !key do
retval ||:= lookup[ord(c) - 31]
return retval
end
This is inelegant but fast.
Is there any way I can have my cake and eat it too? I wouldn't mind a small
loss in speed, but the difference here seems pretty big.
Paul Abrahams
Abrahams@mts.cc.wayne.edu
From alex@laguna.Metaphor.COM Wed Apr 3 19:52:34 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 3 Apr 91 19:52:34 MST
Received: from relay.metaphor.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA01041; Wed, 3 Apr 91 19:52:27 -0700
Received: from laguna.Metaphor.COM by relay.metaphor.com (4.1/SMI-4.1)
id AA00313; Wed, 3 Apr 91 18:47:42 PST
Received: by laguna.Metaphor.COM (4.0/SMI-4.0)
id AA09079; Wed, 3 Apr 91 18:51:32 PST
Date: Wed, 3 Apr 91 18:51:32 PST
From: alex@laguna.Metaphor.COM (Bob Alexander)
Message-Id: <9104040251.AA09079@laguna.Metaphor.COM>
To: Paul_Abrahams@MTS.cc.Wayne.edu
Subject: Re: Using the ``map'' function
Cc: icon-group@cs.arizona.edu
Hi Paul --
In your initial procedure (the slow one) it's likely that much of the
time used in repeatedly executing
return map(key, collator, &ascii[33:128])
is due to the fact that every call converts the cset, &ascii, to a
string.
Also, there is an optimization in the iconx code for map() such that
the internal translation table is not rebuilt if the second and third
arguments are the same (i.e. identical descriptors) as for the previous
map() call. That optimization cannot be used in your proc.
Given all that, I'll bet this will execute a lot faster (the proof is
left to the reader :)
procedure keytrans(key)
static collator, ascii
initial {
collator := ...
ascii := &ascii[33:128]
}
return map(key, collator, ascii)
end
-- Bob Alexander
Metaphor Computer Systems (415) 961-3600 x751 alex@metaphor.com
====^=== Mountain View, CA ...{uunet}!{decwrl,apple}!metaphor!alex
From icon-group-request@arizona.edu Wed Apr 3 21:57:43 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 3 Apr 91 21:57:43 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Osprey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02486; Wed, 3 Apr 91 21:57:41 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 3 Apr
1991 21:57 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA25670; Wed, 3 Apr 91 20:50:57
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 3 Apr 1991 21:57 MST
Date: 4 Apr 91 03:40:38 GMT
From: att!linac!midway!ellis.uchicago.edu!goer@ucbvax.Berkeley.EDU (Richard L.
Goerwitz)
Subject: bits -> bytes
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <875233CCB4401C20@Arizona.edu>
Message-Id: <1991Apr4.034038.271@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
Perhaps I'm opening a can of worms, like I did with the last such
posting ("terrible code"). Anyway, I just wrote a section of code
for some compression work I'm doing, and I just don't like the
looks of it. Is there a clearer and/or more efficient way of do-
ing this sort of thing in Icon??
-Richard
(what sort of thing I'm talking about will shortly become clear;
behold the code -)
#
# outbits() & inbits()
#
# Pass to outbits(i, len) an integer i, and a length parameter (len),
# and outbits will suspend byte-sized chunks of i converted to
# characters (most significant bits first) until there is not enough
# left of i to fill up an 8-bit character. The remaining portion is
# stored in a buffer until outbits() is called again, at which point
# the buffer is combined with the new i and then output in the same
# manner as before. The buffer is flushed by calling outbits() with
# no i argument.
#
# A trivial example of how outbits() might be used:
#
# outtext := open("some.file.name","w")
# l := [1,2,3,4]
# every writes(outtext, outbits(!l,3))
# writes(outtext, outbits(&null,3)) # flush buffer
#
# List l may be reconstructed with inbits() (see inbits.icn):
#
# intext := open("some.file.name")
# l := []
# while put(l, inbits(intext, 3))
#
# Note that outbits() is a generator, while inbits() is not.
#
procedure outbits(i, len)
local old_part, new_part, window, old_byte_mask
static old_i, old_len, byte_length, byte_mask
initial {
old_i := old_len := 0
byte_length := 8
byte_mask := (2^byte_length)-1
}
old_byte_mask := (0 < 2^old_len - 1) | 0
window := byte_length - old_len
old_part := ishift(iand(old_i, old_byte_mask), window)
# If we have a no-arg invocation, then flush buffer (old_i).
if /i then {
old_i := old_len := 0
return char(old_part)
} else {
new_part := ishift(i, window-len)
len -:= (len >= window) | {
old_len +:= len
old_i := ior(ishift(old_part, len-window), i)
fail
}
suspend char(ior(old_part, new_part))
}
until len < byte_length do {
suspend char(iand(ishift(i, byte_length-len), byte_mask))
len -:= byte_length
}
old_len := len
old_i := i
fail
end
procedure inbits(f, len)
local i, byte, old_byte_mask
static old_byte, old_len, byte_length
initial {
old_byte := old_len := 0
byte_length := 8
}
old_byte_mask := (0 < 2^old_len - 1) | 0
old_byte := iand(old_byte, old_byte_mask)
i := ishift(old_byte, len-old_len)
len -:= (len > old_len) | {
old_len -:= len
return i
}
while byte := ord(reads(f)) do {
i := ior(i, ishift(byte, len-byte_length))
len -:= (len > byte_length) | {
old_len := byte_length-len
old_byte := byte
return i
}
}
end
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From alex@laguna.Metaphor.COM Fri Apr 5 16:04:36 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 5 Apr 91 16:04:36 MST
Received: from relay.metaphor.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA09355; Fri, 5 Apr 91 16:04:34 -0700
Received: from laguna.Metaphor.COM by relay.metaphor.com (4.1/SMI-4.1)
id AA00534; Fri, 5 Apr 91 14:59:48 PST
Received: by laguna.Metaphor.COM (4.0/SMI-4.0)
id AA10400; Fri, 5 Apr 91 10:53:52 PST
Date: Fri, 5 Apr 91 10:53:52 PST
From: alex@laguna.Metaphor.COM (Bob Alexander)
Message-Id: <9104051853.AA10400@laguna.Metaphor.COM>
To: eru!kth.se!sunic!mcsun!ukc!mucs!m1!bevan@bloom-beacon.mit.edu
Subject: Re: Survey Results
Cc: icon-group@cs.arizona.edu
I read your language survey with great interest, since (1) I'm also
currently in the process of surveying languages for a particular use,
and (2) I'm an Icon fan, user, and implementor.
Regarding (1), you've done a really nice job of researching the
languages and sharing your findings -- my interest is piqued to further
investigate a couple of new languages. Thanks.
Regarding (2), I watched the icon-group traffic stimulated by your
posting, and noticed a couple of area that might not have been
covered. So here are my additions:
> - Unix interface is quite primitive.
> If you just want to use a command, you can use `callout', anything
> more complicated requires building a personal interpreter (not as
> difficult as it may sound)
I'm not sure just what constitutes a good UNIX interface, but Icon has
great access to "commands" via subshells. It has a system() function
just like C, and has popen() access for both reading and writing via
the "p" option of the Icon open() function. "callout" was really
intended for adding C functions to Icon, not for access to UNIX
"commands". (However, if what you intended by the term "commands" is
UNIX system calls, I agree the built-in interface is weak, although
some of that sort of work can be done through subshell commands).
> + can define your own iterators
> i.e. your own procedures for iterating through arbitrary structures.
Merely the tip of the generator/goal-directed iceberg :-)!
> The Icon Programmming Language
> Ralph E. Griswold and Madge T. Griswold
> Prentice Hall 1983
There's a second edition of the excellent "Icon Book" that is even
bigger and better than the original:
Griswold, Ralph E. and Madge T. Griswold. "The Icon Programming
Language, Second Edition", Prentice-Hall, Inc., Englewood Cliffs, New
Jersey. 1990.
-- Bob Alexander
Metaphor Computer Systems (415) 961-3600 x751 alex@metaphor.com
====^=== Mountain View, CA ...{uunet}!{decwrl,apple}!metaphor!alex
From icon-group-request@arizona.edu Sat Apr 6 04:19:06 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Sat, 6 Apr 91 04:19:06 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Osprey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA21193; Sat, 6 Apr 91 04:19:04 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sat, 6 Apr
1991 04:18 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA16343; Sat, 6 Apr 91 03:12:14
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sat, 6 Apr 1991 04:18 MST
Date: 5 Apr 91 14:22:37 GMT
From: eru!hagbard!sunic!mcsun!ukc!mucs!m1!bevan@bloom-beacon.mit.edu (Stephen J
Bevan)
Subject: Portability (was Re: Survey Results : Perl vs Icon vs ...)
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <4EEF664444402C3C@Arizona.edu>
Message-Id: <BEVAN.91Apr5152237@panda.cs.man.ac.uk>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Department of Computer Science, University of Manchester
References: <BEVAN.91Mar29162211@panda.cs.man.ac.uk>
> What is portability? Portability doesn't just involve the compiler or
> interpreter itself. It's a property of code written for it as well.
If we are talking about the base language, then I'd agree with this.
However, if you have a decent module system (like Python) you can put
system specific features in separate modules. i.e if you are running
under Amoeba, you can use the Amoeba module, if you are running on a
Mac, you can use the Mac module. BTW I'm not saying the modules have to
impement the same thing, rather they take advantage of the facilties
of the machine.
Where's the portability problem?
Stephen J. Bevan bevan@cs.man.ac.uk
From ksr!ksr.com!tim@uunet.UU.NET Sun Apr 7 11:20:37 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 7 Apr 91 11:20:37 MST
Received: from relay1.UU.NET by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA06775; Sun, 7 Apr 91 11:20:35 -0700
Received: from ksr.UUCP by relay1.UU.NET with UUCP
(5.61/UUNET-shadow-mx) id AA06792; Sun, 7 Apr 91 14:20:31 -0400
Received: from kaos.ksr.com by ksr.com (4.0/SMI-3.2)
id AA24983; Sat, 6 Apr 91 18:23:38 EST
Received: by kaos.ksr.com (4.0/SMI-3.2)
id AA19070; Sat, 6 Apr 91 18:23:37 EST
Message-Id: <9104062323.AA19070@kaos.ksr.com>
To: icon-group@cs.arizona.edu
Subject: Bignum bug in Icon Version 8
Date: Sat, 06 Apr 91 18:23:36 EST
From: Tim Peters <tim@ksr.com>
Attempting to add the most negative native integer to a bignum causes an
"Illegal instruction" trap on our SPARC (Solbourne, pretty much
equivalent to a Sun-4) installation of Icon V8.
Following is a terminal session showing the problem:
kaos 338= cat bug.icn
procedure main()
local i, j
write( "host: ", &host )
write( "version: ", &version )
write( "features:" )
every write( " ", &features )
i := -2147483647
i -:= 1
j := 6103515625
write(i," ",j)
i +:= j
end
kaos 339= /usr/local/lib/icon/v8/bin/icont -u bug -x
Translating:
bug.icn:
main (521/15000)
No errors
Linking:
Executing:
host: kaos
version: Icon Version 8.0. May 7, 1990
features:
UNIX
ASCII
co-expressions
direct execution
environment variables
error trace back
executable images
expandable regions
external functions
large integers
math functions
memory monitoring
pipes
string invocation
system function
-2147483648 6103515625
Illegal instruction
kaos 340= echo $?
132
kaos 341=
There's a longish (perhaps a second) pause between the output of i & j
and the "Illegal instruction" trap, leading me to believe that Icon has
gotten horribly confused.
Note that i is -2^31, the most negative native integer on this "long
ints are 4 bytes" machine. The problem does not occur for other values
of i (well, I didn't try *all* possible values ... <grin>), and goes
away if i is intialized via
i := -2147483648
instead. Indeed, *most* plausible ways of setting i to -2^31 make the
problem go away: I assume the code sequence in the test case is special
only in that it causes i to "look like" a native integer internally,
while most other ways cause i to look like a bignum internally.
Finally, I doubt this is a local installation problem, because I've used
Icon's bignums extensively over several months, and this is the first
major error I've stumbled into.
If I can be of any further assistance in tracking this down, please let
me know.
one-of-icon's-admirers-ly y'rs - tim
Tim Peters Kendall Square Research Corp
tim@ksr.com, ksr!tim@harvard.harvard.edu
From @um.cc.umich.edu:Paul_Abrahams@MTS.cc.Wayne.edu Sun Apr 7 20:17:10 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 7 Apr 91 20:17:10 MST
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03010; Sun, 7 Apr 91 20:17:07 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA28022; Sun, 7 Apr 91 23:17:01 -0400
Received: from MTS.cc.Wayne.edu by um.cc.umich.edu via MTS-Net; Sun, 7 Apr 91 23:11:32 EDT
Date: Sun, 7 Apr 91 23:11:42 EDT
From: Paul_Abrahams@MTS.cc.Wayne.edu
To: icon-group@cs.arizona.edu
Message-Id: <317214@MTS.cc.Wayne.edu>
Subject: Efficiency of the `map' function
Thanks to all for your informative comments about the efficiency
of the map function. I had guessed that it might do some caching
of its arguments. I'm glad to hear that it really does and in
particular that its cache can hold more than one item.
I'm still wondering, though, how the map cache works and what its
capacity is. Is the cache associated with each call or is it
global over the program? It seems pretty difficult to get a
decent implementation of map without a cache, since each call
requires processing every character in the second argument and
possibly in the third as well. There does seem to be a hazard
here: writing calls on map that aren't cached and therefore take
a long time to execute. Not knowing the caching policy, it would
be easy for someone (like me) to inadvertently write a noncached
map call.
There's a deeper issue buried here, what some have called
`performance transparency'. It's the property of a programming
language that enables a programmer to gauge the relative costs of
different constructs. Certainly someone familiar with the
innards of the Icon implementation can gauge these costs, but as
someone who isn't familiar with the innards, I've always found
that difficult.
Paul Abrahams
abrahams@mts.cc.wayne.edu
From @um.cc.umich.edu:Paul_Abrahams@MTS.cc.Wayne.edu Sun Apr 7 20:17:30 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 7 Apr 91 20:17:30 MST
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03020; Sun, 7 Apr 91 20:17:28 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA28042; Sun, 7 Apr 91 23:17:22 -0400
Received: from MTS.cc.Wayne.edu by um.cc.umich.edu via MTS-Net; Sun, 7 Apr 91 23:13:00 EDT
Date: Sun, 7 Apr 91 23:13:06 EDT
From: Paul_Abrahams@MTS.cc.Wayne.edu
To: icon-group@cs.arizona.edu
Message-Id: <317216@MTS.cc.Wayne.edu>
Subject: Plusses and minuses of Icon
I've been following with interest the discussion about the
plusses and minuses of Icon. My own view is that we shouldn't
expect a single programming language to be the best one around
for absolutely everything, any more than we expect that of other
fine tools. Icon is superb for prototyping medium-size programs,
for quick and dirty solutions, and for symbol manipulation tasks,
especially those where goal-directed evaluation helps. Examples
of tasks where I've found it beyond compare are an index
generation program for a book, a bootstrap version of a compiler,
and a printer-specific simulator of the IBM Script document
formatter. Moreover, its internal structure and its superb
engineering make it a pleasure to use.
At the same time I cannot imagine that Icon would *ever* be the
language of choice for, say, writing a disk caching program in a
competitive commercial environment where the name of the game is
coming out first in the PC Magazine speed comparisons. Nor can I
imagine it being used for writing a million-line spaceship
control program. Two of its limitations are the inherent
efficiency of its code and the weakness of its global packaging
mechanisms.
The proponents of nearly every language I know seem to feel that
criticism of the language for a particular application implies
criticism of the language in general. I think that feeling is
misplaced. With respect to Icon in particular, a very useful
activity would be to try to spell out the scope of tasks at which
Icon excels without attempting to make that scope universal.
There are few language around that are as good at *anything* as
Icon is at the tasks for which it is suited.
Several people have argued that Idol solves the global packaging
problem. That argument is in a sense irrelevant, for reasons
that have nothing to do with the intrinsic merits of Idol. Idol
is not Icon; if we're talking about Icon, then let's leave Idol
out of it. Perhaps Idol is the natural direction in which Icon
should evolve, and perhaps Idol will turn out to be Icon 9.0 (or
n.0). But Idol does not as yet have the wide distribution, the
supporting structure, or the backlog of experience that Icon
does. This is in no way a criticism of it or even a statement
about the limitations of its future. If we're discussing the
merits of languages, let's keep our languages straight.
Paul Abrahams
abrahams@mts.cc.wayne.edu
From icon-group-request@arizona.edu Mon Apr 8 15:34:51 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 8 Apr 91 15:34:51 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28894; Mon, 8 Apr 91 15:34:49 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Mon, 8 Apr
1991 15:34 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA15549; Mon, 8 Apr 91 12:49:54
-0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 8 Apr 1991 15:34 MST
Date: 8 Apr 91 09:45:22 GMT
From: mcsun!hp4nl!charon!guido@uunet.uu.net (Guido van Rossum)
Subject: RE: Survey Results : Perl vs Icon vs .... (> 500 lines)
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <3FA3956016C005C3@Arizona.edu>
Message-Id: <3282@charon.cwi.nl>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <1991Apr1.043321.11251@midway.uchicago.edu>, <3252@charon.cwi.nl>,
<1991Apr3.151153.3447@midway.uchicago.edu>
goer@ellis.uchicago.edu (Richard L. Goerwitz) writes:
>What is portability? Portability doesn't just involve the compiler or
>interpreter itself. It's a property of code written for it as well.
>Why? Because the code is as important as the language tools themselves.
>What good is it, say, to be make it easy to reimplement a compiler for
>more than one system when code written for that compiler will present
>a horrendous problem?
>
>Portability is also not just a theoretical thing. The proof is in the
>pudding. How many platforms is Python actively used on? Here's a list
>for Icon. Note that most programs will run practically unaltered on
>each of the listed platforms. Do you know of any language for which a
>similar claim could be made for so many machines and operating systems?
If I understand you well, you can make this claim for Icon because
Icon forbids things that are inherently system-dependent. This means
that probably a host of programs that would benefit from Icon's
high-level problem-solving abilities won't be written in Icon because
it lacks the low-level interfaces needed to gather the data or
whatever.
True, if a program opens a pipe and forks off a process that calls
sendmail it won't be portable to the Mac. But forbidding such things
even when the OS provides the functionality forces the author to use a
non-portable solution anyway (such as writing a shell script wrapper
around an Icon program). I argue that if the language at least allows
you to make non-portable OS calls, users are better off -- of course
assuming standard modularization techniques are available to isolate
non-portable portions of programs, and encouraging portable solutions
where they exist.
>[list of platforms on which Ican is used deleted]
I don't really want to engage in "mine is longer than yours" contests,
but just for the record: Python is out only two months now and has
already been ported to all of the Unix platforms you mention (plus
hpux) and some of the micro ones (Mac, MS-DOS, Atari ST). I don't
claim that all Python programs run on all platforms, because some
platforms don't provide some built-in modules, but Python programs
that don't use system-dependent modules will run everywhere
without change. The crux is that a non-portable Python program is
immediately recognizable because it imports a system-dependent module.
Also note that Python provides uniform interfaces for OS-dependent
features that are available on many systems but not all -- if you have
a symbolic link system call, it will be called posix.symlink().
Programs can dynamically test for the presence of such features (which
is unly useful if they have a way of handling their absence).
>[...] Still, I think you are right that languages
>need a good OS interface in order to be useful for certain types of
>tasks. The question is, "What features would you regard as vital for
>work in a Unix environment?" I'll be curious to see your answer.
>Mine would be:
>
> ability to call C functions
> ability to store C pointers for calls to C functions
> built-in support for conversion from Icon to C types
> intrinsic fork()/exec()/wait() ability
> intrinsic ability to work with pipes
> intrinsic system() function
>These would be the basic things I'd want. Icon has three of them. It
>lacks the other two. Yet another it partially implements, but the inter-
>face is nontrivial for complex objects (I'm talking about Icon->C type
>conversions).
You don't say which three Icon has and I don't know enough about Icon
to guess. Python has all that you mention except fork/exec/wait and
pipes, which are easy enough to add, but since this is a one-person
project, for now I am content with system() and temporary files.
Disclaimer: maybe I seem stubborn on this point, but I have worked on
a language project where OS independence was considered so important
that the language didn't even have a primitive to open a file and read
data from it within a program. The language didn't become a terrible
success, even though it had other properties that made it a big leap
forward from other languages...
--Guido van Rossum, CWI, Amsterdam <guido@cwi.nl>
"Twenty years ago, Dan Bernstein would be defending Assembler against HLL's"
From icon-group-request@arizona.edu Tue Apr 9 05:16:51 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 9 Apr 91 05:16:51 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00431; Tue, 9 Apr 91 05:16:49 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Tue, 9 Apr
1991 05:16 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA15630; Tue, 9 Apr 91 05:00:44
-0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 9 Apr 1991 05:16 MST
Date: 9 Apr 91 08:23:13 GMT
From: olivea!samsung!transfer!lectroid!jjmhome!smds!rh@apple.com (Richard
Harter)
Subject: RE: Survey Results : Perl vs Icon vs .... (> 500 lines)
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <B27FB80626C00C35@Arizona.edu>
Message-Id: <388@smds.UUCP>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: SMDS Inc., Concord, MA
References: <BEVAN.91Mar29162211@panda.cs.man.ac.uk>,
<1991Apr3.151153.3447@midway.uchicago.edu>
In article <1991Apr3.151153.3447@midway.uchicago.edu>, goer@ellis.uchicago.edu (Richard L. Goerwitz) writes:
> What is portability? Portability doesn't just involve the compiler or
> interpreter itself. It's a property of code written for it as well.
> Why? Because the code is as important as the language tools themselves.
> What good is it, say, to be make it easy to reimplement a compiler for
> more than one system when code written for that compiler will present
> a horrendous problem?
There are some issues that weren't addressed in this discussion. In
languages which have OS command capability one has to come to terms with
the fact that different OS's have differing command syntax and differing
file system syntax. Portability of command code across OS's really implies
that the language must supply that portability. Consider, for example,
path names. UNIX and VMS both have a path naming system that amounts to
device - directory tree list - file name. If the code refers to files by
path name then the language should provide a standard function to return
a correct path name from the components [or equivalent functionality]. I
am supposing here that the language is strong enough so that path name
elements are symbolic and switchable in a config file.
One can list a number of such requirements, depending on the objectives
of the language in question. In general, however, portability of code
in the language requires that all host OS interface capability be portable
across the OS's being supported.
--
Richard Harter, Software Maintenance and Development Systems, Inc.
Net address: jjmhome!smds!rh Phone: 508-369-7398
US Mail: SMDS Inc., PO Box 555, Concord MA 01742
This sentence no verb. This sentence short. This signature done.
From TENAGLIA@mis.mcw.edu Tue Apr 9 06:04:05 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 9 Apr 91 06:04:05 MST
Received: from mis.mcw.edu (mis3.mis.mcw.edu) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00505; Tue, 9 Apr 91 06:03:54 -0700
Date: Tue, 9 Apr 1991 08:01 CST
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Comparative Languages (icon vs perl etal)
To: icon-group@cs.arizona.edu
Message-Id: <C9931A3740801DA5@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Vms-To: IN%"icon-group@cs.arizona.edu"
I run icon under VMS. I use it usually as a file filter. Typical languages
such as BASIC, FORTRAN, PASCAL, and C may generate faster running code, but
I usually find myself spending all my time fighting typed variables. VMS
has a shell language called DCL which is easy to program, but it's
interpreted and runs 10 times slower than icon in regards to file I/O.
I often find myself making DCL/icon hybrid applications. DCL offers much
faster screen I/O, so I use it to front end icon filters which are much
faster with file I/O.
As far as structured languages go, Icon has one thing to it's advantage that
all the other 'structured' languages lack. No GOTO. The other languages
preach against GOTO, yet implement it anyway. Icon doesn't even acknowledge
its existence and thus, no GOTO. In my years of Icon programming, I've never
needed a GOTO in it. Apparently it was well thought out and implemented.
There is another string handling language in the genre of icon and perl.
It's ABC. I've seen it for PC and MAC. I've heard it exists for unix, and
a VMS implementation is in the works. It's a nifty interactive environment
set up to handle strings. It doesn't have a lot of features, but it looks
like it my be a nice first programming to teach.
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From icon-group-request@arizona.edu Tue Apr 9 09:34:26 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 9 Apr 91 09:34:26 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA01411; Tue, 9 Apr 91 09:34:23 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Tue, 9 Apr
1991 09:33 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA20832; Tue, 9 Apr 91 08:50:52
-0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 9 Apr 1991 09:34 MST
Date: 9 Apr 91 15:14:51 GMT
From: usc!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!midway!ellis.uchicago.edu!goer@apple.com (Richard L.
Goerwitz)
Subject: RE: Comparative Languages
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <D67A83BD16C00EA4@Arizona.edu>
Message-Id: <1991Apr9.151451.6713@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <C9931A3740801DA5@mis.mcw.edu>
There seems to be some misunderstanding about where Icon "fits in" in
the great scheme of programming languages. Having worked with Icon
very intensely for several years now, I feel I can report effectively
on it, and would like to do so here. I would only offer my standard
word of warning: I'm trained as a philologist, and have never taken a
CS or programming course from any CS department in any university I've
attended.
First, let's speak diachronically. How did Icon evolve? A simple
illustration will suffice here, I think:
SNOBOL ----> SL5 -----\
\----> Icon
/
ALGOL ---> Pascal ----/
Along about '76 or so, the people at the U of Arizona working on SL5
suddenly realized that the evaluation mechanisms originally confined
to string scanning in SNOBOL could actually be generalized to the
entire language. You might say, "Whaddya think Prolog is?" Prolog,
though, is a somewhat constrained implementation of first order
predicate logic :-), and is foreign to most programmers (and even many
theorists). Instead of going off on some "tangent," the people at the
U of Arizona designed a language that utilized backtracking and
goal-directed evaluation within the context of a more standard,
Algol-derived, structures.
Icon was first implemented in FORTRAN (save the barfing, please), and
then later in C (1979 or so?). It's now one of the most widely
implemented of the "unknown" programming languages.
Okay, that's my mangled version of Icon's evolution. Now let's talk
synchronically (i.e. typologically).
One thing I find amusing is that people often put perl and Icon in the
same category. About all they have in common is that they are both
optimized for string handling of one kind or another. If there is any
real relation, it's via awk, which took on a few SNOBOL-ish features
(e.g. the ~ "contains" operator). Awk, perl, and Icon all have
associative arrays and what not, and free the user from having to
worry about storage. Many LISP dialects, though, have these same
features, and I don't seem LISP as being all that closely related to
Icon. Perl and awk are also regexp based, which makes them very good
at recognizing simple languages and patterns (fundamentally these are
the same). Icon, though slower at handling these same patterns, is
much more of a general-purpose programming language, and is capable of
recognizing, and effectively parsing, patterns which cannot be handled
by your run-of-the-mill DFA. Icon really isn't very much like perl,
except in the very, very general typological sense of being geared
for more than low-level systems programming and numerical processing.
Put in practical terms, Icon represents a successful admixture of
Prolog-like backtracking mechanisms with an Algol-like structure and
SNOBOL-inspired string handling capabilities. It is very strictly,
but dynamically, typed, and offers conversion facilities allowing the
user to move effortlessly from char set to string to integer or real
data-types and back again. Icon is at its best doing string
processing, parsing, data conversion, and anything involving a more
heuristic, rather than purely algorithmic, approach. Icon is also
good for prototyping and for small jobs that would ordinarily be done
using awk. I use Icon mainly for medium-scale indexing and
concordance programs. I also use it for fairly large-scale text
retrieval engines and for things like semiautomatic collation of
manuscripts, and linguistic analysis of ancient textual corpora.
Icon is clearly at its worst doing anything that requires close
interface with the hardware or operating system, or which requires
pointer-based access to memory locations. Icon has no pointers, so
there is just no way to "get at" anything on this low a level without
dipping down into its C interface. Icon also lacks OS-specific I/O
capabilities (e.g. under Unix there is no support for terminfo or
termio-based I/O, and interfacing the curses library to it is clumsy,
due to Icon's inability to store C pointers without kludges like
casting them to ints, and then converting them to its integer data
type). If some solution to these problems could be found, Icon would
become viable for commercial software systems. As yet, it can be used
for certain such projects. It is, however, not suitable for many
others.
Icon is popular among people in the liberal arts, specifically
literary and linguistic people. One of them - Alan Corre - has in
fact written a book on using Icon. It is also, ironically, popular
among language theorists who like to stick offbeat and interesting
feathers in their caps. Icon is also, naturally, popular among the
many people who have worked on it at one time or another.
Icon would be an ideal first language, since it offers all the
advantages of a Pascal, without many of its disadvantages. It handles
garbage collection, storage allocation, and necessary type
conversions, freeing the beginning programmer to think about things
that are more important. It also makes things like mathematical sets,
lists, hash tables, and strings into trivially simple data objects,
again freeing the programmer to think about the general typology of
his or her solution, and not so much about the as-yet irrelevant
details of implementation. From Icon it is not difficult to move into
other Algol-derived dialects, since the overt structure is basically
the same. Icon also gives one a leg up in languages like Prolog which
make use of vaguely similar backtracking mechanisms. Though these
advantages would be important for beginning programmers planning to
move into other areas, Icon's most valuable asset as an instructional
language is that teachers competent to use it would not have to
separate out the "humanities" students (who are making up a larger and
larger share of low-level CS classes). Icon has all the facilities
that both the "Hum" and "Sci" students would need on the introductory
level.
I hope that this posting clears up some of the many misconceptions
people seem to have about Icon. If there are inaccuracies, I'm sure
that someone who's been more "officially" involved with it can clear
them up.
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From @um.cc.umich.edu:Paul_Abrahams@MTS.cc.Wayne.edu Tue Apr 9 11:24:16 1991
Received: from megaron.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 9 Apr 91 11:24:16 MST
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA04329; Tue, 9 Apr 91 11:24:12 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA00823; Tue, 9 Apr 91 14:24:06 -0400
Received: from MTS.cc.Wayne.edu by um.cc.umich.edu via MTS-Net; Tue, 9 Apr 91 13:30:32 EDT
Date: Tue, 9 Apr 91 13:29:58 EDT
From: Paul_Abrahams@MTS.cc.Wayne.edu
To: icon-group@cs.arizona.edu
Message-Id: <317920@MTS.cc.Wayne.edu>
Subject: Portability
An example of a portable Icon function with a nonportable
implementation is the file name generator I posted a while back.
Given a file name with wildcards, its result sequence is the set
of specific file names that match. The DOS implementation uses a
specific system call, while the Unix implementation (I'd guess)
would use a shell echo call with redirected output (since
wildcard interpretation is generally done in the shell, not in
the underlying system.) Note that DOS wildcards and Unix
wildcards have somewhat different interpretations: DOS
essentially ignores characters after `*', while Unix doesn't; and
the DOS treatment of the file extension is quite different from
that of Unix.
Path name interpretation is another example of a portable
function with a non-portable implementation, since DOS uses `\'
but Unix uses `/' (and maybe the Mac uses something else again).
But the notion of a path makes sense in any system that has
tree-structured directories. (Does anyone know how this maps to
the IBM OS/370 world?)
Paul Abrahams
Abrahams@mts.cc.wayne.edu
From icon-group-request@arizona.edu Wed Apr 10 15:02:02 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 10 Apr 91 15:02:02 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA03042; Wed, 10 Apr 91 15:01:58 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 10 Apr
1991 15:01 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA15302; Wed, 10 Apr 91
14:39:08 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 10 Apr 1991 15:01 MST
Date: 10 Apr 91 21:23:50 GMT
From: sharp@noao.edu (Nigel Sharp)
Subject: RE: Comparative Languages
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <CD649933C6C00DBD@Arizona.edu>
Message-Id: <1991Apr10.212350.15137@noao.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: National Optical Astronomy Observatories, Tucson AZ
References: <C9931A3740801DA5@mis.mcw.edu>,
<1991Apr9.151451.6713@midway.uchicago.edu>
I hope you will forgive a neophyte posting.
Some years ago I used SNOBOL/Spitbol for some tasks in pattern matching
(including literary manuscript analysis for author identification)
and algebra manipulation, and found it to be a very lovely language.
I may soon need to do some similar work, and have been following some
news groups to catch up to the state of the art. I was wondering if one
of the current experts could tell me a) if a knowledge of Snobol helps,
b) if Icon is similar enough that I won't be starting from scratch, and
c) (sorry about this one) which books are recommended (the article I am
"following" mentioned one written by a literary type, but without
details). My past experience lends me to favour Icon, as you might expect.
Before you notice I'm in Tucson and could walk across and ask the
inventors, let me say that I have too much respect to bother them
directly with such trivial questions.
Nigel Sharp, nsharp@noao.edu
From icon-group-request@arizona.edu Wed Apr 10 19:52:42 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 10 Apr 91 19:52:42 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA16147; Wed, 10 Apr 91 19:52:39 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 10 Apr
1991 19:52 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA23947; Wed, 10 Apr 91
19:39:30 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 10 Apr 1991 19:52 MST
Date: 11 Apr 91 02:12:29 GMT
From: midway!quads.uchicago.edu!goer@handies.ucar.edu (Richard L. Goerwitz)
Subject: partial input completion utility
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F603C2B7F6C009C0@Arizona.edu>
Message-Id: <1991Apr11.021229.27400@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
I just wrote this as part of a larger project, and I believe it would
be of general interest. To anyone who tries it out: Please let me
know if you find problems or make modifications that significantly
affect performance (ahem - for the *better*).
-Richard
############################################################################
#
# Name: complete.icn
#
# Title: complete partial input string
#
# Author: Richard L. Goerwitz
#
# Version: 1.2
#
############################################################################
#
# This file contains a single procedure, complete(s,st), which
# completes a string (s) relative to a set or list of strings (st).
# Put differently, complete() lets you supply a partial string, s,
# and get back those strings in st that s is either equal to or a
# substring of.
#
# Lots of command interfaces allow completion of partial input.
# Complete() simply represents my personal sentiments about how this
# might best be done in Icon. If you strip away the profuse comments
# below, you end up with less than thirty lines of actual source
# code.
#
# I have arranged things so that only that portion of an automaton
# which is needed to complete a given string is actually created and
# stored. Storing automata for later use naturally makes complete()
# eat up more memory. The performance gains make it worth the
# trouble, though. If, for some reason, there comes a time when it
# is advisable to reclaim the space occupied by complete's static
# structures, you can just call it without arguments. This
# "resets" complete() and forces an immediate garbage collection.
#
# Example code:
#
# commands := ["run","stop","quit","save","load","continue"]
# while line := read(&input) do {
# cmds := list()
# every put(cmds, complete(line, commands))
# case *cmds of {
# 0 : input_error(line)
# 1 : do_command(cmds[1])
# default : display_possible_completions(cmds)
# }
# etc...
#
# More Iconish methods might include displaying successive
# alternatives each time the user presses the tab key (this would,
# however, require using the nonportable getch() routine). Another
# method might be to use the first string suspended by complete().
#
############################################################################
#
# Links: none
#
############################################################################
procedure complete(s,st)
local dfstn, c, l, old_char, newtbl, str, strset
static t
initial t := table()
# No-arg invocation wipes out static structures & causes an
# immediate garbage collection.
if /s & /st then {
t := table()
collect() # do it NOW
fail
}
type(st) == ("list"|"set") |
stop("error (complete): list or set expected for arg2")
# Seriously, all that's being done here is that possible states
# are being represented by sets containing possible completions of
# s relative to st. Each time a character is snarfed from s, we
# check to see what strings in st might represent possible
# completions, and store these in a set for future use. At some
# point, we either run into a character in s that makes comple-
# tion impossible (fail), or we run out of characters in s (in
# which case we succeed, & suspend each of the possible
# completions).
# Store any sets we have to create in a static structure for later
# re-use.
/t[st] := table()
# We'll call the table entry for the current set dfstn. (It really
# does enable us to do things deterministically.)
dfstn := t[st]
# Snarf one character at a time from s.
every c := !s do {
# The state we're in is represented by the set of all possible
# completions before c was read. If we haven't yet seen char
# c in this state, run through the current-possible-completion
# set, popping off the first character of each possible
# completion, and then construct a table which uses these
# initial as keys, and the completions that are possible for
# each of these characters are the values for those keys.
if /dfstn[st] then {
# To get strings that start with the same char together,
# sort the current string set (st).
l := sort(st)
newtbl := table()
old_chr := ""
every str := !l do {
str ?:= (chr := move(1), tab(0)) | next
if old_chr ~==:= chr then
strset := set()
insert(newtbl, chr, insert(strset, str))
}
insert(dfstn, st, newtbl)
}
# What we've done essentially is to create a table in which
# the keys represent labeled arcs out of the current state,
# and the values represent possible completion sets for those
# paths. What we need to do now is store that table in dfstn
# as the value of the current state-set (i.e. the current
# range of possible completions). Once stored, we can then
# see if there is any arc from the current state (dfstn[st])
# with the label c (dfstn[st][c]). If so, its value becomes
# the new current state (st), and we cycle around again for
# yet another c.
st := \(\dfstn[st])[c] | fail # see NB below
}
# Eventually we run out of characters in c. The current state
# (i.e. the set of possible completions) can simply be suspended
# one element at a time, with s prefixed to each element. If, for
# instance, st had contained ["hello","help","hear"] at the outset
# and s was equal to "hel", we would now be suspending "hel" ||
# !set(["lo","p"]).
suspend s || !st
# NB: Slight performance gains could be had in certain cases by
# checking the size of st. If size = 1 and s is a substring of
# its only element (or else matches in its entirety), then we are
# essentially finished. No need to go on and on creating nodes
# and arcs. Storage space gains could be had by only inserting
# arcs needed in order to handle the current character, c, instead
# of creating all possible arcs out the current state whenever a
# new arc is needed.
end
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From isidev!nowlin@uunet.uu.net Thu Apr 11 06:25:52 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 11 Apr 91 06:25:52 MST
Received: from relay1.UU.NET by optima.cs.arizona.edu (4.1/15)
id AA06835; Thu, 11 Apr 91 06:25:49 MST
Received: from isidev.UUCP by relay1.UU.NET with UUCP
(5.61/UUNET-shadow-mx) id AA08584; Thu, 11 Apr 91 09:25:47 -0400
Date: Thu, 11 Apr 91 09:25:47 -0400
From: isidev!nowlin@uunet.uu.net
Message-Id: <9104111325.AA08584@relay1.UU.NET>
To: uunet!cs.arizona.edu!icon-group@uunet.uu.net
Subject: Re: partial input ...
I know I should resist but it's like a challenge. I just can't let a
verbose Icon program go by without wanting to terse it up. I think of Icon
as making it easier on me as a programmer. If Icon is going to do all this
work for me why not let it? That's only partly rhetorical.
Anyway, what follows contains a terser version of the complete() procedure.
I included the original version since the program below tests both. I
took the comments (which were useful by the way) out of the original since
it was 40 lines even without them:
procedure main()
l := ["idaho","ohio","utah","indiana","illinois","texas","iowa"]
write("\nProgrammer does the work:")
every write("\t",complete("i",l))
write("\nIcon does the work:")
every write("\t",terscomp("i",l))
end
procedure terscomp(s,st)
suspend match(s,p := !st) & p
end
procedure complete(s,st)
local dfstn, c, l, old_char, newtbl, str, strset
static t
initial t := table()
if /s & /st then {
t := table()
collect()
fail
}
type(st) == ("list"|"set") |
stop("error (complete): list or set expected for arg2")
/t[st] := table()
dfstn := t[st]
every c := !s do {
if /dfstn[st] then {
l := sort(st)
newtbl := table()
old_chr := ""
every str := !l do {
str ?:= (chr := move(1), tab(0)) | next
if old_chr ~==:= chr then
strset := set()
insert(newtbl, chr, insert(strset, str))
}
insert(dfstn, st, newtbl)
}
st := \(\dfstn[st])[c] | fail
}
suspend s || !st
end
--- ---
| S | Iconic Software, Inc. - Jerry Nowlin - uunet!isidev!nowlin
--- ---
From icon-group-request@arizona.edu Thu Apr 11 10:29:21 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 11 Apr 91 10:29:21 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA13449; Thu, 11 Apr 91 10:29:19 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 11 Apr
1991 10:02 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA13077; Thu, 11 Apr 91
09:56:42 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 11 Apr 1991 10:29 MST
Date: 11 Apr 91 16:27:49 GMT
From: agate!bionet!uwm.edu!linac!midway!quads.uchicago.edu!goer@ucbvax.berkeley.edu
(Richard L. Goerwitz)
Subject: RE: partial input ...
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <708201BF168000B9@Arizona.edu>
Message-Id: <1991Apr11.162749.1637@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <9104111325.AA08584@relay1.UU.NET>
In article <9104111325.AA08584@relay1.UU.NET> nowlin@isidev.UUCP writes:
>I know I should resist...
Jerry, the whole reason I posted was that I had hoped people would
not be able to resist :-) !
>Anyway, what follows contains a terser version of the complete() procedure.
I fooled with my program a while, and got it to run faster than the
"let Icon do the work" approach, but let me point out that the speed
difference is less than 5% in most instances, and never more than 10%.
If anyone wants what I came up with, I'll gladly send it out. I don't
really see any reason why anyone should want it, though, when there is
a three-line equivalent that does pretty much the same thing (and uses
less memory to boot).
-Richard
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From alex@laguna.metaphor.com Thu Apr 11 10:57:45 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 11 Apr 91 10:57:45 MST
Received: from relay.metaphor.com by optima.cs.arizona.edu (4.1/15)
id AA14391; Thu, 11 Apr 91 10:57:42 MST
Received: from laguna.Metaphor.COM by relay.metaphor.com (4.1/SMI-4.1)
id AA00144; Thu, 11 Apr 91 10:52:52 PDT
Received: by laguna.Metaphor.COM (4.0/SMI-4.0)
id AA14124; Thu, 11 Apr 91 10:56:43 PDT
Date: Thu, 11 Apr 91 10:56:43 PDT
From: alex@laguna.metaphor.com (Bob Alexander)
Message-Id: <9104111756.AA14124@laguna.Metaphor.COM>
To: icon-group@cs.arizona.edu
Subject: Re: partial input ...
I, too, was interested in seeing how the obvious terser version of
Richard G's complete() procedure would work. My terse version was much
like Jerry N's (before I saw Jerry's). So I did some timings, and
here's what I found: The terse version was faster when used with a
list with a size on the order of Richard's or Jerry's sample program
(how much faster depended on the size of input string). *However*,
when the list gets large (~100 entries), Richard's wins hands down.
I guess that makes sense -- Richard's run time will vary
(predominantly) with the size of the abbreviated string, where the
terse method varies with the size of the list.
-- Bob Alexander
Metaphor Computer Systems (415) 961-3600 x751 alex@metaphor.com
====^=== Mountain View, CA ...{uunet}!{decwrl,apple}!metaphor!alex
From icon-group-request@arizona.edu Thu Apr 11 16:58:40 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 11 Apr 91 16:58:40 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA29887; Thu, 11 Apr 91 16:58:36 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 11 Apr
1991 16:57 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA26261; Thu, 11 Apr 91
15:59:00 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 11 Apr 1991 16:58 MST
Date: 11 Apr 91 21:22:52 GMT
From: pacbell.com!mips!sdd.hp.com!wuarchive!uwm.edu!linac!midway!ellis.uchicago.edu!goer@ucsd.edu
(Richard L. Goerwitz)
Subject: RE: partial input ...
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <A6D9376E268003B6@Arizona.edu>
Message-Id: <1991Apr11.212252.14436@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <9104111756.AA14124@laguna.Metaphor.COM>
alex@LAGUNA.METAPHOR.COM (Bob Alexander) writes:
>I, too, was interested in seeing how the obvious terser version of
>Richard G's complete() procedure would work. My terse version was much
>like Jerry N's (before I saw Jerry's). So I did some timings, and
>here's what I found: The terse version was faster when used with a
>list with a size on the order of Richard's or Jerry's sample program
>(how much faster depended on the size of input string). *However*,
>when the list gets large (~100 entries), Richard's wins hands down.
>
>I guess that makes sense -- Richard's run time will vary
>(predominantly) with the size of the abbreviated string, where the
>terse method varies with the size of the list.
I managed to get performance of the version I posted to a level where
it offers an acceptable increase over Jerry's version. I confess that
one of the big reasons I wrote it was just to determine whether
Icon could offer me a fairly fast, deterministic way of handling
such problems.
At one point several months ago I actually wrote an Icon-only egrep-
type program that actually constructed a full-blown deterministic au-
tomaton, constructing only what it needed in order to accept or re-
ject a line. Trouble is that it actually ran much slower than a simi-
lar program I wrote that goes to a nondeterministic pushdown automaton
under certain circumstances. I would guess that for very complex fstns
the deterministic algorithm would be faster, but in practical use it
just didn't cut the mustard. (The nondeterministic version of this
program is in one or another IPL update as findre.icn.)
Anyway, it frustrated me that Icon didn't really let me get at anything
on a low enough level to solve basic pattern-matching problems deter-
ministically and with reasonable storage requirements (I still wish
Icon had *some* form of pointers for simple data types). This little
string completion utility was really just another attempt on my part
to solve this problem of performance and deterministic automata in
Icon. The fact that it now runs faster than the "obvious" solution
only gratifies me in the sense that I might be able to apply the tech-
nique used here to problems where the performance gain would be a lot
more significant.
Since a couple of people asked for the "fixed" version, I'm reposting
it.
-Richard
############################################################################
#
# Name: complete.icn
#
# Title: complete partial input string
#
# Author: Richard L. Goerwitz
#
# Version: 1.3
#
############################################################################
#
# This file contains a single procedure, complete(s,st), which
# completes a string (s) relative to a set or list of strings (st).
# Put differently, complete() lets you supply a partial string, s,
# and get back those strings in st that s is either equal to or a
# substring of.
#
# Lots of command interfaces allow completion of partial input.
# Complete() simply represents my personal sentiments about how this
# might best be done in Icon. If you strip away the profuse comments
# below, you end up with less than thirty lines of actual source
# code.
#
# I have arranged things so that only that portion of an automaton
# which is needed to complete a given string is actually created and
# stored. Storing automata for later use naturally makes complete()
# eat up more memory. The performance gains make it worth the
# trouble, though. If, for some reason, there comes a time when it
# is advisable to reclaim the space occupied by complete's static
# structures, you can just call it without arguments. This
# "resets" complete() and forces an immediate garbage collection.
#
# Example code:
#
# commands := ["run","stop","quit","save","load","continue"]
# while line := read(&input) do {
# cmds := list()
# every put(cmds, complete(line, commands))
# case *cmds of {
# 0 : input_error(line)
# 1 : do_command(cmds[1])
# default : display_possible_completions(cmds)
# }
# etc...
#
# More Iconish methods might include displaying successive
# alternatives each time the user presses the tab key (this would,
# however, require using the nonportable getch() routine). Another
# method might be to use the first string suspended by complete().
#
# NOTE: This entire shebang could be replaced with a slightly slower
# and much smaller program suggested to me by Jerry Nowlin and Bob
# Alexander.
#
# procedure terscompl(s, st)
# suspend match(s, p := !st) & p
# end
#
# This program will work fine for lists with just a few members, and
# will use a lot less memory.
#
############################################################################
#
# Links: none
#
############################################################################
procedure complete(s,st)
local dfstn, c, l, old_char, newtbl, str, strset
static t
initial t := table()
# No-arg invocation wipes out static structures & causes an
# immediate garbage collection.
if /s & /st then {
t := table()
collect() # do it NOW
fail
}
type(st) == ("list"|"set") |
stop("error (complete): list or set expected for arg2")
# Seriously, all that's being done here is that possible states
# are being represented by sets containing possible completions of
# s relative to st. Each time a character is snarfed from s, we
# check to see what strings in st might represent possible
# completions, and store these in a set for future use. At some
# point, we either run into a character in s that makes comple-
# tion impossible (fail), or we run out of characters in s (in
# which case we succeed, & suspend each of the possible
# completions).
# Store any sets we have to create in a static structure for later
# re-use.
/t[st] := table()
# We'll call the table entry for the current set dfstn. (It really
# does enable us to do things deterministically.)
dfstn := t[st]
# Snarf one character at a time from s.
every c := !s do {
# The state we're in is represented by the set of all possible
# completions before c was read. If we haven't yet seen char
# c in this state, run through the current-possible-completion
# set, popping off the first character of each possible
# completion, and then construct a table which uses these
# initial as keys, and the completions that are possible for
# each of these characters are the values for those keys.
if /dfstn[st] then {
# To get strings that start with the same char together,
# sort the current string set (st).
l := sort(st)
newtbl := table()
old_chr := ""
every str := !l do {
str ? { chr := move(1) | next; str := tab(0) }
if old_chr ~==:= chr then {
strset := set([str])
insert(newtbl, chr, strset)
}
else insert(strset, str)
}
insert(dfstn, st, newtbl)
}
# What we've done essentially is to create a table in which
# the keys represent labeled arcs out of the current state,
# and the values represent possible completion sets for those
# paths. What we need to do now is store that table in dfstn
# as the value of the current state-set (i.e. the current
# range of possible completions). Once stored, we can then
# see if there is any arc from the current state (dfstn[st])
# with the label c (dfstn[st][c]). If so, its value becomes
# the new current state (st), and we cycle around again for
# yet another c.
st := \dfstn[st][c] | fail
if *st = 1 & match(s,!st)
then break
}
# Eventually we run out of characters in c. The current state
# (i.e. the set of possible completions) can simply be suspended
# one element at a time, with s prefixed to each element. If, for
# instance, st had contained ["hello","help","hear"] at the outset
# and s was equal to "hel", we would now be suspending "hel" ||
# !set(["lo","p"]).
suspend s || !st
end
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From ralph Sun Apr 14 07:34:25 1991
Date: Sun, 14 Apr 91 07:34:25 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9104141434.AA08467@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Sun, 14 Apr 91 07:34:25 MST
To: icon-group
Subject: Icon Compiler for UNIX Platforms
Icon Compiler for UNIX Platforms
As mentioned earlier, a preliminary release of the optimizing compiler for the
Icon programming language is now available for UNIX platforms. This compiler
generates stand-alone executable files unlike the Icon interpreter. The
compilation process itself is slow compared with the interpreter, but the
resulting executable files run much faster than interpreted ones.
The Icon compiler produces C code, so you'll need a C compiler to use it.
The preliminary release corresponds approximately to Version 7.6 of Icon
and does not have all Version 8 features. Version 8 of the compiler will
be released later.
The compiler is available in two ways: in "object" packages for specific UNIX
platforms and as source code.
If you want to run the compiler and there's an object package for your
platform, all you need to do is pick up the object package and install it,
which is a comparatively simple process.
If there's not an object package for your platform or if you are interested
in the source code, you can get that and build your own compiler. Building
the compiler takes quite a bit of machine time. It also requires about 6MB
of disk space to build.
At present there are object packages for the following UNIX platforms:
DECstation 3100 running Ultrix
HP 9000/300 running HP/UX
HP 9000/800 running HP/UX
Intel 386 running System V
Iris 4D running IRIX
Macintosh running A/UX
NeXT running Mach
PS/2 running AIX
Sequent Symmetry running DYNIX
Sun 3 Workstation running SunOS
Sun 4 Workstation running SunOS
UNIX PC (AT&T 3B1)
VAX running 4.3 BSD
VAX running Ultrix
Implementations for other platforms will be added as they are completed.
To get a copy of the Icon compiler, do an anonymous FTP to cs.arizona.edu.
Then cd to /icon/v8/Compiler. There are three subdirectories, Docs,
Packages, and Source.
The subdirectory Docs contains PostScript for documents relating to the
installation and use of the Icon compiler.
The subdirectory Packages contains object packages in additional
subdirectories, one for each presently supported platform. The subdirectory
names identify the platforms.
The subdirectory Source contains the source code for the Icon compiler.
See the READ.ME files in the various directories for additional information.
Please direct any questions to me, not icon-group.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From @cunyvm.cuny.edu:r1325%CSUOHIO.BITNET@CORNELLC.CIT.CORNELL.EDU Wed Apr 17 08:00:33 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 17 Apr 91 08:00:33 MST
Message-Id: <9104171500.AA19932@optima.cs.arizona.edu>
Received: from CUNYVM.CUNY.EDU by optima.cs.arizona.edu (4.1/15)
id AA19932; Wed, 17 Apr 91 08:00:30 MST
Received: from CSUOHIO.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.2.2MX) with BSMTP id 8353; Wed, 17 Apr 91 11:00:55 EDT
Date: 91/04/17 10:57:37
From: r1325%CSUOHIO.BITNET%CORNELLC.CCS.CORNELL.EDU@cunyvm.cuny.edu
To: icon-group@cs.arizona.edu
Subject: content analysis
APRIL 17, 1991
BEING NEW TO ELETRONIC MAIL.....
I AM RESENDING THIS MESSAGE BECAUSE I'M UNSURE IF IT INITIALLY REACHED
THE ICON-GROUP. I WOULD APPRECIATE ANY RESPONSE TO AFFIRM PROCEDURES ON
THIS END. THANKS.
WE'RE DOING A CONTENT ANALYSIS OF SURVEY DATA THAT REQUIRES MORE
than word frequency counts, something more on the level of a qualitative
factor analysis. I am the research associate at the Child Guidance Center of
Greater Cleveland, a non-profit 401(c)(3) organization. Having purchased the
MS-DOS/386 version of Icon and the book Icon Programming for Humanists late
last year but only being able to upgrade memory beyond 1 meg recently, I'm in
a fix to put together a program (by 4/16/91) beyond word counts. Can anyone
help?
Bill Burkey
Child Guidance Center
2525 E 22
Cleveland, OH 44115
(216)696-5800 x23
bitnet <r1325@csuohio>
From r1325@CSUOHIO.BITNET Wed Apr 17 08:04:56 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 17 Apr 91 08:04:56 MST
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA20395; Wed, 17 Apr 91 08:04:52 MST
Received: from CEARN.cern.ch (MAILER@CEARN) by Arizona.edu with PMDF#10282;
Wed, 17 Apr 1991 08:04 MST
Received: from CSUOHIO.BITNET (R1325) by CEARN.cern.ch (Mailer R2.07B) with
BSMTP id 0002; Wed, 17 Apr 91 17:04:05 GVA
Date: 91/04/17 11:00:20
From: r1325@CSUOHIO.BITNET
Subject: content analysis
To: icon-group@cs.arizona.edu
Message-Id: <134CA64D766014BD@Arizona.edu>
X-Envelope-To: icon-group@cs.arizona.edu
APRIL 17, 1991
BEING NEW TO ELETRONIC MAIL.....
I AM RESENDING THIS MESSAGE BECAUSE I'M UNSURE IF IT INITIALLY REACHED
THE ICON-GROUP. I WOULD APPRECIATE ANY RESPONSE TO AFFIRM PROCEDURES ON
THIS END. THANKS.
WE'RE DOING A CONTENT ANALYSIS OF SURVEY DATA THAT REQUIRES MORE
than word frequency counts, something more on the level of a qualitative
factor analysis. I am the research associate at the Child Guidance Center of
Greater Cleveland, a non-profit 401(c)(3) organization. Having purchased the
MS-DOS/386 version of Icon and the book Icon Programming for Humanists late
last year but only being able to upgrade memory beyond 1 meg recently, I'm in
a fix to put together a program (by 4/16/91) beyond word counts. Can anyone
help?
Bill Burkey
Child Guidance Center
2525 E 22
Cleveland, OH 44115
(216)696-5800 x23
bitnet <r1325@csuohio>
From r1325@CSUOHIO.BITNET Wed Apr 17 08:09:04 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 17 Apr 91 08:09:04 MST
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA20949; Wed, 17 Apr 91 08:09:01 MST
Received: from UKACRL.BITNET (MAILER@UKACRL) by Arizona.edu with PMDF#10282;
Wed, 17 Apr 1991 08:08 MST
Received: from CSUOHIO.BITNET (R1325) by UKACRL.BITNET (Mailer R2.07) with
BSMTP id 9743; Wed, 17 Apr 91 16:04:53 BST
Date: 91/04/17 10:59:10
From: r1325@CSUOHIO.BITNET
Subject: content analysis
To: icon-group@cs.arizona.edu
Message-Id: <13DA5200B660150F@Arizona.edu>
X-Envelope-To: icon-group@cs.arizona.edu
APRIL 17, 1991
BEING NEW TO ELETRONIC MAIL.....
I AM RESENDING THIS MESSAGE BECAUSE I'M UNSURE IF IT INITIALLY REACHED
THE ICON-GROUP. I WOULD APPRECIATE ANY RESPONSE TO AFFIRM PROCEDURES ON
THIS END. THANKS.
WE'RE DOING A CONTENT ANALYSIS OF SURVEY DATA THAT REQUIRES MORE
than word frequency counts, something more on the level of a qualitative
factor analysis. I am the research associate at the Child Guidance Center of
Greater Cleveland, a non-profit 401(c)(3) organization. Having purchased the
MS-DOS/386 version of Icon and the book Icon Programming for Humanists late
last year but only being able to upgrade memory beyond 1 meg recently, I'm in
a fix to put together a program (by 4/16/91) beyond word counts. Can anyone
help?
Bill Burkey
Child Guidance Center
2525 E 22
Cleveland, OH 44115
(216)696-5800 x23
bitnet <r1325@csuohio>
From kelvin@kickapoo.cs.iastate.edu Wed Apr 17 09:36:04 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 17 Apr 91 09:36:04 MST
Received: from judy.cs.iastate.edu by optima.cs.arizona.edu (4.1/15)
id AA24333; Wed, 17 Apr 91 09:36:01 MST
Received: from kickapoo.cs.iastate.edu.noname by judy.cs.iastate.edu (4.1) id AA15899; Wed, 17 Apr 91 11:35:13 CDT
Received: by kickapoo.cs.iastate.edu.noname (4.1/SMI-4.1)
id AA06833; Wed, 17 Apr 91 11:35:13 CDT
Date: Wed, 17 Apr 91 11:35:13 CDT
From: kelvin@kickapoo.cs.iastate.edu (Kelvin Don Nilsen)
Message-Id: <9104171635.AA06833@kickapoo.cs.iastate.edu.noname>
To: r1325%CSUOHIO.BITNET%CORNELLC.CCS.CORNELL.EDU@cunyvm.cuny.edu
Cc: icon-group@cs.arizona.edu
In-Reply-To: r1325%CSUOHIO.BITNET%CORNELLC.CCS.CORNELL.EDU@cunyvm.cuny.edu's message of 91/04/17 10:57:37 <9104171500.AA19932@optima.cs.arizona.edu>
Subject: content analysis
>Date: 91/04/17 10:57:37
>From: r1325%CSUOHIO.BITNET%CORNELLC.CCS.CORNELL.EDU@cunyvm.cuny.edu
>APRIL 17, 1991
>BEING NEW TO ELETRONIC MAIL.....
>I AM RESENDING THIS MESSAGE BECAUSE I'M UNSURE IF IT INITIALLY REACHED
>THE ICON-GROUP. I WOULD APPRECIATE ANY RESPONSE TO AFFIRM PROCEDURES ON
>THIS END. THANKS.
>WE'RE DOING A CONTENT ANALYSIS OF SURVEY DATA THAT REQUIRES MORE
>than word frequency counts, something more on the level of a qualitative
>factor analysis. I am the research associate at the Child Guidance Center of
>Greater Cleveland, a non-profit 401(c)(3) organization. Having purchased the
>MS-DOS/386 version of Icon and the book Icon Programming for Humanists late
>last year but only being able to upgrade memory beyond 1 meg recently, I'm in
>a fix to put together a program (by 4/16/91) beyond word counts. Can anyone
>help?
>Bill Burkey
>Child Guidance Center
>2525 E 22
>Cleveland, OH 44115
>(216)696-5800 x23
>bitnet <r1325@csuohio>
i'm not sure i understand what your needs are. are you looking for an
Icon programmer to do volunteer work for you? are you trying to find
an off-the-shelf package that does "qualitative factor analysis"? what
exactly do you mean by "qualitative factor analysis"? what is the point
you are trying to make about 4/16/91? is this your deadline? is this
when you want the volunteers to be done? or is this just the date on
which you composed your message (which would be redundant and wrong, since
you date the article 4/17/91)?
perhaps it would be helpful if you could provide a sample survey response,
and accompany this with the sort of analysis report that you expect the
icon program to provide for you.
by the way, your message did reach the icon group.
Kelvin Nilsen/Dept. of Computer Science/Iowa State University/Ames, IA 50011
(515) 294-2259 kelvin@cs.iastate.edu uunet!atanasoff!kelvin
From icon-group-request@arizona.edu Thu Apr 18 21:13:09 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 18 Apr 91 21:13:09 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA08983; Thu, 18 Apr 91 21:13:03 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 18 Apr
1991 21:03 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA04514; Thu, 18 Apr 91
20:53:55 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 18 Apr 1991 21:03 MST
Date: 18 Apr 91 14:27:01 GMT
From: hsi!mlfarm!ron@uunet.uu.net (Ronald Florence)
Subject: cron.icn
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <4952B9C1B6800D32@Arizona.edu>
Message-Id: <797@mlfarm.com>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Maple Lawn Farm, Stonington, CT
A friend who takes a mail/news feed from us with an ms-dos system
wanted to be able to poll when he was on-the-road. I know next to
nothing about ms-dos, don't want to learn about things like TSRs, and
Icon is the only language our systems share. This was the quick &
dirty solution. The busy-loops are dumb (I anticipate flames), but
Icon tables made this fun.
I'd urge NOT running this code on a multi-tasking system like Unix,
unless you're interested in seeing how high your system load can
reach.
--
Ronald Florence ron@mlfarm.com
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# cron.icn
# This archive created: Thu Apr 18 10:25:34 1991
# By: Ronald Florence (Maple Lawn Farm, Stonington, CT)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'cron.icn'
then
echo shar: "will not over-write existing file 'cron.icn'"
else
cat << \SHAR_EOF > 'cron.icn'
############################################################################
#
# Name: cron.icn
#
# Title: Cron Daemon
#
# Author: Ronald Florence (ron@mlfarm.com)
#
# Date: 18 April 1991
#
# Version: 1.0
#
############################################################################
#
# This program provides a crude cron daemon for ms-dos or other
# single-tasking systems. If a scheduled command fails, it is
# retried at a specified interval.
#
# usage: cron [-r] [-c cmd] [-t tries] [-i interval] 0-23 [0-59]
# cron < cron-table [ > cron.log ]
#
# The command-line usage invokes a single command at a specified time.
# The -r option runs the daemon continuously. Defaults for the command,
# interval, and retries can be specified in the code. The second usage
# reads an ascii table in the following format:
#
# # hour minute interval retries command
# 0 15 5 3 uuio | mail postmaster
# 1 35 0 0 rnews *.nws
# 6 30 2 2 make coffee
#
# Lines beginning with `#' in the table are treated as comments.
#
############################################################################
#
# Link: options
# Bugs: This busy-loop should NOT be run on multi-tasking systems.
# Commands scheduled at conflicting times may not be invoked.
# The cron-table is not compatible with Unix cron tables.
#
############################################################################
link options
procedure main(arg)
usage := ["usage: cron [-r] [-c cmd] [-t tries] [-i interval] 0-23 [0-59]",
" cron < cron-table"]
default_cmd := "uuio"
default_interval := 5
default_retries := 3
cmd := table(0)
interval := table(0)
retries := table(0)
if *arg > 0 then {
opts := options(arg, "c:i+t+r")
h := integer(arg[1])
m := integer(arg[2]) | 0
(/h | h < 0 | h > 23 | m < 0 | m > 59 ) & { every write(!usage); exit(-1) }
t := h * 3600 + m * 60
cmd[t] := \opts["c"] | default_cmd
interval[t] := \opts["i"] | default_interval
retries[t] := \opts["t"] | default_retries
}
else every s := !&input do s ? {
="#" & next
tmp := []
while tab(upto(&digits)) \4 do put(tmp,tab(many(&digits)))
t := pop(tmp) * 3600 + pop(tmp) * 60
interval[t] := pop(tmp)
retries[t] := pop(tmp)
cmd[t] := (tab(many(' \t')), tab(0))
}
write(&errout, "time\tint\tret\tcommand")
write(&errout, "-------------------------------")
every t := key(cmd) do
write(&errout, right(t/3600, 2, "0"), ":", left((t % 3600)/60, 2, "0"),
"\t", interval[t], "\t", retries[t], "\t", cmd[t])
while t := now() do (t = key(cmd)) & {
try := 0
repeat {
(system(cmd[t]) = 0) & {
write(cmd[t], " completed ", &dateline)
while t = now()
break
}
write(cmd[t], " FAILED ", &dateline)
((try +:= 1) >= retries[t]) & break
repoll := now() + interval[t] * 60
while repoll > now()
}
(*arg = 0) | \opts["r"] | exit(try)
}
end
procedure now()
time := []
&clock ? while tab(upto(&digits)) do put(time,tab(many(&digits)))
return time[1] * 60 * 60 + time[2] * 60 + time[3]
end
SHAR_EOF
if test 3218 -ne "`wc -c < 'cron.icn'`"
then
echo shar: "error transmitting 'cron.icn'" '(should have been 3218 characters)'
fi
fi
exit 0
# End of shell archive
--
Ronald Florence ron@mlfarm.com
From icon-group-request@arizona.edu Sun Apr 21 19:53:33 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 21 Apr 91 19:53:33 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA17113; Sun, 21 Apr 91 19:53:24 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sun, 21 Apr
1991 19:52 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03934; Sun, 21 Apr 91
19:47:42 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 21 Apr 1991 19:52 MST
Date: 21 Apr 91 13:31:23 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: Klondike solitaire, v3.01, part 2/6
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <9AEB29664C80079A@Arizona.edu>
Message-Id: <1942@hslrswi.hasler.ascom.ch>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# klonstr.icn
# getchlib.icn
# This archive created: Sun Apr 21 15:03:15 1991
# By: Norman H. Azadian (Hasler AG)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'klonstr.icn'" '(5135 characters)'
if test -f 'klonstr.icn'
then
echo shar: will not over-write existing file "'klonstr.icn'"
else
cat << \SHAR_EOF > 'klonstr.icn'
#klonstr.icn 910309 NHA
#Routines to implement strategic play for klondike solitaire.
#For each strategy there is a procedure with the same name.
#findBest() is the interface to the rest of klondike.
# t a k e F i r s t
# This strategy is the simplest possible, simply taking the first suggestion
# proffered by suggest(). Equivalent to find1().
# Note that it is therefore dependent on the exact implementation of suggest().
# When Thumbing, terminate upon second occurrence of *deckDown = 0.
procedure takeFirst ()
local emptySeen, s
until (\emptySeen) & (*deckDown = 0) do {
/emptySeen := (*deckDown = 0)
(s := suggest()) & return (s || "0") #good move found
((*deckUp + *deckDown) = 0) & break #no cards to thumb through
writeInfo (Vbold || "T" || Vnormal || "humb")
push (ops, thumb())
}
fail #nothing left to do
end #takeFirst
# i n t e r a c t i v e
# For multi-choice positions, allows the user to choose.
procedure interactive ()
local suggestions, emptySeen, s, op
until (\emptySeen) & (*deckDown = 0) do {
/emptySeen := (*deckDown = 0)
suggestions := [] #generate a new list of suggestions
every put (suggestions, suggest())
(1 = *suggestions) & (return (suggestions[1] || "0")) #one possibility
if (1 < *suggestions) then { #multiple -- user picks
outputAt (lineCount, 40, VclearEOL, Vreverse)
every s := !suggestions do writes (s[2:0], " ")
writeInfo (Vblink || "choose a move")
until any(cset("123456789abc"[1+:*suggestions]), (s := getch())) do
complain()
op := suggestions["16r" || s]
outputAt (lineCount, 40, VclearEOL, Vnormal)
every s := !suggestions do
if s == op then
output (Vreverse, op[2:0], Vnormal, " ")
else
writes (s[2:0], " ")
return (op || "0")
}
# no useful moves found -- thumb
((*deckUp + *deckDown) = 0) & break #no cards to thumb through
writeInfo (Vbold || "T" || Vnormal || "humb")
push (ops, thumb())
}
fail #nothing left to do
end #interactive
# d e c k F i r s t
# The idea here is that, if possible, nothing will get done in this
# pass through the deck until a card has been taken from the deck.
# Otherwise, the strategy is simply takeFirst.
# We run with automaticAce disabled simply so we can know when
# we take one from the deck.
# Since there is no way to know that we are starting a new game, we cannot
# guarantee that the flags are correct in the event of user intervention.
procedure deckFirst ()
local s
static taken, modified
initial {
taken := &null #assume nothing taken from deck yet
modified := &null #nothing done yet on this pass
}
automaticAce := &null
repeat {
every s := suggest() do
if (\taken) | (s[2] == "D") then {
modified := taken := 1 #[sic]
return (s || "0")
}
((*deckUp + *deckDown) = 0) & break #no cards to thumb through
writeInfo (Vbold || "T" || Vnormal || "humb")
push (ops, thumb())
if 0 = *deckDown then #end of a pass through the deck
if \modified then
modified := taken := &null #normal case -- reset flags
else
if \taken then
break #nothing left to do [sic]
else
taken := 1 #allow other moves for next pass
}
modified := taken := null #reset flags for next game
fail #nothing useful left to do
end #deckFirst
# f i n d B e s t
# If called with a parameter, the parameter is taken to be the name of a play
# strategy and is saved for future use by findBest() after sanity checking.
# An empty string is taken to be a request to use the default strategy.
# Note that, at least for now, the name of the strategy procedure is
# necessarily identical to the name of the strategy.
#
# If called without any parameter, returns with the move selected by the
# pre-determined strategy routine.
# Largely for hysterical raisons, strategy routines are expected to do their
# own Thumbing until either they find a good move to return, or they decide
# there is no point to continuing and so return failure.
# Strategy routines are expected to keep the user informed of any moves
# (e.g. Thumbing) that they do before returning.
#
# Note that the strategy procedure may decide it is necessary to
# unilaterally disable the automaticAce option during its execution.
# Therefore automaticAce is saved here and restored before returning.
# However, if the strategy procedure leaves automaticAce intact, then
# any Ace uncovered whilst thumbing will be automaticall moved and the
# search will continue. It does not count as a move.
procedure findBest (s)
static strategies, strategyProc
local automaticAceSave
initial {
strategies := set ( ["takeFirst", "interactive", "deckFirst"] )
}
if \s then { #remember strategy
(s == "") & (s := "takeFirst") #default strategy
(s == !strategies) | stop ("klondike: unknown strategy ", s)
strategyProc := (strategy := s) #remember for future use
} else { #execute strategy
automaticAceSave := automaticAce
s := strategyProc()
automaticAce := automaticAceSave
(s === &null) & fail
}
return s
end #findBest
SHAR_EOF
if test 5135 -ne "`wc -c < 'klonstr.icn'`"
then
echo shar: error transmitting "'klonstr.icn'" '(should have been 5135 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'getchlib.icn'" '(9166 characters)'
if test -f 'getchlib.icn'
then
echo shar: will not over-write existing file "'getchlib.icn'"
else
cat << \SHAR_EOF > 'getchlib.icn'
############################################################################
#
# Name: getchlib.icn
#
# Title: Implementation of getch() for Unix (and more)
#
# Author: Richard L. Goerwitz
#
# Version: 1.13
#
############################################################################
#
# I place this and future versions of getchlib in the public domain - RLG
#
############################################################################
#
# Implementing getch() is a much, much more complex affair under Unix
# than it is under, say, MS-DOS. This library represents one,
# solution to the problem - one which can be run as a library, and
# need not be compiled into the run-time system. Note that it will
# not work on all systems. In particular, certain Suns (with a
# screwy stty command) and the NeXT 1.0 OS (lacking the -g option for
# stty) do not run getchlib properly. See the bugs section below for
# workarounds.
#
# Four basic utilities are included here:
#
# getch() - waits until a keystroke is available &
# returns it without displaying it on the screen
# getche() - same as getch() only with echo
# getse(s) - like getche() only for strings. The optional
# argument s gives getse() something to start with. Use this
# if, say, you want to read single characters in cbreak mode,
# but get more input if the character read is the first part
# of a longer command. If the user backspaces over everything
# that has been input, getse() fails. Returns on \r or \n.
# reset_tty() - absolutely vital routine for putting the cur-
# rent tty line back into cooked mode; call it before exiting
# or you will find yourself with a locked-up terminal; use it
# also if you must temporarily restore the terminal to cooked
# mode
#
# Note that getse() *must* be used in place of read(&input) if you
# are planning on using getch() or getche(), since read(&input)
# assumes a tty with "sane" settings.
#
# Warning: The routines below do not do any sophisticated output
# processing. As noted above, they also put your tty line in raw
# mode. I know, I know: "Raw is overkill - use cbreak." But in
# a world that includes SysV, one must pick a lowest common denomi-
# nator. And no, icanon != cbreak.
#
# BUGS: These routines will not work on systems that do not imple-
# ment the -g option for the stty command. The NeXT workstation is
# an example of such a system. Tisk, tisk. If you have a SunOS stty
# that is too clever (read stupid) to write its output to a pipe,
# then substitute /usr/5bin/stty (or whatever your system calls the
# System V stty command) for /bin/stty in this file. If you have no
# SysV stty command online, then you can try replacing every instance
# of "stty -g 2>&1" below with "stty -g 2>&1 1> /dev/tty" or
# something similar.
#
############################################################################
#
# Example program:
#
# The following program is a simple file viewer. To run, it
# needs to be linked with itlib.icn, iscreen.icn, and this file
# (getchlib.icn).
#
# procedure main(a)
#
# # Simple pager/file searcher for Unix systems. Must be linked
# # with itlib.icn and iscreen.icn.
#
# local intext, c, s
#
# # Open input file
# intext := open(a[1],"r") | {
# write(&errout,"Can't open input file.")
# exit(1)
# }
#
# # Initialize screen
# clear()
# print_screen(intext) | exit(0)
#
# # Prompt & read input
# repeat {
# iputs(igoto(getval("cm"), 1, getval("li")))
# emphasize()
# writes("More? (y/n or /search):")
# write_ce(" ")
# case c := getche() of {
# "y" : print_screen(intext) | break
# " " : print_screen(intext) | break
# "n" : break
# "q" : break
# "/" : {
# iputs(igoto(getval("cm"), 1, getval("li")))
# emphasize()
# writes("Enter search string:")
# write_ce(" ")
# pattern := GetMoreInput()
# /pattern | "" == pattern & next
# # For more complex patterns, use findre() (IPL findre.icn)
# if not find(pattern, s := !intext) then {
# iputs(igoto(getval("cm"), 1, getval("li")))
# emphasize()
# write_ce("String not found.")
# break
# }
# else print_screen(intext, s) | break
# }
# }
# }
#
# reset_tty()
# write()
# exit(0)
#
# end
#
# procedure GetMoreInput(c)
#
# local input_string
# static BS
# initial BS := getval("bc") | "\b"
#
# /c := ""
# if any('\n\r', chr := getch())
# then return c
# else {
# chr == BS & fail
# writes(chr)
# input_string := getse(c || chr) | fail
# if any('\n\r', input_string)
# then fail else (return input_string)
# }
#
# end
#
# procedure print_screen(f,s)
#
# if /s then
# begin := 1
# # Print top line, if one is supplied
# else {
# iputs(igoto(getval("cm"), 1, 1))
# write_ce(s ? tab(getval("co") | 0))
# begin := 2
# }
#
# # Fill the screen with lines from f; clear and fail on EOF.
# every i := begin to getval("li") - 1 do {
# iputs(igoto(getval("cm"), 1, i))
# if not write_ce(read(f) ? tab(getval("co") | 0)) then {
# # Clear remaining lines on the screen.
# every j := i to getval("li") do {
# iputs(igoto(getval("cm"), 1, j))
# iputs(getval("ce"))
# }
# iputs(igoto(getval("cm"), 1, i))
# fail
# }
# }
# return
#
# end
#
# procedure write_ce(s)
#
# normal()
# iputs(getval("ce")) |
# writes(repl(" ",getval("co") - *s))
# writes(s)
# return
#
# end
#
############################################################################
#
# Requires: UNIX
#
# Links: itlib.icn
#
############################################################################
global c_cc, current_mode # what mode are we in, raw or cooked?
record termio_struct(vintr,vquit,verase,vkill)
procedure getse(s)
# getse() - like getche, only for strings instead of single chars
#
# This procedure *must* be used instead of read(&input) if getch
# and/or getche are to be used, since these put the current tty
# line in raw mode.
#
# Note that the buffer can be initialized by calling getse with a
# string argument. Note also that, as getse now stands, it will
# fail if the user backspaces over everything that has been input.
# This change does not coincide with its behavior in previous ver-
# sions. It can be changed by commenting out the line "if *s < 1
# then fail" below, and uncommenting the line "if *s < 1 then
# next."
local chr
static BS
initial {
BS := getval("bc") | "\b"
if not getval("bs") then {
reset_tty()
stop("Your terminal can't backspace!")
}
}
/s := ""
repeat {
case chr := getch() | fail of {
"\r"|"\n" : return s
c_cc.vkill : {
if *s < 1 then next
every 1 to *s do writes(BS)
s := ""
}
c_cc.verase : {
# if *s < 1 then next
writes(BS) & s := s[1:-1]
if *s < 1 then fail
}
default: writes(chr) & s ||:= chr
}
}
end
procedure setup_tty()
change_tty_mode("setup")
return
end
procedure reset_tty()
# Reset (global) mode switch to &null to show we're in cooked mode.
current_mode := &null
change_tty_mode("reset")
return
end
procedure getch()
local chr
# If the global variable current_mode is null, then we have to
# reset the terminal to raw mode.
if /current_mode := 1 then
setup_tty()
chr := reads(&input)
case chr of {
c_cc.vintr : reset_tty() & stop() # shouldn't hard code this in
c_cc.vquit : reset_tty() & stop()
default : return chr
}
end
procedure getche()
local chr
# If the global variable current_mode is null, then we have to
# reset the terminal to raw mode.
if /current_mode := 1 then
setup_tty()
chr := reads(&input)
case chr of {
c_cc.vintr : reset_tty() & stop()
c_cc.vquit : reset_tty() & stop()
default : writes(chr) & return chr
}
end
procedure change_tty_mode(switch)
# global c_cc (global record containing values for kill, etc. chars)
local get_term_params, i
static reset_string
initial {
getval("li") # check to be sure itlib is set up
find("unix",map(&features)) |
stop("change_tty_mode: These routines must run under Unix.")
get_term_params := open("/bin/stty -g 2>&1","pr")
reset_string := !get_term_params
close(get_term_params)
reset_string ? {
# tab upto the fifth field of the output of the stty -g cmd
# fields of stty -g seem to be the same as those of the
# termio struct, except that the c_line field is missing
every 1 to 4 do tab(find(":")+1)
c_cc := termio_struct("\x03","\x1C","\x08","\x15")
every i := 1 to 3 do {
c_cc[i] := char(integer("16r"||tab(find(":"))))
move(1)
}
c_cc[i+1] := char(integer("16r"||tab(0)))
}
}
if switch == "setup"
then system("/bin/stty -echo raw")
else system("/bin/stty "||reset_string)
return
end
SHAR_EOF
if test 9166 -ne "`wc -c < 'getchlib.icn'`"
then
echo shar: error transmitting "'getchlib.icn'" '(should have been 9166 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Sun Apr 21 19:53:56 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 21 Apr 91 19:53:56 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA17123; Sun, 21 Apr 91 19:53:51 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sun, 21 Apr
1991 19:52 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03962; Sun, 21 Apr 91
19:48:29 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 21 Apr 1991 19:53 MST
Date: 21 Apr 91 14:08:13 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: Klondike solitaire, v3.01, part 5/6
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <9AF6F9FF2C800E1B@Arizona.edu>
Message-Id: <1945@hslrswi.hasler.ascom.ch>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# klonsub.icn
# This archive created: Sun Apr 21 15:04:30 1991
# By: Norman H. Azadian (Hasler AG)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'klonsub.icn'" '(14804 characters)'
if test -f 'klonsub.icn'
then
echo shar: will not over-write existing file "'klonsub.icn'"
else
cat << \SHAR_EOF > 'klonsub.icn'
#klonsub.icn 901029 NHA
#some subroutines for Klondike
# d i e I f
# If the first argument succeeds, then write out the remaining args & die.
# Note that the remaining arguments must succeed.
procedure dieIf (failed, writeArgs[])
writeCursor (1, 20)
every writes (&output, !writeArgs)
write (&output)
display ()
every writes (&errout, !writeArgs)
write (&errout)
runerr (500)
end #dieIf
# f i t O n S t a c k
# Given a card and a stack number, fail unless card can be added to the stack.
# Note that we disallow putting an Ace on a stack, period. This prevents
# ever building a stack with 13 cards, which we can't display in 25 rows.
procedure fitOnStack (c, n)
if *stackUp[n] = 0 then {
dieIf (*stackDown[n] ~= 0, "Up empty, Down not")
(c.rank = 13) | fail #only a king can go to empty stack
} else {
(c.rank = (stackUp[n][-1].rank - 1)) | fail #top wrong rank
(color[c.suit] == color[stackUp[n][-1].suit]) & fail #top same color
(c.rank = 1) & fail #no aces on stak
dieIf (*stackUp[n] >= 12, "stack too big")
}
return #success
end #fitOnStack
# s u g g e s t
# Suggest a(nother) possible (useful) move in this situation.
# Suspends with an operation string for the suggested move.
# Fails if there is none and you should Thumb.
# This internal routine is currently the heart and soul of all program play.
procedure suggest ()
local i, j, k
# look at deckUp to see if the top card fits on an ace pile
(deckUp[1].rank = (pile[deckUp[1].suit] + 1)) & suspend "MDA"
# look at deckUp to see if the top card fits on a stack
every (fitOnStack (deckUp[1], i := 1 to 7)) do suspend "MD" || string(i)
# look at each stack to see if top card can be put on an ace pile
every (stackUp[i := 1 to 7][-1].rank = pile[stackUp[i][-1].suit] + 1) do
suspend "M" || string(i) || "A"
# look at each stack to see if one can be (usefully) moved to another
every fitOnStack (stackUp[i := 7 to 1 by -1][1], j := 1 to 7) do
if 0 < *stackDown[i] then
suspend "M" || string(i) || string(j)
else
# possibility, but since there are no cards hidden under
# this pile, we reject it UNLESS there are no empty slots
# AND at least one of the following is true:
# (1) deckUp[1].rank = 13
# (2) there is a king with cards hidden beneath it
if not (*stackUp[1 to 7] = 0) then
if deckUp[1].rank = 13 then
suspend "M" || string(i) || string(j) #(1)
else
# only suspend once, no matter how many kings there are
if ( (stackUp[k := 1 to 7][1].rank = 13) &
(0 < *stackDown[k]) ) then
suspend "M" || string(i) || string(j) #(2)
# punt (Thumb)
fail
end #suggest
# c h e c k 4 a c e
# Only has an effect when global automaticAce is set!
# Given a stack number, check for an ace as the top of stackUp[n].
# If present, move it over to it's ace pile, turn over the next card
# from stackDown, and check again.
# Must not be more than one up card in stack.
# Returns a string of the operations performed.
procedure check4ace (n)
local c, op
op := ""
if \automaticAce then {
dieIf (1 < *stackUp[n])
while stackUp[n][1].rank = 1 do {
op ||:= (c := pop (stackUp[n])).suit #remove ace from the stack
writeStack (n)
pile[c.suit] := 1 #move to ace pile
writePile (c.suit)
click ()
if push (stackUp[n], get(stackDown[n])) then { #turn over card
writeStack (n)
click ()
}
}
}
return op
end #check4ace
# m o v e S t a c k
# Move a stack to another stack, no questions asked.
# Updates video and audio.
# Returns any automatic ace operations that were done as a consequence.
##It would be nice to do this in a visually and audibly more satisfying way
procedure moveStack (src, dst)
# move up cards from src stack to dst stack
while put (stackUp[dst], get(stackUp[src]))
writeStack (src)
writeStack (dst)
click ()
# turn over new card (if any) on src stack
put (stackUp[src], get(stackDown[src])) | return "" #empty stackDown
writeStack (src)
click ()
return check4ace (src)
end #moveStack
# m o v e 1
# This is the internal move, taking an operation string. No Thumbs allowed.
# Upon success it returns the (possibly modified) operation string.
# There's some redundant code here, but it makes the action look better
# (at least on slow machines).
procedure move1 (op)
local src, dst, c
dieIf ((op[1] ~== "M"), op)
src := op[2]
dst := op[3]
if src == "D" then { # Deck -> somewhere
c := deckUp[1]
if dst == "A" then { # Deck -> Ace
if c.rank = (pile[c.suit] + 1) then {
op[4] := c.suit # Deck -> Ace: fits - do it
pop (deckUp)
writeDeckUp ()
pile[c.suit] +:= 1
writePile (c.suit)
} else {
fail # Deck -> Ace: doesn't fit
}
} else { # Deck -> stack
if fitOnStack (c, dst) then {
pop (deckUp) # Deck -> stack: fits - do it
writeDeckUp ()
put (stackUp[dst], c)
writeStack (dst)
} else {
fail # Deck -> stack: doesn't fit
}
}
click ()
if \automaticAce then {
while deckUp[1].rank = 1 do {
op ||:= (c := pop(deckUp)).suit
writeDeckUp ()
pile[c.suit] := 1
writePile (c.suit)
click ()
}
}
} else { # stack -> somewhere
if dst == "A" then { # stack -> Ace
c := stackUp[src][-1] #copy of card on top of stack
if c.rank = (pile[c.suit] + 1) then {
op[4] := c.suit # stack -> Ace: fits - do it
pull (stackUp[src])
writeStack (src)
pile[c.suit] +:= 1
writePile (c.suit)
click ()
if 0 = *stackUp[src] then {
op[4] +:= 4 #mark this case for undo()
put (stackUp[src], get(stackDown[src])) #turn over a card
writeStack (src)
if 0 < *stackUp[src] then {
click ()
op ||:= check4ace (src)
}
}
} else {
fail # stack -> Ace: doesn't fit
}
} else { # stack -> stack
if fitOnStack (stackUp[src][1], dst) then {
# stack -> stack: fits - do it
op[4] := "123456789abcdef"[*stackUp[src]]
op ||:= moveStack (src, dst)
} else {
fail # stack -> stack: doesn't fit
}
}
}
return op #success
end #move1
# t h u m b
# Move to next spot in deckDown
# Returns the operation performed (usually just "T3"), or fail if none possible.
procedure thumb ()
local c, op
((*deckDown) = (*deckUp) = 0) & (complain(), fail) #no cards left
if 0 = *deckDown then { #no cards left in hand
while push (deckDown, pop(deckUp)) #pick up (and turn) the face-up deck
writeDeckUp () #show the (empty) deck on table
writeDeckDown () #show the face-down deck [in hand]
click ()
}
op := ( "T" || ((*deckDown >= 3) | *deckDown) )
every | push (deckUp, pop(deckDown)) \ 3
writeDeckDown ()
writeDeckUp ()
click ()
if \automaticAce then {
while deckUp[1].rank = 1 do {
op ||:= (c := pop (deckUp)).suit
writeDeckUp ()
pile[c.suit] := 1
writePile (c.suit)
click ()
}
}
return op
end #thumb
# u n d o
# Backup one move, including any automatic ace moves
# This is the internal routine.
procedure undo ()
local op, suit
if op := pop (ops) then {
writeInfo (expandOp(op))
# op looks like: Msdixxx
# where x is an [optional] number 1..4 of an ace pile
# and s is either a stack number or "D"
# and d is either "A" or a number 1..7 of a stack
# and i is an extra piece of info which is only occasionally used
case op[1] of {
"M" : {
dieIf ((*op < 4) | ((/automaticAce) & (4 < *op)), op)
if op[2] == "D" then {
#Move cards from Ace piles to deck, starting at end
while 4 < *op do {
suit := op[-1]
pile[suit] := 0
writePile (suit)
push (deckUp, card(suit,1))
writeDeckUp ()
click ()
op[-1] := ""
}
if op[3] == "A" then {
# unMove Deck to Ace op[4]
suit := op[4]
push (deckUp, card(suit,pile[suit]))
pile[suit] -:= 1
writePile (suit)
} else {
# unMove Deck to stack op[3]
push (deckUp, pull(stackUp[op[3]]))
writeStack (op[3])
}
writeDeckUp ()
} else {
#Move cards from Ace piles to stack, starting at end
while 4 < *op do {
suit := op[-1]
pile[suit] := 0
writePile (suit)
dieIf (1 < *stackUp[op[2]], op)
push (stackDown[op[2]], pull(stackUp[op[2]]))
push (stackUp[op[2]], card(suit,1))
writeStack (op[2])
click ()
op[-1] := ""
}
if op[3] == "A" then {
# unMove stack op[2] to Ace pile op[4]
if 4 < (suit := op[4]) then {
suit -:= 4 #ace pile card was last on stack
dieIf (1 < *stackUp[op[2]], op)
push (stackDown[op[2]], pull(stackUp[op[2]]))
}
put (stackUp[op[2]], card(suit,pile[suit]))
pile[suit] -:= 1
writePile (suit)
writeStack (op[2])
} else {
# unMove top op[4] cards on stack op[2]
# to stack op[3]
dieIf (1 < *stackUp[op[2]], op)
push (stackDown[op[2]], pull(stackUp[op[2]]))
every 1 to ("16r" || op[4]) do
push (stackUp[op[2]], pull(stackUp[op[3]]))
writeStack (op[3])
writeStack (-op[2])
}
}
}
"T" : {
dieIf (((/automaticAce) & (*op ~= 2)), op)
## op looks like: Tcxx
## where c is the number of cards thumbed (usually 3)
## and x is an optional number 1..4 of an ace pile
## There can be 0,1,2, or 3 of these x's.
# move cards from Ace piles to deck, starting at end
while 2 < *op do {
suit := op[-1]
pile[suit] := 0
writePile (suit)
push (deckUp, card(suit,1))
writeDeckUp ()
click ()
op[-1] := ""
}
# then undo the Thumb operation itself
dieIf (0 = *deckUp)
every 1 to op[2] do
push (deckDown, pop(deckUp))
if 0 = *deckUp then
while push (deckUp, pop(deckDown))
writeDeckUp ()
writeDeckDown ()
}
default : runerr (500, op)
}
click ()
} else {
## Admittedly this is a bit of a kluge, but better than nothing ?
(0 = *deckDown) & while push (deckDown, pop(deckUp))
writeDeckUp ()
writeDeckDown ()
complain ("At Beginning")
}
return
end #undo
# s h o w L i s t
# Display a list of cards at the current cursor position.
# Intended for debugging only .
procedure showList (lst)
local c
every c := !lst do
output (color[c.suit], rankID[c.rank], suitID[c.suit], Vnormal, " ")
return
end #showList
# c a r d 2 s t r
# Given a list of card records, returns a string representation.
# Even an empty list results in a non-zero string length.
procedure card2str (lst)
local c, s
s := "$"
every c := !lst do
s ||:= string(c.suit) || "123456789abcd"[c.rank]
return s
end #card2str
# s t r 2 c a r d
# Given a string [as generated by card2str()],
# return corresponding list of card records.
# Fails if the string is invalid.
procedure str2card (s)
local cc, i
(s[i:=1] == "$") | fail
cc := []
while put (cc, card(s[i+:=1], integer("14r"||s[i+:=1])))
return cc
end #str2card
# s a v e S t a t e
# Saves the current state in the named file, which is created/overwritten
# as necessary.
# Fails if the state was not successfully saved.
# Obviously the ordering here must exactly match that in restoreState().
procedure saveState (filename)
local f, i
(f := open ((directory || filename), "c")) | fail
write (f, &dateline)
write (f, firstSeed)
write (f, lastSeed)
write (f, &random)
every write (f, !pile)
every write (f, card2str(!stackUp))
every write (f, card2str(!stackDown))
write (f, card2str(deckUp))
write (f, card2str(deckDown))
write (f, totalGames)
write (f, totalWins)
write (f, totalAces)
every write (f, !ops)
return close (f)
end #saveState
# r e s t o r e S t a t e
# Restore game from the named file.
# Fails if the file isn't there, isn't readable, or isn't correct format.
# Otherwise returns date the file was last written.
# Note that we do not update the screen here !!
# Obviously the ordering here must exactly match that in saveState().
procedure restoreState (filename)
local f, date
(f := open ((directory || filename), "r")) | fail
(25 < *(date := read(f))) | fail
firstSeed := read (f)
lastSeed := read (f)
&random := read (f)
every ((!pile) := read(f))
every ((!stackUp) := str2card (read(f)))
every ((!stackDown) := str2card (read(f)))
deckUp := str2card (read(f))
deckDown := str2card (read(f))
totalGames := read (f)
totalWins := read (f)
totalAces := read (f)
ops := []
while push (ops, read (f))
dieIf (not close (f), f)
return date
end #restoreState
# i n i t V a r i a b l e s
# Initialize the various lists so that everyone can reference them.
procedure initVariables ()
ops := [] #no operations done yet
deckUp := [] #deck in hand, face-up
deckDown := [] #deck in hand, face-down
stackUp := list(7, 0) #columns on table, face up
stackDown := list(7, 0) #columns on table, face down
pile := list(4, 0) #aces - only top rank stored
every put (deckDown, card(1 to 4, 1 to 13)) #take cards out of the box
return
end #initVariables
# n e w G a m e
# Set up all the global variables for a new game.
# Returns the seed used to generate this game.
procedure newGame ()
local i, j, s, seed
initScreen ()
initVariables () #reset everything to ground zero
writeInfo (Vblink || "Shuffling")
seed := &random
every | (?deckDown :=: ?deckDown) \ 123
writeInfo ("")
every !stackUp := []
every !stackDown := []
every push(stackUp[i := 1 to 7], get(deckDown)) do {
writeStack (-i)
click ()
every push (stackDown[j := i+1 to 7], get(deckDown)) do {
writeStack (-j)
click ()
}
### writeStack (-i) ### this could replace 2 calls above
}
writeDeckDown(1)
#handle any Aces which are showing
every *(s := check4ace (i := 1 to 7)) ~= 0 do
push (ops, "M" || string(i) || "A" || string(integer(s) + 4))
return seed
end #newGame
# e x p a n d O p
# Given an operation string, return an expanded human-readable equivalent.
procedure expandOp (op)
static opChars
local s
initial {
opChars := table("oops!")
opChars["A"] := Vbold || "A" || Vnormal || "ce"
opChars["D"] := Vbold || "D" || Vnormal || "eck"
every opChars[s := !"1234567"] := Vbold || s || Vnormal
}
# This slightly more efficient scheme assumes op[1] is 1st char of result
return (Vbold || op[1] || Vnormal ||
case op[1] of {
"M" : ( "ove " || opChars[op[2]] || " to " || opChars[op[3]] )
"Q" : "uit"
"T" : "humb"
default : runerr (500, op)
})
end #expandOp
SHAR_EOF
if test 14804 -ne "`wc -c < 'klonsub.icn'`"
then
echo shar: error transmitting "'klonsub.icn'" '(should have been 14804 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Sun Apr 21 19:54:23 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 21 Apr 91 19:54:23 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA17137; Sun, 21 Apr 91 19:54:14 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sun, 21 Apr
1991 19:53 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03923; Sun, 21 Apr 91
19:47:22 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 21 Apr 1991 19:53 MST
Date: 21 Apr 91 13:29:42 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: Klondike release, v3.01, part 1/6
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <9B0371FB9C80161D@Arizona.edu>
Message-Id: <1941@hslrswi.hasler.ascom.ch>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
Here's a good version of the Klondike (solitaire) card game for which I
posted a beta version some time ago. This is the result of an international
joint effort between me in Switzerland and Richard Goerwitz in Chicago.
Six parts are necessary to keep each one under 20KBytes.
Note that the unix end-of-line convention (just a newline) is used,
so you might need to take special measures with your editor under DOS.
Note also that the tab interval is 4.
NHA
---
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# readme
# klondike.man
# makefile.dos
# makefile.unx
# klonstub.icn
# This archive created: Sun Apr 21 15:03:00 1991
# By: Norman H. Azadian (Hasler AG)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'readme'" '(4587 characters)'
if test -f 'readme'
then
echo shar: will not over-write existing file "'readme'"
else
cat << \SHAR_EOF > 'readme'
README 910330 NHA version 3.00
Just when you'd about given up hope, Klondike is finally being released
in "final" form. It's bigger and slower than ever, and chock full of
marginal features. It should, however, run on just about any PC or unix
machine known to man.
In case you didn't catch the initial beta release, Klondike is an Icon
implementation of the single-player card game variously known under such
names as Solitaire or Patience. When you get tired of playing, you can
let the machine take over for you.
INSTALLATION - DOS
==================
For a fast start simply:
icont -c iolib kloncon klonsub klonstr
icont -u -Si1000 -Sn2000 klondike
iconx klondike
Later you might want to move IOLIB.ICN to your Icon library directory,
and compile it there. If you have "make" on your machine, you can copy
"makefile.dos" to "makefile", and use make to build klondike.icx for you.
INSTALLATION - UNIX
===================
For a fast start simply:
icont -c iolib
cp makefile.unx makefile
make
iconx klondike
Later you might want to move IOLIB.ICN and GETCHLIB.ICN to your Icon
library directory, and compile them there.
NOTES
=====
Richard Goerwitz provided the GETCHLIB library package to allow
operation under unix. He also provided the IOLIB library package that
is essential if your terminal isn't ANSI compatible. He assures me that
it should be adequate for most terminals currently in use. If, however,
you are stuck with an old slow terminal that requires padding, you
will need his industrial-strength ITLIB package instead of IOLIB.
You can get this direct from Richard at "goer%sophist@gargoyle.uchicago.edu".
All suggestions, bug reports and compliments for these libraries should
be directed to Richard. All of these libraries will probably become
available in the Icon Program Library at some point in the future.
On a PC the "A" and "C" commands can be interrupted by hitting (nearly)
any key on the keyboard. Under unix, the natural way to do this would
be to use SIGINT. Alas, for the sake of portability we had to forgo this
feature. This is because the terminal needs to run in raw mode to
implement the getch() function, and signals aren't available in raw mode.
With BSD this could be handily solved by using cbreak mode instead of raw
mode, but that isn't a possibility under SysV. The kbhit() that DOS
uses doesn't port well to unix.
If for some reason you can't/won't run an ANSI driver on your PC, it is
possible to run with the termcap capabilities provided by IOLIB. To do
this you will need a TERMCAP file. I have such a beast, as does Richard,
but I have not included it in the distribution because probably no one
will actually use it. If you are the exception, you can get it from one
of us, or you could write it yourself.
For terminals with only 24 lines, a kluge is necessary in order to
display the maximal-length stack of 12 cards. The top card (at the
bottom of the screen) is moved up one row so that it covers up the
suit and rank of the card it rests upon. However, you know it must
be a 3, and it can't be used anyway until the 2 on top of it is put
onto its ace pile.
One of the excuses for writing this was to have a means of evaluating
various strategies for playing klondike solitaire. A strategy is easily
coded in klonstr.icn, and then tested with a batch file that uses the
-S, -B and -I options. On my AT clone, Klondike can pump out nearly
5 games per minute in batch mode, thus an overnight run can produce
3000-4000 games worth of statistics. And under unix you can run it
in background with "nice" to soak up those excess machine cycles.
On a PC, the size of the .ICX file is limited to 65KBytes. As long as
you are running an ANSI driver, you don't actually need IOLIB, and you
can save a bunch of space in KLONDIKE.ICX by stubbing it out. This will
probably be essential if you want to add any play strategies to
klonstr.icn. Assuming that your IOLIB is in a library directory
distinct from where you keep your Klondike, you can accomplish this by
simply doing the following in your Klondike directory:
copy klonstub.icn iolib.icn
icont -c iolib
I am very interested in suggestions, ideas, speed ups, and above all,
bug reports. I'd also like to hear about your experiences with
alternate strategies.
Enjoy!
NHA
---
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
SHAR_EOF
if test 4587 -ne "`wc -c < 'readme'`"
then
echo shar: error transmitting "'readme'" '(should have been 4587 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'klondike.man'" '(9788 characters)'
if test -f 'klondike.man'
then
echo shar: will not over-write existing file "'klondike.man'"
else
cat << \SHAR_EOF > 'klondike.man'
NAME
klondike -- one of the many versions of solitaire
SYNOPSIS
klondike [-AQZ] [-B[gameCount]] [-D[directory]] [-I[reportInterval]
[-P[phraseFile]] [-RrandomSeed] [-Sstrategy]
[-T[termType]]")
DESCRIPTION
A popular variation on the Klondike version of Solitaire (or
Patience) as described on page 181 of my 1963 version of "Hoyle's
Rules of Games". The difference is that here we go through the
deck (stock) 3 cards at a time instead of one-by-one, and we allow
it any number of times.
This program runs best on a PC with a color monitor. It will
run on any system providing an ANSI-compatible screen by simply
giving option -Tmono or -Tcolor as appropriate. Further,
thanks largely to Richard L. Goerwitz's encouragement, help
and excellent iolib package, it should run on just about any
(non-magic-cookie) terminal supported by termcap.
OPTIONS
Except for strategy, options may be either upper or lower case.
They may be given in any order. Parameters follow their options
with no whitespace inbetween. Each option must be given as a
separate argument. Except for toggling options, only the last
occurence of an option is honored.
-A By default uncovered Ace cards are automatically
promoted to an Ace pile. This option toggles that
behaviour. Note that, in any case, it is not allowed
to put an Ace onto a stack, as this could lead to
building stacks which are too big to display with
a 25 line screen. Some computer-play strategies
will unilaterally disable this option during
programmed play.
-B[count]
Batch mode. The requested number of games is played
and a line of ASCII is written to standard output
with four tab-separated numbers: random seed, number
of games played, number of games won, and number of
cards promoted to the ace piles. Before exiting,
the usual additional statistics are dumped (with
explanatory text) to stderr. If the count is 0 or
missing, games are played forever (or until interrupted).
In batch mode play can always be terminated with
an interrupt from the user, as defined by system-
dependent routine userInterrupt() in kloncon.icn.
Under DOS this consists of entering any character
from the keyboard.
No I/O is ever done other than that described
above. In particular, the checkpoint file,
klondike.sav, generated by a previous Boss command,
is ignored in batch mode.
-D[dir] gives the directory to be used for all file I/O.
The dir string is simply pre-pended to all filenames,
including the phrase file if given. If dir is not
given, environment variables $HOME and then $ROOTDIR
are tried. Failing these, the current directory is
used.
-I[reportInterval]
enables intermediate reporting of results when
running in Batch mode. Default is 1.
-P[file]
Normally an incorrect keystroke is greeted by one
of a set of stock phrases. With this option phrases
are instead taken from the indicated file, 1 per line,
up to 16 printing characters each. For the hard of
humor, funny phrases may be disabled altogether by
giving the option without any file name.
-Q toggle Quiet mode. Klondike is initially noisy,
with clicks for card movement and bells for
getting attention. With this option there are
no clicks, and bells are visual if possible.
-Rseed set the random seed to the designated value.
-Sstrategy
allows the user to determine which of the programmed
strategy play possibilities will be used for all
computer play (commands Automatic and Continuous).
The default strategy is called "takeFirst", others
may be discovered by reading file klonstr.icn.
NOTE that case IS important in the strategy name.
-T[termtype]
use termcap instead of assuming that this is a PC with
an ANSI screen. If termtype is given then that name
is sought in /etc/termcap, otherwise environment
variables TERMCAP and TERM are consulted in the usual
manner. Termcap screens are always considered to be
monochrome. Three special (case-independent) values
for termtype are defined: PC, MONO, and COLOR.
PC gives the default behaviour, i.e. an ANSI driver
(ANSI.SYS or compatible) must be running, and the
BIOS is consulted to see whether it is monochrome
or color. This BIOS dependency is avoided with
COLOR and MONO.
-Z toggle debugging mode. In debugging mode the
debug command (Z) is allowed. Debugging mode
is initially disabled since it allows cheating.
COMMANDS
H or ? display a Help screen. Under DOS, F1 also works.
^L (control-L) redraws the screen
A Automatic mode. Plays the game until nothing useful
remains to be done, or until any key is struck.
B Boss key. The screen is blanked and the current position
is saved. When the game is started again in the usual
way, this saved game will be automatically restored and
the save file deleted.
C Continuous mode. The computer plays games automatically
until interrupted. Two statistics are displayed:
the number of games already played, and the total number
of aces which have been promoted to the ace piles.
F Find next useful move, thumbing as necessary. If invoked
immediately again, the move is performed and the next
one is sought. Note that unless automatic ace mode
is disabled with the -A option, ace promotion will be
automatic, and not considered as a useful move. Note
also that no strategy is used, i.e. the move found is
not necessarily the best.
M Move a card from the deck or a stack to a stack or an
ace pile.
Q Quit this game, with the opportunity to play another.
S Suggest a possible move. Hitting this key multiple times
results in multiple suggestions being displayed. When
there is nothing interesting left to do, it will suggest
"Thumb". Otherwise the possibilities are listed in no
particular order.
T Thumb. Remove the top 3 cards from the face-down deck
and turn them over (as a group) onto the face-up deck.
U Undo. This can be used all the way back to the start
of the current game.
Z Debug. This is only enabled when the -Z option has
been given on the command line. There is a sub-menu
of commands available, including a (very brief) Help
summary.
The Move command takes two parameters: source and destination.
Possible sources are: D for the Deck of face-up cards; and a
number from 1 to 7 inclusive, meaning the corresponding stack.
Possible destinations are the stacks (1-7) and A for the
appropriate ace pile. For instance, to move the visible card
from the face-up deck to stack 4, one types the three characters:
"MD4". Actually, the "M" character itself is optional, which
explains why the "debug" command isn't invoked with a "D".
ENVIRONMENT VARIABLES
KLONDIKE the contents of this variable are pre-pended
to the command line.
HOME, ROOTDIR used for directory when -D given without arg.
TERM, TERMCAP used for terminal type determination as usual.
FILES
klondike.sav Boss key checkpoints the position here.
klondike.sv? State checkpointed here with the S debug command.
"?" can be any (upper-case) character legal in
your filesystem.
BUGS
On 24-line terminals you will have to guess at the suit of the
next-to-top card in a maximal-length stack.
"Continuous" command not (gracefully) stoppable under SYS V unix.
Slow, particularly with non-ANSI terminals.
The program's play is simplistic; no interesting strategic play
has yet been programmed.
The average time statistic is sometimes wrong for PCs, and is
always wrong when the Boss command has been used.
ACKNOWLEDGEMENTS
The termcap capability was contributed by Richard L. Goerwitz.
The inspiration, name, and some elements of the user interface
were lifted wholesale from a computer game copyrighted in 1985
by Allyn Wade.
VERSION
3.01 -- 30 March, 1991
AUTHOR
Norman H. Azadian
naz@hslrswi.com
SHAR_EOF
if test 9788 -ne "`wc -c < 'klondike.man'`"
then
echo shar: error transmitting "'klondike.man'" '(should have been 9788 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile.dos'" '(506 characters)'
if test -f 'makefile.dos'
then
echo shar: will not over-write existing file "'makefile.dos'"
else
cat << \SHAR_EOF > 'makefile.dos'
#makefile.dos 910322 NHA
#A DOS makefile for klondike
#
#Assumes that iolib.u? is already available somewhere along $IPATH.
#If you don't want to use iolib (because you have an ANSI screen/terminal
#and you are running out of memory) then you can do the following:
# cp klonstub.icn iolib.icn
# icont -c iolib.icn
.SUFFIXES: .u1 .icn .icx
.icn.u1:
icont -c $?
klondike.icx: klondike.icn kloncon.u1 klonstr.u1 klonsub.u1
icont -u -Si1000 -Sn2000 klondike
clean:
rm -f *.u? klondike.icx
SHAR_EOF
if test 506 -ne "`wc -c < 'makefile.dos'`"
then
echo shar: error transmitting "'makefile.dos'" '(should have been 506 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile.unx'" '(444 characters)'
if test -f 'makefile.unx'
then
echo shar: will not over-write existing file "'makefile.unx'"
else
cat << \SHAR_EOF > 'makefile.unx'
#makefile.unx 910322 NHA
#An unix makefile for klondike
#
#Assumes that iolib.u? and getchlib.u? are already available somewhere
#along $IPATH.
#Note that only getchlib is linked on the command line. Everything else
#is linked in the program.
.SUFFIXES: .u1 .icn
.icn.u1:
icont -c $?
klondike: klondike.icn kloncon.u1 klonstr.u1 klonsub.u1 getchlib.u1
icont -u -Si1000 -Sn2000 klondike getchlib.u1
clean:
rm -f *.u? klondike
SHAR_EOF
if test 444 -ne "`wc -c < 'makefile.unx'`"
then
echo shar: error transmitting "'makefile.unx'" '(should have been 444 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'klonstub.icn'" '(571 characters)'
if test -f 'klonstub.icn'
then
echo shar: will not over-write existing file "'klonstub.icn'"
else
cat << \SHAR_EOF > 'klonstub.icn'
#klonstub.icn 910310 NHA
#Stubs for iolib.icn
#Copy this file to iolib.icn to reduce runtime memory requirements.
#Obviously this will only be effective if you have an ANSI screen/terminal.
procedure setname (term)
stop ("klondike: invoked stub version of setname(", image(name), ")")
end
procedure getval (id)
stop ("klondike: invoked stub version of getval(", image(id), ")")
end
procedure igoto (cm, dstcol, dstline)
stop ("klondike: invoked stub version of igoto()")
end
procedure iputs (cp, affcnt)
stop ("klondike: invoked stub version of iputs()")
end
SHAR_EOF
if test 571 -ne "`wc -c < 'klonstub.icn'`"
then
echo shar: error transmitting "'klonstub.icn'" '(should have been 571 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Sun Apr 21 19:54:33 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 21 Apr 91 19:54:33 MST
Resent-From: icon-group-request@arizona.edu
Received: from by optima.cs.arizona.edu (4.1/15)
id AB17137; Sun, 21 Apr 91 19:54:25 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sun, 21 Apr
1991 19:53 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03945; Sun, 21 Apr 91
19:48:06 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 21 Apr 1991 19:53 MST
Date: 21 Apr 91 14:07:16 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: Klondike solitaire, v3.01, part 4/6
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <9B0FB8FCFC800E9E@Arizona.edu>
Message-Id: <1944@hslrswi.hasler.ascom.ch>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# kloncon.icn
# This archive created: Sun Apr 21 15:04:11 1991
# By: Norman H. Azadian (Hasler AG)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'kloncon.icn'" '(19868 characters)'
if test -f 'kloncon.icn'
then
echo shar: will not over-write existing file "'kloncon.icn'"
else
cat << \SHAR_EOF > 'kloncon.icn'
#kloncon.icn 901029 NHA
# Console interface routines for Klondike.
#
# TO FIX:
#
#
# TO DO:
#
# - develop a visual indication (for isQuiet) for a PC
# - Click for each card moved in a stack ??
#
link iolib #non-ANSI screen output subroutines
# constants
global rankID, suitID #card identification chars
global isANSI # non-&null for ANSI-compatible
global isMonochrome # non-&null when running Black&White
global output #function for writing control chars
global lineCount #total possible rows on screen
# Video control strings, etc
global Vnormal, Vreverse, Vblink, Vbold, VclearAll, VclearEOL, VbackSpace,Vbell
global Vcontrols, ESC #set of control strings, ESC char
global visualBell # non-&null when Vbell is visual
global color #list of suit color strings
# u s e r I n t e r r u p t
# Succeeds iff the user wishes to interrupt the action.
# THIS ROUTINE IS SYSTEM DEPENDENT.
# For DOS, we simply look to see if any keystroke is waiting, discarding
# it/them. Your system may be different.
procedure userInterrupt ()
static keyWaiting
initial {
keyWaiting := if \type(kbhit) then "kbhit"
}
if \isDOS then
while keyWaiting() do {
(getch() == "\0") & getch() #eat interrupting keystroke
return #success means "interrupt requested"
}
else
(\keyWaiting) & keyWaiting() & getch() & return
fail #failure = "interrupt NOT requested"
end #userInterrupt
# m y P u t s
# Output all the strings, using iputs() for control strings.
# This slightly cheesy algorithm requires that all control strings
# start with ESC. This, however, does not apply when \isANSI,
# since this routine isn't called then.
# Note that if isQuiet changes while running (using debug command), then
# Vbell and visualBell may not be optimally set.
procedure myPuts (sl[])
static outstr
local s
initial {
outstr := table("Oops!")
outstr[VclearAll] := getval("cl") | (getval("ho") || getval("cd"))
outstr[VclearEOL] := getval("ce")
outstr[Vnormal] := getval("me") || getval("ue")
outstr[Vbold] := getval("md" | "us")
outstr[Vblink] := getval("mb")
outstr[Vreverse] := getval("mr" | "so")
outstr[VbackSpace] := if getval("bs") then "\b" else getval("le")
if \isQuiet then
outstr[Vbell] := (visualBell := getval("vb")) | getval("bl")
else
outstr[Vbell] := getval ("bl") | "\^G";
}
while s := string(get(sl)) do
s ? {
while writes (tab(upto(ESC))) do
iputs (outstr[=(!Vcontrols)])
writes (tab(0))
}
return
end #myPuts
# g e t A N S I t y p e
# Determine if this ANSI-compatible screen is monochrome or color.
# This only works on a PC with the ANSI.SYS (or similar) driver installed.
procedure getANSItype ()
local i
if \isPC then {
i := ord (Peek([16r40, 16r49])) #BIOS display mode byte
case i of {
2 : isMonochrome := 1
3 : isMonochrome := &null #living color
7 : isMonochrome := 1
default : stop ("Klondike: unknown BIOS display mode ", i)
}
} else
runerr (500, "Klondike: but I thought you were on a PC !")
return
end #getANSItype
# i n i t C o n s t a n t s
# Initialize the program "constants". These are actually variables that
# are set just once at the beginning of the world.
procedure initConstants (termtype)
local Vred, Vblack #suit color strings
lineCount := 25 #assume the best
case (map(termtype, &lcase, &ucase)) of {
"PC" : { getANSItype (); isANSI := 1 }
"MONO" : { isMonochrome := 1; isANSI := 1 }
"COLOR" : { isMonochrome := &null; isANSI := 1 }
default : { isMonochrome := 1; isANSI := &null
(0 < *termtype) & setname (termtype)
lineCount := getval("li")
}
}
(lineCount < 24) &
stop ("klondike: need at least 24-line terminal. Yours is ", lineCount)
# Use this function for outputting any string containing control characters,
# unless you're sure that the screen is ANSI-compatible.
output := if \isANSI then writes else myPuts
# set Video control strings, plus the set of all Video control strings
ESC := "\e" #escape character
VclearAll := "\e[2J" #clear screen and home cursor
VclearEOL := "\e[K" #clear to End Of Line
Vnormal := "\e[0m"
Vbold := "\e[1m"
Vblink := "\e[5m"
Vreverse := "\e[7m"
if \isANSI then {
VbackSpace := "\b"
Vbell := "\^G"
} else {
#additional escape required for myPuts()
VbackSpace := "\e\b"
Vbell := "\e\^G" #ding dong, Avon calling
}
Vcontrols := set( [VclearAll, VclearEOL, Vnormal, Vbold,
Vblink, Vreverse, VbackSpace, Vbell] )
if \isMonochrome then {
Vred := Vnormal
Vblack := Vreverse
} else {
Vred := "\e[0;47;31m" # "extra" 0 seems to be necessary
Vblack := "\e[0;47;30m" # "extra" 0 seems to be necessary
}
# Suits are: 1=Hearts, 2=Diamonds, 3=Clubs, 4=Spades
suitID := if \isPC then "\3\4\5\6" else "HDCS"
color := [Vred, Vred, Vblack, Vblack]
rankID := "A23456789TJQK"
return
end #initConstants
# i n i t S c r e e n
# Initialize output and write the fixed parts of the screen.
# initConstants() must have been called earlier.
# Note that the screen and its mode must remain unmodified if \invisible.
procedure initScreen ()
local f
static vertical
initial {
vertical := if \isANSI then "\272" else "|"
}
(\invisible) & return
if \isANSI then {
if (\isPC) then
if \isMonochrome then writes ("\e[=2h") #25x80 B&W text mode
else writes ("\e[=3h") #25x80 color text mode
writes (Vnormal, VclearAll, "\e[=7l") #clear screen, prevent wrap
} else {
if not iputs (getval("is")) then { #terminal Init Ftring
if f := open (getval("if"), "r") then { #terminal Init File
while writes (reads(f)) ## should use iputs() ??
close (f)
}
}
iputs (getval("ti")) #Termcap Init string
output (VclearAll)
}
every writeStackNumber (1 to 7, Vnormal)
writeCursor (2, 64)
if \isANSI then
writes ("\311\315\315\315\315SOLITAIRE\315\315\315\315")
else
writes ("=====SOLITAIRE====")
every writeAt (3 to lineCount, 64, vertical)
outputAt ((if lineCount = 25 then 25 else 1), 66,
Vbold, "Q", Vnormal, "=Quit ", Vbold, "H", Vnormal, "=Help")
return
end #initScreen
# t e r m i n a t e S c r e e n
# Put the screen in the correct state prior to program termination.
procedure terminateScreen ()
static resetCooked
initial {
resetCooked := if \type(reset_tty) then "reset_tty"
}
if /invisible then
if \isANSI then
write ("\e[=7h", VclearAll, Vnormal) #set cursor wrap mode
else {
output (VclearAll, Vnormal, getval("te"))
(/isDOS) & (\resetCooked) & resetCooked ()
}
return
end #terminateScreen
# w r i t e C u r s o r
# Position the cursor to row,col.
# Screen origin (top left corner) is row=1 and col=1.
procedure writeCursor (row, col)
static cm
initial {
(\isANSI) | (cm := (getval("cm") | (getval("ch") || getval("cv"))))
}
if /invisible then
if \isANSI then
writes ("\e[", row, ";", col, "H")
else
iputs (igoto(cm, col, row))
return
end #writeCursor
# w r i t e A t
# Position the cursor to row,col and then write the following string(s).
# Screen origin (top left corner) is row=1 and col=1.
# Note that the standard write() should normally not be used because the newline
# doesn't work when running in raw mode under unix.
procedure writeAt (row, col, s[])
if /invisible then {
writeCursor (row, col)
writes! (s)
}
return
end #writeAt
# o u t p u t A t
# Position the cursor to row,col and then write the following string(s).
# Screen origin (top left corner) is row=1 and col=1.
procedure outputAt (row, col, s[])
if /invisible then {
writeCursor (row, col)
output! (s)
}
return
end #outputAt
# w r i t e S t a c k N u m b e r
# Write the indicated stack number with the specified video attribute.
# Note that this will almost surely alter your current cursor position.
procedure writeStackNumber (num, attr)
(\invisible) | outputAt (1, [3,12,21,30,39,48,57][num], attr, num, Vnormal)
return
end #writeStackNumber
# w r i t e F r o n t
# Displays an image of the specified card fronts at the specified spot.
## WARNING: The input cards must be in a list!
# Top left corner of the first card will be placed at the specified position.
# Successive cards are displayed two rows higher (lower position on the screen).
# Cursor need not be in any particular position before this, and is left
# in a random position afterwards. Video is always left normal (not reversed).
# Cards are 7 columns wide by 5 rows tall.
# We only display the first 2 rows of each card, except for the top card.
# With 25 rows, we can put 12 cards in a stack (assuming we start in row 2).
# But if there are 11 in the stack we can only display 4 rows of the top card.
# If there are 12 cards, we can only display 2 rows of the topmost card.
# With a 24 row screen, the topmost card (a 2) is moved up one line on a full
# stack. This will obscure the 3 that it is resting on, but the topmost 2 will
# be visible, which is rather more important.
##We can only write a row at a time due to a problem with ANSI col 80 handling.
procedure writeFront (cardlist, row, col)
local card
static vertical, topHorizontal, bottomHorizontal
initial {
if \isANSI then {
topHorizontal := "\332\304\304\304\304\304\277"
vertical := "\263"
bottomHorizontal := "\300\304\304\304\304\304\331"
} else {
topHorizontal := "-------"
vertical := "|"
bottomHorizontal := "-------"
}
}
dieIf (lineCount < row, row)
# output first 2 rows of every card
# for long stack and short screen the next-to-top card is mostly obscured
every card := !cardlist do {
(row = lineCount) & (row -:= 1) #long stack, short screen
outputAt (row, col, Vreverse, topHorizontal)
outputAt (row+:=1, col, vertical, color[card.suit], rankID[card.rank],
suitID[card.suit], Vreverse, " ", vertical)
row +:= 1
}
# maybe put out some more rows of the top card
if row <= lineCount then {
outputAt (row, col, Vreverse, vertical, " ", vertical)
if (row +:= 1) <= lineCount then {
outputAt (row, col, vertical, " ", color[card.suit],
rankID[card.rank], suitID[card.suit], Vreverse, vertical)
if (row +:= 1) <= lineCount then
writeAt (row, col, bottomHorizontal) #last row of top card
}
}
output (Vnormal)
return
end #writeFront
# w r i t e B a c k
# Puts an image of the back of a card at the specified spot on the screen.
procedure writeBack (row, col)
static backLine
local i
initial {
backLine := list(5)
if \isANSI then {
backLine[1] := "\332\304\304\304\304\304\277"
backLine[2] := "\263\332\304\304\304\277\263"
backLine[3] := "\263\263\040\040\040\263\263"
backLine[4] := "\263\300\304\304\304\331\263"
backLine[5] := "\300\304\304\304\304\304\331"
} else {
backLine[1] := "-------"
backLine[2] := "| --- |"
backLine[3] := "| | | |"
backLine[4] := "| --- |"
backLine[5] := "-------"
}
}
(\invisible) | (every writeAt (row, col, !backLine) do row +:= 1)
return
end #writeBack
# w r i t e B l a n k
# Blanks a card-sized area at the specified spot on the screen.
procedure writeBlank (row, col)
(\invisible) | (every writeAt (row + (0 to 4), col, " "))
return
end #writeBlank
# w r i t e S t a c k
# Display the specified stack. Left end is bottom of stackUp, top of stackDown.
# Stacks start in row 2, column1; with 2 columns between stacks.
# Optimized to avoid re-writing cards that are already on the screen.
# prevs[] holds, for each stack, the total number of visible (up) cards
# on that stack as of the last time writeStack() was called. This allows
# us to simply draw (or erase) the cards that have been added (or subtracted).
# By special arrangement, this routine can be called with a negative stack
# number! This is a hint that our idea of what is on the display is actually
# wrong, and therefore the entire stack needs to be re-displayed. This can
# happen in two situations: 1) in refreshScreen(), the entire screen is cleared
# before calling writeStack(); 2) in undo() when undoing a move between
# stacks, the bottom card needs to be changed, although the normal algorithm
# would consider that it is already correctly displayed. Note that in neither
# case is the stack shrinking, therefore we don't need to worry about erasing
# any cards that were displayed last time.
procedure writeStack (n)
local row, col
static prevs, blankLine, firstRow, lastRow
initial {
prevs := [0,0,0,0,0,0,0] #previous stack height displayed
blankLine := repl (" ", 7)
# first and last screen rows for each card in a stack
firstRow := [2,4,6,8,10,12,14,16,18,20,22,24]
lastRow := [6,8,10,12,14,16,18,20,22,24,lineCount,lineCount]
}
(\invisible) & return
(n < 0) & (prevs[n := abs(n)] := 0) #n < 0 forces complete re-write
col := (n * 9) - 8 #leftmost column for this stack
if (*stackUp[n]) <= prevs[n] then {
# the stack just got smaller (or stayed the same)
# blank out two rows for each card that has been removed
row := lastRow[prevs[n]] + 1 #<last row used by top card> + 1
while *stackUp[n] < prevs[n] do {
every writeAt (row -:= (1 | 1), col, blankLine)
prevs[n] -:= 1 #countdown and update
}
dieIf (*stackUp[n] ~= prevs[n], prevs[n])
# re-write new top card
if *stackUp[n] = 0 then
(if *stackDown[n] = 0 then writeBlank else writeBack) (2, col)
else
writeFront ([stackUp[n][-1]], firstRow[prevs[n]], col)
} else {
# the stack just got bigger -- display new cards
writeFront (stackUp[n][prevs[n]+1:0], firstRow[prevs[n]+1], col)
prevs[n] := *stackUp[n] #remember how much is displayed
}
# display the number of hidden cards
writeAt (4, (7 + col), " 123456???"[1+*stackDown[n]])
return
end #writeStack
# w r i t e P i l e
# Displays an image of the specified ace pile, face up (or blank if empty)
procedure writePile (n)
static pileRow, pileCol
initial {
pileRow := [3,3,9,9]
pileCol := [66,74,66,74]
}
if /invisible then
if 0 = pile[n] then
writeBlank (pileRow[n], pileCol[n])
else
writeFront ([card(n,pile[n])], pileRow[n], pileCol[n])
return
end #writePile
# w r i t e D e c k D o w n
# Displays an image of deckDown (the face-down deck) in the proper spot.
# Avoids re-displaying blank or card back that is already on the screen.
# Parameter is non-null to force displaying something (assuming not invisible).
procedure writeDeckDown (forget)
static p
initial {
forget := 1 #assume the screen is blank
}
if /invisible then {
(\forget) & (p := writeDeckDown) #anything but writeBlank | writeBack
(p ~===:= (if 0 < *deckDown then writeBack else writeBlank)) (20, 74)
writeAt (19, 76, right(*deckDown, 2)) #display card count in deckDown
}
return
end #writeDeckDown
# w r i t e D e c k U p
# Displays an image of deckUp (the face-up deck) in the proper spot.
procedure writeDeckUp ()
if /invisible then {
writeFront ([deckUp[1]], 20, 66) | writeBlank (20, 66)
writeAt (19, 68, right(*deckUp, 2)) #write number of cards in deckUp
}
return
end #writeDeckUp
# c o u n t C o n t r o l s
# Returns a count of video control sequences in the proffered string.
# This is not a very general algorithm, being valid only for our V constants.
procedure countControls (s)
local count #of [invisible] video control chars
local seq #control sequence found
count := 0
every find ((seq := (!Vcontrols)), s) do count +:= *seq
return count
end #countControls
# w r i t e I n f o
# Displays a new short string (up to 16 printing characters) centered in the
# officially approved information area of the screen.
# All known video attributes (in set "Vcontrols") are specially handled.
# An empty string results in clearing the area.
# We always revert to normal text mode after outputting the string.
procedure writeInfo (s)
(\invisible) | outputAt (15, 65, Vnormal, VclearEOL,
trim(center(s, 16+countControls(s)), ' '), Vnormal)
return
end #writeInfo
# c l i c k
# Make a quick sound to accompany card transfers, if possible and not Quiet.
procedure click ()
local x
if (not \isQuiet) & (\isPC) then {
x := InPort (16r61)
OutPort (16r61, 3)
OutPort (16r61, x)
}
return
end #click
# b e e p
# The short beep produced under isPC is not as annoying as the normal beeeeep.
# This always puts out something, although it might be a visual indication.
procedure beep ()
local x
if (\isPC) then { #no visual indication yet for a PC
x := InPort (16r61)
every | OutPort (16r61, 3) \ 22
OutPort (16r61, x)
} else
output (Vbell)
return
end #beep
# c o m p l a i n
# Let the boob know he done something wrong, with a dash of humor.
# Complaint can be specified, otherwise a generic one will be selected for you.
# Phrases can be up to 16 visible characters long.
# Additionally there may be embedded recognized video control sequences.
# Complaint will always be bold, and will blink if isQuiet.
procedure complain (complaint)
static phrases
local f, s
initial {
phrases := ["INVALID"] #irreducible minimum
if \phraseFile then {
if f := open((directory || phraseFile), "r") then {
while put (phrases,
trim(center(s, 16+countControls(s := read(f))), ' '))
close (f)
(1 < *phrases) & pop(phrases) #success -- remove ours
}
} else {
phrases |||:= [
"cut that out!", "oops!", "be nice!", "get real",
"be serious", "What??", "huh?", "idiot alert",
"dummy!", "Hey man!", "giggle giggle", "engage brain",
"NOW what?", "yuk yuk", "funky dude", "wake up, man",
"yeah, real funny", "totally awesome", "boffo", "boogie boogie",
"Bozo!", "watch it!", "oi vey", "~@?$!&*=(*%^!*",
"forty lashes!", "way cool, dude", "ha ha ha", "see an analyst",
"go fly a kite", "wish upon a star", "basket case", "braindamaged",
"dummkopf", "holy cow", "reject", "try harder",
"think again", "watch your hands", "We're not amused", "adjust fingers",
"gimme a break", "R U 4 real ?", "that's a laugh", "Ho Ho Ho",
"space case", "space cadet", "call AA", "oh yeah?",
"dum de dum dum", "try thinking", "sigh", "get a life"
]
}
(\debugging) & writeInfo (*phrases || " phrases")
}
/complaint := ?phrases
#Note that isQuiet can change while running if debugging is enabled (-Z)
if (\isQuiet) & (not \visualBell) then
writeInfo (Vbold || Vblink || complaint)
else {
writeInfo (Vbold || complaint)
beep()
}
return
end #complain
# g e t C m d C h a r
# Returns an upper-case command character, echoed to current cursor position.
# Fails if character wasn't "normal" and complaint was made.
# For ESC, abort information is written, and ESC is returned.
# Normal calling sequence (from within a command procedure) is thus:
# until (s := getCmdChar ())
# (s == ESC) & fail
# Under DOS, F1 [function key 1] is specially treated as a request for Help.
procedure getCmdChar ()
local s
s := getch () #get command character
if s == "\0" then { #non-ASCII character
s := getch () #check keyboard scan code
if (\isDOS) & (s == ";") then {
s := "h" #jigger F1 to look like "Help"
} else {
complain ()
fail
}
}
s := map (s, &lcase, &ucase)
if s == ESC then
writeInfo (Vbold || "Cmd Aborted.")
else
writes (s) #echo the command character
return s
end #getCmdChar
# r e f r e s h S c r e e n
# Re-write entire screen.
procedure refreshScreen ()
if /invisible then {
initScreen ()
every writeStack (-1 to -7 by -1)
every writePile (1 to 4)
writeDeckDown (1)
writeDeckUp ()
}
return
end #refreshScreen
SHAR_EOF
if test 19868 -ne "`wc -c < 'kloncon.icn'`"
then
echo shar: error transmitting "'kloncon.icn'" '(should have been 19868 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Sun Apr 21 19:55:13 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 21 Apr 91 19:55:13 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA17181; Sun, 21 Apr 91 19:55:05 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sun, 21 Apr
1991 19:53 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03979; Sun, 21 Apr 91
19:48:51 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 21 Apr 1991 19:54 MST
Date: 21 Apr 91 14:06:05 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: Klondike solitaire, v3.01, part 3/6
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <9B27C2184C800E22@Arizona.edu>
Message-Id: <1943@hslrswi.hasler.ascom.ch>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# klondike.icn
# This archive created: Sun Apr 21 15:03:59 1991
# By: Norman H. Azadian (Hasler AG)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'klondike.icn'" '(19820 characters)'
if test -f 'klondike.icn'
then
echo shar: will not over-write existing file "'klondike.icn'"
else
cat << \SHAR_EOF > 'klondike.icn'
#klondike.icn 901207 NHA
#The Klondike version of Solitaire; main program and command routines.
#
# TO FIX:
#
#
# TO DO:
#
# - Add a "cheated" flag ??
# - Find a better way to determine isPC.
# - Implement an heuristic to discover optimal play
#
link kloncon #klondike console I/O subroutines
link klonstr #klondike strategy subroutines
link klonsub #klondike miscellaneous subroutines
record card(suit, rank) #suit is 1..4, rank is 1..13
# v a r i a b l e s
# lists of record card
global deckUp #face Up portion of deck (stock)
global deckDown #face Down portion of deck
global stackUp #list of face Up cards per stack
global stackDown #list of face Down cards per stack
# others
global pile #ace piles - top rank only
global ops #list of all operations ever done
global isDOS, isPC # "state of our world" flags
global debugging, automaticAce #command-line flags
global invisible, isQuiet # for visual and audible feedback
global strategy #strategy to use for automatic play
global directory, phraseFile #pathnames
global firstSeed, lastSeed #&random remembered
global totalGames, totalAces, totalWins #ace pile statistics
# u h e l p
# Provide command summary for user, plus statistics to date, if any.
procedure uhelp ()
local row, info
static helpInfo
initial {
helpInfo := [
["A", "Automatic", " mode -- finish out this game on automatic pilot"],
["B", "Boss", " key for when you-know-who visits"],
["C","Continuous"," mode -- play games continuously until interrupted"],
["F", "Find", " (next) useful move to do"],
["H,?", "Help", ", this help screen"],
["M", "Move", " card (or stack) from Deck/Stack to Stack/Ace pile"],
["Q", "Quit", " this game"],
["S", "Suggest", " (another) possible move"],
["T", "Thumb", " through the deck"],
["U", "Undo", " -- back up one move"],
["Z", "Debug", ""],
["^L", "re-draw", " screen"],
["ESC", "Escape", " -- abort current command"]
]
}
output (VclearAll, Vnormal)
output ("Klondike version 3.01 910330 NHA\t\t", &version)
outputAt (4, 4, "The following commands are available:")
row := 6
every info := !helpInfo do
if (\debugging) | (info[1] ~== "Z") then {
outputAt (row, 8, Vbold, info[1])
outputAt (row, 16, info[2], Vnormal, info[3])
row +:= 1
}
if 0 < totalGames then
writeAt (21, 1, "totalGames = ", totalGames,
" totalWins = ", totalWins,
" totalAces = ", totalAces,
" average = ",
left (string(real(totalAces) / real(totalGames)), 6) )
outputAt (24, 20, Vblink, "Press any key to resume game", Vnormal)
(getch() == "\0") & getch() #wait for a keystroke & swallow it
refreshScreen ()
return
end #uhelp
# f i n d 1
# Find the best move, thumbing as necessary to achieve it.
# Return the operation string for that move.
# Fails if there is nothing useful left to do.
# When Thumbing, fails upon second occurrence of *deckDown = 0.
# This is an internal routine but it does keep the user informed.
# Note that if automaticAce is set, any Ace uncovered whilst thumbing
# will be automatically moved and the search will continue.
procedure find1 ()
local emptySeen, s
repeat {
/emptySeen := (*deckDown = 0)
(s := suggest()) & return (s || "0") #good move found
((*deckUp + *deckDown) = 0) & fail #no cards to thumb through
writeInfo (Vbold || "T" || Vnormal || "humb")
push (ops, thumb())
(\emptySeen) & (*deckDown = 0) & fail #no point Thumbing forever
}
end #find1
# u f i n d
# Thumb as necessary until a reasonable move appears, then stop and suggest it.
# When nothing is left to do, suggest "Quit".
# When invoked twice in a row, again will be non-null and we should take the
# previous suggestion and find the next.
# Returns success to request termination.
# Note that the suggestion is not necessarily the "best" suggestion.
# Note that if automaticAce is set, an uncovered Ace will be automatically
# moved and the search will continue. It does not count as a move.
procedure ufind (again)
static lastOp
local s
if \again then
if lastOp == "Q" then { #pretend he typed "Q" instead of "F"
output (VbackSpace, Vbold, "Q", Vnormal)
return uterminate () #Th.th.th.that's all, folks!
} else {
writes ("ind")
writeInfo ("") #clear prevs suggestion
s := expandOp (lastOp) #build suggestion
# show previous suggestion as current command
outputAt (17, 65, "> ", left (s, 14 + countControls(s)))
push (ops, move1(lastOp)) | runerr (500, lastOp) #execute it
outputAt (17, 65, VclearEOL,Vnormal, "> F") #go find next suggestion
}
writes ("ind")
writeInfo ( expandOp (lastOp := (find1() | "Q") ) ) #suggest (next) move
fail #do NOT request a new game
end #ufind
# u s u g g e s t
# Suggest a (reasonable) possible move in this situation.
# Repeated invocations produce successive possibilities, until the
# only thing left to do is Thumb.
# "another" is non-null when this command was also the previous command.
# Suggestions are given in essentially random order, and thumbing is
# suggested only as a last resort.
procedure usuggest (another)
static suggestions, i
writes ("uggest")
if /another then { #prev command was NOT Suggest
suggestions := [] #generate a new list of suggestions
every put ( suggestions, suggest() )
i := 0
}
return writeInfo ( expandOp (suggestions[i+:=1] | "T") )
end #usuggest
# a u t o m a t i c
# Run the game, as far as possible, untouched by human hands
# This is an internal routine but it keeps the user informed.
# Returns total ace cards promoted when there is nothing useful left to do.
# Returns with failure when the user interrupts the proceedings.
procedure automatic ()
local op
repeat {
userInterrupt() & fail #interrupted
(!pile < 13) | return 52 #victory
if not writeInfo ( expandOp ( op := findBest() ) ) then
return (pile[1] + pile[2] + pile[3] + pile[4]) #no moves left
push (ops, move1 (op)) | runerr (500, op)
}
end #automatic
# u a u t o m a t i c
# Play this hand automatically, untouched by human hands.
# This is the command fuction that interacts with the user.
procedure uautomatic ()
writes ("utomatic")
writeInfo (if automatic() then "" else "Interrupted")
return
end #uautomatic
# u c o n t i n u o u s
# Plays automatic games -- forever (or until user interrupts)
procedure ucontinuous()
writes ("ontinuous")
repeat {
writeCursor (16, 65) #between Info line and Command line
writes (center ((string(totalGames) || " " || string(totalAces)), 16))
(totalAces +:= automatic()) | (writeInfo ("Interrupted"), break)
totalGames +:= 1
(!pile < 13) | (totalWins +:= 1)
lastSeed := newGame()
writeAt (17, 65, "> Continuous")
}
return
end #ucontinuous
# u m o v e
# Move a card from deck to stack, or from stack to ace pile,
# or move a stack to another stack.
# Parameter is the source [1-7 or D]; else &null to indicate that "M" was used
# and therefore source should be gathered from the keyboard.
# Fails if indicated move is not possible
# This is the routine that interacts with the user.
procedure umove (src)
local dst, c, op, moved, col
if \src then
output (VbackSpace, "Move ", Vbold, src)
else {
output ("ove ", Vbold);
until (src := getCmdChar ())
(src == ESC) & return
}
col := 73
if src == "D" then {
(*deckUp = 0) & fail
output (Vnormal, "eck")
col +:= 3
} else {
any ('1234567', src) | fail
(*stackUp[src] = 0) & fail
writeStackNumber (src, Vblink)
writeCursor (17, col)
}
output (Vnormal, " to ", Vbold)
until (dst := getCmdChar ())
col +:= 5
if src ~== "D" then {
writeStackNumber (src, Vnormal)
writeCursor (17, col)
}
(dst == ESC) & return
any ('A1234567', dst) | fail
(dst == src) & fail
(dst == "A") & (src ~== "D") & output (Vnormal, "ce")
return push (ops, move1("M" || src || dst || "0"))
end #umove
# u u n d o
# backup one move, including any automatic ace moves
procedure uundo ()
writes ("ndo")
undo()
return
end #uundo
# u d e b u g
# Additional commands to support the implementer.
procedure udebug ()
local s, d, name
(\debugging) | return complain()
output (VbackSpace, "Debug ")
until (s := getCmdChar ())
case s of {
ESC : fail #debug command aborted
"A" : { #play this game again
writes ("gain")
&random := lastSeed
outputAt (22, 1, Vbold,
"&random set. Quit to play this game again.",
Vnormal, VclearEOL)
}
"D" : display() #dump ICON state
"H"|"?" : {
output (if s == "?" then (VbackSpace || "help") else "elp")
outputAt (22, 1, Vbold,
"Again, Dump, Options, Move, Peek{1-7UD}, Restore, Save, Toggle{AQT}.",
Vnormal, VclearEOL)
}
"M" : { #move, without legality checking
writes ("ove ")
until (s := getCmdChar ()) #Source
(s == ESC) & fail
(s == "A") & fail
until (d := getCmdChar ()) #Destination
(d == ESC) & fail
(d == s) & fail
any('1234567', d) | fail
if s == "D" then {
(*deckUp = 0) & fail
put (stackUp[d], get(deckUp))
writeDeckUp ()
writeStack (d)
push (ops, "MD" || d || "0")
} else {
moveStack (s, d)
push (ops, "M" || s || d || "123456789abcdef"[*stackUp[s]])
}
}
"O" : { #show command-line options
writes ("ptions")
outputAt (22, 1, Vbold,
if \automaticAce then "AutomaticAce " else "",
if 0 < *directory then ("-D"||directory||" ") else "",
if \phraseFile then ("-P"||phraseFile||" ") else "",
if \isQuiet then "Quiet " else "",
("-S" || strategy), Vnormal, VclearEOL)
outputAt (23, 1, Vbold, "&trace=", &trace,
" firstSeed=", firstSeed, " lastSeed=", lastSeed,
Vnormal, VclearEOL)
}
"P" : { #look at hidden cards
writes ("eek ")
until (s := getCmdChar ())
(s == ESC) & fail
outputAt (22, 1, VclearEOL, Vnormal)
if any('1234567', s) then showList (stackDown[s])
else if s == "D" then showList (deckDown)
else if s == "U" then showList (deckUp)
else complain ()
}
"R" : { #restore current state from a file
writes ("estore")
until (s := getCmdChar ())
(s == ESC) & fail
name := "klondike.sv" || s
if (d := restoreState(name)) then {
refreshScreen()
outputAt (22, 1, Vbold, "Restored position from file ",
directory || name, " of ", d, Vnormal,VclearEOL)
} else {
outputAt (22, 1, Vblink, "Can't restore from file ",
directory || name, Vnormal, VclearEOL)
}
}
"S" : { #save current state to a file
writes ("ave ")
until (s := getCmdChar ())
(s == ESC) & fail
name := "klondike.sv" || s
writeCursor (22, 1)
if saveState (name) then
output (Vbold, "Position saved in file ",
directory || name, Vnormal, VclearEOL)
else
output (Vblink, "Can't save in file ",
directory || name, Vnormal, VclearEOL)
}
"T" : { #toggle a command-line flag
writes ("oggle ")
until (s := getCmdChar ())
(s == ESC) & fail
case s of {
"A" : automaticAce := if \automaticAce then &null
else 1
"Q" : isQuiet := if \isQuiet then &null else 1
"T" : &trace := if &trace = 0 then -1 else 0
default : complain ()
} #case for Toggle
}
default : complain ()
} #case for Debug command
return
end #udebug
# u b o s s
# Cheese it, the Fuzz.
# Quick -- clear the screen and save the position in a file.
procedure uboss ()
writes ("oss") # "consistency is the hobgoblin of small minds"
terminateScreen () #put screen in the correct state
writes ("C>") #look innocent
saveState ("klondike.sav")
exit ()
end #uboss
# w r i t e S t a t i s t i c s
# Using the global counter variables, compute & write out some elementary stats.
# These are written to stderr so as not to mess up any batch file which might
# be collecting statistics whilst running klondike in -Batch mode.
# Note that write() is kosher here since this should only be called after
# terminate() has been called to restore the screen to its original state.
procedure writeStatistics ()
if 1 < totalGames then {
write (&errout, "In ", totalGames, " games you put ", totalAces,
" cards on the ace piles.")
if 0 < totalAces then
write (&errout,
"Average ", real(totalAces) / real(totalGames),
" cards on the ace piles per game.")
if 0 < totalWins then
write (&errout,
"You won ", totalWins, " (",
left((totalWins * 100.) / totalGames, 4),
"%) of those games.")
write (&errout,
"Average ", real(&time) / totalGames / 1000,
" seconds per game.")
} else {
write (&errout,
"In 1 game you put ", totalAces, " cards on the ace piles.")
write (&errout, "Total time was ", real(&time) / 1000, " seconds.")
}
write (&errout, "Initial random seed was ", firstSeed)
return
end #writeStatistics
# u t e r m i n a t e
# Returns success to quit this game and start another.
# Returns failure to just continue this game.
# If program termination is wished, that is done right here.
procedure uterminate ()
local s
if (!pile < 13) then
writes ("uit")
else
outputAt (12, 22, Vbold, Vblink, "Congratulations -- You've WON !!!",
Vnormal)
writeInfo (Vbold || "Another game? ")
until (s := getCmdChar ())
case s of {
ESC : fail #didn't really want to quit after all
"Y" : return #please start a new game
"N" : { #program termination requested
totalGames +:= 1
every totalAces +:= !pile
(!pile < 13) | (totalWins +:= 1)
terminateScreen ()
writeStatistics ()
exit ()
}
default : {complain(); fail} #continue playing this game
}
runerr (500, s)
end #uterminate
# d o B a t c h
# Plays the requested number of games in batch mode.
# Returns three-element list of results.
# If the number of games to play is 0 or negative, then plays until interrupted.
procedure doBatch (gamesToPlay)
local games, wins, aces
games := wins := aces := 0
repeat {
newGame ()
if aces +:= automatic() then {
(!pile < 13) | (wins +:= 1)
((games +:= 1) = gamesToPlay) & break
} else
break #interrupted from keyboard
}
return [games, wins, aces]
end #doBatch
# u b a t c h
# Plays the requested number of games (0 => infinity) in batch mode.
# Results are reported after every interval (0 => only at end) games.
# Statistics are output when done or interrupted, whichever comes first.
procedure ubatch (gamesToPlay, interval)
local veryFirstSeed, stat
isQuiet := invisible := 1
veryFirstSeed := &random #remember the initial random seed
(interval = 0) & (interval := gamesToPlay)
repeat {
(0 < gamesToPlay) & (interval >:= gamesToPlay)
firstSeed := &random #random seed for first game this set
stat := doBatch (interval)
write (firstSeed, "\t", stat[1], "\t", stat[2], "\t", stat[3])
totalGames +:= stat[1]
totalWins +:= stat[2]
totalAces +:= stat[3]
(stat[1] ~= interval) & break #interrupted by user
(0 = (gamesToPlay -:= interval)) & break
}
firstSeed := veryFirstSeed #required for writeStatistics()
writeStatistics ()
exit ()
end #ubatch
# m a i n
procedure main (av)
local s, prevsCmd, batchMode, reportInterval, again, termtype
# initialize
isDOS := find("MS-DOS", &host) #probably a reasonable assumption
isPC := isDOS #really a pretty poor assumption
totalGames:=totalAces:=totalWins := 0 #statistics
# set defaults
findBest("") # set global variable strategy
automaticAce := 1 # automatic ace handling
debugging := &null # no debugging allowed
directory := "" # use current directory
invisible := &null # let's see the action
batchMode := &null # interactive mode
reportInterval := 0 # report only at end of batch mode
phraseFile := &null # use all built-in phrases
isQuiet := &null # make clicks & beeps if possible
termtype := if \isPC then "pc" else "mono"
&random := map (&clock, ":", "7") # randomize the seed
# deal with command-line parameters
reverse(getenv("KLONDIKE")) ? #pre-pend env var words to cmd line
while tab(upto(~" \t\v\f\r\n")) do
push (av, reverse(tab(many(~" \t\v\f\r\n"))))
while s := get (av) do
case s[1:3] of {
"-A" | "-a" : automaticAce :=if \automaticAce then &null else 1
"-B" | "-b" : batchMode := (integer(s[3:0]) | 0)
"-D" | "-d" : directory := if *s < 3 then
getenv ("HOME" | "ROOTDIR")
else
s[3:0]
"-I" | "-i" : reportInterval := (integer(s[3:0]) | 1)
"-P" | "-p" : phraseFile := s[3:0]
"-Q" | "-q" : isQuiet := if \isQuiet then &null else 1
"-R" | "-r" : &random := integer (s[3:0])
"-S" | "-s" : findBest (s[3:0]) #check & store strategy
"-T" | "-t" : termtype := s[3:0]
"-Z" | "-z" : debugging := if \debugging then &null else 1
default : {
# screen mode not yet initialized, so write() is OK
write ("klondike [-AQZ] [-B[count]] [-D[dir]] [-I[interval]]")
write (" [-P[file]] [-Rseed] [-Sstrategy] [-T[term]]")
# screen mode not yet initialized, so stop() is OK
stop ("klondike: bogus option ", s)
}
}
# initializations which use command-line parameters
(map(termtype, &lcase, &ucase) == "PC") & isPC := 1
initConstants (termtype) #need updated termtype from cmdline
initVariables () #establish all the lists and such
# when defined, batchMode is the number of games to play; 0 => infinity.
ubatch (\batchMode, reportInterval) #conditional call of no return
# Establish the directory for file I/O; with a trailing "/" if non-empty.
# It is only used directly in the open() and remove() calls.
(0 < *directory) & (directory := trim(directory, '/\\') || "/")
# If last game was terminated via the Boss key then restore it now,
# otherwise start up a new game.
if restoreState ("klondike.sav") then {
refreshScreen ()
writeInfo ("Game restored")
remove (directory || "klondike.sav")
} else {
firstSeed := &random #random seed for first game
lastSeed := newGame () #start a new game, stashing seed
}
repeat { #game loop
prevsCmd := "-none-"
repeat { #command loop
outputAt (17, 65, VclearEOL, Vnormal, "> ") #clear command line
until (s := getCmdChar ())
again := (if s == prevsCmd then s else &null)
writeInfo ("") #clear info line
writeCursor (17, 68) #just after cmd char
case s of {
"?"|"H" : uhelp()
"1"|"2"|"3"|"4"|"5"|"6"|"7"|"D" : #short-cut for Move
umove (s) | complain ()
"A" : uautomatic() #look Ma, no hands!
"B" : uboss() #bail out quick
"C" : ucontinuous() #no hands, forever
"F" : ufind (again) & break #new game
"M" : umove (&null) | complain ()
"Q" : uterminate () & break #new game
"S" : usuggest (again)
"T" : { writes("humb"); push(ops, thumb()) }
"U" : uundo()
"Z" : udebug()
"\^L" : refreshScreen()
ESC : s #do nothing here
default : complain()
} #case
prevsCmd := s
(!pile < 13) | (uterminate () & break) # VICTORY!
} #repeat command
totalGames +:= 1
every totalAces +:= !pile
(!pile < 13) | (totalWins +:= 1)
lastSeed := newGame ()
} #repeat game
end #main
SHAR_EOF
if test 19820 -ne "`wc -c < 'klondike.icn'`"
then
echo shar: error transmitting "'klondike.icn'" '(should have been 19820 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Sun Apr 21 20:11:07 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 21 Apr 91 20:11:07 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA17560; Sun, 21 Apr 91 20:11:02 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sun, 21 Apr
1991 20:10 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA04085; Sun, 21 Apr 91
19:53:24 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 21 Apr 1991 20:10 MST
Date: 21 Apr 91 14:09:12 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: Klondike solitaire, v3.01, part 6/6
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <9D656F0E8C8016B5@Arizona.edu>
Message-Id: <1946@hslrswi.hasler.ascom.ch>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# iolib.icn
# This archive created: Sun Apr 21 15:04:45 1991
# By: Norman H. Azadian (Hasler AG)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'iolib.icn'" '(17272 characters)'
if test -f 'iolib.icn'
then
echo shar: will not over-write existing file "'iolib.icn'"
else
cat << \SHAR_EOF > 'iolib.icn'
########################################################################
#
# Name: iolib.icn
#
# Title: Icon termlib-type tools for MS-DOS and UNIX
#
# Author: Richard L. Goerwitz (with help from Norman Azadian)
#
# Version: 1.9
#
#########################################################################
#
# The authors place this and future versions of iolib in the public
# domain.
#
#########################################################################
#
# The following library represents a series of rough functional
# equivalents to the standard Unix low-level termcap routines. It is
# not meant as an exact termlib clone. Nor is it enhanced to take
# care of magic cookie terminals, terminals that use \D in their
# termcap entries, or archaic terminals that require padding. This
# library is geared mainly for use with ANSI and VT-100 devices.
# Note that this file may, in most instances, be used in place of the
# older UNIX-only itlib.icn file. It essentially replaces the DOS-
# only itlibdos routines. For DOS users not familiar with the whole
# notion of generalized screen I/O, I've included extra documentation
# below. Please read it.
#
# The sole disadvantage of this over the old itlib routines is that
# iolib.icn cannot deal with archaic or arcane UNIX terminals and/or
# odd system file arrangements. Note that because these routines
# ignore padding, they can (unlike itlib.icn) be run on the NeXT and
# other systems which fail to implement the -g option of the stty
# command. Iolib.icn is also simpler and faster than itlib.icn.
#
# I want to thank Norman Azadian for suggesting the whole idea of
# combining itlib.icn and itlibdos.icn into one distribution, for
# suggesting things like letting drive specifications appear in DOS
# TERMCAP environment variables, and for finding several bugs (e.g.
# the lack of support for %2 and %3 in cm). Although he is loathe
# to accept this credit, I think he deserves it.
#
#########################################################################
#
# Contents:
#
# setname(term)
# Use only if you wish to initialize itermlib for a terminal
# other than what your current environment specifies. "Term" is the
# name of the termcap entry to use. Normally this initialization is
# done automatically, and need not concern the user.
#
# getval(id)
# Works something like tgetnum, tgetflag, and tgetstr. In the
# spirit of Icon, all three have been collapsed into one routine.
# Integer valued caps are returned as integers, strings as strings,
# and flags as records (if a flag is set, then type(flag) will return
# "true"). Absence of a given capability is signalled by procedure
# failure.
#
# igoto(cm,destcol,destline) - NB: default 1 offset (*not* zero)!
# Analogous to tgoto. "Cm" is the cursor movement command for
# the current terminal, as obtained via getval("cm"). Igoto()
# returns a string which, when output via iputs, will cause the
# cursor to move to column "destcol" and line "destline." Column and
# line are always calculated using a *one* offset. This is far more
# Iconish than the normal zero offset used by tgoto. If you want to
# go to the first square on your screen, then include in your program
# "iputs(igoto(getval("cm"),1,1))."
#
# iputs(cp,affcnt)
# Equivalent to tputs. "Cp" is a string obtained via getval(),
# or, in the case of "cm," via igoto(getval("cm"),x,y). Affcnt is a
# count of affected lines. It is completely irrelevant for most
# modern terminals, and is supplied here merely for the sake of
# backward compatibility with itlib, a UNIX-only version of these
# routines (one which handles padding on archaic terminals).
#
##########################################################################
#
# Notes for MS-DOS users:
#
# There are two basic reasons for using the I/O routines
# contained in this package. First, by using a set of generalized
# routines, your code will become much more readable. Secondly, by
# using a high level interface, you can avoid the cardinal
# programming error of hard coding things like screen length and
# escape codes into your programs.
#
# To use this collection of programs, you must do two things.
# First, you must add the line "device=ansi.sys" (or the name of some
# other driver, like zansi.sys, nansi.sys, or nnansi.sys [=new
# nansi.sys]) to your config.sys file. Secondly, you must add two
# lines to your autoexec.bat file: 1) "set TERM=ansi-mono" and 2)
# "set TERMCAP=\location\termcap." The purpose of setting the TERM
# variable is to tell this program what driver you are using. If you
# have a color system, you could use "ansi-color" instead of
# "ansi-mono," although for compatibility with a broader range of
# users, it would perhaps be better to stick with mono. The purpose
# of setting TERMCAP is to make it possible to determine where the
# termcap database file is located. The termcap file (which should
# have been packed with this library as termcap.dos) is a short
# database of all the escape sequences used by the various terminal
# drivers. Set TERMCAP so that it reflects the location of this file
# (which should be renamed as termcap, for the sake of consistency
# across UNIX and MS-DOS spectra). If desired, you can also try
# using termcap2.dos. Certain games work a lot better using this
# alternate file. To try it out, rename it to termcap, and set
# the environment variable TERMCAP to its location.
#
# Although the authors make no pretense of providing here a
# complete introduction to the format of the termcap database file,
# it will be useful, we believe, to explain a few basic facts about
# how to use this program in conjunction with it. If, say, you want
# to clear the screen, add the line,
#
# iputs(getval("cl"))
#
# to your program. The function iputs() outputs screen control
# sequences. Getval retrieves a specific sequence from the termcap
# file. The string "cl" is the symbol used in the termcap file to
# mark the code used to clear the screen. By executing the
# expression "iputs(getval("cl"))," you are 1) looking up the "cl"
# (clear) code in the termcap database entry for your terminal, and
# the 2) outputting that sequence to the screen.
#
# Some other useful termcap symbols are "ce" (clear to end of
# line), "ho" (go to the top left square on the screen), "so" (begin
# standout mode), and "se" (end standout mode). To output a
# boldfaced string, str, to the screen, you would write -
#
# iputs(getval("so"))
# writes(str)
# iputs(getval("se"))
#
# You can also write "writes(getval("so") || str || getval("se")),
# but this would make reimplementation for UNIX terminals that
# require padding rather difficult.
#
# It is also heartily to be recommended that MS-DOS programmers
# try not to assume that everyone will be using a 25-line screen.
# Most terminals are 24-line. Some 43. Some have variable window
# sizes. If you want to put a status line on, say, the 2nd-to-last
# line of the screen, then determine what that line is by executing
# "getval("li")." The termcap database holds not only string-valued
# sequences, but numeric ones as well. The value of "li" tells you
# how many lines the terminal has (compare "co," which will tell you
# how many columns). To go to the beginning of the second-to-last
# line on the screen, type in:
#
# iputs(igoto(getval("cm"), 1, getval("li")-1))
#
# The "cm" capability is a special capability, and needs to be output
# via igoto(cm,x,y), where cm is the sequence telling your computer
# to move the cursor to a specified spot, x is the column, and y is
# the row. The expression "getval("li")-1" will return the number of
# the second-to-last line on your screen.
#
##########################################################################
#
# Requires: UNIX or MS-DOS, co-expressions
#
# See also: itlib.icn, iscreen.icn
#
##########################################################################
global tc_table, isDOS
record true()
procedure check_features()
initial {
if find("UNIX",&features) then
isDOS := &null
else if find("MS-DOS", &features) then
isDOS := 1
else stop("check_features: OS not (yet?) supported.")
find("expressi",&features) |
er("check_features","co-expressions not implemented - &$#!",1)
}
return
end
procedure setname(name)
# Sets current terminal type to "name" and builds a new termcap
# capability database (residing in tc_table). Fails if unable to
# find a termcap entry for terminal type "name." If you want it
# to terminate with an error message under these circumstances,
# comment out "| fail" below, and uncomment the er() line.
#tc_table is global
check_features()
tc_table := table()
tc_table := maketc_table(getentry(name)) | fail
# er("setname","no termcap entry found for "||name,3)
return "successfully reset for terminal " || name
end
procedure getname()
# Getname() first checks to be sure we're running under DOS or
# UNIX, and, if so, tries to figure out what the current terminal
# type is, checking successively the value of the environment
# variable TERM, and then (under UNIX) the output of "tset -".
# Terminates with an error message if the terminal type cannot be
# ascertained. DOS defaults to "mono."
local term, tset_output
check_features()
if \isDOS then {
term := getenv("TERM") | "mono"
}
else {
if not (term := getenv("TERM")) then {
tset_output := open("/bin/tset -","pr") |
er("getname","can't find tset command",1)
term := !tset_output
close(tset_output)
}
}
return \term |
er("getname","can't seem to determine your terminal type",1)
end
procedure er(func,msg,errnum)
# short error processing utility
write(&errout,func,": ",msg)
exit(errnum)
end
procedure getentry(name, termcap_string)
# "Name" designates the current terminal type. Getentry() scans
# the current environment for the variable TERMCAP. If the
# TERMCAP string represents a termcap entry for a terminal of type
# "name," then getentry() returns the TERMCAP string. Otherwise,
# getentry() will check to see if TERMCAP is a file name. If so,
# getentry() will scan that file for an entry corresponding to
# "name." If the TERMCAP string does not designate a filename,
# getentry() will scan the termcap file for the correct entry.
# Whatever the input file, if an entry for terminal "name" is
# found, getentry() returns that entry. Otherwise, getentry()
# fails.
local isFILE, f, getline, line, nm, ent1, ent2
static slash, termcap_names
initial {
if \isDOS then {
slash := "\\"
termcap_names := ["termcap","termcap.dos","termcap2.dos"]
}
else {
slash := "/"
termcap_names := ["/etc/termcap"]
}
}
# You can force getentry() to use a specific termcap file by cal-
# ling it with a second argument - the name of the termcap file
# to use instead of the regular one, or the one specified in the
# termcap environment variable.
/termcap_string := getenv("TERMCAP")
if \isDOS then {
if \termcap_string then {
if termcap_string ? (
not ((tab(any(&letters)), match(":")) | match(slash)),
pos(1) | tab(find("|")+1), =name)
then return termcap_string
else isFILE := 1
}
}
else {
if \termcap_string then {
if termcap_string ? (
not match(slash), pos(1) | tab(find("|")+1), =name)
then return termcap_string
else isFILE := 1
}
}
# The logic here probably isn't clear. The idea is to try to use
# the termcap environment variable successively as 1) a termcap en-
# try and then 2) as a termcap file. If neither works, 3) go to
# the /etc/termcap file. The else clause here does 2 and, if ne-
# cessary, 3. The "\termcap_string ? (not match..." expression
# handles 1.
if \isFILE # if find(slash, \termcap_string)
then f := open(termcap_string)
/f := open(!termcap_names) |
er("getentry","I can't access your termcap file. Read iolib.icn.",1)
getline := create read_file(f)
while line := @getline do {
if line ? (pos(1) | tab(find("|")+1), =name, any(':|')) then {
entry := ""
while (\line | @getline) ? {
if entry ||:= 1(tab(find(":")+1), pos(0))
then {
close(f)
# if entry ends in tc= then add in the named tc entry
entry ?:= tab(find("tc=")) ||
# recursively fetch the new termcap entry
(move(3), getentry(tab(find(":"))) ?
# remove the name field from the new entry
(tab(find(":")+1), tab(0)))
return entry
}
else {
\line := &null # must precede the next line
entry ||:= trim(trim(tab(0),'\\'),':')
}
}
}
}
close(f)
er("getentry","can't find and/or process your termcap entry",3)
end
procedure read_file(f)
# Suspends all non #-initial lines in the file f.
# Removes leading tabs and spaces from lines before suspending
# them.
local line
\f | er("read_tcap_file","no valid termcap file found",3)
while line := read(f) do {
match("#",line) & next
line ?:= (tab(many('\t ')) | &null, tab(0))
suspend line
}
fail
end
procedure maketc_table(entry)
# Maketc_table(s) (where s is a valid termcap entry for some
# terminal-type): Returns a table in which the keys are termcap
# capability designators, and the values are the entries in
# "entry" for those designators.
local k, v
/entry & er("maketc_table","no entry given",8)
if entry[-1] ~== ":" then entry ||:= ":"
/tc_table := table()
entry ? {
tab(find(":")+1) # tab past initial (name) field
while tab((find(":")+1) \ 1) ? {
&subject == "" & next
if k := 1(move(2), ="=") then {
# Get rid of null padding information. Iolib can't
# handle it (unlike itlib.icn). Leave star in. It
# indicates a real dinosaur terminal, and will later
# prompt an abort.
str := ="*" | ""; tab(many(&digits))
tc_table[k] := Decode(str || tab(find(":")))
}
else if k := 1(move(2), ="#")
then tc_table[k] := integer(tab(find(":")))
else if k := 1(tab(find(":")), pos(-1))
then tc_table[k] := true()
else er("maketc_table", "your termcap file has a bad entry",3)
}
}
return tc_table
end
procedure getval(id)
/tc_table := maketc_table(getentry(getname())) |
er("getval","can't make a table for your terminal",4)
return \tc_table[id] | fail
# er("getval","the current terminal doesn't support "||id,7)
end
procedure Decode(s)
# Does things like turn ^ plus a letter into a genuine control
# character.
new_s := ""
s ? {
while new_s ||:= tab(upto('\\^')) do {
chr := move(1)
if chr == "\\" then {
new_s ||:= {
case chr2 := move(1) of {
"\\" : "\\"
"^" : "^"
"E" : "\e"
"b" : "\b"
"f" : "\f"
"n" : "\n"
"r" : "\r"
"t" : "\t"
default : {
if any(&digits,chr2) then {
char(integer("8r"||chr2||move(2 to 0 by -1))) |
er("Decode","bad termcap entry",3)
}
else chr2
}
}
}
}
else new_s ||:= char(ord(map(move(1),&lcase,&ucase)) - 64)
}
new_s ||:= tab(0)
}
return new_s
end
procedure igoto(cm,col,line)
local colline, range, increment, padding, str, outstr, chr, x, y
if col > (tc_table["co"]) | line > (tc_table["li"]) then {
colline := string(\col) || "," || string(\line) | string(\col|line)
range := "(" || tc_table["co"]-1 || "," || tc_table["li"]-1 || ")"
er("igoto",colline || " out of range " || (\range|""),9)
}
# Use the Iconish 1;1 upper left corner & not the C-ish 0 offsets
increment := -1
outstr := ""
cm ? {
while outstr ||:= tab(find("%")) do {
tab(match("%"))
if padding := integer(tab(any('23')))
then chr := (="d" | "d")
else chr := move(1)
if case \chr of {
"." : outstr ||:= char(line + increment)
"+" : outstr ||:= char(line + ord(move(1)) + increment)
"d" : {
str := string(line + increment)
outstr ||:= right(str, \padding, "0") | str
}
}
then line :=: col
else {
case chr of {
"n" : line := ixor(line,96) & col := ixor(col,96)
"i" : increment := 0
"r" : line :=: col
"%" : outstr ||:= "%"
"B" : line := ior(ishift(line / 10, 4), line % 10)
">" : {
x := move(1); y := move(1)
line > ord(x) & line +:= ord(y)
&null
}
} | er("goto","bad termcap entry",5)
}
}
return outstr || tab(0)
}
end
procedure iputs(cp, affcnt)
# Writes cp to the screen. Use this instead of writes() for
# compatibility with itlib (a UNIX-only version which can handle
# albeit inelegantly) terminals that need padding.
static num_chars
initial num_chars := &digits ++ '.'
type(cp) == "string" |
er("iputs","you can't iputs() a non-string value!",10)
cp ? {
if tab(many(num_chars)) & ="*" then
stop("iputs: iolib can't use terminals that require padding.")
writes(tab(0))
}
return
end
SHAR_EOF
if test 17272 -ne "`wc -c < 'iolib.icn'`"
then
echo shar: error transmitting "'iolib.icn'" '(should have been 17272 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
INTERNET: naz%hslrswi.uucp@uunet.uu.net
UUCP: ...{uunet,ukc,mcvax,...}!chx400!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Mon Apr 22 01:53:37 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 22 Apr 91 01:53:37 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA26295; Mon, 22 Apr 91 01:53:34 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Mon, 22 Apr
1991 01:53 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA11154; Mon, 22 Apr 91
01:50:41 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 22 Apr 1991 01:53 MST
Date: 22 Apr 91 06:53:31 GMT
From: agate!stanford.edu!unixhub!linac!midway!ellis.uchicago.edu!goer@ucbvax.berkeley.edu (Richard L.
Goerwitz)
Subject: UNIX diffs, klondike
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <CD42F585CC80089A@Arizona.edu>
Message-Id: <1991Apr22.065331.13394@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
These are a some fairly minor patches which I applied to klondike
in order to get it to run on my local system here. Since the vast,
vast majority of UNIX systems out there don't use the PC character
set, I've changed the defaults around so that klondike doesn't as-
sume a PC character set if \isPC and \isDOS are not defined. I did
a few other things here and there to get klondike to run on a vt100
terminal at my home using my (poor) system termcap file. Really,
though, I didn't do much.
I don't believe I've ever seen such a nice piece of software posted
on this newsgroup. (N.A., why not cross-post to comp.sources.games
when we've all had our fun with it?) What's especially interesting
about klondike is that the author - who used to claim novice-hood at
Icon - clearly has come into full mastery of his medium, and has
gone to great lengths to write clean and readable code. It'll be a
pleasure to stick this in my source tree!
-Richard
P.S. Unix users: Apply these using patch -p < patchfilename.
----------------------- diffs for klondike -------------------------
*** kloncon.icn~ Sun Apr 21 22:30:15 1991
--- kloncon.icn Mon Apr 22 01:27:44 1991
***************
*** 32,48 ****
# For DOS, we simply look to see if any keystroke is waiting, discarding
# it/them. Your system may be different.
procedure userInterrupt ()
! static keyWaiting
! initial {
! keyWaiting := if \type(kbhit) then "kbhit"
! }
if \isDOS then
! while keyWaiting() do {
(getch() == "\0") & getch() #eat interrupting keystroke
return #success means "interrupt requested"
}
else
! (\keyWaiting) & keyWaiting() & getch() & return
fail #failure = "interrupt NOT requested"
end #userInterrupt
--- 32,45 ----
# For DOS, we simply look to see if any keystroke is waiting, discarding
# it/them. Your system may be different.
procedure userInterrupt ()
!
if \isDOS then
! while kbhit() do {
(getch() == "\0") & getch() #eat interrupting keystroke
return #success means "interrupt requested"
}
else
! (\kbhit)() & getch() & return
fail #failure = "interrupt NOT requested"
end #userInterrupt
***************
*** 58,69 ****
static outstr
local s
initial {
! outstr := table("Oops!")
outstr[VclearAll] := getval("cl") | (getval("ho") || getval("cd"))
outstr[VclearEOL] := getval("ce")
! outstr[Vnormal] := getval("me") || getval("ue")
outstr[Vbold] := getval("md" | "us")
! outstr[Vblink] := getval("mb")
outstr[Vreverse] := getval("mr" | "so")
outstr[VbackSpace] := if getval("bs") then "\b" else getval("le")
if \isQuiet then
--- 55,66 ----
static outstr
local s
initial {
! outstr := table(getval("me" | "se") || getval("ue"))
outstr[VclearAll] := getval("cl") | (getval("ho") || getval("cd"))
outstr[VclearEOL] := getval("ce")
! outstr[Vnormal] := getval("me" | "se") || (getval("ue") | "")
outstr[Vbold] := getval("md" | "us")
! outstr[Vblink] := getval("mb" | "us" | "md")
outstr[Vreverse] := getval("mr" | "so")
outstr[VbackSpace] := if getval("bs") then "\b" else getval("le")
if \isQuiet then
***************
*** 107,118 ****
local Vred, Vblack #suit color strings
lineCount := 25 #assume the best
! case (map(termtype, &lcase, &ucase)) of {
"PC" : { getANSItype (); isANSI := 1 }
"MONO" : { isMonochrome := 1; isANSI := 1 }
"COLOR" : { isMonochrome := &null; isANSI := 1 }
default : { isMonochrome := 1; isANSI := &null
! (0 < *termtype) & setname (termtype)
lineCount := getval("li")
}
}
--- 104,116 ----
local Vred, Vblack #suit color strings
lineCount := 25 #assume the best
! termtype := (map(\termtype, &lcase, &ucase))
! case termtype of {
"PC" : { getANSItype (); isANSI := 1 }
"MONO" : { isMonochrome := 1; isANSI := 1 }
"COLOR" : { isMonochrome := &null; isANSI := 1 }
default : { isMonochrome := 1; isANSI := &null
! setname (map("" ~== \termtype))
lineCount := getval("li")
}
}
***************
*** 202,218 ****
# t e r m i n a t e S c r e e n
# Put the screen in the correct state prior to program termination.
procedure terminateScreen ()
- static resetCooked
- initial {
- resetCooked := if \type(reset_tty) then "reset_tty"
- }
if /invisible then
! if \isANSI then
write ("\e[=7h", VclearAll, Vnormal) #set cursor wrap mode
! else {
! output (VclearAll, Vnormal, getval("te"))
! (/isDOS) & (\resetCooked) & resetCooked ()
}
return
end #terminateScreen
--- 200,215 ----
# t e r m i n a t e S c r e e n
# Put the screen in the correct state prior to program termination.
procedure terminateScreen ()
if /invisible then
! if \isANSI then {
write ("\e[=7h", VclearAll, Vnormal) #set cursor wrap mode
! (\reset_tty) ()
}
+ else {
+ output (VclearAll, Vnormal)
+ iputs (getval("te"))
+ (\reset_tty) () # will be nonnull only if getchlib
+ } # is linked
return
end #terminateScreen
*** klondike.icn~ Sun Apr 21 22:30:14 1991
--- klondike.icn Mon Apr 22 00:42:25 1991
***************
*** 44,50 ****
helpInfo := [
["A", "Automatic", " mode -- finish out this game on automatic pilot"],
["B", "Boss", " key for when you-know-who visits"],
! ["C","Continuous"," mode -- play games continuously until interrupted"],
["F", "Find", " (next) useful move to do"],
["H,?", "Help", ", this help screen"],
["M", "Move", " card (or stack) from Deck/Stack to Stack/Ace pile"],
--- 44,50 ----
helpInfo := [
["A", "Automatic", " mode -- finish out this game on automatic pilot"],
["B", "Boss", " key for when you-know-who visits"],
! ["C","Continuous"," mode -- play until interrupted (not UNIX)"],
["F", "Find", " (next) useful move to do"],
["H,?", "Help", ", this help screen"],
["M", "Move", " card (or stack) from Deck/Stack to Stack/Ace pile"],
***************
*** 365,371 ****
procedure uboss ()
writes ("oss") # "consistency is the hobgoblin of small minds"
terminateScreen () #put screen in the correct state
- writes ("C>") #look innocent
saveState ("klondike.sav")
exit ()
end #uboss
--- 365,370 ----
***************
*** 457,464 ****
# Results are reported after every interval (0 => only at end) games.
# Statistics are output when done or interrupted, whichever comes first.
procedure ubatch (gamesToPlay, interval)
! local veryFirstSeed, stat
! isQuiet := invisible := 1
veryFirstSeed := &random #remember the initial random seed
(interval = 0) & (interval := gamesToPlay)
repeat {
--- 456,463 ----
# Results are reported after every interval (0 => only at end) games.
# Statistics are output when done or interrupted, whichever comes first.
procedure ubatch (gamesToPlay, interval)
! local veryFirstSeed, stat
! isQuiet := invisible := 1
veryFirstSeed := &random #remember the initial random seed
(interval = 0) & (interval := gamesToPlay)
repeat {
***************
*** 472,479 ****
(stat[1] ~= interval) & break #interrupted by user
(0 = (gamesToPlay -:= interval)) & break
}
! firstSeed := veryFirstSeed #required for writeStatistics()
! writeStatistics ()
exit ()
end #ubatch
--- 471,479 ----
(stat[1] ~= interval) & break #interrupted by user
(0 = (gamesToPlay -:= interval)) & break
}
! firstSeed := veryFirstSeed #required for writeStatistics()
! (\reset_tty)()
! writeStatistics ()
exit ()
end #ubatch
***************
*** 483,490 ****
local s, prevsCmd, batchMode, reportInterval, again, termtype
# initialize
! isDOS := find("MS-DOS", &host) #probably a reasonable assumption
! isPC := isDOS #really a pretty poor assumption
totalGames:=totalAces:=totalWins := 0 #statistics
# set defaults
--- 483,491 ----
local s, prevsCmd, batchMode, reportInterval, again, termtype
# initialize
! if isDOS := find("MS-DOS",
! &host|&features) #probably a reasonable assumption
! then isPC := isDOS #really a pretty poor assumption
totalGames:=totalAces:=totalWins := 0 #statistics
# set defaults
***************
*** 497,503 ****
reportInterval := 0 # report only at end of batch mode
phraseFile := &null # use all built-in phrases
isQuiet := &null # make clicks & beeps if possible
! termtype := if \isPC then "pc" else "mono"
&random := map (&clock, ":", "7") # randomize the seed
# deal with command-line parameters
--- 498,504 ----
reportInterval := 0 # report only at end of batch mode
phraseFile := &null # use all built-in phrases
isQuiet := &null # make clicks & beeps if possible
! termtype := if \isPC then "pc" # default term type for PCs
&random := map (&clock, ":", "7") # randomize the seed
# deal with command-line parameters
***************
*** 518,523 ****
--- 519,525 ----
"-R" | "-r" : &random := integer (s[3:0])
"-S" | "-s" : findBest (s[3:0]) #check & store strategy
"-T" | "-t" : termtype := s[3:0]
+
"-Z" | "-z" : debugging := if \debugging then &null else 1
default : {
# screen mode not yet initialized, so write() is OK
***************
*** 529,535 ****
}
# initializations which use command-line parameters
! (map(termtype, &lcase, &ucase) == "PC") & isPC := 1
initConstants (termtype) #need updated termtype from cmdline
initVariables () #establish all the lists and such
--- 531,537 ----
}
# initializations which use command-line parameters
! (map(\termtype, &lcase, &ucase) == "PC") & isPC := 1
initConstants (termtype) #need updated termtype from cmdline
initVariables () #establish all the lists and such
***************
*** 566,572 ****
umove (s) | complain ()
"A" : uautomatic() #look Ma, no hands!
"B" : uboss() #bail out quick
! "C" : ucontinuous() #no hands, forever
"F" : ufind (again) & break #new game
"M" : umove (&null) | complain ()
"Q" : uterminate () & break #new game
--- 568,574 ----
umove (s) | complain ()
"A" : uautomatic() #look Ma, no hands!
"B" : uboss() #bail out quick
! "C" : \isDOS & ucontinuous() #no hands, forever
"F" : ufind (again) & break #new game
"M" : umove (&null) | complain ()
"Q" : uterminate () & break #new game
*** makefile.unx~ Sun Apr 21 22:30:12 1991
--- makefile.unx Mon Apr 22 00:45:46 1991
***************
*** 1,18 ****
#makefile.unx 910322 NHA
! #An unix makefile for klondike
#
! #Assumes that iolib.u? and getchlib.u? are already available somewhere
! #along $IPATH.
! #Note that only getchlib is linked on the command line. Everything else
! #is linked in the program.
! .SUFFIXES: .u1 .icn
.icn.u1:
icont -c $?
! klondike: klondike.icn kloncon.u1 klonstr.u1 klonsub.u1 getchlib.u1
! icont -u -Si1000 -Sn2000 klondike getchlib.u1
clean:
rm -f *.u? klondike
--- 1,19 ----
#makefile.unx 910322 NHA
! #Unix makefile for klondike
#
! #Note that only getchlib and iolib are explicitly linked on the command
! #line; other auxiliary files are loaded by link directives withing klon-
! #dike.icn.
! .SUFFIXES: .u1 .icn
.icn.u1:
icont -c $?
! SHELL = /bin/sh
!
! klondike: klondike.icn kloncon.u1 klonstr.u1 klonsub.u1 getchlib.u1 iolib.u1
! icont -u -Si1000 -Sn2000 klondike getchlib.u1 iolib.u1
clean:
rm -f *.u? klondike
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From icon-group-request@arizona.edu Mon Apr 22 17:24:51 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 22 Apr 91 17:24:51 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA29076; Mon, 22 Apr 91 17:24:48 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Mon, 22 Apr
1991 17:24 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA05600; Mon, 22 Apr 91
17:11:33 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 22 Apr 1991 17:24 MST
Date: 22 Apr 91 23:07:34 GMT
From: swrinde!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!midway!ellis.uchicago.edu!goer@ucsd.edu (Richard L.
Goerwitz)
Subject: RE: UNIX diffs, klondike
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <4F57807CCC8019A1@Arizona.edu>
Message-Id: <1991Apr22.230734.1432@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <1991Apr22.065331.13394@midway.uchicago.edu>
Just a note - an IMPORTANT one - to tack onto the preceding: Please
read through the getchlib docs if you are on a system that does not
implement the -g option for stty. Also if your stty command can't
write its output to a pipe (what a sorry world this is), check the
getchlib.icn file as well. OTHERWISE YOUR TERMINAL ENDS UP IN RAW
MODE!
People with regular System V stty commands or older BSD ones (or some
newer BSD ones -it apparently works here on our Sun3) should have no-
thing to worry about.
I'm sorry I didn't mention this sooner.
-Richard
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From @um.cc.umich.edu:Paul_Abrahams@MTS.cc.Wayne.edu Mon Apr 22 19:26:15 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 22 Apr 91 19:26:15 MST
Received: from umich.edu by optima.cs.arizona.edu (4.1/15)
id AA02566; Mon, 22 Apr 91 19:26:13 MST
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA17068; Mon, 22 Apr 91 22:26:09 -0400
Received: from MTS.cc.Wayne.edu by um.cc.umich.edu via MTS-Net; Mon, 22 Apr 91 22:21:45 EDT
Date: Mon, 22 Apr 91 22:21:50 EDT
From: Paul_Abrahams@mts.cc.wayne.edu
To: icon-group@cs.arizona.edu
Message-Id: <322705@MTS.cc.Wayne.edu>
Subject: Evaluation rules for !set
I'm puzzled by the behavior of the following tiny program:
procedure main()
x := set([1,2,3])
every writes(e := !x, " ") do insert(x, e+10)
end
In MS-DOS Icon V8 it prints:
1 2 3 11 12 21
The question is: what happens when you iterate over a set and modify
it at the same time? I would have expected either just "1 2 3" (if the
value of x is saved) or an infinite sequence (if x is continually modified.)
I don't understand what accounts for the result I got. Is there an
explanation of this somewhere in the (new) Icon book?
Paul Abrahams
From ralph Mon Apr 22 19:31:43 1991
Date: Mon, 22 Apr 91 19:31:43 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9104230231.AA05065@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Mon, 22 Apr 91 19:31:43 MST
To: Paul_Abrahams@mts.cc.wayne.edu, icon-group@cs.arizona.edu
Subject: Re: Evaluation rules for !set
It's bad policy to iterate over a aggregate that has no defined
order while modifying that aggregate. That's basically asking
for trouble.
We've taken some pains to make sure you don't get garbage or get
in a loop, but beyond that what you get is implementation dependent.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From icon-group-request@arizona.edu Thu Apr 25 04:18:45 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 25 Apr 91 04:18:45 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA21780; Thu, 25 Apr 91 04:18:42 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 25 Apr
1991 04:18 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA05315; Thu, 25 Apr 91
04:12:45 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 25 Apr 1991 04:18 MST
Date: 25 Apr 91 11:01:24 GMT
From: eru!hagbard!sunic!news.funet.fi!hydra!cc.helsinki.fi!veijalainen@bloom-beacon.mit.edu
Subject: Icon Version 8 fot Acorn Archimedes needed!
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <3D068E126C802944@Arizona.edu>
Message-Id: <1991Apr25.110125.6122@cc.helsinki.fi>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Helsinki
ICON VERSION 8 FOR ACORN ACHIMEDES NEEDED
I have sources off poring library of Icon version 8 for hierarchical filing
systems. I have however considerable difficulty off adapting the language to
extensionless filing system names of British/Italian Acorn Archimedes. I have
conditionally compiled hierarchical name references of the icon source #include
statements, but language itself needs to refer to files and that part I have
not fixed (yet). If somebody has allready done the work, I don't want to tackle
the project myself. Also after seeing article about coroutines in latest
Archive magazine, I would like an icon with coroutines implemented. My
C-compiler is however is old Arthur version ( I think ver. 1.54, is there any
way to link programs to shared C library with it? ), so the routine is not
suitable for my own use. If you do have done the conversion, I hope you
send it to Newcastle (info-server@newcastle.ac.uk)
and Oulu, Finland ( tolsun.oulu.fi, directory incoming/acorn) or
of course mail it to me.
Tony Veijalainen
Veijalainen@cc.helsinki.FI
From gudeman Mon Apr 29 12:16:59 1991
Received: from orator.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 29 Apr 91 12:16:59 MST
Date: Mon, 29 Apr 91 12:16:57 MST
From: "David Gudeman" <gudeman>
Message-Id: <9104291916.AA23734@orator.cs.arizona.edu>
Received: by orator.cs.arizona.edu; Mon, 29 Apr 91 12:16:57 MST
To: icon-group
Subject: augmented assignment
Someone in another newsgroup suggested that C should have the
augmented assignment "a ->= b" which means "a = a->b". In Icon this
would translate to "a .:= b" which means "a := a.b". It seems to me
that this could be useful in Icon even though it might be a little
hard to parse. (It wouldn't be quite as useful as in C, where you
write code like "p = p->next" all the time.)
From kelvin@kickapoo.cs.iastate.edu Mon Apr 29 12:41:44 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 29 Apr 91 12:41:44 MST
Received: from judy.cs.iastate.edu by optima.cs.arizona.edu (4.1/15)
id AA22268; Mon, 29 Apr 91 12:41:34 MST
Received: from kickapoo.cs.iastate.edu.noname by judy.cs.iastate.edu (4.1) id AA15244; Mon, 29 Apr 91 14:40:09 CDT
Received: by kickapoo.cs.iastate.edu.noname (4.1/SMI-4.1)
id AA07045; Mon, 29 Apr 91 14:40:43 CDT
Date: Mon, 29 Apr 91 14:40:43 CDT
From: kelvin@kickapoo.cs.iastate.edu (Kelvin Don Nilsen)
Message-Id: <9104291940.AA07045@kickapoo.cs.iastate.edu.noname>
To: gudeman@cs.arizona.edu
Cc: icon-group@cs.arizona.edu
In-Reply-To: "David Gudeman"'s message of Mon, 29 Apr 91 12:16:57 MST <9104291916.AA23734@orator.cs.arizona.edu>
Subject: augmented assignment
Here's a minor point to consider regarding the proposal of adding ".:="
as another augmented assignment operator:
If this operation were added to the language, it would represent
a "special case" in that the right hand subexpression argument is
really not an arbitrary expression, but must represent a record field
name.
On the other hand, many users likely view its omission as a special case.
I did, until I started to consider implementation concerns.
Kelvin Nilsen/Dept. of Computer Science/Iowa State University/Ames, IA 50011
(515) 294-2259 kelvin@cs.iastate.edu uunet!atanasoff!kelvin
From pbewig@netcom.netcom.com Tue May 14 10:16:02 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 14 May 91 10:16:02 MST
Received: from netcom.netcom.com ([192.100.81.100]) by optima.cs.arizona.edu (4.1/15)
id AA24070; Tue, 14 May 91 10:15:57 MST
Received: by netcom.netcom.com (/\==/\ Smail3.1.20.1 #20.6)
id <m0jd2Wx-000CPgC@netcom.netcom.com>; Tue, 14 May 91 09:47 PDT
Message-Id: <m0jd2Wx-000CPgC@netcom.netcom.com>
Date: Tue, 14 May 91 10:15 PDT
From: pbewig@netcom.com (Phil Bewig)
X-Mailer: Mail User's Shell (7.2.0 10/31/90)
To: icon-group@cs.arizona.edu
Shown below is a superset of the c language printf family of functions
for icon. I am new enough to icon that most of the procedures can
doubtless be rewritten; see float2str for a particularly bad example.
############################################################################
#
# Name: printf.icn
#
# Title: print formatted output
#
# Author: Philip L. Bewig
#
# Date: May 13, 1991
#
############################################################################
#
# The printf procedures provide general formatted output. They share a
# common syntax, differing only in the place where output is sent:
#
# printf(fmt, expr, expr ...) - send output to stdout
# sprintf(fmt, expr, expr ...) - return output as value of function
# fprintf(fd, fmt, expr, expr ...) - send output to file fd
#
# Essentially, the printf functions work by copying the format string to
# the output. Regular characters are copied unchanged. Escape sequences
# are converted to their corresponding string values; the same escape
# sequences recognized by the icon language are recognized by printf. The
# only real processing performed is to interpret conversion specifications
# which begin with the "%" character; each conversion specification trans-
# forms the next expression in the procedure call to the desired form.
#
# Conversion specifications have the form
#
# %[-|=][w][.p]c
#
# where
#
# - left justifies the field
# = centers the field
# w is the minimum field width
# p is the precision
# c is the conversion character
#
# By default, the field is right justified in a field of width w, which
# has a default value of zero; the "-" and "=" specifiers override the
# default. In a string, the precision is the maximum number of characters
# to be printed; in a floating point number, the precision is the number
# of digits to be printed to the right of the decimal point and has a
# default value of six. If "w" or "p" is "*" (star), the minimum field
# width or precision will be the value of the next expr in the function
# call. For a numeric field, if "w" begins with zero the field will be
# padded to the left with zeros instead of blank spaces; this implemen-
# tation faithfully reproduces a bug in many printf functions which causes
# sprintf("%05d", -2) to produce the string "000-2".
#
# The conversion character c is one of the following:
#
# a positive integer, using letters as digits; the integers
# 1 through 256 are counted a, b, ..., z, aa, ab, ...
# az, ba, bb, ..., iv (same as Lotus 1-2-3 columns)
# A same as a, but print upper-case letters
# b unsigned binary integer
# c single character of an integer value
# d decimal integer
# e floating point (scientific notation)
# E same as e, but print upper-case "E"
# f floating point
# g the shorter of e and f (suppresses non-significant zeros)
# G same as g, but print upper-case "E"
# o unsigned octal integer
# r integer in range 1 to 3999, converted to roman numerals
# R same as r, but print upper-case letters
# s string
# S string, with all letters converted to upper-case
# u unsigned decimal integer
# w integer with absolute value less than one billion, converted
# to english words
# W same as x, but print letters as upper-case
# x unsigned hexadecimal integer
# X same as x, but print hex digit letters as upper-case
# $ similar to f, but with a "$" prepended to the output;
# negative numbers are parenthesized, and an extra
# print position is allowed to the right of positive
# numbers
# % literal percent sign; no expr is consumed
#
# There may be any number of expressions following the format string;
# extra expressions are ignored, but missing expressions cause a run-time
# error.
#
# This printf function is a strict superset of the features provided by
# the standard c or awk printf function; any format specification which
# they provide is provided identically here.
#
# There are several local functions which provide a single type of con-
# version which may be more useful than a general-purpose formatter in
# some situations. They are float2str(num, prec), float2sci(num, prec),
# float2dollar(num, prec), int2alpha(num), int2roman(num), int2words(num),
# unsigned2hex(num), unsigned2dec(num), unsigned2oct(num), and
# unsigned2bin(num). All of these functions return lower-case letters
# where appropriate which may be converted to upper-case by the function
# map(...,&lcase,&ucase).
#
############################################################################
#
# test driver
# procedure main()
# repeat {
# writes("enter a format specification (null to quit): ")
# fmt := read()
# if *fmt = 0 then break
# exprlist := []
# repeat {
# writes("enter an expression (null to print): ")
# temp := read()
# if *temp = 0 then break
# put(exprlist, temp)
# }
# write("the output is |" || sprintf(fmt, exprlist) || "|")
# write()
# }
# end
#
############################################################################
# sprintf - return formatted string
procedure sprintf(fmt, exprlist)
local out, just, wid, prec, conv, pad, val, v1, v2, i, s
out := ""
fmt ? repeat {
(out ||:= tab(upto('%\\'))) | (out ||:= tab(0) & break)
case move(1) of {
"%": { # format specification
# initialize
just := right
wid := prec := conv := pad := val := &null
# parse the format specification
tab(match("-")) & just := left
tab(match("=")) & just := center
wid := (tab(many(&digits)) | tab(match("*")))
(\wid)[1] == "*" & wid := get(exprlist)
tab(match(".")) & (prec := (tab(many(&digits)) | tab(match("*"))))
(\prec)[1] == "*" & prec := get(exprlist)
conv := move(1)
# perform the specified conversion
val := get(exprlist)
case map(conv) of {
"a": { if not(val := int2alpha(val)) then val := &null }
"b": { (\wid)[1] == "0" & pad := "0"
if not(val := unsigned2bin(val)) then val := &null }
"c": { val := char(val) }
"d": { (\wid)[1] == "0" & pad := "0"; val := integer(val) }
"e": { (\wid)[1] == "0" & pad := "0"; val := float2sci(val, prec) }
"f": { (\wid)[1] == "0" & pad := "0"; val := float2str(val, prec) }
"g": { (\wid)[1] == "0" & pad := "0"
v1 := float2sci(val, prec)
v2 := float2str(val, prec)
val := (if *v1 < *v2 then v1 else v2) }
"o": { (\wid)[1] == "0" & pad := "0"
if not(val := unsigned2oct(val)) then val := &null }
"r": { if not(val := int2roman(val)) then val := &null }
"s": { if \prec then val := left(val, prec) }
"u": { (\wid)[1] == "0" & pad := "0"
if not(val := unsigned2dec(val)) then val := &null }
"w": { if not(val := int2words(val)) then val := &null }
"x": { (\wid)[1] == "0" & pad := "0"
if not(val := unsigned2hex(val)) then val := &null }
"$": { (\wid)[1] == "0" & pad := "0"
val := float2dollar(val, prec) }
"%": { push(exprlist, val); val := "%" }
default: { out := &null; break }
}
if conv ~== map(conv) then val := map(val, &lcase, &ucase)
if \wid & *val < wid then val := just(val, wid, pad)
out ||:= val
}
"\\": { # escape sequence
# escape handler derived from an ipl proc by William H. Mitchell
out ||:= case c := map(move(1)) of {
"b": "\b"
"d": "\d"
"e": "\e"
"f": "\f"
"l": "\l"
"n": "\n"
"r": "\r"
"t": "\t"
"v": "\v"
"'": "'"
"\"": "\""
"x": {
move(i := 2 | 1) ? s := tab(upto(~'0123456789ABCDEFabcdef') | 0)
move(*s - i)
char("16r" || s)
}
"^": char(iand(ord(move(1)), 16r1f))
!"01234567": {
move(-1)
move(i := 3 | 2 | 1) ? s := tab(upto(~'01234567') | 0)
move(*s - i)
if s > 377 then {
s := s[1:3]
move(-1)
}
char("8r" || s)
}
default: c
}
}
}
}
return out
end
# printf - print formatted string
procedure printf(fmt, exprlist)
writes(sprintf(fmt, exprlist))
return
end
# fprintf - write formatted string to file
procedure fprintf(fd, fmt, exprlist)
writes(fd, sprintf(fmt, exprlist))
return
end
# float2str - convert floating point number to string format
# this procedure looks more like pascal than icon
procedure float2str(num, ndigs)
local out, nbefore, i, digit
nbefore := 1; /ndigs := 6 # initialize, set default
if num < 0 then { out := "-"; num *:= -1 } else { out := "" }
num +:= 0.5 / 10.0 ^ ndigs # round to desired precision
while num >= 10.0 do { num /:= 10.0; nbefore +:= 1 } # normalize
every i := 1 to (nbefore + ndigs) do {
if i = nbefore + 1 then out ||:= "."
digit := integer(num)
out ||:= char(digit + 48)
num := 10.0 * (num - digit)
}
return out
end
# float2sci - convert floating point number to string in scientific format
procedure float2sci(num, ndigs)
local frac, expo
frac := num; expo := 0
if abs(frac) >= 10.0 then {
until abs(frac) < 10.0 do {
frac /:= 10.0; expo +:= 1
}
} else if abs(frac) < 1.0 & frac ~= 0.0 then {
until abs(frac) > 1.0 do {
frac *:= 10.0; expo -:= 1
}
}
return float2str(frac, ndigs) || "e" || string(expo)
end
# float2dollar - convert floating point number to string, prepend dollar sign
procedure float2dollar(num, prec)
if num >= 0 then
return "$" || float2str(num, prec) || " "
else
return "($" || float2str(-num, prec) || ")"
end
# unsigned2hex - convert unsigned int to hex string
procedure unsigned2hex(num)
local out, nonzero, digit
static hexdigit
initial { hexdigit := "0123456789abcdef" }
if num ~= integer(num) then fail
if num > 2147483647 then fail
if num < -2147483648 then fail
out := ""; nonzero := &null
every i := 28 to 0 by -4 do {
digit := hexdigit[iand(ishift(num,-i),15)+1]
if digit == "0" & /nonzero then next
nonzero := ""; out ||:= digit
}
return out
end
# unsigned2oct - convert unsigned int to octal string
procedure unsigned2oct(num)
local out, nonzero, digit
if num ~= integer(num) then fail
if num > 2147483647 then fail
if num < -2147483648 then fail
out := ""; nonzero := &null
every i := 30 to 0 by -3 do {
digit := string(iand(ishift(num,-i),7))
if digit == "0" & /nonzero then next
nonzero := ""; out ||:= digit
}
return out
end
# unsigned2bin - convert unsigned int to binary string
procedure unsigned2bin(num)
local out, nonzero, digit
if num ~= integer(num) then fail
if num > 2147483647 then fail
if num < -2147483648 then fail
out := ""; nonzero := &null
every i := 31 to 0 by -1 do {
digit := string(iand(ishift(num,-i),1))
if digit == "0" & /nonzero then next
nonzero := ""; out ||:= digit
}
return out
end
# unsigned2dec - convert unsigned int to decimal string
procedure unsigned2dec(num)
if num ~= integer(num) then fail
else if num > 2147483647 then fail
else if num < -2147483648 then fail
else if num >= 0 then return string(num)
else return string(4294967296 - -num)
end
# int2alpha - convert integer to alpha string
procedure int2alpha(num)
local out
static alpha
initial alpha := string(&lcase)
if num ~= integer(num) then fail
if num <= 0 then fail
num -:= 1
out := alpha[num % 26 + 1]
while (num := num / 26 - 1) >= 0 do
out ||:= alpha[num % 26 + 1]
return reverse(out)
end
# int2roman - convert integer to roman numerals
# this procedure derived from a program by Ralph E. Griswold
procedure int2roman(num)
local arabic, result
static equiv
initial equiv := ["","i","ii","iii","iv","v","vi","vii","viii","ix"]
integer(num) > 0 | fail
result := ""
every arabic := !num do
result := map(result,"ivxlcdm","xlcdm**") || equiv[arabic+1]
if find("*",result) then fail else return result
end
# int2words - convert integer to english words
procedure int2words(num)
local out
static tens, nums
initial {
nums := ["one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen",
"eighteen", "nineteen"]
tens := ["ten", "twenty", "thirty", "forty", "fifty", "sixty",
"seventy", "eighty", "ninety"]
}
if num ~= integer(num) then fail
if num < 0 then
return "negative " || int2words(-num)
if num >= 1000000000 then {
fail
} else if num >= 1000000 then {
out := int2words(num/1000000) || " million"
if num%1000000 ~= 0 then out ||:= " " || int2words(num%1000000)
} else if num >= 1000 then {
out := int2words(num/1000) || " thousand"
if num%1000 ~= 0 then out ||:= " " || int2words(num%1000)
} else if num >= 100 then {
out := int2words(num/100) || " hundred"
if num%100 ~= 0 then out ||:= " " || int2words(num%100)
} else if num >= 20 then {
out := tens[integer(num/10)]
if num%10 ~= 0 then out ||:= " " || int2words(num%10)
} else if num > 0 then {
out := nums[num]
} else out := "zero"
return out
end
From pbewig@netcom.netcom.com Tue May 14 15:25:46 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 14 May 91 15:25:46 MST
Received: from netcom.netcom.com ([192.100.81.100]) by optima.cs.arizona.edu (4.1/15)
id AA08666; Tue, 14 May 91 15:25:42 MST
Received: by netcom.netcom.com (/\==/\ Smail3.1.20.1 #20.6)
id <m0jd7nj-000CSEC@netcom.netcom.com>; Tue, 14 May 91 15:25 PDT
Message-Id: <m0jd7nj-000CSEC@netcom.netcom.com>
Date: Tue, 14 May 91 15:25 PDT
From: pbewig@netcom.com (Phil Bewig)
X-Mailer: Mail User's Shell (7.2.0 10/31/90)
To: icon-group@cs.arizona.edu
Hello,
Here's another little procedure for formatted output. Enjoy! !
############################################################################
#
# Name: prdate.icn
#
# Title: print formatted dates
#
# Author: Philip L. Bewig
#
# Date: May 13, 1991
#
############################################################################
#
# The prdate family of procedures provide formatted date output. They
# share a common syntax, differing only in the place where output is sent:
#
# prdate(fmt, date) - send output to stdout
# sprdate(fmt, date) - return output as value of function
# fprdate(fd, fmt, date) - send output to file fd
#
# Essentially, the prdate functions work by copying the format string to
# the output. Regular characters are copied unchanged. Escape sequences
# are converted to their corresponding string values; the same escape
# sequences recognized by the icon language are recognized by prdate. The
# only real processing performed is to interpret conversion specifications
# which begin with the "%" character.
#
# Conversion specifications have the form
#
# %xx
#
# where xx may be any of the following:
#
# m1 - month number in range 1 to 12
# m2 - month number in range 01 to 12
# m3 - month name in range Jan to Dec
# M3 - month name in range JAN to DEC
# m4 - month name in range January to December
# M4 - month name in range JANUARY to DECEMBER
#
# d1 - day number in range 1 to 31
# d2 - day number in range 01 to 31
#
# y1 - year number in range 0 to 99
# y2 - year number in range 00 to 99
# y3 - year number in range 0 to 9999
# y4 - year number in range 0000 to 9999
#
# n1 - day name in range Sun to Sat
# N1 - day name in range SUN to SAT
# n2 - day name in range Sunday to Saturday
# N2 - day name in range SUNDAY to SATURDAY
#
# A percent sign may be input literally by "%%".
#
# The date may be specified in one of two formats. An eight-digit number
# is assumed to be a date of the form "CCYYMMDD". A smaller number is
# assumed to be a julian number representing a date, calculated using the
# jdate.icn code posted to icon-group by Cary Coutant. Dates preceeding
# the christian era are not supported.
#
# For example, the function call sprdate("n2, m4 d1, y3", 17760704)
# returns the string "Thursday, July 4, 1776" and the function call
# sprdate("m2/d2/y4", 17760704) returns the string "07/04/1776".
#
############################################################################
#
# links: julian.icn - Cary Coutant's julian date routines
# (gregorian, julian, datestring, dayofweek,
# tomdy, and floor procedures)
#
############################################################################
#
# test driver
# procedure main()
# repeat {
# writes("enter a format specification (null to quit): ")
# fmt := read()
# if *fmt = 0 then break
# writes("enter a date in CCYYMMDD or julian number form: ")
# expr := read()
# write("the output is |" || sprdate(fmt, expr) || "|")
# write()
# }
# end
#
############################################################################
link julian
# sprdate - return formatted date string
procedure sprdate(fmt, expr)
local out, i, s, g, m, d, y, dow, val
static months
initial {
months := ["January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December"]
}
if *expr >= 8 then {
m := integer(expr[5:7])
d := integer(expr[7:9])
y := integer(expr[1:5])
dow := dayofweek(gregorian(m,d,y))
} else {
mdy := tomdy(expr)
m := mdy[1]; d := mdy[2]; y := mdy[3]
dow := dayofweek(expr)
}
out := ""
fmt ? repeat {
(out ||:= tab(upto('%\\'))) | (out ||:= tab(0) & break)
case move(1) of {
"%": { # format specification
if match('%') then {
out ||:= "%"
move(1)
} else {
conv := move(2)
case conv of {
"m1": { val := m }
"m2": { val := right(m, 2, "0") }
"m3": { val := left(months[m], 3) }
"M3": { val := map(left(months[m], 3), &lcase, &ucase) }
"m4": { val := months[m] }
"M4": { val := map(months[m], &lcase, &ucase) }
"d1": { val := d }
"d2": { val := right(d, 2, "0") }
"y1": { val := y % 100 }
"y2": { val := right(y % 100, 2, "0") }
"y3": { val := y }
"y4": { val := right(y, 4, "0") }
"n1": { val := left(dow, 3) }
"N1": { val := map(left(dow, 3), &lcase, &ucase) }
"n2": { val := dow }
"N2": { val := map(dow, &lcase, &ucase) }
default: { val := &null; break }
}
out ||:= val
}
}
"\\": { # escape sequence
# escape handler derived from an ipl proc by William H. Mitchell
out ||:= case c := map(move(1)) of {
"b": "\b"
"d": "\d"
"e": "\e"
"f": "\f"
"l": "\l"
"n": "\n"
"r": "\r"
"t": "\t"
"v": "\v"
"'": "'"
"\"": "\""
"x": {
move(i := 2 | 1) ? s := tab(upto(~'0123456789ABCDEFabcdef') | 0)
move(*s - i)
char("16r" || s)
}
"^": char(iand(ord(move(1)), 16r1f))
!"01234567": {
move(-1)
move(i := 3 | 2 | 1) ? s := tab(upto(~'01234567') | 0)
move(*s - i)
if s > 377 then {
s := s[1:3]
move(-1)
}
char("8r" || s)
}
default: c
}
}
}
}
return out
end
# prdate - write date to standard output
procedure prdate(fmt, expr)
writes(sprdate(fmt, expr))
return
end
# fprdate - write date to file
procedure fprdate(fd, fmt, expr)
writes(fd, sprdate(fmt, expr))
return
end
From icon-group-request@arizona.edu Tue May 14 16:03:38 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 14 May 91 16:03:38 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA10944; Tue, 14 May 91 16:03:36 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Tue, 14 May
1991 16:03 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA19587; Tue, 14 May 91
15:52:26 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 14 May 1991 16:03 MST
Date: 14 May 91 22:26:51 GMT
From: midway!ellis.uchicago.edu!goer@handies.ucar.edu (Richard L. Goerwitz)
Subject: Algol->Icon & Pascal
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <8DA76AF1E6401602@Arizona.edu>
Message-Id: <1991May14.222651.16502@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
I've always wondered why Icon uses the brace notation (rather than
begin ... end;) for most groupings, but yet for procedures, a kind
of mixed procedure name(vars)...end notation is used. I'm also a
bit curious why the notion of functions and procedures was collap-
sed into procedures, and yet with retention of the notion that a
procedure is a value (i.e. like what we normally associate with fun-
ctions).
Just curious.
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From gudeman Tue May 14 16:13:39 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 14 May 91 16:13:39 MST
Resent-From: "David Gudeman" <gudeman>
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA11319; Tue, 14 May 91 16:13:37 MST
Received: from optima.cs.arizona.edu by Arizona.edu with PMDF#10282; Tue, 14
May 1991 16:13 MST
Received: from orator.cs.arizona.edu by optima.cs.arizona.edu (4.1/15) id
AA11267; Tue, 14 May 91 16:13:01 MST
Received: by orator.cs.arizona.edu; Tue, 14 May 91 16:12:59 MST
Resent-Date: Tue, 14 May 1991 16:13 MST
Date: Tue, 14 May 91 16:12:59 MST
From: David Gudeman <gudeman@cs.arizona.edu>
Subject: Algol->Icon & Pascal
In-Reply-To: Richard L. Goerwitz's message of 14 May 91 22:26:51 GMT
<1991May14.222651.16502@midway.uchicago.edu>
Resent-To: icon-group@cs.arizona.edu
To: midway!ellis.uchicago.edu!goer@handies.ucar.edu
Cc: icon-group@arizona.edu
Resent-Message-Id: <8F0D1523C6401611@Arizona.edu>
Message-Id: <9105142312.AA11405@orator.cs.arizona.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: midway!ellis.uchicago.edu!goer@handies.ucar.edu
X-Vms-Cc: icon-group@Arizona.edu
>From: Richard L. Goerwitz
>... I'm also a
>bit curious why the notion of functions and procedures was collap-
>sed into procedures, and yet with retention of the notion that a
>procedure is a value (i.e. like what we normally associate with fun-
>ctions).
I assume you are talking about the Pascal distinction that functions
are expression (things that return values) and procedures are
statements (things that change variables but don't return values).
But Icon doesn't have statements --only expressions-- so there is no
such distinction to make.
As to procedures being values, there is nothing unlikely about
procedures-as-values even for Pascal-style procedures. It's just not
traditional for Pascal-like languages to have procedures or functions
as first-class values.
From R.J.Hare@edinburgh.ac.uk Thu May 16 01:06:48 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 16 May 91 01:06:48 MST
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA23169; Thu, 16 May 91 01:06:45 MST
Received: from UKACRL.BITNET (MAILER@UKACRL) by Arizona.edu with PMDF#10282;
Thu, 16 May 1991 01:06 MST
Received: from RL.IB by UKACRL.BITNET (Mailer R2.07) with BSMTP id 2380; Thu,
16 May 91 09:02:59 BST
Received: from RL.IB by UK.AC.RL.IB (Mailer R2.07) with BSMTP id 5317; Thu, 16
May 91 09:00:21 BST
Date: 16 May 91 08:57:28 bst
From: R.J.Hare@edinburgh.ac.uk
Subject: Language 'tutors'
To: icon-group@cs.arizona.edu
Message-Id: <16 May 91 08:57:28 bst 060957@EMAS-A>
X-Envelope-To: icon-group@cs.arizona.edu
Via: UK.AC.ED.EMAS-A; 16 MAY 91 9:00:19 BST
Has anyone used Icon to develop 'tutors' for learning foreign languages
in any way - for example, vocabulary drills, simple phrase translation,
etc.?
If yes, are such programs available?
Thanks.
Roger Hare.
From KKTK_KOTUS@cc.helsinki.fi Thu May 16 04:25:57 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 16 May 91 04:25:57 MST
Received: from HYLKA.HELSINKI.FI by optima.cs.arizona.edu (4.1/15)
id AA02858; Thu, 16 May 91 04:25:45 MST
Date: Thu, 16 May 1991 14:25 EET
From: KKTK_KOTUS@cc.helsinki.fi
Subject: A word/line procedure
To: icon-group@cs.arizona.edu
Message-Id: <124E207800E17F06@cc.Helsinki.FI>
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Dear iconists,
I have a following, obviosly simple problem. I have made a nice
Icon procedure, which divides a text file one word/line. It is much easier,
simpler and faster than the one given in Icon book. It goes like this
(the original idea is, I believe, from some Unix-procedure, and it is the same
thing you would do with any editor or text processing program, if you had to
use them for the work):
procedure main()
while line:=read() do write(map(line," ","\l"))
end
It works fine and fast, but it produces also empty lines which I cannot get rid
off in the same procedure, although I try to filter them out with something
like
if *line > 0 then write(line)
But if I make the first procedure to write the stuff in a file and then process
that file with the procedure
procedure main()
while line:=read() do if *line > 0 then write(line)
end
I get rid off the empty lines. It is easy to make a .bat or .com or whatever
from these two procedures, and the whole thing still works at least as fast or
even faster than the procedure in the Icon book. But
I would still like to know, how I actually could make it work in one shot. I
have tried different solutions, but they do not work. Can anybody
explain it?
Greetings,
Kimmo Kettunen
KKTK_KOTUS@CC.HELSINKI.FI
From isidev!nowlin@uunet.uu.net Thu May 16 07:53:49 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 16 May 91 07:53:49 MST
Received: from relay1.UU.NET by optima.cs.arizona.edu (4.1/15)
id AA06729; Thu, 16 May 91 07:53:46 MST
Received: from isidev.UUCP (LOCALHOST.UU.NET) by relay1.UU.NET with SMTP
(5.61/UUNET-internet-primary) id AA23636; Thu, 16 May 91 10:53:42 -0400
Date: Thu, 16 May 91 10:53:42 -0400
From: isidev!nowlin@uunet.uu.net
Message-Id: <9105161453.AA23636@relay1.UU.NET>
To: uunet!cs.arizona.edu!icon-group@uunet.uu.net
Subject: Re: word/line procedure
> From Kimmo Kettunen
>
> I have a following, obviosly simple problem. I have made a nice Icon
> procedure, which divides a text file one word/line. It is much easier,
> ...
> procedure main()
> while line:=read() do write(map(line," ","\l"))
> end
>
> It works fine and fast, but it produces also empty lines which I cannot get
> rid off in the same procedure, although I try to filter them out with
> something like
>
> if *line > 0 then write(line)
First you have to remember that in Icon you're working on strings, NOT
lines. The result of the map() is not a series of lines but the same basic
string with spaces changed to newlines. The length of the string hasn't
changed. Testing the length of the string to discard empty lines won't do
any good at this point.
> But if I make the first procedure to write the stuff in a file and then
> process that file with the procedure
>
> procedure main()
> while line:=read() do if *line > 0 then write(line)
> end
The reason testing the length works on the second pass is that now you're
reading in the original string in little pieces, one line at a time. If
some of these pieces are empty lines they now exhibit zero length and can
be discarded.
> ...
> I would still like to know, how I actually could make it work in one shot.
> I have tried different solutions, but they do not work. Can anybody
> explain it?
I diddled your basic design, which is a neat idea by the way, and instead
of writing out the entire mapped string I write it out in pieces that are
delimited by the newlines that were mapped into the string. This allows
the program to skip over consecutive bunches of newlines and thereby
discard the "blank lines" in one pass. You'll have to test its speed. It
may not be that fast now.
procedure main()
# convert input spaces to newlines and scan the result
while line := map(read()," ","\l") do line ? {
# skip initial newlines
tab(many('\l'))
# write out substrings delimited by newlines
while write(tab(upto('\l'))) do
# skip newlines
tab(many('\l'))
# write out the last substring
if not pos(0) then write(tab(0))
}
end
I'd assign the newline cset to a variable since it's used several places
now and maybe change the map to handle more "white space" characters than
just the space. The tab comes to mind. It's a good program idea.
--- ---
| S | Iconic Software, Inc. - Jerry Nowlin - uunet!isidev!nowlin
--- ---
From cargo@cherry.cray.com Thu May 16 08:34:24 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 16 May 91 08:34:24 MST
Received: from timbuk (timbuk.cray.com) by optima.cs.arizona.edu (4.1/15)
id AA07941; Thu, 16 May 91 08:34:19 MST
Received: from cherry04.cray.com by timbuk (4.1/CRI-MX 1.6d)
id AA17236; Thu, 16 May 91 10:34:07 CDT
Received: by cherry04.cray.com
id AA23758; 4.1/CRI-5.6; Thu, 16 May 91 10:34:04 CDT
Date: Thu, 16 May 91 10:34:04 CDT
From: cargo@cherry.cray.com (David S. Cargo)
Message-Id: <9105161534.AA23758@cherry04.cray.com>
To: icon-group@cs.arizona.edu
Subject: input pushbacks
I'm writing a program that is simplified by having a mechanism for
"unreading" a line (or group of lines). I'm looking a various
implementations for doing that. Some use an input list that checked
for size before reading from a file. Others use more elaborate
structures.
I'm curious about possible solutions the problem and whether other
people have found a need for such mechanisms themselves.
o o
cargo@escargot.cray.com \_____/
(612) 683-5591 /-o-o-\ _______
DDDD SSSS CCCC / ^ \ /\\\\\\\\
D D S C \ \___/ / /\ ___ \
D D SSS C \_ _/ /\ /\\\\ \
D D S C \ \__/\ /\ @_/ /
DDDDavid SSSS. CCCCargo \____\____\______/
From shafto@eos.arc.nasa.gov Thu May 16 12:27:50 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 16 May 91 12:27:50 MST
Received: from eos.arc.nasa.gov by optima.cs.arizona.edu (4.1/15)
id AA16754; Thu, 16 May 91 12:27:48 MST
Received: Thu, 16 May 91 12:27:44 -0700 by eos.arc.nasa.gov (5.65/1.2)
Date: Thu, 16 May 91 12:27:44 -0700
From: Michael Shafto <shafto@eos.arc.nasa.gov>
Message-Id: <9105161927.AA25003@eos.arc.nasa.gov>
To: cargo@cherry.cray.com, icon-group@cs.arizona.edu
Subject: Re: input pushbacks
Cc: shafto@eos.arc.nasa.gov
Have you looked at the routine in Gimpel's
_Algorithms in SNOBOL4_, pp. 167ff.?
Mike
From icon-group-request@arizona.edu Thu May 16 13:43:26 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 16 May 91 13:43:26 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA20127; Thu, 16 May 91 13:43:23 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 16 May
1991 13:42 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA27814; Thu, 16 May 91
10:12:27 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 16 May 1991 13:43 MST
Date: 16 May 91 15:30:40 GMT
From: usc!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!midway!ellis.uchicago.edu!goer@ucsd.edu (Richard L.
Goerwitz)
Subject: RE: A word/line procedure
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <0C637EE0B6401F3A@Arizona.edu>
Message-Id: <1991May16.153040.9843@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <124E207800E17F06@cc.Helsinki.FI>
In article <124E207800E17F06@cc.Helsinki.FI> KKTK_KOTUS@cc.helsinki.fi writes:
>
>I have a following, obviously simple problem. I have made a nice
>Icon procedure, which divides a text file one word/line....:
>
> procedure main()
> while line:=read() do write(map(line," ","\l"))
> end
>
>It works fine and fast, but it produces also empty lines which I cannot get rid
>off in the same procedure, although I try to filter them out with something
>like
>
> if *line > 0 then write(line)
I don't see how you can eliminate blank lines that are due to adjacent
spaces. If all words are guaranteed to be separated by one space, and
no more, then naturally you could say
... do write("" ~== map(line, " ", "\l"))
This would eliminate lines with no words on them. If, though, your files
distance words from each other using more than one blank space, you will
surely need to scan the lines by hand. I don't know what was in the Icon
book, but I'd probably just use:
procedure main(a)
separators := \a[1] | ',":<>,._+-=)(*&^%$#!@~`\'?/|\\][} {\t;'
while read(&input) ? {
tab(many(separators))
if not pos(0) then {
while write(tab(upto(separators))) do
tab(many(separators))
}
pos(0) | write(tab(0))
}
end
If you add in control characters to your separator list, and add a test
for length, you'll have something like the UNIX strings command.
Quiz time:
Why must the line "pos(0) | write(tab(0))" stand after the if..then
expression?
If you are stumped, here is a hint (don't peek):
Notice how I called "if...then" an "expression." That means it pro-
duces a result. What is that result?
If you are still stumped, here is the (or rather one) answer:
The read(&input) ? { if...then; junk } expression always succeeds,
because "junk" (i.e. "pos(0) | write(tab(0))") always succeeds. If
junk were not present, then we'd have read(&input) ? { if...then }.
If the if-condition fails, the if...then expression fails. More-
over, if it succeeds, the then { expression } is evaluated. Since
"expression" is a while loop, it will eventually fail, causing the
entire if...then expression to fail. When it fails, the read(&input)
? { etc. } expression will fail, which will cause termination of the
while construct it is part of, and ultimately termination of the
program. The upshot is that junk must be present, and must always
succeed.
I probably should have tested the above program, but I have to run. If
there are any errors, then I apologize (though I really don't see where
any could be [famous last words]).
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From belli@adt.uni-paderborn.de Fri May 17 05:31:08 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 17 May 91 05:31:08 MST
Received: from pbinfo.uni-paderborn.de by optima.cs.arizona.edu (4.1/15)
id AA23185; Fri, 17 May 91 05:30:35 MST
Received: from [131.234.128.175] by pbinfo.uni-paderborn.de with SMTP
(5.65+/PB-3.85+yp+master) id AA03987; Fri, 17 May 91 14:32:00 +0200
Received: by alpha.uni-paderborn.de
(5.61++/PB-3.41) id AA00712; Fri, 17 May 91 14:29:08 -0100
Date: Fri, 17 May 91 14:29:08 -0100
From: Fevzi Belli <belli@adt.uni-paderborn.de>
Message-Id: <9105171529.AA00712@alpha.uni-paderborn.de>
To: icon-group@cs.arizona.edu
Subject: Call for Papers IEA/AIE-92
We would like to inform you about our conference and would be
appreciated if you could also inform your colleagues about the
IEA/AIE-92. Please forward the Call for Papers to anyone who
is interested in the scope of the conference. Thank you very
much.
Bernhard Hoppe-Biermeyer
Univ. Paderborn
Arrangements & Publicity-Chair
phone: (+49) 5251 60 3283
fax : (+49) 5251 60 2519/3238
email: bernhard@adt.uni-paderborn.de
-----------------------------------------------------------------------
C A L L F O R P A P E R S
-----------------------------------------------------------------------
THE FIFTH INTERNATIONAL CONFERENCE ON INDUSTRIAL AND ENGINEERING
APPLICATIONS OF ARTIFICIAL INTELLIGENCE AND EXPERT SYSTEMS (IEA/AIE-92)
June 9-12, 1992 The University of Paderborn, Germany
Sponsored by:
Daimler-Benz AG
Dornier Deutsche Aerospace
Siemens Nixdorf Informationssysteme AG
The University of Tennessee Space Institute
Universitaet-Gesamthochschule Paderborn
In Cooperation with:
American Association for Artificial Intelligence
Association for Computing Machinery/SIGART
Canadian Society for Computational Studies of Intelligence
European Coordinating Committee for AI
Gesellschaft fuer Informatik e.V. (Germany)
IEEE Computer Society
International Society of Applied Intelligence
International Association of Knowledge Engineers
International Neural Network Society
Japanese Society of Artificial Intelligence
This conference continues its tradition of emphasizing applications of
artificial intelligence and expert/knowledge-based systems to engineering
and industrial problems. One of the specialities of the IEA/AIE-92 will
be the Industrial Program. Topics of interest include but are not
limited to:
Pattern Recognition Knowledge Representation
Neural Networks Knowledge Acquisition
Machine Learning Robotics
Model-Based & Qualitative Reasoning Machine Vision
Computer Aided Manufacturing Natural Language Processing
Computer Aided Design Reasoning Under Uncertainty
Expert & Diagnostic Systems Distributed AI Architectures
Intelligent Databases Planning/Scheduling
Intelligent Interfaces Sensor Fusion
AI In Administration & Government Intelligent Tutoring
Verifaction, Validation, Software Engineering & AI/ES
Dependability & AI/ES
Please indicate the area of submission as shwon above, and submit by
November 1, 1991 six copies of your paper (single spaced, minimum length
of 6 and maximum length of 10 pages) to the Program Chair. Authors will
be notified of the status of their manuscript by February 11, 1992. Final
copies of papers will be due for inclusion in the conference proceedings
by March 16, 1992.
Program Chair General Chair
Dr. Fevzi Belli Dr. Moonis Ali
Universitaet-GH Paderborn Computer Science Department
Postfach 1621 Univ. of Tennessee Space Inst.
4790 Paderborn Tullahoma, TN 37388
Germany USA
Tel. (+49) 5251 60-3283 Tel. (+1) 615 455-0631
E-mail: belli@adt.uni-paderborn.de E-mail: alif@utsiv1.bitnet
Fax: (+49) 5251 60-3238 Fax: (+1) 615 454-2354
General information and registration materials may be obtained from:
Alireza Azem Ms. Sandy Shankle
Univ.-GH Paderborn, FB 14 UTSI
4790 Paderborn Tullahoma, TN 37388-8897
Germany USA
The proceedings will be available at the conference. Proceedings of
earlier conferences are available -- contact: Ms. Nancy Wise at
(+1) 615 455-0631, ext. 236.
Program Co-Chairs:
Graham Forsyth, DSTO Aeronautical/Melbourne
Edward Grant, Univ. of Strathclyde
Franz-Josef Radermacher, FAW Ulm
Program Committee
Olaf Abeln, ASEA Brown-Bov./Mannheim
J. H. Andreae, Univ. of Canterbury
W. Bibel, TH Darmstadt
Gautam Biswas, Vanderbilt Univ./Nashville
Hinrich Bonin, Polytechnic Lueneburg
Ivan Bratko, Univ. of Ljubljana
Luigia Carlucci Aiello, Univ. di Roma
Thomas Christaller, GMD/St. Augustin
Paul Chung, University of Edingburgh
A. G. Cohn, University of Leeds
Alain Costes, LAAS-CNRS/Toulouse
Thore Danielsen, Norw. Telecom/Tromso
R. Freedman, Polytechnic Univ./New York
Toshio Fukuda, Nagoya University
Oliver Guenther, FAW Ulm
Uwe L. Haass, FORWISS/Erlangen
Georg Hartmann, Univ. Paderborn
K. M. van Hee, Eindhoven Univ. of Techn.
Alexander Herold/ECRC Munich
P. Jedrzejowicz, Merch. Mar. Acad./Gdynia
M. Klein, HEC GSM, Jouy-en-Josas
Jay Liebowitz, G. Washington Univ./Washington
Ramon Lopez de Mantaras, CSIC/Blanes
Bernard Moulin, Universite Laval/Quebec
Lee Naish, Univ. Melbourne
Bernd Neumann, LKI Hamburg
Setsuo Ohsuga, University of Tokyo
Dick Peacocke, BNR/Ottawa
Ivan Plander, ITCSAC/Bratislava
M. M. Richter, Univ. Kaiserslautern
Enrique Ruspini, SRI Internat./Menlo Park
Erik Sandewall, Linkoeping University
Jonathan Shapiro, The Turing Inst./Glasgow
Peter Sydenham, Univ. of South Australia
Ludger Thomas, Siemens Nixdorf/Paderborn
M. Trivedi, Univ. of Tennessee/Knoxville
Ian Witten, University of Calgary
T. Yamakawa, Kyushu Inst. of Technology
Ex-Officio
Jim Bezdek, Univ. of W. Florida/Pensacola
M. Matthews, Univ. of s. Carolina/Columbia
Proceedings Editors Tutorial Chair
F. Belli & Alfred Schmidt Oliver Guenther, FAW Ulm
Univ. Paderborn
Arrangements & Publicity Chair Industrial Program & Exhibits Chair
Bernhard Hoppe-Biermeyer Stefan Omlor, Telenorma Frankfurt
Univ. Paderborn
Registration Chair Administration Chair
Sandy Shankle, UTSI Tullahoma Alireza Azem, Univ. Paderborn
-----------------------------------------------------------------------
From icon-group-request@arizona.edu Sat May 18 07:10:11 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sat, 18 May 91 07:10:11 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA24544; Sat, 18 May 91 07:10:07 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sat, 18 May
1991 07:09 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA26823; Sat, 18 May 91
06:57:43 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sat, 18 May 1991 07:09 MST
Date: 17 May 91 18:36:46 GMT
From: agate!bionet!ucselx!usc!cs.utexas.edu!sdd.hp.com!spool.mu.edu!cs.umn.edu!msi.umn.edu!noc.MR.NET!ns!ns!dean@ucbvax.berkeley.edu (Dean C.
Gahlon)
Subject: RE: Language 'tutors'
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <67C978A7F64025A3@Arizona.edu>
Message-Id: <1991May17.183646.28895@ns.network.com>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Network Systems Corporation
References: <16.May.91..08:57:28.bst..060957@EMAS-A>
In article <16.May.91..08:57:28.bst..060957@EMAS-A> R.J.Hare@edinburgh.ac.uk writes:
>Has anyone used Icon to develop 'tutors' for learning foreign languages
>in any way - for example, vocabulary drills, simple phrase translation,
>etc.?
>
>If yes, are such programs available?
>
>Thanks.
>
>Roger Hare.
Yes, as a matter of fact. I have a couple of Japanese tutoring programs
written in Icon. They're not very fancy (and in fact don't use an incredible
number of the more advanced features of the language (i.e., I suspect that
they could be written to be better)), but they work. If I remember, I will
try to upload them to this machine and then post them on the network
sometime soon.
Dean C. Gahlon
dean@ns.network.com
From icon-group-request@arizona.edu Thu May 23 08:00:37 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 23 May 91 08:00:37 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA28264; Thu, 23 May 91 08:00:34 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 23 May
1991 08:00 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA11969; Thu, 23 May 91
07:54:41 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 23 May 1991 08:00 MST
Date: 23 May 91 00:31:56 GMT
From: mvb.saic.com!unogate!unocal!genisco!arcturus!felix!ka%felix.UUCP@ucsd.edu
(Kenneth Almquist)
Subject: RE: Algol->Icon & Pascal
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <5CAA2B07ECC00A9C@Arizona.edu>
Message-Id: <163508@felix.UUCP>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: FileNet Corp., Costa Mesa, CA
References: <1991May14.222651.16502@midway.uchicago.edu>
goer@ellis.uchicago.edu (Richard L. Goerwitz) writes:
> I've always wondered why Icon uses the brace notation (rather than
> begin ... end;) for most groupings, but yet for procedures, a kind
> of mixed procedure name(vars)...end notation is used.
My guess is that this produces better diagnostics when braces are
omitted. If you omit an open brace in C, the compiler will eventually
encounter a closing brace in the middle of the procedure which appears
to match the start of the procedure. None of the C compilers that I
have seen are capable of recognizing this situation and determining
that the procedure hasn't actually ended. Instead, they treat the
procedure as ended and squawk about every line from the closing brace
until the actual end of the procedure. Using something other than a
closing brace to mark the end of a procedure avoids this problem.
> I'm also a bit curious why the notion of functions and procedures
> was collapsed into procedures, and yet with retention of the notion
> that a procedure is a value (i.e. like what we normally associate
> with functions).
I'm not sure what you mean by a procedure being a value. Calling ICON
procedures "functions" would be a mistake because the term "function"
is defined by mathematicians to be something that returns exactly one
value. In contrast, "procedure" is defined by usage within the compu-
ter science community. In Algol and Pascal, a procedure can return
values by setting parameters, but not by returning a value using the
syntax for returning a value from a function. In PL/1 (which is more
widely used than either Algol or Pascal) this restriction was lifted
and a procedure can return a value using a "return" statement. So
ICON's use of the term "procedure" to refer to something that can
return zero or more values is a natural extension of prior practice.
Kenneth Almquist
From icon-group-request@arizona.edu Thu May 23 23:16:13 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 23 May 91 23:16:13 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA08193; Thu, 23 May 91 23:16:10 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 23 May
1991 23:15 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA09418; Thu, 23 May 91
23:08:59 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 23 May 1991 23:15 MST
Date: 24 May 91 05:12:31 GMT
From: mips!news.cs.indiana.edu!ux1.cso.uiuc.edu!midway!ellis.uchicago.edu!goer@apple.com (Richard L.
Goerwitz)
Subject: icont .el files
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <DC9272BC8CC00C3E@Arizona.edu>
Message-Id: <1991May24.051231.9618@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
I recall seeing something like a describe-icon-function.el file
some months ago. I guess I'm wondering just what has been done
in the way of Emacs utility files for Icon programmers (aside from
the icon.el file that comes with the standard distribution). If
anyone could point me in the right direction (or send some code),
I'd appreciate it very much.
Naturally, I'll summarize if there's interest.
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From uunet!men2a!aquin!luvthang!talmage Fri May 24 12:18:29 1991
Received: from univers.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 24 May 91 12:18:29 MST
Received: from uunet.UUCP by univers.cs.arizona.edu; Fri, 24 May 91 12:18:27 MST
Received: from men2a.UUCP (localhost.UU.NET) by relay1.UU.NET with SMTP
(5.61/UUNET-internet-primary) id AA14737; Fri, 24 May 91 15:03:36 -0400
Received: by men2a.ori-cal.com (smail2.5)
id AA10279; 24 May 91 15:08:22 EDT (Fri)
Received: by aquin.ORI-CAL.COM (smail2.5)
id AA07256; 24 May 91 14:56:30 EDT (Fri)
Received: by luvthang.UUCP (1.05D/Amiga)
id AA02127; Fri, 24 May 91 13:25:29 EST
Date: Fri, 24 May 91 13:25:29 EST
Message-Id: <9105241825.AA02127@luvthang.UUCP>
From: uunet!luvthang!talmage (David W. Talmage)
To: uunet!icon-group
Subject: Icon debugging tools? -REPOST-
On or about 4 May, I asked about Icon tools. I've had major mailer
problems since then, so I have no idea if my note made it out to the
icon-group or if anyone replied to it. Because I'm still
interested, I post again:
>What tools do you use to debug your Icon programs? I have a poor
>man's profiler which I use on occasion. What I'd really like is a
>symbolic debugger that works like Sun's dbxtool or like Digital's
>run-time debugger. It would be a win for me if said tools can run on
>my Amiga.
In my original posting, I included an Icon implementation of pmp, Dan
Berenstein's Poor Man's Profiler. If anyone wants it, please drop me
a line. If more than 10 people ask for it, I'll post it.
-----------------------------------------------------------------------------
David W. Talmage (talmage@luvthang.aquin.ori-cal.com)
"I need fifty dollars to make you hollar. I get paid to run this luvthang."
From icon-group-request@arizona.edu Sat May 25 03:32:43 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sat, 25 May 91 03:32:43 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA08320; Sat, 25 May 91 03:32:39 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sat, 25 May
1991 03:32 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA21070; Sat, 25 May 91
03:14:33 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sat, 25 May 1991 03:32 MST
Date: 25 May 91 09:57:43 GMT
From: munnari.oz.au!deakin.OZ.AU!rand!rdb@uunet.uu.net (Rodney Brown)
Subject: MS-DOS ICON binaries
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <C991B478ECC012B8@Arizona.edu>
Message-Id: <283@rand.mel.cocam.oz.au>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Co-Cam Computer Group, Melbourne, OZ
I have a MS-DOS Icon binary dating from 1985 distributed through PC-Blue.
Is there a more recent version available? 8086 or 80386 extended mode binaries?
I checked SIMTEL a while back & every mention of ICON seemed to be aimed
at MS Windows & GUIs.
Rodney Brown, Co-Cam Computer Group, ACSNet: rdb@rand.mel.cocam.oz.au
From icon-group-request@arizona.edu Sat May 25 23:23:29 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sat, 25 May 91 23:23:29 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA09375; Sat, 25 May 91 23:23:27 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Sat, 25 May
1991 23:22 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA17485; Sat, 25 May 91
23:18:38 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sat, 25 May 1991 23:23 MST
Date: 26 May 91 06:10:00 GMT
From: andrew@arizona.edu (Andrei V. Zaitsev)
Subject: Comments in ICON
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <6FE990FA6CC01339@Arizona.edu>
Message-Id: <1537@caslon.cs.arizona.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: U of Arizona CS Dept, Tucson
Here is an extremely simple question : how
to put a comment into a ICON program ?
(I tried /**/,(**),REM and * , none of them works).
From isidev!nowlin@uunet.uu.net Sun May 26 10:55:10 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 26 May 91 10:55:10 MST
Received: from relay1.UU.NET by optima.cs.arizona.edu (4.1/15)
id AA25285; Sun, 26 May 91 10:55:08 MST
Received: from isidev.UUCP (LOCALHOST.UU.NET) by relay1.UU.NET with SMTP
(5.61/UUNET-internet-primary) id AA07484; Sun, 26 May 91 13:55:06 -0400
Date: Sun, 26 May 91 13:55:06 -0400
From: isidev!nowlin@uunet.uu.net
Message-Id: <9105261755.AA07484@relay1.UU.NET>
To: uunet!cs.arizona.edu!icon-group@uunet.uu.net
Subject: Re: icon comments
> Date: 26 May 91 06:10:00 GMT
> From: uunet!arizona!arizona.edu!andrew (Andrei V. Zaitsev)
>
> Here is an extremely simple question : how
> to put a comment into a ICON program ?
> (I tried /**/,(**),REM and * , none of them works).
You must be young since you still have stars in your eyes. Think pound
signs instead. Examples follow:
procedure main()
write(&clock) # print the current time
write(&date) # print the current date
# print more information on the time and date
write(&dateline)
end
At least you're thinking about comments!
--- ---
| S | Iconic Software, Inc. - Jerry Nowlin - uunet!isidev!nowlin
--- ---
From TENAGLIA@mis.mcw.edu Tue May 28 06:42:52 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 28 May 91 06:42:52 MST
Received: from MIS1.MIS.MCW.EDU by optima.cs.arizona.edu (4.1/15)
id AA02919; Tue, 28 May 91 06:42:46 MST
Received: from mis.mcw.edu (MCWMI3) by MIS1.MIS.MCW.EDU with PMDF#10477; Tue,
28 May 1991 08:42 CST
Date: Tue, 28 May 1991 08:42 CST
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Holiday TidBit
To: icon-group@cs.arizona.edu
Message-Id: <50632F0EE04001B8@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Another holiday has passed, and with it came another icon game. This is
Yahtzee, the poker dice game. I use ICON 8 under VMS 5.4-1, but I tried
to avoid system specific stuff. I'll probably get flamed again for my
screen management methods (I tried a little something different.) It's
written for VT100,2XX,3XX,4XX and compatible terminals, since that's all
I have at this site. Bye the way, this version allows for multiple players.
I've played it several times with my daughter and it seems pretty solid.
Game design involves many tricky decisions. The two in this implementation
were..
o Not to repaint dice if the value stayed the same
This is seen in procedure depict(). I use a list
'od' to remember former values. Then when choosen
dice are shaken, the unshaken ones stay put. But,
so do the ones that come up the same. Oh well.
o To give the player the feel of the three shakes,
I provide a prompt saying whose turn it is, and
asking them to press <RETURN>. These lines can be
found at the beginning of procedure play(name).
I also ask them to press return after their turn
is over in order to allow some time to read their
scorecard and think about future strategy.
So here's the code. Enjoy!
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
#
# YAHT.ICN 5/27/91 BY TENAGLIA
#
# YAHTZEE GAME
#
global players,slot,team,d,od,dice,round
procedure main(param)
paint()
assign_players()
every round := 1 to 13 do
every play(!team)
summarize()
end
#
# DISPLAYS THE HEADER AND SEPARATOR LINE AT BEGINNING OF GAME
#
procedure paint()
write(cls(),high(uhalf(" Y A H T Z E E ")))
write(high(lhalf(" Y A H T Z E E ")))
write(at(1,10),graf(repl("q",75)))
end
#
# DISPLAYS THE FINAL SCORE OF ALL THE PLAYERS
#
procedure summarize()
write(at(1,11),blink(high(inverse(chop("Final Score Summary")))))
every player := key(players) do
{
card := players[player]
top := 0 ; every i := 1 to 6 do top +:= card[i]
if top > 62 then top +:= 35
bottom := 0 ; every i := 7 to 13 do bottom +:= card[i]
write("Player ",high(left(player,14))," Top = ",right(top,5),
" Bottom = ",right(bottom,5),
" Total = ",right(top+bottom,5))
}
input("<press return>")
end
#
# SETUP AND INITIALIZATION OF YAHTZEE ENVIRONMENT
#
procedure assign_players()
n := 1 ; team := [] ; slot := [] ; d := list(6,"") ; od := list(5,0)
&random := map(&clock,":","9")
players := table("n/a")
repeat
{
(player := input(("Name of player #" || n || ":"))) | stop("Game called off.")
if player == "" then break
n +:= 1
put(team,player)
players[player] := list(13,"*")
}
if n = 1 then stop("Nobody wants to play!")
put(slot,"Ones") ; put(slot,"Twos") ; put(slot,"Threes")
put(slot,"Fours") ; put(slot,"Fives") ; put(slot,"Sixes")
put(slot,"3oK") ; put(slot,"4oK") ; put(slot,"FullH")
put(slot,"SmStr") ; put(slot,"LgStr") ; put(slot,"Yahtzee")
put(slot,"Chance")
d[1] := "lqqqqqkx xx ` xx xmqqqqqj"
d[2] := "lqqqqqkx xx ` ` xx xmqqqqqj"
d[3] := "lqqqqqkx` xx ` xx `xmqqqqqj"
d[4] := "lqqqqqkx` `xx xx` `xmqqqqqj"
d[5] := "lqqqqqkx` `xx ` xx` `xmqqqqqj"
d[6] := "lqqqqqkx` ` `xx xx` ` `xmqqqqqj"
end
#
# THIS ROUTINE LETS A PLAYER TAKE THEIR TURN
#
procedure play(name)
writes(at(1,11),"It's ",high(name),"'s turn",chop())
writes(at(1,12),high(name)) ; input(", Please press <RETURN> to begin.")
score(name)
dice := [] ; every 1 to 5 do put(dice,?6)
depict()
shake := obtain("Shake which ones :")
(shake === []) | (every dice[!shake] := ?6)
depict()
shake := obtain("(Last Chance) Shake which ones :")
(shake === []) | (every dice[!shake] := ?6)
depict()
repeat
{
select := input(at(1,22) || clip("Tally to which category (1 -> 13) :"))
numeric(select) | next
(1 <= select <= 13) | next
(players[name][select] == "*") | next
break
}
tally(name,select)
score(name)
input(at(1,22) || clip("Press <RETURN>"))
end
#
# THIS ROUTINE DRAWS THE DICE
#
procedure depict()
every i := 1 to 5 do
{
if od[i] = dice[i] then next
x := 1
writes(at(i*10+4,3),inverse(i))
# writes(at(i*10+4,9),inverse(dice[i]))
every j := 4 to 8 do
{
writes(at(i*10,j),graf(d[dice[i]][x:x+7]))
x +:= 7
}
od[i] := dice[i]
}
end
#
# THIS ROUTINE LETS THE PLAYER DECIDE WHAT TO APPLY THE SHAKES TO
#
procedure tally(name,area)
case integer(area) of
{
1 : { # ones
sum := 0 ; every unit := !dice do if unit = 1 then sum +:= 1
players[name][1] := sum
}
2 : { # twos
sum := 0 ; every unit := !dice do if unit = 2 then sum +:= 2
players[name][2] := sum
}
3 : { # threes
sum := 0 ; every unit := !dice do if unit = 3 then sum +:= 3
players[name][3] := sum
}
4 : { # fours
sum := 0 ; every unit := !dice do if unit = 4 then sum +:= 4
players[name][4] := sum
}
5 : { # fives
sum := 0 ; every unit := !dice do if unit = 5 then sum +:= 5
players[name][5] := sum
}
6 : { # sixes
sum := 0 ; every unit := !dice do if unit = 6 then sum +:= 6
players[name][6] := sum
}
7 : { # 3 of a kind
sum := 0 ; flag := 0
tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
every piece := key(tmp) do
if tmp[piece] >= 3 then flag := 1
if flag = 1 then every sum +:= !dice
players[name][7] := sum
}
8 : { # four of a kind
sum := 0 ; flag := 0
tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
every piece := key(tmp) do
if tmp[piece] >= 4 then flag := 1
if flag = 1 then every sum +:= !dice
players[name][8] := sum
}
9 : { # full house
sum := 0 ; flag := 0
tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
every piece := key(tmp) do
{
if tmp[piece] = 3 then flag +:= 1
if tmp[piece] = 2 then flag +:= 1
}
if flag = 2 then sum := 25
players[name][9] := sum
}
10 : { # small straight
sum := 0 ; flag := 0
hold := set() ; every insert(hold,!dice)
tmp := sort(hold)
if tmp[1]+1 = tmp[2] &
tmp[2]+1 = tmp[3] &
tmp[3]+1 = tmp[4] then flag := 1
if tmp[2]+1 = tmp[3] &
tmp[3]+1 = tmp[4] &
tmp[4]+1 = tmp[5] then flag := 1
if flag = 1 then sum := 30
players[name][10] := sum
}
11 : { # large straight
sum := 0 ; flag := 0
tmp := sort(dice)
if tmp[1]+1 = tmp[2] &
tmp[2]+1 = tmp[3] &
tmp[3]+1 = tmp[4] &
tmp[4]+1 = tmp[5] then flag := 1
if flag = 1 then sum := 40
players[name][11] := sum
}
12 : { # yahtzee
sum := 0 ; flag := 0
tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
every piece := key(tmp) do
if tmp[piece] = 5 then flag := 1
if flag = 1 then sum := 50
players[name][12] := sum
}
13 : { # chance
sum := 0 ; every sum +:= !dice
players[name][13] := sum
}
}
end
#
# THIS ROUTINE OBTAINS A VALID SHAKER REQUEST
#
procedure obtain(prompt)
repeat
{
writes(at(1,22),prompt)
(line := read()) | next
if match("q",map(line)) then stop("Game Quit")
if trim(line) == "" then return []
units := parse(line,', \t')
every unit := !units do
(1 <= unit <= 5) | next
break
}
return units
end
#
# THIS ROUTINE PAINTS THE SCORECARD FOR A GIVEN PLAYER
#
procedure score(name)
writes(at(1,11),chop(),at(25,11),under(),"Player = ",name," Round = ",under(round))
writes(at(10,12)," 1 : Ones = ",players[name][1])
writes(at(10,13)," 2 : Twos = ",players[name][2])
writes(at(10,14)," 3 : Threes = ",players[name][3])
writes(at(10,15)," 4 : Fours = ",players[name][4])
writes(at(10,16)," 5 : Fives = ",players[name][5])
writes(at(10,17)," 6 : Sixes = ",players[name][6])
writes(at(40,12)," 7 : 3oK = ",players[name][7])
writes(at(40,13)," 8 : 4oK = ",players[name][8])
writes(at(40,14)," 9 : FullH = ",players[name][9])
writes(at(40,15),"10 : SmStr = ",players[name][10])
writes(at(40,16),"11 : LgStr = ",players[name][11])
writes(at(40,17),"12 : Yahtzee = ",players[name][12])
writes(at(40,18),"13 : Chance = ",players[name][13])
st1 := 0 ; every i := 1 to 6 do st1 +:= numeric(players[name][i])
if st1 > 62 then bonus := 35 else bonus := 0
st2 := 0 ; every i := 7 to 13 do st2 +:= numeric(players[name][i])
writes(at(10,19),"Bonus = ",clip(bonus))
writes(at(10,20),"Subtotal = ",st1+bonus)
writes(at(40,20),"Subtotal = ",st2)
writes(at(37,21),"Grand Total = ",st1+st2+bonus)
end
#
# VIDEO ROUTINE CLEARS SCREEN
#
procedure cls(str)
/str := ""
return "\e[2J\e[H" || str
end
#
# VIDEO ROUTINE ERASES REST OF SCREEN
#
procedure chop(str)
/str := ""
return "\e[J" || str
end
#
# VIDEO ROUTINE OUTPUTS UPPER HALF OF DOUBLE SIZE MESSAGES
#
procedure uhalf(str)
/str := ""
if str == "" then return "\e#3"
return "\e#3" || str
end
#
# VIDEO ROUTINE OUTPUTS BOTTOM HALF OF DOUBLE SIZE MESSAGES
#
procedure lhalf(str)
/str := ""
if str == "" then return "\e#4"
return "\e#4" || str
end
#
# VIDEO ROUTINE OUTPUTS STRING AND CLEARS TO EOL
#
procedure clip(str)
/str := ""
if str == "" then return "\e[K "
return str ||:= "\e[K"
end
#
# VIDEO ROUTINE OUTPUTS HIGHLIGHTED STRINGS
#
procedure high(str)
/str := ""
if str == "" then return "\e[1m"
str := "\e[1m" || str
if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m")
then return str
else return str || "\e[m"
end
#
# VIDEO ROUTINE OUTPUTS INVERSE VIDEO STRINGS
#
procedure inverse(str)
/str := ""
if str == "" then return "\e[7m"
str := "\e[7m" || str
if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m")
then return str
else return str || "\e[m"
end
#
# VIDEO ROUTINE OUTPUTS UNDERLINED STRINGS
#
procedure under(str)
/str := ""
if str == "" then return "\e[4m"
str := "\e[4m" || str
if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m")
then return str
else return str || "\e[m"
end
#
# VIDEO ROUTINE OUTPUTS BLINKING STRINGS
#
procedure blink(str)
/str := ""
if str == "" then return "\e[5m"
str := "\e[5m" || str
if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m")
then return str
else return str || "\e[m"
end
#
# VIDEO ROUTINE SETS NORMAL VIDEO MODE
#
procedure norm(str)
/str := ""
if str == "" then return "\e[m"
str := "\e[m" || str
return str
end
#
# VIDEO ROUTINE TURNS ON VT GRAPHICS CHARACTERS
#
procedure graf(str)
/str := ""
if str == "" then return "\e(0"
str := "\e(0" || str
if (str[-3:0] == "\e(B")
then return str
else return str || "\e(B"
end
#
# VIDEO ROUTINE TURNS OFF VT GRAPHICS CHARACTERS
#
procedure nograf(str)
/str := ""
if str == "" then return "\e(B"
str := "\e(B" || str
return str
end
#
# VIDEO ROUTINE SETS CURSOR TO GIVEN X,Y COORDINATES
#
procedure at(x,y)
return "\e[" || y || ";" || x || "f"
end
#
# PARSES A STRING INTO A LIST WITH RESPECT TO A GIVEN DELIMITER
#
procedure parse(line,delims)
static chars
chars := &cset -- delims
tokens := []
line ? while tab(upto(chars)) do put(tokens,tab(many(chars)))
return tokens
end
#
# TAKE AN INPUT STRING VIA GIVEN PROMPT
#
procedure input(prompt)
writes(prompt)
return read()
end
#
# DISCLAIMER
#
#########################################################################
# #
# Copyright (c) 1991, Chris D. Tenaglia # 12p #
# #
# This software is intended for free and unrestricted distribution. #
# I place only two conditions on its use: 1) That you clearly mark #
# any additions or changes you make to the source code, and 2) that #
# you do not delete this message therefrom. In order to protect #
# myself from spurious litigation, it must also be stated here that, #
# because this is free software, I, Chris tenaglia, make no claim #
# about the applicability or fitness of this software for any #
# purpose, and expressly disclaim any responsibility for any damages #
# that might be incurred in conjunction with its use. #
# #
#########################################################################
From icon-group-request@arizona.edu Tue May 28 07:35:18 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 28 May 91 07:35:18 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA04097; Tue, 28 May 91 07:35:15 MST
Received: from ucbvax.Berkeley.EDU (128.32.133.1) by Arizona.edu with
PMDF#10282; Tue, 28 May 1991 03:48 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA13404; Tue, 28 May 91
03:22:47 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 28 May 1991 03:48 MST
Date: 28 May 91 07:46:01 GMT
From: cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!midway!ellis.uchicago.edu!goer@tut.cis.ohio-state.edu (Richard L.
Goerwitz)
Subject: list scanning routines
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <274E1C38BCC01BB5@Arizona.edu>
Message-Id: <1991May28.074601.23950@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
############################################################################
#
# Name: lscan.icn
#
# Title: Quasi ? scanning routines for lists.
#
# Author: Richard L. Goerwitz
#
# Version: 1.20
#
############################################################################
#
# PURPOSE: String scanning is terrific, but often I am forced to
# tokenize and work with lists. So as to make operations on these
# lists as close to corresponding string operations as possible, I've
# implemented a series of list analogues to any(), bal(), find(),
# many(), match(), move(), pos(), tab(), and upto(). Their names are
# just like corresponding string functions, except with a prepended
# "l_" (e.g. l_any()). Functionally, the list routines parallel the
# string ones closely, except that in place of strings, l_find and
# l_match accept lists as their first argument. L_any(), l_many(),
# and l_upto() all take either sets of lists or lists of lists (e.g.
# l_tab(l_upto([["a"],["b"],["j","u","n","k"]])). Note that l_bal(),
# unlike the builtin bal(), has no defaults for the first four
# arguments. This just seemed appropriate, given that no precise
# list analogue to &cset, etc. occurs.
#
# The default subject for list scans (analogous to &subject) is
# l_SUBJ. The equivalent of &pos is l_POS. Naturally, these
# variables are both global. They are used pretty much like &subject
# and &pos, except that they are null until a list scanning
# expression has been encountered containing a call to l_Bscan() (on
# which, see below).
#
# Note that environments cannot be maintained quite as elegantly as
# they can be for the builtin string-scanning functions. One must
# use instead a set of nested procedure calls, as explained in the
# _Icon Analyst_ 1:6 (June, 1991), p. 1-2. In particular, one cannot
# suspend, return, or otherwise break out of the nested procedure
# calls. They can only be exited via failure. The names of these
# procedures, at least in this implementation, are l_Escan and
# l_Bscan. Here is one example of how they might be invoked:
#
# suspend l_Escan(l_Bscan(some_list_or_other), {
# l_tab(10 to *l_SUBJ) & {
# if l_any(l1) | l_match(l2) then
# old_l_POS + (l_POS-1)
# }
# })
#
# Note that you cannot do this:
#
# l_Escan(l_Bscan(some_list_or_other), {
# l_tab(10 to *l_SUBJ) & {
# if l_any(l1) | l_match(l2) then
# suspend old_l_POS + (l_POS-1)
# }
# })
#
# Remember, it's no fair to use suspend within the list scanning
# expression. l_Escan must do all the suspending. It is perfectly OK,
# though, to nest well-behaved list scanning expressions. And they can
# be reliably used to generate a series of results as well.
#
############################################################################
#
# Here's another simple example of how one might invoke the l_scan
# routines:
#
# procedure main()
#
# l := ["h","e","l","l","o"," ","t","t","t","h","e","r","e"]
#
# l_Escan(l_Bscan(l), {
# hello_list := l_tab(l_match(["h","e","l","l","o"]))
# every writes(!hello_list)
# write()
#
# # Note the nested list-scanning expressions.
# l_Escan(l_Bscan(l_tab(0)), {
# l_tab(l_many([[" "],["t"]]) - 1)
# every writes(!l_tab(0))
# write()
# })
# })
#
# end
#
# The above program simply writes "hello" and "there" on successive
# lines to the standard output.
#
############################################################################
#
# PITFALLS: In general, note that we are comparing lists here instead
# of strings, so l_find("h", l), for instance, will yield an error
# message (use l_find(["h"], l) instead). The point at which I
# expect this nuance will be most confusing will be in cases where
# one is looking for lists within lists. Suppose we have a list,
#
# l1 := ["junk",[["hello"]," ",["there"]],"!","m","o","r","e","junk"]
#
# and suppose, moreover, that we wish to find the position in l1 at
# which the list
#
# [["hello"]," ",["there"]]
#
# occurs. If, say, we assign [["hello"]," ",["there"]] to the
# variable l2, then our l_find() expression will need to look like
#
# l_find([l2],l1)
#
############################################################################
#
# Extending scanning to lists is really very difficult. What I think
# (at least tonight) is that scanning should never have been
# restricted to strings. It should have been designed to operate on
# all homogenous one-dimensional arrays (vectors, for you LISPers).
# You should be able, in other words, to scan vectors of ints, longs,
# characters - any data type that seems useful. The only question in
# my mind is how to represent vectors as literals. Extending scanning
# to lists goes beyond the bounds of scanning per-se. This library is
# therefore something of a stab in the dark.
#
############################################################################
global l_POS
global l_SUBJ
record l_ScanEnvir(subject,pos)
procedure l_Bscan(e1)
#
# Prototype list scan initializer. Based on code published in
# the _Icon Analyst_ 1:6 (June, 1991), p. 1-2.
#
local l_OuterEnvir
initial {
l_SUBJ := []
l_POS := 1
}
#
# Save outer scanning environment.
#
l_OuterEnvir := l_ScanEnvir(l_SUBJ, l_POS)
#
# Set current scanning environment to subject e1 (arg 1). Pos
# defaults to 1. Suspend the saved environment. Later on, the
# l_Escan procedure will need this in case the scanning expres-
# sion as a whole sends a result back to the outer environment,
# and the outer environment changes l_SUBJ and l_POS.
#
l_SUBJ := e1
l_POS := 1
suspend l_OuterEnvir
#
# Restore the saved environment (plus any changes that might have
# been made to it as noted in the previous run of comments).
#
l_SUBJ := l_OuterEnvir.subject
l_POS := l_OuterEnvir.pos
#
# Signal failure of the scanning expression (we're done producing
# results if we get to here).
#
fail
end
procedure l_Escan(l_OuterEnvir, e2)
local l_InnerEnvir
#
# Set the inner scanning environment to the values assigned to it
# by l_Bscan. Remember that l_SUBJ and l_POS are global. They
# don't need to be passed as parameters from l_Bscan. What
# l_Bscan() needs to pass on is the l_OuterEnvir record,
# containing the values of l_SUBJ and l_POS before l_Bscan() was
# called. l_Escan receives this "outer environment" as its first
# argument, l_OuterEnvir.
#
l_InnerEnvir := l_ScanEnvir(l_SUBJ, l_POS)
#
# Whatever expression produced e2 has passed us a result. Now we
# restore l_SUBJ and l_POS, and send that result back to the outer
# environment.
#
l_SUBJ := l_OuterEnvir.subject
l_POS := l_OuterEnvir.pos
suspend e2
#
# Okay, we've resumed to (attempt to) produce another result. Re-
# store the inner scanning environment (the one we're using in the
# current scanning expression). Remember? It was saved in l_Inner-
# Envir just above.
#
l_SUBJ := l_InnerEnvir.subject
l_POS := l_InnerEnvir.pos
#
# Fail so that the second argument (the one that produced e2) gets
# resumed. If it fails to produce another result, then the first
# argument is resumed, which is l_Bscan(). If l_Bscan is resumed, it
# will restore the outer environment and fail, causing the entire
# scanning expression to fail.
#
fail
end
procedure l_move(i)
/i & stop("l_move: Null argument.")
if /l_POS | /l_SUBJ then
stop("l_move: Call l_Bscan() first.")
#
# Sets l_POS to l_POS+i; suspends that portion of l_SUBJ extending
# from the old l_POS to the new one. Resets l_POS if resumed,
# just the way matching procedures are supposed to. Fails if l_POS
# plus i is larger than l_SUBJ+1 or if l_POS+i is less than 1.
#
suspend l_SUBJ[.l_POS:l_POS <- (0 < (*l_SUBJ+1 >= l_POS+i))]
end
procedure l_tab(i)
/i & stop("l_tab: Null argument.")
if /l_POS | /l_SUBJ then
stop("l_tab: Call l_Bscan() first.")
if i <= 0
then suspend l_SUBJ[.l_POS:l_POS <- 0 < (*l_SUBJ+1 >= (*l_SUBJ+1)+i)]
else suspend l_SUBJ[.l_POS:l_POS <- 0 < (*l_SUBJ+1 >= i)]
end
procedure l_any(l1,l2,i,j)
#
# Like any(c,s2,i,j) except that the string & cset arguments are
# replaced by list arguments. l1 must be a list of one-element
# lists, while l2 can be any list (l_SUBJ by default).
#
local sub_l
/l1 & stop("l_any: Null first argument!")
if type(l1) == "set" then l1 := sort(l1)
/l2 := l_SUBJ
if \i then {
if i < 1 then
i := *l2 + (i+1)
}
else i := \l_POS | 1
if \j then {
if j < 1 then
j := *l2 + (j+1)
}
else j := *l_SUBJ+1
(i+1) > j & i :=: j
every sub_l := !l1 do {
if not (type(sub_l) == "list", *sub_l = 1) then
stop("l_any: Elements of l1 must be lists of length 1.")
# Let l_match check to see if i+1 is out of range.
if x := l_match(sub_l,l2,i,i+1) then
return x
}
end
procedure l_match(l1,l2,i,j)
#
# Analogous to match(s1,s2,i,j), except that s1 and s2 are lists,
# and l_match returns the next position in l2 after that portion
# (if any) which is structurally identical to l1. If a match is not
# found, l_match fails.
#
if /l1
then stop("l_match: Null first argument!")
if type(l1) ~== "list"
then stop("l_match: Call me with a list as the first arg.")
/l2 := l_SUBJ
if \i then {
if i < 1 then
i := *l2 + (i+1)
}
else i := \l_POS | 1
if \j then {
if j < 1 then
j := *l2 + (j+1)
}
else j := *l_SUBJ+1
i + *l1 > j & i :=: j
i + *l1 > j & fail
if l_comp(l1,l2[i+:*l1]) then
return i + *l1
end
procedure l_comp(l1,l2)
#
# List comparison routine basically taken from Griswold & Griswold
# (1st ed.), p. 174.
#
local i
/l1 | /l2 & stop("l_comp: Null argument!")
l1 === l2 & (return l2)
if type(l1) == type(l2) == "list" then {
*l1 ~= *l2 & fail
every i := 1 to *l1
do l_comp(l1[i],l2[i]) | fail
return l2
}
end
procedure l_find(l1,l2,i,j)
#
# Like the builtin find(s1,s2,i,j), but for lists.
#
local x
/l1 & stop("l_find: Null first argument!")
/l2 := l_SUBJ
if \i then {
if i < 1 then
i := *l2 + (i+1)
}
else i := \l_POS | 1
if \j then {
if j < 1 then
j := *l2 + (j+1)
}
else j := *l_SUBJ+1
#
# See l_upto() below for a discussion of why things have to be done
# in this manner.
#
old_l_POS := l_POS
suspend l_Escan(l_Bscan(l2[i:j]), {
l_tab(1 to *l_SUBJ) & {
if l_match(l1) then
old_l_POS + (l_POS-1)
}
})
end
procedure l_upto(l1,l2,i,j)
#
# See l_any() above. This procedure just moves through l2, calling
# l_any() for each member of l2[i:j].
#
local old_l_POS
/l1 & stop("l_upto: Null first argument!")
if type(l1) == "set" then l1 := sort(l1)
/l2 := l_SUBJ
if \i then {
if i < 1 then
i := *l2 + (i+1)
}
else i := \l_POS | 1
if \j then {
if j < 1 then
j := *l2 + (j+1)
}
else j := *l_SUBJ+1
#
# Save the old pos, then try arb()ing through the list to see if we
# can do an l_any(l1) at any position.
#
old_l_POS := l_POS
suspend l_Escan(l_Bscan(l2[i:j]), {
l_tab(1 to *l_SUBJ) & {
if l_any(l1) then
old_l_POS + (l_POS-1)
}
})
#
# Note that it WILL NOT WORK if you say:
#
# l_Escan(l_Bscan(l2[i:j]), {
# l_tab(1 to *l_SUBJ) & {
# if l_any(l1) then
# suspend old_l_POS + (l_POS-1)
# }
# })
#
# If we are to suspend a result, l_Escan must suspend that result.
# Otherwise scanning environments are not saved and/or restored
# properly.
#
end
procedure l_many(l1,l2,i,j)
local x, old_l_POS
/l1 & stop("l_many: Null first argument!")
if type(l1) == "set" then l1 := sort(l1)
/l2 := l_SUBJ
if \i then {
if i < 1 then
i := *l2 + (i+1)
}
else i := \l_POS | 1
if \j then {
if j < 1 then
j := *l2 + (j+1)
}
else j := *l_SUBJ+1
#
# L_many(), like many(), is not a generator. We can therefore
# save one final result in x, and then later return (rather than
# suspend) that result.
#
old_l_POS := l_POS
l_Escan(l_Bscan(l2[i:j]), {
while l_tab(l_any(l1))
x := old_l_POS + (l_POS-1)
})
#
# Fails if there was no positional change (i.e. l_any() did not
# succeed even once).
#
return old_l_POS ~= x
end
procedure l_pos(i)
local x
if /l_POS | /l_SUBJ
then stop("l_move: Call l_Bscan() first.")
if i <= 0
then x := 0 < (*l_SUBJ+1 >= (*l_SUBJ+1)+i) | fail
else x := 0 < (*l_SUBJ+1 >= i) | fail
if x = l_POS
then return x
else fail
end
procedure l_bal(l1,l2,l3,l,i,j)
local l2_count, l3_count, x, position
/l1 & stop("l_bal: Null first argument!")
if type(l1) == "set" then l1 := sort(l1) # convert to a list
if type(l2) == "set" then l1 := sort(l2)
if type(l3) == "set" then l1 := sort(l3)
/l2 := l_SUBJ
if \i then {
if i < 1 then
i := *l2 + (i+1)
}
else i := \l_POS | 1
if \j then {
if j < 1 then
j := *l2 + (j+1)
}
else j := *l_SUBJ+1
l2_count := l3_count := 0
every x := i to j-1 do {
if l_any(l2, l, x, x+1) then {
l2_count +:= 1
}
if l_any(l3, l, x, x+1) then {
l3_count +:= 1
}
if l2_count = l3_count then {
if l_any(l1,l,x,x+1)
then suspend x
}
}
end
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From R.J.Hare@edinburgh.ac.uk Tue May 28 10:03:39 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 28 May 91 10:03:39 MST
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA15448; Tue, 28 May 91 10:03:35 MST
Received: from UKACRL.BITNET (MAILER@UKACRL) by Arizona.edu with PMDF#10282;
Tue, 28 May 1991 10:03 MST
Received: from RL.IB by UKACRL.BITNET (Mailer R2.07) with BSMTP id 5763; Tue,
28 May 91 17:32:02 BST
Received: from RL.IB by UK.AC.RL.IB (Mailer R2.07) with BSMTP id 6741; Tue, 28
May 91 17:32:02 BST
Date: 28 May 91 17:32:28 bst
From: R.J.Hare@edinburgh.ac.uk
Subject: Records
To: icon-group@cs.arizona.edu
Message-Id: <28 May 91 17:32:28 bst 060196@EMAS-A>
X-Envelope-To: icon-group@cs.arizona.edu
Via: UK.AC.ED.EMAS-A; 28 MAY 91 17:31:57 BST
I'm just about to start writing my first program which uses records.
Question, can I write a record straight to a file without separating the
fields - like this:
record line(a,b,c,d)
procedure(main)
.
.
output_line:=line(w,x,y,z)
write(file,output_line)
.
.
or do I have to do it a field at a time:
.
every i := 1 to 4 do write(file,output_line[i])
.
Any advice appreciated.
Thanks.
Roger Hare.
From ralph Tue May 28 10:07:54 1991
Date: Tue, 28 May 91 10:07:54 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9105281707.AA08271@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Tue, 28 May 91 10:07:54 MST
To: R.J.Hare@edinburgh.ac.uk
Subject: Re: Records
Cc: icon-group
You have to write each field separatey. However, you can generate the
fields of a record. E.g., if x is a record,
every write(!x)
writes all the fields of x, one per line.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From gmt Tue May 28 10:27:02 1991
Received: from owl.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 28 May 91 10:27:02 MST
Date: Tue, 28 May 91 10:27:00 MST
From: "Gregg Townsend" <gmt>
Message-Id: <9105281727.AA22946@owl.cs.arizona.edu>
Received: by owl.cs.arizona.edu; Tue, 28 May 91 10:27:00 MST
To: icon-group
Subject: Re: Records
To write the record as a single line I would do this:
every writes (!output_line | "\n")
Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
+1 602 621 4325 gmt@cs.arizona.edu 110 57 16 W / 32 13 45 N / +758m
From icon-group-request@arizona.edu Tue May 28 21:12:26 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 28 May 91 21:12:26 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA04640; Tue, 28 May 91 21:12:24 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Tue, 28 May
1991 21:11 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA25558; Tue, 28 May 91
21:05:29 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 28 May 1991 21:12 MST
Date: 29 May 91 04:00:11 GMT
From: cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!midway!ellis.uchicago.edu!goer@ucbvax.berkeley.edu (Richard L.
Goerwitz)
Subject: RE: Holiday TidBit
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <B91A8B4E56C00210@Arizona.edu>
Message-Id: <1991May29.040011.2409@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <50632F0EE04001B8@mis.mcw.edu>
If anyone wants a Unix version of Chris Tenaglia's yahtzee game (will
probably work for DOS, too), please let me know. If I get more than
a few requests, I'll post it.
-Richard
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From icon-group-request@arizona.edu Wed May 29 08:14:10 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 29 May 91 08:14:10 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA24922; Wed, 29 May 91 08:14:04 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 29 May
1991 08:12 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA09005; Wed, 29 May 91
07:53:42 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 29 May 1991 08:13 MST
Date: 29 May 91 14:56:04 GMT
From: cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!midway!ellis.uchicago.edu!goer@ucbvax.berkeley.edu (Richard L.
Goerwitz)
Subject: RE: Holiday TidBit, part 1 of 3 of Unix port
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <1586849566C00422@Arizona.edu>
Message-Id: <1991May29.145604.4017@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <50632F0EE04001B8@mis.mcw.edu>,
<1991May29.040011.2409@midway.uchicago.edu>
I logged in this morning, and had six requests for the game. I suspect
I'll get more, so let me just post the Unix (test!) port of Chris Tenaglia's
yahtzee game. It's been tested by me alone, and this only on ansi terminals.
I believe it will work, though, on just about any non-cookie terminal that
has cd capability. Part 1 follows. Parts 2 & 3 come in separate mailings.
Please let me know about bugs.
---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 05/29/1991 05:23 UTC by goer@sophist.uchicago.edu
# Source directory /u/richard/Yahtz
#
# existing files will NOT be overwritten unless -c is specified
# This format requires very little intelligence at unshar time.
# "if test", "cat", "rm", "echo", "true", and "sed" may be needed.
#
# This is part 1 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 15750 -r--r--r-- yahtz.icn
# 17272 -r--r--r-- iolib.icn
# 2391 -r--r--r-- termcap.dos
# 994 -rw-r--r-- Makefile.dist
# 1194 -rw-r--r-- README
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= yahtz.icn ==============
if test -f 'yahtz.icn' -a X"$1" != X"-c"; then
echo 'x - skipping yahtz.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting yahtz.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'yahtz.icn' &&
X############################################################################
X#
X# Name: yahtz.icn
X#
X# Title: yahtz (alias yahtzee, without a naming conflict)
X#
X# Author: Chris Tenaglia, modified by Richard Goerwitz
X#
X# Version: 1.3 (beta!)
X#
X#########################################################################
X#
X# Copyright (c) 1991, Chris D. Tenaglia # 12p
X#
X# This software is intended for free and unrestricted distribution.
X# I place only two conditions on its use: 1) That you clearly mark
X# any additions or changes you make to the source code, and 2) that
X# you do not delete this message therefrom. In order to protect
X# myself from spurious litigation, it must also be stated here that,
X# because this is free software, I, Chris tenaglia, make no claim
X# about the applicability or fitness of this software for any
X# purpose, and expressly disclaim any responsibility for any damages
X# that might be incurred in conjunction with its use.
X#
X#########################################################################
X#
X# This hacked version will run under UNIX, and under DOS as well. It
X# should run out of the box on DOS as long as you stay in the current
X# directory. See the README file.
X#
X# This is a test version!! In accordance with the author's wishes,
X# I'd like to make it clear that I've altered all the screen I/O
X# routines, and have removed characters peculiar to VT terminals.
X# I've tried to keep intact the author's indentation and brace style.
X# Changes, where present, have been indicated by my initials. The
X# IPL-style header was added by me. I also moved Chris's copyright
X# notice to the top of the document. It seems to me that such no-
X# tices have to be prominently displayed in order to be considered
X# valid.
X#
X# -Richard Goerwitz.
X#
X############################################################################
X
X
Xglobal players,slot,team,d,od,dice,round
Xprocedure main(param)
X paint()
X assign_players()
X every round := 1 to 13 do
X every play(!team)
X summarize()
X end
X
X#
X# DISPLAYS THE HEADER AND SEPARATOR LINE AT BEGINNING OF GAME
X#
Xprocedure paint()
X # Clear first, separately. Screws up on some terminals of you don't.
X writes(cls())
X # Check to be sure the terminal is big enough, and won't leave magic
X # cookies on the screen. -RLG
X if getval("ug"|"sg") > 0
X then stop("abort: Can't do magic cookie terminals!")
X if getval("li") < 24 | getval("co") < 80 then
X stop("abort: Your terminal is too small!")
X write(high(uhalf(" Y A H T Z E E ")))
X write(high(lhalf(" Y A H T Z E E ")))
X write(at(1,10),graf(repl("=",75)))
X end
X
X#
X# DISPLAYS THE FINAL SCORE OF ALL THE PLAYERS
X#
Xprocedure summarize()
X # blink, high, inverse was just too much for my terminal to handle -RLG
X write(at(1,11), high(chop("Final Score Summary")))
X every player := key(players) do
X {
X card := players[player]
X top := 0 ; every i := 1 to 6 do top +:= card[i]
X if top > 62 then top +:= 35
X bottom := 0 ; every i := 7 to 13 do bottom +:= card[i]
X write("Player ",high(left(player,14))," Top = ",right(top,5),
X " Bottom = ",right(bottom,5),
X " Total = ",right(top+bottom,5))
X }
X input("<press return>")
X end
X
X#
X# SETUP AND INITIALIZATION OF YAHTZEE ENVIRONMENT
X#
Xprocedure assign_players()
X n := 1 ; team := [] ; slot := [] ; d := list(6,"") ; od := list(5,0)
X &random := map(&clock,":","9")
X players := table("n/a")
X repeat
X {
X (player := input(("Name of player #" || n || ": "))) |
X stop("Game called off.")
X if player == "" then break
X n +:= 1
X put(team,player)
X players[player] := list(13,"*")
X }
X if n = 1 then stop("Nobody wants to play!")
X
X put(slot,"Ones") ; put(slot,"Twos") ; put(slot,"Threes")
X put(slot,"Fours") ; put(slot,"Fives") ; put(slot,"Sixes")
X put(slot,"3oK") ; put(slot,"4oK") ; put(slot,"FullH")
X put(slot,"SmStr") ; put(slot,"LgStr") ; put(slot,"Yahtzee")
X put(slot,"Chance")
X
X # VT-specific characters removed. -RLG
X d[1] := "+-----+| || o || |+-----+"
X d[2] := "+-----+| || o o || |+-----+"
X d[3] := "+-----+|o || o || o|+-----+"
X d[4] := "+-----+|o o|| ||o o|+-----+"
X d[5] := "+-----+|o o|| o ||o o|+-----+"
X d[6] := "+-----+|o o o|| ||o o o|+-----+"
X end
X
X#
X# THIS ROUTINE LETS A PLAYER TAKE THEIR TURN
X#
Xprocedure play(name)
X writes(at(1,11),"It's ",high(name),"'s turn",chop())
X writes(at(1,getval("li")-1),high(name))
X input(", please press <RETURN> to begin.")
X score(name)
X dice := [] ; every 1 to 5 do put(dice,?6)
X depict()
X shake := obtain("Shake which ones : ")
X (shake === []) | (every dice[!shake] := ?6)
X depict()
X shake := obtain("Shake which ones (last chance) : ")
X (shake === []) | (every dice[!shake] := ?6)
X depict()
X repeat
X {
X select := input(at(1,22) || clip("Tally to which category (1-13) : "))
X numeric(select) | next
X (1 <= select <= 13) | next
X (players[name][select] == "*") | next
X break
X }
X tally(name,select)
X score(name)
X input(at(1,22) || clip("Press <RETURN>"))
X end
X
X#
X# THIS ROUTINE DRAWS THE DICE
X#
Xprocedure depict()
X every i := 1 to 5 do
X {
X if od[i] = dice[i] then next
X x := 1
X writes(at(i*10+3,3),inverse(i))
X# writes(at(i*10+4,9),inverse(dice[i]))
X every j := 4 to 8 do
X {
X writes(at(i*10,j),graf(d[dice[i]][x:x+7]))
X x +:= 7
X }
X od[i] := dice[i]
X }
X end
X
X#
X# THIS ROUTINE LETS THE PLAYER DECIDE WHAT TO APPLY THE SHAKES TO
X#
Xprocedure tally(name,area)
X case integer(area) of
X {
X 1 : { # ones
X sum := 0 ; every unit := !dice do if unit = 1 then sum +:= 1
X players[name][1] := sum
X }
X 2 : { # twos
X sum := 0 ; every unit := !dice do if unit = 2 then sum +:= 2
X players[name][2] := sum
X }
X 3 : { # threes
X sum := 0 ; every unit := !dice do if unit = 3 then sum +:= 3
X players[name][3] := sum
X }
X 4 : { # fours
X sum := 0 ; every unit := !dice do if unit = 4 then sum +:= 4
X players[name][4] := sum
X }
X 5 : { # fives
X sum := 0 ; every unit := !dice do if unit = 5 then sum +:= 5
X players[name][5] := sum
X }
X 6 : { # sixes
X sum := 0 ; every unit := !dice do if unit = 6 then sum +:= 6
X players[name][6] := sum
X }
X 7 : { # 3 of a kind
X sum := 0 ; flag := 0
X tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
X every piece := key(tmp) do
X if tmp[piece] >= 3 then flag := 1
X if flag = 1 then every sum +:= !dice
X players[name][7] := sum
X }
X 8 : { # four of a kind
X sum := 0 ; flag := 0
X tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
X every piece := key(tmp) do
X if tmp[piece] >= 4 then flag := 1
X if flag = 1 then every sum +:= !dice
X players[name][8] := sum
X }
X 9 : { # full house
X sum := 0 ; flag := 0
X tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
X every piece := key(tmp) do
X {
X if tmp[piece] = 3 then flag +:= 1
X if tmp[piece] = 2 then flag +:= 1
X }
X if flag = 2 then sum := 25
X players[name][9] := sum
X }
X 10 : { # small straight
X sum := 0 ; flag := 0
X hold := set() ; every insert(hold,!dice)
X tmp := sort(hold)
X if tmp[1]+1 = tmp[2] &
X tmp[2]+1 = tmp[3] &
X tmp[3]+1 = tmp[4] then flag := 1
X if tmp[2]+1 = tmp[3] &
X tmp[3]+1 = tmp[4] &
X tmp[4]+1 = tmp[5] then flag := 1
X if flag = 1 then sum := 30
X players[name][10] := sum
X }
X 11 : { # large straight
X sum := 0 ; flag := 0
X tmp := sort(dice)
X if tmp[1]+1 = tmp[2] &
X tmp[2]+1 = tmp[3] &
X tmp[3]+1 = tmp[4] &
X tmp[4]+1 = tmp[5] then flag := 1
X if flag = 1 then sum := 40
X players[name][11] := sum
X }
X 12 : { # yahtzee
X sum := 0 ; flag := 0
X tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1
X every piece := key(tmp) do
X if tmp[piece] = 5 then flag := 1
X if flag = 1 then sum := 50
X players[name][12] := sum
X }
X 13 : { # chance
X sum := 0 ; every sum +:= !dice
X players[name][13] := sum
X }
X }
X end
X
X#
X# THIS ROUTINE OBTAINS A VALID SHAKER REQUEST
X#
Xprocedure obtain(prompt)
X repeat
X {
X writes(at(1,22),prompt)
X (line := read()) | next
X if match("q",map(line)) then stop("Game Quit")
X if trim(line) == "" then return []
X units := parse(line,', \t')
X every unit := !units do
X (1 <= unit <= 5) | next
X break
X }
X return units
X end
X
X#
X# THIS ROUTINE PAINTS THE SCORECARD FOR A GIVEN PLAYER
X#
Xprocedure score(name)
X # Slight realignment. -RLG
X writes(at(1,11),chop(),at(18,11),under(),"Player = ",name," Round = ",under(round))
X writes(at(10,12)," 1 : Ones = ",players[name][1])
X writes(at(10,13)," 2 : Twos = ",players[name][2])
X writes(at(10,14)," 3 : Threes = ",players[name][3])
X writes(at(10,15)," 4 : Fours = ",players[name][4])
X writes(at(10,16)," 5 : Fives = ",players[name][5])
X writes(at(10,17)," 6 : Sixes = ",players[name][6])
X writes(at(40,12)," 7 : 3oK = ",players[name][7])
X writes(at(40,13)," 8 : 4oK = ",players[name][8])
X writes(at(40,14)," 9 : FullH = ",players[name][9])
X writes(at(40,15),"10 : SmStr = ",players[name][10])
X writes(at(40,16),"11 : LgStr = ",players[name][11])
X writes(at(40,17),"12 : Yahtzee = ",players[name][12])
X writes(at(40,18),"13 : Chance = ",players[name][13])
X st1 := 0 ; every i := 1 to 6 do st1 +:= numeric(players[name][i])
X if st1 > 62 then bonus := 35 else bonus := 0
X st2 := 0 ; every i := 7 to 13 do st2 +:= numeric(players[name][i])
X writes(at(10,19),"Bonus = ",clip(bonus))
X writes(at(10,20),"Subtotal = ",st1+bonus)
X writes(at(40,20),"Subtotal = ",st2)
X writes(at(37,21),"Grand Total = ",st1+st2+bonus)
X end
X
X#
X# From here down, all CT's VT-specific I/O codes have been replaced
X# with calls to iolib/itlib routines. The replacements were quite
X# easy to do because of the great modularity of the original program.
X# -RLG
X#
X
X#
X# VIDEO ROUTINE CLEARS SCREEN
X#
Xprocedure cls(str)
X static clear_string
X initial {
X clear_string := getval("cl") |
X (igoto(getval("cm"),1,1) || getval("cd")) |
X stop("abort: Your terminal can't clear screen!")
X }
X /str := ""
X return clear_string || str
X end
X
X#
X# VIDEO ROUTINE ERASES REST OF SCREEN
X#
Xprocedure chop(str)
X static clear_rest
X initial {
X clear_rest := getval("cd") |
X stop("abort: Sorry, your terminal must have cd capability.")
X }
X /str := ""
X return clear_rest || str
X end
X
X#
X# VIDEO ROUTINE OUTPUTS UPPER HALF OF DOUBLE SIZE MESSAGES
X#
Xprocedure uhalf(str)
X # Disabled for non-VT{2,3,4}XX terminals. I'd have left them in for
X # vt100s, but there are so many vt100 terminal emulation programs out
X # there that don't do the big characters that I thought better of it.
X # -RLG
X static isVT
X initial
X {
X if map(getname()) ? (tab(find("vt")+2), tab(any('234')), integer(tab(0)))
X then isVT := 1
X }
X if \isVT then
X {
X /str := ""
X if str == "" then return "\e#3"
X return "\e#3" || str
X }
X end
X
X#
X# VIDEO ROUTINE OUTPUTS BOTTOM HALF OF DOUBLE SIZE MESSAGES
X#
Xprocedure lhalf(str)
X static isVT
X initial
X {
X if map(getname()) ? (tab(find("vt")+2), tab(any('234')), integer(tab(0)))
X then isVT := 1
X }
X if \isVT then
X {
X /str := ""
X if str == "" then return "\e#4"
X return "\e#4" || str
X }
X end
X
X#
X# VIDEO ROUTINE OUTPUTS STRING AND CLEARS TO EOL
X#
Xprocedure clip(str)
X static clear_line
X initial
X {
X clear_line := getval("ce") | " "
X }
X /str := ""
X if str == "" then return clear_line
X return str ||:= clear_line
X end
X
X#
X# VIDEO ROUTINE OUTPUTS HIGHLIGHTED STRINGS
X#
Xprocedure high(str)
X static bold_code, off_other_modes
X initial
X {
X off_other_modes := ""
X every off_other_modes ||:= getval("me"|"ue"|"se")
X bold_code := off_other_modes || getval("md"|"us"|"so")
X }
X /str := ""
X return bold_code || str || off_other_modes
X end
X
X#
X# VIDEO ROUTINE OUTPUTS INVERSE VIDEO STRINGS
X#
Xprocedure inverse(str)
X static reverse_code, off_other_modes
X initial
X {
X off_other_modes := ""
X every off_other_modes ||:= getval("se"|"ue"|"me")
X reverse_code := off_other_modes || getval("so"|"us"|"md")
X }
X /str := ""
X return reverse_code || str || off_other_modes
X end
X
X#
X# VIDEO ROUTINE OUTPUTS UNDERLINED STRINGS
X#
Xprocedure under(str)
X static underline_code, off_other_modes
X initial
X {
X off_other_modes := ""
X every off_other_modes ||:= getval("ue"|"me"|"se")
X underline_code := off_other_modes || getval("us"|"md"|"so")
X }
X /str := ""
X return underline_code || str || off_other_modes
X end
X
X#
X# VIDEO ROUTINE OUTPUTS BLINKING STRINGS
X#
Xprocedure blink(str)
X static blink_code, off_other_modes
X initial
X {
X off_other_modes := ""
X every off_other_modes ||:= getval("me"|"se"|"ue")
X blink_code := off_other_modes || getval("mb"|"md"|"so"|"us")
X }
X /str := ""
X return blink_code || str || off_other_modes
X end
X
X#
X# VIDEO ROUTINE SETS NORMAL VIDEO MODE
X#
Xprocedure norm(str)
X static off_modes
X initial
X {
X off_modes := ""
X every off_modes ||:= getval("me"|"se"|"ue")
X }
X /str := ""
X return off_modes || str
X end
X
X#
X# VIDEO ROUTINE TURNS ON VT GRAPHICS CHARACTERS
X#
Xprocedure graf(str)
X # Again, disabled for non-VT{234}XX terminals. -RLG
X static isVT
X initial
X {
X if map(getname()) ? (tab(find("vt")+2), tab(any('234')), integer(tab(0)))
X then isVT := 1
X }
X /str := ""
X if \isVT then
X {
X if str == "" then return "\e(0"
X str := "\e(0" || str
X if (str[-3:0] == "\e(B")
X then return str
X else return str || "\e(B"
X }
X else return str
X end
X
X#
X# VIDEO ROUTINE TURNS OFF VT GRAPHICS CHARACTERS
X#
Xprocedure nograf(str)
X static isVT
X initial
X {
X if map(getname()) ? (tab(find("vt")+2), tab(any('234')), integer(tab(0)))
X then isVT := 1
X }
X /str := ""
X if \isVT then
X {
X if str == "" then return "\e(B"
X str := "\e(B" || str
X }
X return str
X end
X
X#
X# VIDEO ROUTINE SETS CURSOR TO GIVEN X,Y COORDINATES
X#
Xprocedure at(x,y)
X return igoto(getval("cm"), x, y)
X end
X
X######### Here end the I/O routines I needed to alter. -RLG
X
X#
X# PARSES A STRING INTO A LIST WITH RESPECT TO A GIVEN DELIMITER
X#
Xprocedure parse(line,delims)
X local i, tokens
X static chars
X chars := &cset -- delims
X tokens := []
X line ? while tab(upto(chars)) do put(tokens,tab(many(chars)))
X #
X # My first time playing, I didn't put spaces between the numbers
X # for the dice. When you think about it, though, why bother?
X # They can't be any longer than one digit each, so there's no
X # ambiguity. This bit of code makes the game a bit more idiot-
X # proof. -RLG (one of the idiots)
X #
X if *!tokens > 1 then line ?
X {
X tokens := []
X if tab(upto(&digits)) then
X {
X while put(tokens, move(1)) do
X tab(upto(&digits)) | break
X put(tokens, integer(tab(0)))
X }
X }
X return tokens
X end
X
X#
X# TAKE AN INPUT STRING VIA GIVEN PROMPT
X#
Xprocedure input(prompt)
X writes(prompt)
X return read()
X end
SHAR_EOF
true || echo 'restore of yahtz.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= iolib.icn ==============
if test -f 'iolib.icn' -a X"$1" != X"-c"; then
echo 'x - skipping iolib.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting iolib.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'iolib.icn' &&
X########################################################################
X#
X# Name: iolib.icn
X#
X# Title: Icon termlib-type tools for MS-DOS and UNIX
X#
X# Author: Richard L. Goerwitz (with help from Norman Azadian)
X#
X# Version: 1.9
X#
X#########################################################################
X#
X# The authors place this and future versions of iolib in the public
X# domain.
X#
X#########################################################################
X#
X# The following library represents a series of rough functional
X# equivalents to the standard Unix low-level termcap routines. It is
X# not meant as an exact termlib clone. Nor is it enhanced to take
X# care of magic cookie terminals, terminals that use \D in their
X# termcap entries, or archaic terminals that require padding. This
X# library is geared mainly for use with ANSI and VT-100 devices.
X# Note that this file may, in most instances, be used in place of the
X# older UNIX-only itlib.icn file. It essentially replaces the DOS-
X# only itlibdos routines. For DOS users not familiar with the whole
X# notion of generalized screen I/O, I've included extra documentation
X# below. Please read it.
X#
X# The sole disadvantage of this over the old itlib routines is that
X# iolib.icn cannot deal with archaic or arcane UNIX terminals and/or
X# odd system file arrangements. Note that because these routines
X# ignore padding, they can (unlike itlib.icn) be run on the NeXT and
X# other systems which fail to implement the -g option of the stty
X# command. Iolib.icn is also simpler and faster than itlib.icn.
X#
X# I want to thank Norman Azadian for suggesting the whole idea of
X# combining itlib.icn and itlibdos.icn into one distribution, for
SHAR_EOF
true || echo 'restore of iolib.icn failed'
fi
echo 'End of part 1'
echo 'File iolib.icn is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From icon-group-request@arizona.edu Wed May 29 08:28:34 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 29 May 91 08:28:34 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA25313; Wed, 29 May 91 08:28:31 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 29 May
1991 08:27 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA09529; Wed, 29 May 91
08:14:33 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 29 May 1991 08:28 MST
Date: 29 May 91 14:57:12 GMT
From: cis.ohio-state.edu!zaphod.mps.ohio-state.edu!maverick.ksu.ksu.edu!ux1.cso.uiuc.edu!midway!ellis.uchicago.edu!goer@ucbvax.berkeley.edu
(Richard L. Goerwitz)
Subject: RE: Holiday TidBit, part 3 of 3
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <178CE29C26C00433@Arizona.edu>
Message-Id: <1991May29.145712.4616@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <50632F0EE04001B8@mis.mcw.edu>,
<1991May29.040011.2409@midway.uchicago.edu>
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is yahtz.03 (part 3 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file Makefile.dist continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping Makefile.dist'
else
echo 'x - continuing file Makefile.dist'
sed 's/^X//' << 'SHAR_EOF' >> 'Makefile.dist' &&
XPROGNAME = yahtz
X
X# You may need to change this.
XICONC = /usr/icon/v8/bin/icont
X
X# Don't change this, unless you happen to have a copy of itlib.icn
X# around, and know it works for your system.
XITLIB = iolib
X
X# Please edit these to reflect your local file structure & conventions.
XDESTDIR = /usr/local/games
XOWNER = root
XGROUP = root
X
X# Please don't change these.
XSRC = $(PROGNAME).icn $(ITLIB).icn
XSHELL = /bin/sh
X
X# I hope you won't have to use this.
X# DEBUGFLAG = -t
X
X$(PROGNAME): $(SRC)
X $(ICONC) $(DEBUGFLAG) -o $(PROGNAME) $(SRC)
X
X# Pessimistic assumptions regarding the environment (in particular,
X# I don't assume you have the BSD "install" shell script).
Xinstall: $(PROGNAME)
X test -d $(DESTDIR) || (mkdir $(DESTDIR) && chmod 755 $(DESTDIR))
X cp $(PROGNAME) $(DESTDIR)/
X chgrp $(GROUP) $(DESTDIR)/$(PROGNAME)
X chown $(OWNER) $(DESTDIR)/$(PROGNAME)
X @echo "\nInstallation done.\n"
X
Xclobber:
X -rm -f *~ .u?
X -rm -f $(PROGNAME)
SHAR_EOF
echo 'File Makefile.dist is complete' &&
true || echo 'restore of Makefile.dist failed'
rm -f _shar_wnt_.tmp
fi
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
echo 'x - skipping README (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
XThis hacked version of Chris Tenaglia's yahtzee program will run under
XUNIX, and under DOS as well. To run it under DOS, you need
Xnnansi.sys. Sorry, but the old ansi driver doesn't cut it. Check out
Xthe iolib.icn file for directions on how to set your environment
Xvariables so that iolib can find your termcap file regardless of what
Xdirectory it's in, and so that you can tell iolib that you aren't
Xusing the old ansi.sys driver.
X
XUnix users, type "make" and relax. If you have root privileges, type
X"make install," and relax. If you're worried, check the default vari-
Xables in the makefile. Oh, be sure to cp Makefile.dist makefile before
Xtrying to make anything.
X
XThis is a test version!! In accordance with the author's wishes, I'd
Xlike to make it clear that I've altered all the screen I/O routines,
Xand have removed characters peculiar to VT terminals. I've tried to
Xkeep intact the author's indentation and brace style. Changes, where
Xpresent, have been indicated by my initials.
X
XOne more thing: There are lots of yahtzee programs out there, so I had
Xto rename the program. I've seen yahtzee, yahtzee2, and yaht. I guess
Xyahtz was all that was left ;-).
X
X-Richard Goerwitz.
SHAR_EOF
true || echo 'restore of README failed'
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo You have unpacked the last part
exit 0
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From icon-group-request@arizona.edu Wed May 29 08:28:55 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 29 May 91 08:28:55 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA25328; Wed, 29 May 91 08:28:52 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 29 May
1991 08:28 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA09522; Wed, 29 May 91
08:14:21 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 29 May 1991 08:28 MST
Date: 29 May 91 14:56:34 GMT
From: cis.ohio-state.edu!zaphod.mps.ohio-state.edu!maverick.ksu.ksu.edu!ux1.cso.uiuc.edu!midway!ellis.uchicago.edu!goer@ucbvax.berkeley.edu
(Richard L. Goerwitz)
Subject: RE: Holiday TidBit, part 2 of 3
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <179AEB4AB6C00434@Arizona.edu>
Message-Id: <1991May29.145634.4276@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <50632F0EE04001B8@mis.mcw.edu>,
<1991May29.040011.2409@midway.uchicago.edu>
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is yahtz.02 (part 2 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file iolib.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping iolib.icn'
else
echo 'x - continuing file iolib.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'iolib.icn' &&
X# suggesting things like letting drive specifications appear in DOS
X# TERMCAP environment variables, and for finding several bugs (e.g.
X# the lack of support for %2 and %3 in cm). Although he is loathe
X# to accept this credit, I think he deserves it.
X#
X#########################################################################
X#
X# Contents:
X#
X# setname(term)
X# Use only if you wish to initialize itermlib for a terminal
X# other than what your current environment specifies. "Term" is the
X# name of the termcap entry to use. Normally this initialization is
X# done automatically, and need not concern the user.
X#
X# getval(id)
X# Works something like tgetnum, tgetflag, and tgetstr. In the
X# spirit of Icon, all three have been collapsed into one routine.
X# Integer valued caps are returned as integers, strings as strings,
X# and flags as records (if a flag is set, then type(flag) will return
X# "true"). Absence of a given capability is signalled by procedure
X# failure.
X#
X# igoto(cm,destcol,destline) - NB: default 1 offset (*not* zero)!
X# Analogous to tgoto. "Cm" is the cursor movement command for
X# the current terminal, as obtained via getval("cm"). Igoto()
X# returns a string which, when output via iputs, will cause the
X# cursor to move to column "destcol" and line "destline." Column and
X# line are always calculated using a *one* offset. This is far more
X# Iconish than the normal zero offset used by tgoto. If you want to
X# go to the first square on your screen, then include in your program
X# "iputs(igoto(getval("cm"),1,1))."
X#
X# iputs(cp,affcnt)
X# Equivalent to tputs. "Cp" is a string obtained via getval(),
X# or, in the case of "cm," via igoto(getval("cm"),x,y). Affcnt is a
X# count of affected lines. It is completely irrelevant for most
X# modern terminals, and is supplied here merely for the sake of
X# backward compatibility with itlib, a UNIX-only version of these
X# routines (one which handles padding on archaic terminals).
X#
X##########################################################################
X#
X# Notes for MS-DOS users:
X#
X# There are two basic reasons for using the I/O routines
X# contained in this package. First, by using a set of generalized
X# routines, your code will become much more readable. Secondly, by
X# using a high level interface, you can avoid the cardinal
X# programming error of hard coding things like screen length and
X# escape codes into your programs.
X#
X# To use this collection of programs, you must do two things.
X# First, you must add the line "device=ansi.sys" (or the name of some
X# other driver, like zansi.sys, nansi.sys, or nnansi.sys [=new
X# nansi.sys]) to your config.sys file. Secondly, you must add two
X# lines to your autoexec.bat file: 1) "set TERM=ansi-mono" and 2)
X# "set TERMCAP=\location\termcap." The purpose of setting the TERM
X# variable is to tell this program what driver you are using. If you
X# have a color system, you could use "ansi-color" instead of
X# "ansi-mono," although for compatibility with a broader range of
X# users, it would perhaps be better to stick with mono. The purpose
X# of setting TERMCAP is to make it possible to determine where the
X# termcap database file is located. The termcap file (which should
X# have been packed with this library as termcap.dos) is a short
X# database of all the escape sequences used by the various terminal
X# drivers. Set TERMCAP so that it reflects the location of this file
X# (which should be renamed as termcap, for the sake of consistency
X# across UNIX and MS-DOS spectra). If desired, you can also try
X# using termcap2.dos. Certain games work a lot better using this
X# alternate file. To try it out, rename it to termcap, and set
X# the environment variable TERMCAP to its location.
X#
X# Although the authors make no pretense of providing here a
X# complete introduction to the format of the termcap database file,
X# it will be useful, we believe, to explain a few basic facts about
X# how to use this program in conjunction with it. If, say, you want
X# to clear the screen, add the line,
X#
X# iputs(getval("cl"))
X#
X# to your program. The function iputs() outputs screen control
X# sequences. Getval retrieves a specific sequence from the termcap
X# file. The string "cl" is the symbol used in the termcap file to
X# mark the code used to clear the screen. By executing the
X# expression "iputs(getval("cl"))," you are 1) looking up the "cl"
X# (clear) code in the termcap database entry for your terminal, and
X# the 2) outputting that sequence to the screen.
X#
X# Some other useful termcap symbols are "ce" (clear to end of
X# line), "ho" (go to the top left square on the screen), "so" (begin
X# standout mode), and "se" (end standout mode). To output a
X# boldfaced string, str, to the screen, you would write -
X#
X# iputs(getval("so"))
X# writes(str)
X# iputs(getval("se"))
X#
X# You can also write "writes(getval("so") || str || getval("se")),
X# but this would make reimplementation for UNIX terminals that
X# require padding rather difficult.
X#
X# It is also heartily to be recommended that MS-DOS programmers
X# try not to assume that everyone will be using a 25-line screen.
X# Most terminals are 24-line. Some 43. Some have variable window
X# sizes. If you want to put a status line on, say, the 2nd-to-last
X# line of the screen, then determine what that line is by executing
X# "getval("li")." The termcap database holds not only string-valued
X# sequences, but numeric ones as well. The value of "li" tells you
X# how many lines the terminal has (compare "co," which will tell you
X# how many columns). To go to the beginning of the second-to-last
X# line on the screen, type in:
X#
X# iputs(igoto(getval("cm"), 1, getval("li")-1))
X#
X# The "cm" capability is a special capability, and needs to be output
X# via igoto(cm,x,y), where cm is the sequence telling your computer
X# to move the cursor to a specified spot, x is the column, and y is
X# the row. The expression "getval("li")-1" will return the number of
X# the second-to-last line on your screen.
X#
X##########################################################################
X#
X# Requires: UNIX or MS-DOS, co-expressions
X#
X# See also: itlib.icn, iscreen.icn
X#
X##########################################################################
X
X
Xglobal tc_table, isDOS
Xrecord true()
X
X
Xprocedure check_features()
X
X initial {
X
X if find("UNIX",&features) then
X isDOS := &null
X else if find("MS-DOS", &features) then
X isDOS := 1
X else stop("check_features: OS not (yet?) supported.")
X
X find("expressi",&features) |
X er("check_features","co-expressions not implemented - &$#!",1)
X }
X
X return
X
Xend
X
X
X
Xprocedure setname(name)
X
X # Sets current terminal type to "name" and builds a new termcap
X # capability database (residing in tc_table). Fails if unable to
X # find a termcap entry for terminal type "name." If you want it
X # to terminate with an error message under these circumstances,
X # comment out "| fail" below, and uncomment the er() line.
X
X #tc_table is global
X
X check_features()
X
X tc_table := table()
X tc_table := maketc_table(getentry(name)) | fail
X # er("setname","no termcap entry found for "||name,3)
X return "successfully reset for terminal " || name
X
Xend
X
X
X
Xprocedure getname()
X
X # Getname() first checks to be sure we're running under DOS or
X # UNIX, and, if so, tries to figure out what the current terminal
X # type is, checking successively the value of the environment
X # variable TERM, and then (under UNIX) the output of "tset -".
X # Terminates with an error message if the terminal type cannot be
X # ascertained. DOS defaults to "mono."
X
X local term, tset_output
X
X check_features()
X
X if \isDOS then {
X term := getenv("TERM") | "mono"
X }
X else {
X if not (term := getenv("TERM")) then {
X tset_output := open("/bin/tset -","pr") |
X er("getname","can't find tset command",1)
X term := !tset_output
X close(tset_output)
X }
X }
X
X return \term |
X er("getname","can't seem to determine your terminal type",1)
X
Xend
X
X
X
Xprocedure er(func,msg,errnum)
X
X # short error processing utility
X write(&errout,func,": ",msg)
X exit(errnum)
X
Xend
X
X
X
Xprocedure getentry(name, termcap_string)
X
X # "Name" designates the current terminal type. Getentry() scans
X # the current environment for the variable TERMCAP. If the
X # TERMCAP string represents a termcap entry for a terminal of type
X # "name," then getentry() returns the TERMCAP string. Otherwise,
X # getentry() will check to see if TERMCAP is a file name. If so,
X # getentry() will scan that file for an entry corresponding to
X # "name." If the TERMCAP string does not designate a filename,
X # getentry() will scan the termcap file for the correct entry.
X # Whatever the input file, if an entry for terminal "name" is
X # found, getentry() returns that entry. Otherwise, getentry()
X # fails.
X
X local isFILE, f, getline, line, nm, ent1, ent2
X static slash, termcap_names
X initial {
X if \isDOS then {
X slash := "\\"
X termcap_names := ["termcap","termcap.dos","termcap2.dos"]
X }
X else {
X slash := "/"
X termcap_names := ["/etc/termcap"]
X }
X }
X
X
X # You can force getentry() to use a specific termcap file by cal-
X # ling it with a second argument - the name of the termcap file
X # to use instead of the regular one, or the one specified in the
X # termcap environment variable.
X /termcap_string := getenv("TERMCAP")
X
X if \isDOS then {
X if \termcap_string then {
X if termcap_string ? (
X not ((tab(any(&letters)), match(":")) | match(slash)),
X pos(1) | tab(find("|")+1), =name)
X then return termcap_string
X else isFILE := 1
X }
X }
X else {
X if \termcap_string then {
X if termcap_string ? (
X not match(slash), pos(1) | tab(find("|")+1), =name)
X then return termcap_string
X else isFILE := 1
X }
X }
X
X # The logic here probably isn't clear. The idea is to try to use
X # the termcap environment variable successively as 1) a termcap en-
X # try and then 2) as a termcap file. If neither works, 3) go to
X # the /etc/termcap file. The else clause here does 2 and, if ne-
X # cessary, 3. The "\termcap_string ? (not match..." expression
X # handles 1.
X
X if \isFILE # if find(slash, \termcap_string)
X then f := open(termcap_string)
X /f := open(!termcap_names) |
X er("getentry","I can't access your termcap file. Read iolib.icn.",1)
X
X getline := create read_file(f)
X
X while line := @getline do {
X if line ? (pos(1) | tab(find("|")+1), =name, any(':|')) then {
X entry := ""
X while (\line | @getline) ? {
X if entry ||:= 1(tab(find(":")+1), pos(0))
X then {
X close(f)
X # if entry ends in tc= then add in the named tc entry
X entry ?:= tab(find("tc=")) ||
X # recursively fetch the new termcap entry
X (move(3), getentry(tab(find(":"))) ?
X # remove the name field from the new entry
X (tab(find(":")+1), tab(0)))
X return entry
X }
X else {
X \line := &null # must precede the next line
X entry ||:= trim(trim(tab(0),'\\'),':')
X }
X }
X }
X }
X
X close(f)
X er("getentry","can't find and/or process your termcap entry",3)
X
Xend
X
X
X
Xprocedure read_file(f)
X
X # Suspends all non #-initial lines in the file f.
X # Removes leading tabs and spaces from lines before suspending
X # them.
X
X local line
X
X \f | er("read_tcap_file","no valid termcap file found",3)
X while line := read(f) do {
X match("#",line) & next
X line ?:= (tab(many('\t ')) | &null, tab(0))
X suspend line
X }
X
X fail
X
Xend
X
X
X
Xprocedure maketc_table(entry)
X
X # Maketc_table(s) (where s is a valid termcap entry for some
X # terminal-type): Returns a table in which the keys are termcap
X # capability designators, and the values are the entries in
X # "entry" for those designators.
X
X local k, v
X
X /entry & er("maketc_table","no entry given",8)
X if entry[-1] ~== ":" then entry ||:= ":"
X
X /tc_table := table()
X
X entry ? {
X
X tab(find(":")+1) # tab past initial (name) field
X
X while tab((find(":")+1) \ 1) ? {
X &subject == "" & next
X if k := 1(move(2), ="=") then {
X # Get rid of null padding information. Iolib can't
X # handle it (unlike itlib.icn). Leave star in. It
X # indicates a real dinosaur terminal, and will later
X # prompt an abort.
X str := ="*" | ""; tab(many(&digits))
X tc_table[k] := Decode(str || tab(find(":")))
X }
X else if k := 1(move(2), ="#")
X then tc_table[k] := integer(tab(find(":")))
X else if k := 1(tab(find(":")), pos(-1))
X then tc_table[k] := true()
X else er("maketc_table", "your termcap file has a bad entry",3)
X }
X }
X
X return tc_table
X
Xend
X
X
X
Xprocedure getval(id)
X
X /tc_table := maketc_table(getentry(getname())) |
X er("getval","can't make a table for your terminal",4)
X
X return \tc_table[id] | fail
X # er("getval","the current terminal doesn't support "||id,7)
X
Xend
X
X
X
Xprocedure Decode(s)
X
X # Does things like turn ^ plus a letter into a genuine control
X # character.
X
X new_s := ""
X
X s ? {
X
X while new_s ||:= tab(upto('\\^')) do {
X chr := move(1)
X if chr == "\\" then {
X new_s ||:= {
X case chr2 := move(1) of {
X "\\" : "\\"
X "^" : "^"
X "E" : "\e"
X "b" : "\b"
X "f" : "\f"
X "n" : "\n"
X "r" : "\r"
X "t" : "\t"
X default : {
X if any(&digits,chr2) then {
X char(integer("8r"||chr2||move(2 to 0 by -1))) |
X er("Decode","bad termcap entry",3)
X }
X else chr2
X }
X }
X }
X }
X else new_s ||:= char(ord(map(move(1),&lcase,&ucase)) - 64)
X }
X new_s ||:= tab(0)
X }
X
X return new_s
X
Xend
X
X
X
Xprocedure igoto(cm,col,line)
X
X local colline, range, increment, padding, str, outstr, chr, x, y
X
X if col > (tc_table["co"]) | line > (tc_table["li"]) then {
X colline := string(\col) || "," || string(\line) | string(\col|line)
X range := "(" || tc_table["co"]-1 || "," || tc_table["li"]-1 || ")"
X er("igoto",colline || " out of range " || (\range|""),9)
X }
X
X # Use the Iconish 1;1 upper left corner & not the C-ish 0 offsets
X increment := -1
X outstr := ""
X
X cm ? {
X while outstr ||:= tab(find("%")) do {
X tab(match("%"))
X if padding := integer(tab(any('23')))
X then chr := (="d" | "d")
X else chr := move(1)
X if case \chr of {
X "." : outstr ||:= char(line + increment)
X "+" : outstr ||:= char(line + ord(move(1)) + increment)
X "d" : {
X str := string(line + increment)
X outstr ||:= right(str, \padding, "0") | str
X }
X }
X then line :=: col
X else {
X case chr of {
X "n" : line := ixor(line,96) & col := ixor(col,96)
X "i" : increment := 0
X "r" : line :=: col
X "%" : outstr ||:= "%"
X "B" : line := ior(ishift(line / 10, 4), line % 10)
X ">" : {
X x := move(1); y := move(1)
X line > ord(x) & line +:= ord(y)
X &null
X }
X } | er("goto","bad termcap entry",5)
X }
X }
X return outstr || tab(0)
X }
X
Xend
X
X
X
Xprocedure iputs(cp, affcnt)
X
X # Writes cp to the screen. Use this instead of writes() for
X # compatibility with itlib (a UNIX-only version which can handle
X # albeit inelegantly) terminals that need padding.
X
X static num_chars
X initial num_chars := &digits ++ '.'
X
X type(cp) == "string" |
X er("iputs","you can't iputs() a non-string value!",10)
X
X cp ? {
X if tab(many(num_chars)) & ="*" then
X stop("iputs: iolib can't use terminals that require padding.")
X writes(tab(0))
X }
X
X return
X
Xend
SHAR_EOF
echo 'File iolib.icn is complete' &&
true || echo 'restore of iolib.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= termcap.dos ==============
if test -f 'termcap.dos' -a X"$1" != X"-c"; then
echo 'x - skipping termcap.dos (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting termcap.dos (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'termcap.dos' &&
Xansi|color|ansi-color|ibm|ibmpc|ANSI.SYS color:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[H\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0;44m:te=\E[0m:\
X :so=\E[1;35;44m:se=\E[0;44m:\
X :us=\E[1;31;44m:ue=\E[0;44m:\
X :mb=\E[5m:md=\E[1m:me=\E[0;44m:
Xmono|ansi-mono|ANSI.SYS:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[H\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
X :mb=\E[5m:md=\E[1m:me=\E[m:
Xnnansi-mono|NNANSI.SYS:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:cd=\E[J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :so=\E[7m:se=\E[2m:\
X :us=\E[4m:ue=\E[24m:\
X :mb=\E[5m:md=\E[1m:mh=\E[2m:mr=\E[7m:me=\E[m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
Xnnansi|nnansi-color|NNANSI.SYS color:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:cd=\E[J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0;44m:te=\E[0m:\
X :so=\E[1;35;44m:se=\E[2;37m:\
X :us=\E[4m:ue=\E[24m:\
X :mb=\E[5m:md=\E[1m:mh=\E[2m:mr=\E[7m:me=\E[0;44m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
Xnansi-mono|zansi-mono|N/ZANSI.SYS:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0m:te=\E[0m:\
X :so=\E[7;35m:se=\E[0m:\
X :us=\E[1;31m:ue=\E[0m:\
X :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
Xnansi|zansi|nansi-color|zansi-color|N/ZANSI.SYS color:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0;44m:te=\E[0m:\
X :so=\E[1;35;44m:se=\E[0;44m:\
X :us=\E[1;31;44m:ue=\E[0;44m:\
X :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[0;44m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
XAX|ANSI X3.64|full ANSI X3.64 (1977) standard:\
X :co#80:li#25:bs:pt:am:mi:bl=^G:le=^H:\
X :cl=\E[2J:ce=\E[K:cd=\E[J:\
X :ho=\E[H:cm=\E[%i%d;%dH:cs=\E[%i%d;%dr:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :UP=\E[%dA:DO=\E[%dB:LE=\E[%dC:RI=\E[%dD:\
X :so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
X :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:as=^N:ae=^O:\
X :ku=\E[A:kd=\E[B:kl=\E[C:kr=\E[D:kb=^H:\
X :kn#4:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
X :im=\E[4h:ei=\E[4l:al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:sf=\ED:sr=\EM:
SHAR_EOF
true || echo 'restore of termcap.dos failed'
rm -f _shar_wnt_.tmp
fi
# ============= Makefile.dist ==============
if test -f 'Makefile.dist' -a X"$1" != X"-c"; then
echo 'x - skipping Makefile.dist (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting Makefile.dist (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile.dist' &&
X# Don't change this unless you're sure of what you're doing.
SHAR_EOF
true || echo 'restore of Makefile.dist failed'
fi
echo 'End of part 2'
echo 'File Makefile.dist is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From goer%sophist@gargoyle.uchicago.edu Thu May 30 20:12:40 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 30 May 91 20:12:40 MST
Received: from gargoyle.uchicago.edu by optima.cs.arizona.edu (4.1/15)
id AA19642; Thu, 30 May 91 20:12:33 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu) (4.0/1.14)
id AA03009; Thu, 30 May 91 22:12:31 CDT
Return-Path: <goer@sophist.uchicago.edu>
Received: by sophist (4.1/UofC3.1X)
id AA03062; Thu, 30 May 91 22:13:41 CDT
Date: Thu, 30 May 91 22:13:41 CDT
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Message-Id: <9105310313.AA03062@sophist>
To: icon-group@cs.arizona.edu
Subject: utilities
I've got a fairly large library of utilities for things like rewrapping
text, excizing sentences from ASCII files, comma-izing ints and reals,
outputting non-byte-width int/chars, stripping chars from strings, an
extended snapshot routine, and other stuff. I've posted bits here and
there, but I'd like to disseminate this material more widely, and in a
more complete form. I'm interested in helping anyone out who thinks
he or she might be helped by them. I'm really interested (deep down),
though, in rooting up bugs.
If anyone wants these routines, please drop me a line. Promise me you
will let me know about any changes that you make or about any bugs you
find.
-Richard (goer@sophist.uchicago.edu)
From R.J.Hare@edinburgh.ac.uk Fri May 31 04:21:37 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 31 May 91 04:21:37 MST
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA09625; Fri, 31 May 91 04:21:29 MST
Received: from UKACRL.BITNET (MAILER@UKACRL) by Arizona.edu with PMDF#10282;
Fri, 31 May 1991 04:21 MST
Received: from RL.IB by UKACRL.BITNET (Mailer R2.07) with BSMTP id 2445; Fri,
31 May 91 11:22:45 BST
Received: from RL.IB by UK.AC.RL.IB (Mailer R2.07) with BSMTP id 0929; Fri, 31
May 91 11:22:45 BST
Date: 31 May 91 11:23:12 bst
From: R.J.Hare@edinburgh.ac.uk
Subject: Records
To: icon-group@cs.arizona.edu
Message-Id: <31 May 91 11:23:12 bst 060024@EMAS-A>
X-Envelope-To: icon-group@cs.arizona.edu
Via: UK.AC.ED.EMAS-A; 31 MAY 91 11:22:43 BST
Thanks to all those who answered my query about records.
Next question - I am using records as the basis for a simple database
program. Given that the program will be written in a tight enough way to
ensure that it won't be possible to write a list with more elements than
there are in a database entry, what is the advantage of using a record
to store a database entry as opposed to a list?
I've got my own ideas on this, but I'd like to canvass a few other
opinions.
Thanks.
Roger Hare.
From cargo@cherry.cray.com Fri May 31 06:13:47 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 31 May 91 06:13:47 MST
Received: from timbuk (timbuk.cray.com) by optima.cs.arizona.edu (4.1/15)
id AA11503; Fri, 31 May 91 06:13:44 MST
Received: from cherry04.cray.com by timbuk (4.1/CRI-MX 1.6e)
id AA13694; Fri, 31 May 91 08:13:40 CDT
Received: by cherry04.cray.com
id AA03855; 4.1/CRI-5.6; Fri, 31 May 91 08:13:31 CDT
Date: Fri, 31 May 91 08:13:31 CDT
From: cargo@cherry.cray.com (David S. Cargo)
Message-Id: <9105311313.AA03855@cherry04.cray.com>
To: icon-group@cs.arizona.edu
Subject: Records
I use records instead of lists in cases where I want a more
mnemonic way of accessing structures. In a program I'm working
on right now, I can tell what structures are compatible because
I have named the fields the same names in the same order. It
would not be possible to decide that so easily if the lists were
simply the same size.
Likewise, the fact that records are their own types allows me to
base actions based on the type of a particular parameter. I have
exploited these factors together in the following fragment of code.
Because the name of the record type is also the name of the record
constructor for that type, the following routine returns a value
whose type is the same as the type passed to it without knowing
what that type is. As long as the type is a record with at least
one field named entries, this fragment will work.
## entry_name -- return the entry portion of an absolute path
procedure entry_name(a_path)
# Uses globals
# verified (record constructor)
# unverified (record constructor)
# record verified(entries)
# record unverified(entries)
if *a_path.entries > 1
then return type(a_path)(a_path.entries[-1])
end
A lot of the code I write takes advantage of the type information
carried along by record values.
David S. Cargo (cargo@cray.com)
From TENAGLIA@mis.mcw.edu Fri May 31 06:55:19 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 31 May 91 06:55:19 MST
Received: from MIS1.MIS.MCW.EDU by optima.cs.arizona.edu (4.1/15)
id AA12408; Fri, 31 May 91 06:55:12 MST
Received: from mis.mcw.edu (MCWMI3) by MIS1.MIS.MCW.EDU with PMDF#10477; Fri,
31 May 1991 08:53 CST
Date: Fri, 31 May 1991 08:52 CST
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Re: database
To: icon-group@cs.arizona.edu
Message-Id: <AD537D3440400955@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Regarding: Records
> Thanks to all those who answered my query about records.
> Next question - I am using records as the basis for a simple database
> program. Given that the program will be written in a tight enough way to
> ensure that it won't be possible to write a list with more elements than
> there are in a database entry, what is the advantage of using a record
> to store a database entry as opposed to a list?
> I've got my own ideas on this, but I'd like to canvass a few other
> opinions.
> Thanks.
> Roger Hare.
Perhaps I don't understand the true use of records, or the true meaning of
database. I wrote a useful little database. I call it 'AtterCop'. It's
nomenclature and early evolution is too bizaare for this message. In it's
first ICON manifestation it used lists. Lists worked well. If you wanted
the data sorted, I had a menu entry that would ask for which fields. It
was slow especially on inquiry serially scanning through the list elements.
Deletion was slower. I moved all the elements back one to cover up the
unwanted record and popped off the last element (duplicate). It permitted
multiple occurences of the key, and printed pretty fast.
Records? I always thought of records as ICONs method for creating user
defined datatypes. I once thought it was a database component, but after
a few experiments, it's true purpose became clear.
Tables? After a database contains 1000 or so items, lists become very slow.
So I rewrote 'AtterCop' using icon tables instead. The database key is a
concatenated string from the key fields, is the index to the table. The
entire record (string with fields delimited including the key ones) is a
list element to that table entry. Thus the database is actually a table of
lists. This still allows multiple occurences to a key, and lookup, and
maintenance functions are handled quite speedily. Also, no explicit sort
is needed. Sorting is done optionally at print or view time. Speed of loading,
saving, printing seems to take a little longer though. See example.
Writing out the database as a list Writing it as a table of lists
out := open(database,"w") out := open(database,"w")
every write(out,!db) every lookup := key(db) do
every write(out,!db[lookup])
close(out)
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From sboisen@bbn.com Fri May 31 07:38:41 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 31 May 91 07:38:41 MST
Message-Id: <9105311438.AA13650@optima.cs.arizona.edu>
Received: from REGULUS.BBN.COM by optima.cs.arizona.edu (4.1/15)
id AA13650; Fri, 31 May 91 07:38:37 MST
To: icon-group@cs.arizona.edu
Subject: GNU Emacs utility for short on-line summary of Icon syntax
From: Sean Boisen <sboisen@bbn.com>
Sender: sboisen@bbn.com
Reply-To: sboisen@bbn.com
Date: Fri, 31 May 91 10:28:15 EDT
Appended below (in shar format) is a simple GNU Emacs utility that
lets you check the syntax of Icon expressions: for example, while
editing a program, i may forget the arguments to "any". I can then
call the Emacs function describe-icon-symbol, which displays
any(cset,string,i,j)
Much easier than reaching for the manual!
Richard Goerwitz encouraged me to post it here: no guarantees, but
enjoy. I'd be particularly interested if somebody has more complete
descriptions (mine are only a single line, not always enough to keep
me from reaching for the manual).
........................................
Sean Boisen -- sboisen@bbn.com
BBN Systems and Technologies, Cambridge MA
------------------------------ snip snip ------------------------------
#! /bin/sh
# To extract, remove mail header lines and type "sh filename"
echo x - icon-describe.text
sed -e 's/^X//' > icon-describe.text << '!FaR!OuT!'
XThis is a quick syntax helper for Icon users that work with GNU Emacs.
XThe idea is a simple one: while creating a program, say, you're unsure
Xabout the arguments or their orders for push(). With icon-describe, you
Xsimple execute the function "describe-icon-symbol" with point
Xsomewhere around the word push, and the following information
Xis displayed in the mini-buffer:
X
Xpush(list,x)
X
XThis works with procedures, infix/prefix operators, control
Xstructures/reserved words, and keywords. Note that you get notified if
Xsomething isn't in the documentation file, so you can also use it to
Xcheck whether you've got the right symbol name or not (but you'd have
Xto actually go look at the file to see what the _right_ one is).
X
X
XCaveats:
X
XSee your Emacs manual for how to load this automatically when you
Xvisit .icn files (look at auto-mode-alist and icon-mode-hook, assuming
Xyou're using an icon-mode).
X
Xdescribe-icon-symbol is not initially bound to a key, but you'll
Xprobably want to do so.
X
XThe format of the documentation file is one to a line: this is nice
Xbecause it can be displayed in the minibuffer instead of a pop-up
Xwhich then has to be gotten rid of. It's not so nice in that it limits
Xthe amount of information pretty severely. If somebody wants to
Xprovide a larger documentation file i might provide a pop-up version
X(or some hybrid): i'm too lazy to do all the typing, for one thing!
XThere's also an uneven mix of bare syntax description with some
Xdiscussion of what (especially prefix) operators do. A few keywords
Xhave no description because they're newer than the Icon book, and i
Xdidn't have a description handy. Please contribute to this doc file if
Xyou can!
X
XThe function which determines the symbol at point isn't perfect
X(surprise surprise!). In particular it depends on the syntax tables to
Xdetermine what punctuation is, so if your syntax tables aren't right,
Xthis won't be either. I'm open to suggestions for better algorithms.
XThe current version has a preference for looking backward if not
Xactually on part of a symbol: this seemed more useful for those cases
Xwhere you become hesitant about the arguments to a function just after
Xtyping it.
X
XWhile the usual lack of warranty and support applies, i'd still like
Xto hear if there are problems with this.
X
XSean Boisen
XBBN Systems and Technologies Corporation
X
X
XTwo files follow: i call the first icon-describe.el (don't forget to
Xbyte-compile it!), and the second icondoc.txt. Whatever you decide to
Xcall the latter, make sure you set the variable icon-doc-file accordingly!
!FaR!OuT!
echo x - icon-describe.el
sed -e 's/^X//' > icon-describe.el << '!FaR!OuT!'
X;;; Icon syntax describer: by Sean Boisen, BBN Systems and
X;;; Technologies Corporation, sboisen@bbn.com. Standard lack of
X;;; warranty applies: may be freely distributed subject to the
X;;; restrictions of the GNU Emacs copyright. Please send me any bug
X;;; fixes and/or improvements!
X;;;
X;;; This still has at least the following known deficiences:
X;;;
X;;; The descriptive text file lacks descriptions for the newer
X;;; keywords. Please add them and send me a version if you can!
X;;;
X;;; It might be nice if icon-symbol-at-point did escape sequences as
X;;; well: it doesn't.
X;;;
X;;; Someday it might be more useful to provide more than one line of
X;;; information, especially for procedures: the main hurdle here is
X;;; that i'm too lazy to type all the text in.
X
X;;; additions:
X;;;
X;;; sboisen 2/23/89: i noticed that &pos gets
X;;; picked up as pos. Hacked describe-icon-symbol for this as a
X;;; special case. Still imperfect if point in just past the colon in
X;;; 0:&pos however...
X;;;
X;;; sboisen 2/23/89: symbols which contain characters with special
X;;; meanings in regexps don't get handled properly! not yet fixed...
X
X(require 'icon-mode)
X
X(provide 'icon-describe)
X
X(defvar icon-doc-file "/d4m/sboisen/emacs/icondoc.txt"
X "Where the documentation file can be found.")
X
X;; a helper function: get a string containing all the characters matching
X;; some spec in a syntax table. Class is an atom. Useful in conjunction with
X;; skip-chars-forward. Doesn't do the eighth bit.
X
X(defun get-chars-in-class (class syntax-table)
X (let ((classcode
X (cond
X ((eq class 'whitespace) 0)
X ((eq class 'punctuation) 1)
X ((eq class 'word) 2)
X ((eq class 'symbol) 3)
X ((eq class 'open) 4) ;this doesn't work!
X ((eq class 'close) 5)
X ((eq class 'prefix) 6)
X ((eq class 'stringquote) 7)
X ((eq class 'charquote) 9)
X ((eq class 'startcomment) 11)
X ((eq class 'endcomment) 12)
X ))
X (index 0)
X (str ""))
X (while (< index 128)
X (if (eql (aref syntax-table index) classcode)
X (setq str (concat str (char-to-string index))))
X (setq index (1+ index)))
X str))
X
X(defvar wordchars "a-zA-Z0-9_")
X(defvar junkchars (concat " \n\t\r" "({[)}]"))
X(defvar punct (get-chars-in-class 'punctuation icon-mode-syntax-table))
X
X(defun icon-symbol-at-point ()
X "Get the closest Icon symbol to point, but don't change your
X position. Has a preference for looking backward when not
X directly on a symbol."
X (let (start end symbol)
X (save-excursion
X ;; first see if you're just past a symbol
X (if (looking-at "\\s-\\|\\s(\\|\\s)\\|\\s>")
X (skip-chars-backward junkchars)
X ;; else move forward one character, presumably either a \w or
X ;; a symbol: but not if at the end of the buffer
X (or (= (point) (point-max))
X (forward-char 1)))
X
X (cond
X ;; special case for (potential) keywords: just past a &
X ((eql (preceding-char) 38)
X (setq start (1- (point)))
X (cond
X ((looking-at "\\w")
X (skip-chars-forward wordchars))
X ((looking-at "\\s.")
X (skip-chars-forward punct))
X ;; else whitespace?
X ))
X ;; just past a \\w
X ((eql (aref icon-mode-syntax-table (preceding-char)) 2)
X (skip-chars-backward wordchars)
X ;; worry about being in the middle of a keyword
X (if (eql (preceding-char) 38)
X (setq start (1- (point)))
X (setq start (point)))
X (skip-chars-forward wordchars))
X ;; else a symbol?
X (t
X (skip-chars-backward punct)
X (setq start (point))
X (skip-chars-forward punct)))
X ;; THE OLD WAY THAT LOOKED FORWARD INSTEAD OF BACKWARD
X;; ;; skip past whitespace and parens
X;; (while (looking-at "\\s-\\|\\s(\\|\\s)\\|\\s>")
X;; (skip-chars-forward junkchars))
X;; (if (looking-at "\\w")
X;; (progn
X;; (skip-chars-forward wordchars)
X;; (setq start (point))
X;; (skip-chars-backward wordchars))
X;; ;; else a symbol?
X;; (progn
X;; (skip-chars-forward punct)
X;; (setq start (point))
X;; (skip-chars-backward punct)))
X (buffer-substring start (point)))))
X
X(defun describe-icon-symbol (symbol)
X "Display the documentation of SYMBOL, an Icon operator."
X (interactive
X (let ((fn (icon-symbol-at-point))
X (enable-recursive-minibuffers t)
X (case-fold-search nil) ;require that case match for search
X val args-file regexp)
X (setq val (read-from-minibuffer
X (if fn
X (format "Symbol (default %s): " fn)
X "Symbol: ")))
X (if (string= val "")
X (setq val fn))
X ;; this may not work for characters which are special to regexp
X ;; (like ".")
X (setq regexp (concat "^" val "[ \t(]"))
X (if (not (get-file-buffer icon-doc-file))
X (progn
X (setq args-file
X (find-file-noselect icon-doc-file))
X (set-buffer args-file)
X (rename-buffer "*ICON-DOC*")))
X (set-buffer (get-file-buffer icon-doc-file))
X (goto-char (point-min))
X (list (if (re-search-forward regexp (point-max) t)
X (save-excursion
X (beginning-of-line 1)
X (let ((lnstart (point)))
X (end-of-line)
X (message (buffer-substring lnstart (point)))))
X (error (format "No definition for %s" val)))))))
!FaR!OuT!
echo x - icondoc.txt
sed -e 's/^X//' > icondoc.txt << '!FaR!OuT!'
XFORMAT: a regexp like "^word(args)" of "^word[\t ]descriptive_text
Xabs(numeric)
Xany(cset,string,i,j)
Xbal(cset1,cset2,cset3,string,i,j)
Xcenter(string1,i,string2)
Xchar(i)
Xclose(file)
Xcollect()
Xcopy(x)
Xcset(x)
Xdelete(x1,x2)
Xdetab(string,i1,i2,...,in)
Xdisplay(i,file)
Xentab(string,i1,i2,...,in)
Xerrorclear()
Xexit(i)
Xfind(string1,string2,i,j)
Xget(list)
Xgetenv(string)
Xiand(i,j)
Xicom(i)
Ximage(x)
Xinsert(x1,x2,x3)
Xinteger(x)
Xior(i,j)
Xixor(i,h)
Xishift(i,j)
Xleft(string1,i,string2)
Xlist(i,x)
Xmany(cset,string,i,j)
Xmap(string1,string2,string3)
Xmatch(string1,string2,i,j)
Xmember(x1,x2)
Xmove(i)
Xnumeric(x)
Xopen(string1,string2)
Xord(string)
Xpop(list)
Xpos(i)
Xproc(x)
Xpull(list)
Xpush(list,x)
Xput(list,x)
Xread(file)
Xreads(file,i)
Xreal(x)
Xremove(string)
Xrename(string1,string2)
Xrepl(string,i)
Xreverse(string)
Xright(string1,i,string2)
Xrunerr(i,x)
Xsave(string)
Xseek(file,i)
Xseq(i,j)
Xset(list)
Xsort(list)
Xsort(table,i)
Xstop(x1,x2,...,xn)
Xstring(x)
Xsystem(string)
Xtab(i)
Xtable(x)
Xtrim(string,cset)
Xtype(x)
Xupto(cset,string,i,j)
Xwhere(file)
Xwrite(x1,x2,...,xn)
Xwrites(x1,x2,...,xn)
XCONTROL STRUCTURES/RESERVED WORDS
Xbreak expr
Xby i to j by k
Xcase expr of {...}
Xcreate x
Xdefault : expr
Xdo every expr1 do expr2; until expr1 do expr2; while expr1 do expr2
Xdynamic identifiers
Xelse if expr1 then expr2 else expr3
Xend
Xevery expr1 do expr2
Xfail
Xglobal identifiers
Xif expr1 then expr2 else expr3
Xinitial expr
Xlink file1,file2,...filen
Xlocal identifiers
Xnext
Xnot expr
Xof case expr of {...}
Xprocedure identifier(identifiers)
Xrecord identifiers(fields)
Xrepeat expr
Xreturn expr
Xstatic identifiers
Xsuspend expr
Xthen if expr1 then expr2 else expr3
Xto i to j by k
Xuntil expr1 do expr2
Xwhile expr1 do expr2
X| expr1 | expr2; |expr
X\ expr \ i ; \x produces x if x is not null, otherwise fails
X?:= s ?:= x
X? s ? x; ?x produces a random element of x, failing if x is empty
XINFIX OPERATIONS
X+ n + m produces the sum of n and m; +n produces the numeric value of n
X- n - m produces the difference of n and m; -n produces the negative of n
X* n * m produces the product of n and m; *x produces the size of x
X/ n / m produces n divided by m; /x produces x if x is null, or else fails
X% n % m produces the remainder of n divided by m
X^ n ^ m produces n to the power of m; ^e produces a refreshed copy of e
X< n < m produces m if n is less than m, else fails
X<= n <= m produces m if n is less than or equal to m, else fails
X= n = m produces m if n equals m, else fails; =s equiv. to tab(match(s))
X>= n >= m produces m if n is greater than or equal to m, else fails
X> n > m produces m if n is greater than m, else fails
X~= n ~= m produces m if n is not equal to m, else fails
X++ c1 ++ c2 produces the cset union of c1 and c2
X-- c1 -- c2 produces the cset difference of c1 and c2
X** c1 ** c2 produces the cset intersection of c1 and c2
X|| s1 || s2 produces a string consisting of s1 followed by s2
X<< s1 << s2 produces s2 if s1 is lexically less than s2, else fails
X<<= s1 <<= s2 produces s2 if s1 is lexically <= s2, else fails
X== s1 == s2 produces s2 if s1 is lexically equal to s2, else fails
X>>= s1 >>= s2 produces s2 if s1 is lexically >= s2, else fails
X>> s1 >> s2 produces s2 if s1 is lexically greater than s2, else fails
X~== s1 ~== s2 produces s2 if s2 isn't lexically equal to s2, else fails
X||| a1 ||| a2 produces a list of the values of a1 followed by those of a2
X@ x @ e activates e and transmits x to it; @e produces the outcome of activating e
X:= x := y assigns the value of y to x, and produces the variable x
X<- x <- y assigns y to x and produces x; reverses assignment if resumed
X:=: x :=: y exchanges the values of x and y and produces the variable x
X<-> x <-> y exchanges x and y and produces x; reverses exchange if resumed
X=== x === y produces y if x and y have the same value, else fails
X~=== x ~=== y produces y if x and y don't have the same value, else fails
X& x & y produces y; produces a variable if y is a variable
X. x . y produces a variable for the y field of record x
X+:= n +:= m assigns the sum of n and m to n and produces n
X-:= n -:= m assigns the difference of n and m to n and produces n
X*:= n *:= m assigns the product of n and m to n and produces n
X/:= n /:= m assigns the difference of n and m to n and produces n
X%:= n %:= m assigns the remainder of n divided by m to n and produces n
X^:= n ^:= m assigns n raised to the power m to n and produces n
X<:= n <:= m assigns m to n if n < m, else fails; produces n
X<=:= n <=:= m assigns m to n if n <= m, else fails; produces n
X=:= n =:= m assigns m to n if n = m, else fails; produces n
X>=:= n >=:= m assigns m to n if n >= m, else fails; produces n
X>:= n >:= m assigns m to n if n > m, else fails; produces n
X~=:= n ~=:= m assigns m to n if n ~= m, else fails; produces n
X++:= c1 ++:= c2 assigns the cset union of c1 and c2 to c1 and produces c1
X--:= c1 --:= c2 assigns the cset difference of c1 and c2 to c1, producing c1
X**:= c1 **:= c2 assigns the intersection of c1 and c2 to c1, producing c1
X||:= s1 ||:= s2 assigns the string s1 || s2 to s1 and produces s1
X<<:= s1 <:= s2 assigns s2 to s1 if s1 << s2, else fails; produces s1
X<<=:= s1 <=:= s2 assigns s2 to s1 if s1 <<= s2, else fails; produces s1
X==:= s1 =:= s2 assigns s2 to s1 if s1 == s2, else fails; produces s1
X>>=:= s1 >=:= s2 assigns s2 to s1 if s1 >>= s2, else fails; produces s1
X>>:= s1 >:= s2 assigns s2 to s1 if s1 >> s2, else fails; produces s1
X~==:= s1 ~=:= s2 assigns s2 to s1 if s1 ~== s2, else fails; produces s1
X|||:= a1 |||:= a2 assigns to a1 the concatenation of a1 and a2; produces a1
X@:= x @:= e activates e with the value of x, and assigns the result to x
X===:= x ===:= y assigns y to x if x === y, else fails; produces x
X~===:= x ~===:= y assigns y to x if x ~=== y, else fails; produces x
X&:= x &:= y assigns the value of y to x and produces x
XPREFIX OPERATIONS (some under infix instead)
X~ ~c produces the cset complement of c with respect to &cset
X! !x generates the elements of x, failing if x is empty (x may be a file)
X. .x produces the value of x
XKEYWORDS
X&ascii produces a cset of the 128 ASCII characters
X&clock produces a string consisting of the current time of day
X&collections
X&cset produces a cset consisting of all 256 characters
X¤t
X&date produces a string consisting of the current date
X&dateline produces a string of the current date and time of day
X&digits
X&error
X&errornumber
X&errortext
X&errorvalue
X&errout produces the standard error output file
X&fail fails
X&features
X&file
X&host produces a string that identifies the host computer
X&input produces the standard input file
X&lcase produces a cset consisting of the 26 lowercase letters
X&level produces the integer level of the current procedure call
X&line
X&main produces a co-expression for the initial call of main
X&null produces the null value
X&output produces the standard output file
X&pos produces the integer position of scanning in &subject
X&random produces the value of the seed for the psuedo-random sequence
X®ions
X&source produces a co-expression for the activator of the current co-expression
X&storage how much of each storage region is currently being used
X&subject produces the variable whose value is the string being scanned
X&time produces the integer number of msecs since beginning of execution
X&trace produces a variable whose value controls procedure tracing
X&ucase produces a cset consisting of the 26 uppercase characters
X&version produces a string that identifies the version of Icon
!FaR!OuT!
exit
From icon-group-request@arizona.edu Fri May 31 08:17:53 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Fri, 31 May 91 08:17:53 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA15592; Fri, 31 May 91 08:17:51 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Fri, 31 May
1991 08:17 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA29331; Fri, 31 May 91
08:02:33 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 31 May 1991 08:17 MST
Date: 31 May 91 14:38:15 GMT
From: cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!midway!ellis.uchicago.edu!goer@ucbvax.berkeley.edu (Richard L.
Goerwitz)
Subject: RE: Records
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <A8669FE806C00FB6@Arizona.edu>
Message-Id: <1991May31.143815.4204@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <31.May.91..11:, 23:12.bst..060024@EMAS-A>
In <31.May.91..11:23:12.bst..060024@EMAS-A> R.J.Hare@edinburgh.ac.uk writes:
>
>Next question - I am using records as the basis for a simple database
>program. Given that the program will be written in a tight enough way to
>ensure that it won't be possible to write a list with more elements than
>there are in a database entry, what is the advantage of using a record
>to store a database entry as opposed to a list?
Record field access is much faster than list subscripting. You can also
get at the fields by name, and not worry about their order. If you want,
though, you can subscript records (as long as you realize that doing so
erases most of their method of/speed of access advantages).
If you really want to be clever, use a record for all the fields you know
you'll be using, but make one member of the record into a list where you
can store optional or other fields. You'll get the best of both worlds,
at the expense of some clarity and straightforwardness.
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From uunet!men2a!aquin!luvthang!talmage Sat Jun 1 02:07:07 1991
Received: from univers.cs.arizona.edu by cheltenham.cs.arizona.edu; Sat, 1 Jun 91 02:07:07 MST
Received: from uunet.UUCP by univers.cs.arizona.edu; Sat, 1 Jun 91 02:07:06 MST
Received: from men2a.UUCP (LOCALHOST.UU.NET) by relay2.UU.NET with SMTP
(5.61/UUNET-internet-primary) id AA04543; Sat, 1 Jun 91 03:46:13 -0400
Received: from men2a.UUCP by uunet.uu.net with UUCP/RMAIL
(queueing-rmail) id 034526.15947; Sat, 1 Jun 1991 03:45:26 EDT
Received: by men2a.ori-cal.com (smail2.5)
id AA00353; 1 Jun 91 03:52:14 EDT (Sat)
Received: by aquin.ORI-CAL.COM (smail2.5)
id AA01610; 1 Jun 91 03:37:12 EDT (Sat)
Received: by luvthang.UUCP (1.05D/Amiga)
id AA02235; Fri, 31 May 91 17:17:07 EST
Date: Fri, 31 May 91 17:17:07 EST
Message-Id: <9105312217.AA02235@luvthang.UUCP>
From: uunet!luvthang!talmage (David W. Talmage)
To: uunet!icon-group
Subject: Idol gotcha: mixing procedures and methods
Boy, do I feel dumb! Here's a "gotcha" for those of us who work with
Idol, Clint Jeffery's neato object-oriented language derived from Icon.
In Idol, you can have both procedures and methods in a class
definition. Procedures become part of the global name space while
methods stay local to the objects of their class. Because procedures
are in the global space, they have no concept of the variable "self",
which all methods may use to access the instance variables of their
class. Procedures which try to dereference self invoke a run-time
error: "record expected".
This sample should illustrate the problem:
class DoNuthin(theFrobotz, theZimZam)
method asString()
return "theFrobotz= " || self.theFrobotz || " theZimZam= " || self.theZimZam
end
procedure printThem()
write( self.theFrobotz )
write( self.theZimZam )
end
initially
printThem()
end
procedure main()
local aDoNuthin
aDoNuthin := DoNuthin( "David", "Talmage" )
write( aDoNuthin$asString() )
end
I don't want to tell you how long it took me to figure that one out.
-----------------------------------------------------------------------------
David W. Talmage (talmage@luvthang.aquin.ori-cal.com)
"I need fifty dollars to make you hollar. I get paid to run this luvthang."
From cjeffery Mon Jun 3 12:17:05 1991
Date: Mon, 3 Jun 91 12:17:05 MST
From: "Clinton Jeffery" <cjeffery>
Message-Id: <9106031917.AA17352@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Mon, 3 Jun 91 12:17:05 MST
To: uunet!men2a!aquin!luvthang!talmage
Cc: icon-group
In-Reply-To: David W. Talmage's message of Fri, 31 May 91 17:17:07 EST <9105312217.AA02235@luvthang.UUCP>
Subject: Idol gotcha: mixing procedures and methods
<<This is a reply to David Talmage's note on mixing procedures and methods
in Idol. Regular Icon readers will not miss anything if they skip it.>>
Procedures inside class declarations are regular Icon procedures and do not
have any implicit "self" object on which to operate. Idol used to flag this
with an error to prevent the kind of confusion Mr. Talmage experienced. But
it is quite useful to allow normal Icon code (such as helping procedures)
to be included within a class declaration. Idol does not take the view
that every piece of code should be a method, any more than it views
every piece of data as an object. Saying "procedure" when you mean
"method" will indeed cause the kind of problems Mr. Talmage described.
From uunet!men2a!aquin!luvthang!talmage Wed Jun 5 14:36:06 1991
Received: from univers.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 5 Jun 91 14:36:06 MST
Received: from uunet.UUCP by univers.cs.arizona.edu; Wed, 5 Jun 91 14:36:06 MST
Received: from uunet.uu.net (LOCALHOST.UU.NET) by relay1.UU.NET with SMTP
(5.61/UUNET-internet-primary) id AA11701; Wed, 5 Jun 91 14:26:09 -0400
Received: from men2a.UUCP by uunet.uu.net with UUCP/RMAIL
(queueing-rmail) id 142547.9400; Wed, 5 Jun 1991 14:25:47 EDT
Received: by men2a.ori-cal.com (smail2.5)
id AA24099; 5 Jun 91 14:34:43 EDT (Wed)
Received: by aquin.ORI-CAL.COM (smail2.5)
id AA02705; 5 Jun 91 14:17:48 EDT (Wed)
Received: by luvthang.aquin.ori-cal.com (1.05D/Amiga)
id AA02343; Wed, 5 Jun 91 08:50:51 EST
Date: Wed, 5 Jun 91 08:50:51 EST
Message-Id: <9106051350.AA02343@luvthang.aquin.ori-cal.com>
From: uunet!luvthang.aquin.ori-cal.com!talmage (David W. Talmage)
To: uunet!icon-group
Subject: sorting files larger than physical memory
Once upon a time, Richard Goerwitz posted some text indexing code he
called gettext(). I've been using it and trying to improve it. One
thing I'm working on is sorting the keys in the index files so
searches for keys are faster. This presents a problem when the keys
are too many to fit in available memory at one time. I'm looking for
solutions to this problem.
My solution, for the time being, is to read the keys in batches that
fit in my limited memory, sorting each batch with the built-in
function sort(). Each sorted batch I write to a temporary file. When
all batches are sorted, I merge the temporary files one record at a
time in much the same way as you'd merge piles of sorted index cards.
I welcome comments and code from anyone.
-----------------------------------------------------------------------------
David W. Talmage (talmage@luvthang.aquin.ori-cal.com)
"I need fifty dollars to make you hollar. I get paid to run this luvthang."
From @um.cc.umich.edu:Paul_Abrahams@MTS.cc.Wayne.edu Wed Jun 5 15:53:57 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Wed, 5 Jun 91 15:53:57 MST
Received: from umich.edu by optima.cs.arizona.edu (4.1/15)
id AA26204; Wed, 5 Jun 91 15:53:54 MST
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA18627; Wed, 5 Jun 91 18:53:50 -0400
Received: from MTS.cc.Wayne.edu by um.cc.umich.edu via MTS-Net; Wed, 5 Jun 91 18:47:45 EDT
Date: Wed, 5 Jun 91 18:47:34 EDT
From: Paul_Abrahams@mts.cc.wayne.edu
To: icon-group@cs.arizona.edu
Message-Id: <335121@MTS.cc.Wayne.edu>
Subject: Sorting index files
Dave Talmage inquired about sorting files that are too large to
fit in memory. I had the same problem in my indexing program
for ``TeX for the Impatient''. My solution was simple: two Icon
programs and a sort in between, using the sort program that comes
with your system. This solution works equally well for Unix and
DOS, although the standard DOS sorting program is probably not
satisfactory; you'll have to shop around for a better one. You
can also do it with a single Icon program and the `system'
function, or maybe even more elegantly with `system' and piped
files under Unix. But the two-program solution ain't that bad.
A couple more details: the first pass analyzes each index entry
and attaches a sort key to it. With appropriate use of the Icon
map function, you can handle the fine points of sorting uppercase
versus lowercase and handling index entries that begin with
special characters. The second pass strips the sort keys and
collects the entries for a particular index heading.
By the way, the standard practice on ordering special characters
in an index is to use the ASCII collating sequence. As far as
I'm concerned, that's a copout. Indices are intended to be read
by people, not by machines. How many of your buddies (male or
female, no sexism intended) remember the ASCII collating sequence
for the special characters? A much better solution is to sort
the special characters by their English names, which you should
list for the reader so as to avoid any confusion (is it ``star''
or ``asterisk'', ``dash'' or ``minus'')? A few twiddles are in
order: ``parenthesis, left'' rather than ``left parenthesis'',
etc.
Paul Abrahams
Abrahams@mts.cc.wayne.edu
From TENAGLIA@mis.mcw.edu Thu Jun 6 04:09:14 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 6 Jun 91 04:09:14 MST
Received: from MIS1.MIS.MCW.EDU by optima.cs.arizona.edu (4.1/15)
id AA25230; Thu, 6 Jun 91 04:09:09 MST
Received: from mis.mcw.edu (MCWMI3) by MIS1.MIS.MCW.EDU with PMDF#10477; Thu, 6
Jun 1991 06:09 CST
Date: Thu, 6 Jun 1991 06:09 CST
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Re: Sorting index files
To: Paul_Abrahams@mts.cc.wayne.edu
Cc: icon-group@cs.arizona.edu
Message-Id: <4D82694060200B20@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Vms-To: IN%"Paul_Abrahams@mts.cc.wayne.edu"
X-Vms-Cc: IN%"icon-group@cs.arizona.edu"
Regarding: Sorting index files
> Dave Talmage inquired about sorting files that are too large to
> fit in memory. I had the same problem in my indexing program
> for ``TeX for the Impatient''. My solution was simple: two Icon
> programs and a sort in between, using the sort program that comes
> with your system. This solution works equally well for Unix and
> DOS, although the standard DOS sorting program is probably not
> satisfactory; you'll have to shop around for a better one. You
> can also do it with a single Icon program and the `system'
> function, or maybe even more elegantly with `system' and piped
> files under Unix. But the two-program solution ain't that bad.
>>..more..
> Paul Abrahams
> Abrahams@mts.cc.wayne.edu
I also have a report generator with the same problem. It loads, sorts,
outputs. Somewhere between 2000 and 5000 items is the limit of icon
sort() {under VMS} so once the list is loaded I test it's size. If
greater than the limit, I write it to a temporary file, sort with
system("sort/key=(pos:5,size:12,ascending) file.tmp")
reload the file, output the report and cleanup temp files.
Although there are sometimes when the list goes to 20,000 to 50,000 items
and I can't even fit it. So I have a passed parameter (-file) when I know this
will happen to run everything with temp files. VMS, unlike unix does not
have piping (who | sort | mail tenaglia).
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From icon-group-request@arizona.edu Thu Jun 6 11:08:23 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 6 Jun 91 11:08:23 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA09074; Thu, 6 Jun 91 11:08:20 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 6 Jun
1991 10:56 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA17391; Thu, 6 Jun 91 10:48:02
-0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 6 Jun 1991 11:08 MST
Date: 6 Jun 91 17:30:10 GMT
From: agate!spool.mu.edu!sol.ctr.columbia.edu!ira.uka.de!i41s5!angelo@ucbvax.berkeley.edu (Angelo
Schneider Betr.Prechelt)
Subject: WHAT Icon ?
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <7734F3E5A4C02B85@Arizona.edu>
Message-Id: <1991Jun6.173010.17650@ira.uka.de>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Karlsruhe, FRG
Would anybody please mail me some information
about icon?
Can I get anywhere a compiler or at least a to C-Compiler?
thanx in advance
angelo
From goer%sophist@gargoyle.uchicago.edu Sun Jun 9 12:24:09 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 9 Jun 91 12:24:09 MST
Received: from gargoyle.uchicago.edu by optima.cs.arizona.edu (4.1/15)
id AA20386; Sun, 9 Jun 91 12:24:07 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu) (4.0/1.14)
id AA28884; Sun, 9 Jun 91 14:24:05 CDT
Return-Path: <goer@sophist.uchicago.edu>
Received: by sophist (4.1/UofC3.1X)
id AA07148; Sun, 9 Jun 91 14:25:08 CDT
Date: Sun, 9 Jun 91 14:25:08 CDT
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Message-Id: <9106091925.AA07148@sophist>
To: icon-group@cs.arizona.edu
Subject: ansi routines
Is anyone using the IPL ansi.icn library? If so, I have a set of
compatible routines I'm trying to test out that will run under a
wider variety of platforms. Anyone who wants to try them out, pleas
drop me a line.
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From shafto@eos.arc.nasa.gov Mon Jun 10 12:42:17 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 10 Jun 91 12:42:17 MST
Received: from eos.arc.nasa.gov by optima.cs.arizona.edu (4.1/15)
id AA08664; Mon, 10 Jun 91 12:42:15 MST
Received: Mon, 10 Jun 91 12:42:05 -0700 by eos.arc.nasa.gov (5.65/1.2)
Date: Mon, 10 Jun 91 12:42:05 -0700
From: Michael Shafto <shafto@eos.arc.nasa.gov>
Message-Id: <9106101942.AA02715@eos.arc.nasa.gov>
To: goer%sophist@gargoyle.uchicago.edu, icon-group@cs.arizona.edu
Subject: Re: ansi routines
Cc: shafto@eos.arc.nasa.gov
Richard --
Yes, and I would be interested in testing your new improved version.
Mike
From icon-group-request@arizona.edu Mon Jun 10 14:50:07 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Mon, 10 Jun 91 14:50:07 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA19481; Mon, 10 Jun 91 14:49:55 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Mon, 10 Jun
1991 14:49 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03491; Mon, 10 Jun 91
14:30:50 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 10 Jun 1991 14:49 MST
Date: 10 Jun 91 21:11:45 GMT
From: cis.ohio-state.edu!zaphod.mps.ohio-state.edu!sdd.hp.com!news.cs.indiana.edu!ux1.cso.uiuc.edu!midway!ellis.uchicago.edu!goer@ucbvax.berkeley.edu (Richard L.
Goerwitz)
Subject: RE: ansi routines
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <BACF26FE2CC02640@Arizona.edu>
Message-Id: <1991Jun10.211145.23543@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
References: <9106101942.AA02715@eos.arc.nasa.gov>
shafto@EOS.ARC.NASA.GOV (Michael Shafto) writes:
>
>Yes, and I would be interested in testing your new improved version.
I wasn't clear enough: My version is expanded (in the sense that
the ANSI interface can be applied to non-ANSI terminals). I'm not
sure that it really constitutes an improvement. Anyway, I haven't
had enough requests to consider posting, so I reiterate the offer
of sending them to anyone who wants to use them.
It's really a good idea to used generalized I/O for any programs
written in Icon, since Icon runs on so many platforms. These new
ANSI routines have the advantage of working as-is on DOS platforms
with the ansi.sys driver installed. The escape codes are hard-
coded in. If, however, you want to run a program written with
them on, say, a UNIX box, the routines are structured so that you
can just link in the Icon termlib-type routines I posted some time
ago here (and which I have copies of I'll gladly pass on; I use
them constantly, and can't seem to stop revising them). There is
also a library of high-level routines I wrote for use in conjunc-
tion with the termlib-type library. These can also be linked in
with the revised ANSI screen control library. The routines in
the revised library sense what it is you've linked in, and make
use of whatever you've made available (if in fact they need any
additional help - which they don't in DOS environments).
The idea is to have a generalized library of screen functions
that DOS users can blindly use, which take up minimal space, are
fairly fast, and which can be augmented for Unix without having
to change a single line of code (and without requiring the user
to have to do worry about setting up any sort of database). Ad-
mittedly, these routines are a bit more spartan than the iolib
routines I posted a while back. They are a lot more hassle-free,
though, and they cover pretty much all the basic functions that
people doing visually oriented programs would need.
You know, speaking of screen control, I wrote a set of Icon-based
windowing routines some time ago. They let you open up virtual
screens, move them around, create borders, overlap them, write to
any screen (aka window), and have the portion showing on the stan-
dard screen be correctly updated (if in fact any was showing).
The reason I didn't post them is quite simple: Although they were
fast enough for most purposes, they ate up way, way too much mem-
ory. I implemented the concept of a displayable area with the
Icon equivalent of a 2d array (a list of lists), and then tried
various ways of representing squares in that array (integers, rec-
ords, etc.). The trouble was that I wanted them to be pointers
to window structures created by the user. Not having this facility,
I had to use records, which used up just too much space.
It *almost* worked. :-( I guess I wish that Icon had some sort
of explicit pointer data type.
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer
From icon-group-request@arizona.edu Tue Jun 11 16:39:17 1991
Received: from optima.cs.arizona.edu by cheltenham.cs.arizona.edu; Tue, 11 Jun 91 16:39:17 MST
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Merlin.Telcom.Arizona.EDU) by optima.cs.arizona.edu (4.1/15)
id AA20908; Tue, 11 Jun 91 16:39:12 MST
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Tue, 11 Jun
1991 16:38 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA17305; Tue, 11 Jun 91
16:30:41 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 11 Jun 1991 16:38 MST
Date: 11 Jun 91 22:45:29 GMT
From: acf5!mitsolid@nyu.edu (Thanasis Mitsolides)
Subject: ALLOY: Parallel, higher level, and flexible. V2.0
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <933F0BC460C03614@Arizona.edu>
Message-Id: <1624@acf5.NYU.EDU>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: New York University
This, announces the availability of the interpreter, manual,
examples, and thesis for the programming language ALLOY v2.0.
ALLOY now completely unifies its functional and object oriented aspects.
Also, its supports a much richer library.
ALLOY is high level, parallel, flexible and efficient.
ALLOY combines serial/parallel ev., eager/lazy ev., single/multiple solutions
and parallel object oriented programming in a remarkably simple framework.
Example programs ready for execution include:
1) factorial, partition sort, FP (highly parallel)
2) fibonacci sequence, prime numbers (eager or lazy)
3) systolic sort, hamming network (clear flow of data)
4) list member, tree leave, list permutation, n queens (multiple solutions)
5) queue, stack, faa, semaphores, dinning philosophers (objects)
6) prolog package, prolog/parlog programming styles (flexibility)
Part of ALLOY is explained in:
[MH90] Thanasis Mitsolides and Malcolm Harrison. Generators and the
replicator control structure in the parallel environment of ALLOY.
In ACM SIGPLAN '90 Conference on Programming Language Design and
Implementation, pages 189--196, White Plains, New York, June 1990.
The abstract of the ALLOY manual is appended at the end of this message.
The sources, manual, example programs, benchmarks, and thesis of ALLOY
are available for anonymous FTP from cs.nyu.edu (128.122.140.24)
I hope you will find ALLOY interesting.
I will be glad to answer your comments!
Thank you,
Thanasis
===============================================================================
ABSTRACT
ALLOY is a higher level parallel programming language appropriate
for programming massively parallel computing systems. It is based
on a combination of ideas from functional, object oriented and
logic programming languages.
The result is a language that can directly support functional,
object oriented and logic programming styles in a unified and
controlled framework. Evaluating modes support serial or parallel
execution, eager or lazy evaluation, non-determinism or multiple
solutions etc. ALLOY is simple as it only requires 29 primitives
in all (half of which for Object Oriented Programming support).
This article, starts with a formal definition of the small ALLOY
kernel proceeds with the definition of some useful libraries and
concludes with examples which demonstrate its expressiveness and
clarity.
Programming language ALLOY is located on system spunky.cs.nyu.edu
directory ~mitsolid/alloy. This article can be found in dvi and
ascii form on subdirectory doc, The examples presented can be
found in subdirectory progs. The interpreter is executable file
alloy. All the above and the sources of the ALLOY interpreter are
available for anonymous ftp on system cs.nyu.edu directory
pub/local/alloy.
-------------------------------------------------------------------------------
Internet: mitsolid@cs.nyu.edu (mitsolid%cs.nyu.edu@relay.cs.net)
UUCP : ...!uunet!cmcl2!cs!mitsolid
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------
Internet: mitsolid@cs.nyu.edu (mitsolid%cs.nyu.edu@relay.cs.net)
UUCP : ...!uunet!cmcl2!cs!mitsolid
-------------------------------------------------------------------------------
From uunet!men2a!aquin!luvthang!talmage Thu Jun 13 10:11:25 1991
Received: from univers.cs.arizona.edu by cheltenham.cs.arizona.edu; Thu, 13 Jun 91 10:11:25 MST
Received: from uunet.UUCP by univers.cs.arizona.edu; Thu, 13 Jun 91 10:11:24 MST
Received: from uunet.uu.net (via LOCALHOST.UU.NET) by relay1.UU.NET with SMTP
(5.61/UUNET-internet-primary) id AA00621; Thu, 13 Jun 91 08:22:21 -0400
Received: from men2a.UUCP by uunet.uu.net with UUCP/RMAIL
(queueing-rmail) id 082208.20608; Thu, 13 Jun 1991 08:22:08 EDT
Received: by men2a.ori-cal.com (smail2.5)
id AA12884; 13 Jun 91 08:19:53 EDT (Thu)
Received: by aquin.ORI-CAL.COM (smail2.5)
id AA05816; 13 Jun 91 07:34:44 EDT (Thu)
Received: by luvthang.aquin.ori-cal.com (1.05D/Amiga)
id AA02419; Tue, 11 Jun 91 10:25:31 EST
Date: Tue, 11 Jun 91 10:25:31 EST
Message-Id: <9106111525.AA02419@luvthang.aquin.ori-cal.com>
From: uunet!luvthang.aquin.ori-cal.com!talmage (David W. Talmage)
To: uunet!icon-group
Subject: Increasing the number of concurrently open files
How many open files can an Icon program have at one time? How can I
change this? I'm encountering a limit of about 20 with Amiga Icon
version 8.0, February 14, 1990. It looks like I can open 17 files of
my own choosing. The remaining three must be &input, &output, and
&errout.
The documentation tells me of an icont option -SFnnnn where nnnn is
the number of files. Is there anything else I must do? I've tried
-SF50, for example, with no change.
Enclosed, for the curious, is a program that determines how many open
files you can have at one time.
David Talmage
uunet!luvthang!talmage
----- Begin included text -----
# File: OpenFileTest.icn
# Author: David W. Talmage
#
# Usage: iconx OpenFileTest [numfiles]
#
# OpenFileTest attempts to open numfiles files and keep them all open
# at the same time. If it cannot open one of the files, OpenFileTest
# reports the name and number of the file.
#
# OpenFileTest removes all of the files it creates.
#
# By default, numfiles is 15.
#
record fileRec( theFilePointer, theFileName )
procedure main( argv )
local aFileRec
local fileName
local fRecList
local numFRecs
local openFileCount
local j
openFileCount := 0
numFRecs := integer( argv[1] ) | 15
fRecList := list()
#
# CHANGE THE BASE NAME OF THE TEMPORARY FILE TO ONE FITTING YOUR SYSTEM.
#
every fileName := (tempname("t:xxOFT." ) \ numFRecs) do {
aFileRec := fileRec( open( fileName, "w" ), fileName ) | break(
write( "OpenFileTest: Can't open ", fileName,
", file #", openFileCount + 1 ) )
openFileCount +:= 1
put( fRecList, aFileRec )
}
write( "OpenFileTest: opened ", openFileCount, " concurrently." )
#
# Clean up after ourselves. Close and delete each temporary file.
#
every j := 1 to openFileCount do {
close( fRecList[ j ].theFilePointer )
remove( fRecList[ j ].theFileName )
}
end
# This is a version of Ronald Florence's (ron@mlfarm.com) tempname
# generator from post.icn of January 8, 1991. That procedure was
# based on Richard Goerwitz's tempname generator, probably the one
# named get_dos_tempname in gdl.icn version 1.2.
#
# tempname() generates a sequence of unique temporary file names with
# some common base name.
#
procedure tempname(basename)
local temp_name
every temp_name := basename || right(1 to 999,3,"0") do {
close(open(temp_name)) & next
suspend \temp_name
}
end