DECC on x86 getline, getdelim issue

OpenVMS x86 native compilers, cross compilers news and questions.

Topic author
arpadffy
Member
Posts: 9
Joined: Sun May 24, 2020 1:23 pm
Reputation: 0
Location: Stockholm, Sweden
Status: Offline

DECC on x86 getline, getdelim issue

Post by arpadffy » Fri Nov 24, 2023 3:31 pm

Hi,

I apologize for a stupid question, but even after few hours of reading the code and header files, I could not find any explanation for this phenomena.

Could somebody be kind and explain what is going on with the DECC on x86 around getline and getdelim functions?

Background: I am porting an open source project to x86VMS

The very same code works well on VAX, Alpha and Itanium.
Tested with the following compilers - and the program builds and works very well:
Compaq C V6.4-005 on OpenVMS VAX V7.3
HP C V7.3-020 on OpenVMS IA64 V8.4
Compaq C V6.5-001 on OpenVMS Alpha V7.3
VSI C V7.4-002 on OpenVMS Alpha V8.4-2L1

...but on x86 it fails with a very strange error.
I use: VSI C x86-64 X7.4-843 (GEM 50XB9) on OpenVMS x86_64 V9.2-1

Code: Select all

            line = cp->getline(c, cp->cookie, indent, options);
...............................^
%CC-W-TOOMANYACTLS, Too many actual parameters in the invocation of the macro "getline".

            line = cp->getline(c, cp->cookie, indent, options);
...................^
%CC-E-NEEDMEMBER, In this statement, "getdelim" is not a member of "cp".
First: as the very same code works on all other platforms and getline has not changed for ages it is strange that it complains about the number of arguments

Second: the getdelim function is not used anywhere in the code, regardless the compiler complies about a missing member.

Without getting deep in the far too complicated piece of code, let's describe the issue on a simple way:

There is a given structure:

Code: Select all

struct loop_cookie
{
    int		current_line;		
    int		repeating;		
    char_u	*(*getline)(int, void *, int, getline_opt_T);
    void	*cookie;
};

The struct is used in the following way:

struct loop_cookie  *cp = (struct loop_cookie *)cookie;
line = cp->getline(c, cp->cookie, indent, options);
In order to satisfy the compiler I went on (a lucid) changing the structure by adding the getdelim member.

Code: Select all

struct loop_cookie
{
    int		current_line;		
    int		repeating;	
    char_u	*(*getline)(int, void *, int, getline_opt_T);
#if defined (VMS) || defined (X86_64)
    char_u	*(*getdelim)(int, void *, int, getline_opt_T);
#endif
    void	*cookie;
};
After this change the compiler was mostly satisfied as the error vanished but the warning still persisted

Code: Select all

            line = cp->getline(c, cp->cookie, indent, options);
...............................^
%CC-W-TOOMANYACTLS, Too many actual parameters in the invocation of the macro "getline".
The executable was built with warnings. The program mostly works... but it has problems with the functionality that depends on this piece of code (while on all other platforms all works well).

The getline and getdelim basically differs just in number of parameters and what is the line delimiter. This might cause the issues... but I do not understand how the getdelim() comes into the picture at all (just in X86VMS)?

Any explanation or a workaround suggestion would be highly appreciated.

Thanks,
Z
Last edited by arpadffy on Fri Nov 24, 2023 3:44 pm, edited 4 times in total.


hb
Valued Contributor
Posts: 79
Joined: Mon May 01, 2023 12:11 pm
Reputation: 0
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by hb » Fri Nov 24, 2023 5:06 pm

I would use /LIST/SHOW=ALL to find out, where the getline macro is defined and how it is expanded in the source.

To me it looks like the shown struct member, a function pointer named getline, conflicts with a (new) macro, which implements the Posix function getline(). I would try to rename the name of the function pointer to something else.


pustovetov
VSI Expert
Contributor
Posts: 18
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by pustovetov » Fri Nov 24, 2023 6:39 pm

arpadffy wrote:
Fri Nov 24, 2023 3:31 pm

First: as the very same code works on all other platforms and getline has not changed for ages it is strange that it complains about the number of arguments

