Compiling on Tru64Unix 4.0f

Started by pjot, May 11, 2005, 09:37:47 AM

Previous topic - Next topic

pjot

Hi all,



Today I tried to compile version 8.5.7 on Tru64Unix 4.0f (formerly known as Digital Unix). I have adapted the makefile using the makefile for Solaris as a template:



OBJS = newlisp.o nl-symbol.o nl-math.o nl-list.o nl-liststr.o nl-string.o nl-filesys.o
        nl-sock.o nl-import.o nl-xml.o nl-web.o nl-matrix.o nl-debug.o pcre.o

CFLAGS = -pedantic -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET

CC = cc

default: $(OBJS)
        $(CC) $(OBJS) -lm -lrt -ldb -o newlisp

.c.o:
        $(CC) $(CFLAGS) $<

$(OBJS): primes.h protos.h makefile_solaris


Also I made some minor changes in in sourcefiles:



- Put the #define, #elsif, #endif to the first column in the sourcefiles nl-string.c and nl-sock.c

- Removed "RTLD_GLOBAL" from nl-import.c

- Commented the line #define FIONREAD I_NREAD in nl-sock.c since Tru64 knows the FIONREAD



Now there is only 1 thing left which the Compaq C compiler cannot pass:


Quote
pamela_vaspadm> make -f makefile_tru64

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS newlisp.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS nl-symbol.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS nl-math.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS nl-list.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS nl-liststr.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS nl-string.c

cc: Error: nl-string.c, line 499: In this statement, "args" is of type "pointer to signed char", and cannot be converted to "struct declared without a tag". (noconvert)

vasprintf(&ptr, format, args);

------------------------^

*** Exit 1

Stop.


So the 'vasprintf' is known, but it cannot accept the 3rd argument which indeed appears to be a "char*".



If I comment this 'vasprintf' then everything compiles, but the resulting 'newlisp' binary cores.



Any ideas?



Peter

pjot

#1
Hm, probably newLisp will not run anyway because of the 64-bit architecture of Tru64Unix.



Still it is nice to know that it *almost* compiles... :-)

Lutz

#2
First, thanks for doing this work Peter, every new platform for newLISP is always very welcome by somebody.



For the vasprintf just change the line 499 in nl-string.c to



vasprintf(&ptr, format, (va_list)args)



va_list and char* seem to be equivalent on all OS ( hopefully ;-) )



I will do the same in the next version and check that all is OK on the other platforms.



Lutz

Lutz

#3
Yes, it might not run, but if it compiles/links? why not. I also have a makefile_linux64 for the AMD64 but compile with a special flag -m32, which makes the platform know that it's really a 32bit app.



Lutz

pjot

#4
Unfortunately, that doesn't work either, now I receive the following error:


Quote
pamela_vaspadm> make -f makefile_tru64

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET newlisp.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-symbol.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-math.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-list.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-liststr.c

cc -pedantic -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-string.c

cc: Error: nl-string.c, line 499: In this statement, "va_list" is a struct type, which is not scalar. (needscalartyp)

vasprintf(&ptr, format, (va_list)args);

------------------------^

*** Exit 1

Stop.


