Microsoft C v1.0

This commit is contained in:
davidly 2024-06-30 12:06:07 -07:00
parent 643f795c5a
commit c4ecbf7d91
34 changed files with 1948 additions and 0 deletions

116
Microsoft C v1/C.ASM Normal file
View File

@ -0,0 +1,116 @@
; name XCMAIN -- initiate execution of C program
;
; description This is the main module for a C program on the
; MS-DOS implementation. It initializes the segment
; registers, sets up the stack, and calls the C main
; function _main with a pointer to the remainder of
; the command line.
;
; Also defined in this module is the exit entry point
; XCEXIT.
;
pgroup group base,prog
dgroup group data,stack
;
; The following segment serves only to force "pgroup" lower in
; memory. It also contains the Microsoft C revision number.
;
base segment 'prog'
db "MS-C V 1.04 "
base ends
;
; The data segment defines locations which contain the offsets
; of the base and top of the stack.
;
data segment byte public 'data'
public _top, _base
_top dw 0
_base dw 0
data ends
;
; The stack segment is included to prevent the warning from the
; linker, and also to define the base (lowest address) of the stack.
;
stack segment stack 'data'
sbase dw 128 dup (?)
stack ends
;
; The main program must set up the initial segment registers
; and the stack pointer, and set up a far return to the MS-DOS
; exit point at ES:0. The command line bytes from the program
; segment prefix are moved onto the stack, and a pointer to
; them supplied to the C main module _main (which calls main).
;
prog segment byte public 'prog'
public XCMAIN, XCEXIT
extrn _main:near
assume cs:pgroup, ds:dgroup, ss:dgroup
XCMAIN proc far
cli ;disable interrupts
mov ax,dgroup
mov ds,ax ;initialize ds and ss
mov ss,ax
mov bx,es:2 ;total memory size (paragraphs)
sub bx,ax
test bx,0f000h
jnz m1 ;branch if more than 64K bytes
mov cl,4
shl bx,cl ;highest available byte
jmp short m2
m1: mov bx,0fff0h
m2: mov sp,bx ;set stack pointer
sti ;enable interrupts
mov _top,bx ;save top of stack
mov ax,offset dgroup:sbase
mov _base,ax ;store ptr to bottom of stack
push es ;push ptr to pgm segment prefix
xor ax,ax
push ax ;instr ptr for far return
mov bp,sp ;save in bp
mov si,80h ;ptr to command line bytes
mov cl,es:[si] ;get number of bytes
inc si
xor ch,ch ;clear high byte
mov bx,cx
add bx,4 ;3 bytes additional, 1 for rounding
and bx,0fffeh ;force even number of bytes
sub sp,bx ;allocate space on stack
mov di,sp
mov byte ptr [di],'c' ;store dummy program name
inc di
jcxz m4 ;skip if no bytes to move
mov byte ptr [di],' '
inc di
m3: mov al,es:[si] ;move bytes to stack
mov [di],al
inc si
inc di
loop m3
m4: xor ax,ax
mov [di],al ;store null byte
mov ax,ds
mov es,ax ;es, ds, and ss are all equal
mov ax,sp
push ax ;ptr to command line
call _main ;call C main
mov sp,bp ;restore ptr to far return
ret ;return to MS-DOS
XCMAIN endp
;
; name XCEXIT -- terminate execution of C program
;
; description This function terminates execution of the current
; program by returning to MS-DOS. The error code
; argument normally supplied to XCEXIT is ignored
; in this implementation.
;
XCEXIT proc far
mov ax,_top ;load stack ptr with top address
sub ax,4
mov sp,ax
ret ;return
XCEXIT endp
prog ends
end XCMAIN


BIN
Microsoft C v1/C.EXE Normal file

Binary file not shown.

BIN
Microsoft C v1/C.MAP Normal file

Binary file not shown.

BIN
Microsoft C v1/C.OBJ Normal file

Binary file not shown.

33
Microsoft C v1/CAT.C Normal file
View File

