Re: translate at warp speed
Posted in 1993
>Date: Mon, 15 Nov 93 14:24:52 MST
>From: alan@po.den.mmc.com (Alan Popiel)
>Subject: translate at warp speed
>X-Informix-List-Id: <list.3100>
Alan,
Thanks for the function you offer. I have a number of comments to make, all
about parameter passing in one direction or the other.
>Summary:
>--------
>Jack Parker, Robert Minter, and I have been having some fun developing a
>reasonably general purpose Informix 4GL callable function for doing substring
>search and replace. Calling syntax for this function is:
>
>CALL translate ( old, new, stringin ) RETURNING stringout
>or
>LET stringout = translate ( old, new, stringin )
> ...
>However, for those of you who may need to do such translations thousands
>or more times, I offer my C version for your use. Please see the notes
>below regarding parameter fetching.
> ...
>translate (nparms)
>int nparms;
>{
> ...
> /* fetch arguments; note that 'nparms', number of
> arguments, is NOT checked for correct value 3 */
> popquote( strin, sizeof(strin) );
> popquote( new, sizeof(new) );
> popquote( old, sizeof(old) );
> ...
> pushquote( strout, sizeof(strout)-1 );
> return(1);
>} /* end function 'translate' */
To return values, you are supposed to use:
retquote(strout, sizeof(strout)-1);
and not pushquote(). I grant you that they do much the same job, but they
don't do the same job. retquote() deals with the problem that strout is a
local variable to the translate() routine and no longer exists (officially)
by the calling code pops the value off the stack. By contrast, pushquote()
is used when calling another routine, and the variable continues to exist
after the called routine exits. If you worked on a fussy enough machine,
you could get an access violation error because strout is below the current
bottom of the (C) stack when the value is read.
>Parameter fetching notes:
>-------------------------
>The above 'popquote()' and 'pushquote()' work with Informix C4gl version 2.10.
>Jack Parker tells me that for Informix C4gl 4.10, he needed to change the code
>to this:
>
> /* fetch arguments */
> popint(&ls); popquote( strin, ls );
> popint(&ln); popquote( new, ln );
> popint(&lo); popquote( old, lo );
> ...
> retquote( strout );
I can find no justification for the popint() calls. Indeed, I can think of
several reasons not to do it, such as I can't find any code that needs it
or will be guaranteed to work correctly with it. For example, given this
code:
FUNCTION f()
DEFINE c, d, e CHAR(256)
CALL g(c, d, e) RETURNING c
END FUNCTION
the 4.12 compiled I4GL compiler produces:
f (fgl_pcnt)
int fgl_pcnt;
{
$ char c [257];
$ char d [257];
$ char e [257];
_anyerr = 0;
ixpshhwm();
{
int fgl_svstk, fgl_nret;
fgl_svstk = mark_stack();
pushquote(c,256);
pushquote(d,256);
pushquote(e,256);
fgl_nret = g(3);
rest_stack(fgl_svstk);
_anyerr = 0;
ld_quote(0, c, 257) ;
ixrsthwm();
}
ixpophwm();
return(0);
}
The ixXYZhwm() routines are there to ensure that error -4518 doesn't occur
any more. The rest shows no justification for the function g() to pop any
integers off the stack before popping the strings -- the source code for
pushquote() definitely only pushes a single (string) value onto the stack.
Oh, and 4.12 also doesn't restrict you to returning only 512 bytes; you are
stuck with just 32767 bytes per character string. I wouldn't recommend
using that size of variable (it takes a long time to copy the data around),
but you will be able to do so if you want to.
Yours,
Jonathan Leffler (johnl@informix.com) #include <disclaimer.h>