라벨이 port인 게시물 표시

Porting to OS/2: Case #27 iconv() and configure test

iconv() is used to support i18n(internationalization). On OS/2, there are ULS(Universal Language Support) APIs. kLIBC provides iconv() implemented by this ULS APIs. By the way, ULS APIs are dependent on the installed code page files in \LANGUAGE\CODEPAGE on a boot drive. Unfortunately, SBCS OS/2 does not have some DBCS code page files by default. As a result, some DBCS charsets are not supported by ULS APIs on SBCS system. Likewise iconv() of kLIBC fails to support DBCS charsets. Especially, configure test for iconv()(iconv.m4) checks the eucJP charset which corresonds to IBM-954 code page(See \LANGUAGE\CODEPAGE\UCSTBL.LST). However, SBCS OS/2 does not have IBM-954 code page file in \LANGUAGE\CODEPAGE by default. After all, configure test for working iconv() fails. There are three ways to solve this problem. 1. Copying IBM943 to IBM954 IBM943 is a Japanese code page file. So copy it to IBM954. This is very simple workaround to pass configure test. But IBM943 is not same as...

Porting to OS/2: Case #26 getrusage()

getrusage() provides measure of resource used by the current process or its child processes. See for details. http://pubs.opengroup.org/onlinepubs/9699919799/functions/getrusage.html OS/2 kLIBC has a declaration of getrusage(), but not implemented it actually. Instead, OS/2 kLIBC provides a minimal information for getrusage(). Here is the implementation using it. source: https://github.com/komh/os2compat/blob/master/process/getrusage.c test: https://github.com/komh/os2compat/blob/master/testcase/getrusage-1.c

Porting to OS/2: Case #25 POSIX semaphores

POSIX semaphores are used to control the execution of threads. There are unnamed semaphores and named semaphores. Although named semaphores are always shareable between processes, unnamed semaphores may be private or shareable between processes. Out of these, implementation of unnamed private semaphore is here. source: https://github.com/komh/os2compat/blob/master/thread/semaphore.c header: https://github.com/komh/os2compat/blob/master/thread/semaphore.h test: https://github.com/komh/os2compat/blob/master/testcase/semaphore-1.c  

Porting to OS/2: Case #24 scandir() and alphsort()

scandir() scans a directory, and alphsort() is provided to scandir() as a comparison function to sort directory entries into alphabetical order. OS/2 kLIBC has a declaration for scandir(), but has not implemented it. In case of alphsort(), OS/2 kLIBC has no even the declaration for it. Here is the implementation and a test for them. source: https://github.com/komh/os2compat/blob/master/io/scandir.c header: https://github.com/komh/os2compat/blob/master/io/scandir.h test: https://github.com/komh/os2compat/blob/master/testcase/scandir-1.c This implementation follows OS/2 kLIBC declaration. However, notice that OS/2 kLIBC declaration is slightly different from POSIX specs. See the comments for details.

Porting to OS/2: Case #23 if_nameindex() family

if_nameindex() is used to retrive all network interface names and indexes. if_freenameindex() is used to free internal storages allocated by if_nameindex(). And there is a family which maps a network inteface name to its corresponding index, and vice versa. They are if_nametoindex() and if_indextoname() . OS/2 has no them. Fortunately, however, OS/2 provides socket calls to implement them. First, you can use os2_ioctl( SIOSTATIF42 ) . This call provides interface statistics for all interfaces up to 42 via struct ifmib which includes a index and a description of a network interface. A index is 0-based. However, if_nameindex() family accepts 0-index as the last entry of network interfaces or an invalid index. So it's needed to increase the index by 1. A description is a long description not a short description. For example, Ethernet-Csmacd not lan0. So you should generate a canonical name from a description and an index. For details, see the following ODIN source. htt...

Porting to OS/2: Case #22 _response()