@ -0,0 +1,33 @@
/* (This program is from p. 154 of the Kernighan and Ritchie text */
#include <stdio.h>
main(argc, argv) /* cat: concatenate files */
int argc;
char *argv[];
{
FILE *fp, *fopen();
if (argc == 1) /* no args; copy standard input */
filecopy(stdin);
else
while (--argc > 0)
if ((fp = fopen(*++argv, "r")) == NULL) {
fprintf(stderr,
"cat: can't open %s\n", *argv);
exit(1);
} else {
filecopy(fp);
fclose(fp);
}
exit(0);
}
filecopy(fp) /* copy file fp to standard output */
FILE *fp;
{
int c;
while ((c = getc(fp)) != EOF)
putc(c, stdout);
}
p) /* cop

133
Microsoft C v1/CC.ASM Normal file
View File

@ -0,0 +1,133 @@
; name XCMAIN -- initiate execution of C program
;
; description This is the main module for a C program on the
; MS-DOS implementation. It initializes the segment
; registers, sets up the stack, and calls the C main
; function _main with a pointer to the remainder of
; the command line.
;
; Also defined in this module is the exit entry point
; XCEXIT.
;
pgroup group base,prog,tail
dgroup group data,stack
assume cs:pgroup
;
; The following segment serves only to force "pgroup" lower in
; memory.
;
base segment 'prog'
db ?
base ends
;
; The data segment defines locations which contain the offsets
; of the base and top of the stack.
;
data segment public 'data'
public _top, _base
_top dw 0
_base dw 0
data ends
;
; The stack segment defines the base (lowest address) of the
; stack. Note that in this module it is NOT defined to be
; of the STACK combining type, thus allowing a .COM file to be
; made of the resulting .EXE file.
;
stack segment 'data'
sbase dw 128 dup (?)
stack ends
;
; The tail segment allows this module to determine the paragraph
; at which the data segment begins, without use of a relocatable
; value.
;
tail segment byte 'prog'
db "MS-C V 1.04 "
last db 0 ;last byte in PGROUP
tail ends
;
; The main program must set up the initial segment registers
; and the stack pointer, and set up a far return to the MS-DOS
; exit point at ES:0. The command line bytes from the program
; segment prefix are moved onto the stack, and a pointer to
; them supplied to the C main module _main (which calls main).
;
prog segment byte public 'prog'
public XCMAIN, XCEXIT
extrn _main:near
assume cs:pgroup, ds:dgroup, ss:dgroup
org 0ffh
XCMAIN proc far
cli
mov ax,offset pgroup:last ;get offset of last byte
add ax,16
mov cl,4
shr ax,cl ;number of paragraphs in PGROUP
mov bx,cs
add ax,bx ;base of DGROUP
mov ds,ax ;initialize ds and ss
mov ss,ax
mov bx,es:2 ;total memory size (paragraphs)
sub bx,ax
test bx,0f000h
jnz m1 ;branch if more than 64K bytes
mov cl,4
shl bx,cl ;highest available byte
jmp short m2
m1: mov bx,0fff0h
m2: mov sp,bx ;set stack pointer
sti
mov _top,bx ;save top of stack
mov ax,offset dgroup:sbase
mov _base,ax ;store ptr to bottom of stack
push es ;push ptr to pgm segment prefix
xor ax,ax
push ax ;instr ptr for far return
mov bp,sp ;save in bp
mov si,80h ;ptr to command line bytes
mov cl,es:[si] ;get number of bytes
inc si
xor ch,ch ;clear high byte
mov bx,cx
add bx,4 ;3 bytes additional, 1 for rounding
and bx,0fffeh ;force even number of bytes
sub sp,bx ;allocate space on stack
mov di,sp
mov byte ptr [di],'c' ;store dummy program name
inc di
jcxz m4 ;skip if no bytes to move
mov byte ptr [di],' '
inc di
m3: mov al,es:[si] ;move bytes to stack
mov [di],al
inc si
inc di
loop m3
m4: xor ax,ax
mov [di],al ;store null byte
mov ax,ds
mov es,ax ;es, ds, and ss are all equal
mov ax,sp
push ax ;ptr to command line
call _main ;call C main
mov sp,bp ;restore ptr to far return
ret ;return to MS-DOS
XCMAIN endp
;
; name XCEXIT -- terminate execution of C program
;
; description This function terminates execution of the current
; program by returning to MS-DOS. The error code
; argument normally supplied to XCEXIT is ignored
; in this implementation.
;
XCEXIT proc far
mov ax,_top ;load stack ptr with top address
sub ax,4
mov sp,ax
ret ;return
XCEXIT endp
prog ends
end XCMAIN


BIN
Microsoft C v1/CC.EXE Normal file

Binary file not shown.

BIN
Microsoft C v1/CC.OBJ Normal file

Binary file not shown.

151
Microsoft C v1/CONIO.C Normal file
View File

@ -0,0 +1,151 @@
/**
*
* This module defines the various console I/O functions. They may
* be called directly, using the names included here, or the header
* file CONIO.H may be included so that more standard names may be
* used. This source module is provided so that users may customize
* the console I/O functions, if desired. Note that "cprintf" and
* "cscanf" (included in MC.LIB) call the functions "putch", "getch",
* and "ungetch".
*
**/
#define BDOS_IN 7 /* input function for "getch" */
#define BDOS_OUT 6 /* output function for "putch" */
#define BDOS_CKS 11 /* check keyboard status for "kbhit" */
#define BDOS_BKI 10 /* buffered keyboardd input for "cgets" */
#define BDOS_PRT 9 /* print string for "cputs" */
static char pushback; /* character save for "ungetch" */
/**
*
* name getch -- get character from console
*
* synopsis c = getch();
* char c; input character
*
* description This function obtains the next character typed at
* the console or, if one was pushed back via "ungetch",
* returns the previously pushed back character.
*
**/
getch()
{
int c;
if (pushback != '\0')
{ /* character was pushed back */
c = pushback;
pushback = '\0';
return(c);
}
return(bdos(BDOS_IN, 0xFF) & 127);
}
/**
*
* name putch -- send character directly to console
*
* synopsis putch(c);
* char c; character to be sent
*
* description This function sends the specified character directly
* to the user's console.
*
**/
putch(c)
char c;
{
bdos(BDOS_OUT, c&127);
return(c);
}
/**
*
* name ungetch -- push character back to console
*
* synopsis r = ungetch(c);
* int r; return code
* char c; character to be pushed back
*
* description This function pushes the indicated character back
* on the console. Only a single level of pushback is
* allowed. The effect is to cause "getch" to return
* the pushed-back character the next time it is called.
*
* returns r = -1 if character already pushed back
* = c otherwise
*
**/
ungetch(c)
char c;
{
if (pushback != '\0') return(-1);
pushback = c;
return(c);
}
/**
*
* name cgets -- get string directly from console
*
* synopsis p = cgets(s);
* char *p; pointer to result string
* char *s; string buffer (first byte = count)
*
* description This function obtains a string directly from the
* user's console. This version uses the buffered
* keyboard input function supported by the BDOS, so
* that all of the line editing capabilities are available.
* The first byte of "s" must be initialized to contain
* the number of bytes, minus two, in "s". The string
* pointer returned is "s+2", which contains the first
* byte of input data. Note that "s[1]" will contain
* the number of characters in the string. The carriage
* return (which the user at the console must type to
* terminate the operation) is replaced by a null byte.
*
* returns p = pointer to string received
*
**/
char *cgets(s)
char *s;
{
char *p;
if (*s == 0) *s = 250; /* do not allow zero byte count */
bdos(BDOS_BKI, s);
p = s+2;
p[s[1]] = '\0'; /* set terminating byte */
return(p);
}
/**
*
* name cputs -- send character string directly to console
*
* synopsis cputs(s);
* char *s; character string to be sent
*
* description This function sends the specified string directly to
* the user's console. The BDOS function for "print
* string" is used. The function locates the terminating
* null byte, changes it to a '$' (the terminator
* required by the BDOS function), and then changes it
* back to the null byte before returning. Thus, the
* string to be printed cannot itself contain a '$' and
* it cannot reside in read-only memory (ROM).
*
* Note that a carriage return or linefeed is NOT appended
* by this function; they must be included in the string,
* if desired.
*
**/
cputs(s)
char *s;
{
char *p;
for (p = s; *p != '\0'; p++) ; /* find string terminator */
*p = '$';
bdos(BDOS_PRT, s);
*p = '\0';
return;
}

15
Microsoft C v1/CONIO.H Normal file
View File

@ -0,0 +1,15 @@
/**
*
* This header file defines an equivalence between several of the
* standard level 2 I/O functions and their console I/O counterparts.
* Use this header file for programs which perform all of these functions
* to the console only, and need an unbuffered, direct interface to the
* user's console. See Section 3.2.3 of the manual for more information.
*
**/
#define getchar getch
#define putchar putch
#define gets cgets
#define puts cputs
#define printf cprintf
#define scanf cscanf

52
Microsoft C v1/CTYPE.H Normal file
View File

