From info-sr-sender  Fri Mar 25 10:54:47 1988
Received: by bocklin.arizona.edu; Fri, 25 Mar 88 10:54:52 MST
Date: Fri, 25 Mar 88 10:54:47 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8803251754.AA06773@bocklin.arizona.edu>
To: info-sr@arizona.edu
Subject: info-sr mailing list
Errors-To: info-sr-errors

We have added your name to the info-sr mailing list;  welcome aboard!

Info-sr is a mailing list for discussing all aspects of the SR programming
language and its implementation.  Your participation is encouraged;  the list
is *not* restricted to SR "experts".

Messages sent to "info-sr@arizona.edu" are immediately redistributed to all
members of the mailing list.

Administrative requests (e.g. changes of address, removal from list) should be
sent to "info-sr-request@arizona.edu" and not to the general mailing list.

Other questions that are not of general interest can be sent directly to
"sr-project@arizona".

If you should submit an item to info-sr and get back failure notifications from
distant mailers, you can help us eliminate such problems by sending these
notification messages to the request address above.  Our software tries to
arrange for failure notifications to be sent to us, but this isn't foolproof.

From info-sr-sender  Mon May 16 05:26:24 1988
Received: by bocklin.arizona.edu; Mon, 16 May 88 05:26:27 MST
Message-Id: <8805161226.AA14456@megaron.arizona.edu>
Date: 16 MAY 88 14:24-
From: KIESEL%DBNINF5.BITNET@CUNYVM.CUNY.EDU
To: INFO-SR@arizona.edu
Subject: anything happend?
Errors-To: info-sr-errors

Date: 16-MAY-1988 14:22:03.01
From: Norbert Kiesel KIESEL AT DBNINF5
To:   0::"info-sr@ARIZONA.EDU",KIESEL
Subj: anything happend?
                        Hi there,
I Just wnt to know wether my subscription to this list has been successfull.
It's now about three weeks ago and I haven't heard anything. Or is this
just dead??

                so long Norbert


From info-sr-sender  Mon May 16 11:20:32 1988
Received: by bocklin.arizona.edu; Mon, 16 May 88 11:20:35 MST
Date: Mon, 16 May 88 11:20:22 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8805161820.AA01862@megaron.arizona.edu>
To: info-sr
Subject: Re:  anything happend?
Errors-To: info-sr-errors

Norbert Kiesel asked a question that several people are probably wondering
about:  does the info-sr mailing list really work?

Well, yes, we think it does, but everybody's been VERY quiet.  This is
probably because it's just starting up, but there should now be enough
people to maintain a discussion.

I'll try and start something going by asking a provocative question:
in your experiences with SR so far, what's the most surprising thing
you've encountered?

(Remember, to join the discussion, just send your message to
 info-sr@arizona.edu)

     Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
     +1 602 621 4325      gmt@Arizona.EDU       110 57 16 W / 32 13 45 N / +758m

From info-sr-sender  Mon May 16 19:15:33 1988
Received: by bocklin.arizona.edu; Mon, 16 May 88 19:15:36 MST
Date: 16 May 88 17:54 -0700
From: Stella Atkins <stella%cmpt.sfu.cdn%ean.ubc.ca@RELAY.CS.NET>
To: info-sr@arizona.edu
In-Reply-To: <8805161820.AA01862@megaron.arizona.edu>
Message-Id: <876*stella@cmpt.sfu.cdn>
Subject: Re:  anything happend?
Errors-To: info-sr-errors

At the risk of being facetious, I would say the most surprising thing about SR
is that within 8 hours we had a working system which distributed over 4 SUN-3
machines. Congratulations!


From info-sr-sender  Tue May 17 02:14:14 1988
Received: by bocklin.arizona.edu; Tue, 17 May 88 02:14:17 MST
Date: 17 May 88  0:02 -0700
From: Douglas Bailey <bailey%cmpt.sfu.cdn%ean.ubc.ca@RELAY.CS.NET>
To: info-sr@arizona.edu
Message-Id: <118*bailey@cmpt.sfu.cdn>
Subject: surprises
Errors-To: info-sr-errors

Allright -- the thing I found to be most surprising is the extremely high
cost of communication between different vms (either on the same or different
physical machines).  I ran a simple test, and the *best* results I got
indicated that a vm to vm send required about 100ms.  Is this typical, or
just a result of something strange in our network?

Doug Bailey / Simon Fraser University / Burnaby, B.C. Canada


From info-sr-sender  Tue May 17 06:27:22 1988
Received: by bocklin.arizona.edu; Tue, 17 May 88 06:27:25 MST
Message-Id: <8805171325.AA01371@megaron.arizona.edu>
Date: 17 MAY 88 14:50-
From: KIESEL%DBNINF5.BITNET@CUNYVM.CUNY.EDU
To: INFO-SR@arizona.edu
Subject: Some remarks on SR
Errors-To: info-sr-errors

Date: 17-MAY-1988 14:48:33.73
From: Norbert Kiesel KIESEL AT DBNINF5
To:   0::"info-sr@arizona.edu",KIESEL
Subj: Some remarks on SR
                Hello SR friends,
I'm the one who kicked the first stone (into info-sr :-).  Up to now, I
haven't got the SR compiler, as I'm not on ARPANET and have to wait
for my tape.  But at all, I've some remarks on SR resulting from
reading the TR 86-6c "An Overview of the SR Language and
Implementation":


    1)  Why is the declaration of the resource parameters not a part of
        the specification?  This is much more in the sense of writing
        modular programs as a user of a resource only needs to know
        the specification and not the body for using it, i.e the
        internals would be hidden.

    2)  Was it really a good idea to add the parameter kind "ref" for
        operations called on the same vm?  This breaks transparency
        and must (?) be controlled for every invocation.

There is a typo in the "Dining Philosophers" program: Instances of
"Servant" resources are created with a parameter which isn't specified
in the body of "Servant".

Last not least I have a question to the Saguaro example (in the same
report): Is there a special resaon for counting the number of
processes accessing the same file in "DirectoryMgr" and not in
"FileServer"?


                so long Norbert

P.S.: I'm interested in porting SR to XENIX 3.3 running on Intel
310/12 (we've some of them connected via Ethernet). Does anyone has
got the same idea? NK

From info-sr-sender  Tue May 17 08:36:53 1988
Received: by bocklin.arizona.edu; Tue, 17 May 88 08:36:56 MST
Date: Tue, 17 May 88 08:36:50 MST
From: "Greg Andrews" <greg>
Message-Id: <8805171536.AA20404@paloverde>
To: info-sr
Subject: responses
Errors-To: info-sr-errors

It's nice to see some interest -- and good questions.

Credit for the distribution goes to Gregg Townsend
and Ron Olsson.  I had the sense to stay out of their way.

The inter-vm time is high, due to Unix overhead.
There is also extra overhead on the first use of a new vm
because of the way vm's are managed.
Before too long we should have a native implementation
on top of a kernel (the x-kernel) being developed
here by Larry Peterson and Norm Hutchinson.  Times
should then be quite reasonable, but the distribution
will be less usable since it won't have Unix.  If Mach
eventually supplants Unix, we should be able to get
a much more efficient implementation.

The declaration of resource parameters *is* part of the
spec in the current version of SR.  TR 86-6c, which is
the TOPLAS paper that appeared in January, is not quite
accurate.  We realized the problem shortly after the last
revision to that paper and changed the implementation.
The paper is otherwise pretty accurate though.

Yes, there are dangers associated with using ref parameters --
and pointers too for that matter.  However, we felt that
we should not force inefficient solutions on some problems
just for the sake of purity and transparency.  There are
already a hundred ways the programmer can hang him/herself.

There is indeed a typo in the Dining Philosophers program.
Servant resources should not be created with parameter i.

In the Saguaro example, Directory Managers coordinate File
Server creation/destruction.  Thus they need to know how
many clients are using a file.  If that number were in
the File Server, there could be a race condition if the
last client known to the server closed the file at about
the same time a new client opened it.  In particular, the
File Server could destroy itself at the same time another
client tried to start using it.  The problem is avoided
by the standard technique of using a centralized allocator,
in this case the Directory Manager.

-- Greg

From info-sr-sender  Tue May 17 10:34:12 1988
Received: by bocklin.arizona.edu; Tue, 17 May 88 10:34:15 MST
Date: Tue, 17 May 88 10:34:10 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8805171734.AA13050@megaron.arizona.edu>
To: info-sr
Subject: communication rates
Errors-To: info-sr-errors

It turns out that the number of messages passing between virtual machines
is limited by the granularity of SR's internal clock. This is the
CLOCK_INTERVAL parameter in limits.h.

You can experiment with different values by setting an environment
variable SRCLOCK to a granularity in milliseconds, with the caveat
that your environment variables don't affect remote virtual machines.

The default clock interval is 100 milliseconds.  I just did some
experimentation here and found that by setting it to 10 I could get
200 messages (100 round trips) per second on a vax, or 5ms/message.
Values less than 10 didn't help any.

I'm going to change the default for future releases;  you might wish to do
the same with your versions.  CLOCK_INTERVAL is only referenced in
rts/process.c, so only the runtime system will require a rebuild.

     Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
     +1 602 621 4325      gmt@Arizona.EDU       110 57 16 W / 32 13 45 N / +758m

From @CUNYVM.CUNY.EDU:KIESEL@DBNINF5.BITNET  Thu May 19 09:00:39 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Thu, 19 May 88 09:00:39 MST
Message-Id: <8805191559.AA26230@megaron.arizona.edu>
Received: from [128.228.1.2] by megaron.arizona.edu; Thu, 19 May 88 08:59:15 MST
Received: from DBNINF5.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.1) with BSMTP id 5260; Thu, 19 May 88 11:56:01 EDT
Date: 19 MAY 88 17:12-
From: KIESEL%DBNINF5.BITNET@CUNYVM.CUNY.EDU
To: INFO-SR@arizona.edu
Subject: ?-operator still existing ?

