[comp.sys.amiga.tech] strins

jdp@caleb.UUCP (Jim Pritchett) (06/06/89)

Recently, Chuck McManis posted a program which shows the active Locks on
a volume.  The program calls a function called strins().  Could someone
out there provide a description of what this function does?  I assume that
it is a Lattice supplied function.  However, since I have the Aztec compiler
so I will need to write a substitute function.

By the way, does anyone out there know when/if a new version of the Aztec C
compiler and SDB will be available?  (I have 3.6A)


                                  Thanks,



--

                                         Jim Pritchett

                                         UUCP:  {killer!texbell}!letni!caleb!jdp
                                          or    killer!gtmvax!dms3b1!caleb!jdp

cmcmanis%pepper@Sun.COM (Chuck McManis) (06/12/89)

SUMMARY:
	(void) strins(s1, s2)
	char *s1, *s2;

Null terminated string s2 is copied into the front of null terminated
string s1. So if s2 had a pointer to "foo" in it and s1 had a pointer
to "bar" in it, after the call s1 will point to a string "foobar".

Probably the best way to simulate this is with :
string(s1, s2)
	char	*s1, *s2;
{
	char tmp[80];

	strcpy(tmp, s1);
	strcat(tmp, s2);
	strcpy(s1, tmp);
	return;
}


--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.
"A most excellent barbarian ... Genghis Kahn!"

jmsc@inesc.UUCP (Miguel Casteleiro) (06/13/89)

In article <109394@sun.Eng.Sun.COM>, cmcmanis%pepper@Sun.COM (Chuck McManis) writes:
> 
> SUMMARY:
> 	(void) strins(s1, s2)
> 	char *s1, *s2;
> 
> Null terminated string s2 is copied into the front of null terminated
> string s1. So if s2 had a pointer to "foo" in it and s1 had a pointer
> to "bar" in it, after the call s1 will point to a string "foobar".
                                                           ^^^^^^^^
  Shouldn't it be "barfoo" ??

> Probably the best way to simulate this is with :
> string(s1, s2)
> 	char	*s1, *s2;
> {
> 	char tmp[80];
> 
> 	strcpy(tmp, s1);
> 	strcat(tmp, s2);
> 	strcpy(s1, tmp);
> 	return;
> }
>
> --Chuck McManis

   Am I missing something, or this is exactly wath strcat is suppose to do !!

   From the UNIX manual:

SYNTAX
     char *strcat(s1, s2)
     char *s1, *s2;

DESCRIPTION
     The arguments s1 and s2 point to strings (arrays of
     characters terminated by a null character).

     The strcat subroutine appends a copy of string s2 to the end
     of string s1.


-- 
                                                                      __
 Miguel Casteleiro at                                            __  ///
 INESC, Lisboa, Portugal.                                        \\\/// Only
 UUCP: ...!mcvax!inesc!jmsc   "Life is hard and then you die."    \XX/ Amiga

doug@xdos.UUCP (Doug Merritt) (06/13/89)

In article <10285@watcgl.waterloo.edu> gswan@watcgl.waterloo.edu (Geo Swan) writes:
>I have seen lots of code that builds strings, particularly pathnames
>through the use of several calls to strcat.  I have never been able
>to understand why people didn't use sprintf.  Particularly in the
>case of building pathnames.

One perfectly valid reason is that sprintf() is much higher overhead
than simpler routines. It runs slower and takes up a fair amount of space.

I dunno about Manx and Lattice on the Amiga, but on many systems, the
existence of %f/%e/%g in {s,f,}printf means that a lot of unneeded floating
point code overhead will get thrown in.
	Doug
-- 
Doug Merritt		{pyramid,apple}!xdos!doug
Member, Crusaders for a Better Tomorrow		Professional Wildeyed Visionary

cmcmanis%pepper@Sun.COM (Chuck McManis) (06/14/89)

In article <10285@watcgl.waterloo.edu> (Geo Swan) writes:
> I have never been able to understand why people didn't use sprintf. 