@ -0,0 +1,52 @@
/**
*
* This header file defines various ASCII character manipulation macros,
* as follows:
*
* isalpha(c) non-zero if c is alpha
* isupper(c) non-zero if c is upper case
* islower(c) non-zero if c is lower case
* isdigit(c) non-zero if c is a digit (0 to 9)
* isxdigit(c) non-zero if c is a hexadecimal digit (0 to 9, A to F,
* a to f)
* isspace(c) non-zero if c is white space
* ispunct(c) non-zero if c is punctuation
* isalnum(c) non-zero if c is alpha or digit
* isprint(c) non-zero if c is printable (including blank)
* isgraph(c) non-zero if c is graphic (excluding blank)
* iscntrl(c) non-zero if c is control character
* isascii(c) non-zero if c is ASCII
* iscsym(c) non-zero if valid character for C symbols
* iscsymf(c) non-zero if valid first character for C symbols
*
**/
#define _U 1 /* upper case flag */
#define _L 2 /* lower case flag */
#define _N 4 /* number flag */
#define _S 8 /* space flag */
#define _P 16 /* punctuation flag */
#define _C 32 /* control character flag */
#define _B 64 /* blank flag */
#define _X 128 /* hexadecimal flag */
extern char _ctype[]; /* character type table */
#define isalpha(c) (_ctype[(c)+1]&(_U|_L))
#define isupper(c) (_ctype[(c)+1]&_U)
#define islower(c) (_ctype[(c)+1]&_L)
#define isdigit(c) (_ctype[(c)+1]&_N)
#define isxdigit(c) (_ctype[(c)+1]&_X)
#define isspace(c) (_ctype[(c)+1]&_S)
#define ispunct(c) (_ctype[(c)+1]&_P)
#define isalnum(c) (_ctype[(c)+1]&(_U|_L|_N))
#define isprint(c) (_ctype[(c)+1]&(_P|_U|_L|_N|_B))
#define isgraph(c) (_ctype[(c)+1]&(_P|_U|_L|_N))
#define iscntrl(c) (_ctype[(c)+1]&_C)
#define isascii(c) ((unsigned)(c)<=127)
#define iscsym(c) (isalnum(c)||(c==0x5f))
#define iscsymf(c) (isalpha(c)||(c==0x5f))
#define toupper(c) (islower(c)?((c)-('a'-'A')):(c))
#define tolower(c) (isupper(c)?((c)+('a'-'A')):(c))
#define toascii(c) ((c)&127)

23
Microsoft C v1/FTOC.C Normal file
View File

@ -0,0 +1,23 @@
/* print Fahrenheit-Celsius table
for f = 0, 20, ..., 300
(This program is from p. 8 of the Kernighan and Ritchie text)
*/
main()
{
int lower, upper, step;
float fahr, celsius;
lower = 0; /* lower limit of temperature table */
upper = 300; /* upper limit */
step = 20; /* step size */
fahr = lower;
while (fahr <= upper) {
celsius = (5.0/9.0) * (fahr-32.0);
printf("%4.0f %6.1f\n", fahr, celsius);
fahr = fahr + step;
}
}
 celsius = (5.0/9.0) * (fahr-32.0);
printf("%4.0f %6.1f\n", fahr, celsius);
fahr = fahr +

149
Microsoft C v1/FXU.C Normal file
View File

