Copyright (c) Hyperion Entertainment and contributors.

Difference between revisions of "Newlib Library"

From AmigaOS Documentation Wiki
Jump to navigation Jump to search
m (Small correction in the last Shared Interface Pointer sentence.)
 
(3 intermediate revisions by one other user not shown)
Line 3: Line 3:
 
== Shared Interface Pointer ==
 
== Shared Interface Pointer ==
   
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 you child process is to share the parent process' newlib context information (e.g. stdin, stdout and stderr).
+
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 Shell console. Your program always starts using the standard '''argc''' and '''argv''' parameters:
+
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 ===

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.

Shared Interface Pointer

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.