libi86 icon indicating copy to clipboard operation
libi86 copied to clipboard

Attempt to reimplement non-standard C library facilities (e.g. <conio.h>) used in MS-DOS programs, for IA-16 GCC & ACK ― mirror of https://gitlab.com/tkchia/libi86 • Ubuntu packages for cross-compilat...

= libi86

// Macros to work around AsciiDoc lossage. :-| :plus: + :lowline: _ :or: | :nbsp:   :bcmt: /{nbsp} :ecmt: {nbsp}/

https://gitlab.com/tkchia/libi86/-/commits/master[image:https://gitlab.com/tkchia/libi86/badges/master/pipeline.svg["GitLab pipeline status"]] · https://github.com/tkchia/libi86/actions/workflows/ci-build.yml[image:https://github.com/tkchia/libi86/actions/workflows/ci-build.yml/badge.svg["GitHub pipeline status"]]

This is a code library which attempts to reimplement non-standard C library facilities (e.g. <conio.h>) commonly used in classical MS-DOS programs. The library also implements a few standard facilities which are part of newer C language standards, where the underlying C library lacks them.

:fn-tkchia-22: footnote:tkchia-22[https://github.com/tkchia/build-ia16/.] :fn-given-21: footnote:given-21[https://github.com/davidgiven/ack.]

For now, the library is meant to be used with the following compilers and targets:

  • either a GCC toolchain for 16-bit x86;{fn-tkchia-22}
  • or the Amsterdam Compiler Kit{fn-given-21} with the msdos86 target platform.

It may be ported to other compilers and targets in the future.

:fn-ow: footnote:ow[https://github.com/open-watcom/open-watcom-v2/.] :fn-ow-22: footnote:ow-2022[Open Watcom Contributors, et al. Open Watcom C Library Reference, 2022. https://github.com/open-watcom/open-watcom-v2-wikidocs/blob/master/docs/clib.pdf. Retrieved on 6 Jan 2022.]

The current aim is to be compatible enough with the Open Watcom{fn-ow} runtime — as described in the Open Watcom C Library Reference{fn-ow-22} — to be useful for building existing MS-DOS code.

:fn-borland: footnote:borland[http://cc.embarcadero.com/Item/25636.] :fn-borland-91: footnote:borland-91[Borland International. Borland C{plus}{plus} 2.0 Library Reference, 1991. https://archive.org/details/bitsavers_borlandborn2.0LibraryReference1991_17218611.] :fn-borland-92: footnote:borland-92[Borland International. Borland C{plus}{plus} 3.1 Library Reference, 1991--1992. https://archive.org/details/bitsavers_borlandborn3.1LibraryReference1992_19008612.]

Defining the macro _BORLANDC_SOURCE will also enable some degree of compatibility with the Borland Turbo C{plus}{plus}{fn-borland} compiler's C library, which is described in the Borland C{plus}{plus} 2.0 Library Reference{fn-borland-91} and the Borland C{plus}{plus} 3.1 Library Reference.{fn-borland-92}

== Synopsis

=== Use

When using IA-16 GCC:

  • ia16-elf-gcc [...gcc-options...] -li86 [...]
  • On a MS-DOS host: i16gcc [...gcc-options...] -li86 [...]

When using ACK:

  • ack-cc -mmsdos86 -.c [...ack-options...] -li86.a [...]
  • Or (if compiler is installed as ack): ack -mmsdos86 -.c [...ack-options...] -li86.a [...]

=== Installing from pre-compiled Ubuntu Linux packages, for cross development

When using IA-16 GCC:

:fn-tkchia-22b: footnote:tkchia-22b[https://launchpad.net/~tkchia/+archive/ubuntu/build-ia16/.]

  • Grab the gcc-ia16-elf and libi86-ia16-elf packages from https://launchpad.net/~tkchia/+archive/ubuntu/build-ia16/[my build-ia16 PPA].{fn-tkchia-22b}
  • You can now (June 2022) also install and run libi86 's self-test suite. link:doc/ppa-test.md[Instructions] for doing so are available.

When using ACK:

:fn-tkchia-22c: footnote:tkchia-22c[https://launchpad.net/~tkchia/+archive/ubuntu/de-rebus/.]

  • Grab the ack-compiler and libi86-ack packages from https://launchpad.net/~tkchia/+archive/ubuntu/de-rebus/[my de-rebus PPA].{fn-tkchia-22c}

=== Building from sources, installing, and testing, on Linux

:fn-tkchia-22d: footnote:tkchia-22d[https://gitlab.com/tkchia/libi86.] :fn-tkchia-22e: footnote:tkchia-22e[https://codeberg.org/tkchia/libi86.] :fn-tkchia-22f: footnote:tkchia-22f[https://github.com/tkchia/libi86.]

  • link:doc/linux-build.md[Detailed instructions] for building the code are available.
  • You can download the libi86 source code from https://gitlab.com/tkchia/libi86[GitLab],{fn-tkchia-22d} https://codeberg.org/tkchia/libi86[Codeberg],{fn-tkchia-22e} or https://github.com/tkchia/libi86[GitHub].{fn-tkchia-22f}

== License

libi86 as a whole is now distributed under the link:LICENSE[3-clause BSD License].

(A few files are distributed under other licenses, but in ways that are ultimately compatible with the BSD License.)

== Implemented facilities

=== Legend

:fn-iso-iec-99: footnote:iso-iec-99[International Organization for Standardization, and International Electrotechnical Commission. ISO/IEC 9899:1999: Programming Languages: C, 1999.] :fn-iso-iec-07: footnote:iso-iec-07[International Organization for Standardization, and International Electrotechnical Commission. ISO/IEC 9899:TC3: Committee Draft — September 7, 2007. WG14/N1256, 2007. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf.] :fn-ieee-04: footnote:ieee-04[Institute of Electrical and Electronics Engineers, and The Open Group. IEEE Std 1003.1, 2004 Edition, 2004. https://pubs.opengroup.org/onlinepubs/009695399/.]

[cols=">1,9"] |=== | Compat. | Meaning

| C99 | Part of the C99 standard{fn-iso-iec-99}{fn-iso-iec-07} — enable with a macro _ISOC99_SOURCE if necessary. | P01 | Part of the POSIX.1-2001{fn-ieee-04} standard. | W | Behaves like the corresponding function in Open Watcom. | W+ | Behaves like the corresponding function in Open Watcom, but with some extended behaviours. | B | From Borland Turbo C{plus}{plus} — enable with _BORLANDC_SOURCE. | UB | Undocumented (?) functionality from Borland Turbo C{plus}{plus} — enable with _BORLANDC_SOURCE. | W/B | By default, behaves as in Open Watcom; if _BORLANDC_SOURCE is defined, behaves as in Borland C{plus}{plus}. | IW | From internal interfaces in Open Watcom's library code. | X | libi86-specific extension; not in Open Watcom or Borland C{plus}{plus}. Enabled even if the macros _BORLANDC_SOURCE and _ISOC99_SOURCE are not defined. | XB | libi86-specific extension. Behaves slightly differently if _BORLANDC_SOURCE is defined. |===

[cols=">1,9"] |=== | Avail. | Meaning

| = | Available for all compilers and platforms that libi86 targets. | (=) | Available for all compilers and platforms that do not already define this facility themselves. | := | Available for all compilers and platforms that libi86 targets. If the C library already defines the corresponding standard library function — usually without a leading underscore — then this function is defined as an alias of the standard function; otherwise, libi86 provides its own definition. For example, _getpid () is an alias of getpid () if the C library already defines the latter. | G | Available (only) under IA-16 GCC. | (G) | Available (only) under IA-16 GCC, and only where the C library does not already define this facility. | (❧) | Additional notes on the implementation. |===

=== Functions

:im-dir-h: link:doc/implem-notes.asciidoc#user-content-dir-h[(❧)] :im-direct-h: link:doc/implem-notes.asciidoc#user-content-direct-h[(❧)] :im-dos-h: link:doc/implem-notes.asciidoc#user-content-dos-h[(❧)] :im-process-h: link:doc/implem-notes.asciidoc#user-content-process-h[(❧)] :im-stdlib-h: link:doc/implem-notes.asciidoc#user-content-libi86stdlib-h[(❧)]

[cols=">1,>1,4,4"] |=== | Compat. | Avail. | Function | Notes

2+| 2+| ▗▚▚▚▚ <bios.h> ▞▞▞▞▖ | W+ | = | _bios_disk (service, *diskinfo); | As an extension, also accepts service = _DISK_DRIVEPARAMS, which returns drive parameters in *diskinfo. | W | = | _bios_equiplist (); | | B | = | biosequip (); | | W | = | _bios_memsize (); | | B | = | biosmemory (); | | W | = | _bios_keybrd (service); | | B | = | bioskey (service); | | W | = | _bios_printer (service, port, data); | | W | = | _bios_serialcom (service, port, data); | | W | = | _bios_timeofday (service, *timeval); | | X | = | _bios_joystick (unsigned service, union _joyinfo_t *joyinfo); | Reads joystick status via int 0x15 function 0x84. 4+| 2+| 2+a| ▗▚▚▚▚ <conio.h> ▞▞▞▞▖

		* **If `_BORLANDC_SOURCE` is defined, ``<conio.h>`` switches to an alternate implementation of the console output routines which is based on ``<graph.h>`` facilities.**

| W/B | = | cgets (buf); | | W/B | = | cprintf (fmt, ...); | | W/B | = | cputs (buf); | | W/B | = | cscanf (fmt, ...); | | W | = | getch (); | | W | = | _getch (); | | W/B | = | getche (); | | W | = | _getche (); | | W | = | kbhit (); | | W | = | _kbhit (); | | W | = | ungetch (ch); | | W | = | _ungetch (ch); | | W/B | = | putch (ch); | | W/B | = | vcprintf (fmt, ap); | | W/B | = | vcscanf (fmt, ap); | 4+| | B | = | clreol (); | | B | = | clrscr (); | | B | = | delline (); | | B | = | getpass (prompt); | | B | = | gettextinfo (text-info); | If the active video mode is a SuperVGA mode, text-info\->currmode may be invalid. | B | = | gotoxy (x, y); | | B | = | highvideo (); | | B | = | insline (); | | B | = | lowvideo (); | | B | = | normvideo (); | | B | = | textattr (new-attr); | | B | = | textbackground (new-color); | | B | = | textcolor (new-color); | | B | = | textmode (mode); | Does not support mode = LASTMODE yet. | B | = | wherex (); | | B | = | wherey (); | | B | = | window (left, top, right, bottom); | 4+| | W | = | inp (port); | | W | = | _inp (port); | | B | = | inportb (port); | | W | = | inpw (port); | | W | = | _inpw (port); | | B | = | inport (port); | Returns a signed value. | B | = | inportw (port); | Returns an unsigned value. | W | = | outp (port, value); | | W | = | _outp (port, value); | | B | = | outportb (port, value); | | W | = | outpw (port, value); | | W | = | _outpw (port, value); | | B | = | outport (port, value); | Accepts a signed value to write. | B | = | outportw (port, value); | Accepts an unsigned value to write. 4+| 2+| 2+| ▗▚▚▚▚ <dir.h> ▞▞▞▞▖ | B | = {im-dir-h} | searchpath (file); | | X | = {im-dir-h} | _searchpath (file); | 4+| 2+| 2+| ▗▚▚▚▚ <direct.h> ▞▞▞▞▖ | P01, W | (=) | chdir (path); | (POSIX places this function in <unistd.h>.) | W | := | _chdir (path); | | P01, W | (=) | getcwd (buffer, size); | (POSIX places this function in <unistd.h>.) | W | := | _getcwd (buffer, size); | | W | = | _getdcwd (drive, buffer, size); | | W | = | _getdrive (); | | P01 | (=) {im-direct-h} | mkdir (path, mode); .4+a| * In Watcom, both mkdir and _mkdir take only a single path argument. * POSIX however says that mkdir (placed in <sys/stat.h>) takes two arguments; the second argument gives Unix-style permission bits. * For compatibility with both, libi86 under gcc-ia16 allows both mkdir and _mkdir to be called with either one or two arguments. * Under ACK, however, _mkdir will always only take one argument, and mkdir will take two (unless ACK's C library says otherwise). | X | G {im-direct-h} | _mkdir (path, mode); | W | (G) | mkdir (path); | W | = | _mkdir (path); | P01, W | (=) | rmdir (path); | (POSIX places this function in <unistd.h>.) | W | := | _rmdir (*path); | 4+| 2+| 2+a| ▗▚▚▚▚ <dos.h> ▞▞▞▞▖

		* **``<dos.h>`` also includes ``<i86.h>``, described below.**
		* **If `_BORLANDC_SOURCE` is defined, the ``union REGS`` type gets an additional ``.x.flags`` field, and ``<dos.h>`` switches accordingly to a different version of the ``intdos`` and ``intdosx`` routines.**

| W | = {im-dos-h} | bdos (dos-func, dx, al); | | B | = | bdosptr (dos-func, dx, al); | | W/B | = | intdos (in-regs, out-regs); | | W/B | = | intdosx (in-regs, out-regs, seg-regs); | 4+| | W+ | = | _dos_allocmem (size, segment); | Also works under DPMI; yields a starting protected-mode selector. | W | = | _dos_close (handle); | | W | = | _dos_commit (handle); | | W | = | _dos_creat (path, attr, handle); | | W | = | _dos_creatnew (path, attr, handle); | | W | = | _dos_findfirst (path, attributes, buffer); | | W | = | _dos_findnext (buffer); | | W | = | _dos_findclose (buffer); | | W+ | = | _dos_freemem (segment); | Also works under DPMI; accepts a starting protected-mode selector. | W | = | _dos_getdate (date); | | W | = | _dos_getdiskfree (drive, disk-space); | | W | = | _dos_getdrive (drive); | | W | = | _dos_getfileattr (*path, *attributes); | | W | = | _dos_getftime (handle, *date, time); | | W | = | _dos_gettime (time); | | W | = | _dos_getvect (intr-no); | Some versions of gcc-ia16 and ACK may not understand the interrupt function attribute. In that case, this function will return a far data pointer. | W | = | _dos_keep (status, keep-paras); | | B | = | keep (status, keep-paras); | | W | = | _dos_open (path, mode, *handle); | | W | = | _dos_read (handle, *buf, count, bytes); a| * _dos_read always directly invokes the relevant syscall (int 0x21 function 0x3f), without transforming the input bytes. * Under ACK — but not gcc-ia16 — the C library's read function may behave differently from _dos_read: it may translate CRLFs to LFs, and handle end-of-file indicators (ASCII 26), if handle is open 'd in "text mode". | W | = | _dos_setblock (size, seg, max-size); | | W | = | _dos_setdate (date); | | W | = | _dos_setdrive (drive, total); | | W | = | _dos_setfileattr (path, attributes); | | W | = | _dos_setftime (handle, date, time); | | W | = | _dos_settime (time); | | W | = | _dos_setvect (intr-no, *handler); | Some versions of gcc-ia16 and ACK may not understand the interrupt function attribute. In that case, this function will not be supported. | X | = | _dos_spawn (unsigned char subfunc, const char *path, union _dosspawn_t *params); | int 0x21 function 0x4b (for subfunc ≠ 4) or 0x80 (for subfunc = 4). Returns an error code on error, 0 on success. | X | = | _dos_wait (unsigned *error-level); | int 0x21 function 0x4d. | W | = | _dos_write (handle, *buf, count, bytes); a| * _dos_write always directly invokes the relevant syscall (int 0x21 function 0x40), without transforming the output bytes. * Under ACK — but not gcc-ia16 — the C library's write function may behave differently from _dos_write: it may translate LFs to CRLFs if handle is open 'd in "text mode". | W | = | dosexterr (err-info); | | B | = | _getdrive (); | | UB | = | getswitchar (); .2+| Returns the (nominal) character for command line switches — usually '/' — per int 0x21, %ax = 0x3700. | X | = | _getswitchar (); | B | = | *getvect (intr-no); | Some versions of gcc-ia16 and ACK may not understand the interrupt function attribute. In that case, this function will return a far data pointer. | X | = | _getsysvars (); | int 0x21 function 0x52. | X | = | _makefcb (cmd-line, *fcb, opt); a| * Parses cmd-line[] into a DOS 1.x-style File Control Block (FCB) — via int 0x21, %ah = 0x29. * Returns a struct _makefcb_t structure (result): ** result._status is either 0 (parse successful, no wildcards), 1 (parse successful, found wildcards), or -1 (invalid drive); ** result._tail points to the first unparsed character, or may be NULL if a system error occurred. * cmd-line[] should end with either a null character, a carriage return ('\r'), or a new line ('\n'). * In non-Borland mode, fcb should point to a struct _fcb (with underscore), rather than a struct fcb. * This function provides more detailed information on the parse than the more "standardized" parsfnm function below. | X | = | _parsfnm (cmd-line, *fcb, opt); .2+a| * Parses cmd-line[] into a DOS 1.x-style File Control Block (FCB) — via int 0x21, %ah = 0x29. * cmd-line[] should end with either a null character, a carriage return ('\r'), or a new line ('\n'). * In non-Borland mode, fcb should point to a struct _fcb (with underscore), rather than a struct fcb. | B | = | parsfnm (cmd-line, *fcb, opt); | UB | = | setswitchar (ch); .2+| Sets the (nominal) character for command line switches, with int 0x21, %ax = 0x3701. | X | = | _setswitchar (ch); | B | = | setvect (intr-no, *handler); | Some versions of gcc-ia16 and ACK may not understand the interrupt function attribute. In that case, this function will not be supported. 4+| | B | = | peek (segment, offset); | | B | = | peekb (segment, offset); | | B | = | poke (segment, offset, word-value); | | B | = | pokeb (segment, offset, byte-value); | | B | = | inportb (port); | | B | = | inport (port); | Returns a signed value. | B | = | inportw (port); | Returns an unsigned value. | B | = | outportb (port, value); | | B | = | outport (port, value); | Accepts a signed value to write. | B | = | outportw (port, value); | Accepts an unsigned value to write. 4+| | UB | = | inp (port); .4+| In non-Borland mode, these functions are declared only in <conio.h>. | UB | = | inpw (port); | UB | = | outp (port, value); | UB | = | outpw (port, value);

4+| 2+| 2+a| ▗▚▚▚▚ <dpmi.h> ▞▞▞▞▖

		* **Except for ``__DPMI_hosted ()`` and ``_DPMIIdle ()``, functions in ``<dpmi.h>`` should only be called when the caller knows it is running in DPMI mode.**
		* **``<dpmi.h>`` is not supported for ACK.**

| IW | G | __DPMI_hosted (); | Returns 1 if running in protected mode under DPMI, -1 otherwise. If the underlying C library has an implementation of this function, libi86 will use that instead. | IW | G | _DPMIAllocateDOSMemoryBlock (paras); | int 0x31 function 0x0100. Returns a structure giving the real mode segment and protected mode selector for the DOS memory block. On failure, returns { 0, 0 }. | IW | G | _DPMIAllocateLDTDescriptors (count); | int 0x31 function 0x0000. Returns a starting protected-mode selector, case to an int32_t. On failure, returns a negative value. | IW | G | _DPMIFreeDOSMemoryBlock (sel); | int 0x31 function 0x0101. Returns 0 on success, -1 on error. | IW | G | _DPMIFreeLDTDescriptor (sel); | int 0x31 function 0x0001. Returns 0 on success, -1 on error. | X | G | _DPMIGetCapabilities (uint16_t *capabilities-1, uint16_t *reserved-2, uint16_t *reserved-3, dpmi_host_info {lowline}{lowline}far *host-info); | int 0x31 function 0x0401. Returns 0 on success, -1 on error. | IW | G | _DPMIGetDescriptor (sel, *desc); | int 0x31 function 0x000b. Returns 0 on success, -1 on error. | IW | G | _DPMIGetSegmentBaseAddress (sel); | int 0x31 function 0x0006. Returns sel's base address on success; return value is undefined on error. | IW | G | _DPMIGetVendorSpecificAPI (vendor); | int 0x2f function 0x168a. Returns a far null pointer on error. | X | G | _DPMIGetVirtualInterruptState (); | int 0x31 function 0x0902. Returns true if virtual interrupts enabled, false otherwise. | IW | G | _DPMIIdle (); | int 0x2f function 0x1680. This implementation also returns a byte value saying whether this function call is actually supported (0x00), or not (0x80). It is OK to ignore this value. | IW | G | _DPMISegmentToDescriptor (seg-para); | int 0x31 function 0x0002. On success, returns a protected-mode selector value for the real-mode segment seg-para_:0. On failure, returns a negative value. | IW | G | _DPMISetDescriptor (sel, *desc); | int 0x31 function 0x000c. Returns 0 on success, -1 on error. | IW | G | _DPMISimulateRealModeInterrupt (inter-no, reset, words-to-copy, *call-struct); | int 0x31 function 0x0300. Returns 0 on success, -1 on error. words-to-copy should probably be 0. 4+| 2+| 2+a| ▗▚▚▚▚ <graph.h> ▞▞▞▞▖

		* **Unlike in Open Watcom, where all functions in ``<graph.h>`` are far, in ``libi86`` the far-ness of functions follows the chosen memory model.  Thus, in a small-memory-model program, ``_setvideomode`` is a near function.  However, pointers to data are still far.**

| W | = | _clearscreen (area); | | W | = | _displaycursor (curs-mode); | | W | = | _gettextposition (); | | X | = | _getvideomode (); | | W | = | _outmem (text, length); | | W | = | _outtext (text); | | W | = | _scrolltextwindow (rows); | | W | = | _setbkcolor (color); | | W | = | _settextcolor (pix-val); | | W | = | _settextposition (row, col); | | W | = | _settextwindow (row1, col1, row2, col2); | | W | = | _setvideomode (mode); | In the case of SuperVGA screen modes, only works with VESA interface. 4+| 2+| 2+a| ▗▚▚▚▚ <i86.h> ▞▞▞▞▖

		* **If `_BORLANDC_SOURCE` is defined, the ``union REGS`` type gets an additional ``.x.flags`` field, and ``<i86.h>`` switches accordingly to a different version of the ``int86``, ``int86x``, ``_int86f``, and ``_int86xf`` routines.**

| W | = | delay (ms); | | W | = | nosound (); | | W | = | sound (freq); | | W | = | segread (*seg-regs); | | W | = | _disable (); | | W | = | _enable (); | 4+| | W/B | = | int86 (inter-no, *in-regs, *out-regs); | | W/B | = | int86x (inter-no, *in-regs, *out-regs, *seg-regs); | | W | = | intr (inter-no, *regs); | Clears SZAPC flags to 0 before issuing interrupt. (This follows a documentation change in Open Watcom versions after Oct 2018.) | XB | = | _int86f (inter-no, *in-regs, *out-regs); | Loads carry flag before issuing interrupt. | XB | = | _int86xf (inter-no, *in-regs, out-regs, seg-regs); | Loads carry flag before issuing interrupt. | W | = | intrf (inter-no, regs); | Loads SZAPC flags before issuing interrupt. | X | = | _intrf (inter-no, regs); | Loads SZAPC flags before issuing interrupt. 4+| | W | = | FP_OFF (ptr); | Macro. | W | = | _FP_OFF (ptr); | Macro. | W | = | FP_SEG (ptr); | Macro. | W | = | _FP_SEG (ptr); | Macro. | W | = | *MK_FP (seg, off); | Macro. | W | = | *_MK_FP (seg, off); | Macro. | X | = | *_CV_FP (const volatile void *ptr); | Convert a default-sized pointer to a far pointer. This is mainly useful for ACK, which lacks built-in far pointer support. | X | = | _FP_EQ (const volatile void {lowline}{lowline}far *ptr1, const volatile void {lowline}{lowline}far *ptr2); | Test whether two far pointers are exactly equal. This is mainly useful for ACK, which lacks built-in far pointer support. 4+| 2+| 2+| ▗▚▚▚▚ <process.h> ▞▞▞▞▖ | P01, W | (=) | getpid (); | (POSIX places this function in <unistd.h>.) | W | := | _getpid (); | | W+ | = {im-process-h} | _spawnl (mode, *path, *arg, ... {bcmt}NULL{ecmt}); .12+a| * For these functions, libi86 purposely deviates from Open Watcom's documented behaviour in a few ways. * libi86 currently only implements the P_WAIT spawning mode (and a special P_WAIT {or} _P_RESTRICT_EXT submode). * See the link:doc/implem-notes.asciidoc#user-content-process-h[implementation notes] for details. | W+ | = {im-process-h} | _spawnle (mode, *path, *arg, ... {bcmt}NULL, *envp{ecmt}); | W+ | = {im-process-h} | _spawnlp (mode, *path, *arg, ... {bcmt}NULL{ecmt}); | W+ | = {im-process-h} | _spawnlpe (mode, *path, *arg, ... {bcmt}NULL, *envp{ecmt}); | W+ | = {im-process-h} | spawnv (mode, *path, *argv); | W+ | = {im-process-h} | _spawnv (mode, *path, *argv); | W+ | = {im-process-h} | spawnve (mode, *path, *argv, *envp); | W+ | = {im-process-h} | _spawnve (mode, *path, *argv, *envp); | W+ | = {im-process-h} | spawnvp (mode, *path, *argv); | W+ | = {im-process-h} | _spawnvp (mode, *path, *argv); | W+ | = {im-process-h} | spawnvpe (mode, *path, *argv, *envp); | W+ | = {im-process-h} | _spawnvpe (mode, *path, *argv, envp); | P01 | (=) | system (command); | (POSIX and C89 (ISO/IEC 9899:1990) place this function in <stdlib.h>.) 4+| 2+| 2+a| ▗▚▚▚▚ <libi86/stdio.h> ▞▞▞▞▖

		* **``<libi86/stdio.h>`` also includes the underlying C library's ``<stdio.h>``.**
		* **Under newer versions of `gcc-ia16`, ``<stdio.h>`` will also automatically include ``<libi86/stdio.h>``, unless GCC is in "strict ANSI" mode.**

| C99, W | (=) | vsscanf (*s, fmt, ap); | (C99 places this function in <stdio.h>.) | X | := | _vsscanf (s, *fmt, ap); | 4+| 2+| 2+a| ▗▚▚▚▚ <libi86/stdlib.h> ▞▞▞▞▖

		* **``<libi86/stdlib.h>`` also includes the underlying C library's ``<stdlib.h>``.**
		* **Under newer versions of `gcc-ia16`, ``<stdlib.h>`` will also automatically include ``<libi86/stdlib.h>``, unless GCC is in "strict ANSI" mode.**

| W | = {im-stdlib-h} | _fullpath (out-path, *path, size); | | W | G | *lltoa (value, *buffer, radix); | Not yet supported on ACK — it lacks long long support for IA-16. | W | G | *_lltoa (value, *buffer, radix); | Not yet supported on ACK — it lacks long long support for IA-16. | W | = | *ltoa (value, *buffer, radix); | | W | = | *_ltoa (value, buffer, radix); | | W+ | = {im-stdlib-h} | _makepath (path, *drive, *dir, *fname, ext); a| * As extensions, this function ** checks for buffer overflow, and ** gives a return value. * Upon an error, the return value is non-zero, errno is set, and path[] holds either an empty string or a truncated path. * Network drive[] values starting with two backslashes (\\) are not supported. | W | = {im-stdlib-h} | _splitpath (path, *drive, *dir, *fname, ext); | Long filenames, and network paths starting with two backslashes (\\), are not supported. | P01 | (=) | system (command); | | W | G | *ulltoa (value, *buffer, radix); | Not yet supported on ACK — it lacks long long support for IA-16. | W | G | *_ulltoa (value, *buffer, radix); | Not yet supported on ACK — it lacks long long support for IA-16. | W | = | *ultoa (value, *buffer, radix); | | W | = | *_ultoa (value, *buffer, radix); | 4+| 2+| 2+a| ▗▚▚▚▚ <libi86/string.h> ▞▞▞▞▖

		* **``<libi86/string.h>`` also includes the underlying C library's ``<string.h>``.**
		* **Under newer versions of `gcc-ia16`, ``<string.h>`` will also automatically include ``<libi86/string.h>``, unless GCC is in "strict ANSI" mode.**

| W | = | _fmemcmp (*s1, *s2, n); | | W | = | _fmemcpy (dest, *src, n); | | W | = | _fmemmove (dest, *src, n); | | X | = | _fmempcpy (dest, src, n); | Like _fmemcpy, but returns dest + n. | W | = | _fmemset (s, c, n); | | W | = | _fstrlen (s); | |===

=== Variables

[cols=">1,>1,4,4"] |=== | Compat. | Avail. | Variable | Notes

2+| 2+| ▗▚▚▚▚ <libi86/stdlib.h> ▞▞▞▞▖ | W | (=) | _osmajor | Implemented as a function call on ACK. | W | (=) | _osminor | Implemented as a function call on ACK. | W | (=) | _psp | Implemented as a function call on ACK. |===