OS/2 kLIBC provides _response() to expand arguments from a response file. And this enables to pass a very long command line. Because OS/2 itself has the limit of a command line length up to 32K. By the way, _response() has a problem. It limits characters per line up to 8192 characters. So if a line has characters more than 8192, then the line is splitted into two or more lines. This is not an expected behavior. To overcome this, I've reimplemented _response() without a line length limit. Here it is. _response(): https://github.com/komh/os2compat/blob/master/process/_response.c   test: https://github.com/komh/os2compat/blob/master/testcase/_response-1.c

Porting to OS/2: Case #21 setmode()

setmode() is used to change the text/binary mode of a file handle. By the way, these modes exists on DOS-like OSes such as OS/2, Windows and DOS. Whereas, UNIX-like OSes such as Linux don't distinguish these modes. They treats all the file handles as a binary mode. In addition, they uses pipes actively via standard handles such as stdin, stdout and stderr. By the way, on OS/2, they are opened in a text mode by default. So it is general to call setmode() in order to change standard handles to a binary mode at the beginning. Because -Zbin-files does not affect on standard handles. This is a good strategy. However, standard handles are used to input from keyboard and to output to a screen, too. As a result, if you change standard handles to binary mode when they are not connected to pipes, then you would encounter unexpected behaviors. For example, if you output two lines, "Hello," and "World", then you expect like this. Hello, World Instead, howver, yo...

Porting to OS/2: Case #20 CMSG_ALIGN, CMSG_SPACE and CMSG_LEN macros

OS/2 kLIBC has been missing some control message such as CMSG_ALIGN , CMSG_SPACE and CMSG_LEN macros until 0.6.6. They should be like this, Colored By Color Scripter ™ 1 2 3 4 #define  CMSG_ALIGN( len ) _ALIGN( len ) #define  CMSG_SPACE( len ) ( CMSG_ALIGN(  sizeof (  struct  cmsghdr )) + \                             CMSG_ALIGN( len )) #define  CMSG_LEN( len ) ( CMSG_ALIGN(  sizeof (  struct  cmsghdr )) + ( len )) Here, struct msghdr is in sys/socket.h . See the following link for a detail. https://github.com/komh/os2compat/blob/master/network/cmsg.h

Porting to OS/2: Case #19 Windows and Odin

OS/2 and Windows are based on similar architectures. Because of these, when porting programs for other platforms to OS/2, Windows codes are very helpful. Then how about porting from Windows to OS/2 directly ? As I said above, architectures used on OS/2 and Windows are similar. So it's possible to think that porting is relatively easy. However, implementing and replacing Windows APIs are hard and boring task. Especially, porting GUI APIs is peak. Nevertheless, there is no need to be afraid beforehand. Find the way to go slowly. Implementing Windows APIs First way is to implement Windows APIs directly. When you try to this, MSDN is your friend. You should implement those APIs in according to specifications of MSDN. If you have no clues, then try googling or refer to Odin sources. Many people already implemented many Windows APIs in Odin proejct. And Odin project is being maintained at netlabs. Window Coordinate Systems When implementing GUI APIs, there is one thing whic...

Porting to OS/2: Case #18 Qt basic

Qt is a very powerful cross-platform framework. And it was ported to OS/2, but it is more or less old. Because the latest upstream version is 5.3, and OS/2 version is 4.7.3. Nevertheless, Qt4 is still very powerful and useful. In addition, bww bitwise works, who is porting Qt to OS/2, has a plan to port Qt5 as well. So I recommend to use Qt if you have a plan to create GUI programs for OS/2 rather than native PM APIs. And this has another benefits. If you don't use specific codes to OS/2, then you can create a program for other platforms with minimum modifications. This is true when porting to OS/2. That is, if some programs have no specific codes to specific OSes, they can be ported to OS/2 easily. Based on this aspect, let's find basic ways to port programs using Qt to OS/2. Basic procedures to build Qt-programs is like the following. qmake make What a simple. But sometimes, some projects requires some tasks such as configure before qmake. Or, they may use other pr...

