0

I am learning C and trying to make sure my code is portable. For that effect, I build on Macs (ARM, PPC, Intel), Linux (ARM, PPC, PA-RISC) and HP-UX (PA-RISC). To make sure I have an easy way to output simple graphics, I am using GLUT.

I have the following code and functions:

GLfloat white[3] = { 1.0, 1.0, 1.0 };
GLfloat red[3] = { 1.0, 0.0, 0.0 };
GLfloat green[3] = { 0.0, 1.0, 0.0 };

void printText(char *text, const GLfloat colour[3], float posX, float posY) {
    glColor3fv (colour);
    glRasterPos2f(posX, posY); //define position on the screen
      
    while(*text){
      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *text++);
    }
}

void GLprintTextAndInteger (char *text, int value, float colour[3], float posX, float posY) {
    int length = snprintf(NULL, 0, "%s %i", text, value);
    char *stringToPrint = malloc(length + 1);
    snprintf(stringToPrint, length + 1, "%s %i",text,value);
    printText(stringToPrint,colour,posX,posY);
    free(stringToPrint);
}

void GLprintTextAndLong (char *text, long value, float colour[3], float posX, float posY) {
    int length = snprintf(NULL, 0, "%s %ld", text, value);
    char *stringToPrint = malloc(length + 1);
    snprintf(stringToPrint, length + 1, "%s %ld", text, value);
    printText(stringToPrint,colour,posX,posY);
    free(stringToPrint);
}

Which I call as follows, for example:

GLprintTextAndInteger("sample text", int whatever, white, -0.98f, 0.1f);
GLprintTextAndLong("sample text", long whatever, white, -0.98f, 0.0f);
printText("some text",white,-0.98f,-0.1f);

When I build on HP-UX, using both HP's compiler and also GCC, when I run the program, only printText works. GLprintTextAndInteger and GLprintTextAndLong do nothing (or maybe they work, but are black and then I can't see the output). The code builds without any warnings in all platforms. It runs perfectly well on Linux and Mac, in all architectures.

Any suggestions?

Edit:

During troubleshooting, I found out that if I replace:

int length = snprintf(NULL, 0, "%s %i", text, value);

with

int length = 40;

it works fine. Why is snprintf failing?

Shiunbird
  • 87
  • 8
  • Hope you are using freeglut and not the glut in opengl. https://stackoverflow.com/q/15613978/1216776 – stark May 01 '21 at 22:04
  • Thank you @stark . I don't see how this is relevant, though. My goal is actually to use the officially supported libraries that came with the system. I think the problem I am having is more related to C than to GLUT. – Shiunbird May 02 '21 at 09:32
  • Are you sure that you're having AND using a POSIX.1-2001 or C99 conformant C library environment on HP-UX? Quoting form the manpage: "Concerning the return value of snprintf(), SUSv2 and C99 contradict each other: when snprintf() is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. POSIX.1-2001 and later align their specification of snprintf() with C99." – derhass May 02 '21 at 12:00
  • @derhass You are up to something here. I placed a printf() to print int length after running snprintf(NULL, 0, "%s %i", text, value); and I get 0 under HP-UX and the real length of the string everywhere else. I'm still very much a beginner, so I don't even know exactly where to look up, but I will dig into the documentation. – Shiunbird May 03 '21 at 14:55
  • Well, the behavior you describe is conformant to the Single Unix Specification v2. It is just not conforming to C99 or POSIX.1-2001. In the end of day, this is why stuff like GNU autotools exist - which allow you to write tests for all sorts of differences between Unix flavours, and use a separate implementation if necessary. See for example https://www.jhweiss.de/software/snprintf.html for a C99 compatible snprintf implementation which you might just add to your project. – derhass May 03 '21 at 15:02

1 Answers1

0

According to the man page for snprintf(3s) (see https://www.unix.com/man-page/hpux/3s/snprintf/):

By default, returns a negative value if maxsize is smaller than the number of characters formatted. In the UNIX 2003 standards environment (see standards(5)) it returns the the number of bytes that would have been written to buffer s, excluding the terminating null byte, if maxsize had been sufficiently large.

The UNIX 2003 standard is only supported on HP-UX 11iv3 (11.31), if you compile like this:

$ export UNIX_STD=2003
$ make/cc/whatever

Here is a test program I used to verify this:

root@hpvm01:~/t$ cc -o s s.c
root@hpvm01:~/t$ ./s
r=0
root@hpvm01:~/t$ UNIX_STD=2003 cc -o s s.c
root@hpvm01:~/t$ ./s
r=6
root@hpvm01:~/t$ cat s.c
#include <stdio.h>

int main()
{
  int r = snprintf(NULL, 0, "hello\n");

  printf("r=%d\n", r);
}

So I hope you are using 11.31 and not an earlier version. In that case maybe an open source version of snprintf might help: http://hpux.connect.org.uk/hppd/hpux/Development/Libraries/snprintf-2.2/

fork2execve
  • 1,561
  • 11
  • 16