Date: 19-MAY-1988 17:09:40.22
From: Norbert Kiesel KIESEL AT DBNINF5
To:   SR,KIESEL
Subj: ?-operator still existing ?
                        Hello,
I've just a liite question:

Does the ?-operator still exists in SR? If it exists, what's its syntax
and semantics? (I haven't yet the actual reference manual).

                so long Norbert

From greg  Thu May 19 09:08:04 1988
Received: from paloverde.arizona.edu by bocklin.arizona.edu; Thu, 19 May 88 09:08:04 MST
Date: Thu, 19 May 88 09:07:59 MST
From: "Greg Andrews" <greg>
Message-Id: <8805191607.AA04264@paloverde>
Received: by paloverde; Thu, 19 May 88 09:07:59 MST
In-Reply-To: <8805191559.AA26230@megaron.arizona.edu>
To: INFO-SR@arizona.edu, KIESEL%DBNINF5.BITNET@CUNYVM.CUNY.EDU
Subject: Re:  ?-operator still existing ?

Yes, it exists.  Its syntax is

	?operation

where operation is the identity of the operation.

-- Greg

From @CORNELLC.CCS.CORNELL.EDU:KIESEL@DBNINF5.BITNET  Mon May 30 03:54:26 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Mon, 30 May 88 03:54:26 MST
Message-Id: <8805301054.AA17897@megaron.arizona.edu>
Received: from [128.253.7.20] by megaron.arizona.edu; Mon, 30 May 88 03:54:09 MST
Received: from DBNINF5.BITNET by CORNELLC.CCS.CORNELL.EDU ; Mon, 30 May 88 06:28:52 EDT
Date: 30 MAY 88 12:12-
From: KIESEL%DBNINF5.BITNET@CORNELLC.CCS.CORNELL.EDU
To: INFO-SR@arizona.edu
Subject: primes program

Date: 30-MAY-1988 11:33:25.11
From: Norbert Kiesel KIESEL AT DBNINF5
To:   SR,KIESEL
Subj: primes program
                        Hello SR-friends,
following is a (nearly guaranteed faulty :-) little SR program to
calculate some primes. The basic idea is: create some processes,
distribute them over all machines (i.e. encapsulate them resources),
and send them a prime number candidate. Each of the processes builds
up a (disjunct) list of primes against which the new candidate is tested.
If all processes agree about the candidate to be prime, its given to one
of the processes enlarging his prime number list.

The program is not intended to be the fastest prime number searcher, it
should just give an impression how much improvement one can get by writing
distributed solutions for problems. The right test candidate for this
program is the program itself -- with just one local test process.

I've neither the SR compiler nor the current SR language reference manual,
so I can't test or verify my solution. However, if someone is interested
in this problem, (s)he can either modify&try my solution or write another
one. Any responses are wellcome!!!

                so long Norbert

=-=-=-=-=-=-=-=-=- snipp, snipp, snipp -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

resource main(max:int,num:int)
body main
      import pt
      var ptc[1:max]:cap pt

initial
      fa i := 1 to num ->
            ptc[i] := create pt(max)    # on every possible machine
      af
end

final
      fa i := 1 to num
            destroy ptc[i]
      af
end

process loop
      var is_prim_for_me:bool
      var turn:int := 1
      var vote:int

      fa i := 2 to max st i=2 | i=3 | i=5 | (i>6 & ((i-1)%6=0 | (i-5)%6=0)) ->
            vote := 0
            co (j := 1 to num) ->
                  ptc[j].guess(i,is_prim_for_me) ->
                        if is_prim_for_me ->
                              vote++
                              if vote=num ->
                                    ptc[turn].take(i)
                                    turn := (turn%num) + 1
                                    write(i," ")
                                    exit
                              [] else ->
                                    next
                              fi
                        [] else ->
                              exit
                        fi
            oc
      af
end



resource pt(max:int)

      op guess(val n:int; res pfm:bool) {call}
      op take(val n:int) {call}

body pt

process test
      var primes[1:max]:int
      var last:int := 0

      do true ->
            in guess(n,pfm) ->
                  fa i := 1 to last ->
                        if (n%primes[i] = 0 or ?guess > 0) ->
                              pfm := false
                              return
                        fi
                  af
                  pfm := true
            [] take(n) ->
                  last++
                  primes[last] := n
            ni
      od
end

=-=-=-=-=-=-=-=-=-=- snipp, snipp, snipp -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

P.S.: I've called for a SR compiler using the order form. As my university
isn't very happy about sending money without a bill, I've called for
a purchase-order processing. Some days ago I've got my order back with
a letter saying that there was no payment enclosed and so my order has not
been processed. So what's about purchase-order processing? Have I misunderstood
anything? NK

From gmt  Thu Jun 23 16:41:41 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Thu, 23 Jun 88 16:41:41 MST
Date: Thu, 23 Jun 88 16:41:39 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8806232341.AA16943@megaron.arizona.edu>
Received: by megaron.arizona.edu; Thu, 23 Jun 88 16:41:39 MST
To: info-sr
Subject: troff formatter for SR

Several people have worked on vgrind definitions for SR.  I've incorporated
those along with some ideas of my own in the program below.  It's a shell
script that calls vgrind, plus a man page.  This has been tested on a Vax
(4.3BSD) and a Sun (SunOS 3.4).

     Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
     +1 602 621 4325      gmt@Arizona.EDU       110 57 16 W / 32 13 45 N / +758m


# To unbundle, sh this file
echo unbundling srgrind.1 1>&2
cat >srgrind.1 <<'AlBeRtEiNsTeIn'
.TH SRGRIND 1 "22 June 1988" "University of Arizona"
.SH NAME
srgrind \- format SR program for troff
.SH SYNOPSIS
\fBsrgrind [\-f] [\-n] [\-w] [\-x] [\-d \fIdefs\fP] \
[\-h \fIheader\fP] [\-s \fIsize\fP] [\fRfile ...\fP]
.br
.SH DESCRIPTION
.LP
.I Srgrind
formats an SR program for typesetting by
.IR troff (1).
.I Srgind
is a front end to
.IR vgrind (1).
.LP
Input is read from the named files, or from standard input if none are given.
The
.I troff
directives are written to standard output.
.LP
.I Srgrind
accepts the following options:
.TP 11
.BI \-d " defs"
Use an alternate
.IR vgrindefs (5)
file instead of the default one inside
.I srgrind.
.TP
.BI \-f
Run in filter mode. 
In this mode,
.I srgrind
passes most input untouched, processing only those lines
delimited by
.B .vS
and
.B .vE
macro calls.
.TP
.BI \-h " header"
Place a header at the top of the page.
.TP
.BI \-n
Don't embolden keywords.
.TP
.BI \-s " size"
Set the pointsize for typesetting.
.TP
.BI \-w
Consider tabs to be spaced every four columns instead of every eight
(Sun only).
.TP
.BI \-x
Pass
.B \-x
to
.I vgrind
for index processing.
.SH SEE ALSO
.LP
sr(1), troff(1), vgrind(1), vgrindefs(5), srtex(1)
.SH CAVEATS
.LP
.I Srgrind
is limited by the capabilities of
.IR vgrind .
For example, comments of the form /*...*/ do not nest.
.LP
.I Vgrind
macros can conflict with others when using filter mode.
AlBeRtEiNsTeIn
echo unbundling srgrind 1>&2
cat >srgrind <<'AlBeRtEiNsTeIn'
#!/bin/sh
#
#   format an SR file for troff using vgrind's back end

#   This script calls the undocumented "vfontedpr" directly because
#   /usr/ucb/vgrind is badly (& differently) broken on both Vax (4.3 Mt Xinu)
#   and Sun (3.5); for example, try a  simple "TROFF=cat vgrind foo.c".

#   Note that we allow "-s 12" and "-dfile" as well as the "-s12" and "-d file"
#   forms vgrind insists on; but we still don't allow "-fn" for "-f -n".

#   vgrindefs below are based on efforts of Roger Hayes, Doug Cook, Ron Olsson.

USAGE="[-f] [-n] [-w] [-x] [-s size] [-d defs] [-h header] [file...]"

VFPATH="/usr/lib/vfontedpr"
VGMACS="/usr/lib/tmac/tmac.vgrind"

TEMP=/tmp/srg.$$

# copy default vgrindefs(5) to a temp file
#
# strings don't really end at EOL, but we'll say they do to help
# resynchronize things if vgrind gets confused

trap "rm -f $TEMP" 0 1 2 15
cat >$TEMP <<"==END=="
sr|SR:\
	:pb=\d(((proc(ess?))|resource|global)\d\p(\d|\())|(body\d\p\d?(/|#|$)):\
	:bb=\d(if|fa|do|co|in|initial|final)\d:\
	:be=\d(fi|af|od|oc|ni|end)\d:\
	:cb=#:ce=$:\
	:ab=/*:ae=*/:\
	:sb=":se=(\e"|$):\
	:lb=':le=(\e'|$):\
	:kw=af and any body bool by call cap char co const create destroy do \
	downto else end enum EOF exit extend external fa false fi file final \
	global if import in initial int new next ni noop not null oc od on op \
	optype or proc process ptr rec receive ref reply res resource return \
	rn returns send separate skip st stop string to true type val var xor:
==END==


# process command options

DEFS=$TEMP
OPTIONS=
for i
do
    case $i in
	-[fnx])
	    OPTIONS="$OPTIONS $i"
	    shift;;
	-w)
	    OPTIONS="$OPTIONS -t"
	    shift;;
	-s)
	    shift
	    test $# '=' 0 && echo "$0: $i requires a value" 1>&2 && exit 1
	    OPTIONS="$OPTIONS -s$1"
	    shift;;
	-s?*)
	    OPTIONS="$OPTIONS $i"
	    shift;;
	-d)
	    shift
	    test $# '=' 0 && echo "$0: $i requires a value" 1>&2 && exit 1
	    DEFS="$1"
	    shift;;
	-d?*)
	    val=`echo $i | sed 's/..//'`
	    OPTIONS="$OPTIONS -d $val"
	    shift;;
	-h)
	    shift
	    test $# '=' 0 && echo "$0: $i requires a value" 1>&2 && exit 1
	    OPTIONS="$OPTIONS -h '$1'"
	    shift;;
	-h?*)
	    val=`echo "$i" | sed 's/..//'`
	    OPTIONS="$OPTIONS -h '$val'"
	    shift;;
	--)
	    shift
	    break;;

	-*)
	    echo "usage: $0 $USAGE" 1>&2
	    exit 1;;
	*)
	    break;;
	esac
    done


