libc, libsys have name conflict with Pascal
The following Pascal program causes a linker error, because its procedure malloc conflicts with malloc in libc:
program callmalloc(output);
var p : ^integer;
procedure malloc;
begin
writeln('pass');
end;
begin
new(p);
malloc;
end.
$ ack -mlinuxppc -o callmalloc callmalloc.p
led: /home/kernigh/park/ack-build/staging/share/ack/linuxppc/libc.a(malloc.o): _malloc: multiply defined (error)
This only happens because Pascal's new uses libc's malloc (since c084f9f). If I delete the new(p); line and the p variable, then the program prints pass.
This kind of name conflict seems to be caused by recent changes to ACK. Older ACK did more to prevent name conflicts between Pascal and C. In older ACK, Pascal programs did not link to libc. Old descr files like lib/i386/descr don't link libc to Pascal programs, but new descr files like plat/linux386/descr do link libc.
Also in older ack, libsys had alternate names for some system calls. These names had underscores, like _exit and _times. They hid from Pascal because Pascal has no underscores in its names. Pascal's libpc called the hidden names. Commit 1c83baa in 2007, and later commits, switched some calls to the regular names like close and open, but the regular names can conflict with Pascal programs.
lang/pc/libpc/READ_ME also mentioned this problem. But this file is quite old, it maybe out of time.
Hmm, yeah.
Modula-2 doesn't suffer from this because it mangles Modula-2 symbol names to include the module name as well. Possibly Pascal should do the same thing? With the extern function declaration syntax, we could still import C symbols easily enough.
Looks like fpc does exactly this, BTW:
$ nm test.o
[...]
0000000000000000 T P$CALLMALLOC_$$_MALLOC
Luckily there's already at least some code in the Pascal compiler for doing this, in gen_proc_name(): https://github.com/davidgiven/ack/blob/default/lang/pc/comp/misc.c It's used for generating unique names for nested functions, but should be adaptable. I don't know how hard it would be to not mangle extern declarations.
Also, what about multiple compilation? How does Pascal normally handle this?
I think that ISO 7185 does not specify module system, which is added in ISO 10206, both can be found at here.
The ACK docs for the Pascal compiler (here: http://tack.sourceforge.net/olddocs/pascal.pdf) has a long list of ISO 7185 extensions which are implemented, none of which I can find references for. extern is apparently defined in ISO 6.1.4. However, the doc says later (in section 10.2) that the compiler only works with programs, not modules, so that sounds like it's only possible to use extern with non-Pascal identifiers.
That means that mangling Pascal symbol names but not extern names should work fine here.
The doc is out of date. Here's our module system at work.
(* part1.p *)
program part1(output);
function secret : integer; extern;
begin
writeln('The secret is', secret);
end.
(* part2.p *)
function secret : integer;
begin
secret := 2000;
end;
Compile with ack -o part1 part1.p part2.p. The compiler for part1 can't know if secret is in C or Pascal.
I found this feature by accident while looking for _m_a_i_n in the Pascal runtime. The compiler only emits _m_a_i_n in a program. If the Pascal file isn't a program, it's a module.
That's both really useful and very annoying --- because extern is used to link both external Pascal symbols and external C symbols we can't use different mangling to distinguish the two.
Open to suggestions --- I don't know what's the best thing to do here (potentially, nothing, and just live with the libc naming conflict problem).