[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::languages

Title:Languages
Notice:Speaking In Tongues
Moderator:TLE::TOKLAS::FELDMAN
Created:Sat Jan 25 1986
Last Modified:Thu May 22 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:394
Total number of notes:2683

8.0. "BLISS vs C" by SARAH::BOOMAN () Sat Mar 17 1984 17:40

Just talked to a friend of mine the other day who has been working in a
C/UNIX environment for a year, but used to work with Bliss.  He doesn't
care for C at all.  According to him, Bliss is far more powerful.  He felt
that C was restricting him to no advantage.  Pascal is restricted, too, 
but at least it finds bugs for you...  I was actually rather surprised.

But then again, most people I know who've used Bliss for more than a year
really like it.  Lots of moans the first year (Damned dots!), though.

So: Bliss is complex and powerful, while C is simpler and weaker.  If you
know Bliss already, you don't need C (as long as you work at DEC).  If
you don't know Bliss, learn it if you can afford the time.

I have to admit that I am jealous of the DECUS C library, though.

Gordon
T.RTitleUserPersonal
Name
DateLines
8.1BABEL::HOBBSSat Mar 17 1984 21:4747
I recently interviewed someone who had both C and BLISS experience.  Probably
everyone has heard C described as being similar to TECO in that it is a
"writeonly" language.  The person I was interviewing described BLISS as
a "readonly" language.

Basically, it is much easier to learn C than to learn BLISS.  Although
both C and BLISS allow the programmer to access low-level machine functions
(i.e. slop around in the bits) and both languages allow one to write very
obscure code, C programmers tend to do these things where ever possible
while BLISS programmers try to avoid them.  BLISS programmers do a lot
of machine specific stuff in things like operating systems where there
is a lot of payoff but even here they tend to structure there use of
such features.

The designs of the two languages have much to do this.  What particularly
comes to mind is BLISS STRUCTUREs which allow the programmer to design new
high-level data access algorithms by isolating a low-level implementation in
a single STRUCTURE definition.  Unfortunately, writing a good BLISS program
(and particularly a good STRUCTURE declaration or MACRO definition) requires
quite a bit of experience with BLISS--easily the one year mentioned in the
note.  However, once a good BLISS program (with well designed STRUCTUREs
and MACROs) is written then it is usually very easy for any other experienced
BLISS programmer to understand it and maintain it.  This is where the "readonly"
nature of the language comes from--difficult to learn to write but easy to read
and maintain.  If the maintenance costs of a system are to be comparable to
the initial development cost then BLISS would seem to have an advantage over C
(PROVIDING the project can continue to find the necessary trained BLISS
programmers during the maintenance life of the system).

The emphasis on "providing" above is another reason why BLISS programs tend
to be easier to read than C progammers.  There are very few trained BLISS
programmers outside of DEC.  Therefore, whenever DEC hires a new software
engineer the company must train him or her in using BLISS.  Although this is
expensive, it has the advantage that the new hire rarely has any bad
BLISS programming habits before this training begins and it is fairly
easy to train the new hire the "correct" way to write BLISS programs.
(Note that the definition of "correct" differs between various locations
in this company but "correct" should always mean "in a similar style to
the other programmers on the same project" so that new maintainers on
a project need only learn to understand one style of BLISS usage in
order to understand the entire system).

When Digital hires a C programmer chances are that the new programmer
already knows C and already has his programming style (with both good and
bad habits) which is different from other project members.  For this reason it
is more difficult to get a project coded by several C programmers to have a
consistent style. 
8.2ELUDOM::ARSENAULTMon Mar 19 1984 15:2710
The previous reply describes the overhead of having to train new programmers
in the use of BLISS.  Consider that this policy may help to retain 
programmers who have suffered through the agony of becoming proficient in
BLISS and hence do not want to work elsewhere because it mean writing in
an "inferior" language.

Yes folks.  As the senior member of the Bliss project I am totally biased,
and think Bliss is tops.

mark
8.3PBSVAX::CAMPBELLTue Mar 20 1984 20:2612
BLISS is OK (I even like it), but it is fatally flawed.  It is a company
language.  It only runs on VAXes, 11s, and 10/20s, and will probably
never run on anything else.  If you believe DEC will never produce
another architecture then BLISS is a great idea.  But it's a safe
bet that the first compilers written for Titan and SAFE will be C
compilers;  do that and spend a few months writing device drivers and
you've got Unix running.  No way will any DEC operating system port
that well (hell, they won't port at ALL).

I don't know about the other readers of this notes file, but I plan
to run my programs on new machines when they arrive.  So I write
them in C.
8.4ELUDOM::ARSENAULTWed Mar 21 1984 15:306
Of course, you're right about the transportability issue.  

There is, however, some possibility that BLISS will run on other machines
and operating systems, at least as a cross-compiler.

mark
8.5ELUDOM::HETRICKWed Mar 21 1984 20:092
	I understood that the SAFE people were already working on a BLISS
	compiler.
8.6BABEL::HOBBSSun Mar 25 1984 03:5631
RE: .3

BLISS is available on a few more machines that those mentioned.  Bell
Labs wote a version that runs on the IBM 360/370 architecture (and you
thought that Bell Labs used only C as a systems implementation language).
General Electric has a version of BLISS-10 that generates code that runs
under GCOS on the Honeywell 6000 architecture.  I am also told that
various dialects of BLISS are popular in the Soviet Union.  However,
none of these places use BLISS anywhere near as heavily as Digital.

Actually BLISS is a fairly easy language to compile.  A dumb BLISS
compiler is not much harder to build than a dumb C compiler.   However,
while C programmers expect their compiler to do little optimization,
BLISS programmers demand a highly optimizing compiler.  It is because
BLISS is always implemented with an optimizing compiler that BLISS
programs are easy to read.  A BLISS programmer can code an algorithm
in a straight-forward easy to understand manner because the optimizer
will do many the tricky transformations necessary for efficient code.
C programs are often difficult to understand because the programmer
did the tricky optimizations in the source code.  Even though there
are many more C users than BLISS users I suspect that there are
not many more high quality optimizing C compilers than there
are comparable quality optimizing BLISS compilers.

Recent developments in optimizing compiler construction techniques should
have two effects in the future:  (1) it will be easier to build an
optimizing BLISS compiler for a new architecture, and (2) C programmers will 
do fewer tricky source transformation because they will expect their
compiler to do the optimization.  I do not expect increase ease in
writing BLISS compilers will make BLISS any more popular but I do expect that
increased availablity of optimizing C compilers will make C more popular.
8.7SARAH::BOOMANSun Mar 25 1984 15:361
What is "Titan".  What is "SAFE".
8.8VAXUUM::DYERWed Mar 28 1984 17:2028
	[RE .7]:  Titan and SAFE are RISC machines.  One's being worked
on in the West, the other in Marlboro.  (Am I right about this?)

	[RE EVERYTHING ELSE]:  When I came to DEC I knew C a little.  I
developed my C programming at DEC.  I happen to thing that my C code is
very readable and very consistent with "the way things are done here."
	It is unfortunate that so many C compilers do such a poor job
of optimizing.  There are a lot of chintzy C compilers out there, be-
cause there isn't much to C itself and a lot of people get away with
writing the parsing (the simple part) and shortchanging the optimizing.
	However, a C compiler isn't *necessarily* poor at optimizing.
The original C compilers did it well, and The Book (a.k.a. K&R) was
filled with examples of writing the same code in two different ways
while suggesting the clearer way ("it will compile into the same thing").
	I tend to agree that writing optimized code is a response to
poor optimization; but at least the code will work as well as possible
regardless of which compiler is used.

	As an aside, I think the Bliss developers could do the other
languages a favor and distribute their optimizations.  Isn't it a matter
of analyzing assembly code?  And doesn't every compiler go through a
step where assembly code is generated and optimized?  Or is there ano-
ther approach taken.

	I don't know Bliss, but I ask you this:  If I'm going to have
to spend a year using it to get any good at it, why don't I just use
MACRO?
		<_Jym_>
8.9ORPHAN::BLICKSTEINThu Mar 29 1984 02:1232
No, almost all optimization for almost all compilers is done before code
generation.  The reasons for this are many and include:

1) Optimization is much easier to perform on the compilers internal 
   representation of the program (trees) than on an instruction sequence.

   Once a program is translated into instructions, much of it's structure
   (blocks, scoping, control structures, data, etc.) are lost.   Thus there
   is less context available to do optimization.

   Also, since the original semantics of the program may be lost, it is
   hard to tell what optimizations are "safe" (don't produce an invalid
   program).

2) Doing optimization while the program is still in an intermediate form
   keeps the optimizer from being specific to one architecture.

Some optimiztions are done after code generation.  This is usually refered
to as peephole optimization.  A VAX example might be to replace:

		JSB	X
		RSB
with:

		JMP	X

Right now, the optimizing champion of VAX languages is VAX FORTRAN V4.0
which is now in field test.   If we were to transfer optimization technology
from anywhere, FORTRAN is the place to take it from, and this is probably
going to be done.

	db
8.10REX::MINOWThu Apr 05 1984 14:5139
C optimizations are limited by a few language contstraints, as well
as the obvious practical problems (fit compiler in PDP-11 memory --
that sort of thing).

One of the language constraints is the fact that a pointer to a
variable can point to anything.  For example,

	function(ptr, value)
	int		*ptr;		/* Pointer to integer	*/
	int		value;		/* Integer value	*/
	{
		extern int	another_value;

		*ptr = another_value + value;
		return (another_value + value);
	}

The two "common subexpressions" cannot be optimized as the actual
value of "ptr" may contain the address of "another_value".
While a compiler could perform a more elaborate flow analysis
to determine whether this problem could occur (for example, if
both "value" and "another_value" were declared "register", the
compiler could optimize).

The rule of thumb I have used is that Bliss could potentially offer
slightly "better" code (10-15% maybe) than C, but this would disappear
when programmer quality issues are take into account.  (In other words,
no Bliss compiler would change a bubble-sort into a quicksort.)

On the other hand, it has been said that it takes about a year to become
a proficient Bliss programmer.  That year costs Dec $100,000 in manpower
and must be compared to the month or so required to become equally
proficient in C.

Bliss has been around for about 14 years without gaining wide acceptance
in the industry.  C was almost unknown 3 years ago.  The world is
trying to tell us something.

Martin.
8.11ELUDOM::ARSENAULTThu Apr 05 1984 16:2818
The primary reason Bliss has not gained wide acceptance outside of Digital
is because our company has decided to not push the language.  For years,
Bliss has cost ten times what it would cost if we were trying to sell it.

Our former Bliss project leader (and all around Bliss guru), Al Lehotsky,
periodically sent memos to our management saying that Bliss is way over
priced.  I don't know what kind of response he got, though I assume not
much of any.

Another reason that Bliss has not caught on is that there isn't any
decent tutorial documentation on the language.  The only thing that exists
is the Bliss PRIMER, which are universally considered to be awful.  
Besides that, they are also overpriced.  I believe a set of PRIMERs
(which consists of three modestly sized workbooks) sells for three 
hundred dollars.  Thirty dollars might be a more reasonable price.
Now that's now to encourage new users.

