info-vax@ucbvax.ARPA (02/20/85)
From: Gail Rubin <grubin@bbn-spca> If you ever get a response to your SPR on the "address of arguments" problem, I would be interested in hearing about it. We currently use Whitesmith's C but we may decide to switch to DEC C, but not with this bug in it. I have one application that has a large number of routines which, as the first thing they do, is figure out how many arguments they were called with by taking the address of the first argument, subtracting 4, and using that as a pointer to the number of arguments. It sounds like DEC C version 2.0 would break this. [Is there some other "approved" way, from C, of determining number of arguments?] -- Gail Rubin (grubin@bbn-spca or @bbn-unix)
info-vax@ucbvax.ARPA (02/20/85)
From: Gene Lege' <ots!gene@rice.ARPA> I would suggest using the varargs.h macros, or implementing them if they are not available. There is no other completely portable way to pass a variable # of arguements to a "C" function, other than simply defining the called function to accept a large number of args and making sure you don't exceed this number. For instance, on a Pyramid 90x running OSx (UNIX), some of the args would be in the parameter registers, while others would be in the (logical) extension of the stack that is actually in RAM. The net result is that the stack is seperated into two components, the virtual addresses of which are non-contiguous. I believe that the varargs.h standard will be sanctioned by the forthcoming ANSI C standard. I am glad to see this discussion of the DEC VMS C compiler. We are working on a project that will need to run under both UNIX and VMS; Does anybody know of other pitfalls we should watch out for while doing the development under UNIX?
info-vax@ucbvax.ARPA (02/21/85)
From: Jerry Leichter <Leichter@YALE.ARPA> If you ever get a response to your SPR on the "address of arguments" problem, I would be interested in hearing about it. We currently use Whitesmith's C but we may decide to switch to DEC C, but not with this bug in it. I have one application that has a large number of routines which, as the first thing they do, is figure out how many arguments they were called with by taking the address of the first argument, subtracting 4, and using that as a pointer to the number of arguments. It sounds like DEC C version 2.0 would break this. [Is there some other "approved" way, from C, of determining number of arguments?] -- Gail Rubin (grubin@bbn-spca or @bbn-unix) a) Before you get too incensed about the "bug", find a reference anywhere in K&R, or in the proposed ANSI C standard, that says that arguments to a function are allocated sequentially in memory. I doubt you'll succeed. (If I remember right, the ANSI proposal includes some spec for a varargs facility; but this says nothing at all about the underlying mechanism.) The fact that an implementation happens to be different from pcc does not make it buggy. In fact, it's the code that uses a pcc implementation detail that is non- portable. (A look at K&R will reveal a discussion of what one may assume about memory layout - basically, that arrays and structures are layed out sequentially, but there may be gaps inside of structures - and an explicit warning that making any other assumptions is non-portable.) It's one thing to want a "pcc compatibility mode" in some other C compiler, quite another to claim that another C compiler is "buggy" if it doesn't match pcc in every one of its little quirks. b) There is no way (at all) to determine how many arguments a C function was called with. What you will find on the stack is a count of THE NUMBER OF WORDS (or is it bytes?) of arguments pushed. This corresponds in a direct way to the number of arguments only as long as you pass neither structures nor doubles. Once you do that, there is no way to make the translation without knowing the lengths of all the arguments. It's interesting to note, BTW, that the VAX Calling Standard requires all arguments to be longwords. Long floating point values, not to mention "big" objects like structures, are supposed to be passed by reference. However, the definition of C requires the ability to pass such things by immediate value, so the VAX C compiler is "given a variance". Programs in other languages don't support this extension; C programs using such calling sequences cannot call or be called by programs in other languages. (For example, you can use printf() from other languages - but not to print doubles.) BTW, nothing in K&R, or the ANSI draft spec, claims that a C function can determine how many arguments it was called with either. Some PDP-11 Unix versions had a nargs() function that worked by tracing back through the stack and examining the code at the point of call. This broke on machines with an I/D space split. The only effective way to do this is to pass the number of arguments as an additional argument - somewhere. That's what the VAX procedure call, in effect, does for you - as long as all your arguments are the same length. While handy, providing a count is not free and may be quite expensive on some machines; hence, for a low-level language like C, it's inappropriate to require it. I've always thought that the best approach would be to do this through the macro processor; that is, allow something like: #define f(a,b,#) real_f(#count,a,b,#) where "#" matches any number of additional arguments and #count is the actual count in the macro call being expanded. Trivial to implement, gives you the count when you need it and has no overhead when you don't need it. -- Jerry -------
info-vax@ucbvax.ARPA (02/21/85)
From: Gail Rubin <grubin@bbn-spca> Your information about the C standard and portability is reasonable however, the particular application I am concerned with in my message is one that is explicitly designed for VMS only. On the VAX, I KNOW what the stack format is and since I don't use doubles as arguments, the number of longwords IS the number of arguments. My application is a package of routines, a run-time library of sorts, that gets sent to customers and they write programs which call the routines. Since I then have absolutely no control over whether my routines are called correctly, or what language they are called from and some of the routines do have optional arguments, I try to check the number of arguments as one of my validity checks so I can give a more explicit error code back to the user program instead of an access violation or strange behavior. I follow calling standard behavior in that I never modify actual arguments; basically all arguments are passed by reference or descriptor anyway. In light of this, the behavior of DEC C 2.0 is unsuitable for my application. I would be more inclined to stick with the C I have rather than rewrite my routines in Macro. -- Gail