[comp.software-eng] Source File Organization

rfarris@rfengr.com (Rick Farris) (02/26/91)

I have a problem that I'm sure has been solved in the C
language before; would someone point me in the right
direction?

I have an enumerated type:

typedef enum { A, B, C, D } CMD;

and a corresponding array of ascii representations :

char ltrs[] = { 'A', 'B', 'C', 'D' };

used for printing and other various purposes.  (Of course
the real problem is much more complicated than this, but
this simple example is sufficient for illustrative
purposes.) 

My problem is: How do I keep the darn things in sync?

Suppose I add a new CMD, "Z", is there any way to ensure
that ltrs[] is updated?

The problem is exacerbated by the fact that the CMD enum,
being a typedef, is in a header file that is included in
many places.  Since ltrs[] is an instantiated variable, it
*can't* live in the same place.  Where should it live?  

Thanks!


--
Rick Farris  RF Engineering POB M Del Mar, CA 92014  voice (619) 259-6793
rfarris@rfengr.com     ...!ucsd!serene!rfarris      serenity bbs 259-7757

pkr@media01.UUCP (Peter Kriens) (02/27/91)

> typedef enum { A, B, C, D } CMD;
> and a corresponding array of ascii representations :
> char ltrs[] = { 'A', 'B', 'C', 'D' };
...
> The problem is exacerbated by the fact that the CMD enum,
> being a typedef, is in a header file that is included in
> many places.  Since ltrs[] is an instantiated variable, it
> *can't* live in the same place.  Where should it live?

You could place the table in the header file like

	typedef enum { A, B, C, D ) CMD;
	#ifdef _CMDDEF_
	char ltrs = { 'A', 'B', 'C', 'D' };
	#endif

This would at least take care of the fact that they are close together
which means that the change of noth being updated simulteneous is actually
not zero. The only thing you have to do in the source that is allowed
to define the table ltrs, is defining _CMDDEF_ before you include the
header file

Peter Kriens

peter@ficc.ferranti.com (Peter da Silva) (02/27/91)

In article <1991Feb26.045242.23453@rfengr.com> rfarris@rfengr.com (Rick Farris) writes:
> My problem is: How do I keep the darn things in sync?

Try this:

---- ltrs.h
typedef enum { A, B, C, D } CMD;
#ifdef LTRS_C
char ltrs[] = { 'A', 'B', 'C', 'D' };
#else
extern char ltrs[];
#endif
---- ltrs.c
#define LTRS_C
#include "ltrs.h"
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

jls@yoda.Rational.COM (Jim Showalter) (02/27/91)

In Ada, you'd just use the 'IMAGE attribute on the enumerated type,
which would eliminate the double-entry bookkeeping problem you
describe at no cost to you.

Of course, Ada is a big language with lots of useless bells and 
whistles, according to every C hacker I've ever met.

(No smiley.)
--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (02/27/91)

In article <1991Feb26.045242.23453@rfengr.com>, rfarris@rfengr.com (Rick Farris) writes:
> I have a problem that I'm sure has been solved in the C
> language before; would someone point me in the right
> direction?

> typedef enum { A, B, C, D } CMD;
> char ltrs[] = { 'A', 'B', 'C', 'D' };

> My problem is: How do I keep the darn things in sync?

I've seen this one often enough that I think it belongs in the FAQ list.
The answer is that you *don't* do it by any special magic in the C source
code itself, but use some other tool to transform a "mini language" to
both files.  For example, write a little file like
	cmd.defs
	-----------
	A	"Alfa"
	B	"Bravo"
	...
	D	"Delta"
and two awk scripts:
	cmd.awk
	-------------
	BEGIN	{ print "typedef enum {" }
		{ print $1, "," }
	END	{ print "} CMD;" }
and
	ltrs.awk
	-------------
	BEGIN	{ print "char ltrs[] = {" }
		{ print "  '" substr($2,1,1) "'," }
	END	{ print "};"}
and then put in your Makefile
	cmd.h: cmd.defs cmd.awk
		awk -f cmd.awk <cmd.defs >cmd.h
	ltrs.c: cmd.defs ltrs.awk
		awk -f ltrs.awk <cmd.defs >ltrs.c

(This is not a UNIX-specific solution: make and awk lookalikes are
available for other systems.  If you haven't got them, it's trivial
to do this in C itself.)