mark
8.12ORPHAN::BLICKSTEINFri Apr 06 1984 04:5319
I think that the BLISS language Reference is one of the best language
introductions I've ever used.   I really like its organization (syntax
and semantics sections, chapter by topic, etc.).

I think that once you've seen a few languages, tutorial type books just
waste your time.  They tend to just rehash old ground.  An extra nice
thing about the BLISS manual is that you can use it both to learn the
language and as a fine reference manual.

Regarding optimizations in C:  I wouldn't be surprised if that feature
stopped C from optimizing un-aliased variables.  I didn't understand the
example you provided, but PL/I has a similar feature and it is easy to
tell (via classifying the references and scoping) which variables can
be accessed through an alias.  This doesn't hinder PL/I.

I'd have to believe that C can determine an aliased variable otherwise
it would never be able to cache named variables in registers.

	db
8.13ADVAX::A_VESPERTue Apr 10 1984 13:4365
I just can't resist adding my own comments to the BLISS vs C discussion.
I have used C for a number of years, though not for any LARGE project.
I used BLISS-16 in development of 'system' software, software that
accessed the hardware registers of a video subsystem to draw graphics.
(Pro/GIDIS for those who know and care.)

My major comment on BLISS is:  Fine control structures (although nothing
fancy), extensive data structures (complicated but useful), but why in
heavens name require all those xxxxxx dots!  C is much better in this,
when you want the address you explicitly put the '&' operator in front.
95% of the time you want the contents, so BLISS requires 95 dots for
100 references where C requires 5 '&'s.

My major comment on C is:  control structures good (although amenable
to misuse), commonly required data structures, some shorthand operators
that require getting used to, curious data declarations (but what other
language allows you to declare something as a pointer to a function
returning a pointer to a real?).

Neither language defines any I/O.  I dislike this in both, but at least
in C you have the 'stdio' package, which does seem to be standard and
allows (relatively) portable software to be written.  I have used XPORT
in BLISS but I think that it provides only the basics (open file,
read record ...) when I usually want data translation (print the value
of this integer in decimal ...).  I have not used the $STR_ASCII
or $STR_BINARY functions -- didn't know about them in time.

Macro capabilities in BLISS are far more extensive than those in
C.  (DECUS C does not even allow parameters on macros.)  C programmers
who need macro support beyond the normal pre-processor can use M4,
a macro pre-processor compatable with the normal pre-processor.  I don't
think that M4 is as powerful as the BLISS macro capabilities, but then
I found the BLISS macros hard to use.  (Let's see, which type of macro
do I want to define?  Certain macros are not evaluated at all when
there are no parameters -- in my opinion a mistake.)

Summary.  Both languages can be used for software development.  BLISS
is FATALLY flawed because of the dots.  C is available on MANY machines.
C programs can be portable across operating systems and computers.
BLISS provides more ways for the programmer to create hard-to-maintain
and inefficient code (data structures and macros).  Programming is an
ART; simple tools focus attention on the work being created where
complex tools can (repeat, CAN) cause attention to be shifted to the
tools themselves.

I will choose C over BLISS for almost any project; I will bribe, blackmail,
threaten, etc. my bosses for this choice unless there are clear technical
reasons for using BLISS (such as a large amount of code already written).

Andy Vesper

p.s. in case you think I am enamored of simplicity for simplicity's sake
I will add that I would use SIMULA-67 if it were available on my VAX.
SIMULA-67 is based on ALGOL-60 but adds a well defined I/O system and
a CLASS concept which combines data and procedures to manipulate that data.
Not a simple language, but the power does not seem to get in your way
the way the BLISS constructs do.  I would not use ALGOL-68 -- it is far too
powerful and complex.  I am withholding judgement on ADA till I have an
opportunity to use it in a large project.

p.p.s. Technical Language group PLEASE support a C compiler for the
PDP-11 series.  If that were done it would help me convince management
to use C.

p.p.p.s.   C  :-)          BLISS   :-(
8.14This note trashed accidentally, sorryELUDOM::CLARKWed Apr 11 1984 13:2658504
8.15ELUDOM::ARSENAULTWed Apr 11 1984 13:4713
Reply to 13

"Bliss is FATALLY flawed on account of the xxxxxx dots."

This is an extreme over-reaction.  The dots can be a nuisance.  They present
the inexperienced user with one more thing to think about -- and hence do
incorrectly.  However, after one becomes even a little proficient in using
Bliss, the dots become a non-issue.

I applaud Ward's argument in .14.  I consider Bliss expression and fetch
operator (the dot) to be much more elegant than C's address operator ("&").

mark
8.16ADVAX::A_VESPERWed Apr 11 1984 14:3149
re .14: Yes, I know that BLISS is an expression language.  Yes,
I know that:

   X = .X;

would convert to:

   &X = .X;

oops -- that should be:

   &X = X;

if the people who originally proposed the dot had decided that a name
should imply fetch except when explicitly preceeded by '&'.

But, why not do what is done for most languages and say that the
'=' operator needs an ADDRESS (expression) on the left and a VALUE
(expression) on the right.  It implies two expression evaluation
techniques, one that returns addresses and one that returns values,
but this is not unreasonable.

What I feel is unreasonable is that simple code like:

   X = X1;
   X1 = X2;
   X2 = X;

must be written in BLISS as:

   X = .X1;
   X1 = .X2;
   X2 = .X;

If you think this is much ado about tiny little dots -- after all
I only had to type 3 extra characters, here is something that irks
me tremendously:

   MACRO  abs (x) = (IF x LSS 0 THEN -x ELSE x) %;

   ROUTINE absolute (x) = (IF .x LSS 0 THEN -.x ELSE .x) ;

Both 'abs' and 'absolute' should do the same thing, but note
that I had to change 'x' to '.x' when converting from macro
to routine.  (There is no difference between the two calls,
so why should there be this awkward difference between the
definitions?)

Andy
8.17NEWTON::NORTONWed Apr 11 1984 16:4123
One vote for Andy of .13,.16.  Thanks for the first reason I've seen
for the lousy dots (they really are a pain, since you have to have yet
another level of "am I doing the right thing for this side of =" etc.)
in .14 or .15.  I like expressions.  C macros lose (not powerful enough)
and M4 isn't enough either -- can't flexibly suck things out of the input
and glom them into symbols in the text.  

There are no concrete statements (aside from comments re: macro expansion)
backing up an early comment in this file about "Bliss being more powerful".
I'd be interested in what that means, since I find it not true.

One real win for C that never gets mentioned is that it is terse.  It isn't
popular to try and defend terse, and I believe in lots of comments.  However,
I really feel there is a significant increase in effort for the reader if
a lot of verbosity is in the way.  Its much less intimidating to have a clean
short routine with lots of white space.  I'd be interested in whether others
have noticed this or if I'm alone in this observation.

Any language is better in a different environment.  C/Unix is a much better
environment than C/VMS.  (should read better, not different above).
Don't flame at me on this if you have only second hand association with either
of the above.  I'm refering to ctags, lint, and debugging in a real sub
process.  
8.18ELUDOM::CLARKWed Apr 11 1984 18:516
I know I'm asking for it with this comment, but I'm brave:

   C has always seemed to me to be a mating of PASCAL and TECO -
	a hacker's delight!

Ward
8.19VAXUUM::DYERThu Apr 12 1984 13:5911
	[RE .17]:  Has anyone ported lint to VMS?  How necessary is it,
since VAX C tends to check things more than usual C compilers.
	What would be nice is
	    $ CC/LINT
	VMS has ripped off a bunch of nice tools from Unix:  CMS, MMS,
Gosling's EMACS, etc.  We'll get there.

	[RE .18]:  (-: What do you code in?  Pascal?  Do you use TECO to
edit your Pascal files? :-)

		<_Jym_>
8.20EIFFEL::HARRISTue Apr 17 1984 17:2824
One of the main ADVANTAGES of BLISS is that it allows us to write NON-PORTABLE
software!  What good is it to DEC if we write something in C and it gets used
all over the place?  We get only the software revenue, not the hardware sales.

This is the same mistake all the analysts are making about ATT.  They say:
"ATT has UNIX, that gives them a great advantage".  Bull.  Everyone has UNIX.
The UNIX for the VAX (Berkeley 4.2bsd based) is universally acknowledged to
be better than the Bell System V Unix that is being advertised so heavily.

This is still a HARDWARE company, and any programmer here that doesn't take
note of the fact that hardware revenues are still running 4-5 times the
software revenues is just plain blind.

The software development policies and procedures document specifically states
that the implementation language to be used for all corporate software is
BLISS.  There are several good reasons for this, I won't list them here but
suffice it to say it has little to do with the BLISS language itself, except
for the fact that it is eminently adequate and has in-house supported 
optimizing compilers.

Any programmer so irresponsible as to subvert the policy by writing DEC
software in another language just drives up costs and hinders our ability
to sell hardware.
			-Kevin
8.21ARK::THOMPSONWed Apr 18 1984 17:1312
RE: 20

Does this mean we should write all applications programs in DIBOL and
skip on COBOL and BASIC?

Most customers today, it is true, look for the software first and then 
for HW to run it own. As long as our HW runs our SW the best then we will
have no problem getting the HW sales. To demand that people use non-standard
languages to keep people buying DEC iron is to admit that our HW is not
as good (atleast for the money) as someone elses.

Alfred
8.22KOALA::ROBINSThu Apr 19 1984 06:4627
re:.20,.21

I agree with .21.  The driving force in the computer industry today is
SOFTWARE, not hardware.  People want functions, not boxes.  The software
performs the function, they could care less what box it does it on. 

My father is VP of data processing for Moore Business Forms (ya know, that
paper in the lab) and when I told him I have a VT102 at home, he asked me, "Oh,
is that like an IBM 360?"  And this man is a VP!!!!!!! of data processing!!!!!!

I agree with .20 that this is still a hardware company.  However, I think that
if we are to be as successful in the next 26 years as we have been in the past
26, we've got to start emphasizing software.  We have some of the greatest
software engineers in the world!!!!  Every time I find a new feature of VMS
that I didn't know was there, but that is so obvious once I Think about it, I
am amazed all over again. 

I like his comment, "...we get only the software revenue, not the hardware
sales."  I can just see some DEC accountant now, saying to some creditor who is
handing him a check, "Oh, no, you must be mistaken.  That's only software
revenue, we don't want it." 

Hardware is becoming more and more similar anyway.  Didn't ATT just announce
a complete line of computers?  What fact was emphasized in the newspaper
stories?  Each one was very similar to a VAX model.

sar
8.23BARTOK::BARABASHThu Apr 19 1984 18:26464
I think the following discussion from USENET, comparing our BLISS-32 compiler
with the Berkeley Un*x C compiler for code quality, can shed some light on why
discriminating programmers of impeccable taste choose BLISS all the time :-)

-- Bill B.

[456 lines of text follow.]

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Newsgroups: net.unix-wizards,net.lang.c
Path: decwrl!decvax!mcnc!idis!mi-cec!dvk
Subject: Does "C" really optimize? - No, and why not
Posted: Tue Feb 14 11:00:13 1984


This is a continuation of my diatribe on "C doesn't optimize, it neatens".
Some time ago I made the rash statement that "C does not have an optimizer,
it has a neatener".  I also threatened to make good my statement by proving
it.