Porting to OS/2: Case #17 spawn...()

Many Unix programs seem not to care about command line length. So sometimes they pass a very long command line to a child program. However, OS/2 has a limitation for a command line length. It's 32KB. If a length is longer than 32KB, then OS/2 cannot execute a child program. If so, there is no way to workaround this ? Fortunately, there is a way in case of kLIBC. kLIBC supports a response file as an argument. Instead of passing arguments to a child program directly, passing arguments via a response file is the way. Here is spwanvpe() to pass a very long command line as a response file. https://github.com/komh/os2compat/blob/master/process/spawnvpe.c And a test program. https://github.com/komh/os2compat/blob/master/testcase/spawnvpe-1.c https://github.com/komh/os2compat/blob/master/testcase/spawnvpe-1-child.c How to build spawnvpe-1.exe gcc spwanvpe-1.c spawnvpe.c How to build spawnvpe-1-child.c gcc spawnvpe-1-child.c Other spawnl...() and spawnv...() can ...

Porting to OS/2: Case #16 mmap()

mmap() is used to map a file into memory. It is known that using mmap() is more efficiency than using file-related functions such as read()/write(). So many projects are using it. Unfortunately, however, OS/2 kLIBC does not support mmap(). And OS/2 itself does not have features corresponding to mmap() directly. Because of this, there is need to implement mmap() by ourselves. When I was porting binary codec support of MPlayer to OS/2, mmap() was needed. Although it does not have all the features which mmap() has, it is useful generally. // ----- 2014/11/04 It support MAP_PRIVATE, partially MAP_FIXED but not MAP_SHARED. It supports MAP_PRIVATE, MAP_SHARED and partially MAP_FIXED. // ----- mmap.c mmap.h mmap-1.c mmap-1.c is a test program for mmap(). To build, gcc -o mmap-1.exe mmap-1.c mmap.c Finally, you should be careful for translation mode. If opening in text mode, translation of CR/LF to LF may cause unexpected behaviors. And even if opening in binary mode, you sho...

Porting to OS/2: Case #15 fast mutex

Mutex(mutual-exclusive) is used to synchronize executions of threads. Of course, OS/2 supports mutex very well. But, there is one caution. OS/2 mutex is a recursive mutex. That is, if a thread requests a mutex which is already owned by a different thread, that thread is blocked. But if a thread which already owns a mutex requests the same mutex, then it succeeds. This is a recursive mutex. In general, this works well. However, sometimes a non-recursive mutex, so called fast mutex, is needed. That is, even if an owner thread requests its owning mutex, that thread should be blocked, get an error at least. A fast mutex can be implemented easily with a recursive mutex of OS/2. The following are the codes. Colored By Color Scripter ™ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #define  INCL_DOS #include  ...

Porting to OS/2: Case #14 open() and DASD access

On Unix-like systems, open() can open various devices including files, storages and so on. On OS/2 kLIBC as well, open() does like that. However, open() of kLIBC does not support DASD. If you open [x:] expecting to open a drive x: in DASD mode, your expectation will go wrong. Although open() for x: succeeds, it is not for DASD mode, but for a directory. The handle returned can be used with functions which do not alter a file position and contents. For examples, fchdir() and fstat(). Then what is how to open in DASD mode ? Use a wrapper function for DosOpen(). The following are the codes used by libdvdnav.  Colored By Color Scripter ™ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #ifdef  __OS2__ #define  INCL_DOS #include  <os2safe.h> #include  <os2.h> #include  <io.h>      /* setmode() */ #include  <fcntl.h>   /* O_BINARY  *...

Porting to OS/2: Case #13 iconv()