Moral: C source code is plain text that can be generated by other
programs.

-- 
The purpose of advertising is to destroy the freedom of the market.

lfd@cbnewsm.att.com (Lee Derbenwick) (02/28/91)

In article <1991Feb26.045242.23453@rfengr.com>, rfarris@rfengr.com (Rick Farris) writes:
> I have an enumerated type:
> 
> typedef enum { A, B, C, D } CMD;
> 
> and a corresponding array of ascii representations :
> 
> char ltrs[] = { 'A', 'B', 'C', 'D' };
> 
> My problem is: How do I keep the darn things in sync?

This is a bit kludgy, and it doesn't _guarantee_ that they're in
sync (i.e., no protection from typos), but its flexible and
general, and _very_ easy to do.  The key is an include file using
macros that are defined differently in different contexts.

letters.h contains:

  LETTER(A, 'A')
  LETTER(B, 'B')
  LETTER(C, 'C')
  LETTER(D, 'D')
  #undef LETTER

Then, to get your two examples:

  #define LETTER(A,B) A
  typedef enum {
  #include "letters.h"
  } CMD;

  #define LETTER(A,B) B
  char ltrs[] = {
  #include "letters.h"
  };

This trick can also be useful for creating a number of tables
that are really views of a single relation.

 -- Speaking strictly for myself,
 --   Lee Derbenwick, AT&T Bell Laboratories, Warren, NJ
 --   lfd@cbnewsm.ATT.COM  or  <wherever>!att!cbnewsm!lfd

harrison@necssd.NEC.COM (Mark Harrison) (02/28/91)

In article <1991Feb26.045242.23453@rfengr.com>,
rfarris@rfengr.com (Rick Farris) writes:

> I have an enumerated type:
> typedef enum { A, B, C, D } CMD;
> 
> and a corresponding array of ascii representations :
> char ltrs[] = { 'A', 'B', 'C', 'D' };
> 
> My problem is: How do I keep the darn things in sync?

One way:  Have a definition file that builds a header file
with the typedef and a C file with the array.  I have used
this method successfully for things like symbol table string
constants and error messages.

Example:

file foo.def
------------
CMD:	A B C D
TOKENS:	Q X Y

generates foo.h:
----------------
typedef enum { A, B, C, D } CMD;
typedef enum { Q, X, Y } TOKENS;

and foo.c:
----------
char CMD_ltrs[] = { 'A', 'B', 'C', 'D' };
char TOKENS_ltrs[] = { 'Q', 'X', 'Y' };

Awk and Perl are good languages for building tools like this.
-- 
Mark Harrison             harrison@necssd.NEC.COM
(214)518-5050             {necntc, cs.utexas.edu}!necssd!harrison
standard disclaimers apply...

black@blake.u.washington.edu (Jim Black) (02/28/91)

Rick Farris writes :

>I have an enumerated type:
>
>typedef enum { A, B, C, D } CMD;
>
>and a corresponding array of ascii representations :
>
>char ltrs[] = { 'A', 'B', 'C', 'D' };
>
> [...]
>
>My problem is: How do I keep the darn things in sync?
>
>Suppose I add a new CMD, "Z", is there any way to ensure
>that ltrs[] is updated?
>
>The problem is exacerbated by the fact that the CMD enum,
>being a typedef, is in a header file that is included in
>many places.  Since ltrs[] is an instantiated variable, it
>*can't* live in the same place.  Where should it live?  
>

One was is to use the C preprocessor, as follows:

1.  Use a macro in an include file that groups all the related items together.
Eg, in "CmdStuff.h":
/*       CMD ltr etc  */
CmdStuff (A, 'A', ..)
CmdStuff (B, 'B', ..)
CmdStuff (C, 'C', ..)
CmdStuff (D, 'D', ..)
CmdStuff (Z, 'Z', ..)

2.  Then in each source file (or header, as appropriate), define the CmdStuff 
macro to do what you want in the particular case, and #include "CmdStuff.h"
locally.

The CMD enum definition would look like this:

#define CmdStuff(enumval, ltr, ..)  enumval,
typedef enum {
 #include "CmdStuff.h"  /* enum values get enumerated here */
 } CMD;
#undef CmdStuff 

And the ltrs[] definition would look like this:

