In order for a programming language like W to be useful, it must be accompanied by a run-time system of some kind that interfaces programs to the underlying operating system. In some programming languages, the run-time system is, in fact, part of the language specification (e.g., I/O instructions are part of the language.) Not so in W; interfacing with the operating system is accomplished through a series of library functions that are ordinary (user-defined) functions themselves.
The library functions presented here are not part of the W language specification; they are, however, the same functions that were used for the W compiler itself for file I/O, formatted output, and string manipulation.
File I/O functions
write(file, data, length)
The write() function is used to write a set number of bytes to a file or device. This function is a wrapper for the MS-DOS Interrupt 21h function 40h. The first parameter is the MS-DOS file handle; the second parameter is a pointer to the data to be written; the third parameter is the number of bytes to be written.
Return value: the function returns the number of bytes actually written, or 0 if no data has been written.
write := 0x8B55, 0x8BEC, 0x085E, 0x4E8B, 0x8B04, 0x0656, 0x00B8, 0xCD40, 0x7321, 0x3102, 0x8BC0, 0x5DE5, 0x90C3 ; ; 0100 55 PUSH BP ; 0101 8BEC MOV BP,SP ; 0103 8B5E08 MOV BX,[BP+08] ; 0106 8B4E04 MOV CX,[BP+04] ; 0109 8B5606 MOV DX,[BP+06] ; 010C B80040 MOV AX,4000 ; 010F CD21 INT 21 ; 0111 7302 JNB 0115 ; 0113 31C0 XOR AX,AX ; 0115 8BE5 MOV SP,BP ; 0117 5D POP BP ; 0118 C3 RET
read(file, data, length)
The read() function is used to read a set number of bytes from a file or device. This function is a wrapper for the MS-DOS Interrupt 21h function 3Fh. The first parameter is the MS-DOS file handle; the second parameter is a pointer to a buffer where data will be copied; the third parameters in the maximum number of bytes to be read.
Return value: the function returns the number of bytes actually read, or 0 if no data has been read.
read := 0x8B55, 0x8BEC, 0x085E, 0x4E8B, 0x8B04, 0x0656, 0x00B8, 0xCD3F, 0x7321, 0x3102, 0x8BC0, 0x5DE5, 0x90C3 ; ; 0100 55 PUSH BP ; 0101 8BEC MOV BP,SP ; 0103 8B5E08 MOV BX,[BP+08] ; 0106 8B4E04 MOV CX,[BP+04] ; 0109 8B5606 MOV DX,[BP+06] ; 010C B8003F MOV AX,3F00 ; 010F CD21 INT 21 ; 0111 7302 JNB 0115 ; 0113 31C0 XOR AX,AX ; 0115 8BE5 MOV SP,BP ; 0117 5D POP BP ; 0118 C3 RET
open(filename, mode)
The open() function opens a file or device for reading or writing. If a file that's being opened for writing doesn't exist, it is created by this function. The filename parameter is any valid MS-DOS file name in the form of a null-terminated string. The mode parameter can be 0 (open the file for reading), 1 (open the file for writing), or 2 (open the file for reading or writing). This function is a wrapper for MS-DOS Interrupt 21h functions 3Ch and 3Dh.
Return value: upon success, the function returns the MS-DOS file handle. Upon failure, the return value is 0.
open := 0x8955, 0x8BE5, 0x0656, 0x468B, 0x3C04, 0x7501, 0x3107, 0xB8C9, 0x3C00, 0x02EB, 0x3DB4, 0x21CD, 0x0273, 0xC031, 0xEC89, 0xC35D ; 0100 55 PUSH BP ; 0101 89E5 MOV BP,SP ; 0103 8B5606 MOV DX,[BP+06] ; 0106 8B4604 MOV AX,[BP+04] ; 0109 3C01 CMP AL,01 ; 010B 7507 JNZ 0114 ; 010D 31C9 XOR CX,CX ; 010F B8003C MOV AX,3C00 ; 0112 EB02 JMP 0116 ; 0114 B43D MOV AH,3D ; 0116 CD21 INT 21 ; 0118 7302 JNB 011C ; 011A 31C0 XOR AX,AX ; 011C 89EC MOV SP,BP ; 011E 5D POP BP ; 011F C3 RET
close(file)
The close() function closes a previously opened file handle. This function is a wrapper for MS-DOS Interrupt 21h function 3Eh.
close := 0x8955, 0x8BE5, 0x045E, 0x00B8, 0xCD3E, 0x7221, 0x3102, 0x89C0, 0x5DEC, 0x90C3 ; 0100 55 PUSH BP ; 0101 89E5 MOV BP,SP ; 0103 8B5E04 MOV BX,[BP+04] ; 0106 B8003E MOV AX,3E00 ; 0109 CD21 INT 21 ; 010B 7202 JB 010F ; 010D 31C0 XOR AX,AX ; 010F 89EC MOV SP,BP ; 0111 5D POP BP ; 0112 C3 RET ; 0113 90 NOP
seek(file, position, direction)
The seek() function positions the read/write pointer within an open file. The position parameter is a pointer to a two-word array that determines the location where the file pointer is to be moved. The direction parameter can be 0, meaning the move is relative to the beginning of the file; 1, meaning the move is relative to the current location; or 2, meaning the move is relative to the end of the file. If the direction parameter is 1 or 2, the position parameter is interpreted as a signed quantity, meaning that it is possible to move the file pointer both forward and backward.
The seek() function is a wrapper for MS-DOS Interrupt 21h function 42h.
Return value: upon failure, the function returns 0xFFFF and sets the position value pointed to by the position parameter to 0xFFFF, 0xFFFF. Upon success, the function sets the position value to the current (new) file location. It is, therefore, possible to use the seek() function to determine the current location in the file by setting the position pointed to by the position parameter to 0, 0, and the direction parameter to 1.
The behavior of seek() is undefined if file is a handle to an I/O device.
seek := 0x8955, 0x8BE5, 0x065E, 0x178B, 0x4F8B, 0x8B02, 0x085E, 0x468B, 0xB404, 0xCD42, 0x7321, 0xB806, 0xFFFF, 0xFFBA, 0x8BFF, 0x065E, 0x0789, 0x5789, 0x8902, 0x5DEC, 0x90C3 ; 0100 55 PUSH BP ; 0101 89E5 MOV BP,SP ; 0103 8B5E06 MOV BX,[BP+06] ; 0106 8B17 MOV DX,[BX] ; 0108 8B4F02 MOV CX,[BX+02] ; 010B 8B5E08 MOV BX,[BP+08] ; 010E 8B4604 MOV AX,[BP+04] ; 0111 B442 MOV AH,42 ; 0113 CD21 INT 21 ; 0115 7306 JNB 011D ; 0117 B8FFFF MOV AX,FFFF ; 011A BAFFFF MOV DX,FFFF ; 011D 8B5E06 MOV BX,[BP+06] ; 0120 8907 MOV [BX],AX ; 0122 895702 MOV [BX+02],DX ; 0125 89EC MOV SP,BP ; 0127 5D POP BP ; 0128 C3 RET ; 0129 90 NOP
unlink(filename)
The unlink() function deletes the file specified by the filename parameter. This parameter can point to a string containing any valid, null-terminated MS-DOS filename. This function is a wrapper for MS-DOS Interrupt 21h function 41h.
Return value: the function returns 0 on success, or a non-0 error value.
unlink := 0x8955, 0x8BE5, 0x0456, 0x00B8, 0xCD41, 0x7221, 0x3102, 0x89C0, 0x5DEC, 0x90C3 ; 0100 55 PUSH BP ; 0101 89E5 MOV BP,SP ; 0103 8B5604 MOV DX,[BP+04] ; 0106 B80041 MOV AX,4100 ; 0109 CD21 INT 21 ; 010B 7202 JB 010F ; 010D 31C0 XOR AX,AX ; 010F 89EC MOV SP,BP ; 0111 5D POP BP ; 0112 C3 RET ; 0113 90 NOP
Standard file handles
In addition to the file manipulation functions described above, the following standard file handles are defined:
stdin := 0 ; MS-DOS standard input stdout := 1 ; MS-DOS standard output stderr := 2 ; and standard errorThese file handles are open and valid when a W program begins execution.
getc(file)
The getc() function retrieves a single character from a file or device.
Return value: the return value is the character read, or 0xFFFF is the end of the file has been reached or an error occurred.
getc(f) := { c := 0 read(f, #c, 1) ? c, 0xFFFF }
ungetc(file)
The ungetc() function positions the read/write pointer in a file backward by one byte. The effect of this function is undefined for handles that don't represent a disk file.
ungetc(f) := { p[2] := 0xFFFF, 0xFFFF seek(f, #p, 1) }
Data conversion functions
atoi(string)
The atoi() function interprets a null-terminated string value as a decimal integer and converts it to a binary value.
Return value: the return value is a binary word corresponding to the number represented by the string. There is no error return.
atoi(s) := { n := 0 p := $ @s&0xFF >= '0' ? { @s&0xFF <= '9' ? { n = n*10 + (@s&0xFF - '0') s = s+1 $ = p } } n ; Return value }
itoa(number, string)
The itoa() function converts a binary number into a decimal number using its ASCII string representation. The converted string is stored at the location pointed to by the string parameter; this parameter must point to a location containing at least 3 words of allocated memory.
Return value: the return value is the number of digits in the result.
itoa(n, s) := { @s = @s & 0xFF00 c := 0 p := $ m := n / 10 d := n % 10 m || d ? { i := c q := $ i > 0 ? { @(s+i) = (@(s+i) & 0xFF00) + (@(s+i-1) & 0xFF) i = i - 1 $ = q } c = c + 1 @s = (@s & 0xFF00) + d + '0' n = m $ = p } c == 0 ? { @s = '0' c = c + 1 } c }
itox(number, string)
The itox() function converts a binary number into a hexadecimal number using its 4-digit ASCII string representation. Leading zeroes are not suppressed. The converted string is stored at the location pointed to by the string parameter; this parameter must point to a location containing at least 3 words of allocated memory.
Return value: the return value is the number of digits in the result (i.e., it's always 4.)
itox(n, s) := { i := 0 x := ? p := $ i < 4 ? { x = (n & 0xF000) >> 12 @(s+i) = @(s+i) & 0xFF00 + (x > 9 ? x + 'A' - 10, x + '0') n = n << 4 i = i + 1 $ = p } @s[2] = 0 i }
String manipulation functions
strlen(string)
The strlen() function computes the length of a null-terminated character string pointed to by the string parameter. The terminating null character is not included in the count.
Return value: the function returns the length of its string parameter.
strlen := 0x8955, 0x57E5, 0x7E8B, 0xB904, 0xFFFF, 0x30FC, 0xF2C0, 0xB8AE, 0xFFFE, 0xC829, 0x5D5F, 0x90C3 ; 55 PUSH BP ; 89E5 MOV BP,SP ; 57 PUSH DI ; 8B7E04 MOV DI,[BP+04] ; B9FFFF MOV CX,FFFF ; FC CLD ; 30C0 XOR AL,AL ; F2 REPNZ ; AE SCASB ; B8FEFF MOV AX,FFFE ; 29C8 SUB AX,CX ; 5F POP DI ; 5D POP BP ; C3 RET ; 90 NOP
strncpy(dst, src, len)
The strncpy() function copies up to len characters from the location pointed to by src to the location pointed to by dst. If a null character is encountered, the copy operation is stopped.
strncpy := 0x8955, 0x57E5, 0x8B56, 0x067E, 0x4E8B, 0xFC04, 0xC030, 0xAEF2, 0x4E2B, 0xF704, 0x8BD9, 0x087E, 0x768B, 0xF306, 0x5EA4, 0x5D5F, 0x90C3 ; 0100 55 PUSH BP ; 0101 89E5 MOV BP,SP ; 0103 57 PUSH DI ; 0104 56 PUSH SI ; 0105 8B7E06 MOV DI,[BP+06] ; 0108 8B4E04 MOV CX,[BP+04] ; 010B FC CLD ; 010C 30C0 XOR AL,AL ; 010E F2 REPNZ ; 010F AE SCASB ; 0110 2B4E04 SUB CX,[BP+04] ; 0113 F7D9 NEG CX ; 0115 8B7E08 MOV DI,[BP+08] ; 0118 8B7606 MOV SI,[BP+06] ; 011B F3 REPZ ; 011C A4 MOVSB ; 011D 5E POP SI ; 011E 5F POP DI ; 011F 5D POP BP ; 0120 C3 RET ; 0121 90 NOP
strcpy(dst, src)
The strcpy() functions copies strings from src to dst up to and including the terminating null character.
strcpy(d, s) := strncpy(d, s, 0xFFFF)
memcmp(dst, src, len)
The memcmp() function compares up to len bytes of data located at the addresses pointed to by the src and dst parameters.
Return value: the return value is 0 if the two areas of memory contain the same data; if there is a difference, the return value is non-0 (but otherwise undefined.)
memcmp := 0x8955, 0x57E5, 0x8B56, 0x044E, 0x7E8B, 0x8B08, 0x0676, 0xA6F3, 0x01B8, 0x7500, 0x3102, 0x5EC0, 0x5D5F, 0x90C3 ; 0100 55 PUSH BP ; 0101 89E5 MOV BP,SP ; 0103 57 PUSH DI ; 0104 56 PUSH SI ; 0105 8B4E04 MOV CX,[BP+04] ; 0108 8B7E08 MOV DI,[BP+08] ; 010B 8B7606 MOV SI,[BP+06] ; 010E F3 REPZ ; 010F A6 CMPSB ; 0110 B80100 MOV AX,0001 ; 0113 7502 JNZ 0117 ; 0115 31C0 XOR AX,AX ; 0117 5E POP SI ; 0118 5F POP DI ; 0119 5D POP BP ; 011A C3 RET ; 011B 90 NOP
strncmp(dst, src, len)
The strncmp() function compares up to len bytes of string data located at the addresses pointed to by the src and dst parameters. The compare operation stops if a null character is encountered in either strings.
Return value: the return value is 0 if the two strings contain the same data; if there is a difference, the return value is non-0 (but otherwise undefined.)
strncmp(d, s, n) := { k := strlen(d) l := strlen(s) 0 != ((k > n && l > n) || (k == l)) ? { k < n ? n = k memcmp(d, s, n) }, 0xFFFF }
strcmp(dst, src)
The strcmp() function compares two strings data located at the addresses pointed to by the src and dst parameters. The compare operation stops if a null character is encountered in either strings.
Return value: the return value is 0 if the two strings contain the same data; if there is a difference, the return value is non-0 (but otherwise undefined.)
strcmp(d, s) := strncmp(d, s, 0xFFFF)
at(string, number)
The at() function retrieves a specific character (determined by the number parameter) from the string pointed to by the string parameter.
Return value: the return value is the byte at the specified location. There is no error return.
at(s, n) := (@s[n >> 1] & ((n&1) ? 0xFF00, 0x00FF)) >> ((n&1) ? 8, 0)
Character classification functions
isalphabetic(character)
The isalphabetic() function returns a non-zero result if its argument represents the ASCII code of an upper-, or lowercase letter.
isalphabetic(c) := { c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_' }
isdigit(character)
The isdigit() function returns a non-zero result if its argument represent the ASCII code of a digit.
isdigit(c) := { c >= '0' ? c <= '9' }
isalphanumeric(character)
The isalphanumeric() function returns a non-zero result if its argument is either a letter, or a digit.
isalphanumeric(c) := { isalphabetic(c) || isdigit(c) }
isspace(character)
The isspace() function returns a non-zero value if its argument is the ASCII code of a whitespace character: i.e., a space, tab, carriage-return or newline character.
isspace(c) := { c == ' ' || c == '\t' || c == '\r' || c == '\n' }
Formatted output functions
puts(file, string)
The puts() function writes a null-terminated string to the file or device represented by the file parameter.
Return value: the return value is the number of bytes written, or 0 if no data is written.
puts(o, s) := write(o, s, strlen(s))
putn(file, number)
The putn() function formats a binary value as a decimal number and writes it to the file or device represented by the file parameter.
Return value: the return value is the number of bytes written, or 0 if no data is written.
putn(o, n) := { s[3] := ? n = itoa(n, #s) write(o, #s, n) }
putx(file, number)
The putx() function formats a binary value as a hexadecimal number and writes it to the file or device represented by the file parameter.
Return value: the return value is the number of bytes written, or 0 if no data is written.
putx(o, n) := { s[3] := ? n = itox(n, #s) write(o, #s, n) }
putss(string)
The putss() function writes a null-terminated string to standard output. Its operation is identical to that of puts().
putss(s) := puts(stdout, #s)
putsn(number)
The putsn() function writes a null-terminated string to standard output. Its operation is identical to that of putn().
putsn(n) := putn(stdout, n)
printf([parameters,...] format-string, file)
The printf() function emits formatted output to the specified device. The format-string parameter points to a string that controls the appearance of the output. The format string may contain the special character sequences, which will be replaced with additional parameters supplied to this function. The sequence %s means a string substitution; the sequence %d means a decimal parameter; and the sequence %x means a hexadecimal parameter. Any other character following a % character (including a second % character) is printed unchanged.
The printf() function is a function with a variable number of arguments. These arguments must appear in reverse order relative to the appearance of the corresponding placeholders in format-string.
printf(s, o) := { n := 0 m := 0 c := ? p := #s + 2 r := $ c = at(s, n) c != 0 ? { c == '%' ? { write(o, s + m, n - m) m = n + 2 n = n + 1 c = at(s, n) c == 's' ? { puts(o, @p) }, c == 'd' ? { putn(o, @p) }, c == 'x' ? { putx(o, @p) }, { write(o, #c, 1) } p = p + 2 } n = n + 1 c = at(s, n) $ = r } m < n ? write(o, s + m, n - m) }