The answer is fairly simple. sprintf(3) is often entangled with the 
stdio library. When you use it, it depends on a bunch of other stuff
that pulls in most of stdio. Your "simple" function suddenly yanks
14K of code out of the library into your executable. Plus it is a
lot more efficient to use strxxx() routines which are simply loops
where as sprintf() invokes the _doprnt() parser to figure out how to
put together your strings. Generally, sprintf() is easier but strxxx()
routines are smaller. If your compiler/linker is smart enough to 
recognize the difference between when you want full stdio versus 
just simple printf's that helps. 


--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.
"A most excellent barbarian ... Genghis Kahn!"

cmcmanis%pepper@Sun.COM (Chuck McManis) (06/14/89)

In article <897@inesc.UUCP> jmsc@inesc.UUCP (Miguel Casteleiro) writes:
>   Am I missing something, or this is exactly wath strcat is suppose to do !!

Your missing something, it is the _inverse_ of strcat(). strins() _prepends_
strings, whereas strcat() _appends_ strings.


--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.
"A most excellent barbarian ... Genghis Kahn!"

jms@tardis.Tymnet.COM (Joe Smith) (06/14/89)

[I predict there will be over 25 followups to Geo's article.]

In article <10285@watcgl.waterloo.edu> gswan@watcgl.waterloo.edu (Geo Swan) writes:
>Let me suggest that our original poster consider using the following macro:
>#define	strins( s1, s2 )	sprintf( s1, "%s%s", s2, s1 )

Can you guarantee that the above macro will work when s2 is longer than s1?
Example:  Let's say s1 is a pointer to an array of 80 bytes, and only the
first two bytes have any characters, the rest are null.  Let's say s2 is
a pointer to a string of 4 bytes.  As sprintf copies s2 into s1, it overwrites
the original string.  If sprintf copies until len(s1), then it will return
a pointer to an 8 byte string - s2 concatenated with s2.  If sprintf copies
until it gets to the null byte, it will never find it - s1 will get an
infinite number of copies of s2.  Or guru.

It's OK to use sprintf as long as the destination does not include any of
the sources.
-- 
Joe Smith (408)922-6220 | SMTP: JMS@F74.TYMNET.COM or jms@tymix.tymnet.com
McDonnell Douglas FSCO  | UUCP: ...!{ames,pyramid}!oliveb!tymix!tardis!jms
PO Box 49019, MS-D21    | PDP-10 support: My car's license plate is "POPJ P,"
San Jose, CA 95161-9019 | narrator.device: "I didn't say that, my Amiga did!"

root@dialog.UUCP (Christian Motz) (06/14/89)

In article <109394@sun.Eng.Sun.COM> cmcmanis%pepper@Sun.COM (Chuck McManis) writes:
>
> [...]
>
>Probably the best way to simulate this is with :
>string(s1, s2)
>	char	*s1, *s2;
>{
>	char tmp[80];
>
>	strcpy(tmp, s1);
>	strcat(tmp, s2);
>	strcpy(s1, tmp);
>	return;
>}

Maybe so, but isn't this a little bit inflexible? I usually use the
following routine:

char *strins(at, str)
char *at, *str;
{
	movmem(at, at+strlen(str), strlen(at)+1);
	movmem(str, at, strlen(str));
	return at;
}

There is no limit to your string length imposed by this routine,
you don't need a lot of valuable stack space, and who knows, it
might even be a tick faster ...

--
Christian Motz       uucp: ...!uunet!mcvax!unido!pfm!nadia!dialog!root
"Trust me, I know what I'm doing!" -- Sledge Hammer         Bix: cmotz

giguere@aries5.uucp (Eric Giguere) (06/14/89)

In article <10285@watcgl.waterloo.edu> gswan@watcgl.waterloo.edu (Geo Swan) writes:
>I have seen lots of code that builds strings, particularly pathnames
>through the use of several calls to strcat.  I have never been able
>to understand why people didn't use sprintf.  Particularly in the
>case of building pathnames.

If you're trying to write small programs with as little library 
overhead as possible you should avoid any of the (f/s/v)printf routines
if at all possible.  As anyone who's looked through the bowels of a C
compiler knows, the printf routines are some of the largest routines
around and non-trivial to code.  That's why the standard program      

     main()
       {
         printf( "hello, world\n" );
       }

is actually more of a test for the C compiler than you'd normally think.
A routine like strcat is for the most part just a tight loop that moves
characters around and is very economical.

Having said that, once you've used printf even once in a program you might
as well use the others if convenient (and if not too slow for you) since
the code is there already (fprintf, sprintf, vprintf and printf are all
front-ends to a central format routine).

At least in Aztec C (and Lattice, I assume) printf isn't too bad if you
don't use any floating-point functions.

Eric Giguere                                  268 Phillip St #CL-46
For the curious: it's French ("jee-gair")     Waterloo, Ontario  N2L 6G9
Bitnet  : GIGUERE at WATCSG                   (519) 746-6565
Internet: giguere@aries5.UWaterloo.ca         "Nothing but urges from HELL!!"

doug@xdos.UUCP (Doug Merritt) (06/15/89)

In article <109819@sun.Eng.Sun.COM> cmcmanis@sun.UUCP (Chuck McManis) writes:
>In article <897@inesc.UUCP> jmsc@inesc.UUCP (Miguel Casteleiro) writes:
>>   Am I missing something, or this is exactly wath strcat is suppose to do !!
>
>Your missing something, it is the _inverse_ of strcat(). strins() _prepends_
>strings, whereas strcat() _appends_ strings.
>
He's not missing as much as you think; your posted example definition of
strins() had a bug in it such that it actually implemented the functionality
of strcat()!

I didn't say anything at the time because I figured it was an obvious
mistake and somebody else would probably nitpick it anyway.

If anyone's still confused, this is what he *meant*:

strins(d, s)
	char	*d, *s;
{
	char	tmp[256];

	strcpy(tmp, s);
	strcat(tmp, d);
	strcpy(d, tmp);
}

	Doug
-- 
Doug Merritt		{pyramid,apple}!xdos!doug
Member, Crusaders for a Better Tomorrow		Professional Wildeyed Visionary

C506634@UMCVMB.BITNET ("Eric Edwards") (06/15/89)

Sorry about the duplicate in comp.sys.amiga. I hit "reply" and amiga-relay only
 sends to comp.sys.amiga.  Now back to our regulary scheduled posting...

  - - The original note follows - -

In Measage ID<256@maytag.waterloo.edu> giguere@aries5.uucp says:
>If you're trying to write small programs with as little library
>overhead as possible you should avoid any of the (f/s/v)printf routines
>if at all possible.  As anyone who's looked through the bowels of a C
>compiler knows, the printf routines are some of the largest routines
>around and non-trivial to code.  That's why the standard program
>
>     main()
>       {
>         printf( "hello, world\n" );
>       }
>
>is actually more of a test for the C compiler than you'd normally think.

Lattice uses a bultin function to get arround this problem in printf.
I quote from the Lattice manual, _Lattice C Compiler_ version 4.0

"     printf

When this function is called, the compiler examines the formatting string:

*  When it is a constant string with no substitutions, the compiler changes the
   printf call to a _write call.
*  When it is a constant string AND only contains %s, %d and p% formats a call
   is made to _tinyprintf "

Disclaimer:  All typos are assumed to be mine, not the manual's.

Further they say they may do similar tricks for scanf, sprintf and fprintf but
upon checking my 5.0 manual I don't thing they have done this to date.

>Eric Giguere                                  268 Phillip St #CL-46
>For the curious: it's French ("jee-gair")     Waterloo, Ontario  N2L 6G9

Bitnet:    C506634@umcvmb.bitnet                    __________________________
Internet:  C506634@umcvmb.missouri.edu             / \.--------.           /  \
"The Amiga just isn't reliable enough unless you   |  | Eric   |---------+    |
know a lot about the machine" -- Jerry Pournelle   |  `--------'         !    |
  ================================================||  .--------.         !    |
"I did notice that at my party people stood in     |  | Edwards|_________+    |
 line to play with the Amiga"-- Jerry Pournelle    | /`--------'          ^   |
                           BYTE, October '88       \__________________________/
\\\ Note Forwarded  on: 06/14/89 19:16:30 ///
\\\      To: AMIGATEC ///

peter@sugar.hackercorp.com (Peter da Silva) (06/15/89)

In article <8906150029.AA22430@jade.berkeley.edu>, C506634@UMCVMB.BITNET ("Eric Edwards") writes:
> Lattice uses a bultin function to get arround this problem in printf.

What problem?

> I quote from the Lattice manual, _Lattice C Compiler_ version 4.0

> "     printf
> *  When it is a constant string with no substitutions, the compiler changes the
>    printf call to a _write call.

What if you have your own version of printf? Say, one that understands more
escape sequences (%e -- error text, %t -- absolute tab, %l -- length byte)?

Can you freely interleave _write with stdio routines?

Does it work if you have freopened stdout?

This sounds like a pretty dubious optimisation.
-- 
Peter "Have you hugged your wolf today" da Silva      `-_-'
...texbell!sugar!peter, or peter@sugar.hackercorp.com  'U`

new@udel.EDU (Darren New) (06/16/89)

In article <3930@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes:
>In article <8906150029.AA22430@jade.berkeley.edu>, C506634@UMCVMB.BITNET ("Eric Edwards") writes:
>> Lattice uses a bultin function to get arround this problem in printf.
>> "     printf
>> *  When it is a constant string with no substitutions, the compiler changes the
>>    printf call to a _write call.
>
>What if you have your own version of printf? Say, one that understands more
>escape sequences (%e -- error text, %t -- absolute tab, %l -- length byte)?

The way this works in LC4.0 (and I would suspect 5.0) is that stdio.h has
a #define printf __builtin_printf. Taking this line out (or #undef) would
turn this back into a normal function. Redefining printf seems kind of dubious 
to me, knowing the little I do about ANSI. This is also used to inline
strcpy, strcat, and a couple others (in 4.0).

>Can you freely interleave _write with stdio routines?
Not standardly. I would think that you would change it to puts(), myself.
>Does it work if you have freopened stdout?
Which would cure this problem also. I'm interested in seeing what they
do in 5.0 also (just ordered it today..) -- Darren

gay_d@elma.epfl.ch (06/16/89)

In article <17740@louie.udel.edu: new@udel.edu (Darren New) writes:
->In article <3930@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Si
lva) writes:
->>In article <8906150029.AA22430@jade.berkeley.edu>, C506634@UMCVMB.BITNET ("Er
ic Edwards") writes:
->>> Lattice uses a bultin function to get arround this problem in printf.
->>> "     printf
->>> *  When it is a constant string with no substitutions, the compiler changes
 the
->>>    printf call to a _write call.

I think it's called _writes

->>What if you have your own version of printf? Say, one that understands more
->>escape sequences (%e -- error text, %t -- absolute tab, %l -- length byte)?
->
->[...] Redefining printf seems kind of dubious
->to me, knowing the little I do about ANSI. This is also used to inline
->strcpy, strcat, and a couple others (in 4.0).

From the little I know about ANSI, you can't portably redefine printf, as
other library routines may use it ... Also, I think that they suggest that
you inline strcat, et al (though not printf).

->>Can you freely interleave _write with stdio routines?
->Not standardly. I would think that you would change it to puts(), myself.

Seeing that it isn't _write, you can freely intermix _writes with stdio
routines! Also, don't forget that puts() adds a newline.

David Gay
GAY_D@ELMA.EPFL.CH   <-- Note the change of address

limonce@pilot.njin.net (Tom Limoncelli) (06/17/89)

My understanding of the ANSI standard is as follows:

The original draft insisted that if you create a function that has
the same name as something in the standard library, the behavior
was implementation defined with the warning that you might have
problems if you write a function called printf() that (for example)
formats disks.  Pray that none of the other library routines use
your printf instead of their intended one.

The second draft states that "the library names are (in principle)
[now] reserved names.  If you write your own version of fopen, say,
your program MIGHT work in some environment that you know well, but
it would have slim chances of being generally portable." {footnote:
The C Journal, Summer 1985, "Draft ANSI C Scorecard -- Second
Round" by Thomas Plum, pg 29-34}

Of course, this is not completely helpful nor is it a generally
good way of dealing with this problem.  So, in a later draft [no
footnote here, this is "as I understand it"] the X3J11 committee
decided to adopt a better method.  Now if you want to write your
own "fopen" routine, that is, if you want to write a routine named
"fopen", not replace "fopen"'s functionality with a function of
your own:

 #undef fopen

then you have full access to that reserved word.  If you think
about it, it makes sence.  Basically, fopen has a definition.  If
you want to change it, undefine it and redefine it yourself.  Just
like if you want to (eeek!) change the value of EOF.

 #undef EOF
 #define EOF (-69)

This is also very easy to implement.  If a vender wants to
implement a function as inline code, they use a very long #define.
If the user doesn't want it to be inlined, they simply #undef it
and now the linker will try to find that routine first in the
current module (.o file) then in one of the libraries.  ANSI also
dictates that the linkers must perform in this way.

If the vender doesn't want the function to be inlined, they call it
(for example) __stlib_fopen and do a #define fopen __stlib_fopen.
All identifiers beginning with "__" are the domain of the vender,
so there will be no namespace conflict.  I don't recall how they deal
with the #undef'ed identifier, I wouldn't expect them to put
__stlib_fopen and fopen in the library (duplicate code).  Maybe someone
can follow up on this.

Simple?  I think it's very workable.

I hope this explanation is helpful, I know it was a bit long winded
but I think it covered all the bases.


Please correct me if I'm wrong.  As I said, this is how I
understand it.

-Tom
-- 
 Tom Limoncelli -- tlimonce@drunivac.Bitnet -- limonce@pilot.njin.net
       Drew University -- Box 1060, Madison, NJ -- 201-408-5389
   Standard Disclaimer: I am not the mouth-piece of Drew University

jyegiguere@lion.waterloo.edu (Eric Giguere) (06/18/89)

In article <Jun.16.23.36.52.1989.29150@pilot.njin.net> limonce@pilot.njin.net (Tom Limoncelli) writes:
>If the user doesn't want it to be inlined, they simply #undef it
>and now the linker will try to find that routine first in the
>current module (.o file) then in one of the libraries.  ANSI also
>dictates that the linkers must perform in this way.

Frankly I don't like the idea of having the compiler rename printf() on me
by default... I think defining a macro that would turn ON the "tiny printf"
substitution would be better.

One thing I'm curious about, though, is where you got the idea that the
ANSI specs say anything about the linkers?  I can't find that statement
about the linkers having to perform that way at all.  If that's true then
none of the C compilers on IBM mainframes can be conforming compilers 
because the standard IBM linker (on CMS at least) will not link a set of
files with duplicate identifiers.... 

I think this discussion has passed the scope of this group... further 
comments should go to comp.lang.c....

Eric Giguere                                  268 Phillip St #CL-46
For the curious: it's French ("jee-gair")     Waterloo, Ontario  N2L 6G9
Bitnet  : GIGUERE at WATCSG                   (519) 746-6565
Internet: giguere@aries5.UWaterloo.ca         "Nothing but urges from HELL!!"

cmcmanis%pepper@Sun.COM (Chuck McManis) (06/20/89)

To kick a completely dead horse, another 10' out into the pasture ...

The question :
	"Why use strxxx() routines when sprintf() is easier to read/use ?"

The answer : (from several sources) 
	"Because the stdio printf is _huge_."

In article <8906150029.AA22430@jade.berkeley.edu> ("Eric Edwards") writes:
> Lattice uses a bultin function to get arround this problem in printf.

Good for Lattice, unfortunately they don't define the standard for the
world. In general when designing useful utility routines like strins()
you must work from the assumption that the compiler is minimally compliant
and doesn't play any games with the library routines. 


--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.
"A most excellent barbarian ... Genghis Kahn!"