#define CmdStuff(enumval, ltr, ..)  ltr,
char ltrs[] = { 
 #include "CmdStuff.h"   /* corresponding letter codes get enumerated here */
 };
#undef CmdStuff

That's the basic idea, you can do more with this than these examples show.

Everything is declared together in one place ("CmdStuff.h", here):  
each time you add a CmdStuff() entry you will be forced to declare 
all appropriate parallel values, as intended.


P.S.  I can't remember if some C compilers might complain about a trailing
comma in the aggregate initialization (mine doesn't) - but you can add a
trailing null/nil/bottom entry in such cases.  Often that's useful anyway.
--
Jim Black  (black@blake.u.washington.edu) 

lerman@stpstn.UUCP (Ken Lerman) (02/28/91)

In article <1991Feb26.045242.23453@rfengr.com> rfarris@rfengr.com (Rick Farris) writes:
............
>I have an enumerated type:
>
>typedef enum { A, B, C, D } CMD;
>
>and a corresponding array of ascii representations :
>
>char ltrs[] = { 'A', 'B', 'C', 'D' };
>
>used for printing and other various purposes.
.............

>My problem is: How do I keep the darn things in sync?
>
>Suppose I add a new CMD, "Z", is there any way to ensure
>that ltrs[] is updated?

>The problem is exacerbated by the fact that the CMD enum,
>being a typedef, is in a header file that is included in
>many places.  Since ltrs[] is an instantiated variable, it
>*can't* live in the same place.  Where should it live?  
..................
>--
>Rick Farris  RF Engineering POB M Del Mar, CA 92014  voice (619) 259-6793
>rfarris@rfengr.com     ...!ucsd!serene!rfarris      serenity bbs 259-7757


I saw this idea in the gnu C compiler.

In file defs.h:
/* establish the pairs */
xxx(A,'A'),
xxx(B,'B'),
xxx(C,'C'),
xxx(D,'D'),

Then in file use1.c:

#define xxx(a,b) a
typedef enum { 
#include "defs.h"
} CMD;
#undef xxx

In file use2.c (or in another place in the same file):

#define xxx(a,b) b
char ltrs[] = {
#include "defs.h"
};
#undef xxx

I haven't actually tried this, or there may be some typos, but I think
the idea is worth posting.

Ken

schow@bcarh181.bnr.ca (Stanley T.H. Chow) (02/28/91)

[Since I don't want generate megaflames, the distribution has been trimmed.
 In particular, comp.lang.c]


In article <1991Feb26.045242.23453@rfengr.com>, rfarris@rfengr.com (Rick Farris) writes:
> I have a problem that I'm sure has been solved in the C
> language before; would someone point me in the right
> direction?
>
> typedef enum { A, B, C, D } CMD;
> char ltrs[] = { 'A', 'B', 'C', 'D' };
>
> My problem is: How do I keep the darn things in sync?

This is a shortcoming of C. In many other languages, especially the strongly
typed languages, arrays have specific index type. In your example, "ltrs"
would have index type "CMD". If the type and the array got out of sync, the
compiler would complaind.

Like all other problems of C, for every specific instance of any problem, you
can come up with hacks to solve it. Usually, the hacks are non-extensible, and
often, it involves considerable work.

Since you say your problem is more complicated than your example, I suspect
see exactly your problem and which suggestion you adpot.ll be interested to



In article <4836@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
>
>I've seen this one often enough that I think it belongs in the FAQ list.
>The answer is that you *don't* do it by any special magic in the C source
>code itself, but use some other tool to transform a "mini language" to
>both files.  For example, write a little file like
[example with awk script deleted]
>(This is not a UNIX-specific solution: make and awk lookalikes are
>available for other systems.  If you haven't got them, it's trivial
>to do this in C itself.)

Certainly this example solves this particular problem. What if you want a
foo.h that has many different enum ranges? Each range with an array with
different structure? The response, of course, is "no problem, here is this
other awk script".

Also, you have just added extra complexity to the system - some .h files
cannot be edited directly and must be regenerated after editing the "real"
source. Each particular header file is also likely to have different
syntax for its "mini language", making the system harder to understand.
Unless you awk script is very clever, the resultent .h files will be hard
for humans to read.


In Article <17268@milton.u.washington.edu>, black@blake.u.washington.edu (Jum Black) writes:
>
>One was is to use the C preprocessor, as follows:
>
>1.  Use a macro in an include file that groups all the related items together.
>Eg, in "CmdStuff.h":
>/*       CMD ltr etc  */
>CmdStuff (A, 'A', ..)
>CmdStuff (B, 'B', ..)
>CmdStuff (C, 'C', ..)
>CmdStuff (D, 'D', ..)
>CmdStuff (Z, 'Z', ..)
>
>2.  Then in each source file (or header, as appropriate), define the CmdStuff 
>macro to do what you want in the particular case, and #include "CmdStuff.h"
>locally.
 [details deleted]

Again, this clearly works. The price is that "CmdStuff.h" file has now totally
of "ltrs"? Also, generalizing this to more complicated structures is likely to
make the macro a lot more complicated.

>P.S.  I can't remember if some C compilers might complain about a trailing
>comma in the aggregate initialization (mine doesn't) - but you can add a
>trailing null/nil/bottom entry in such cases.  Often that's useful anyway.
Yet another artificial hack to conform to C.

Stanley Chow        BitNet:  schow@BNR.CA
BNR		    UUCP:    ..!uunet!bnrgate!bcarh185!schow
(613) 763-2831               ..!psuvax1!BNR.CA.bitnet!schow
Me? Represent other people? Don't make them laugh so hard.

rlk@telesoft.com (Bob Kitzberger @sation) (02/28/91)

Rick Farris writes:

> typedef enum { A, B, C, D } CMD;
> 
> and a corresponding array of ascii representations :
> 
> char ltrs[] = { 'A', 'B', 'C', 'D' };

Yes, you asked for a C solution, but since this was cross-posted to
comp.software-eng I thought I'd point out Ada's solution to this.
The example below specifies a type 'color', and a call to a language-defined
attribute of this prefix, 'IMAGE. 

with text_io;
procedure foo is
  type color is (red, green, blue );
  my_color : color := green;
begin
  text_io.put_line( color'image(my_color) );
end foo;

All enumerated types have a corresponding 'IMAGE attribute, which implies 
that an ASCII (or EBCDIC ;-) representation of each enumerated value be 
present at execution time.  These image tables may be supressed at compile 
time.

	.Bob.
-- 
Bob Kitzberger               Internet : rlk@telesoft.com
TeleSoft                     uucp     : ...!ucsd.ucsd.edu!telesoft!rlk
5959 Cornerstone Court West, San Diego, CA  92121-9891  (619) 457-2700 x163
------------------------------------------------------------------------------
"Wretches, utter wretches, keep your hands from beans!"	-- Empedocles

jls@rutabaga.Rational.COM (Jim Showalter) (03/01/91)

Again, in Ada this is handled by the predefined attribute 'IMAGE. Considering
the range of kludgy/complex "solutions" posted here to what is a non-issue
in Ada, it never ceases to amaze me how violently C hackers cling to that
damned language.

You don't suppose they're IGNORANT, do you?...
--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

marick@m.cs.uiuc.edu (Brian Marick) (03/01/91)

jls@rutabaga.Rational.COM (Jim Showalter) writes:

>Again, in Ada this is handled by the predefined attribute 'IMAGE. Considering
>the range of kludgy/complex "solutions" posted here to what is a non-issue
>in Ada, it never ceases to amaze me how violently C hackers cling to that
>damned language.

Let's not get bogged down in this month's C vs. Ada flame war.  

1.  The C style of solving the problem does cost more than the Ada
style: it is more difficult to learn, and the reliability is certainly
no higher (probably lower).

2.  However, both the cost and reliability delta are probably
insignificant in relation to total development costs.

3.  The various C (really C/UNIX) techniques are applicable to other
tasks, including various styles of table-driven programming.

(Me, I use the "include the same definitions file several times,
changing the applicable #defines each time" trick -- without either
being pleased by a clever hack or being dismayed about its kludginess.
I wish I had such sure answers to the important problems that such a
small matter really mattered.)


Brian Marick
Motorola @ University of Illinois
marick@cs.uiuc.edu, uiucdcs!marick

dave@aspect.UUCP (Dave Corcoran) (03/01/91)

In article <1991Feb26.045242.23453@rfengr.com>, rfarris@rfengr.com (Rick Farris) writes:
> I have an enumerated type:
> 
> typedef enum { A, B, C, D } CMD;
> 
> and a corresponding array of ascii representations :
> 
> char ltrs[] = { 'A', 'B', 'C', 'D' };
> 
> Suppose I add a new CMD, "Z", is there any way to ensure
> that ltrs[] is updated?
> 

run this through m4 you might be pleasantly suprised; although anyone
maintaining your code may what to drop the adjective "pleasantly" :-)

define(awkdef,
	`syscmd((echo ' '$2' | sed 's/^(//;s/^)//' `>/tmp/am_$1))'
	`define($1,`syscmd(awk $'`2 -f /tmp/am_$1 ifelse($'`1,,,<<@@
$'`1
@@))')'
)