# turn a null file list into "-" for the back end

case $# in
    0)	FILES="-";  break;;
    *)	FILES="$@"; break;;
    esac


# insert a call for the macros, and then call the back end
# "eval" is used to get quoting right (e.g. "srgrind -h 'tricky header')

echo ".so $VGMACS"
eval $VFPATH -lsr -d $DEFS $OPTIONS $FILES
exit
AlBeRtEiNsTeIn
chmod +x srgrind

From cook@iris.ucdavis.edu  Thu Jun 23 17:02:49 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Thu, 23 Jun 88 17:02:49 MST
Received: from clover.ucdavis.edu by megaron.arizona.edu; Thu, 23 Jun 88 17:02:37 MST
Received: from iris.ucdavis.edu by clover.ucdavis.edu (5.59/4.7)
	id AA06075; Thu, 23 Jun 88 16:52:36 PDT
Received: by iris.ucdavis.edu (5.51/3.14)
	id AA11612; Thu, 23 Jun 88 16:59:55 PDT
Date: Thu, 23 Jun 88 16:59:55 PDT
From: cook@iris.ucdavis.edu (Doug Cook)
Message-Id: <8806232359.AA11612@iris.ucdavis.edu>
To: info-sr@arizona.edu
Subject: X windows interface for SR
Cc: cook@iris.ucdavis.edu, olsson@ivy.ucdavis.edu


	I have been working on a (hopefully!) easy-to use, high-level X windows 
interface to the SR language. Essentially what I hope to do is to represent each
SR proc/process or resource as an X-window with its own I/O, scrollbar, buttons,
etc. I'd also like the configuration of a group of windows to be user-defined.
	For example, a hypercube simulator written in SR could, using this 
interface, represent each processor in the network as a window, and the windows 
could be arranged in a hypercube. This would require very little additional
SR code. Additionally, this interface could form part of an SR debugging tool,
since it allows each process to be separately monitored.
	At the moment, I've got a somewhat brain-damaged prototype running
under X 11 release 2, and I'm working on a more flexible version. Before I go
and put a lot of additional work into this, I'd like to know two things:
	1) Is anyone out there working on anything similar?
	2) What would people like to see implemented in such an interface? 

		-Doug

From AJCD@ECSVAX.ED.AC.UK  Mon Jul 11 12:26:04 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Mon, 11 Jul 88 12:26:04 MST
Received: from rvax.ccit.arizona.edu by megaron.arizona.edu (5.59/MRM1.4) via SMTP
	id AA23478; Mon, 11 Jul 88 12:26:01 MST
Received: from BITNET-GATEWAY by rvax.ccit.arizona.edu; Mon, 11 Jul 88 12:19 MST
Received: from RL.IB by UKACRL.BITNET (Mailer X1.25) with BSMTP id 7062; Mon,
 11 Jul 88 12:21:15 BST
Date: 11 Jul 88 12:25:29 BST
From: AJCD@ECSVAX.ED.AC.UK
Subject: RTS bind problem on Suns
To: info-sr@arizona.edu
Via:        UK.AC.ED.ECSVAX; 11 JUL 88 12:21:04 BST
Message-Id: <"11-JUL-1988 12:25:30">

   I have just received the SR tape, and installed it on some of our Sun
workstations. When I tried the examples/remote test in the installation
document I got an error -
 
   islay% a.out skye
   trying locally:	0.  pid=2398	host=islay
   trying skye:	1.  pid=3707	host=skye
 
   islay% a.out arran
   trying locally:	0.  pid=2406	host=islay
   trying arran:	[vm 3] RTS abort: bind: Can't assign requested address
   can't create vm on arran
 
   This error only occurs when trying to bind to a virtual machine on
the diskless nodes; between the disk servers it works fine. Has anyone
come across this problem, and how can it be sorted? I think we are running
SunOS 3.2 on these machines.
                                 Thanks,
                                       Angus
 
--
Angus Duggan, Department of Computer Science, University of Edinburgh,
James Clerk Maxwell Building, The King's Buildings, Mayfield Road,
Edinburgh, EH9 3JZ, Scotland, U.K.
JANET:  ajcd@uk.ac.ed.ecsvax  ARPA: ajcd%ed.ecsvax@nss.cs.ucl.ac.uk
USENET: ajcd@ecsvax.ed.ac.uk  UUCP: ...!mcvax!ukc!ed.ecsvax!ajcd
BITNET: ukacrl.earn!ed.ecsvax!ajcd or ajcd%ed.ecsvax@uk.ac

From @RELAY.CS.NET:bailey%cmpt.sfu.cdn@ean.ubc.ca  Tue Jul 12 08:42:43 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Tue, 12 Jul 88 08:42:43 MST
Received: from RELAY.CS.NET by megaron.arizona.edu (5.59/MRM1.4) via SMTP
	id AA21298; Tue, 12 Jul 88 08:42:30 MST
Received: from relay2.cs.net by RELAY.CS.NET id ac13042; 12 Jul 88 10:54 EDT
Received: from ubc by RELAY.CS.NET id ac17405; 12 Jul 88 10:45 EDT
Received: by ean.ubc.ca id AA00425; Mon, 11 Jul 88 22:35:17 pdt
Date: 11 Jul 88 22:33 -0700
From: Douglas Bailey <bailey%cmpt.sfu.cdn%ean.ubc.ca@RELAY.CS.NET>
To: info-sr@arizona.edu
Message-Id: <166*bailey@cmpt.sfu.cdn>
Subject: Bind error

I did have similar problems.  I was running distributed programs
on a LAN with several Sun-3's (BSD Unix 3.2).  Particular Sun-3's
could not be used because of the problem you described.  This was
not a problem with SR, however, but rather with Unix.  My supervisor
wrote a C program that had the same problem (hers was one of the
machines which could not be used in a distributed program).  Our
system operator messed around for a while and eventually fixed it,
but I believe he said something to the effect that he did not know
what it was that he did to fix it.  Stella: what did Honman say,
precisely?

Doug Bailey


From olsson@ivy.ucdavis.edu  Tue Jul 12 12:57:09 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Tue, 12 Jul 88 12:57:09 MST
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59/MRM1.4) via SMTP
	id AA09415; Tue, 12 Jul 88 12:57:01 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/4.7)
	id AA29166; Tue, 12 Jul 88 12:45:27 PDT
Received: by ivy.ucdavis.edu (3.2/3.14)
	id AA18653; Tue, 12 Jul 88 12:54:25 PDT
Date: Tue, 12 Jul 88 12:54:25 PDT
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8807121954.AA18653@ivy.ucdavis.edu>
To: info-sr@arizona.edu
In-Reply-To: AJCD@ECSVAX.ED.AC.UK's message of 11 Jul 88 12:25:29 BST <"11-JUL-1988 12:25:30">
Subject: RTS bind problem on Suns

   Date: 11 Jul 88 12:25:29 BST
   From: AJCD@ECSVAX.ED.AC.UK

      I have just received the SR tape, and installed it on some of our Sun
   workstations. When I tried the examples/remote test in the installation
   document I got an error -
   ...
      This error only occurs when trying to bind to a virtual machine on
   the diskless nodes; between the disk servers it works fine. Has anyone
   come across this problem, and how can it be sorted? I think we are running
   SunOS 3.2 on these machines.