I have posted to net.lang.c a collection of examples on how C fails to create
very good code.  Rather than state what *I* could have done were *I* a
compiler (easy to say, hard to implement), I show what a compiler with an
optimizer is capable of.  To accomplish this, I have compared the output of
4.1c BSD "C" with VAX/VMS "Bliss-32".  Identical program fragments were fed
to both compilers, and the resultant assembly code is presented and discussed.
While a number of the optimizations require flow analysis (something "C" does
very little or none of), some suggestions can be incorporated into the
"Optimizer" pass of "C".  (Are you listening, maintainers?)

I have taken pains *not* to compare Bliss with C (syntax, semantics, or
capabilities), but concentrate on the ability of the compilers to optimize.
In all cases, no tricks were used to get one language to behave better than
another, and in all cases the default level of optimization was used.  The
unexpurgated assembly code is given; the only neatening I have done is to
insert tabs for readability.  Any and all counterexamples are welcome.  (If
you don't have a Bliss compiler, I can run tests for you, depending on the
size and number of requests).

		-Dan Klein, Mellon Institute, Pittsburgh	(412)578-3382

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

In this comparison, I present a test which selects between two routines,
each of which has the identical arguments passed to it.  Now, since either
one or the other routine is called (i.e. flow control analysis can readily
determine that there is no condition under which neither or both routines
are called), a great optimizer would first push all the arguments onto the
stack, and then test the condition "t", and call the appropriate routine.
Regrettably, even Bliss is not smart enough to do this.  However, it is
smarter than C in that:

	1) It uses two MOVQ instructions to load the procedure arguments
instead of 4 PUSHL instructions (this is a space optimization, but gives
a small speed optimization since there are two less instructions to execute).
If Bliss were assured of the target processor, it could use a MOVO (move
octaword).  However, the 11/730 doesn't support that instruction, so Bliss
avoids it.
	2) C uses a common exit point from the routine.  Since no cleanup
code is used, the "jbr L19" is wasteful.  Bliss instead simply generates
two RET instructions where required.  This is a drawback of the peephole
optimizer that C uses.  It can eliminate jumps to jumps, but it does not
eliminate jumps to returns.  It should, since that optimization is both a
speed and space improvement.

----------------------------------------+-------------------------------------
external routine alpha;			|	extern  int	alpha();
external routine beta;			|	extern  int	beta();
					|
routine test(p,q,r,s,t) : novalue =	|	test(p,q,r,s,t)
begin					|	{
    if .t neq 0				|	    if (t!=0)
	then alpha(.p,.q,.r,.s)		|		alpha(p,q,r,s);
	else beta(.p,.q,.r,.s);		|	    else
end;					|		beta(p,q,r,s);
					|	}
					|
	.TITLE  FOO			|		.data
					|		.text
	.PSECT  $CODE$,NOWRT,2		|	LL0:	.align  1
					|		.globl  _test
TEST:	.WORD	^M<>			|		.set	L14,0x0
	TSTL	20(AP)			|		.data
	BEQL	1$			|		.text
	MOVQ	12(AP), -(SP)		|	_test:  .word	L14
	MOVQ	4(AP), -(SP)		|		tstl	20(ap)
	CALLS	#4, W^ALPHA		|		jeql	L18
	RET				|		pushl	16(ap)
1$:	MOVQ	12(AP), -(SP)		|		pushl	12(ap)
	MOVQ	4(AP), -(SP)		|		pushl	8(ap)
	CALLS	#4, W^BETA		|		pushl	4(ap)
	RET				|		calls	$4,_alpha
					|		jbr	L19
					|	L18:	pushl	16(ap)
					|		pushl	12(ap)
					|		pushl	8(ap)
					|		pushl	4(ap)
					|		calls	$4,_beta
					|	L19:	ret

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

In this example I show what the compilers do when given two blocks of code
that are nearly identical (i.e. they are "tail identical").  Only the head
is different (namely whether the first argument pushed to "alpha" is a 0
or a 1.  Both compilers behave well in that they share the tail identical code
between the two conditions.  The only complaint I have against C is that
it uses 4 PUSHL instructions to pass the remaining arguments, rather than a
more speed/space effifient two MOVQ instructions.  If you were sure you were
not going to run on an 11/730, you could further reduce this to a single MOVO
instruction, but that is an unreasonable request.
----------------------------------------+-------------------------------------
external routine alpha;			|	extern  int	alpha();
					|
routine test(p,q,r,s,t) : NoValue =	|	test(p,q,r,s,t)
	begin				|	{
					|	    if (t!=0)
	if .t neq 0 then		|		alpha(p,q,r,s,0);
		alpha(.p,.q,.r,.s,0)	|	    else
	else				|		alpha(p,q,r,s,1);
		alpha(.p,.q,.r,.s,1);	|	}
	end;				|
					|
					|
	.TITLE  FOO			|		.data
					|		.text
	.EXTRN  ALPHA			|	LL0:	.align  1
					|		.globl  _test
	.PSECT  $CODE$,NOWRT,2		|		.set	L13,0x0
					|		.data
TEST:	.WORD	^M<>			|		.text
	TSTL	20(AP)			|	_test:  .word	L13
	BEQL	1$			|		tstl	20(ap)
	CLRL	-(SP)			|		jeql	L17
	BRB	2$			|		pushl	$0
1$:	PUSHL	#1			|		jbr	L200004
2$:	MOVQ	12(AP), -(SP)		|	L17:	pushl	$1
	MOVQ	4(AP), -(SP)		|	L200004:pushl	16(ap)
	CALLS	#5, W^ALPHA		|		pushl	12(ap)
	RET				|		pushl	8(ap)
					|		pushl	4(ap)
					|		calls	$5,_alpha
					|		ret

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

In this example, I demonstrate the ability (and lack thereof) of the compilers
to extract loop invariant code from the body of a loop.  This is a technique
we were all taught in Programming-1.  The Bliss compiler knows about this
technique, and does it for you when you forget (or when it is less elegant to
create a temporary variable to hold the invariant value).  What I do here is
loop on "i" from 0 to "(5+a)/2", and do *nothing* in the body of the loop.
The invariant expression is "(5+a)/2".  It doesn't take a genius to see that
that value will never change in the loop, especially since the loop does
nothing at all (let alone reference "a").  This is a very simple example of
loop invariant code.  Bliss can recognize more complex examples than this.
Neither compiler eliminates the loop altogether.  This is a religious issue,
in that "is the loop needed at all if you know you aren't going to do anything
in it".  There is no "right" answer to that question, since it is really very
application dependant (i.e. do you really want to ignore software timing
delays?).  So, on to the comparison:

	1) Bliss recognizes the loop invariant section of the loop, and
evaluates it once (before the loop is executed).  Thereafter, it does not
need to reevaluate the expression.  The C compiler, on the other hand,
evaluates the limit expression before each pass of the loop.  Not only is
this computationally redundant, but speed inefficient.
	2) Bliss uses the AOBLEQ (Add One and Branch if Less or Equal) to
effect the loop.  The C compiler (after having recalculated the limit
expression), uses an "incr" / "cmpl" / "jleq" combination.  This is less
efficient in both speed and space.
	3) In the calculation of the limit expression, both compilers need
a temporary variable to place the result.  The Bliss compiler chooses R1,
while the C compiler allocates a stack location.  This is a poor choice on
the part of C, since stack accesses take far longer than register accesses
and require more bytes of assembly code.  The register "r1" is available
(and does not need to be preserved on routine entry), so C should use it.
	4) The C compiler allocates a single variable on the stack in the
wrong way.  It emits "subl $4,sp" / "clrl -4(fp)" when it could much more
efficiently do "clrl -(sp)".  Thereafter it refers to the variable as "-4(fp)"
when it should use "(sp)".  The latter takes 1 bytes versus 2.  However, as
mentioned in 3) above, using "r1" is better all around.
	5) The Bliss compiler sets the loop index variable to be 1 less than
the starting value it needs, and immediately increments it (i.e. the loop
increment is at the top of the loop).  The loop increment in C is also at the
top of the loop, but C sets the variable to be what it wants to start at,
skips the loop increment the first time, and hits it each time afterward.
For loop increments that are complex (i.e. involve pointer deaccessing),
this is a reasonable approach.  However, for simple increments (like "i++"),
the code is wasteful.
----------------------------------------+-------------------------------------
routine test(a) : novalue =		|	test(a)
begin					|	int	a;
					|	{
    incr i from 0 to (5+.a)/2 do ;	|	    int i;
					|
end;					|	    for (i=0; i<=(5+a)/2; i++) ;
					|	}
					|
	.TITLE  FOO			|		.data
					|		.text
	.PSECT  $CODE$,NOWRT,2		|	LL0:	.align  1
					|		.globl  _test
TEST:	.WORD	^M<>			|		.set	L12,0x0
	ADDL3	#5, 4(AP), R1		|		.data
	DIVL2	#2, R1			|		.text
	MNEGL	#1, R0			|	_test:  .word	L12
1$:	AOBLEQ  R1, R0, 1$		|		subl2	$4,sp
	RET				|		clrl	-4(fp)
					|		jbr	L18
					|	L200001:incl	-4(fp)
					|	L18:	addl3	$5,4(ap),r0
					|		divl2	$2,r0
					|		cmpl	-4(fp),r0
					|		jleq	L200001
					|		ret

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

In this example I show how the compilers allocate local variables.  The
test code declares two local variables, "a", and "b".  By using flow analysis
it can be seen that the use of "a" and "b" does not overlap.  Now a really
"great" optimizer would not bother moving the constant values into the local
variables, and then pushing them on the stack (since it can also be seen that
the only use of the local variable is a place holder).  However, both compilers
can be forgiven in that it is possible for a debugger to tell you the values
of "a" and "b" if they occupy a location, while it is very difficult to make
a debugger smart enough to look on the stack during a partially executed
routine call.  The comparison:
	1) C is not smart enough to recognize that the use of the variables
overlaps, and instead allocates two locations (on the stack) for them.  Bliss
on the other hand recognizes this fact, and shares a location for both the
variables.  DON'T tell me C does it so the debugger can distinguish between
the two variables.  If the VMS debugger is smart enough to tell the difference,
then so can the Unix debuggers.
	2) C allocates the variables on the stack, while Bliss chooses to use
register 0.  Even if Bliss had used two registers, it still could have used
R1 and R0.  C should also, but instead it plods around playing with the stack.
The C code is larger, and also substantially slower.
----------------------------------------+-------------------------------------
external routine alpha;			|	extern  alpha();
					|
routine test(parm) : NoValue =		|	test()
	begin				|	{
	local a,b;			|	    int a, b;
					|
	a = 2;				|	    a = 2;
	alpha(.a);			|	    alpha(a);
	b = 5;				|	    b = 5;
	alpha(.b);			|	    alpha(b);
	end;				|	}
					|
					|
	.TITLE  FOO			|		.data
					|		.text
	.EXTRN  ALPHA			|	LL0:	.align	    1
					|		.globl  _test
	.PSECT  $CODE$,NOWRT,2		|		.set	L13,0x0
					|		.data
