[comp.sys.amiga] #pragma PREPROCESSOR control is evil!

Sullivan@cup.portal.com (sullivan - segall) (12/20/89)

>In article <411@enuxha.eas.asu.edu> martin@enuxha.eas.asu.edu (Ross D. Martin) wri
t
>es:
>>In article <9532@microsoft.UUCP>, w-edwinh@microsoft.UUCP (Edwin Hoogerbeets) wri
t
>es:
>>> 	# 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
>
>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. [eeek!] IMHO, though, this method is a bit of a
>kludge. 

   Yes #pragma is a bit of a kludge!   :)
>
>
>#if !(defined(AMIGA) && defined(LATTICE))
> #define __chip
>#endif

or:

 #ifndef __chip
   #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 create some amiga code that requires
placement in the chip memory, I want my compiler to tell me that something
has changed when I move to a new environment.  I *will* need to think
about the way I'm planning on implementing this thing on any other 
architecture, and I would just as soon have the compiler remind me to
do so.  By comparison, #if, #define, #endif is much less ugly than losing
my __chip references.

>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

or:

 #ifndef __chip 
  #define __chip
 #endif
 #define CHIP __chip

but really I would probably use:

#ifdef AMIGA

  typedef __chip char *rastport[ MAXWIDTH * MAXHEIGHT * PLANES / 8 ];

#else
  ...
#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.
>

I've never met anyone who really thinks that C code can be ported without
any changes.  Especially C code which is machine-specific.  I can't 
imagine using an Amiga rastport on any other machine,... nor for that
matter can I imagine any set of architectures which by their nature allow
structures to be defined such that machine dependant features will work 
with each of them. 

Similarity between machines is really meaningless until you get to 
a higher level of control.  And at that level, the subroutines which 
implement the windows, mouse requests, or what have you, can allocate 
memory however they please, without ANY reference to CHIP, __chip, or 
#pragma in the high level routines calling them.

>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.
>
I disagree.  Register, static, automatic, and even __chip are all 
code generation details.  Register means allocate a machine register
if one is available.  Static means allocate main memory.  Automatic 
means allocate stack space.  __chip means allocate Amiga specific 
chip memory.  (#pragma is a PREPROCESSOR instruction fer gosh sake.)

>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
good use of pragmas.
>  - enabling and disabling generation of stack-checking code
good use of pragmas.
>  - enabling and disabling generation of intrinsic functions
good use of pragmas.
>
>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."

....so your point is that even MicroSoft knows that specialized keywords 
should be used for storage size, and placement definitions.  (ie: for types,
which is exactly what pragmas shouldn't be used for (well using a pragma
to define the primary memory model, or the size of an int isn't evil, but 
declaring a variable using a pragma IS.)

>
>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 ...])
>
eeeeek!  no.  Don't do this.  Please!
>>
>>		Ross Martin
>
>stephan("You can tune a piano, but you can't armadillo");

#pragma dreammode ON

.... hey how about #pragma programming language.  All source files should
end in "p.rag".  If you can't interpret the meaning of any line of code,
just ignore it.  Demo code is listed below:

#pragma I want to play a game.  You be the bad guys and I'll be the 
#pragma good guys.  Oh, and make it nice and graphical too.  Thanks.


As you can see by the code above, the language is very terse.  This 
two line program is equivalent to about 50,000 lines of C, and in fact
generates code equivalent to NetHack (with a few enhancements naturally.)
Or alternatively it compiles to nothing at all depending on which compiler
you have...

-ss



#pragma dreammode OFF

w-stephm@microsoft.UUCP (Stephan MUELLER) (12/22/89)

Summary:
  Many people favour using a new keyword over using a #pragma for specifying
  Amiga implementation details in C programs.  The reasons seem to be
    a) __chip is more convenient
    b) #pragma is ugly
    c) portability is not an issue since the __chip non-portability is
       overwhelmed by other Amiga specific details.

  On more philosophical grounds, I (and a few others) find new keywords to be
  less acceptable because
    a) they pollute the C language
    b) #pragma is the official tool for the job, ugly or not


Doug Walker writes:
% #pragma is extremely non-portable.  Each compiler can implement any #pragma
% keyword any way they wish, and you cannot #define a #pragma away.  You can
% get rid of __chip simply by defining it to nothing.

There is no need to #define a #pragma away.  K&R 2nd edition, section A12.8
pp 233:

"A control line of the form
    #pragma token-sequence(opt)
causes the processor to perform an implementation-dependent action.  An
unrecognized pragma is ignored."

While it is sometimes required, the idea of #defining a symbol to nothing,
in order to get rid of it is nothing short of a kludge. 