Sorry to say that Gregg Townsend -- who would most likely be able to
help you with this problem -- is on vacation for a few weeks.  Doug
Bailey's message suggests that the problem is UNIX's not SR's; I hope
he can provide the details to resolve this problem.


From @RELAY.CS.NET:stella%cmpt.sfu.cdn@ean.ubc.ca  Tue Jul 12 21:05:48 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Tue, 12 Jul 88 21:05:48 MST
Received: from RELAY.CS.NET by megaron.arizona.edu (5.59/MRM1.4) via SMTP
	id AA13353; Tue, 12 Jul 88 21:05:40 MST
Received: from relay2.cs.net by RELAY.CS.NET id ab22619; 12 Jul 88 23:44 EDT
Received: from ubc by RELAY.CS.NET id af22248; 12 Jul 88 23:36 EDT
Received: by ean.ubc.ca id AA00412; Tue, 12 Jul 88 18:00:11 pdt
Date: 12 Jul 88 17:56 -0700
From: Stella Atkins <stella%cmpt.sfu.cdn%ean.ubc.ca@RELAY.CS.NET>
To: info-sr@arizona.edu
Message-Id: <1070*stella@cmpt.sfu.cdn>
Subject: Bind error -- solution!!

I amiled a direct reply to angus, but thought the group might be interested too.
Here is the magic solution.
Stella Atkins
stella@cmpt.sfu.cdn


==================
The problem concerns the binding between the network address to
 the link address. The manual page on ifconfig(8) indicates that
the binding is turned on by default. Somehow something has turned off the
binding. 

Solution: execute the following command as root:

	/etc/ifconfig ethernet-interface hostname arp

eg if you have a SUN-3/50 and the hostname is star, then you should execute:
	/etc/ifconfig le0 star arp

Magic!!
It took me 2 weeks to discover this. I hope you can use this info to fix
your problem.



From @RELAY.CS.NET:bawtree%cmpt.sfu.cdn@ean.ubc.ca  Thu Jul 21 16:41:03 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Thu, 21 Jul 88 16:41:03 MST
Received: from RELAY.CS.NET by megaron.arizona.edu (5.59-1.5) via SMTP
	id AA15075; Thu, 21 Jul 88 16:39:25 MST
Received: from relay2.cs.net by RELAY.CS.NET id aa28761; 21 Jul 88 18:00 EDT
Received: from ubc by RELAY.CS.NET id ac03580; 21 Jul 88 17:40 EDT
Received: by ean.ubc.ca id AA11705; Thu, 21 Jul 88 13:47:44 pdt
Date: 21 Jul 88 13:36 -0700
From: Hugh Bawtree <bawtree%cmpt.sfu.cdn%ean.ubc.ca@RELAY.CS.NET>
To: info-sr@arizona.edu
Mmdf-Warning:  Parse error in original version of preceding line at RELAY.CS.NET
Message-Id: <4*bawtree@cmpt.sfu.cdn>
Subject: SR on non-UNIX opsys

I just joined the info-sr group, so I am quite ignorant of the current
development of SR.  I am hoping to implement SR on the V-system
for my M Sc thesis at Simon Fraser University, Burnaby, BC, Canada.
Some of you must know my supervisor: Stella Atkins.

Is anyone else implementing SR on non-UNIX systems?  If so, what
kind of problems are you running into?  I hope a V-system
implementation can use a large portion of the code written for
the UNIX implementation of SR but I have found the following
changes must be made:

	a) Replace the socket module in the RTS with the V-system
	communication primitives.

	b) Replace the UNIX system calls scattered throughout the
	code with the appropriate V system calls.  In many cases,
	this by itself would not be difficult.  However, I would
	like to do it in a consistent manner.  For instance, I
	could replace all the UNIX system calls with C macros
	which compile to the appropriate system call based on the
	operating system.  But, if I do it this way then all the
	system calls should be programmed this way.  Has anyone
	thought about this problem?  I think it is almost 
	impossible to do in a general way that applies to all OS.

	c) Replace the use of varargs system calls (va_alist,
	va_dcl, etc) since V-system does not seem to have an
	equivalent group of system calls to handle variable
	argument lists.

I would appreciate any comments you have on this project.  Even
if your advice is 'Give it up!'

		Hugh Bawtree
		bawtree@cmpt.sfu.cdn


From olsson@ivy.ucdavis.edu  Sat Jul 30 12:18:08 1988
Received: from megaron.arizona.edu by bocklin.arizona.edu; Sat, 30 Jul 88 12:18:08 MST
Received: from clover.ucdavis.edu by megaron.arizona.edu (5.59-1.5) via SMTP
	id AA29729; Sat, 30 Jul 88 12:17:58 MST
Received: from ivy.ucdavis.edu by clover.ucdavis.edu (5.59/4.7)
	id AA28777; Sat, 30 Jul 88 12:16:48 PDT
Received: by ivy.ucdavis.edu (3.2/3.14)
	id AA21663; Sat, 30 Jul 88 12:15:17 PDT
Date: Sat, 30 Jul 88 12:15:17 PDT
From: olsson@ivy.ucdavis.edu (Ron Olsson)
Message-Id: <8807301915.AA21663@ivy.ucdavis.edu>
To: info-sr@arizona.edu
In-Reply-To: Hugh Bawtree's message of 21 Jul 88 13:36 -0700 <4*bawtree@cmpt.sfu.cdn>
Subject: SR on non-UNIX opsys

   Date: 21 Jul 88 13:36 -0700
   From: Hugh Bawtree <bawtree%cmpt.sfu.cdn%ean.ubc.ca@RELAY.CS.NET>

   I just joined the info-sr group, so I am quite ignorant of the current
   development of SR.  I am hoping to implement SR on the V-system
   for my M Sc thesis at Simon Fraser University, Burnaby, BC, Canada.
   Some of you must know my supervisor: Stella Atkins.

   Is anyone else implementing SR on non-UNIX systems?  If so, what
   kind of problems are you running into?  I hope a V-system
   implementation can use a large portion of the code written for
   the UNIX implementation of SR but I have found the following
   changes must be made:

	   a) Replace the socket module in the RTS with the V-system
	   communication primitives.

	   b) Replace the UNIX system calls scattered throughout the
	   code with the appropriate V system calls.  In many cases,
	   this by itself would not be difficult.  However, I would
	   like to do it in a consistent manner.  For instance, I
	   could replace all the UNIX system calls with C macros
	   which compile to the appropriate system call based on the
	   operating system.  But, if I do it this way then all the
	   system calls should be programmed this way.  Has anyone
	   thought about this problem?  I think it is almost 
	   impossible to do in a general way that applies to all OS.

	   c) Replace the use of varargs system calls (va_alist,
	   va_dcl, etc) since V-system does not seem to have an
	   equivalent group of system calls to handle variable
	   argument lists.

   I would appreciate any comments you have on this project.  Even
   if your advice is 'Give it up!'

		   Hugh Bawtree
		   bawtree@cmpt.sfu.cdn

Since no one else (apparently) has answered, I guess I'll give it a
try.  Irv Elshoff (irv@arizona.edu) redid SR's RTS using V in summer
1986.  However, he ended up abandoning that project -- seems like SR's
requirements and V's functionality did not mesh well.  You might ask
him for the details.  Stella might recall some of the specifics too.

From gmt  Tue Aug 16 17:20:15 1988
Date: Tue, 16 Aug 88 17:20:15 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8808170020.AA15146@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.6/7)
	id AA15146; Tue, 16 Aug 88 17:20:15 MST
To: info-sr
Subject: distributed dining philosophers

Several people have pointed out that the "distributed dining philosophers"
program presented in the SR Overview paper doesn't compile.  That is because
it was written for a slightly older version of the language.  Here's a
corrected version.

     Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
     +1 602 621 4325      gmt@Arizona.EDU       110 57 16 W / 32 13 45 N / +758m

---------------------------- cut here -------------------------------------
##  Distributed Dining Philosophers
#
#   Based on the example in "An Overview of the SR Language and Implementation",
#   by Greg Andrews, Ron Olsson, and a cast of thousands, in the January, 1988
#   issue of TOPLAS (ACM Transactions on Programming Languages and Systems 10,1,
#   51-86).
#
#   The algorithm is from Chandy and Misra's "Drinking Philosophers Problem",
#   which appeared in the October, 1984, issue of TOPLAS (6,4, 632-646).
#
#   usage:  a.out n s	(for n philosophers and s sessions)



#   Abstract operations define two types of servant operations.

resource PhilosopherOps		# services provided to the philosopher
    op getforks()  {call}
    op relforks()
end

resource ServantOps		# messages exchanged among servants
    op needL()	{send}		# requests for a fork
    op needR()	{send}
    op passL()	{send}		# passing a fork to a neighbor
    op passR()	{send}
end



#   Servants do all the work.  There's one for each philosopher.

resource Servant
    extend PhilosopherOps, ServantOps
    op links(l,r : cap ServantOps)			# init neighbor links
    op forks(haveL, dirtyL, haveR, dirtyR : bool)	# init fork values

