[comp.sys.mac.programmer] LSC 3.0, argc & argv, linking

swilson%thetone@Sun.COM (Scott Wilson) (09/03/88)

The topic of passing argc and argv to a C program came up on comp.lang.c
which got me thinking about the way this works in THINK's LightspeedC.
For those who aren't familiar, in LSC to get a pseudo UNIX command line
that allows you to type program arguments that will end up as argv, you
call your main() function _main().  You then link your program with the
file "unix main.c" which has a main() in it that parses the command line
and then calls your _main().  I think this is kludgey.  I don't like the
idea of having code that looks like:

	#ifdef THINK_C
	#define main _main
	#endif

This is ugly.  To me, there seems to be a better way to do this (I would
mail this to THINK, but they don't seem too thrilled to listen to me these
days).  I would like to see this problem solved by how the program
was linked:  if "unix main.c" is added to the project then a command
line is prompted for and args are passed to main() in the user's program; if
"unix main.c" is not in the project then main() is called with argc of 1.
This way main() in the user's program would always be called main.  The
file "unix main.c" could have a _main() in it that would do the command line
stuff and then call main().  In the abscence of "unix main.c", another _main() 
would be linked in that would just set argc to 1 (and either the program
name or "" for argv) and call main().  This other, nearly null, _main() would
reside in MacTraps or some other convenient place and would be supplanted by
the _main() in "unix main.c" if present.  Of course, this means that LSC's
startup code would jump to _main() to start off instead of main(), but
this would be transparent to the program which certainly isn't the case
now.

I don't think this is currently possible at present, however, which
brings me to the next topic.  I haven't been able to make it work,
but does LSC allow you to supersede some functions of a library
without causing link errors?  For example let's say you wanted to
link with strings but wanted to have your own version of just strcpy().
I believe that this evokes an error message complaining of multiple
occurrences of strcpy().  I think this is something LSC should allow,
but it would mean there needs to be some method of determining which
occurrence of a function was used.  UNIX in this case does the following
(I think):  a function that came from a file given on the command line
supersedes any occurrence of a function of the same name that is found
in a library.  The distinction is between compiled user files and system
libraries.  LSC could do something similar, if a user's .c contained
a function also found in a library then the user's version would be used.
This would also mean that code ported to LSC would not have to worry
about clashing with some non-standard fucntions in LSC's library (like
trying to port a program that had it's own Move() in it (I think that's
the name LSC uses, but I don't have it here)).

Any comments on this?

--
Scott Wilson		arpa: swilson@sun.com
Sun Microsystems	uucp: ...!sun!swilson
Mt. View, CA

upstill@pixar.UUCP (Steve Upstill) (09/07/88)

    I say it's unfair to expect ThinkC to do something Unix C doesn't: allow
the user to supercede an arbitrary function from a library.  The Unix
linker links in a whole module whenever it defines a single undefined symbol.

Steve Upstill

kaufman@polya.Stanford.EDU (Marc T. Kaufman) (09/07/88)

In article <2391@pixar.UUCP> upstill@pixar.UUCP (Steve Upstill) writes:

>    I say it's unfair to expect ThinkC to do something Unix C doesn't: allow
>the user to supercede an arbitrary function from a library.  The Unix
>linker links in a whole module whenever it defines a single undefined symbol.

You imply that the link problem is a "C" restriction.  It is not.  It is a
problem with a particular LINKER implementation.  There is no requirement that
there be more than one entry point in a module, or that specific entry points
cannot be overridden quietly...  I had such a linker on a VAX I used, as well
as many other large mainframe machines.  There is no way a user can know in
advance just which entry points are grouped into "modules".  For the sake of
portability, I often include my own version of routines which may be present
on some, but not all, systems the code may run on (such as atan2).  It is
reasonable to expect that a linker will honor my requests to override specific
modules.

Marc Kaufman (kaufman@polya.stanford.edu)

jnp@calmasd.GE.COM (John Pantone) (09/08/88)

(Steve Upstill) writes:
>I say it's unfair to expect ThinkC to do something Unix C doesn't:
>allow the user to supercede an arbitrary function from a library.  The
>Unix linker links in a whole module whenever it defines a single
>undefined symbol.

Are you saying that ThinkC and Unix will not allow something like:

link my_main with (my_)printf and anything else needed from lib c
(except the copy of printf in there)

where the printf explicitly specified also exists in lib c, but I wish
it to be superceeded by my version?

Then the ThinkC and the Unix linker are outmoded and weak, to say the
least.  REAL linkers have allowed this sort of selective replacement
for years. (Even CP/M allow(s/ed) this).
-- 
These opinions are solely mine and in no way reflect those of my employer.  
John M. Pantone @ GE/Calma R&D, 9805 Scranton Rd., San Diego, CA 92121
...{ucbvax|decvax}!sdcsvax!calmasd!jnp   jnp@calmasd.GE.COM   GEnie: J.PANTONE

swilson%thetone@Sun.COM (Scott Wilson) (09/08/88)

>    I say it's unfair to expect ThinkC to do something Unix C doesn't: allow
>the user to supercede an arbitrary function from a library.  The Unix
>linker links in a whole module whenever it defines a single undefined symbol.