@ -0,0 +1,149 @@
/**
* name fxu -- function extract utility
*
* usage fxu filename function
*
* where "filename" is the name of a file containing
* several C functions, and "function" is the name of
* the particular function to be extracted. If the
* named function is found, then (1) standard input is
* copied to the standard output until EOF, and (2) the
* text of the named function is written to the standard
* output. The first option allows header information
* to be prepended to the output file.
*
**/
#include "stdio.h"
#include "ctype.h"
#define MAX 16 /* maximum characters in function name */
#define MAXBUF 2000 /* maximum characters buffered between functions */
main(argc, argv)
int argc;
char *argv[];
{
int c, brace, cnest, nc;
int i, ns, copy, inlit, delim, pc;
FILE *sfp;
char symbol[MAX+1];
char text[MAXBUF];
if (argc != 3)
{
fputs("Usage: fxu filename function\n", stderr);
exit(1);
}
if ((sfp = fopen(argv[1], "r")) == NULL)
{
fputs("Can't open source file\n", stderr);
exit(1);
}
brace = cnest = nc = ns = copy = inlit = pc = 0;
c = getc(sfp); /* get first char */
while (c != EOF)
{ /* scan through source file */
if (ns == MAXBUF)
{
fputs("Maximum buffer size exceeded\n", stderr);
exit(1);
}
if (copy == 0)
{
if (brace == 0) text[ns++] = c; /* save chars between functions */
}
else
if (putchar(c) == EOF)
{
fputs("Copy error\n", stderr);
exit(1);
}
if (c == '/')
{ /* possible comment */
nc = 0;
if ((c = getc(sfp)) == '*')
{
++cnest; /* bump nesting level */
if (copy) putchar(c);
else if (brace == 0) text[ns++] = c;
c = getc(sfp);
}
continue;
}
if (cnest != 0)
{ /* inside comment */
if (c == '*')
{
if ((c = getc(sfp)) == '/')
{
--cnest; /* reduce nesting level */
if (copy) putchar(c);
else if (brace == 0) text[ns++] = c;
c = getc(sfp);
}
continue;
}
nc = 0;
}
else if (inlit)
{ /* inside literal string */
if (c == '\\' && pc == '\\') c = 0;
if (c == delim && pc != '\\') inlit = 0;
pc = c; /* save previous character */
}
else if (c == '\'' || c == '\"')
{ /* enter literal string */
inlit = 1;
pc = 0;
delim = c;
}
else if (c == '{') ++brace;
else if (c == '}')
{ /* right brace */
nc = 0;
if (--brace == 0)
if (copy == 0) ns = 0; /* reset save index if not found */
else
{ /* copy complete */
putchar('\n');
exit(0);
}
}
else if (brace == 0)
{
if (nc == 0)
{ /* symbol not started yet */
if (iscsymf(c))
symbol[nc++] = c; /* start new symbol */
}
else if (iscsym(c) || c == '$')
/* continue symbol */
if (nc < MAX) symbol[nc++] = c;
else symbol[0] = '\0';
else if (nc != 0)
{ /* end of current symbol */
symbol[nc++] = '\0';
if (strcmp(symbol,argv[2]) == 0)
{ /* named function has been found */
while ((c = getchar()) != EOF)
putchar(c); /* copy standard input to output */
for (i = 0; i < ns; i++)
putchar(text[i]); /* copy saved characters */
copy = 1; /* turn on copy flag */
}
nc = 0;
}
}
c = getc(sfp); /* get next char */
}
fputs("Named function not found\n", stderr);
exit(1);
}
 }
}
c = getc(sfp); /* get next char */
}
fputs("Name

BIN
Microsoft C v1/FXU.EXE Normal file

Binary file not shown.

49
Microsoft C v1/IO.ASM Normal file
View File

@ -0,0 +1,49 @@
; This module defines subroutines to input and output bytes from
; an auxiliary port.
;
; name inp -- input byte from port
;
; synopsis c = inp(port);
; int c; returned byte
; int port; port address
;
; description This function inputs a byte from the specified port
; address and returns it as the function value.
;
PGROUP GROUP PROG
PROG SEGMENT BYTE PUBLIC 'PROG'
PUBLIC INP,OUTP
ASSUME CS:PGROUP
INP PROC NEAR
PUSH BP ;SAVE BP
MOV BP,SP
MOV DX,[BP+4] ;GET PORT ADDRESS
IN AL,DX ;GET INPUT BYTE
XOR AH,AH ;CLEAR HIGH BYTE
POP BP
RET
INP ENDP
;
; name outp -- output byte to port
;
; synopsis outp(port,c);
; int port; port address
; int c; byte to send
;
; description This function sends the specified character to
; the specified port.
;
OUTP PROC NEAR
PUSH BP ;SAVE BP
MOV BP,SP
MOV DX,[BP+4] ;GET PORT ADDRESS
MOV AX,[BP+6] ;GET OUTPUT BYTE
OUT DX,AL
POP BP
RET
OUTP ENDP
PROG ENDS
END
,SP
MOV DX,[BP+4] ;GET PORT ADDRESS
MOV AX,[BP+6]

BIN
Microsoft C v1/LIB.EXE Normal file

Binary file not shown.

BIN
Microsoft C v1/LINK.EXE Normal file

Binary file not shown.

Binary file not shown.

126
Microsoft C v1/MAIN.C Normal file
View File

@ -0,0 +1,126 @@
/**
*
* This module defines the standard C main function _main.
*
* This version processes the command-line specifiers which modify
* the stack size or specify assignments for "stdin" and "stdout".
*
**/
#include "stdio.h"
#include "ctype.h"
#define MAXNAM 16 /* maximum filename size */
#define MAXARG 32 /* maximum command line arguments */
/**
*
* The following location defines the default stack size (bytes). It is
* used by "sbrk" to call XCMEM to initialize the memory pool.
*
**/
extern int _stack;
/**
*
* name _main - process command line, open files, and call "main"
*
* synopsis _main(line);
* char *line; ptr to command line that caused execution
*
* description This function performs the standard pre-processing for
* the main module of a C program. It accepts a command
* line of the form
*
* pgmname [=stack] [<infile] [>outfile] parms
*
* and processes the three optional leading fields, builds
* a list of pointers to the other parameters, and calls
* the main function "main". The first optional field
* specifies an override of the default stack size; "stack"
* should be a decimal number of bytes. The second specifies
* a file name for assignment to "stdin"; "infile" is the
* file name. The third specifies, similarly, a file name
* "outfile" for assignment to "stdout". Note that the
* optional fields need not be specified in the order listed
* above.
*
**/
_main(line)
char *line;
{
int i;
FILE *fp0, *fp1, *fp2;
static int argc = 1;
static char *outmode = "w";
static char inam[MAXNAM+1], onam[MAXNAM+1], tnam[1];
static char *argv[MAXARG];
while (isspace(*line)) line++; /* find program name */
for(argc = 0; argc < MAXARG; )
{
switch(*line)
{
case '=': /* stack size specifier */
line++;
_stack = 0;
while (isdigit(*line))
_stack = 10*_stack + (*line++ & 15);
break;
case '<': /* input file specifier */
line++;
for(i = 0; (*line != '\0') && (isspace(*line) == 0); line++)
if (i<MAXNAM) inam[i++] = *line;
inam[i] = '\0';
break;
case '>': /* output file specifier */
line++;
if (*line == '>')
{ /* output file to be appended to */
outmode = "a";
line++;
}
for (i = 0; (*line != '\0') && (isspace(*line) == 0); line++)
if (i<MAXNAM) onam[i++] = *line;
onam[i] = '\0';
break;
default: /* command line argument */
argv[argc++] = line;
while (*line != '\0' && isspace(*line) == 0) line++;
}
i = *line; /* save terminating character */
*line++ = '\0';
if (i == '\0') break; /* end of line */
while (isspace(*line)) line++; /* scan to next */
if (*line == '\0') break;
}
fp0 = fopen(inam, "r"); /* open stdin */
fp1 = fopen(onam, outmode); /* open stdout */
fp2 = fopen(tnam, "a"); /* open stderr */
if (fp2 == NULL) _exit(1);
if (fp0 == NULL)
{
fputs("Can't open stdin file\n", fp2);
exit(1);
}
if (fp1 == NULL)
{
fputs("Can't create stdout file\n", fp2);
exit(1);
}
if (inam[0] == '\0')
fp0->_flag |= _IONBF;
if (onam[0] == '\0')
fp1->_flag |= _IONBF;
fp2->_flag |= _IONBF;
main(argc, argv); /* call main function */
exit(0);
}
0')
fp1->_flag |= _IONBF;
fp2->_flag |= _IONBF;

BIN
Microsoft C v1/MC.BAT Normal file

Binary file not shown.

BIN
Microsoft C v1/MC.LIB Normal file

Binary file not shown.

BIN
Microsoft C v1/MC1.EXE Normal file

Binary file not shown.

BIN
Microsoft C v1/MC2.EXE Normal file

Binary file not shown.

82
Microsoft C v1/MM.C Normal file
View File

@ -0,0 +1,82 @@
/* BYTE magazine October 1982. Jerry Pournelle. */
/* ported to C by David Lee */
/* various bugs not found because dimensions are square fixed by David Lee */
/* expected result: 4.65880E+05 */
#define LINT_ARGS
#include <stdio.h>
#define l 20 /* rows in A and resulting matrix C */
#define m 20 /* columns in A and rows in B (must be identical) */
#define n 20 /* columns in B and resulting matrix C */
#define ftype float
ftype Summ;
ftype A[ l + 1 ] [ m + 1 ];
ftype B[ m + 1 ] [ n + 1 ];
ftype C[ l + 1 ] [ n + 1 ];
int filla()
{
int i, j;
for ( i = 1; i <= l; i++ )
for ( j = 1; j <= m; j++ )
A[ i ] [ j ] = i + j;
return 0;
}
int fillb()
{
int i, j;
for ( i = 1; i <= m; i++ )
for ( j = 1; j <= n; j++ )
B[ i ] [ j ] = (ftype) (int) ( ( i + j ) / j );
return 0;
}
int fillc()
{
int i, j;
for ( i = 1; i <= l; i++ )
for ( j = 1; j <= n; j++ )
C[ i ] [ j ] = 0;
return 0;
}
int matmult()
{
int i, j, k;
for ( i = 1; i <= l; i++ )
for ( j = 1; j <= n; j++ )
for ( k = 1; k <= m; k++ )
C[ i ] [ j ] += A[ i ] [ k ] * B[ k ] [ j ];
return 0;
}
int summit()
{
int i, j;
for ( i = 1; i <= l; i++ )
for ( j = 1; j <= n; j++ )
Summ += C[ i ] [ j ];
return 0;
}
int main( argc, argv ) int argc; char * argv[];
{
Summ = 0;
filla();
fillb();
fillc();
matmult();
summit();
printf( "summ is : %lf\n", Summ );
return 0;
}

BIN
Microsoft C v1/OMD.EXE Normal file

Binary file not shown.

29
Microsoft C v1/SIEVE.C Normal file
View File

@ -0,0 +1,29 @@
#define true 1
#define false 0
#define size 8190
#define sizepl 8191
main() {
int i,prime,k,count,iter;
char flags[sizepl];
printf("10 iterations\n");
for(iter=1;iter<= 10;iter++){
count=0;
for(i = 0; i<=size;i++)
flags[i]=true;
for(i=0;i <= size; i++){
if(flags[i]){
prime = i+i+3;
k=i+prime;
while(k<=size){
flags[k] = false;
k += prime;
}
count = count+1;
}
}
}
printf("\n%d primes\n",count);
}


55
Microsoft C v1/STDIO.H Normal file
View File

@ -0,0 +1,55 @@
/**
*
* This header file defines the information used by the standard I/O
* package.
*
**/
#define _BUFSIZ 512 /* standard buffer size */
#define _NFILE 16 /* maximum number of files */
struct _iobuf
{
char *_ptr; /* current buffer pointer */
int _cnt; /* current byte count */
char *_base; /* base address of I/O buffer */
char _flag; /* control flags */
char _file; /* file number */
};
extern struct _iobuf _iob[_NFILE];
#define _IOREAD 1 /* read flag */
#define _IOWRT 2 /* write flag */
#define _IONBF 4 /* non-buffered flag */
#define _IOMYBUF 8
#define _IOEOF 16 /* end-of-file flag */
#define _IOERR 32 /* error flag */
#define _IOSTRG 64
#define _IORW 128
#define NULL 0 /* null pointer value */
#define FILE struct _iobuf /* shorthand */
#define EOF (-1) /* end-of-file code */
#define stdin (&_iob[0]) /* standard input file pointer */
#define stdout (&_iob[1]) /* standard output file pointer */
#define stderr (&_iob[2]) /* standard error file pointer */
#define getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&255:_filbf(p))
#define getchar() getc(stdin)
#define putc(c,p) (--(p)->_cnt>=0? ((int)(*(p)->_ptr++=(c))):_flsbf((c),p))
#define putchar(c) putc(c,stdout)
#define feof(p) (((p)->_flag&_IOEOF)!=0)
#define ferror(p) (((p)->_flag&_IOERR)!=0)
#define fileno(p) (p)->_file
#define rewind(fp) fseek(fp,0L,0)
#define fflush(fp) _flsbf(-1,fp)
FILE *fopen();
FILE *freopen();
long ftell();
char *fgets();
#define abs(x) ((x)<0?-(x):(x))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<=(b)?(a):(b))

33
Microsoft C v1/TINYMAIN.C Normal file
View File

@ -0,0 +1,33 @@
/**
*
* This module defines a version of _main which processes the
* command line for arguments but does not open "stdin", "stdout",
* and "stderr". Since these files are not opened, the library
* functions "printf" and "scanf" will not work; however, the
* console functions "cprintf" and "cscanf" can be used instead.
*
**/
#include "CTYPE.H"
#define MAXARG 32 /* maximum command line arguments */
_main(line)
char *line;
{
static int argc = 0;
static char *argv[MAXARG];
while (isspace(*line)) line++; /* find program name */
while (*line != '\0' && argc < MAXARG)
{ /* get command line parameters */
argv[argc++] = line;
while (*line != '\0' && isspace(*line) == 0) line++;
if (*line == '\0') break;
*line++ = '\0';
while (isspace(*line)) line++;
}
main(argc, argv); /* call main function */
_exit(0);
}
break;
*line++ = '\0';

33
Microsoft C v1/e.c Normal file
View File

@ -0,0 +1,33 @@
/*#include <string.h>*/
#include <stdio.h>
/*#include <stdlib.h> */
#define DIGITS_TO_FIND 200 /*9009*/
int main() {
int N = DIGITS_TO_FIND;
char buf[ 128 ];
int x = 0;
int a[ DIGITS_TO_FIND ];
int n;
for (n = N - 1; n > 0; --n) {
a[n] = 1;
}
a[1] = 2, a[0] = 0;
while (N > 9) {
n = N--;
while (--n) {
a[n] = x % n;
x = 10 * a[n-1] + x/n;
}
printf("%d", x);
}
printf( "\ndone\n" );
return 0;
}

8
Microsoft C v1/m.bat Normal file
View File

@ -0,0 +1,8 @@
rem errorlevel can't be used because all 3 apps use the value-less cp/m exit function
ntvdm mc1 %1
ntvdm mc2 %1
ntvdm link %1 + c + gettm,, %1.map, mc

99
Microsoft C v1/tap.c Normal file
View File

@ -0,0 +1,99 @@
#include <stdio.h>
/*
#include <time.h>
#include <stdlib.h>
*/
#ifndef __max
#define __max( a, b ) (a) > (b) ? a : b
#define __min( a, b ) (a) < (b) ? a : b
#endif
typedef /*unsigned*/ long ulong;
ulong gcd( m, n ) ulong m, n;
{
ulong a = 0;
ulong b = __max( m, n );
ulong r = __min( m, n );
while ( 0 != r )
{
a = b;
b = r;
r = a % b;
}
return b;
}
/*
ulong randi()
{
return (ulong) rand() | ( ( (ulong) rand() ) << 16 );
}
*/
/* https://en.wikipedia.org/wiki/Ap%C3%A9ry%27s_theorem */
int first_implementation()
{
ulong total = 1000;
ulong i, iq;
double sofar = 0.0;
ulong prev = 1;
for ( i = 1; i <= total; i++ )
{
iq = i * i * i;
sofar += (double) 1.0 / (double) ( iq );
/*printf( "i, iq, and sofar: %lu, %lu, %lf\n", i, iq, sofar );*/
if ( i == ( prev * 10 ) )
{
prev = i;
printf( " at %12lu iterations: %lf\n", i, sofar );
fflush( stdout );
}
}
}
int main()
{
ulong totalEntries = 100000;
ulong i, prev, totalCoprimes, greatest, a, b, c;
printf( "starting, should tend towards 1.2020569031595942854...\n" );
printf( "first implementation...\n" );
first_implementation();
/* no rand
printf( "second implementation...\n" );
totalCoprimes = 0;
prev = 1;
for ( i = 1; i <= totalEntries; i++ )
{
a = randi();
b = randi();
c = randi();
greatest = gcd( a, gcd( b, c ) );
if ( 1 == greatest )
totalCoprimes++;
if ( i == ( prev * 10 ) )
{
prev = i;
printf( " at %12lu iterations: %lf\n", i, (double) i / (double) totalCoprimes );
fflush( stdout );
}
}
*/
printf( "done\n" );
return 1202;
}

171
Microsoft C v1/tm.c Normal file
View File

@ -0,0 +1,171 @@
#include <stdio.h>
#ifdef AZTEC86
#include <stdlib.h>
#endif
#ifdef HISOFTC
#include <stdlib.h>
#endif
#define OLDMSC
#ifdef OLDMSC
#define unsigned
#define void int
#endif
#ifdef WATCOM
#include <malloc.h>
#include <process.h>
#endif
#ifdef powerc
#define allocs 50
#else
#ifdef HISOFTC
#define allocs 66 /* not enough RAM with hisoft to go higher */
#else
/* most c runtimes work up to 69, but use 66 to have a consistent benchmark */
#define allocs 66
#endif
#endif
int logging = 1;
char * memset_x( p, v, c ) char * p; int v; int c;
{
unsigned char * pc = (unsigned char *) p;
unsigned char val = (unsigned char) ( v & 0xff );
int i;
if ( 0 == p )
{
printf( "request to memset a null pointer\n" );
exit( 1 );
}
if ( logging )
#ifdef CPMTIME
printf( " memset p %u, v %d, val %x, c %d\n", p, v, val, c );
#else
#ifdef HISOFTC
printf( " memset p %u, v %d, val %x, c %d\n", p, v, val, c );
#else
printf( " memset p %p, v %d, val %x, c %d\n", p, v, val, c );
#endif
#endif
for ( i = 0; i < c; i++ )
*pc++ = val;
return p;
}
void chkmem( p, v, c ) char * p; int v; int c;
{
unsigned char * pc = (unsigned char *) p;
unsigned char val = (unsigned char) ( v & 0xff );
int i;
if ( 0 == p )
{
printf( "request to chkmem a null pointer\n" );
exit( 1 );
}
for ( i = 0; i < c; i++ )
{
if ( *pc != val )
{
#ifdef CPMTIME
printf( "memory isn't as expected! p %u, v %d, c %d, *pc %d\n",p, v, c, *pc );
#else
printf( "memory isn't as expected! p %p, v %d, c %d, *pc %d\n",p, v, c, *pc );
#endif
exit( 1 );
}
pc++;
}
}
int main( argc, argv ) int argc; char * argv[];
{
int i, cb, c_cb, j;
char * pc;
char * ap[ allocs ];
logging = ( argc > 1 );
pc = argv[ 0 ]; /* evade compiler warning */
for ( j = 0; j < 10; j++ )
{
if ( logging )
printf( "in alloc mode\n" );
for ( i = 0; i < allocs; i++ )
{
cb = 8 + ( i * 10 );
c_cb = cb + 5;
if ( logging )
printf( " i, cb: %d %d\n", i, cb );
pc = (char *) calloc( c_cb, 1 );
chkmem( pc, 0, c_cb );
memset_x( pc, 0xcc, c_cb );
ap[ i ] = (char *) malloc( cb );
memset_x( ap[ i ], 0xaa, cb );
chkmem( pc, 0xcc, c_cb );
free( pc );
}
if ( logging )
printf( "in free mode, even first\n" );
for ( i = 0; i < allocs; i += 2 )
{
cb = 8 + ( i * 10 );
c_cb = cb + 3;
if ( logging )
printf( " i, cb: %d %d\n", i, cb );
pc = (char *) calloc( c_cb, 1 );
chkmem( pc, 0, c_cb );
memset_x( pc, 0xcc, c_cb );
chkmem( ap[ i ], 0xaa, cb );
memset_x( ap[ i ], 0xff, cb );
free( ap[ i ] );
chkmem( pc, 0xcc, c_cb );
free( pc );
}
if ( logging )
printf( "in free mode, now odd\n" );
for ( i = 1; i < allocs; i += 2 )
{
cb = 8 + ( i * 10 );
c_cb = cb + 7;
if ( logging )
printf( " i, cb: %d %d\n", i, cb );
pc = (char *) calloc( c_cb, 1 );
chkmem( pc, 0, c_cb );
memset_x( pc, 0xcc, c_cb );
chkmem( ap[ i ], 0xaa, cb );
memset_x( ap[ i ], 0xff, cb );
free( ap[ i ] );
chkmem( pc, 0xcc, c_cb );
free( pc );
}
}
printf( "success\n" );
return 0;
}

46
Microsoft C v1/tpi.c Normal file
View File

@ -0,0 +1,46 @@
#include <stdio.h>
#define HIGH_MARK 500 /* 2800 */
static long r[HIGH_MARK + 1];
int main() {
long i, k, c;
long b, d;
long iter;
int iterations = 1;
for ( iter = 0; iter < iterations; iter++ ) {
c = 0;
for (i = 0; i < HIGH_MARK; i++) {
r[i] = 2000;
}
for (k = HIGH_MARK; k > 0; k -= 14) {
d = 0;
i = k;
for (;;) {
d += r[i] * 10000;
b = 2 * i - 1;
r[i] = d % b;
d /= b;
i--;
if (i == 0) break;
d *= i;
}
if ( iter == ( iterations - 1 ) )
{
printf( "%.4d", c + d / 10000 );
fflush( stdout );
}
c = d % 10000;
}
}
printf( "\n" );
return 0;
}

545
Microsoft C v1/ttt.c Normal file
View File

@ -0,0 +1,545 @@
/*
This version builds with old compilers including:
Aztec C 1.06 for 8080 & Z80 on CP/M.
Microsoft C Compiler V1.04 for 8086 on DOS. (This is Lattice C)
Microsoft C Compiler V2.03 for 8086 on DOS. (Still Lattice C)
Microsoft C Compiler V3.00 for 8086 on DOS.
QuickC 1.0
Turbo C 2.0
The syntax is old and reminds me of 7th grade summer vacation.
Much of this code is awkward to satisfy the lowest common denominator of many compilers.
unsigned long isn't supported in many older compilers, so long is used instead.
Early DOS and CP/M require register variabes to be int, not char or other types.
The perf improvement of using register-int instead of stack-char is worth it.
*/
#define LINT_ARGS
#include <stdio.h>
#ifdef DOSTIME
#include <time.h>
#include <dos.h>
#endif
#define true 1
#define false 0
/* Function Pointers are the fastest implementation for almost every compiler */
#define UseFunPointers 1
#define UseWinner2 2
#define UseLookForWinner 3
#define WinMethod UseFunPointers
#define ABPrune true /* alpha beta pruning */
#define WinLosePrune true /* stop early on win/lose */
#define ScoreWin 6
#define ScoreTie 5
#define ScoreLose 4
#define ScoreMax 9
#define ScoreMin 2
#define DefaultIterations 100
#define PieceX 1
#define PieceO 2
#define PieceBlank 0
typedef char ttype; /* 8-bit and 16-bit cpus do best with char aside from register in locals */
int g_Iterations = DefaultIterations;
ttype g_board[ 9 ];
#if WinMethod == UseFunPointers
ttype pos0func()
{
/* using "register int" instead of "ttype" for x is faster on 8086 and Z80 */
register int x = g_board[0];
if ( ( x == g_board[1] && x == g_board[2] ) ||
( x == g_board[3] && x == g_board[6] ) ||
( x == g_board[4] && x == g_board[8] ) )
return x;
return PieceBlank;
}
ttype pos1func()
{
register int x = g_board[1];
if ( ( x == g_board[0] && x == g_board[2] ) ||
( x == g_board[4] && x == g_board[7] ) )
return x;
return PieceBlank;
}
ttype pos2func()
{
register int x = g_board[2];
if ( ( x == g_board[0] && x == g_board[1] ) ||
( x == g_board[5] && x == g_board[8] ) ||
( x == g_board[4] && x == g_board[6] ) )
return x;
return PieceBlank;
}
ttype pos3func()
{
register int x = g_board[3];
if ( ( x == g_board[4] && x == g_board[5] ) ||
( x == g_board[0] && x == g_board[6] ) )
return x;
return PieceBlank;
}
ttype pos4func()
{
register int x = g_board[4];
if ( ( x == g_board[0] && x == g_board[8] ) ||
( x == g_board[2] && x == g_board[6] ) ||
( x == g_board[1] && x == g_board[7] ) ||
( x == g_board[3] && x == g_board[5] ) )
return x;
return PieceBlank;
}
ttype pos5func()
{
register int x = g_board[5];
if ( ( x == g_board[3] && x == g_board[4] ) ||
( x == g_board[2] && x == g_board[8] ) )
return x;
return PieceBlank;
}
ttype pos6func()
{
register int x = g_board[6];
if ( ( x == g_board[7] && x == g_board[8] ) ||
( x == g_board[0] && x == g_board[3] ) ||
( x == g_board[4] && x == g_board[2] ) )
return x;
return PieceBlank;
}
ttype pos7func()
{
register int x = g_board[7];
if ( ( x == g_board[6] && x == g_board[8] ) ||
( x == g_board[1] && x == g_board[4] ) )
return x;
return PieceBlank;
}
ttype pos8func()
{
register int x = g_board[8];
if ( ( x == g_board[6] && x == g_board[7] ) ||
( x == g_board[2] && x == g_board[5] ) ||
( x == g_board[0] && x == g_board[4] ) )
return x;
return PieceBlank;
}
typedef ttype pfunc_t();
pfunc_t * winner_functions[9] =
{
pos0func,
pos1func,
pos2func,
pos3func,
pos4func,
pos5func,
pos6func,
pos7func,
pos8func,
};
#endif
#if WinMethod == UseWinner2
ttype winner2( move ) ttype move;
{
register int x; /* faster than ttype x on the stack */
switch( move ) /* msc v3 from 1985 generates a jump table! */
{
case 0:
{
x = g_board[ 0 ];
if ( ( ( x == g_board[1] ) && ( x == g_board[2] ) ) ||
( ( x == g_board[3] ) && ( x == g_board[6] ) ) ||
( ( x == g_board[4] ) && ( x == g_board[8] ) ) )
return x;
break;
}
case 1:
{
x = g_board[ 1 ];
if ( ( ( x == g_board[0] ) && ( x == g_board[2] ) ) ||
( ( x == g_board[4] ) && ( x == g_board[7] ) ) )
return x;
break;
}
case 2:
{
x = g_board[ 2 ];
if ( ( ( x == g_board[0] ) && ( x == g_board[1] ) ) ||
( ( x == g_board[5] ) && ( x == g_board[8] ) ) ||
( ( x == g_board[4] ) && ( x == g_board[6] ) ) )
return x;
break;
}
case 3:
{
x = g_board[ 3 ];
if ( ( ( x == g_board[4] ) && ( x == g_board[5] ) ) ||
( ( x == g_board[0] ) && ( x == g_board[6] ) ) )
return x;
break;
}
case 4:
{
x = g_board[ 4 ];
if ( ( ( x == g_board[0] ) && ( x == g_board[8] ) ) ||
( ( x == g_board[2] ) && ( x == g_board[6] ) ) ||
( ( x == g_board[1] ) && ( x == g_board[7] ) ) ||
( ( x == g_board[3] ) && ( x == g_board[5] ) ) )
return x;
break;
}
case 5:
{
x = g_board[ 5 ];
if ( ( ( x == g_board[3] ) && ( x == g_board[4] ) ) ||
( ( x == g_board[2] ) && ( x == g_board[8] ) ) )
return x;
break;
}
case 6:
{
x = g_board[ 6 ];
if ( ( ( x == g_board[7] ) && ( x == g_board[8] ) ) ||
( ( x == g_board[0] ) && ( x == g_board[3] ) ) ||
( ( x == g_board[4] ) && ( x == g_board[2] ) ) )
return x;
break;
}
case 7:
{
x = g_board[ 7 ];
if ( ( ( x == g_board[6] ) && ( x == g_board[8] ) ) ||
( ( x == g_board[1] ) && ( x == g_board[4] ) ) )
return x;
break;
}
case 8:
{
x = g_board[ 8 ];
if ( ( ( x == g_board[6] ) && ( x == g_board[7] ) ) ||
( ( x == g_board[2] ) && ( x == g_board[5] ) ) ||
( ( x == g_board[0] ) && ( x == g_board[4] ) ) )
return x;
break;
}
}
return PieceBlank;
} /*winner2*/
#endif
#if WinMethod == UseLookForWinner
ttype LookForWinner()
{
register int p = g_board[0]; /* faster as register int than ttype on 8086 and Z80 */
if ( PieceBlank != p )
{
if ( p == g_board[1] && p == g_board[2] )
return p;
if ( p == g_board[3] && p == g_board[6] )
return p;
}
p = g_board[3];
if ( PieceBlank != p && p == g_board[4] && p == g_board[5] )
return p;
p = g_board[6];
if ( PieceBlank != p && p == g_board[7] && p == g_board[8] )
return p;
p = g_board[1];
if ( PieceBlank != p && p == g_board[4] && p == g_board[7] )
return p;
p = g_board[2];
if ( PieceBlank != p && p == g_board[5] && p == g_board[8] )
return p;
p = g_board[4];
if ( PieceBlank != p )
{
if ( ( p == g_board[0] ) && ( p == g_board[8] ) )
return p;
if ( ( p == g_board[2] ) && ( p == g_board[6] ) )
return p;
}
return PieceBlank;
} /*LookForWinner*/
#endif
int g_IMoves = 0;
ttype MinMax( alpha, beta, depth, move ) ttype alpha; ttype beta; ttype depth; ttype move;
{
ttype pieceMove, score; /* better perf with char than int. out of registers so use stack */
register int p, value; /* better perf with these as an int on Z80, 8080, and 8086 */
g_IMoves++;
if ( depth >= 4 )
{
#if WinMethod == UseFunPointers
p = ( * winner_functions[ move ] )();
#endif
#if WinMethod == UseWinner2
p = winner2( move );
#endif
#if WinMethod == UseLookForWinner
p = LookForWinner();
#endif
if ( PieceBlank != p )
{
if ( PieceX == p )
return ScoreWin;
return ScoreLose;
}
if ( 8 == depth )
return ScoreTie;
}
if ( depth & 1 )
{
value = ScoreMin;
pieceMove = PieceX;
}
else
{
value = ScoreMax;
pieceMove = PieceO;
}
for ( p = 0; p < 9; p++ )
{
if ( PieceBlank == g_board[ p ] )
{
g_board[p] = pieceMove;
score = MinMax( alpha, beta, depth + 1, p );
g_board[p] = PieceBlank;
if ( depth & 1 )
{
#if WinLosePrune /* #if statements must be in first column for MS C 1.0 */
if ( ScoreWin == score )
return ScoreWin;
#endif
if ( score > value )
{
value = score;
#if ABPrune
if ( value >= beta )
return value;
if ( value > alpha )
alpha = value;
#endif
}
}
else
{
#if WinLosePrune
if ( ScoreLose == score )
return ScoreLose;
#endif
if ( score < value )
{
value = score;
#if ABPrune
if ( value <= alpha )
return value;
if ( value < beta )
beta = value;
#endif
}
}
}
}
return value;
} /*MinMax*/
long g_Moves = 0;
int FindSolution( position ) ttype position;
{
register int i;
for ( i = 0; i < 9; i++ )
g_board[ i ] = PieceBlank;
g_board[ position ] = PieceX;
for ( i = 0; i < g_Iterations; i++ )
{
g_IMoves = 0;
MinMax( ScoreMin, ScoreMax, 0, position );
g_Moves += g_IMoves; /* do the 4-byte long addition once per loop to save work */
}
return 0;
} /*FindSolution*/
#ifdef CPMTIME
struct CPMTimeValue
{
int h, m, s, l;
};
void print_time_now()
{
/* This CP/M BDOS call of 105 is only implemented in NTVCM -- it's not a standard CP/M 2.2 call */
struct CPMTimeValue t;
t.h = t.m = t.s = t.l = 0;
bdos( 105, &t );
printf( "current time: %02d:%02d:%02d.%02d\n", t.h, t.m, t.s, t.l );
} /*print_time_now*/
long get_ms()
{
/* This CP/M BDOS call of 105 is only implemented in NTVCM -- it's not a standard CP/M 2.2 call */
long h, m, s, l;
struct CPMTimeValue t;
t.h = t.m = t.s = t.l = 0;
bdos( 105, &t );
h = t.h;
m = t.m;
s = t.s;
l = t.l;
return h * 3600000 + m * 60000 + s * 1000 + l * 10;
} /*get_ms*/
#else /* no elif with old compilers */
#ifdef DOSTIME
void print_time_now()
{
/* Make a DOS interrupt call to get the time */
union REGS wrIn, wrOut;
wrIn.h.ah = 0x2c;
intdos( &wrIn, &wrOut );
printf( "current time: %02d:%02d:%02d.%02d\n", wrOut.h.ch, wrOut.h.cl, wrOut.h.dh, wrOut.h.dl );
fflush( stdout );
} /*print_time_now*/
long get_ms()
{
/* this function takes about 3 milliseconds on the original IBM PC */
long h, m, s, l;
union REGS wrIn, wrOut;
wrIn.h.ah = 0x2c;
intdos( &wrIn, &wrOut );
h = wrOut.h.ch;
m = wrOut.h.cl;
s = wrOut.h.dh;
l = wrOut.h.dl;
return h * 3600000 + m * 60000 + s * 1000 + l * 10;
} /*get_ms*/
#else
/* must do this on actual CP/M machines */
int print_time_now() { return 0; }
long get_ms() { return 0; }
#endif
#endif
/* see gettm.asm in masm folder for function to get current time */
extern long gettm();
long getms()
{
long r, h, m, s, l;
r = gettm();
h = ( r >> 24 ) & 0xff;
m = ( r >> 16 ) & 0xff;
s = ( r >> 8 ) & 0xff;
l = ( r >> 0 ) & 0xff;
return h * 3600000 + m * 60000 + s * 1000 + l * 10;
} /*getms*/
int main( argc, argv ) int argc; char * argv[];
{
long start_time, end_time;
if ( 2 == argc )
sscanf( argv[ 1 ], "%d", &g_Iterations ); /* no atoi in MS C 1.0 */
start_time = getms();
FindSolution( 0 );
FindSolution( 1 );
FindSolution( 4 );
end_time = getms();
printf( "runtime in ms: %ld\n", end_time - start_time );
printf( "move count: %ld\n", g_Moves ); /* 6493 * g_Iterations */
printf( "iteration count: %d\n", g_Iterations );
printf( "method: %s\n",
( WinMethod == UseFunPointers ) ? "function pointers" :
( WinMethod == UseWinner2 ) ? "winner2" :
( WinMethod == UseLookForWinner ) ? "look for winner" :
"invalid method" );
return 0;
} /*main*/