body Servant(id : int)
    var l, r : cap ServantOps
    var haveL, dirtyL, haveR, dirtyR : bool
    op hungry()	{send}
    op eat()	{send}

    proc getforks()
	write("philosopher", id, "is hungry")
	send hungry()     # let server know philosopher is hungry
	receive eat()     # wait for permission to eat
    end

    process server
	receive links(l,r)
	receive forks(haveL,dirtyL,haveR,dirtyR)
	write("servant",id,"is executing")
    	do true->
	    in hungry() ->
		# ask for forks I do not have -- note: I ask my right
		# neighbor for his left fork, and my left neighbor for
		# his right fork
		    if ~haveR -> send r.needL() fi
		    if ~haveL -> send l.needR() fi
		# wait until I have both forks
		    do ~(haveL & haveR) ->
			in passL() -> haveL := true; dirtyL := false
			[] passR() -> haveR := true; dirtyR := false
			[] needR() & dirtyR ->
				haveR := false; dirtyR := false
				send r.passL()
			[] needL() & dirtyL ->
				haveL := false; dirtyL := false
				send l.passR()
			ni
		    od
		# let my philosopher eat; wait for him to finish
		    send eat(); dirtyL := true; dirtyR := true
		    receive relforks()
	    [] needR() ->   
		# right neighbor needs his left fork, which is my right fork
		    haveR := false; dirtyR := false
		    send r.passL()
	    [] needL() ->
		# left neighbor needs his right fork, which is my left fork
		    haveL := false; dirtyL := false
		    send l.passR()
	    ni
	od
    end server

end Servant



#  The Philosopher resource is simple.

resource Philosopher
    import PhilosopherOps

body Philosopher(myservant : cap PhilosopherOps; id, t : int)
    process phil
	fa i := 1 to t ->
	    myservant.getforks()
	    write("philosopher",id,"is eating")		# eat
	    myservant.relforks()
	    write("philosopher",id,"is thinking")	# think
	af
    end

end Philosopher




#  The main resource starts everything up.

resource Main
    import Philosopher, PhilosopherOps, ServantOps, Servant

body Main()
    initial
	var n := 5
	var t := 3
	getarg(1,n)	# get number of philosophers, if specified
	getarg(2,t)	# get session count, if specified
	
  	var s[1:n]  : cap Servant
  	var si[1:n] : cap ServantOps
	var pi[1:n] : cap PhilosopherOps
	var p[1:n]  : cap Philosopher

	# create each servant and philosopher
  	  fa i := 1 to n ->
	    s[i] := create Servant(i)
	    si[i].needL := s[i].needL		# build ServantOp cap
	    si[i].needR := s[i].needR
	    si[i].passL := s[i].passL
	    si[i].passR := s[i].passR
	    pi[i].getforks := s[i].getforks	# build PhilosopherOp cap
	    pi[i].relforks := s[i].relforks
	    p[i] := create Philosopher(pi[i],i,t)
	  af
	# give each Servant its links to neighboring Servants
	  send s[1].links(si[n],si[2])
          fa i := 2 to n-1 -> send s[i].links(si[i-1],si[i+1]) af
	  send s[n].links(si[n-1],si[1])
	# initialize each Servant's forks
	#   note:  this must be asymmetric or deadlock could result
	send s[1].forks(true,false,true,false)
	fa i := 2 to n-1 ->  send s[i].forks(false,false,true,false) af
	send s[n].forks(false,false,false,false)
    end

end Main

From gmt  Wed Sep 21 17:11:52 1988
Date: Wed, 21 Sep 88 17:11:52 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8809220011.AA03886@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/12)
	id AA03886; Wed, 21 Sep 88 17:11:52 MST
To: info-sr
Subject: Code for SR on an HP 9000s800

We've just received a copy of the code needed to run SR under HP-UX
on a Hewlett-Packard HP9000s800 (or presumably on others of similar
architecture).

We hope to integrate this code into a future release of SR, but if you
can't wait...

I've put a copy of the code in the "sr" subdirectory of the anonymous FTP
area on Arizona.EDU (128.196.6.1 or 192.12.69.1).  It's a little big to send
to the whole mailing list, but if you need it and can't FTP I can send
individual copies.

    Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
    +1 602 621 4325      gmt@Arizona.EDU       110 57 16 W / 32 13 45 N / +758m

From gmt  Fri Dec 30 16:00:30 1988
Date: Fri, 30 Dec 88 16:00:30 MST
From: "Gregg Townsend" <gmt>
Message-Id: <8812302300.AA10210@megaron.arizona.edu>
Received: by megaron.arizona.edu (5.59-1.7/15)
	id AA10210; Fri, 30 Dec 88 16:00:30 MST
To: info-sr
Subject: sr-mode for GNU Emacs

David Jacobson of Hewlett-Packard has contributed this sr-mode package
for use with GNU Emacs:



;; This is sr-mode for GNU EMACS.  It provides a mode for editing sr programs.
;; Author: David Jacobson  (jacobson@hplabs.hp.com).
;; 
;; Copyright (c) 1988 Hewlett-Packard Company, all rights reserved.
;; 
;;                             LEGAL NOTICE
;; 
;; This sr-mode package is experimental and HP shall have no obligation to
;; maintain or support it.  HP makes no express or implied warranty of any
;; kind with respect to this software, and HP shall not be liable for any
;; direct, indirect, special, incidental or consequential damages (whether
;; based on contract, tort or any other legal theory) arising in any way from
;; use of the software.
;; 
;; Everyone is granted permission to copy, modify and redistribute this
;; sr-mode package, provided:
;;  1.  All copies contain this copyright notice.
;;  2.  All modified copies shall carry a prominant notice stating who
;;      made the last modification and the date of such modification.
;;  3.  No charge is made for this software or works derived from it.  
;;      This clause shall not be construed as constraining other software
;;      distributed on the same medium as this software, nor is a
;;      distribution fee considered a charge.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;      Original distribution, David Jacobson, Dec. 30, 1988
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defconst demo-emacs-sr-bug nil
  "*Set to t to demo the match-beginning bug in emacs.")