awkdef(xx,(  # note the leading (
	BEGIN {printf "enum {"}
	{
	for (i=1;i<=NF;i++) printf "%s,",$i
	}
	END {print "} CMD;"}
))	/* note the first paren MUST be flush against the left margin */


/* note the '\'' construct is needed to get a single ' in the output */

awkdef(yy,(
	BEGIN {printf "char ltrs[] = {"}
	{
	for (i=1;i<=NF;i++) printf "'\''%s'\'',",$i 
	}                                           
												
	END {print "};"}
))

define(letters,`xx($1)yy($1)')
letters(A B C D E F G H I J K L M)

/* if you need conditional compliation */

define(`letters',`ifdef(`header_file',`yy($1)',`xx($1)')')

/* this next line would be in a .c source */
letters(A B C)

/* these two would be in a .h header */
define(header_file)

letters(A B C)

-- 
David Corcoran		      -@@
uunet!aspect!dave	        ~
In a society where anything goes eventually everything will.

schow@bcarh181.bnr.ca (Stanley T.H. Chow) (03/02/91)

In article <8001@aspect.UUCP> dave@aspect.UUCP (Dave Corcoran) writes:
>In article <1991Feb26.045242.23453@rfengr.com>, rfarris@rfengr.com (Rick Farris) writes:
>  [problem deleted]
>
>run this through m4 you might be pleasantly suprised; although anyone
>maintaining your code may what to drop the adjective "pleasantly" :-)
 [solution using m4 macro deleted]