TEST:	.WORD	^M<>			|		.text
	MOVL	#2, R0			|	_test:  .word	  L13
	PUSHL	R0			|		subl2	$8,sp
	CALLS	#1, W^ALPHA		|		movl	$2,-4(fp)
	MOVL	#5, R0			|		pushl	-4(fp)
	PUSHL	R0			|		calls	$1,_alpha
	CALLS	#1, W^ALPHA		|		movl	$5,-8(fp)
	RET				|		pushl	-8(fp)
					|		calls	$1,_alpha
					|		ret

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

In this example I show what the compilers do when they find unused local
variables.  Simply put, if a local variable is unused, there is no reason
to allocate space for it.  The time spent allocating space is a waste.  The
Bliss compiler knows that both "a" and "b" are not used, so no space is
reserved for them.  The C compiler on the other hand subtracts 8 from the
stack pointer, and then does not touch the space.  Why bother?  (The debugger
can always be told the variable is not allocated).  The removal of unused
locals should be a transparent operation.  Instead, the C compiler needs the
help of "lint" to warn you about it.  Bogus!
----------------------------------------+-------------------------------------
external routine alpha;			|	extern  alpha();
					|
routine test(parm) : NoValue =		|	test(parm)
	begin				|	{
	local a,b;			|	    int a, b;
					|
	alpha(.parm);			|	    alpha(parm);
	end;				|	}
					|
					|
	.TITLE  FOO			|		.data
					|		.text
	.EXTRN  ALPHA			|	LL0:	.align	    1
					|		.globl  _test
	.PSECT  $CODE$,NOWRT,2		|		.set	L13,0x0
					|		.data
TEST:	.WORD	^M<>			|		.text
	PUSHL	4(AP)			|	_test:  .word	  L13
	CALLS	#1, W^ALPHA		|		subl2	$8,sp
	RET				|		pushl	4(ap)
					|		calls	$1,_alpha
					|		ret

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

In this example, I show how both compilers are smart enough to do compile
time testing of constant expressions.  This is included to be fair to C,
which does a generally "good" job of generating code.  It just ain't "great".

As can be seen, the generated code is effectively equivalent.  However, here
I raise a gripe to the template nature of the C compiler.  Since it assumes
there to be a data and a text portion to every routine/program, it emits a
".data" pseudo op, outputs the data, emits a ".text" pseudo op, and outputs
the text.  What results is two (count 'em) superfluous ".data" / ".text"
pseudo ops.  Now, this doesn't slow down the assembler a whole lot, but on
a loaded system, every little bit helps.  Likewise, where in the hell is
the label "LL0" ever used?  If you don't use it (and certainly, with a name
like "LL0", it is local), don't emit it.  The same thing holds true for
the routine entry mask being stored in "L13".  What ever for?  You only
use it once, so why clutter the symbol table with it?  C takes 10 lines
of assembly code to do what Bliss does in 5 lines.
----------------------------------------+-------------------------------------
literal P1 = 3,				|	#define P1	3
	P2 = 5;				|	#define P2	5
					|
routine test =				|	extern int alpha();
begin					|
    if P1 lss P2			|	test()
	then return 0			|	{
	else return 1			|	    if (P1 < P2)
end;					|		return 0;
					|	    else
					|		return 1;
					|	}
					|
	.TITLE  FOO			|		.data
					|		.text
	.PSECT  $CODE$,NOWRT,2		|	LL0:	.align  1
					|		.globl  _test
TEST:	.WORD	^M<>			|		.set	L13,0x0
	CLRL	R0			|		.data
	RET				|		.text
					|	_test:  .word	L13
					|		clrl	r0
					|		ret

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

In this example I show what happens when local variables are initialized
and compared.  I have to admit I was disappointed with Bliss here.  A "great"
optimizer should recognize that the local variables are initialized, never
modified, and compared.  This should reduce to a compile time test, and no
intermediate code should be generated.  Alas, both C and Bliss do the tests
at run time.  The same old complaint against C shows up here, though.  It
uses stack locals when it should use "r0" and "r1".  To be fair, other than
that, the code is the same for both compilers.
----------------------------------------+-------------------------------------
literal P1 = 3,				|	#define P1	3
	P2 = 5;				|	#define P2	5
					|
routine test =				|	extern int alpha();
begin					|
    local loc1 : initial(P1),		|	test()
	  loc2 : initial(P2);		|	{
					|	    int loc1 = P1,
    if .loc1 lss .loc2			|		loc2 = P2;
	then return 0			|
	else return 1			|	    if (loc1 < loc2)
end;					|		return 0;
					|	    else
					|		return 1;
					|	}
					|
	.TITLE  FOO			|		.data
					|		.text
	.PSECT  $CODE$,NOWRT,2		|	LL0:	.align  1
					|		.globl  _test
TEST:	.WORD	^M<>			|		.set	L13,0x0
	MOVL	#3, R1			|		.data
	MOVL	#5, R0			|		.text
	CMPL	R1, R0			|	_test:  .word	L13
	BGEQ	1$			|		subl2	$8,sp
	CLRL	R0			|		movl	$3,-4(fp)
	RET				|		movl	$5,-8(fp)
1$:	MOVL	#1, R0			|		cmpl	-4(fp),-8(fp)
	RET				|		jgeq	L17
					|		clrl	r0
					|		ret
					|	L17:	movl	$1,r0
					|		ret

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

In this example, I construct a structure that consists of a pointer and
a data part.  The operation that is being performed is that of moving the
data part of one component to the data part of the component immediately
preceeding it in the linked list.  The mechanism is more naturally expressed
in C, but Bliss outperforms it even in light of the "irregular" constraints
placed on the code generator.

Since the Bliss optimizer has some flow control analysis built into it, it
is able to eliminate common sub-expressions from complex statements or groups
of statements.  In this case, the common subexpression (using C syntax) is
the pointer chain "a->p->p->p->".  Bliss is able to recognize this commonality,
and evaluate that chain only once.  Since C, on the other hand, has only a
peephole optimizer to work with, it fails to see this common subexpression,
and evaluates both "a->p->p->p->d" and "a->p->p->p->p->d" completely.  Without
a doubt, the Bliss generated code is both more speed and space efficient than
the C generated code.
----------------------------------------+-------------------------------------
switches structure(ref block[2]);	|	typedef struct dp *DP;
field CP =				|	struct dp {
    set					|	    int d;
    d = [0,0,%BPVAL,0],			|	    DP  p;
    p = [1,0,%BPADDR,0]			|	    }
    tes;				|
					|	test(a)
routine test(a)  : NoValue =		|	DP a;
    begin				|	{
    map a : ref block[2] field(CP);	|	    a->p->p->p->d =
    a[p][p][p][d] = .a[p][p][p][p][d];  |	 	a->p->p->p->p->d;
    end;				|	}
					|
					|
	.TITLE  FOO			|		.data
					|		.text
	.PSECT  $CODE$,NOWRT,2		|	LL0:	.align  1
					|		.globl  _test
TEST:	.WORD	^M<>			|		.lcomm  L16,8
	MOVL	4(AP), R0		|		.set	L12,0x0
	MOVL	4(R0), R0		|		.data
	MOVL	4(R0), R0		|		.text
	MOVL	4(R0), R0		|	_test:  .word	L12
	MOVL	@4(R0), (R0)		|		movl	4(ap),r0
	RET				|		movl	4(r0),r0
					|		movl	4(r0),r0
					|		movl	4(r0),r0
					|		movl	4(ap),r1
					|		movl	4(r1),r1
					|		movl	4(r1),r1
					|		movl	*4(r0),*4(r1)
					|		movab	L16,r1
					|		movq	(r0),(r1)
					|		movab	L16,r0
					|		ret
Newsgroups: net.lang.c
Path: decwrl!decvax!genrad!wjh12!bbncca!keesan
Subject: Re: C "optimization" (6 of 8)
Posted: Thu Feb 16 15:03:53 1984


-----------------------------
    This particular example is fatuous.  You complain about the  C compiler
emitting unnecessary assembler pseudo-ops and labels, because they "slow the
assembler down", and "on a loaded system, every little bit helps."  This is
totally silly.  The extra code and processing in the C compiler to eliminate
extra lines of assembler code are likely to put as much of a load on a system
as the extra processing in the assembler.
-- 
					Morris M. Keesan
					{decvax,linus,wjh12,ima}!bbncca!keesan
					keesan @ BBN-UNIX.ARPA
8.24REX::MINOWFri Apr 20 1984 13:2534
RE: .20

DECtalk was developed by a researcher at MIT using a PDP-11 running
Unix and a DEC-20 running TOPS-20.  All code was in C.  We converted
the code to Decus C to run on RT11 to show management that it worked,
then to C for the 68000 for the product.  We may choose the J11 for
the next generation, and probably will choose a microvax for
subsequent versions.

We went from purchase of the rights to DECtalk to a product in 18
months total, and less than 2 man-years programming.

By using a transportable language, we could test and debug the
algorithms on a convenient operating system (Vax-11C on VMS)
-- using "real" hardware for final testing.  This gave us
a great advantage in time, as the compile/link/upload/rom-blast
cycle takes about 2 hours, while compile/link/run on VMS takes
a minute or so.

During field-test of DECtalk, we were able to distribute a support
library that ran on VMS, RSTS, RSX (PRO), and Unix without source
code edits.

While DEC may well still get most of its revinue from hardware sales,
I would be willing to bet that most of the engineering man-hours are
spent doing software (including rom-blasted firmware).  According
to a friend who is in a position to know however, the balance is
still 60% hardware, 40% software.  "Software people are generally
less productive per man, although there is great variability."

Most people I know who use both Bliss and C feel they are much more
productive in C.

Martin
8.25ELUDOM::ARSENAULTFri Apr 20 1984 16:39110
From:	FAIMAN       "Neil Faiman   ZKO2-3/N30   381-2017"   27-OCT-1983 09:16  
To:	TRACE,@BLISS
Subj:	Some words of wisdom from Al Lehotsky

From:	BABEL::DUNCAN       "381-2054  ZK2-3/N30"   27-OCT-1983 09:11  
To:	CHIP,ELUDOM::MOORE,NEIL
Subj:	amusing note from lahotsky -- Also, the info may help with DECUS talks etc.

From:	BABEL::SEGAL        "Bill"   27-OCT-1983 08:32  
To:	ELUDOM::LUPTON,DENNIS
Subj:	fyi

From:	WILL           26-OCT-1983 17:35  
To:	SEGAL
Subj:	fyi, words of wisdom from Lehotsky

From:	BETZ           26-OCT-1983 15:24  
To:	MOORE,JACOBSON,BARNES
Subj:	bliss vs. c

>From alan@apollo.UUCP (Alan Lehotsky) Sun Feb  6 01:28:16 206
Relay-Version: version B 2.10.1 6/24/83; site decvax.UUCP
Posting-Version: version B 2.10 Apollo; site apollo.UUCP
Path: decvax!wivax!apollo!alan
From: alan@apollo.UUCP (Alan Lehotsky)
Newsgroups: net.unix-wizards,net.lang.c
Subject: Re:  From VMS to UNIX
Message-ID: <154@apollo.UUCP>
Date: Tue, 25-Oct-83 14:23:53 EDT
Article-I.D.: apollo.154
Posted: Tue Oct 25 14:23:53 1983
Date-Received: Tue, 25-Oct-83 15:35:56 EDT
References: <184@kobold.UUCP>
Organization: Apollo Computer, Chelmsford, Mass.
Lines: 77

