[comp.sys.amiga] __chip keyword is evil

w-stephm@microsoft.UUCP (Stephan Mueller) (12/19/89)

In article <411@enuxha.eas.asu.edu> martin@enuxha.eas.asu.edu (Ross D. Martin) writes:
>In article <9532@microsoft.UUCP>, w-edwinh@microsoft.UUCP (Edwin Hoogerbeets) writes:
>> 	# pragma token-sequence[opt]
>>
>> causes the processor to perform an implementation-dependent action. An
>> unrecognized pragma is ignored.
>> 
>> Why __chip? We've got the PORTABLE mechanism already. Why not use it?
>> Was there some good technical reason? (__chip must go. This is not 
>> negotiable. ;-)
>
>Yes it is.  :-)
>

No, actually as it turns out, it is not. :-) :-) (Two smileys, upping the anty)

>I don't see what you have against __chip.  It is portable.  Just #define
>it to something harmless to do a port.  I believe you can #define something
>to a null string, can't you?  If not, there are several do-little modifiers
>out there that should work ok.  Perhaps #define __chip static?
>Pragmas involve more typing to get less clear, clean code.  Not a good idea
>in my book.

You are correct that one can #define something to the NULL string, so your
method will work, and would be the logical method if we didn't have
something better, like #pragma.  IMHO, though, this method is a bit of a
kludge.

I don't believe that __chip is as portable as using a #pragma.
True, it isn't much work to put #define __chip at the top of a program
when porting it, but it is more work than doing absolutely nothing, which
is what would be required using the #pragma method.  To do the #define
right, would probably require something like the following.  (The AMIGA
and LATTICE symbols should be replaced by whatever the compiler predefines
for you.)

#if !(defined(AMIGA) && defined(LATTICE))
 #define __chip
#endif

which is pretty ugly.  Also, this is probably more typing than a good
#pragma would be.  The conditional is not needed if we are using a
#pragma either, which to me means clearer, cleaner code.

Getting a bit nit pickier, if I #define something, I like to stick to
the fairly standard practice of having my symbols in all upper case,
so I would likely use:

#if defined(AMIGA) && defined(LATTICE)
 #define CHIP __chip
#else
 #define CHIP
#endif

and then declare appropriate structures with the CHIP attribute.  Now, we
have a lot more typing, but at least when I port the program, no
additional #defines are required.

On a more philosophical level, the __chip stuff has nothing to do
with any data structure or any algorithm.  It is a code generation
detail, and so, doesn't belong in the body of a C program which is
supposed to be a high-level description of the program.

As an example, consider Microsoft C 5.1 (context switch into the wonderful
world of MS-DOS now)

MSC features #pragmas for all kinds of code-generation related things:
  - enabling and disabling of various kinds of optimizations
  - enabling and disabling generation of stack-checking code
  - enabling and disabling generation of intrinsic functions

Conversely, MSC uses additional keywords for some kinds of code-generation
related things:
  - specifying Pascal or C calling convention for functions
  - specifying size of pointers.

About these additional keywords, the MSC manual states:
"The disadvantage of using these keywords is that they are specific to
 the MS-DOS implementation of Microsoft C and, thus, are not portable to
 other operating environments."

Now, assuming I've convinced you we should be using #pragma, what should
the syntax of such a #pragma be?

Proposal :
  #pragma chip (identifier1 [, identifier2 ...])

>
>		Ross Martin

stephan("You can tune a piano, but you can't armadillo");

amr@atlantis.egr.duke.edu (Tony Richardson) (12/20/89)

From article <6@microsoft.UUCP>, by w-stephm@microsoft.UUCP (Stephan Mueller):
> In article <411@enuxha.eas.asu.edu> martin@enuxha.eas.asu.edu (Ross D. Martin) writes:
>>In article <9532@microsoft.UUCP>, w-edwinh@microsoft.UUCP (Edwin Hoogerbeets) writes:
>>> 	# pragma token-sequence[opt]
>>>
>>> causes the processor to perform an implementation-dependent action. An
>>> unrecognized pragma is ignored.
>>> 
>>> Why __chip? We've got the PORTABLE mechanism already. Why not use it?
>>> Was there some good technical reason? (__chip must go. This is not 
>>> negotiable. ;-)
>>
>>Yes it is.  :-)
>>
> 
> No, actually as it turns out, it is not. :-) :-) (Two smileys, upping the anty)
  ... lots of discussion as to why #pragma's should be used instead of
      __chip for portability reasons.

It seems to me that anything that requires the use of __chip (or the
corresonding #pragma) is going to be non-portable (at the very least it
is going to be different in some respect) so this whole discussion
seems to be a little nit-picky. (We all know not to use __chip except
for data that HAS to be placed in ram accessible by the custom chips. :-))
Actually if I were trying to port a program to a different system I would
prefer to see an "unrecognized keyword __chip" type message than no
message at all to point out portability problems.