Yet another solution is to "audit" the data. This can be done in the
initialization phase or by a standalone program. You could even go as
far as putting the audit program in your make file so that a "mismatch"
will stop the make. This is not as good as the compiler catching it,
but is a close second.

Stanley Chow        BitNet:  schow@BNR.CA
BNR		    UUCP:    ..!uunet!bnrgate!bcarh185!schow
(613) 763-2831               ..!psuvax1!BNR.CA.bitnet!schow
Me? Represent other people? Don't make them laugh so hard.

jih@ox.com (John Hritz) (03/02/91)

The approach I take when faced with this kind of problem is to place an
assert statement in the main() as a check.
	assert(sizeof(a)  == sizeof(b))
will probably do the trick.  These statements can be left out of the code
by setting a compile switch, usually NDEBUG.
-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
     John I. Hritz                               Photons have mass?!
     jih@ox.com                                       I didn't know they
     313-930-9126                                             were catholic!

dave@cs.arizona.edu (Dave P. Schaumann) (03/02/91)

In article <1991Mar1.143534.50@m.cs.uiuc.edu> marick@m.cs.uiuc.edu (Brian Marick) writes:
>jls@rutabaga.Rational.COM (Jim Showalter) writes:
>>Again, in Ada this is handled by the predefined attribute 'IMAGE. Considering
>>the range of kludgy/complex "solutions" posted here to what is a non-issue
>>in Ada, it never ceases to amaze me how violently C hackers cling to that
>>damned language.
>
>Let's not get bogged down in this month's C vs. Ada flame war.  

Hear, hear.

>[some good points deleted]

I'd like to point out some points more specific to language choice.

There are (at least) three interconnected issues in designing and implementing
any language:  speed, safety, and expressability.

You can have any two of these, but only at the cost of the third.  For
instance, C has speed and expressability at the cost of safety.  Ada chose
expressability over the others.  Some other examples:  assembly language
is the ultimate example of speed over expressability and safety.  At the
other end of the spectrum, we have BASIC, which has safety over speed and
expressability.

Also note that the point that a language finds itself in safety/speed/express-
ability is determined by the skill of the compiler/interpreter writer, the
state of compiler/language theory at the moment, as well as the particular
implementation hardeware.