(defconst sr-paren-indent 1
  "*extra indent added in sr mode for every level
   of paren nesting.")

(defconst sr-block-indent 3
  "*indent for inner part of most sr constructs that
   contains other statements")

(defconst sr-guard-indent 5
  "*indent for inner part of sr guarded commands")

(defconst sr-break-indent  6
  "*Extra indent to indent unfinished statements in sr mode.")

(defvar sr-break-symbols '("(;," "(,")
  "*If the symbols \";\", \",\", or \"(\" appear at the end of a line, the
following line is (usually) considered broken only if the symbol is a 
character in the car of sr-break-symbols.  
\\[cycle-sr-break-symbols] will cycle the list to the left.")

(defvar sr-neg-paren-indent nil)
(defvar sr-neg-block-indent nil)
(defvar sr-neg-guard-indent nil)

(defun sr-internal-setup ()
  "Called to set dependent data structures from advertized ones."
  (setq sr-neg-paren-indent (- 0 sr-paren-indent))
  (setq sr-neg-block-indent (- 0 sr-block-indent))
  (setq sr-neg-guard-indent (- 0 sr-guard-indent)))

(defvar sr-mode-map nil
  "Keymap used in sr mode.")

(defvar sr-mode-abbrev-table nil
  "Abbrev table in use in sr-mode buffers.")
(define-abbrev-table 'sr-mode-abbrev-table ())

(if sr-mode-map
    ()
  (setq sr-mode-map (make-sparse-keymap))
  (define-key sr-mode-map "\177" 'backward-delete-char-untabify)
  (define-key sr-mode-map "\t" 'sr-indent-line)
  (define-key sr-mode-map "\e\C-\\" 'sr-indent-region)
  (define-key sr-mode-map "\C-c\C-i" 'sr-indent-buffer)
  (define-key sr-mode-map "\C-j" 'sr-indent-newline-and-indent)
  (define-key sr-mode-map "\C-c;" 'cycle-sr-break-symbols)
)


(defvar sr-mode-syntax-table nil
  "Syntax table used in sr-mode buffers.")

(if sr-mode-syntax-table
    ()
  (setq sr-mode-syntax-table (make-syntax-table))
  (modify-syntax-entry ?_  "w"  sr-mode-syntax-table)
  (modify-syntax-entry ?\\ "\\" sr-mode-syntax-table)
  (modify-syntax-entry ?# "<" sr-mode-syntax-table)
  (modify-syntax-entry ?\n ">" sr-mode-syntax-table)
  (modify-syntax-entry ?+ "." sr-mode-syntax-table)
  (modify-syntax-entry ?- "." sr-mode-syntax-table)
  (modify-syntax-entry ?= "." sr-mode-syntax-table)
  (modify-syntax-entry ?* "." sr-mode-syntax-table)
  (modify-syntax-entry ?/ "." sr-mode-syntax-table)
  (modify-syntax-entry ?% "." sr-mode-syntax-table)
  (modify-syntax-entry ?< "." sr-mode-syntax-table)
  (modify-syntax-entry ?> "." sr-mode-syntax-table)
  (modify-syntax-entry ?& "." sr-mode-syntax-table)
  (modify-syntax-entry ?| "." sr-mode-syntax-table)
  (modify-syntax-entry ?\' "\"" sr-mode-syntax-table)
  (modify-syntax-entry ?\' "\'" sr-mode-syntax-table)
  ; I wish Gnu could know that " matched " and ' matched '.
)

(defconst sr-obarray (make-vector 127 nil)
  "A obarray for the sr symbols.
Not using the regular obarray prevents interference from anyone
else trying the same trick.")

(defvar sr-symbol-RE nil
  "A pattern to recognize symbols in sr.")

(defun setup-sr-symbols (symbol &optional beginner ender pre-indent 
				post-indent)
  "Sets SYMBOL (as string) to have BEGINNER, ENDER, PRE-INDENT,
   and POST-INDENT properties.  See source code for big comment."

; Many symbols are interned under their actual character representation,
; even though it is not normal lisp syntax, using the intern function.
; These symbols then have property lists to help sr-mode parse and
; indent. If the beginner property is 'absolute, the symbol will be indented
; with respect to the left margin instead of the previous line.  
; If beginner is 'always.  This symbol cannot begin a statement so always 
; add extra indent if it does.  If beginner is 'never or 'absolute, do not 
; add extra indent.  If the ender property is 'always, a line ending in this
; symbol cannot be the end of a statement, so always add extra indent.  If
; the ender property is 'never, a statement ending in this symbol is always
; complete, so never add extra indent to the next statement.  When the ender
; is 'special, it is equivalent to 'always if the symbol is a character in
; the car of sr-break-symbols otherwise it is equivalent to nil.
; The pre-indent and post-indent will be evaluated when indenting is done, so 
; 'sr-guard-indent we become the value of sr-guard-indent.  Those names
; are so long that an abbreviation is used g=> guard, b=>block, p=>paren, 
; these are prefixed with + or - in an obvious way.
; Conceptually the indent algorithm keeps a running indent, adding each
; symbol's pre-indent property, if it the first in a line, indenting to that
; distance, then adding post-indent.
  (let ((sym (intern symbol sr-obarray))
	(tr-alist '((+b sr-block-indent)
		    (-b sr-neg-block-indent)
		    (+g sr-guard-indent)
		    (-g sr-neg-guard-indent)
		    (+p sr-paren-indent)
		    (-p sr-neg-paren-indent))))
    (if beginner (put sym 'beginner beginner))
    (if ender (put sym 'ender ender))
    (if (and (> (length symbol) 1)
	     (not (eq (char-syntax (string-to-char symbol))  ?w)))
	(if (null sr-symbol-RE)
	    (setq sr-symbol-RE (regexp-quote symbol))
	  (setq sr-symbol-RE (concat sr-symbol-RE "\\|" (regexp-quote symbol)))))
    (if post-indent (put sym 'post-indent
			 (or (car (cdr (assq post-indent tr-alist))) post-indent)))
    (if pre-indent (put sym 'pre-indent
			(or (car (cdr (assq pre-indent tr-alist))) pre-indent)))))

(setq sr-symbol-RE nil)

(setup-sr-symbols "global"   'absolute 'never   0    '+b)  ; should be followed by ident
(setup-sr-symbols "end"      'never    nil      '-b  0)    ; may be followed by ident
(setup-sr-symbols "resource" 'absolute 'always  0    '+b)  ; should be followed by ident
(setup-sr-symbols "body"     'absolute 'always  0    '+b)  ; should be followed by ident
(setup-sr-symbols "proc"     'absolute 'always  '+b  '+b)  ; should be followed by ident
(setup-sr-symbols "process"  'absolute 'always  '+b  '+b)  ; should be followed by ident
(setup-sr-symbols "import"   'never    'always  0    0)    ; should be followed list
(setup-sr-symbols "extend"   'absolute 'always  '+b  0)
(setup-sr-symbols "initial"  'absolute 'never   '+b  '+b)
(setup-sr-symbols "final"    'absolute 'never   '+b  '+b)
(setup-sr-symbols "if"       'never    'always  0    '+g)  ; should be followed by expression
(setup-sr-symbols "->"       'always   'never   0    0)    ; should be followd by block, which we should not indent
(setup-sr-symbols "st"       'always   'always)
(setup-sr-symbols "[]"       'never    'always  '-g  '+g)  ; should be followed by expression
(setup-sr-symbols "else"     'always   'always)
(setup-sr-symbols "fi"       'never    'never   '-g  0)    ; always ends statement
(setup-sr-symbols "do"       'never    'always  0    '+g)  ; should be followed by expression
(setup-sr-symbols "od"       'never    'never   '-g  0)    ; always ends statement
(setup-sr-symbols "fa"       'never    'always  0    '+b)  ; should be followed by quantifiers
(setup-sr-symbols "af"       'never    'never   '-b  0)    ; always ends statement
(setup-sr-symbols "co"       'never    nil      0    '+b)  ; can be followed by interaction quantifier
(setup-sr-symbols "//"       'never    'never   '-b  '+b)
(setup-sr-symbols "oc"       'never    'never   '-b  0)    ; always ends statement
(setup-sr-symbols "in"       'never    'always  0    '+g)  ; must match []
(setup-sr-symbols "ni"       'never    'never   '-g  0)
(setup-sr-symbols "("        'always   'special 0    '+p)  
(setup-sr-symbols ")"        'always   nil      '-p  0)
(setup-sr-symbols "["        'always   'always  0    '+p)
(setup-sr-symbols "]"        'always   nil      '-p  0)
(setup-sr-symbols "{"        'always   'always  0    '+p)
(setup-sr-symbols "}"        'always   nil      '-p  0)
(setup-sr-symbols "stop"     'never    nil)           ; can be followed by expression
						      ; This can not work exactly right, since
						      ; we can not tell difference between beg. of expr. and
						      ; beg. of stmt.
(setup-sr-symbols "skip"     'never    'never)
(setup-sr-symbols "exit"     'never    'never)
(setup-sr-symbols "next"     'never    'never)
(setup-sr-symbols "++"       'always   'never)
(setup-sr-symbols "--"       'always   'never)
(setup-sr-symbols ":=:"      'always   'always) ; put before := to avoid a bug in regexp searching
(setup-sr-symbols ":="       'always   'always)
(setup-sr-symbols ">"        'always   'always)
(setup-sr-symbols ">="       'always   'always)
(setup-sr-symbols "<"        'always   'always)
(setup-sr-symbols "<="       'always   'always)
(setup-sr-symbols "="        'always   'always)
(setup-sr-symbols "!="       'always   'always)
(setup-sr-symbols "~="       'always   'always)
(setup-sr-symbols "."        'always   'always) ; may change when floats are added
(setup-sr-symbols ":"        'always   'always)
(setup-sr-symbols ";"        'always   'special)
(setup-sr-symbols "||"       'always   'always)
(setup-sr-symbols "<<"       'always   'always)
(setup-sr-symbols ">>"       'always   'always)
(setup-sr-symbols "@"        'always   'always)
(setup-sr-symbols "+"        'always   'always)
(setup-sr-symbols "-"        'always   'always)
(setup-sr-symbols "~"        'always   'always)
(setup-sr-symbols "?"        'always   'always)
(setup-sr-symbols "*"        'always   'always)
(setup-sr-symbols "/"        'always   'always)
(setup-sr-symbols "%"        'always   'always)
(setup-sr-symbols "not"      'always   'always)
(setup-sr-symbols ","        'always   'special)
(setup-sr-symbols "and"      'always   'always)
(setup-sr-symbols "&"        'always   'always)
(setup-sr-symbols "or"       'always   'always)
(setup-sr-symbols "|"        'always   'always)
(setup-sr-symbols "xor"      'always   'always)
(setup-sr-symbols "on"       'always   'always)
(setup-sr-symbols "destroy"  'never    'always)
(setup-sr-symbols "create"   'never    'always)
(setup-sr-symbols "receive"  'never    'always)
(setup-sr-symbols "send"     'never    'always)
(setup-sr-symbols "reply"    'never    'never)
(setup-sr-symbols "return"   'never    'never)
(setup-sr-symbols "ref"      'always   'always)
(setup-sr-symbols "res"      'always   'always)
(setup-sr-symbols "const"    'never    'always)       ; should be followed by ident
;(setup-sr-symbols "bool"     nil       nil)      
;(setup-sr-symbols "char"     nil       nil)
;(setup-sr-symbols "int"      nil       nil)
(setup-sr-symbols "string"   nil       'always)       ; must be followed by (len)
(setup-sr-symbols "enum"     'always   'always)
(setup-sr-symbols "type"     'never    'always)       ; should be followed by ident
(setup-sr-symbols "var"      'nil      'always)	      ; var is wierd, since it is both 
					              ; used to declare variables and
						      ; as a parameter mode
(setup-sr-symbols "optype"   'never    'always)       ; should be followed by ident
(setup-sr-symbols "op"       'absolute 'always '+b  0); should be followed by ident
(setup-sr-symbols "external" 'absolute 'always '+b  0); just like op
(setup-sr-symbols "returns"  'always   'always)
(setup-sr-symbols "\"\""     'always   nil)           ; Does not appear in real sr.
(setup-sr-symbols "by"       'always   'always)
(setup-sr-symbols "call"     'never    'always)
(setup-sr-symbols "cap"      'always   'always)
(setup-sr-symbols "to"       'always   'always)
(setup-sr-symbols "downto"   'always   'always)

(setq sr-symbol-RE (concat sr-symbol-RE "\\|\\sw+\\|\\S "))
;;; The single character thing must go on the end to avoid a feature
;;; in the RE matcher that causes the first pattern appearing
;;; *in the RE* to be matched.

(defconst sr-symbol-RE-bol (concat "^\\(" sr-symbol-RE "\\)")
  "An RE that matches words, sr-symbols, plus single characters when
   against the left margin.")

(defconst sr-symbol-RE-eol (concat "\\(" sr-symbol-RE "\\)$")
  "An RE that matches words, sr-symbols, plus single characters when
   against the right  margin.")



(defun sr-mode ()
  "Estabishes a mode for editing SR programs.

Use \\[sr-indent-line] to indent a single line.  One or two
    C-u prefixes add or subtract sr-break-indent (when appropriate).
Use \\[newline-and-indent] to go to a new line and position the
    cursor at about the right place.  (LFD is Control-J.) Prefix
    args apply as with \\[sr-indent-line]. 
Use \\[sr-indent-region] to indent region defined by point and mark.
Use \\[sr-indent-buffer] to indent entire buffer.
Use \\[cycle-sr-break-symbols] to cycle between various options
regarding the symbols that, when appearing at the end of a line,
cause the next line to be broken.  In the default configuration, 
this toggles between a terminating semicolon causing or not causing
the following line to be tucked under.

Variables controlling indentation style:

sr-block-indent controls the indentation after constructs such as 
  \"resource\", \"proc\", \"initial\", \"fa\", etc.

sr-guard-indent controls the indentation of commands that involve 
  guards, such as \"if\", \"do\", and \"in\".

sr-break-indent controls the amount by which statement 
  continuations are tucked under the beginning of the statement.

sr-paren-ident is an extra amount that statement continuations get 
tucked under for each level of paren nesting.

sr-break-symbols controls whether \";\", \",\", and \"(\" cause
the following statement to be tucked under. 

Change these with \\[set-variable].

Good possibilities for these variables and their corresponding
coding disciplines are:
1.  (Default) sr-break-symbols = '(\"(;,\" \"(,\")).  You must use semicolons
    to separate lines of parameter specificiations and record fields.
    Avoid semicolons at ends of statements unless you change mode with
    \\[cycle-sr-break-symbols].
2.  sr-break-symbols =  '(\"\" \",\") and sr-paren-indent = sr-break-indent.  
    Semicolons may be used in any way desired.  When not inside parentheses,
    avoid ending lines with commas.  (This affects import and extend clauses.)
    \\[cycle-sr-break-symbols] can change the mode to allow these commas.
    Sometimes produces funny results on long arithmetic expressions.

In all cases, no (uncommented) keywords (e.g. initial, final) after \"end\".

Entering sr-mode calls the value of sr-mode-hook."

  (interactive)
  (kill-all-local-variables)
  (use-local-map sr-mode-map)
  (setq mode-name "sr-mode")
  (setq major-mode 'sr-mode)
  (setq local-abbrev-table sr-mode-abbrev-table)
  (set-syntax-table sr-mode-syntax-table)
  (make-local-variable 'indent-line-function)
  (setq indent-line-function 'sr-indent-line)
  (make-local-variable 'indent-region-function)
  (setq  indent-region-function 'sr-indent-region)
  (make-local-variable 'comment-start)
  (setq comment-start "#")
  (run-hooks 'sr-mode-hook)
)


(defun parse-sr (&optional begin-point end-point)
  "Parses an sr program. Output a list of strings that are genuine sr
   and all appear on one line or numbers that are buffer postions of
   newline characters.  Optional first arg specifies beginning of parse,
   which defaults to first global, resource, body, or proc that begins
   a line (intervening whitespace allowed).  Optional end-point bounds the 
   end of the parse.  It defaults to point.  Don't call this."
  (save-excursion
    (let ((cdot (point))
	  symstart
	  symend
	  symlist)
      (if (null end-point)
	  (progn
	    (end-of-line)
	    (setq end-point (point))
	    (goto-char cdot)))
      (if (null begin-point)
	  (progn
	    (re-search-backward
	       "^\\s *\\(global\\>\\|resource\\>\\|body\\>\\|proc\\>\\)" nil 'move)
	    (setq begin-point (point))))
      (goto-char begin-point)
      (if (bolp) (setq symlist (cons (point) symlist)))
      (skip-chars-forward " \t")
      (while (< (point) end-point)
	(setq symstart (point))
	(cond
	 ((eq (following-char) ?\n)
	      (forward-char)
	      (setq symlist (cons (point) symlist)))
	 ((eq (following-char) ?\")
	  (if (re-search-forward "\"[^\"]*\\(\\\\.\\[^\"]*\\)*\""
				 end-point 'move)
	      (progn
		(setq symend (point))
		(setq symlist (cons (buffer-substring symstart symend)
				   symlist)))))
	 ((eq (following-char) ?\')
	  (if (re-search-forward "\'[^\']*\\(\\\\.\\[^\']*\\)*\'"
				 end-point 'move)
	      (progn
		(setq symend (point))
		(setq symlist (cons (buffer-substring symstart symend)
				   symlist)))))
	 ((eq (following-char) ?#)
	  (end-of-line))
	 ((looking-at "/\\*")
	  (skip-over-sr-comment))
	 (t
	  (if (re-search-forward "#\\|/\\*\\|\n\\|\"\\|\'" end-point 'move)
	      (goto-char (match-beginning 0)))
	  (skip-chars-backward " \t")
	  (setq symend (point))
	  (setq symlist (cons (buffer-substring symstart symend)
			      symlist))))  ; end of cond
	(skip-chars-forward " \t")  
	)
      symlist)))
	
(defun skip-over-sr-comment(&optional search-bound)
  "Positioned before /* moves point to just after matching */.
   An optional arg bounds the search."
  (interactive)
  (if (and (re-search-forward "/\\*" search-bound t)
	   (re-search-forward "\\*/\\|\\(/\\*\\)" search-bound t))
      (let ((mb (nth 2 (match-data)))) ; work around an unfeature of 18.44.2
				       ; wherin errors occur on
				       ; (match-beginning 1) if the second
				       ; pattern did not match.
	(if mb
	    (progn (goto-char mb)
		   (skip-over-sr-comment)
		   (re-search-forward "\\*/" search-bound t))
	  t))))
	       

(defun sr-parse-into-lines (parse-list)
  "Given a parse list such as is returned by parse-sr, returns
   an array each element of which is a list (number string),
   where number is the character in the buffer of the beginning of the line
   and string contains the line, less comments, in left to right order.  Quotes
   have been replaced by just \"\".  Don't call this."
  (let ((wkpt parse-list)
	list-of-lines
	current-line
	)
    (while wkpt
      (cond ((stringp (car wkpt))
	     (setq current-line (concat
				 (if (memq (elt (car wkpt) 0) '(?\" ?\'))
				     "\"\""
				   (car wkpt))
				 current-line)))
	    ((and (numberp (car wkpt)) current-line)
	     (setq list-of-lines (cons (list (car wkpt) current-line) list-of-lines))
	     (setq current-line nil)))
      (setq wkpt (cdr wkpt)))
    list-of-lines))
      
	
(defun sr-first-sym (string)
  "Given a string, finds the first sr symbol in it and returns it as a string"
  (and string
       (string-match sr-symbol-RE-bol string)
       (substring string 0 (match-end 1))))
;;; Avoid the match-beginning bug by hard-coding a 0.

(defun sr-last-sym (string)
  "Given a string, finds the last sr symbol in it and returns it as a string"
  (and string
       (string-match sr-symbol-RE-eol string)
       (substring string (match-beginning 1) (match-end 1))))
;;; The match-beginning bug lurks here!!!  The bug is that sometimes
;;; (match-beginning mumble) returns the wrong value.  The appears to
;;; happen when the match begins with the first character, in which case
;;; (match-beginning mumble) will sometimes return 1 instead of 0.
    
(defun get-sr-indent (symbol property)
  "About like (get symbol property), except that the result is evaled, and 
   nil is converted to 0.  Intended for use in context where the symbol
   pg has the value sr-indent-guard, etc."
  (or (eval (get symbol property)) 0))

	  
(defun sr-indent-line (&optional fudge-break arg)
  "Indents a line of sr.  A optional prefix arg adds or subtracts 
   sr-break-indent.  (One C-u adds, two subtract.)
   In a program, optional FUDGE-BREAK should be nil or numeric.
   When numeric, it adds that many 
   sr-break-indents to the indent value.
   An optional second ARG non-nill causes the previous line to be indented 
   as well.  In this case, FUDGE-BREAK applies to the previous line."
  (interactive "*P")
  (sr-internal-setup)
  (let (bdot
	parse-list
	compute-result
	indent-val
	(fudge (cond ((null fudge-break) 0)
		     ((equal fudge-break '(4)) sr-break-indent)
		     ((equal fudge-break '(16)) (- 0 sr-break-indent))
		     ((equal fudge-break '-)    (- 0 sr-break-indent))
		     (t (* sr-break-indent (prefix-numeric-value fudge-break))))))
    (save-excursion
      (forward-line 0)
      (setq bdot (point))
      (setq parse-list (nreverse (sr-parse-into-lines (parse-sr))))
      (if (null parse-list)
	  ()
	;; If the dot is in a line with program characters (blank or all
	;; comments) the first thing in the parse-list would be the previous
	;; line.  So we stick on a dummy line.  Yes, it is a hack.
	(if (not (eq (car (car parse-list)) bdot))
	    (setq parse-list (cons (list bdot "DUMMY LINE") parse-list)))
	;; A hack to make sr-indent-newline-and-indent work efficiently.
	;; Clearly there must be a cleaner way to do this.
	(if arg
	    (progn
	      (setq compute-result (sr-compute-indent (cdr parse-list)))
	      (setq indent-val (if (eq (car (cdr compute-result)) 'absolute)
				   (car compute-result)
				 (+ fudge
				    (car compute-result)
				    (save-excursion
				      (goto-char (car (nth 2 parse-list)))
				      (current-indentation)))))
	      (save-excursion
		(goto-char (car (nth 1 parse-list)))
		(delete-horizontal-space)
		(indent-to indent-val)
		(forward-line 0)
		(setcar (nth 1 parse-list) (point)))))  ;; repair parse list
	(setq compute-result (sr-compute-indent parse-list))
	(setq indent-val (if (eq (car (cdr compute-result)) 'absolute)
			     (car compute-result)
			   (+ (if arg 0 fudge)
			      (car compute-result)
			      (save-excursion
				(goto-char (car (nth 1 parse-list)))
				(current-indentation))))))
      ;; point is at the beginning of the line to be indented
      (delete-horizontal-space)
      (indent-to indent-val)) ; end of save-excursion
    (if (bolp) (skip-chars-forward " \t"))))

(defun sr-indent-region (beg-reg end-reg)
  "Indents a region of SR code.  Note the indentation is relative
   to the first thing in the region.  Currently there is brain damage
   when the first thing is a tail of a broken statement."
  (interactive "*rP")
  (sr-internal-setup)
  (if (interactive-p)
      (message "Indenting..."))
  (let (parse-list
	traverse-list
	wkpt
	current-line
	running-indent)
    (save-excursion
      (goto-char beg-reg)
      (forward-line 0)
      (setq beg-reg (point))
      (goto-char end-reg)
      (end-of-line)
      (setq end-reg (point))
      (setq parse-list (nreverse (sr-parse-into-lines (parse-sr beg-reg end-reg))))
      (setq wkpt parse-list)
      (while wkpt
	(sr-compute-indent wkpt)	; do most of the work
	(setq wkpt (cdr wkpt)))
      (setq parse-list (nreverse parse-list))
      (setq wkpt parse-list)
      (while wkpt			; traverse lines in forward direction
					; converting all indents to absolute
	(setq current-line (car wkpt))
	(if (eq (nth 3 current-line) 'absolute) 
	    (setq running-indent (nth 2 current-line)) ; absolute indent
	  (setq running-indent (+ (nth 2 current-line) ; relative indent
				  (if running-indent ; nil on first line when it is not absolute
				      running-indent
				    (goto-char (car current-line))
				    (current-indentation))))
	  (setcdr (cdr current-line) (list running-indent 'absolute)))
	(setq wkpt (cdr wkpt)))		; end of while
      (setq parse-list (nreverse parse-list))
      (setq wkpt parse-list)
      (while wkpt			; traverse line backward
					; actually doing indentation
	(goto-char (car (car wkpt)))
	(delete-horizontal-space)
	(indent-to (nth 2 (car wkpt)))
	(setq wkpt (cdr wkpt)))))
    (if (interactive-p)
      (message "Indenting...done")))


(defun sr-indent-buffer ()
  "Like sr-indent-region, except does the whole buffer."
  (interactive "*")
  (if (interactive-p)
      (message "Indenting..."))
  (sr-indent-region (point-min) (point-max))
  (if (interactive-p)
      (message "Indenting...done")))

(defun sr-compute-indent (parse-list)
  "Given a PARSE-LIST of the form returned by sr-parse-into-lines,
   which is a list of line-lists (line-number text), each representing a line,
   sr-compute-indent appends data to the line-list at the head of
   parse-list so it has the form 
   (line-number text indent-distance relative-to), where relative-to
   is 'absolute or nil.  Nil means relative to the previous line, 
   i.e. the one represented by (cdr parse-list).  Returns a list
   (indent-distance relative-to)."
  (let*  ((lead-symbol-string (sr-first-sym (car (cdr (car parse-list)))))
	  (lead-symbol  (intern-soft lead-symbol-string sr-obarray))
	  (running-indent 0)
	  prevline
	  (sympos 0)
	  current-symbol-string
	  current-symbol
	  match-b
	  result-list)
    (cond
     ((eq (get lead-symbol 'beginner) 'absolute)
      (setq result-list (list (get-sr-indent lead-symbol 'pre-indent) 'absolute)))
     ((null (cdr parse-list))
      (setq result-list (list 0 nil)))
     (t (setq prevline (car (cdr (nth 1 parse-list))))
	;;(message "initial indent %d" running-indent)
	;;(sit-for 2)
	(if (sr-broken-statement (cdr parse-list))
	    (setq running-indent
		  (- running-indent sr-break-indent)))
	;;(message "after broken %d" running-indent)
	;;(sit-for 2)
	(setq running-indent
	      (- running-indent
		 (get-sr-indent (intern-soft (sr-first-sym prevline) sr-obarray) 'pre-indent)))
	;;(message "deduct preindent of %s %d" (sr-first-sym prevline) running-indent)
	;;(sit-for 2)
	(setq linelen (length prevline))
	(while (< sympos linelen)
	  (setq match-b (string-match sr-symbol-RE prevline sympos))
	  ;;(setq match-b (match-beginning 0))   ; bug in emacs lurks here
	  (if (and demo-emacs-sr-bug
		   (/= match-b (match-beginning 0)))
	      (debug "match-beginning problem" match-b (match-beginning 0)))
	  (setq sympos (match-end 0))
	  (setq current-symbol-string
		(substring prevline match-b sympos))
	  (setq current-symbol (intern-soft current-symbol-string sr-obarray))
	  (setq running-indent (+ running-indent
				  (get-sr-indent  current-symbol 'pre-indent)
				  (get-sr-indent  current-symbol 'post-indent)))
	  ;;(message "%s %d" current-symbol-string running-indent)
	  ;;(sit-for 2)
	  )  ; end of while
	(setq running-indent (+ running-indent
				(get-sr-indent lead-symbol 'pre-indent)))
	;;(message "%s %d" lead-symbol-string running-indent)
	;;(sit-for 2)
	(if (sr-broken-statement parse-list)
	    (setq running-indent
		  (+ running-indent sr-break-indent)))
	;;(message "add broken statement %d" running-indent)
	;;(sit-for 2)
	(setq result-list  (list running-indent nil))))
    (setcdr (cdr (car parse-list)) result-list)))

(defun sr-broken-statement (parse-list)
  "Returns non-nil if the line at the head of PARSE-LIST is the continuation
   of a previous broken statement."
  (let* ((head-symbol-string (sr-first-sym (car (cdr (nth 0 parse-list)))))
	 (head-symbol (and head-symbol-string
			   (intern-soft head-symbol-string sr-obarray)))
	 (head-beginner-prop (get head-symbol 'beginner))
	 tail-symbol-string
	 tail-symbol
	 tail-ender-prop)
    (if head-beginner-prop
	(eq head-beginner-prop 'always)
      (setq tail-symbol-string (sr-last-sym (car (cdr (nth 1 parse-list)))))
      (setq tail-symbol (and tail-symbol-string
			     (intern-soft tail-symbol-string sr-obarray)))
      (setq tail-ender-prop (get tail-symbol 'ender))
      (cond ((eq tail-ender-prop 'always) t)
	    ((eq tail-ender-prop 'special)
	     (string-match tail-symbol-string (car sr-break-symbols)))
	    ;;(t nil)  ; this happens automatically
	    ))))
    

(defun sr-indent-newline-and-indent (&optional fudge-break)
  "Does what it says, but more efficiently.  An optional arg works as 
   does FUDGE-BREAK in sr-indent-line."
  (interactive "*P")
  (newline)
  (sr-indent-line fudge-break t))

(defun sr-cycle-break-symbols-inner (symstr sofar)
  (if (string-match symstr (car sr-break-symbols))
      sofar
    (concat sofar symstr)))
  

(defun cycle-sr-break-symbols ()
  "Cycles the list sr-break-symbols to the left.  Typically this is to
   toggle whether or not a trailing semicolon causes the following line
   to be tucked under."
  (interactive)
  (setq sr-break-symbols (nconc (cdr sr-break-symbols)
				(list (car sr-break-symbols))))
  (if (interactive-p)
      (message "Breaking: \"%s\"   Non-breaking: \"%s\""
	       (car sr-break-symbols)
	       (sr-cycle-break-symbols-inner
		";" (sr-cycle-break-symbols-inner
		     "," (sr-cycle-break-symbols-inner
			  "(" ""))))))


