Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site ucsfcgl.UUCP Path: utzoo!linus!decvax!ucbvax!ucsfcgl!katzung From: katzung@ucsfcgl.UUCP (Brian Katzung) Newsgroups: net.lang.c Subject: Re: gripe: variable arg lists Message-ID: <394@ucsfcgl.UUCP> Date: Wed, 21-Nov-84 17:27:27 EST Article-I.D.: ucsfcgl.394 Posted: Wed Nov 21 17:27:27 1984 Date-Received: Fri, 23-Nov-84 02:26:32 EST References: <348@gitpyr.UUCP> <3106@alice.UUCP> Organization: UCSF Computer Graphics Lab Lines: 65 > But there is a standard method of dealing with variable argument lists. > #include > The contents of the file differ from machine to machine, but the `entry points' > are standard. > > As to why _doprnt() was used: that's pretty easy. There is no standard > analog to printf which accepts a variable argument list *as an argument*. > > Marty Shannon > UUCP: {alice,rabbit,research}!mjs > (rabbit is soon to die. Does this mean alice is pregnant? Yup!) > Phone: 201-582-3199 (I didn't see the original article so I'm not sure what was said. My apologies if I'm repeating something.) The "standard method" can't always be applied. As far as I know, it is impossible to do under some implementations (I'd be delighted to have somebody prove me wrong by providing a non-trivial solution (ie, one that doesn't consist of separate entry points)). The problem arises on systems like ZILOG that put some arguments in registers (it may speed up execution a little, but it slows me down a lot). Fixing argument references in the case of printf-like routines is messy, but straight-forward: printf(rformat, rarg1, rarg2, rarg3, sarg1) /* r = in register, s = on stack */ char *rformat... { int regcnt = 3; char *argp = &rarg1; /* (argp <- addr of copy of reg) */ /* * Current argument is *argp. Next argument is: */ if (--regcnt) /* Not last register argument. */ (Advance pointer by appropriate amount) else /* Switch from r to s args. */ argp = &sarg1; } Now suppose I have a pair of functions, say "xlist" and "xvec", that have been written on another system and have been "sprinkled" into numerous modules. The routines have the following structure: xvec (vec) xtype *vec; /* ((xtype) 0) terminated vector. */ { body } xlist (element1) /* Called xlist(e1, e2, ..., en, (xtype) 0); */ xtype element1; { xvec(&element1); /* Let xvec do the work. */ } On a Zilog system, xvec has to be split into a routine that takes a vector, and a routine that takes the address of the first "register" argument and the address of the first stack argument. All occurrences of xlist-style calls to xvec have to be changed to xvec2(&rarg1, &sarg1), and xvec becomes "xvec2(vec, &vec[4])" (xvec2 now does the work). Brian Katzung ucbvax!ucsfcgl!katzung