Every language has a different trade-off of these three issues.  Ideally,
language choice would simply be a matter of specifying how important these
three are, and then choosing the best match available (or perhaps implementing
a new language more suited to your needs).

Unfortunately, this is not the case.  Language choice is based on the history
of the environment and the temperment and experience of the programmer.

However, this does lend to an explination of why (in the general case),
no language is really better than another.  It all really depends on the
problem at hand (and to an unfortunate extent the programmer at hand).

-- 
		Dave Schaumann		dave@cs.arizona.edu
'Dog Gang'!  Where do they get off calling us the 'Dog Gang'?  I'm beginning to
think the party's over.  I'm beginning to think maybe we don't need a dog.  Or
maybe we need a *new* dog.  Or maybe we need a *cat*! - Amazing Stories

rjc@uk.ac.ed.cstr (Richard Caley) (03/02/91)

In article <1991Feb26.045242.23453@rfengr.com>, Rick Farris (rf) writes:

rf> My problem is: How do I keep the darn things in sync?

I had to do this for six or seven sets of things in a library. I
decided to write a short shell script to write all the code for me. I
created a file containing the names and any data to be associated with
them and the shell script creats a header and a c file

a file called people with...

	char *name	int age
fred	fred		24
mary	mary		30

would give a header person.h containing

enum person
	{
	pe_NIL= -1,
	pe_fred=0,
	pe_mary=1,
	pe_number=2,
	};

struct person_rec
	{
	char *name;
	int age;
	};

struct person_rec person_data;

enum person person_with_name(char *name);
enum person person_with_age(int age);

and a c file person.c contining the definition of person_data and the
code for the search routines (left as an exercise for the reader).

The Makefile takes care of recreating the files when needed and
nothing can get out of step. Also saves lots of tedious coding of
access routines which are isomorphic for all the tables.

(the reson for having a separate "name" field is that often things
 have names which are not legal c tokens).

--
rjc@cstr.ed.ac.uk

jls@rutabaga.Rational.COM (Jim Showalter) (03/02/91)

>1.  The C style of solving the problem does cost more than the Ada
>style: it is more difficult to learn, and the reliability is certainly
>no higher (probably lower).

>2.  However, both the cost and reliability delta are probably
>insignificant in relation to total development costs.

For this particular instance, perhaps. But in aggregate, given that this
is just one small example of C being more difficult to learn and maintain,
it adds up. That's the point--large problems are composed of thousands of
small problems, so attacking those thousands of small problems AT THE SOURCE
(e.g. the language) can have a big payoff.

>I wish I had such sure answers to the important problems that such a
>small matter really mattered.)

I will grant you that the larger issues concerns architecture and design,
not this or that programming technique. But, presuming you CAN solve the
macro-scale issues (and I have a number of ideas on that particular topic
if you want to change threads), you still aren't out of the woods if your
language of implementation fosters poor software engineering principles.
The language and the culture that grows up around it must be of the highest
quality, not some relic of the 60's.
--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

jls@rutabaga.Rational.COM (Jim Showalter) (03/03/91)

>Hear, hear.

Well, if you wanted to avoid a language war, you're off to a lousy start.

>For instance, C has speed and expressability at the cost of safety.

? C, written according to prevailing standards, resembles line noise more
than anything else. Or are you using "expressibility" to mean something besides
"intelligibility"? As for the claim that C has speed (and, if I read the subtext
correctly, that C is faster than Ada)--horseshit. We sell Ada compilers that
beat C compilers like a gong (whetstones, dhrystones, etc).

>Ada chose
>expressability over the others.

Excuse me, but OTHER people complain that Ada is "too safe" (whatever the hell
THAT means), because it does range checking, type checking, etc. Are you
speaking of some OTHER Ada when you say it did not choose safety? And I
CERTAINLY hope you aren't making the claim that C is safer than Ada--that would
be stoopid: C has no range checks and virtually no type checking (untyped
functions accepting an arbitrary number of arguments of arbitrary type and
return an array of arbitrary size of pointers to functions accepting an
arbitrary number of arguments of arbitrary type certainly does not seem safe
to me).

Also, remember the joke with the punchline "I'd be fast too, if I didn't have
to arrive at the right answer". Just because code executes quickly doesn't
necessarily mean it executes CORRECTLY. Ada, by performing checking that C
does not perform, stands a considerably better chance of not poking a hole in
the kernel, etc. This tends to be an important consideration when you're
building satellites and other sorts of things that are hard to reboot when
they get wedged. Say--you don't suppose this has anything to do with why the
DoD insisted people use Ada instead of C to build such things, do you?

