Nonportable problems are not limited to the start of execution. There is also the question of OS services which are not represented in Glk. The ANSI C libraries are so familiar that they seem universal, but they are actually not necessarily present. Palmtop platforms such as PalmOS are particularly good at leaving out ANSI libraries.
Everyone uses malloc()
, realloc()
, and free()
. However, some platforms have a native memory-management API which may be more suitable in porting your program.
The malloc()
system is simple; it can probably be implemented as a layer on top of whatever native API is available. So you don't absolutely have to worry about this. However, it can't hurt to group all your malloc()
and free()
calls in one part of your program, so that a porter can easily change them all if it turns out to be a good idea.
This is more of a nuisance, because the set of string functions varies quite a bit between platforms. Consider bcopy()
, memcpy()
, and memmove()
; stricmp()
and strcasecmp()
; strchr()
and index()
; and so on. And again, on a palmtop machine, none of these may be available. The maximally safe course is to implement what you need yourself.
See the model.c
program for an example; it implements its own str_eq()
and str_len()
.
The maximally safe course is also a pain in the butt, and may well be inefficient (a platform may have a memcpy()
which is highly optimized for large moves.) That's porting in the big city.
By the way, the next person I see who #define
s memmove()
as memcpy()
when a real memmove()
isn't available, gets slapped in the face with a lead-lined rubber salmon.
This is the real nuisance, because Glk provides a limited set of stream and file functions. And yet there are all these beautiful ANSI stdio calls, which have all these clever tricks — ungetc()
, fast macro fgetc()
, formatted fprintf()
, not to mention the joys of direct pathname manipulation. Why bother with the Glk calls?
The problem is, the stdio library really isn't always the best choice, particularly on mobile OSes.
There's also the problem of hooking into the Glk API. Window output goes through Glk streams.
It would have been lovely to use the stdio API for that, but it's not generally possible.
As usual, it's a judgement call. If you have a large existing pile of source code which you're porting, and it uses a lot of icky stdio features like ungetc()
, it may be better not to bother changing everything to the Glk file API. If you're starting from scratch, using the Glk calls will probably be cleaner.
Sometimes — hopefully rarely — there's stuff you just gotta do.
Explicit pathname modification is one possible case. Creating or deleting directories. New Glk event types caused by interface events. Control over pull-down menus.
Like startup code, you just have to decide what you want, and ask your porters to port it. These are the non-portable parts of your task. As I said, that's porting in the big city.
If an extension or new function is so useful that everyone is implementing it, I'll consider adding it to the Glk API (as an optional capability, with a Gestalt selector and everything.) I'm flexible. In a morally correct manner, of course.