I've decided to step into the BLISS vs. C battle -
as an (obviously) unbiased participant.  To pour
some volatile liquid on this fire, I make the following
assertions:

    I. BLISS is a better systems-programming language
        than C.  The built-in features of the language
        for dealing with

            o bit-fields
            o specific registers
            o user-defined linkage conventions
            o user-written accessing algorithms
              (the STRUCTURE declaration)
            o character sequence manipulation
            o VOLATILE memory

        are far superior to what C provides.  Further,
        the BLISS compile-time and macro-preprocessor
        facilities are orders of magnitude more powerful
        than what C gives you!  

          In BLISS, you can write an interrupt handler without
        invoking ANY runtime support - the compiler emits the REI,
        RTI, RTT or whatever and knows where the PC and PSL or PSW
        are on the stack, etc...

   II. The implementations of BLISS for the VAX, PDP11 and
        PDP-10 are FAR superior to any C compiler which I
        am aware of (for the same hardware).  On the average,
        I would estimate that BLISS produces code which is
        about 75% the size of code produced by the VAX/VMS
        C compiler - without the BLISS programmer attempting
        extensive optimization by doing any register declarations
        or special linkages!

  III.  With regard to the statement

>        There is nothing in the C language that
>        *prevents* me from writing a compiler as good as the VAX/VMS Bliss
>        compiler.
>        -- 
>        	Tom Teixeira,  Massachusetts Computer Corporation.  Littleton MA

        This is probably almost true.  But, it turns out that if you consider the
        effort required, you will discover that it is easier to do a BLISS
        compiler than the correspondingly high quality C compiler.

   IV.  C does have a few minor advantages:

            o Weak typing is convenient sometimes.
            o A lot of programmers know C, very few programmers know
              BLISS.

Now to really make your blood boil.....

    C would be the TECO of programming languages, if TECO wasn't
    already the TECO of programming languages.


    BLISS is a language designed for optimizing compilers, while C is
    a language designed for optimizing programmers.


Blissfully yours,
Alan Lehotsky (formerly BLISS Project Leader @DEC 1977-1983)

The following limerick may amuse you all...

    A languages wizard named Al,
    Found BLISS working at DIGIT-al.
    Though he coded and taught,
     and defends the damned dot;
    At Apollo, he's using PASCAL.
8.26ADVAX::A_VESPERWed Apr 25 1984 15:23330
[330 lines]

The previous reply (from Bill Barabash) discussed the difference
between the 4.1c BSD C compiler and the VAX/VMS BLISS-32 compiler more
than the difference between C and BLISS.  Here are the programs again,
but with the VAX/VMS C compiler results added.  (VAX-11 C V1.3-47)

Summary:  (1 for best, 2 for mediocre, 3 for bad)

		      BLISS	      4.1c C	    VAX/VMS C

alpha/beta		2		3		3
0/1 for 1 param		1		2		3
loop limit (5+a)/2	1		3		2
constant propagation	2		3		1
unused locals		1		3		1
constant if		1		1		1
constant prop. & if	2		3		2
common subexpression	1		3		1

Perhaps the BLISS and C compiler people should take a look at this to 
see if we can bring all tests up to '1'.

Warning -- BLISS and 4.1c C uses decimal offsets, VAX/VMS C uses hex. 

----------------------------------------+-------------------------------
external routine alpha;			|	extern  int	alpha();
external routine beta;			|	extern  int	beta();
					|
routine test(p,q,r,s,t) : novalue =	|	test(p,q,r,s,t)
begin					|	{
    if .t neq 0				|	    if (t!=0)
	then alpha(.p,.q,.r,.s)		|		alpha(p,q,r,s);
	else beta(.p,.q,.r,.s);		|	    else
end;					|		beta(p,q,r,s);
					|	}
					|

      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
	.TITLE  FOO	    |	.data		  | 
			    |	.text		  | 
   .PSECT  $CODE$,NOWRT,2   | LL0: .align  1	  | 
			    |	.globl  _test	  | 
			    |	.set	L14,0x0	  | 
			    |	.data		  | 
			    |	.text		  | test:
TEST:	.WORD	^M<>	    | _test:  .word L14	  | 	.entry	test,^m<r2>
						  | 	moval	(ap),r2
	TSTL	20(AP)	    |	tstl	20(ap)	  | 	tstl	14(r2)
	BEQL	1$	    |	jeql	L18	  | 	beql	vcg.1
	MOVQ   12(AP),-(SP) |   pushl   16(ap)	  | 	pushl	10(r2)
			    |	pushl	12(ap)	  | 	pushl	0C(r2)
	MOVQ	4(AP),-(SP) | 	pushl	8(ap)	  | 	pushl	08(r2)
			    | 	pushl	4(ap)	  | 	pushl	04(r2)
	CALLS	#4, W^ALPHA |	calls $4,_alpha	  | 	calls #4,alpha
	RET		    |	jbr	L19	  | 	ret	
			    |			  | vcg.1:
1$:	MOVQ   12(AP),-(SP) | L18: pushl 16(ap)	  | 	pushl	10(r2)
			    |	pushl	12(ap)	  | 	pushl	0C(r2)
	MOVQ	4(AP),-(SP) | 	pushl	8(ap)	  | 	pushl	08(r2)
			    | 	pushl	4(ap)	  | 	pushl	04(r2)
	CALLS	#4, W^BETA  | 	calls $4,_beta	  |	calls	#4,beta
	RET		    | L19:	ret	  |	ret	

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

----------------------------------------+-------------------------------------
external routine alpha;			|	extern  int	alpha();
					|
routine test(p,q,r,s,t) : NoValue =	|	test(p,q,r,s,t)
	begin				|	{
					|	    if (t!=0)
	if .t neq 0 then		|		alpha(p,q,r,s,0);
		alpha(.p,.q,.r,.s,0)	|	    else
	else				|		alpha(p,q,r,s,1);
		alpha(.p,.q,.r,.s,1);	|	}
	end;				|
					|
      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
	 		    |			  | 
			    |			  |
	.TITLE  FOO	    |	.data		  |
			    |	.text		  |
	.EXTRN  ALPHA	    | LL0: .align  1	  |
			    |	.globl  _test	  |
  .PSECT  $CODE$,NOWRT,2    |	.set	L13,0x0	  |
			    |	.data		  |
			    |	.text		  | test2:
TEST:	.WORD	^M<>	    | _test:  .word L13	  | 	.entry	test2,^m<r2>
			    |			  | 	moval	(ap),r2
	TSTL	20(AP)	    |	tstl	20(ap)	  | 	tstl	14(r2)
	BEQL	1$	    |	jeql	L17	  | 	beql	vcg.2
	CLRL	-(SP)	    |	pushl	$0	  | 	pushl	#0
			    |			  | 	pushl	10(r2)
			    |			  | 	pushl	0C(r2)
			    |			  | 	pushl	08(r2)
			    |			  | 	pushl	04(r2)
			    |			  | 	calls	#5,alpha
			    |			  | 	ret	
	BRB	2$	    |	jbr	L20004	  | 
			    |			  | vcg.2:
1$:	PUSHL	#1	    | L17: pushl $1	  | 	pushl	#1
2$:	MOVQ   12(AP),-(SP) | L20004:pushl 16(ap) | 	pushl	10(r2)
			    |	pushl	12(ap)	  | 	pushl	0C(r2)
	MOVQ	4(AP),-(SP) |	pushl	8(ap)	  | 	pushl	08(r2)
			    |	pushl	4(ap)	  | 	pushl	04(r2)
	CALLS	#5, W^ALPHA |	calls	$5,_alpha | 	calls	#5,alpha
	RET		    |	ret		  | 	ret	

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

----------------------------------------+-------------------------------------
routine test(a) : novalue =		|	test(a)
begin					|	int	a;
					|	{
    incr i from 0 to (5+.a)/2 do ;	|	    int i;
					|
end;					|	    for (i=0; i<=(5+a)/2; i++) ;
					|	}
					|
      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
	.TITLE  FOO	    |	.data		  | 
			    |	.text		  | 
   .PSECT  $CODE$,NOWRT,2   | LL0: .align  1	  | 
			    |	.globl  _test	  | 
			    |	.set	L12,0x0	  | 
			    |	.data		  | 
			    |	.text		  | test3:
TEST:	.WORD	^M<>	    | _test: .word L12	  | 	.entry	test3,^m<r2>
			    |			  | 	moval	(ap),r2
	ADDL3	#5,4(AP),R1 |			  |  	addl3	#5,04(r2),r1
	DIVL2	#2, R1	    |	subl2	$4,sp	  | 	divl2	#2,r1
	MNEGL	#1, R0	    |	clrl	-4(fp)	  | 	clrl	r0
			    |			  | 	cmpl	r0,r1
			    |			  | 	bgeq	vcg.4
			    |	jbr	L18	  | 
			    |			  | vcg.3:
1$:	AOBLEQ  R1, R0, 1$  | L20001:incl -4(fp)  | 	incl	r0
			    | L18: 		  |
			    |	addl3 $5,4(ap),r0 | 
			    |	divl2	$2,r0	  | 
			    |	cmpl	-4(fp),r0 | 	cmpl	r0,r1
			    |	jleq	L20001	  | 	bleq	vcg.3
			    |			  | vcg.4:
	RET		    |	ret		  | 	ret	
=============================================================================

----------------------------------------+-------------------------------------
external routine alpha;			|	extern  alpha();
					|
routine test(parm) : NoValue =		|	test()
	begin				|	{
	local a,b;			|	    int a, b;
					|
	a = 2;				|	    a = 2;
	alpha(.a);			|	    alpha(a);
	b = 5;				|	    b = 5;
	alpha(.b);			|	    alpha(b);
	end;				|	}
					|
					|
      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
	.TITLE  FOO	    | 	.data		  | 
			    |	.text		  | 
	.EXTRN  ALPHA	    | LL0: .align    1	  | 
			    |	.globl  _test	  | 
    .PSECT  $CODE$,NOWRT,2  |	.set	L13,0x0	  | 
			    |	.data		  | 
			    |	.text		  | test4:
TEST:	.WORD	^M<>	    | _test: .word  L13	  | 	.entry	test4,^m<>
			    |	subl2	$8,sp	  | 
	MOVL	#2, R0	    |	movl	$2,-4(fp) | 
	PUSHL	R0	    |	pushl	-4(fp)	  | 	pushl	#2
	CALLS	#1, W^ALPHA |	calls	$1,_alpha | 	calls	#1,alpha
	MOVL	#5, R0	    |	movl	$5,-8(fp) | 
	PUSHL	R0	    |	pushl	-8(fp)	  | 	pushl	#5
	CALLS	#1, W^ALPHA |	calls	$1,_alpha | 	calls	#1,alpha
	RET		    |	ret		  | 	ret	

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

----------------------------------------+-------------------------------------
external routine alpha;			|	extern  alpha();
					|