>Some other examples:  assembly language
>is the ultimate example of speed over expressability and safety.

Yep. That's why we use compilers!

>Also note that the point that a language finds itself in safety/speed/express-
>ability is determined by the skill of the compiler/interpreter writer, the
>state of compiler/language theory at the moment

This might explain why our Ada compilers beat C compilers like a gong.
--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

rlk@telesoft.com (Bob Kitzberger @sation) (03/03/91)

Folks, the intent was to ease an existing maintenance problem.  Adding
preprocessors such as awk or m4 into the loop only trades one maintenance
problem for another.

	.Bob.
-- 
Bob Kitzberger               Internet : rlk@telesoft.com
TeleSoft                     uucp     : ...!ucsd.ucsd.edu!telesoft!rlk
5959 Cornerstone Court West, San Diego, CA  92121-9891  (619) 457-2700 x163
------------------------------------------------------------------------------
"Wretches, utter wretches, keep your hands from beans!"	-- Empedocles

rcd@ico.isc.com (Dick Dunn) (03/03/91)

jls@rutabaga.Rational.COM (Jim Showalter) writes:

> Well, if you wanted to avoid a language war, you're off to a lousy start.

Jim, you started the language war.  Someone tried to steer it back to a
moderate ground and instill a bit of software-engineering content; you've
dragged it back into flaming.  You are forcing the flame-war by insisting
that nobody can say anything good about C or bad about Ada.

> ? C, written according to prevailing standards, resembles line noise more
> than anything else...

Cute.  Well, you've told us you don't know anything about either C or
program legibility.  Not surprising, given that you also don't seem to
know the difference between software engineering and programming language
religious wars.

> ...We sell Ada compilers that
> beat C compilers like a gong (whetstones, dhrystones, etc).

pure marketing bullshit.

1.  Whetstones and Dhrystones do not measure compiler performance.  A
    cross-language Dhrystone measurement is particularly meaningless
    because the C and Ada Dhrystone benchmarks are semantically different.
    But I'm sure it helps sell Ada compilers.  Anyway, nobody who knows or
    cares anything about performance uses Dhrystone to measure it.

2.  The performance of compiled code, for the common large class of
    procedural imperative languages, is essentially independent of
    the language compiled.  It depends on the algorithms used--e.g.,
    a compiler which employs CSE can produce better code than one
    which doesn't, regardless of source language.

...
> ...Say--you don't suppose this has anything to do with why the
> DoD insisted people use Ada instead of C to build such things, do you?

Who knows?  The overriding consideration is massive vested interest.
DoD has now spent nearly two decades and enough money to develop ten
languages (at least) getting Ada off the ground and keeping it going;
you can't very well expect them to waste that investment.

OSEC:  Ada's not a bad language, but comparing it to C is an apples-and-
oranges waste of time.  A decent programmer can produce good code in
either one...and the point all too often missed is that differences among
languages are second-order issues.  The important factors for performance,
portability, maintainability, development time, etc., are elsewhere.
Find a language that you can use, with a good compiler and good support for
your environment--might be Ada, C, Pascal, FORTRAN--and then get on to the
software engineering.
-- 
Dick Dunn     rcd@ico.isc.com -or- ico!rcd       Boulder, CO   (303)449-2870
   ...But is it art?

jls@rutabaga.Rational.COM (Jim Showalter) (03/04/91)

>Well, you've told us you don't know anything about either C or
>program legibility.

Huh? I believe I not only laid out my bona-fides with respect to C (I used
to do UNIX internals maintenance, I have a black belt in C, I've taught
people C++, blah blah blah), but bitched at great length precisely about
the LACK of legibility of C code. Did you actually read what I wrote, or
just get bent out of shape about it because I hammered C.

It's weird, but one of the odd things I've noticed about net behavior is
9 times out of 10 nobody actually responds TO THE PREVIOUS POST, just to
its style, format, whatever. I provided in rec.humor a point by point
comparison of C to Ada in something called the "C hacker commandments" or
some such. I then got flamed for the location of the post--but nobody
was able to refute the CONTENT of what I wrote. I provided here what I
felt was a cogent argument about the shortfalls of C as a software engineering
tool. You responded NOT to what I wrote, and I still wait for someone to
do so.