UNIX libraries (.a files) are composed of many separately compiled object
files (.o files).  As far as I know the linker extracts only the .o files
needed to resolve references when linking.  If you have your own strcpy,
for example, the linker will not get strcpy.o from the library because the
reference has already been satisified.  Which versions of UNIX are you
talking about, because the following has always worked for me without
linker complaints:

		cc try.c strcpy.c -o try

I'm only asking THINK C to be as smart as the UNIX linker, not any smarter.

--
Scott Wilson		arpa: swilson@sun.com
Sun Microsystems	uucp: ...!sun!swilson
Mt. View, CA

hkbirke@mit-amt (Hal Birkeland) (09/08/88)

> UNIX libraries (.a files) are composed of many separately compiled object
> files (.o files).  As far as I know the linker extracts only the .o files
> needed to resolve references when linking.  If you have your own strcpy,
> for example, the linker will not get strcpy.o from the library because the
> reference has already been satisified....

I ran into just such a replacement problem with one recent multi-person
software project (we each wrote separate parts and then combined them
together).  Buried in the middle of one of my partners code was a definition
for random (using longs, of course) which returned a random POSITIVE OR 
NEGATIVE integer.  My code grabbed the library random (positive integer
return value).  The result was that my code crashed when compiled into
the project, but ran fine on its own.

If the library function was not automatically superceded, the error did not
occur (even worse, the problem couldn't be solved until I ran "strings" on
the other guys code).  After all, YOU CAN NAME YOUR FUNCTIONS ANYTHING YOU
WANT while the libraries are ALREADY DEFINED.

Please rename the functions rather than reusing the existing symbol...

-- hal

conybear@bruce.oz (Roland Conybeare) (09/08/88)

From article <2391@pixar.UUCP>, by upstill@pixar.UUCP (Steve Upstill):
> 
>     I say it's unfair to expect ThinkC to do something Unix C doesn't: allow
> the user to supercede an arbitrary function from a library.  The Unix
> linker links in a whole module whenever it defines a single undefined symbol.
> 
> Steve Upstill

	I disagree! :-)  The unix linkers that I have used all link files
left to right*, resolving references as they go.  So if I wanted to redefine
malloc, I could:
1.  Write my own malloc
2.  Link my version before the standard library
    e.g.  cc myprogram.o mymalloc.o -lc

          In this case the linker will resolve all malloc's in myprogram.o
	  when it comes across mymalloc.o.  It will resolve malloc's in
	  the standard library, using the original malloc defined there.

P.S. Caveat Emptor

Roland Conybeare

	
	
* I mean in the order supplied to the linker

levin@bbn.com (Joel B Levin) (09/08/88)

In article <59@calmasd.GE.COM> jnp@calmasd.GE.COM (John Pantone) writes:
|
|Are you saying that ThinkC and Unix will not allow something like:
|
|link my_main with (my_)printf and anything else needed from lib c
|(except the copy of printf in there)
|
|where the printf explicitly specified also exists in lib c, but I wish
|it to be superceeded by my version?
|
|Then the ThinkC and the Unix linker are outmoded and weak, to say the
|least.  REAL linkers have allowed this sort of selective replacement
|for years. . . .

The UNIX(TM) linkers I have known, and the MPW linker as well, do
allow exactly this.  But there is one problem that you have to watch
out for.  Using your example: if the module within the library which
contains printf also contains (say) sprintf, AND my_main calls sprintf
as well as printf, AND you do not provide a substitute (my_)sprintf,
then when the linker attempts to resolve the sprintf reference, it
will find itself with two entries for printf.  This will make it
unhappy.  The solution is to determine all the entry points in the
standard library module containing printf and to provide those entry
points in your own version.

As to the previous question: sorry, I have no idea what ThinkC does.

	/JBL


UUCP:     {backbone}!bbn!levin		POTS: (617) 873-3463
INTERNET: levin@bbn.com

swilson%thetone@Sun.COM (Scott Wilson) (09/09/88)

>If the library function was not automatically superceded, the error did not
>occur (even worse, the problem couldn't be solved until I ran "strings" on
>the other guys code).  After all, YOU CAN NAME YOUR FUNCTIONS ANYTHING YOU
>WANT while the libraries are ALREADY DEFINED.
>
>Please rename the functions rather than reusing the existing symbol...

Part of the point, though, is that reusing the library symbol may
be exactly what you want.  For instance, let's say that code runs
great on machine A.  When you port it to machine B you find that some
library function is broken.  So you write your own version of the function
and link it in superseding the broken library funtion.  If the linker
doesn't allow you do this, you resort to ugliness like putting
"#define fgetc XXXfgetc" at the top of your code.  This is what I have
done with THINK C (and I'm not implying their library is broken, but
in some cases I wanted to use home-made functions that were more compatible
with UNIX).  I would much rather just link the code with my versions of
the library functions.

Another point to consider is that those "already defined" library names
can be non-standard names that will conflict with ones you've chosen.
For example if you had a program that had a function called cgets() it
wouldn't link with THINK C because this is a (non-standard) part of
their stdio library.  (I think that's the name of the function, but
I wouldn't bet my life on it because I don't have my THINK C docs at
work.)

It sounds like a warning from the linker that a library symbol was
being superseded would have prevented your problem while allowing
the type of things I describe.  I don't how hard that would be to
implement, but I could live with the warnings.

--
Scott Wilson		arpa: swilson@sun.com
Sun Microsystems	uucp: ...!sun!swilson
Mt. View, CA

"It's the end of the world as we know it, and I feel fine."	-R.E.M.