Second: the getdelim function is not used anywhere in the code, regardless the compiler complies about a missing member.
Hi. The POSIX functions getline and getdelim were added to the C RTL in 2020 year. Their description in stdio.h is protected in this way - #if defined(__DECC) && (__CRTL_VER >= 80500000). But... in x86 __CRTL_VER became greater than 90000000. This is why you have this problem.
There are two possible solutions - rename getline in your structure; use /DEFINE=(__CRTL_VER_OVERRIDE=80400000) when compiling.


Topic author
arpadffy
Member
Posts: 9
Joined: Sun May 24, 2020 1:23 pm
Reputation: 0
Location: Stockholm, Sweden
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by arpadffy » Fri Nov 24, 2023 7:09 pm

pustovetov wrote:
Fri Nov 24, 2023 6:39 pm
There are two possible solutions - rename getline in your structure; use /DEFINE=(__CRTL_VER_OVERRIDE=80400000) when compiling.
Thank you very much.
It worked.

I was suspecting some solution like this... but is there any way for us mortal warriors to find this out ourselves?

Going forward with the port and choosing solution path using __CRTL_VER_OVERRIDE=80400000 indeed solves the problem with getline function in the structure, but other issues arose:

1. the X86_64 is not defined. This is not unexpected. It is possible to define manually, but it feels more future proof if the compiler does it for us.
2. after including math.h the isinf() appears implicitly declared during usage and the HAVE_ISINF is not set (while isnan() does not have any problem on X86_64) (I do not need to mention that on earlier compilers this works perfect)

@pustovetov do you have a magic for this issue too?

Thanks,
Z
Last edited by arpadffy on Sat Nov 25, 2023 1:31 am, edited 1 time in total.


sms
Master
Posts: 349
Joined: Fri Aug 21, 2020 5:18 pm
Reputation: 0
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by sms » Sat Nov 25, 2023 1:58 am

Code: Select all

> [...] is there any way for us mortal warriors to find this out
> ourselves?

   Find out _what_, exactly?

> I would use /LIST/SHOW=ALL to find out, where the getline macro is
> defined and how it is expanded in the source.

   That'd be how I'd start.  (Except I use /show = (all, nomessages).)

> 1. the X86_64 is not defined. [...]

      HELP CC Language_topics Predefined_Macros System_Identification_Macros

The "__" spellings (including __VMS) tend to be more reliable, unless
you want portability to _very_ obsolete compilers.


pustovetov
VSI Expert
Contributor
Posts: 18
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by pustovetov » Sat Nov 25, 2023 4:45 am

arpadffy wrote:
Sat Nov 25, 2023 1:29 am
I was suspecting some solution like this... but is there any way for us mortal warriors to find this out ourselves?
How we protect old programs from new functions using __CRTL_VER is in the documentation.
The fact that this protection broke on x86 is probably also in some release notes. But I'm not sure.
1. the X86_64 is not defined. This is not unexpected. It is possible to define manually, but it feels more future proof if the compiler does it for us.
Try __x86_64 or __x86_64__
2. after including math.h the isinf() appears implicitly declared during usage and the HAVE_ISINF is not set (while isnan() does not have any problem on X86_64) (I do not need to mention that on earlier compilers this works perfect)
isinf() is a new macro that is protected from being used with #if (__CRTL_VER >= 80500000).


Topic author
arpadffy
Member
Posts: 9
Joined: Sun May 24, 2020 1:23 pm
Reputation: 0
Location: Stockholm, Sweden
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by arpadffy » Sat Nov 25, 2023 12:51 pm

Thank you very much both.
The final solution was to find (again) and use @sms's excellent script (http://antinode.info/ftp/misc/cheader.com) to extract all headers to be able to see what is happening there.

I assume that these protections around the functions are not bugs but intentionally crafted on purpose with conscious decision that they will brake the backwards compatibility.

Thank you for all support.


sms
Master
Posts: 349
Joined: Fri Aug 21, 2020 5:18 pm
Reputation: 0
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by sms » Sat Nov 25, 2023 3:19 pm

Code: Select all