>pure marketing bullshit.

Ah, that must explain why all the C compiler vendors make sure to run
these benchmarks and publish the results. Look, I'm no happier with what
prevailing benchmarks measure than anyone else, but if that's what is
going to be used, then that's what is going to be used. To slam us for
providing the same benchmark results as C compiler vendors seems rather
silly, yes?

>2.  The performance of compiled code, for the common large class of
>    procedural imperative languages, is essentially independent of
>    the language compiled.

Now wait a minute--which IS it? Lots of people parade their ignorance
by claming that Ada is somehow inherently slower than C. You now proclaim
all procedural languages as essentially equally fast. Make up your mind.

>Who knows?  The overriding consideration is massive vested interest.
>DoD has now spent nearly two decades and enough money to develop ten
>languages (at least) getting Ada off the ground and keeping it going;
>you can't very well expect them to waste that investment.

Yeah, and it is pretty sad that it required that much effort to get people
to do commensensical things like emphasizing reuse, avoiding global variables,
packaging related code together, hiding implementation details, etc etc etc.
(This is software engineering, by the way.)

>Find a language that you can use, with a good compiler and good support for
>your environment--might be Ada, C, Pascal, FORTRAN--and then get on to the
>software engineering.

Again, try reading what I wrote. I said that C is a poor vehicle for software
engineering, even in shops that practice good community hygeine. Ada is a
language designed with direct support for sound software engineering principles
in mind from the ground up. C wouldn't recognize a software engineering
principle if it jumped on it out of a tree. C has exceedingly poor support
for spec/body separation, implementation detail suppression, opaque typing,
strong typing, genericity, multi-processing (calling an underlying operating
system doesn't count as direct support), namespace control, etc etc etc.
Ada has such support, and C++ does too (although less cleanly): you don't
suppose the arrival of C++ is an admission that a 1960's language could be
less than optimal for tackling modern problems, do you?

Finally, and I make this point again because you seem to have missed it the
first time, language issues might be a second order effect compared to
macro-scale issues of software engineering such as architecture, design,
etc, but they are still legitimate issues. It makes no more sense to
implement a good architecture in a lousy (from a software engineering
standpoint) language than it does to use crayons to paint a masterpiece.
To the degree that a language thwarts or fails to support the very principles
you are trying to encourage, it is a poor choice as an implementation vehicle.
--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

harrison@necssd.NEC.COM (Mark Harrison) (03/04/91)

In article <1210@telesoft.com>,
rlk@telesoft.com (Bob Kitzberger @sation) writes:

> Folks, the intent was to ease an existing maintenance problem.  Adding
> preprocessors such as awk or m4 into the loop only trades one maintenance
> problem for another.

That is correct, but the new maintenance problem is easier.  Our "bells
and whistles" version of the preprocessor ended up being about three
pages of AWK that hardly ever needed to be touched.  (The only times we
did touch it was to make changes in the generated troff documentation
to fit our documentation dept's. style).

Using MAKE ensured that the preprocessed files stayed in sync.  Being
able to generate documentation saved us days over the old "red-pencil"
method of dealing with our documentation group.
-- 
Mark Harrison             harrison@necssd.NEC.COM
(214)518-5050             {necntc, cs.utexas.edu}!necssd!harrison
standard disclaimers apply...

dave@bigguy.ocpt.ccur.com (David F. Carlson) (03/19/91)

> Rick Farris writes:
> 
> > typedef enum { A, B, C, D } CMD;
> > 
> > and a corresponding array of ascii representations :
> > 
> > char ltrs[] = { 'A', 'B', 'C', 'D' };
> 

I would usually overload the operation for this using the initialization
property of enum types and the fact that they are defined to hold an
integer:

typedef enum { A = (int) 'A', B = (int) 'B', C = (int) 'C', D = (int) 'D'} CMD;

or if lexically ASCII is assumed,

typedef enum { A = (int) 'A', B, C, D } CMD;

Since B, C and D will be sequential, they will be correctly initialized.


Or is that cheating? :-)
-- 
David F. Carlson, Concurrent Computer Co.
dave@bigguy.ocpt.ccur.com       Fairport, NY

"The faster I go, the behinder I get." --Lewis Carroll