iconv() is used to convert one charset  to the other charset. OS/2 kLIBC supports iconv() natively using Uni*() APIs of OS/2. By the way, it has some limitations which Uni*() APIs have. That is, kLIBC iconv() does not support charsets which is not supported by Uni*() APIs. For examples, Uni*() APIs does not support UTF charsets except UTF-8. And some extensions are not supported. For examples, //TRANSLIT and //IGNORE. So if you use kLIBC iconv() with some projects, iconv() may fail due to these. To workaround these, you may use a wrapper function like this. Colored By Color Scripter ™ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #if   defined (__KLIBC__) && ! defined (iconv_open) /* kLIBC iconv_open() does not support UTF-16LE and //TRANSLIT */ static  iconv_t os2_iconv_open ( const   char  *tocode,  const   char ...

Porting to OS/2: Case #12 readdir_r() and struct dirent

readdir() and readdir_r() are used to read directory entries. And readdir_r() is a re-entrant version of readdir(). Because of this, readdir_r() requires additional arguments. Let's see prototypes of them. struct dirent *readdir(DIR * dirp );   int readdir_r(DIR * dirp , struct dirent * entry , struct dirent ** result ); As you see, readdir_r() requires [struct dirent *entry]. And entry should be large enough for a dirent. For this, the recommended portable codes are like this. Colored By Color Scripter ™ 1 2 3 4 5 name_max = pathconf(dirpath, _PC_NAME_MAX); if  (name_max == -1)          /* Limit not defined, or error */     name_max = 255;          /* Take a guess */ len = offsetof( struct  dirent, d_name) + name_max + 1; entryp...

Porting to OS/2: Case #11 freopen()

freopen() is used to reopen a file with a pre-existed stream pointer. kLIBC supports freopen() well. However, it has a problem. First, let's see the prototype of freopen(). FILE *freopen(const char * filename , const char * mode , FILE * stream ); If filename is NULL, freopen() changes the mode of stream. That is, read/write, text/binary and so on. And if freopen() fails, then it returns NULL. By the way, kLIBC freopen() returns NULL even if it succeeds when filename is NULL. For examples, the following code returns NULL. freopen( NULL, "wb", stdout ); However, stdout is changed to binary mode correctly. So in this case, the return value should be ignored. Nevertheless, you should not always ignore NULL. Then what is the way to distinguish them ? freopen() sets 'errno' variable to a proper error value if it fails. So if you check errno, then it is possible to distinguish them. Use the following macro. Colored By Color Scripter ™ 1 2 #define  freopen...

Porting to OS/2: Case # 10 getnameinfo(), freenameinfo() and getaddrinfo()

getnameinfo(), freenameinfo() and getaddrinfo() are not provided by kLIBC. Like poll(), you can find the replacements from many projects such as FFmpeg and Gnulib. Here is the one based on VLC. getaddrinfo.h : https://github.com/komh/os2compat/blob/master/network/getaddrinfo.h getaddrinfo.c : https://github.com/komh/os2compat/blob/master/network/getaddrinfo.c

Porting to OS/2: Case #9 poll()

poll() is similiar to select(), and is used widely. However, kLIBC does not have it. Fortunately, there are many replacements for it. Here, I provide the one from VLC. You can find them in many projects such as FFmpeg and Gnulib. poll.h : https://github.com/komh/os2compat/blob/master/network/poll.h poll.c : https://github.com/komh/os2compat/blob/master/network/poll.c

Porting to OS/2: Case #8 atomic builtins

From time to time, you may encounter the following error when compiling. Undefined symbol ___sync_val_compare_and_swap_4 referenced from text segment This function is an atomic builtin of gcc. Nevertheless, even though you are using the latest gcc, this may occur. This is because this atomic builtin enabled only at i486 cpu or later, but the default architect of OS/2 gcc is i386. If you want to confirm the architect of your gcc, do this. gcc -E -dM - < nul And you can find __tune_i386__. Now add -march=i486. gcc -march=i486 -E -dM - < nul Then, you can find __tune_i486__ instead of __tune_i386__. In addition, you can find another differences. Especially, Colored By Color Scripter ™ 1 2 3 #define  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 #define  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 #define  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 Consequently, if you encounter that error, then add -march=i486 to your compiler flags. For re...