ANSI C89 and POSIX portability?
LordNite asks: "Here is the situation. I am maintaining a piece of source code which is written in K&R C. One of the original goals of this code was to be as portable as possible to as many platforms as possible. The code runs on UNIX and its clones as well as OS/2. The code avoids POSIX functions such as mmap(2) since at the time it was initially written (early 1990s) POSIX was not very wide spread. The code is well written, but in need of some serious fixing. As I go around fixing parts of the code I would also like to modernize it a bit. Since it is now 2004, can I rely on ANSI C89 and POSIX routines without sacrificing the portability of this code? (Yes, I do realize that the purpose of POSIX is code portability...) I am not really interested in the OS/2 port at this time. I am just interested in keeping portability with UNIX clones. To put my question another way: Are there any UNIX-like OSes in common use, which are currently developed and supported by some entity either OSS or proprietary, that do not support POSIX and ANSI C89?"
"Ask Slashdot: Can I revise my code?" Dear Slashdot community, I've got some old code; can I revise old code? Thanks.
Firstly, if you read the entire autoconf manual, you know the intricacies of 90% of these niggling little compatibility differences on every UNIX variant out there.
Secondly (with automake) it can make a build environment that automatically converts ANSI C to K&R C, if the target install environment only supports K&R C. So don't sweat it. Use mmap() if HAVE_MMAP is defined. Personally, I would abstract file I/O and do all work as abstract file operations. You can then choose after-the-fact whether to fopen()/fread()/fclose() or mmap()/memcpy().
Does my bum look big in this?
and let the downstream distro maintainers give you patches. You should probably be focusing on over quality and maintainability of the code, not on why Irix version 5.blah.blah has no shitfuck() system call.
- If it's working, be real careful in how you decide to 'fix' it. The old "if it ain't broke, don't fix it" adage is really true when it comes to old software.
- Check the original assumptions. Which platforms did it have to run on originally? How many of those vendors are still around? What platforms does it have to run on now? You may discover that the only platforms you need to support all have good POSIX facilities.
- If you've really got a wild hair to improve things, consider creating a port to $foo (Perl, Python, Java,
.NET, etc.). One way to get around the lots of different incompatabilities problem is to use a language which already abstracts these things away, after all. - If you absolutely must have platform-specific behavior in C, then GNU Autoconf is probably your best bet. Be warned that GNU Autoconf is arguably a cure that's worse than the disease. I've yet to meet one single programmer who's thought Autoconf was a good idea--only that Autoconf was a marginally less bad idea than all the other alternatives.
Good luck!Anything modern will at least have an ANSI compiler, though for some commercial platforms, the ANSI tools will cost you extra. In such a case, GCC will run just about anywhere, though.
As for the libraries... Well, there are a few calls which are not portable and should be avoided, or at least used with caution, because POSIX/SVID/BSD/etc. all have slight differences which conflict with each other.
I think it helps to look at manpages. Particularly, the "Conforming to" bits. If something says BSD or SVID, it might not work everywhere.
Also, the GNU manpages are fairly good at tracking potential portability problems.
Ok, POSIX is all about the system calls and C library functions. C89 is about compiler support. They are seperate and don't go hand-in-hand.
/dev/[u]random and /proc filesystems. There's a lot of common interfaces, as long as you target relatively recent releases.
i d=762&group_id=1#platforms You have to be a developer of a sourceforge project to get access, but its a good deal.
About POSIX and Unix compatibility. There are a handful of Unixes that remain important and widely deployed. They are:
Solaris
HP-UX
AIX
Linux
*BSD
MacOSX
They pretty much all have modern APIs in recent versions. The older unixes have recently added a bunch of Linux-like modern APIs to make portability easier. This was the reason behind HPUX 11i (the 'i' denotes "internet ready", but what they really mean is glibc/*BSD apis). This is also the reason behind the AIX 5L name (AKA 5.1, 5.2) (L = linux affinity, same deal, new GNU/*BSD apis). You know that MacOSX uses a BSD-based userland, so you're fine there. Then there's Solaris, of which recent versions (>=2.6) are in good shape. Recent versions of the proprietary unixes even have
Ok, once you figure out what platforms you are targeting, you need to figure out what compilers you will support. All of the proprietary Unixes have their own C compiler (sometimes only available for a fee). Many are not fully ANSI compliant. They are definitely not all C99 compliant. That is the bad news.
The good news is that gcc is available for all of the major platforms. This is what gcc excels at, it is highly portable. You can use this to your advantage to get things working on these platforms. If your users then want to get them working with other compilers, that is worth a shot too (non-gcc compilers often produce better optimizations, etc.).. but it will be hit or miss.
Testing. I highly recommend the HP Testdrive program. They make available a bunch of machines with various HP hardware running various operating systems from Linux on Alpha to HPUX on IA64, including Tru64 (aka OSF/1). http://www.testdrive.compaq.com/
Sourceforge also has a build farm which includes Solaris on sparc and x86 and MacOS X. http://sourceforge.net/docman/display_doc.php?doc
Good luck. Hope this helps.
-molo
HPUX Note: Many people think that 11i is for the Itanium platform. That is not the case. 11i is version 11.11 and higher. 11.11 is for HPPA. 11.20 and higher are for IA64. Both are called 11i.
Using your sig line to advertise for friends is lame.
AFAIK really all UNIX and UNIX-like systems support at least POSIX-1988, and most even support SUS1 and higher. Heck, even Windows NT/2000 are (partly) POSIX compatible, and to my knowledge Windows XP can be made POSIX compatible with some extra package from MicroSoft, but I don't know which).
I really recommend Advanced UNIX Programming, it's an excellent book which not only discusses and explains POSIX and SUS APIs but also where you can expect those APIs to be avaible and how to test for them to be sure. It was also reviewed here at Slashdot.
POSIX is not a single specification, but consists of quite a number of parts. While some of the basic interfaces can be considered of widespread use, I wouldn't recommend using others like realtime handling or maybe even threads.
- Hubert
Are you also including embedded systems like:
vxWorks, QNX, pSOS, OSE, etc..
In case anyone's interested, this is a HP-UX 11 (the machine is a 9000/800) system, and we can only use it, not administer it, and they pretty much refuse to upgrade anything other than Oracle on it, so we're still stuck with the damned compiler.
That said, there is a solution: GNU GCC comes with an ANSI to K&R tool. I've not tried it, but it's probably worth playing with. If your ANSI 89 C code can also stay compatable with the translator, then your plans for total compatability should hold up.
And, of course, some people would argue that K&R was never standard anyway. They're kind of correct, there was a general consensus to how it should work (some of which contradicted the book itself) and most of the incompatabilities were actually extensions, but there will be areas of incompatability whatever you do.
You are not alone. This is not normal. None of this is normal.
You can always try to install gcc in some temp dir. That's what I do on such castrated platforms. It goes a long way to restore sanity.
Plan 9 is/was the successor to Unix from the people who brought you Unix to begin with.
It's compiler suites, which approach multiple architectures a little differently, by default don't have hardly and ANSI C or POSIX support. If you need that stuff you have to use the APE frameworks. See this for more information.
The fact that it's not quite ANSI C and not quite POSIX by default shouldn't discourage you from playing with the OS though or even trying to use it. Apparently the "thin client" trend is coming back and Plan 9 systems support that metaphor quite nicely where everyone has a graphical display and a private hierarchical namespace [each process can have a different namespace in fact]. The OS is meant to be distributed across many nodes, with CPU nodes and File Serving nodes being part of a grid, but you can run it standalone fairly easily as well.
I've found that even though it doesn't have a great X implementation I can still VNC to other machines that do when I need X and that I can use ssh with their terminal emulator when I need to work with systems Plan 9 can't "mount" or "bind" into my namespace.
As you can probably tell. I was impressed.
If you don't want to mess with installing over you existing OS you can try Inferno which installs on Windows, Linux, FreeBSD and even MacOS X [but if you run Panther you will probably need this patched emulator and installer to make it work]. Once done you can build a multi-CPU-architecture grid all your own and learn the "Limbo" programming language and start harnessing those extra CPU cyucles. Inferno also supports thos hierarchical namespaces of Plan 9.
Where can I find these?
AIX
IRIX
FreeBSD 5.x
Solaris 10
any 4.2 or 4.3 BSD
any SVR4-MP
any "Trusted" system
OS/390
I need these for an Open Source project I maintain.
QNX is still being used - the latest version now hs gcc support - versus that Watcom compiler for earlier versions (4.25 and earlier).
A Shadeless room is a brighter room.
We go through great lengths in Samba to be as portable as possible. Our build farm runs the most popular unices on all sorts of architectures (you'd be amazed how different Linux on x86 can be than Linux on say a s390). We support a ton of platforms including some as obscure as the Amiga.
What I'd do if I were you is to just grep the Samba source code before you use a function. You'll likely find a list of platforms that it doesn't work on, or that simply doesn't have that particular function. You may also find workarounds for bugs in particular implementations.
int func(int a);
func((b += 3, b));
at the tire shop, i saw that your engine was running on gasoline. how barbaric, i thought, so i upgraded it to hydrogen.
...unless you really want/need to support ancient and obscure platforms. But since the question specifically *said* modern and maintained platforms, then autoconf will just uglify and complicate your code.
And in answer to the original question: yes, if you're talking modern unix or unix-like systems (i.e. AIX 4.3 or 5, Solaris 7 or later, Linux/glibc or BSD from the last several years, HPUX 11), then yes, you can assume POSIX and C89 (although for AIX, Solaris, and HPUX you'll need to buy a compiler or install GCC).
Get an old black NeXTstation or NeXT cube from eBay if you want a 4.2 BSD based machine. IIRC, the original OS, NeXTstep, was based on 4.2 BSD, while the later OS, OpenStep, was based on 4.3 BSD.
If yuo need a Silicon Graphics box to develop software on, check out http://forums.nekochan.net. Someone there can probably give you an account on a SGI IRIX 6.5.x system with gcc and/or MIPSpro. You could also buy an O2 from eBay for about $50. You'll still need to find a more recent version of IRIX, but SGI will give you all of the development tools for free if you join their "plus" developer program as a "hobbyist". SGI also gives away free accounts on their big iron Origin (IRIX) and Altix (Linux) systems, but you probably have to be a full-time serious developer for that.
Just do it.
For both TenDRA and DragonFly we're using ANSI C94 (C90 plus amendments) along with POSIX/SUS and the code in general tends to get cleaner and cleaner (and easier to understand in my opinion).
It is amazing, since I am doing a lot of these conversions on a plethora of different old time tools, how much programming errors/mistakes the old code managed to get away with...
Jeroen Ruigrok/Asmodai
Hi there,
You're one of the few still having a job! You've got a project at hand, and you NEED to do it well.
DO NOT modernize if you don't have to! What you have in your hands is, as you tell, a nice *working* code. IF after your "modernization" crusade, it breaks on some platforms, even due to platform bugs, it will be YOUR neck under the guillotine. Understand THAT!
And, no, I'm not talking this from my behind... been there, done that, got burned!!! Unnecessary modernization/elegance/optimizations/refactoring is root of all evil and prime cause of job loss! Do your job, and fix whatever is *NEEDED*... and make sure you ain't breaking anything. If you can do THAT much flawlessly, you should be thankful. In software engineering there are just too many variables and you carry the onus of working around them. All compiler/platform/libc bugs will form part of YOUR work... so be careful!
- mritunjai
One might check out FreeBSD 4.x, it defined some workaround systems for prototypes to be both Ansi and K&R usable.