routine test(parm) : NoValue =		|	test(parm)
	begin				|	{
	local a,b;			|	    int a, b;
					|
	alpha(.parm);			|	    alpha(parm);
	end;				|	}
					|
      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
			    |			  | 
	.TITLE  FOO	    |	.data		  | 
			    |	.text		  | 
	.EXTRN  ALPHA	    | LL0: .align    1	  | 
			    |	.globl  _test	  | 
  .PSECT  $CODE$,NOWRT,2    |	.set	L13,0x0	  | 
			    |	.data		  | 
			    |	.text		  | test5:
TEST:	.WORD	^M<>	    | _test:  .word L13	  | 	.entry	test5,^m<>
			    |	subl2	$8,sp	  | 
	PUSHL	4(AP)	    |	pushl	4(ap)	  | 	pushl	04(ap)
	CALLS	#1, W^ALPHA |	calls	$1,_alpha | 	calls	#1,alpha
	RET		    |	ret		  | 	ret	

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

----------------------------------------+-------------------------------------
literal P1 = 3,				|	#define P1	3
	P2 = 5;				|	#define P2	5
					|
routine test =				|	extern int alpha();
begin					|
    if P1 lss P2			|	test()
	then return 0			|	{
	else return 1			|	    if (P1 < P2)
end;					|		return 0;
					|	    else
					|		return 1;
					|	}
      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
			    |			  | 
	.TITLE  FOO	    |	.data		  | 
			    |	.text		  | 
  .PSECT  $CODE$,NOWRT,2    | LL0: .align  1	  | 
			    |	.globl  _test	  | 
			    |	.set	L13,0x0	  | 
			    |	.data		  | 
			    |	.text		  | test6:
TEST:	.WORD	^M<>	    | _test:  .word L13	  | 	.entry	test6,^m<>
	CLRL	R0	    |	clrl	r0	  | 	clrl	r0
	RET		    |	ret		  | 	ret	

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

----------------------------------------+-------------------------------------
literal P1 = 3,				|	#define P1	3
	P2 = 5;				|	#define P2	5
					|
routine test =				|	extern int alpha();
begin					|
    local loc1 : initial(P1),		|	test()
	  loc2 : initial(P2);		|	{
					|	    int loc1 = P1,
    if .loc1 lss .loc2			|		loc2 = P2;
	then return 0			|
	else return 1			|	    if (loc1 < loc2)
end;					|		return 0;
					|	    else
					|		return 1;
					|	}
      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
			    |			  | 
	.TITLE  FOO	    |	.data		  | 
			    |	.text		  | 
  .PSECT  $CODE$,NOWRT,2    | LL0: .align  1	  | 
			    |	.globl  _test	  | 
			    |	.set L13,0x0	  | 
			    |	.data		  | 
			    |	.text		  | test7:
TEST:	.WORD	^M<>	    | _test:  .word L13	  | 	.entry	test7,^m<>
			    |	subl2	$8,sp	  | 
	MOVL	#3, R1	    |	movl	$3,-4(fp) |
	MOVL	#5, R0	    |	movl	$5,-8(fp) |
	CMPL	R1, R0	    |  cmpl -4(fp),-8(fp) |	cmpl	#3,#5
	BGEQ	1$	    |	jgeq	L17	  |	bgeq	vcg.5 
	CLRL	R0	    |	clrl	r0	  |	clrl	r0 
	RET		    |	ret		  |	ret	 
			    |			  | vcg.5: 
1$:	MOVL	#1, R0	    | L17: movl	$1,r0	  | 	movl	#1,r0
	RET		    |	ret		  | 	ret	

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

----------------------------------------+-------------------------------------
switches structure(ref block[2]);	|	typedef struct dp *DP;
field CP =				|	struct dp {
    set					|	    int d;
    d = [0,0,%BPVAL,0],			|	    DP  p;
    p = [1,0,%BPADDR,0]			|	    }
    tes;				|
					|	test(a)
routine test(a)  : NoValue =		|	DP a;
    begin				|	{
    map a : ref block[2] field(CP);	|	    a->p->p->p->d =
    a[p][p][p][d] = .a[p][p][p][p][d];  |	 	a->p->p->p->p->d;
    end;				|	}
					|
      VAX/VMS BLISS-32            4.1c BSD C            VAX/VMS C
	 		    |			  | 
			    |			  | 
	.TITLE  FOO	    |	.data		  | 
			    |	.text		  | 
  .PSECT  $CODE$,NOWRT,2    | LL0: .align  1	  | 
			    |	.globl  _test	  | 
			    |	.lcomm  L16,8	  | 
			    |	.set	L12,0x0	  | 
			    |	.data		  | 
			    |	.text		  | test8:
TEST:	.WORD	^M<>	    | _test: .word L12	  | 	.entry	test8,^m<>
	MOVL	4(AP), R0   |	movl	4(ap),r0  | 	movl	04(ap),r0
	MOVL	4(R0), R0   |	movl	4(r0),r0  | 	movl	04(r0),r0
	MOVL	4(R0), R0   |	movl	4(r0),r0  | 	movl	04(r0),r0
	MOVL	4(R0), R0   |	movl	4(r0),r0  | 	movl	04(r0),r0
			    |	movl	4(ap),r1  | 
			    |	movl	4(r1),r1  | 
			    |	movl	4(r1),r1  | 
	MOVL	@4(R0),(R0) |  movl *4(r0),*4(r1) | 	movl	@04(r0),(r0)
			    |	movab	L16,r1	  | 
			    |	movq	(r0),(r1) |
			    |	movab	L16,r0	  | 
	RET		    |	ret		  | 	ret	

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

The last 3 moves in the 4.1c BSD C are there to return a value of type 
DP.  That compiler copies a->p->p->p to a static location and returns 
a pointer to that location.  The VAX/VMS C compiler returns the 
pointer value a->p->p->p.  If there was a semicolon just after the 
definition of struct dp then these instructions would not be
generated. I add this note only because I was curious about it and
thought that others might be also. 
8.27VAXUUM::DYERSun May 06 1984 04:364
	A point was brought up in the UNIX notesfile (in the same directory
as this one) that Unix has caught on partially because the sources are in C
and thus hackable.  Any thoughts on this?
		<_Jym_>
8.28ORPHAN::BRETTSun May 06 1984 12:503
C doesn't imply HACKABLE so much as it implies HACKED.  Seriously though, its
the availability of the source, not its language.
8.29MANANA::BOEBINGERSun May 06 1984 20:0913
As for C's popularity, I wonder if C is popular because of UNIX, or
if UNIX is popular because of C.  In other words, are there more
C programmers because it's a great language, or because it is readily
available in the educational arena?

After all, if a measure of the greatness of a language was the
number of people who know it, the two clear winners would be
COBOL and BASIC.

My favorite comment is that BLISS is the language of the craftsman, and
C is the language of the hacker.

john
8.30PBSVAX::CAMPBELLMon May 07 1984 15:225
I would edit your comment very slightly (but significantly) by saying:
"BLISS is the language of the craftsman who doesn't mind writing code
that will only run on DEC hardware and couldn't care less about people
with hardware from other vendors."  I like BLISS, but damned if I want
to wire my code to VAXes, 11s, and 20s.
8.31ULTRA::HERBISONMon May 07 1984 18:0617
BLISS does have the problem with the dot, but C has similar problems.
For example, "=" is used for assignment and "==" is used to test
equality.  A frequent problem which has caused numerous problems
is someone using "-
"=" when they mean "==".  "if (a = 0) ..." sets a to zero and the
value of the condition is false.  This is normally easy to find,
"if (a = b) ..." can be more subtle.

Both this problem and the problem with the dot in BLISS would probably
not be as much trouble for a new programmer, they only catch people
who have used other languages.

The dot problem in BLISS occurs more often than the == problem in C.
[This is true in spite of the fact that I would prefer to use C rather
than BLISS.]

						B.J.
8.32XENON::STANSBURYTue May 08 1984 13:378
Someone on the USENET recently had a contest to determine the most unreadable
C program. They picked 4 programs as winners. The programs follow in the next
4 replies, starting with the one that won first place.

Any comments on these programs? Can anyone top these with unreadable BLISS
programs (keep them short please)?

Jack
8.33XENON::STANSBURYTue May 08 1984 13:3812
/* Portable between VAX11 && PDP11 */

short main[] = {
	277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800,
	-113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004,
	14880, 10541, 2056, 04010, 4548, 3044, -6716, 0x9,
	4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419,
	0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0,
	4, 0, 0, 0, 0x8, 0, 4, 0, ',', 0, 12, 0, 4, 0, '#',
	0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712,
	'p', 072163, 'r', 29303, 29801, 'e'
};
8.34XENON::STANSBURYTue May 08 1984 13:3933
#define x =
#define double(a,b) int
#define char k['a']
#define union static struct

extern int floor;
double (x1, y1) b,
char x {sizeof(
    double(%s,%D)(*)())
,};
struct tag{int x0,*xO;}

*main(i, dup, signal) {
{
  for(signal=0;*k * x * __FILE__ *i;) do {
   (printf(&*"'\",x);	/*\n\\", (*((double(tag,u)(*)())&floor))(i)));
	goto _0;

_O: while (!(char <<x - dup)) {	/*/*\*/
	union tag u x{4};
  }
}


while(b x 3, i); {
char x b,i;
  _0:if(b&&k+
  sin(signal)		/ *    ((main) (b)-> xO));/*}
  ;
}

*/}}}

8.35XENON::STANSBURYTue May 08 1984 13:4013
a[900];		b;c;d=1		;e=1;f;		g;h;O;		main(k,
l)char*		*l;{g=		atoi(*		++l);		for(k=
0;k*k<		g;b=k		++>>1)		;for(h=		0;h*h<=
g;++h);		--h;c=(		(h+=g>h		*(h+1))		-1)>>1;
while(d		<=g){		++O;for		(f=0;f<		O&&d<=g
;++f)a[		b<<5|c]		=d++,b+		=e;for(		f=0;f<O
&&d<=g;		++f)a[b		<<5|c]=		d++,c+=		e;e= -e
;}for(c		=0;c<h;		++c){		for(b=0		;b<k;++
b){if(b		<k/2)a[		b<<5|c]		^=a[(k		-(b+1))
<<5|c]^		=a[b<<5		|c]^=a[		(k-(b+1		))<<5|c]
;printf(	a[b<<5|c	]?"%-4d"	:"    "		,a[b<<5
|c]);}		putchar(	'\n');}}	/*Mike		Laman*/

8.36XENON::STANSBURYTue May 08 1984 13:403
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}

8.37MANANA::BOEBINGERWed May 09 1984 00:4820
Drat.  I forgot to put the tounge in cheek sign next to the hacker
and craftsman comment.  Heavy sigh.