% There is no portable way to define a non-portable feature.

Then what is #pragma for?  "Implementation dependent" implies "non-portable"
to me.

% "All identifiers that begin with an underscore and either an upper-case letter
% or another underscore are always reserved for any use."
 
That doesn't mean that it is necessarily a good idea to do so.


Tony Richardson writes:
% 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.

Agreed, but...

If I want to port to another Amiga compiler, say Manx, or Amix or some
cross-compiler generating Amiga code, then __chip will be non-portable
but the code using it will not.  In this case, the behaviour of #pragma
is preferable.  Those compilers that do not support the #pragma will
still be able to compile the code, and one will need to specify a link
option or something to get the appropriate module into chip RAM.

When porting to another system, I suspect that you'll get a
"cannot find intuition.h" message long before you get an "unrecognized
keyword __chip" message. :-)

% 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.

Quite true.
 

David Wright writes:
% 	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.

One of the reasons C is so popular is because we have a standard (or 2 :-)
for the language.  I agree that __chip and __fast fill a need.  My
objection is that there is a better way to fill that need; one that doesn't
pollute the C language.  It may be easy to remove those definitions, but
if I don't have to do anything, I'd be happier.

I'm not familiar with any compiler named Microcrud, who makes it? :-)


Sullivan Segall writes:
% >I write:
% >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. [eeek!] IMHO, though, this method is a bit
% >of a kludge. 
% 
%    Yes #pragma is a bit of a kludge!   :)

Touche'

% >#if !(defined(AMIGA) && defined(LATTICE))
% > #define __chip
% >#endif
% 
% or:
% 
%  #ifndef __chip
%    #define __chip
%  #endif

Using this notation, can you tell me on which machine this __chip stuff
has any meaning? 

% Getting a bit nit pickier, if I create some amiga code that requires
% placement in the chip memory, I want my compiler to tell me that something
% has changed when I move to a new environment.  I *will* need to think
% about the way I'm planning on implementing this thing on any other 
% architecture, and I would just as soon have the compiler remind me to
% do so.  By comparison, #if, #define, #endif is much less ugly than losing
% my __chip references.

If we used #pragmas, and grouped them all together, you'd have all of your
chip references, conveniently located for your perusal.  If our compiler
had a warning level which mentioned ignored #pragmas I'd be happy.

% >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
% 
% or:
% 
%  #ifndef __chip 
%   #define __chip
%  #endif
%  #define CHIP __chip
% 

I hadn't thought of that, but I prefer my original version, it seems
clearer to me.  Using my notation it is very clear exactly what CHIP
represents: either the keyword __chip or nothing.

% I've never met anyone who really thinks that C code can be ported without
% any changes.  Especially C code which is machine-specific.  I can't 
% imagine using an Amiga rastport on any other machine,... nor for that
% matter can I imagine any set of architectures which by their nature allow
% structures to be defined such that machine dependant features will work 
% with each of them. 

Agreed.  But I may want to port the program to other compilers running on
the Amiga.  Or perhaps a cross-compiler.

% Register, static, automatic, and even __chip are all 
% code generation details.  Register means allocate a machine register
% if one is available.  Static means allocate main memory.  Automatic 
% means allocate stack space.  __chip means allocate Amiga specific 
% chip memory.  (#pragma is a PREPROCESSOR instruction fer gosh sake.)
 
I mostly disagree.  True, register is a code generation detail.  I guess
I would prefer that it be a #pragma as well.  Obviously this is not going
to happen.  Personally, I don't use (read: haven't yet) used a register
declaration.  I trust my compiler to make its own best guess as to when
to use a register.

Static and automatic are not code generation details.  These keywords
describe the scope and lifetime of objects they are applied to.  That
they happen to be implemented by allocating main memory and stack space
is irrelevant to me (as a programmer writing a C program.)

Is #pragma really a preprocessor directive?  I have a claimed ANSI
compliant C preprocessor which passes #pragmas untouched to the compiler
and refers to #pragma as a compiler directive.

% ....so your point is that even MicroSoft knows that specialized keywords 
% should be used for storage size, and placement definitions.  (ie: for types,
% which is exactly what pragmas shouldn't be used for (well using a pragma
% to define the primary memory model, or the size of an int isn't evil, but 
% declaring a variable using a pragma IS.)

That wasn't my intended point, actually :-)  My point was more that those
features MS implemented as keywords are admitted to be non-portable, whereas
those features implemented as #pragmas have no such admission.

% >Proposal :
% >  #pragma chip (identifier1 [, identifier2 ...])
% >
% eeeeek!  no.  Don't do this.  Please!