I admit I am not trying to an unbiased participant in this discussion.
I like __chip.  When I write programs that use images (or whatever) that
need to be placed in chip ram it find it easy to remember to just stick
__chip in front of the appropriate data structures and it makes programming
a little easier (so I'm lazy). (I have no intention
of porting these programs to other systems -- they wouldn't work.)

It would be nice if Lattice and Manx agreed to standardize on the use
of Amiga specific keywords and pragmas, but I guess it's too late for
that.

Tony Richardson     amr@dukee.egr.duke.edu

davewt@NCoast.ORG (David Wright) (12/20/89)

	There is nothing wrong with using keywords like __chip or
__fast in a C program. True, they are not portable, but SO WHAT?? No other
system NEEDS them. They fill a need on the Amiga, and there is no way
to make them portable. It is a requirement of the Amiga to be able to
specify WHICH type of memory a certain segment belongs in. You can't use
ANY of the ANSI definitions (or the Microcrud either), as these are also
implemented on the Amiga and are used for different reasons.
	There is absolutely NOTHING wrong with putting in non-portable
keywords or definitions in ANY C program, when it is done for these
reasons, and when it is so easy to remove when transfering code to
another machine.

w-edwinh@microsoft.UUCP (Edwin Hoogerbeets) (12/21/89)

dirks@phao.eng.ohio-state.edu (William R.Dirks) writes:
% The following is quoted from the Lattice Amiga Compiler User's Guide
% page G51 without permission.  (I hope they don't get mad at me. ;) )
% 
%   "The chip, far, huge, and near keywords are extensions to the ANSI
%   standard.  The standard requires that each keyword extensions [sic]
%   be preceded by a double underscore, such as __near.  The Lattice 
%   compiler accepts the extended keywords in this form as well as in
%   the more natural form without the double underscores."
% 
% I guess "__chip" is ANSI, but "chip" breaks the rules.

Well, ANSI specifies that identifier names beginning with a double
underscore are not within the defined name space of C. This means that
if you should want to add an *extension* to the language, use the double
underscore method. The double underscore identifiers simply do not
violate ANSI.

It does NOT specify that __chip, __far, __huge or __near are reserved
keywords. If I were writing an ANSI Unix compiler, I would not have to 
support these.

This lack of specification means that they are not portable. 

I don't know if anyone would want to port code that needs chip memory to
a Unix box, but I'm quite sure that the same code might be "Manxified."

If Manx does not support __chip, but has a pragma instead, I'll be
happy.  (Any comments from those beta testers out there?)

martin@enuxha.eas.asu.edu (Ross D. Martin) writes:
% I don't see what you have against __chip.  

It is a pollution of the C language. 

C was designed to be a small language, and as such, it embodies the
"small is beautiful" philosophy quite well. Adding [non-portable] 
keywords to the language should not be done lightly, especially with
keywords like __chip, which do not have any semantic effect on the
code.

This is part of the reason Dennis Ritchie vetoed the "noalias" keyword.

% It is portable.  Just #define
% it to something harmless to do a port.  I believe you can #define something
% to a null string, can't you?  If not, there are several do-little modifiers
% out there that should work ok.  Perhaps #define __chip static?

This is not a good solution. It would be nice to be able to write code
for the Amiga, to be compiled with either of the ANSI compliant compilers
[soon for Manx 8-)]... with NO changes necessary to "port" between them.

% Pragmas involve more typing to get less clear, clean code.  Not a good idea
% in my book.

Pragmas take more typing? A quicksort takes more typing than a nice little
bubblesort, but that is no reason to use the bubblesort all the time.
Programmer convenience should not override more important issues (IMHO)
like portability, efficiency, or esthetics. And especially
maintainability.

As for clean and clear code how about:

char array[10];      

as opposed to

__chip char array[10];

Which is more clear and/or clean?  I'd say the first example.  

As another example of keywords growing wild:

peter@cbmvax.commodore.com (Peter Cherna) writes:
[good discussion of amiga shared libraries deleted - Thanks Peter!]
% char * __saveds __asm LIB_foo(register __d0 int i, register __a0 long *lptr)
% 
% The __saveds instructs Lattice to set up your data area (off A4) when
% anybody calls your function.  The __asm keyword states that you intend
% to specify which registers receive which parameters, as shown above.

__saveds? __asm? __d0? __a0?

Please don't tell me these are clear. Peter even had to tell us what all
these keywords were for! The function declaration is rather obsured.

Are there not pragmas for these, either?

w-stephm@microsoft.UUCP (Stephan Mueller) writes:
% On a more philosophical level, the __chip stuff has nothing to do
% with any data structure or any algorithm.  It is a code generation
% detail, and so, doesn't belong in the body of a C program which is
% supposed to be a high-level description of the program.

Yes! Good point.

% Now, assuming I've convinced you we should be using #pragma, what should
% the syntax of such a #pragma be?
% 
% Proposal :
%   #pragma chip (identifier1 [, identifier2 ...])

Sounds about right. 

How about it, Doug and John? (Actually, I don't know why I'm arguing
this point, since I don't own Lattice... I guess the argument is more 
on philosophical grounds.)

Followups directed to comp.sys.amiga.tech.

Edwin

bader+@andrew.cmu.edu (Miles Bader) (12/21/89)

I was under the impression that #pragma directives as defined by ANSI were
NOT allowed to be used for anything that changed the meaning of the program.
I.e., it has to work the same if the compiler ignores all #pragmas (if
perhaps less quickly, etc).

None of the lattice extensions (__chip, __asm, etc), seem to fit that
definition, so it would seem that you couldn't legally use #pragma to
implement them.  If something needs to be in chip memory, you can't just not
put it there!

Note that the lattice system call hack #pragmas ARE legal, since if you
ignore them, the program just ends up using the library stub instead--
slower, but with the same result.

-Miles