Protability is clearly an issue if we plan on moving things from
architecture to architecture.  But if they are all major DEC
machines (11's, VAX, 20), then there is (or will be) a good BLISS
compiler for it.  So compilers and data managers that are going to
be major DEC products can be written in BLISS.

On the other hand, if you have something that may be moved to
a non-DEC machine (like DECtalk) then you might be better off
with C, and accept the fact that on VAXen or 11's you will end
up with poorer code.

I must confess that I'm a little surprised that C compilers aren't
a lot better than they are.  Since there are schools all over
the country hacking away at C, why is it that a small, isolated
group in ZK is putting out a superior compiler?

john
8.38REX::CONROYThu May 10 1984 21:3833
Re .37
Most of the folks in the universities that are hacking away at C are
just doing that, hacking. I have never come across anybody in the UNIX
user community that was actually working on an optimizing C compiler
[there may be one, I just havn't come across one]. In general, C compiler
hacking follows the following path:
	1) Observe a machine that does not have C on it.
	2) Analyze the machine for 15 minutes or so, at least long
	enough to understand what is different between it and the
	PDP-11 (or VAX).
	3) Decide if you are going to hack at the Ritchie compiler
	or use PCC. This is a complex decision:
		3a) the Ritchie compiler's register allocation scheme
		is very ungeneral; it really doesn't know how to deal
		with the FPP at all (usually it says "Expression needs
		too many registers", but I have seen expressions that
		faked out the check and compiled code up to AC6.
		If your machine doesn't have general registers, with
		even odd pairs for MUL and DIV, this is a bad choice.
		3b) PCC has been hacked more times, so chances are you
		can find something closer.
	4) Write the code tables (or whatever) as quickly as possible,
	and don't worry if you generate funny or bad code for strange
	expressions, like (a %= b for unsigned longs on the PDP-11).
	5) Declare the project *DONE* and go one to something else,
	like porting UNIX to the machine.
Given this, I am not at all surprized that the little group in ZK are
doing a better job. 
On the fair side, there are some folks that are doing a piece of the
problem (some code generation aspects, etc), but nobody ever gets around
to sitting down and slugging through the whole language.

dgc
8.39NEWTON::NORTONFri May 11 1984 13:4625
Random remarks:

Real optimizing compilers seem far more advanced than two grad level compiler
courses, or perhaps the details of really doing the whole job is too much.  In
any event the only things that come out of universities seems to be 60% of a
decent code generator for the latest fad micro.  The high turnover of the slave
labor work force seriously impairs interesting (many human years) efforts.

C code in places where it really counts, (unix kernel) is often coded by a 
human that knows what's going to be generated.  Looking at the generated code
in drivers (all in C in unix) and internals you see that they get exactly what
you would have stuffed in by hand.  This is the "fancy assembler" view of C.
There are even some source --> source optimizers for C, but the ones I've seen
are essentially peephole, rather than mangle a DAG.

Both the C and pascal code generators (parse tree in, assembler text out)
on 4.n unix are pcc.  

In the unix 4.n kernel, jsb's are used instead of calls, for the obvious reason.
To do this without mangling the compiler, the kernal makefile is of the form
source >cc>> assembler_text >sed=mung>> "assembler text with sub/calls/jsb/"
>assembler>> etc.  This is probably the right way to do it, given that it takes
at most four hours to write (simple editor script) and doesn't noticibly slow
down system build (say 4 mins for compile one module, and link all into 
new system).  Not a general soln to the linkage problem, but very effective.
8.40BABEL::HOBBSFri May 11 1984 21:4861
The fact that many C compilers have been written as computer science
projects has been used as an explanation for the poor code of C relative
to BLISS.  However, the BLISS compiler used by Digital was not originally
written "by a small group in ZK".  Instead it was written as computer
science project by one faculty member and small group of grad students
at CMU.  If any of those original grad students were to look at the
code in Digital's BLISS compiler they would find much of the code
very familar.

The major difference in code quality between BLISS and C is not the
nature of their implementation teams but instead the philosophy of
their language and compiler designers.  The original design of BLISS
was based on the principle that the user would use the various
language features (including macros and structures) to write easy
to understand and maintain code and that the programmer would depend on
the optimizer to make the details of code generation efficient.
The C designers acted on the principle that optimizing compilers
are very buggy and often do not understand how to do the optimizations
anyways.  Instead the C language encourages the user to use low-level
C primitives to "hand optimize" the code.  (An example is that C
programmers are encouraged to put the address of an array in a
pointer variable declared with a register declaration
prior to entering a loop and then stepping the pointer inside the loop.
This obscures that fact that algorithm is using a simple indexing
abstraction but guarantees that the compiler generates an efficient
auto-increment or strength-reduction--an optimization that BLISS
often misses).  Steve Johnson, one of the Bell Labs personnel involved in
early C design, has participated in debates at programming language
conferences arguing against optimizing compilers--citing the buggyness
of optimizing compilers and claiming the hand-optimization by the
programmer is much more effective.

BLISS, Pascal, Ada and many other languages have restictive rules on
when a program can depend on side-effects occuring.  These rules are
designed to encourage optimizing compilers.  Such rules are much
more lax in C making it easier for the programmer to hand optimize but
making it much more difficult for the compiler do optimization.

Any C implementer that stays true to the philosophy of the
original C design will do only minimal optimization.  Any C programmer
who stays true to the philosophy of the original C design will
include a lot of hand optimization in the source code.

On the other hand, a BLISS implementer who follows the original BLISS
design will do all optimizations possible.  (Often in the original
design of the BLISS compiler someone would argue against doing an
optizimation (like checking for subtracting a value from itself) because
no programmer would write such nonsense but usually the optimization
was included because the argument went that some trivial invocation
of a high-level concept implemented with a BLISS macro or structure
might result in obviously redundant operations).  Also, a BLISS programmer
following the philosophy of the language will use macros and structures
to implement high-level abstractions so the code is easy to understand
and modify while depending of the compiler's optimizer to generate
efficient object code.

I believe that C would be a better language if the implementers and
programmers would ignore Steve Johnson's arguments against optimizing
compilers.  I believe that any university with a good computer science
department can have a project that will implement an efficient optimizing
compiler.
8.41VAXUUM::DYERTue May 15 1984 03:0416
	*Sigh...*  I remember the compiler we were working on at WPI:  A
re-re-re-modification of Steve Johnson's Portable C Compiler.  What a tra-
vesty!
	Yes, I like the idea of the C language being very low-level.  It's
really useful that way.  But let's give it all the optimization we can!
	I generally like to code in (get this!) assembly language or Lisp.
If I'm not proficient with the machine's assembly language, I'll use C.
(I'll also use C to get something done quicker, or if I want to write some-
thing portable, or if I want to get a great utility from Usenet's net.sour-
ces working on the VAX.)
	If I'm going to have to do my own optimizing, I suspect I'll have
to know so much about the machine that I might as well use the assembly
language!  Let the compiler do it; that's its job!  If it's a great lan-
guage that will let me do the optimizing as well, more power to it!  ...or
rather, more power to the programmer!
		<_Jym_>
8.42VLNVAX::RDFTue May 15 1984 04:5617
I may have missed it in the mass of replies here, but only knowing about
C what I saw from a few short glances at the VAX users guide and from
some software I've seen, a major facet of BLISS, namely condition handling
support, does not pop out at you.

In implementation of any system, the CLEAN handling of error conditions can
make the difference between an unmaintainable mess and a supportable product.
I've had no problems with BLISS in this area, and really feel that this was
quite a good implementation.  The nice thing about this is that it is not
directly tied to VMS (even though it is probably based on the VAX condition
handling facility), condition handling in BLISS-32 and 36 work the same even
though the CHF on BLISS-36 is in run time software.

Question.  Does C provide a condition handling facility proper, or is this
           left to the person who is porting the C program from one system
	    to another?  How do you do condition handling in C?
8.43ADVAX::A_VESPERTue May 15 1984 12:4418
As far as I know, there is no general purpose condition handling
available for C programs. 

The 'setjmp' and 'longjmp' routines allow you to set up a 'return
to here' point then later (from routines called by the routine
that did the 'setjmp') return to that point.  This is kinda like
a SIGNAL, but there is no way to continue.  I don't know about
multiple 'setjmp's. 

My DECUS C library manual mentions a pair, similar to the above,
called 'envsave' and 'envreset'.  Similar things occur, but you
get a pointer from 'envsave' which you give to 'envreset' so that
you can have multiple environments to which you can return. 

Again, you can only return up the stack (unwind), you can't
continue and you only catch explicitly generated signals. 

Andy Vesper
8.44VLNVAX::AMARTINTue May 15 1984 18:3715
Unwinding is the hard part.  Just keeping a global which contains the address
of a procedure to call when encountering any particular signal would suffice
for signals that expect to continue.  As far as hardware or O/S generated
signals go, it shouldn't be that hard to set up interrupt routines that can
use such globals.  But knowing how to peel off layers of the stack (in a
way that works across compiler releases) always struck me as the real challange.
Gee, the idea of storing the addresses of handler routines is in Vax-11 C.
The routines gsignal/signal/ssignal deal with the routines.  And some of the
signals are for things like illegal instruction traps.  Manuals can be a help.

The Vax-11 C manual claims that setjmp and longjmp provide "equivalent
functionality" to a similar feature on (some) Unix systems.  Does anyone
know whether the calling sequences are the same, or is it even more different
than different calling sequences?
				/AHM
8.45ORPHAN::BRETTTue May 15 1984 23:207
The REAL trick on VAX/VMS is you can 'peel off layers of stack' in a way that
works across compiler releases AND ACROSS MULTIPLE LANGUAGES!!!!!!!!!!!!!!!!!

The multi-language support is a HUGE win.

/Bevin
8.46REX::CONROYWed May 16 1984 01:4014
It is indeed possible for a Computer Science department to do what Bill
Wulf et al. did at CMU; that is write an optimizing compiler system. But
most of the "60% of a decent code generator for the current fad micro"
isn't organized; it's just hacking.

You will all be glad to know that the ANSI C standards group (who are,
by the way, happily designing a new language that looks just a little like
C) keep muttering things about not being able to do any optimization at
all. After all, that integer pointer in a user program just might be
pointing at a memory word that changes value every time you read it. They
havn't thought about the consequences of registers with read only and
(especially) write only bits yet.

dgc
8.47HERMES::MARTINWed May 16 1984 04:128
Re .45:

How is Vax-11 Ada dealing with exception handlers which are not enabled
immediately upon entry to a block (inner compound statements with handlers)?

Are you making the block an anonymous routine in the generated code, and
using the Vax condition handling facility, or something else?
				/AHM/THX
8.48VAXUUM::DYERWed May 16 1984 11:183
	C is a low-level (medium-level for you purists) language.  If you want
a condition handler, you have to write one yourself.  Just call lib$establish().
		<_Jym_>
8.49ADVAX::A_VESPERWed May 16 1984 12:4615
re .44: 'setjmp' and 'longjmp' ARE compatable with many
other C run time systems.  I have written programs using
these which run on both VAX-11 C and DECUS C systems.  
Although I have not actually made the tests, the 
various descriptions of the functions are the same in all 
the manuals I have checked.

re ???:  The latest I have heard about the C standard 
committee is that they were trying to clarify some ambiguous 
points in K&R, and establish things like the number of 
significant characters in C identifiers.  I have not heard 
that they are designing a new language.  Could the DEC 
representative (I sure hope we have one!) comment, please?

Andy Vesper
8.50VLNVAX::RDFWed May 16 1984 12:5918
re. 48  That works on VMS, but C is supposed to be so portable....  I really
        feel that a language like C needs some form of a CHF imbedded in its
	design, rather than relying on the O/S.   The problems stated about
        being able to continue or not, catch certain exceptions or not, all
	require loads of system dependent code to be written to create your
	own form of CHF.   It sounds like the C library could be updated to
	include an expanded form of what exists now to do a SIGNAL/SETUNWIND
	type of thing.