What's wrong with it?  (I know you don't like the idea of a #pragma, but
assuming a syntax like this is required, what would you prefer?)

% 
% .... hey how about #pragma programming language.
[details on how to generate NetHack deleted]

I like it.  It would require that we add a #pragma patchlevel though. :-)

Sigh, I'm beginning to think that chip vs. fast should stay the linker's
responsibility.  Assuming a more perfect world, there would be only one
linker and one object module format; and all languages would use them;
and the linker would worry about chip vs. fast (given the right options);
and could do it intelligently because the .obj file would contain all the 
information one could ever need to do it right; and we wouldn't need to
add a keyword or a #pragma to C; and as a free bonus we would have solved the
problem for Modula-2 and Forth and ...

Sorry this got so long, I hope somebody else still cares about this...

stephan("not officially representing Microsoft Corporation");

walker@sas.UUCP (Doug Walker) (01/02/90)

In article <10033@microsoft.UUCP> w-stephm@microsoft.UUCP (Stephan Mueller) writes:
>Doug Walker writes:
>% #pragma is extremely non-portable.  Each compiler can implement any #pragma
>% keyword any way they wish, and you cannot #define a #pragma away.  You can
>% get rid of __chip simply by defining it to nothing.
>
>There is no need to #define a #pragma away.  K&R 2nd edition, section A12.8
>pp 233:
>
>"A control line of the form
>    #pragma token-sequence(opt)
>causes the processor to perform an implementation-dependent action.  An
>unrecognized pragma is ignored."

I am heartily tired of this discussion, since it is (apparently) a case of 
religious belief, but for the benefit of those who didn't seem to get
the point the first time,

#pragma FOOBAR bletch blah bwap

may be implemented on compiler A to mean 'turn on the global optimizer',
while on compiler B the EXACT SAME LINE may mean 'delete all the files on 
my hard disk when I compile this file'.  This is 100% completely ANSI 
conforming definition on BOTH compilers, but the user of compiler A will
be horrified when running compiler B on the file.  This is of course
an extreme example, but it illustrates the fact that #pragmas are NOT
portable.  There is no provision specified to allow a compiler to
determine whether or not the #pragma applies to it.

This is what I meant when I said:
>% There is no portable way to define a non-portable feature.
>


>If I want to port to another Amiga compiler, say Manx, or Amix or some
>cross-compiler generating Amiga code, then __chip will be non-portable
>but the code using it will not.  In this case, the behaviour of #pragma
>is preferable.  Those compilers that do not support the #pragma will
>still be able to compile the code, and one will need to specify a link
>option or something to get the appropriate module into chip RAM.

There is no difference between a couple of lines of #pragmas in an
include file somewhere and a couple of lines of #defines to get rid
of the new keywords.  I'm sorry, I do not believe this is any more
of a kludge than the #pragmas, and I DO believe it is easier to 
maintain since you SEE the __chip keyword on the chip items, and
if you change the name of the item the __chip keyword applies
automatically to the new one.


One other problem: How do you limit the SCOPE of the #pragma?  Or 
are you saying that one

#pragma chip foobar

at the top of the program makes all variables named foobar, including
extern, static and automatic, go into chip memory?  How do you declare
an automatic pointer to chip memory?  How do you declare a near pointer
to far memory, or a far pointer to chip memory?  


  *****
=*|_o_o|\\=====Doug Walker, Software Distiller=======================
 *|. o.| ||
  | o  |//     "READY!   FIRE!   AIM!   (Software under development!)
  ======
usenet: ...mcnc!rti!sas!walker   plink: dwalker  bix: djwalker 

thad@cup.portal.com (Thad P Floryan) (01/04/90)

Doug Walker brings up some GOOD questions about "#pragma".  For all the
good it (#pragma) does, it may as well be renamed "#fragme" or "#smegma".

(If you don't know the genesis of "frag" (Viet Nam war era), don't ask.)

The ANSI-conforming definition of #pragma in the GNU ``C'' compiler is the
best one I've ever seen; from the GNU docs:

"	The `#pragma' command is specified in the ANSI standard to have an
	arbitrary implementation-defined effect.  In the GNU C preprocessor,
	`#pragma' first attempts to run the game `rogue'; if that fails,
	it tries to run the game `hack'; if that fails, it tries to run
	GNU Emacs displaying the Tower of Hanoi; if that fails, it reports a
	fatal error.  In any case, preprocessing does not continue.
"

Enjoy!

Thad Floryan [ thad@cup.portal.com (OR) ..!sun!portal!cup.portal.com!thad ]