I also tried the 'my_vasprintf' in your nl-filesys.c, but also this did not work... :-(

pjot

#5
By the way, I compiled the "types.c" file on Tru64 as well, using the Compaq C compiler, maybe you are interested in the result:


Quote
type      bytes

---------------

char      1

char *    8

short int 2

int       4

long      8

long long 8

float     4

double    8

wchar_t   4

jmp_buf   672

Lutz

#6
The types.c file reveals that it wouldn't work because of the size-8 of char*. And that is probably the reason that va_list is not accepted, which seems to be a struct type on Tru64 but is equivalent to a char* scalar on GCC 32bit.



Perhaps there is a switch similar to -m32 on the AMD64, which lets you compile as a 32 bit application? But it still could be necessary to rewrite my_vasprintf() used in 'format', if workiing differently on that platform.



As soon as 64bit goes mainstream with good GCC support over several platforms newLISP will move to 64bit, but this day seems to be still in the future. It basically means changing the structure of the lisp cell to accomodate 64bit pointers.



Lutz

pjot

#7
There is such an option:  -protect_headers default -xtaso_short



If I compile the types.c with this option, then this is the result:


Quote
type      bytes

---------------

char      1

char *    4

short int 2

int       4

long      8

long long 8

float     4

double    8

wchar_t   4

jmp_buf   672


So this seems to be better. Now, if I compile newlisp, again I receive the same result:


Quote
....

cc -pedantic -protect_headers default -xtaso_short -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-math.c

cc -pedantic -protect_headers default -xtaso_short -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-list.c

cc -pedantic -protect_headers default -xtaso_short -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-liststr.c

cc -pedantic -protect_headers default -xtaso_short -c -O2 -DNANOSLEEP -DSOLARIS -D_POSIX_PII_SOCKET nl-string.c

cc: Error: nl-string.c, line 499: In this statement, "va_list" is a struct type, which is not scalar. (needscalartyp)

vasprintf(&ptr, format, (va_list)args);

------------------------^

*** Exit 1

Stop.


So compiling 32bits is possible, but still it stumbles over this vasprintf argument... ?

Lutz

#8
I would have to study their header files to figure out how "va_list" works on that machine. On the GCC compiler its just the memory addres to the parameters packed one ofter the other in memory.



The types file compile looks good this way, so it should be possible to compile on that machine after the vasprintf obstacle.



Compiling with -DSOLARIS means that the compile is already taking my_vasprintf from nl-filesys.c. You could redefine to take char* on the last argument, but then it might trip over vsnprintf() later in that function and I have no idea how this is defined in your machine'sheader files.



It's tedious to figure out this stuff if you are not on the machine ;)



Lutz

pjot

#9
Yes, I understand, if you're not on the machine yourself, it is hard... the Alphaservers belong to my employer, and unfortunately I cannot just take one home and open a line for you... :-(



Thanks for the compile hints again, tomorrow I'll see if I can pass the vasprintf problem.



Peter

Lutz

#10
You could just out-comment 'format' in primes.h just to see if the whole thing runs after compliling/linking and if it's worth it. Anyway thanks for working on this. The whole vasprintf() and vsnprintf() thing has caused me some head-aches in the past, because it works differently on different compilers. Good luck tomorrow!



Lutz

pjot

#11
Well, good news and bad news.



---> Good news: newLisp compiles and runs on Tru64 4.0f and also Tru64 5.1! <---



Bad news: the 'format' statement delivers "Unaligned access" errors and wrong output.



The reason for the unaligned access is caused by the way I created a workaround for the 'vasprintf' trouble. In the file nl-filesys.c I created an extra function called "tru64_vasprintf" which is a copy of the existing 'my_vasprintf':



int tru64_vasprintf(char * * buffer, const char * format, char* argptr)
{
UINT size = MAX_STRING;
int pSize;

while(TRUE)
        {
        *buffer = allocMemory(size + 2);
        pSize = vsnprintf(*buffer, size + 1, format, argptr);

#ifndef MINGW
        if(pSize > size)
                {
                freeMemory(*buffer);
                size = pSize;
                continue;
                }
#else
        if(pSize < 0)
                {
                freeMemory(*buffer);
                size = size + size / 2;
                continue;
                }
#endif
        break;
        }

return(pSize);
}


The file 'nl-string.c' was changed to point to this function (line 499). Now everything compiles without errors. (Also 'protos.h' was adjusted, adding a prototype.)



However, the 'vsnprinf' takes also a 'va_list' as 3rd argument (why the compiler does not complain now, I don't know). If instead a char* is feeded here, the data alignment error appears.



It might be of your interest to know that the va_list in Tru64 is defined as:



typedef struct {
        char    **_a0;          /* pointer to first homed integer arg */
        int     _offset;                /* byte offset of next param */
} va_list;


Except for the format statement, all other newlisp functions seem to work fine. I will perform some tests today and let you know the results.



Peter

pjot

#12
Adjusted the 'tru64_myvasprinf' function to wrap around the va_list:



int tru64_vasprintf(char * * buffer, const char * format, ...)
{
UINT size = MAX_STRING;
int pSize;
va_list ap;

while(TRUE)
        {
        *buffer = allocMemory(size + 2);
        va_start(ap, format);
        pSize = vsnprintf(*buffer, size + 1, format, ap);
        va_end(ap);

#ifndef MINGW
        if(pSize > size)
                {
                freeMemory(*buffer);
                size = pSize;
                continue;
                }
#else
        if(pSize < 0)
                {
                freeMemory(*buffer);
                size = size + size / 2;
                continue;
                }
#endif
        break;
        }
return(pSize);
}


Now the alignment errors are gone, but the output is wrong. At every string I run through format, the result is 0 (or "0").

Lutz

#13
Its the difference between GNU CC and Tru64 CC how arguments are layed out in memory for vsnprintf().



In Gnu CC all args are packes one after the other in a memory area, in Tru64 after each arg piece comes an int describing the offset. I order to make it work p_format() in nl-string.c would have to be rewritten to pack arguments for the format string in a way necessary for Tru64.



The change you did using va_list and va_start was the right thing to do, but would also require to change the function doing the preperation of it's last args ('ap' in your code) parameter



I wonder if you can get GCC for the Tru64 platform? Perhaps that would be easier then trying to work around the peculiarities of the CC found on Tru64?



This is one of those typical cases where porting gets a head-ache. Another problem is how vsnprintf() returns different values in case of failure, as you can see on the MINGW switch, and this is also something that would have to be looked into.



Anyway, good luck in your porting efforts ... perhaps somebody else here on the port as some 'quick' fix hoew to deal with this problem?



Lutz

pjot

#14
Indeed I already have been busy to change the code in nl-string.c... the memcpy's create a mem layout which indeed is not compatible with Tru64Unix va_list.



I am able to print the first argument though, like (format "c" 65) -> "A". But more complicated formats deliver problems.



The latest GCC for Tru64Unix I am aware of, is version 2.95, which lacks the '-m32' switch.



So I need to hack the memory layout of the 'va_list' anyway, in order to get the format properly working.



BTW: other things, like lists, signals, read-key and sockets, work. It is *only* this format statement which gives a headache. This weekend I will work on the port.



Peter