re. 46  Isn't that what VOLITILE is for?  If you want to make sure that a data
	item is current, you can state this in BLISS, but it really is no reason
	for the compiler to not do optimizations, at least in this case.

Thanks for the info.  I'll drag out the C manual and see if I can get some 
stuff to work as part of a "taste test".

-Rick
8.51REX::MINOWWed May 16 1984 20:2731
signal() is reasonably compatible across Vax-11C and the various Unices.
I didn't add it to the Decus C library for two reasons:  first, I didn't
need it (!) and second, I couldn't figure out a way to do it compatibly
across RSX, RT11, and RSTS/E (a problem faced by other language implementors
and one of the reasons RSTS/E Basic-Plus hasn't been ported to other
operating systems).  Jim Burrows once wrote a RSTS/E-specific signal
handler and a good RSX hacker could probably do one for RSX.

The most interesting "signal", Control/C trap, has been implemented
on most Decus C operating-systems using the "setcc" function.

The "envsave" routines were quite old -- they were either compatable
with some Unix V6 stuff or were an invention of Dave Conroy while
he was still a grad student.

One final note.  In a long article in USENET recently, a writer noted
that he used C because "the lifetime of software greatly exceeds the
lifetime of hardware implementations" -- this is, of course, an
argument for any well-supported higher-level language, whether it
be C, Datatrieve, or Lisp.

Even sitting here inside Dec, I can't trust the language groups to
move my favorite language to the hardware I base my product on.
I learned that lesson while watching the long-running attempts
to kill off non-approved operating systems (RSTS/E and IAS) which
*only* resulted in delaying necessary functionality enhancements
(such as DECnet Phase 4).  By working in an easily retargetable
language, I may increase my product cost, but I feel I minimize
the overall product risk.

Martin.
8.52REX::CONROYWed May 16 1984 21:0157
I am glad to see that Martin has sent me to grad school.

The "envsave" and "envrest" were the original 5th edition UN*X catch
and throw ops.

There is a hidden trap in "setjmp" and "longjmp". Consider the following
hunk of code:

		main()
		{
			if (setjmp(env) != 0) {
				printf("I returned to main\n");
				exit();
			}
			signal(SIGINTR, &catch);	/* ^C catch	*/
			for (;;)
				printf("Hello\n");
		}

		catch()
		{
			longjmp(env, 1);
		}

The program is looping, saying "Hello". You type ^C. It types out "I returned
to main" and quits.

Well, maybe. The printf is jamming data into a buffer by decrementing a byte
count and incrementing a pointer to the buffer. Let's say that that the pointer
is bumped first, then the count is decremented (a possible implementation).
Just after it increments the pointer you type ^C. The longjump pulls control
out of the "putchar" routine. However, the pointer is 1 byte farther along
than the count says it is! The I/O package could scribble on something next
time it was called. 

The important thing to remember is that just because your program can take
a signal, it doesn't mean that the library can. Library routines should be
written in a way that allows signals, but often are not.

Andy, there are lots of things in the new proposed standard that are the
invention of the committee. Functions doing type conversions on arguments.
The wretched "const" syntax. The changes to the type propogation rules for
floats (all because they couldn't think of a syntax for single and double
precision floating point numbers, even though FORTRAN has had one for
years). Etc., etc.

I have done about a half dozen C compilers. There are places in K&R where
you really have to read between the lines to decide what should be done.
What does ":0" do in an "int" declaration on a machine that has no alignment
requirements for words. What is the combination type for 2 unsigned shorts.

It is a pity that people believe that all of the C compilers in the world
are incompatable because the language has no standard. In fact, most of
them are incompatable because the implementors either didn't understand the
issues, or were too lazy to do the hard parts.

dgc
8.53ORPHAN::BRETTWed May 16 1984 21:0218
Ada 'rationale' is that exception handlers should be placed as tightly as
possible around the code being 'watched', and that the exception handling
mechanism should not 'significantly' increase the execution time of a program
that doesn't actually raise an exception.

Given these constraints, we DON'T build an 'anonymous call frame' around
blocks with exception parts.  Instead we keep a pointer to a constant data
structure that describes the current nested list of blocks with exception
parts and update the pointer as required.   This typically adds only two MOVAL
instructions (one to set, and one to reset) to the code required for the
block statement.

Note that not only does Ada not have SS$_CONTINUE semantics, but the exception
handling model has the exception part unwound too.  For various reasons it is
pratically impossible to do anything else - as we found out after literally
years of revisiting the problem each time a new discovery was made.

/Bevin
8.54VLNVAX::AMARTINWed May 16 1984 23:4721
I agree that maintaining a pointer to a push down list of handlers is
cheaper than using stack frames for every handler.  As well as being slightly
cheaper than requiring every stack frame to have space for a handler. That
is the way Bliss-36 implements condition handling.
				     
Considering the fact that all standard Vax stack frames have space set aside
for a condition handler pointer (which is explicitly zeroed duirng a call),
I got a kick out of reading this in the Vax Architecture Handbook:

"The goals in developing the VAX Procedure Calling Standard were:
...
The standard should add no space or time overhead to procedure calls ... that
do not establish handlers..."

It reminds me of the FRED calling standard for the PDP-10 that has a goal of
supporting Algol, but neither discusses nor implements call-by-name.

If an Ada block_statement with an exception_handler for NUMERIC_ERROR calls a
Fortran routine which divides by zero, will the Ada exception handler have a
chance to gain control?  Or are exceptions and conditions entirely separate?
				/AHM
8.55ORPHAN::BRETTFri May 18 1984 02:147
IF there is a handler for NUMERIC_ERROR then that handler will be UNWOUND to,
otherwise the presence of the exception_part is (almost) invisible.  Off hand
I think we mark the signal as 'non-continuable' because ADA SEMANTICS DEMAND
IT (ie - this is not a negotiable issue).

/Bevin
8.56ORPHAN::BRETTFri May 18 1984 02:169
Note though that Ada exception handling is built on top of, and not using 
anything but, VMS condition handling.  I like, and approve of, 99% of the
condition handling support.

The only thing I don't like is specifying how many frames to unwind rather
than which to unwind too.  The later is MUCH cleaner.

/Bevin
8.57ALIEN::PETTENGILLMon May 28 1984 03:2129
I'm rather skeptical about the claims that BLISS takes a year to learn or like
while C only takes a month.  No language I have learned has taken less than a
year to for me to become "truely competent".  However, I've done a lot of
productive work in it prior to that point.

[As an off the wall example, I had been reading and writing MACRO-11 code for
about 8 years, (I certainly rank in the top 1% of MACRO-11 coders for quality),
before I learned of the following code sequences:

	RETSUC:	TST	(PC)+		; Clear carry and skip next instruction
	RETERR:	SEC			; Set carry
		RETURN			;

	BIT	(PC),2(R0)		; Reuse the constant 2

The former is generally useful while the latter is best left to a compiler;
BLISS generates the the latter when possible.]

I don't know C and I find the listings of C code segments very difficult to
understand.  I can't believe that I would be comfortable reading C code in
only a month.  I was able to follow BLISS-11 code after only a few days of
reading the DECUS BLISS-11 documentation.  (Note, BLISS-11, NOT BLISS-16;
BLISS-16 is in many ways simpler than BLISS-11.  I didn't know 9 years ago
that BLISS was such a difficult language, I guess.)  I have read, or tried to
read, books on C and PASCAL.  I find myself trying to figure out how to do
some of the things simple in BLISS in these languages, but the books don't
seem to offer much guidance.  The languages I know best I have read extensively.
Perhaps after a year of using C I would be able to read C as well as I can read
BLISS or MACRO.  Only then would I consider myself competent in C.
8.58WEBSTR::BEYERWed Jul 11 1984 18:2121
re: exception handling in C

Someone with the last name of Lee (I think) gave a talk about a year ago
about implementing something very like Ada's exception handling using
SETJMP and the preprocessor.  It's quite simple, and easily exstensible -
I've modified it to keep a stack of errors like VMS signalling, and to catch
signalled errors and bring them into the exception process.  The best feature
of this kind of error handling is that the penalty to the programmer for doing
it right is very low.  He doesn't have to write a seperate routine and the
code to handle an error is right next to the code that caused it.  It doesn't
allow continuing from an error though; once you've raised an exception there's
no coming back.

SETJMP/LONGJMP, by the way, implement a real crude method of unwinding the 
stack.  SETJMP saves all the processor registers, and LONGJMP restores them.
It means that any intermediate calls don't get a chance to clean up (unless
you do the above kind of exception handling - then they can catch all 
exceptions, clean up, and reraise them), and variables may be in indeterminate
states depending on whether they were in registers or not.

	HRB
8.59Some ObservationsCOMICS::DEMORGANRichard De Morgan, UK CSC/CSWed Sep 23 1987 12:5217
    I see that I'm bringing up an old topic here, but a few comments
    seem to be in order:
    
    Re .13 "what other language allows you to declare something as a
    pointer to a function returning a pointer to a real?" - Algol 68.
    
    Re .15: At an IFIP WG2.4 (Software Engineering) meeting that I attended
    seveal years ago, Bill Wulf admitted that the dot in Bliss was,
    in retrospect, a disaster.
    
    Re .54: What is the FRED callin standard for PDP-10? We implemented
    Algol 60 long before the first meeting of the Calling Standard Ctte
    (I only attended one meeting - and explained how we did Algol 60
    stacks - before I went back to the UK.
    
    I've written a lot of Bliss in my time, but draw the line at C.
    Nowadays I program in Ada.
8.60TLE::JONANMe/Gauss = Cow/CalculusFri Sep 25 1987 16:496
>    Re .13 "what other language allows you to declare something as a
>    pointer to a function returning a pointer to a real?" - Algol 68.
    
    Also, MODULA-2 :-) (and rather clearly I might add...)
    
    /Jon
8.61AITG::VANROGGENSat Sep 26 1987 01:091
    And also Common Lisp, although there's no explicit notion of "pointer".
8.62Waiting for FREDDENTON::AMARTINAlan H. MartinSat Sep 26 1987 07:335
Re .59:

If I find a copy of FREDX.MEM kicking around, I'll send you a copy.  It'll
probably be months before I'm likely to see it, I'm mostly in boxes now.
				/AHM
8.63TLE::JONANMe/Gauss = Cow/CalculusMon Sep 28 1987 12:5310
>    And also Common Lisp, although there's no explicit notion of
>    "pointer".
    
    A similar thing can be said of smallTalk.  In fact, in both these
    cases though the *how* of what you're doing is not clear (really
    not even specified by the programmer...) the *functionality* wanted
    is exceptionally clear.  On the other hand, both are rather "glacial",
    *sigh*.
    
    /Jon
8.64FRED has arrivedDENTON::AMARTINAlan H. MartinThu Oct 08 1987 04:175
Re .59,.62:

Thanks to the efforts of Fortran-10/20 project member Julie Brewer, a
world-readable copy of FREDX.MEM now resides on TLE""::UPORT$:[AMARTIN].
				/AHM