> I assume that these protections around the functions are not bugs but
> intentionally crafted on purpose with conscious decision that they
> will brake the backwards compatibility.

   They're normally not bugs, and they normally _provide_ some forward
and backward compatibility, _not_ break it.  Bear in mind that the C RTL
and the C compiler are two separate items.

   Say you have an old system where, for example, strtok_r() or
strerror_r() does not exist in the VMS C RTL.  With an old C compiler,
they won't be declared in the header files (like <string.h>), and your
program will need to provide replacement functions, and matching
declarations.

   The __CRTL_VER conditions in the header files (like <string.h>) mean
that you can install (on your old system) a new C compiler with its new
header files, and your program can still be built, and will work as
before.

   On a newer system, where the VMS C RTL does have these functions, the
compiler will see those newer declarations, and your program can use
them instead of your old replacement functions.  You might need to add
some __CRTL_VER conditions to your builders, to avoid including your old
replacement functions and the new C RTL in the same executable.

   It's not perfect compatibility, but it's not bad.  (I claim.)

   If you want to keep using your replacement functions, then you might
need to add some items to the /PREFIX_LIBRARY_ENTRIES = (EXCEPT = [...])
list, to avoid conflicts (%LINK-W-MULDEF) between them and the same-name
functions in the new C RTL.  That can be useful if, say, the function or
parameter types are different between your replacement functions and the
functions in the new C RTL (and header files).

   Again, it's not perfect compatibility, but it's not bad.  (I claim.)
   
   Have you a better scheme in mind?
   
      If you look at the GNU (and other) stuff at antinode.info, you'll see
this kind of stuff all over the place.  Maintaining it all manually is
less convenient than having a "configure" script to do it all
automatically, but the existing "configure" scripts tend to be useless
on VMS.


hb
Valued Contributor
Posts: 79
Joined: Mon May 01, 2023 12:11 pm
Reputation: 0
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by hb » Mon Nov 27, 2023 4:26 am

arpadffy wrote:
Sat Nov 25, 2023 12:51 pm
The final solution was to find (again) and use @sms's excellent script (http://antinode.info/ftp/misc/cheader.com) to extract all headers to be able to see what is happening there.
The final solution for what?
I assume that these protections around the functions are not bugs but intentionally crafted on purpose with conscious decision that they will brake the backwards compatibility.
From what I see and understand, getline() is a POSIX.1-2008 function. Protecting it with __CRTL_VER >= 80500000 is insufficient. It should be protected with something like _POSIX_C_SOURCE >= 200809[L] and/or _XOPEN_SOURCE>=700. Also, to fully support /PREFIX_LIBRARY_ENTRIES = (EXCEPT = [...]), getline should not be implemented as a macro.

Again, from what I understand, the problem (or bug) is that the header file exposes a Posix function to non-Posix sources.

You didn't say much about your open source, but it seems it is not a Posix source.


pustovetov
VSI Expert
Contributor
Posts: 18
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: DECC on x86 getline, getdelim issue

Post by pustovetov » Mon Nov 27, 2023 5:12 am

hb wrote:
Mon Nov 27, 2023 4:26 am
From what I see and understand, getline() is a POSIX.1-2008 function. Protecting it with __CRTL_VER >= 80500000 is insufficient. It should be protected with something like _POSIX_C_SOURCE >= 200809[L] and/or _XOPEN_SOURCE>=700.
Agree. But in our headers, _POSIX_C_SOURCE separates standard functions from VMS extensions. And it does not protect non-POSIX-compatible programs from POSIX-specific functions. As an example:

Code: Select all

#ifdef _POSIX_C_SOURCE
    int chdir (const char *__dir_spec);
#else
    int chdir (const char *__dir_spec, ...);
#endif
However, there should be something like this:

Code: Select all

#if _POSIX_C_SOURCE >= 200809L
#if _VMS_C_EXT
#else
    int chdir (const char *__dir_spec, ...);
#endif
    int chdir (const char *__dir_spec);
#endif
#endif
IMO It is difficult to change this legacy without the risk of breaking the compilation of many programs for customers.

Post Reply