Copyright (c) Hyperion Entertainment and contributors.
Difference between revisions of "Newlib Library"
Steven Solie (talk | contribs) |
m (Small correction in the last Shared Interface Pointer sentence.) |
||
(7 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
== Shared Interface Pointer == |
== Shared Interface Pointer == |
||
− | Newlib is a rather unique in that |
+ | Newlib is a rather unique in that it uses a shared interface pointer name INewlib (struct Interface* type). This is only a concern when you are not using the standard C startup code and opening newlib.library directly. One consequence of using a shared interface pointer is that you must specify the NP_Child tag when using IDOS->CreateNewProc() if your child process is going to share the parent process' newlib context information (e.g. stdin, stdout and stderr). |
== Startup Code == |
== Startup Code == |
||
− | The standard C startup code provides information on whether your application was launched from Workbench or |
+ | The standard C startup code provides information on whether your application was launched from Workbench, Shell console or as a file system. Your program always starts using the standard '''argc''' and '''argv''' parameters but they are interpreted differently depending on how it was started. |
<syntaxhighlight> |
<syntaxhighlight> |
||
Line 13: | Line 13: | ||
</syntaxhighlight> |
</syntaxhighlight> |
||
+ | === Workbench === |
||
− | If '''argc''' is equal to zero that means the application was started from the Workbench. In this case, the '''argv''' parameter is a pointer to a struct WBStartup. |
||
+ | The '''argc''' argument is equal to zero. The '''argv''' argument is a pointer to a struct WBStartup. |
||
− | If '''argc''' is non-zero then it means the application was started from the Shell console and the normal C startup rules apply. |
||
+ | |||
+ | <syntaxhighlight> |
||
+ | #include <workbench/startup.h> |
||
+ | |||
+ | int main(int argc, char **argv) |
||
+ | { |
||
+ | struct WBStartup *wbstartup; |
||
+ | |||
+ | if (argc == 0) |
||
+ | { |
||
+ | wbstartup = (struct WBStartup*)argv; |
||
+ | // Parse wbstartup and enter main processing loop. |
||
+ | ... |
||
+ | } |
||
+ | |||
+ | return 0; |
||
+ | } |
||
+ | </syntaxhighlight> |
||
+ | |||
+ | === Shell === |
||
+ | |||
+ | If '''argc''' is greater than zero then it means the application was started from the Shell console and the normal C startup rules apply. |
||
+ | |||
+ | <syntaxhighlight> |
||
+ | int main(int argc, char **argv) |
||
+ | { |
||
+ | if (argc > 0) |
||
+ | { |
||
+ | // Parse argv and enter main processing loop. |
||
+ | ... |
||
+ | } |
||
+ | |||
+ | return 0; |
||
+ | } |
||
+ | </syntaxhighlight> |
||
+ | |||
+ | === File System === |
||
+ | |||
+ | If '''argc''' is -1 then means the application was started as a file system. This special option should only be used by file systems. |
||
+ | |||
+ | <syntaxhighlight> |
||
+ | #include <dos/dosextens.h> |
||
+ | |||
+ | int main(int argc, char **argv) |
||
+ | { |
||
+ | int result; |
||
+ | |||
+ | if (argc == -1) |
||
+ | { |
||
+ | struct DosPacket *pkt = (struct DosPacket*)argv; |
||
+ | struct Message *msg = pkt->dp_Link; |
||
+ | |||
+ | // File system initialization. |
||
+ | BOOL initialized = file_system_init(msg); |
||
+ | |||
+ | if (initialized) |
||
+ | { |
||
+ | // Reply to the startup packet before entering main loop. |
||
+ | pkt->dp_Res1 = DOSTRUE; |
||
+ | pkt->dp_Res2 = 0; |
||
+ | IExec->PutMsg(pkt->dp_Port, msg); |
||
+ | |||
+ | // File system main loop. |
||
+ | ... |
||
+ | |||
+ | result = RETURN_OK; |
||
+ | } |
||
+ | else |
||
+ | { |
||
+ | // File system failed to initialize so return a DOS error code. |
||
+ | pkt->dp_Res1 = DOSFALSE; |
||
+ | pkt->dp_Res2 = ERROR_NO_FREE_STORE; |
||
+ | IExec->PutMsg(pkt->dp_Port, msg); |
||
+ | |||
+ | result = RETURN_FAIL; |
||
+ | } |
||
+ | } |
||
+ | |||
+ | return result; |
||
+ | } |
||
+ | </syntaxhighlight> |
||
=== Standard Interfaces === |
=== Standard Interfaces === |
||
Line 24: | Line 105: | ||
* IUtility |
* IUtility |
||
− | === |
+ | === Options === |
<syntaxhighlight> |
<syntaxhighlight> |
||
Line 30: | Line 111: | ||
</syntaxhighlight> |
</syntaxhighlight> |
||
− | Define '''__stdiowin''' to control the default standard I/O window which will open automatically if your program needs it. The default is "CON:64/48/800/200/[CLI command name|Task name]". |
+ | Define '''__stdiowin''' to control the default standard I/O window which will open automatically if your program needs it. The default is "CON:64/48/800/200/[CLI command name|Task name]/AUTO/CLOSE/WAIT". |
<syntaxhighlight> |
<syntaxhighlight> |
||
Line 36: | Line 117: | ||
</syntaxhighlight> |
</syntaxhighlight> |
||
Define to 1 to enable POSIX style path semantics which is useful when porting applications from UNIX. |
Define to 1 to enable POSIX style path semantics which is useful when porting applications from UNIX. |
||
+ | |||
+ | == DOS File Handles == |
||
+ | |||
+ | Sometimes the underlying DOS file handle may be required in some special circumstances. The '''_get_osfhandle()''' function is provided in the '''fcntl.h''' header file to access DOS file handles. |
||
+ | |||
+ | The following is an example program which demonstrates the feature. |
||
+ | <syntaxhighlight> |
||
+ | #include <proto/dos.h> |
||
+ | #include <stdio.h> |
||
+ | #include <fcntl.h> |
||
+ | |||
+ | int main() |
||
+ | { |
||
+ | printf("0x%08x 0x%08x 0x%08x\n", |
||
+ | (unsigned int)IDOS->Input(), |
||
+ | (unsigned int)IDOS->Output(), |
||
+ | (unsigned int)IDOS->ErrorOutput()); |
||
+ | |||
+ | printf("0x%08x 0x%08x 0x%08x\n", |
||
+ | _get_osfhandle( fileno(stdin) ), |
||
+ | _get_osfhandle( fileno(stdout) ), |
||
+ | _get_osfhandle( fileno(stderr) )); |
||
+ | |||
+ | return 0; |
||
+ | } |
||
+ | </syntaxhighlight> |
||
+ | |||
+ | Note that this feature is available in newlib.library 53.20 and higher. |
Latest revision as of 14:34, 5 July 2020
The built-in AmigaOS C library is a variant of the Newlib C standard library implementation. This section describes features of Newlib which are unique to AmigaOS.
Contents
Newlib is a rather unique in that it uses a shared interface pointer name INewlib (struct Interface* type). This is only a concern when you are not using the standard C startup code and opening newlib.library directly. One consequence of using a shared interface pointer is that you must specify the NP_Child tag when using IDOS->CreateNewProc() if your child process is going to share the parent process' newlib context information (e.g. stdin, stdout and stderr).
Startup Code
The standard C startup code provides information on whether your application was launched from Workbench, Shell console or as a file system. Your program always starts using the standard argc and argv parameters but they are interpreted differently depending on how it was started.
int main(int argc, char **argv)
Workbench
The argc argument is equal to zero. The argv argument is a pointer to a struct WBStartup.
#include <workbench/startup.h> int main(int argc, char **argv) { struct WBStartup *wbstartup; if (argc == 0) { wbstartup = (struct WBStartup*)argv; // Parse wbstartup and enter main processing loop. ... } return 0; }
Shell
If argc is greater than zero then it means the application was started from the Shell console and the normal C startup rules apply.
int main(int argc, char **argv) { if (argc > 0) { // Parse argv and enter main processing loop. ... } return 0; }
File System
If argc is -1 then means the application was started as a file system. This special option should only be used by file systems.
#include <dos/dosextens.h> int main(int argc, char **argv) { int result; if (argc == -1) { struct DosPacket *pkt = (struct DosPacket*)argv; struct Message *msg = pkt->dp_Link; // File system initialization. BOOL initialized = file_system_init(msg); if (initialized) { // Reply to the startup packet before entering main loop. pkt->dp_Res1 = DOSTRUE; pkt->dp_Res2 = 0; IExec->PutMsg(pkt->dp_Port, msg); // File system main loop. ... result = RETURN_OK; } else { // File system failed to initialize so return a DOS error code. pkt->dp_Res1 = DOSFALSE; pkt->dp_Res2 = ERROR_NO_FREE_STORE; IExec->PutMsg(pkt->dp_Port, msg); result = RETURN_FAIL; } } return result; }
Standard Interfaces
The following interfaces are handled by the C startup code and are guaranteed to be present when main() is called:
- IExec
- IDOS
- IUtility
Options
extern const char *__stdiowin;
Define __stdiowin to control the default standard I/O window which will open automatically if your program needs it. The default is "CON:64/48/800/200/[CLI command name|Task name]/AUTO/CLOSE/WAIT".
extern int __unix_path_semantics;
Define to 1 to enable POSIX style path semantics which is useful when porting applications from UNIX.
DOS File Handles
Sometimes the underlying DOS file handle may be required in some special circumstances. The _get_osfhandle() function is provided in the fcntl.h header file to access DOS file handles.
The following is an example program which demonstrates the feature.
#include <proto/dos.h> #include <stdio.h> #include <fcntl.h> int main() { printf("0x%08x 0x%08x 0x%08x\n", (unsigned int)IDOS->Input(), (unsigned int)IDOS->Output(), (unsigned int)IDOS->ErrorOutput()); printf("0x%08x 0x%08x 0x%08x\n", _get_osfhandle( fileno(stdin) ), _get_osfhandle( fileno(stdout) ), _get_osfhandle( fileno(stderr) )); return 0; }
Note that this feature is available in newlib.library 53.20 and higher.