diff --git a/Microsoft C v203/CAT.C b/Microsoft C v203/CAT.C new file mode 100644 index 0000000..f1422e6 --- /dev/null +++ b/Microsoft C v203/CAT.C @@ -0,0 +1,33 @@ + /* (This program is from p. 154 of the Kernighan and Ritchie text */ +#include + +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 \ No newline at end of file diff --git a/Microsoft C v203/CC.BAT b/Microsoft C v203/CC.BAT new file mode 100644 index 0000000..c5c129f --- /dev/null +++ b/Microsoft C v203/CC.BAT @@ -0,0 +1,9 @@ +mc1 %1% +if errorlevel 1 goto skip +mc2 %1% +if errorlevel 1 goto skip +link %1% + cs,, nul.map, mcs +if errorlevel 1 goto skip +del %1%.obj +:skip +  \ No newline at end of file diff --git a/Microsoft C v203/CONIO.C b/Microsoft C v203/CONIO.C new file mode 100644 index 0000000..7f0298c --- /dev/null +++ b/Microsoft C v203/CONIO.C @@ -0,0 +1,121 @@ +/** +* +* 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 LC.LIB) call the functions "putch", "getch", +* and "ungetch". +* +**/ +#define BDOS_IN 8 /* input function for "getch" */ +#define BDOS_INE 1 /* input function for "getche" */ +#define BDOS_OUT 6 /* output function for "putch" */ +#define BDOS_CKS 11 /* check keyboard status for "kbhit" */ + +static char pushback = 0; /* character save for "ungetch" */ +/**/ +/** +* +* name getch -- get character from console +* getche - get character from console and echo it +* +* synopsis c = getch(); +* char c; input character +* +* description These functions obtain the next character typed at +* the console or, if one was pushed back via "ungetch", +* returns the previously pushed back character. +* +**/ +getch() +{ +char c; + +if(pushback) + { + c = pushback; + pushback = 0; + return(c); + } +return(bdos(BDOS_IN)); +} + +getche() +{ +char c; + +if(pushback) + { + c = pushback; + pushback = 0; + return(c); + } +return(bdos(BDOS_INE)); +} +/**/ +/** +* +* 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 kbhit -- check if character has been typed at console +* +* synopsis status = kbhit(); +* int status; 1 if character typed, else 0 +* +* description This function checks to see if a character has been +* typed at the user's console since the completion of +* the last read operation. The character typed can +* be obtained by a "getch" call. +* +* returns 0 if no character has been typed +* 1 if a character is waiting to be read +* +**/ +kbhit() +{ +return(bdos(BDOS_CKS) != 0); +} diff --git a/Microsoft C v203/CS.OBJ b/Microsoft C v203/CS.OBJ new file mode 100644 index 0000000..07fd46d Binary files /dev/null and b/Microsoft C v203/CS.OBJ differ diff --git a/Microsoft C v203/CTYPE.H b/Microsoft C v203/CTYPE.H new file mode 100644 index 0000000..03f3487 --- /dev/null +++ b/Microsoft C v203/CTYPE.H @@ -0,0 +1,53 @@ +/** +* +* 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)&127)==0x5f)) +#define iscsymf(c) (isalpha(c)||(((c)&127)==0x5f)) + +#define toupper(c) (islower(c)?((c)-('a'-'A')):(c)) +#define tolower(c) (isupper(c)?((c)+('a'-'A')):(c)) +#define toascii(c) ((c)&127) + \ No newline at end of file diff --git a/Microsoft C v203/DM8086.H b/Microsoft C v203/DM8086.H new file mode 100644 index 0000000..419f922 --- /dev/null +++ b/Microsoft C v203/DM8086.H @@ -0,0 +1,24 @@ +/** +* +* The following definitions specify which memory addressing model is in use +* for wacky chips of the Intel 8086 variety. +* +* I8086S 64K program, 64K data +* I8086D 64K program, 1M data +* I8086P 1M program, 64K data +* I8086L 1M program, 1M data +* +*/ +#define I8086D 1 + +/** +* +* The following definitions indicate which type of integer has the same size +* as a pointer. +* +* SPTR defined if sizeof(pointer) == sizeof(short int) +* LPTR defined if sizeof(pointer) == sizeof(long int) +* +*/ +#define LPTR 1 + \ No newline at end of file diff --git a/Microsoft C v203/DOS.H b/Microsoft C v203/DOS.H new file mode 100644 index 0000000..efa967b --- /dev/null +++ b/Microsoft C v203/DOS.H @@ -0,0 +1,258 @@ +/** +* +* This header file supplies information needed to interface with the +* particular operating system and C compiler being used. +* +**/ + + +/** +* +* The following symbols define which processor is being used. +* +* I8080 Intel 8080 +* I8085 Intel 8085 +* Z80 Zilog Z80 +* I8086 Intel 8086 or 8088 +* M68000 Motorola 68000 +* GA16 General Automation 16-bit mini +* IBMPC IBM Personal Computer (also sets I8086) +*/ +#define IBMPC 1 + +#ifdef IBMPC +#define I8086 1 +#endif + +#ifdef I8086 +#include "m8086.h" +#endif + +/** +* +* The following symbols specify which operating system is being used. +* +* CPM Any CP/M OS +* CPM80 CP/M for Intel 8080 or Zilog Z80 +* CPM86 CP/M for Intel 8086 +* CPM68 CP/M for Motorola 68000 +* MSDOS Microsoft's MSDOS +* MSDOS1 MSDOS Version 1 (also sets MSDOS) +* MSDOS2 MSDOS Version 2 (also sets MSDOS) +* +* Note: CPM will be set to 1 for any of the above. +* +* UNIX "Standard" UNIX +* QUNIX Quantum's QUNIX OS +* MIBS General Automation's MIBS OS +* OASIS OASIS OS +* PICK PICK OS +* +*/ +#define MSDOS 1 + +#ifdef MSDOS +#include "msdos.h" +#endif + +#ifdef CPM80 +#define CPM 1 +#endif +#ifdef CPM86 +#define CPM 1 +#endif +#ifdef CPM68 +#define CPM 1 +#endif +#ifdef MSDOS +#define CPM 1 +#endif + + +/** +* +* The following definitions specify the particular C compiler being used. +* +* LATTICE Lattice C compiler +* BDS BDS C compiler +* BTL Bell Labs C compiler or equivalent +* MANX MANX Aztec C compiler +* +*/ +#define LATTICE 1 + + + +/** +* +* The following type definitions take care of the particularly nasty +* machine dependency caused by the unspecified handling of sign extension +* in the C language. When converting "char" to "int" some compilers +* will extend the sign, while others will not. Both are correct, and +* the unsuspecting programmer is the loser. For situations where it +* matters, the new type "byte" is equivalent to "unsigned char". +* +*/ +#ifdef LATTICE +typedef char byte; +#endif + +#ifdef BDS +#define byte char +#endif + +#ifdef BTL +typedef unsigned char byte; +#endif + +#ifdef MANX +#define byte char +#endif + +/** +* +* Miscellaneous definitions +* +*/ +#define SECSIZ 128 /* disk sector size */ +#ifdef CPM +#define DMA (char *)0x80 /* disk buffer address */ +#endif + +/** +* +* The following structure is a File Control Block. Operating systems +* with CPM-like characteristics use the FCB to store information about +* a file while it is open. +* +*/ +struct FCB + { + char fcbdrv; /* drive code */ + char fcbnam[8]; /* file name */ + char fcbext[3]; /* file name extension */ +#ifdef MSDOS + short fcbcb; /* current block number */ + short fcblrs; /* logical record size */ + long fcblfs; /* logical file size */ + short fcbdat; /* create/change date */ + char fcbsys[10]; /* reserved */ + char fcbcr; /* current record number */ + long fcbrec; /* random record number */ +#else + char fcbexn; /* extent number */ + char fcbs1; /* reserved */ + char fcbs2; /* reserved */ + char fcbrc; /* record count */ + char fcbsys[16]; /* reserved */ + char fcbcr; /* current record number */ + short fcbrec; /* random record number */ + char fcbovf; /* random record overflow */ +#endif + }; + +#define FCBSIZ sizeof(struct FCB) + +/** +* +* The following symbols define the sizes of file names and node names. +* +*/ +#ifdef CPM +#define FNSIZE 16 /* maximum file node name size */ +#define FMSIZE 16 /* maximum file name size */ +#endif + +#ifdef MSDOS2 +#define FNSIZE 16 +#define FMSIZE 64 +#endif + +#ifdef UNIX +#define FNSIZE 16 +#define FMSIZE 64 +#endif + + +/** +* +* The following structures define the 8086 registers that are passed to +* various low-level operating system service functions. +* +*/ +#ifdef I8086 +struct XREG + { + short ax,bx,cx,dx,si,di; + }; + +struct HREG + { + byte al,ah,bl,bh,cl,ch,dl,dh; + }; + +union REGS + { + struct XREG x; + struct HREG h; + }; + +struct SREGS + { + short es,cs,ss,ds; + }; +#endif + +/** +* +* The following symbols define the code numbers for the various service +* functions. +* +*/ +#ifdef MSDOS +#define SVC_DATE 0x2a /* get date */ +#define SVC_TIME 0x2c /* get time */ +#endif + +/** +* +* The following codes are used to open files in various modes. +* +*/ +#ifdef LATTICE +#define OPENR 0x8000 /* open for reading */ +#define OPENW 0x8001 /* open for writing */ +#define OPENU 0x8002 /* open for read/write */ +#define OPENC 0x8001 /* create and open for writing */ +#else +#define OPENR 0 +#define OPENW 1 +#define OPENU 2 +#endif + +/** +* +* The following codes are returned by the low-level operating system service +* calls. They are usually placed into _oserr by the OS interface functions. +* +*/ +#if MSDOS2 +#define E_FUNC 1 /* invalid function code */ +#define E_FNF 2 /* file not found */ +#define E_PNF 3 /* path not found */ +#define E_NMH 4 /* no more file handles */ +#define E_ACC 5 /* access denied */ +#define E_IFH 6 /* invalid file handle */ +#define E_MCB 7 /* memory control block problem */ +#define E_MEM 8 /* insufficient memory */ +#define E_MBA 9 /* invalid memory block address */ +#define E_ENV 10 /* invalid environment */ +#define E_FMT 11 /* invalid format */ +#define E_IAC 12 /* invalid access code */ +#define E_DATA 13 /* invalid data */ +#define E_DRV 15 /* invalid drive code */ +#define E_RMV 16 /* remove denied */ +#define E_DEV 17 /* invalid device */ +#define E_NMF 18 /* no more files */ +#endif + \ No newline at end of file diff --git a/Microsoft C v203/ERROR.H b/Microsoft C v203/ERROR.H new file mode 100644 index 0000000..ca92e1f Binary files /dev/null and b/Microsoft C v203/ERROR.H differ diff --git a/Microsoft C v203/FCNTL.H b/Microsoft C v203/FCNTL.H new file mode 100644 index 0000000..b5f8d8f --- /dev/null +++ b/Microsoft C v203/FCNTL.H @@ -0,0 +1,28 @@ +/** +* +* The following symbols are used for the "open" and "creat" functions. +* +**/ +#define O_RDONLY 0 /* Read-only value (right byte of mode word) */ +#define O_WRONLY 1 /* Write-only value */ +#define O_RDWR 2 /* Read-write value */ + +#define O_NDELAY 4 /* Non-blocking I/O flag */ +#define O_APPEND 8 /* Append mode flag */ +#define O_CREAT 0x0100 /* File creation flag */ +#define O_TRUNC 0x200 /* File truncation flag */ +#define O_EXCL 0x400 /* Exclusive access flag */ + +#define O_RAW 0x8000 /* Raw I/O flag (Lattice feature) */ + +/** +* +* The following symbols are used for the "fcntl" function. +* +*/ +#define F_DUPFD 0 /* Duplicate file descriptor */ +#define F_GETFD 1 /* Get file descriptor flags */ +#define F_SETFD 2 /* Set file descriptor flags */ +#define F_GETFL 3 /* Get file flags */ +#define F_SETFL 4 /* Set file flags */ + \ No newline at end of file diff --git a/Microsoft C v203/FTOC.C b/Microsoft C v203/FTOC.C new file mode 100644 index 0000000..cf4a1a6 --- /dev/null +++ b/Microsoft C v203/FTOC.C @@ -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 + \ No newline at end of file diff --git a/Microsoft C v203/FXU.C b/Microsoft C v203/FXU.C new file mode 100644 index 0000000..0980474 --- /dev/null +++ b/Microsoft C v203/FXU.C @@ -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 \ No newline at end of file diff --git a/Microsoft C v203/FXU.EXE b/Microsoft C v203/FXU.EXE new file mode 100644 index 0000000..0b023ea Binary files /dev/null and b/Microsoft C v203/FXU.EXE differ diff --git a/Microsoft C v203/IOS1.H b/Microsoft C v203/IOS1.H new file mode 100644 index 0000000..b005df8 --- /dev/null +++ b/Microsoft C v203/IOS1.H @@ -0,0 +1,53 @@ +/** +* +* The following structure is a UNIX file block that retains information about +* a file being accessed via the level 1 I/O functions. +*/ +struct UFB +{ +char ufbflg; /* flags */ +char ufbtyp; /* device type */ +#if MSDOS +#if MSDOS2 +int ufbfh; /* file handle */ +#else +struct FCB ufbfcb; /* file control block */ +#endif +#else +struct FAB + { + struct FCB fcb; /* file control block */ + char wf; /* buffer write flag */ + long fpos; /* file position */ + long eof; /* end of file */ + long peof; /* previous end of file */ + int bn; /* block number */ + char b[128]; /* block buffer */ + } + ufbfcb; +#endif +}; +#define NUFBS 20 /* number of UFBs defined */ + +/* +* +* UFB.ufbflg definitions +* +*/ +#define UFB_OP 0x80 /* file is open */ +#define UFB_RA 0x40 /* reading is allowed */ +#define UFB_WA 0x20 /* writing is allowed */ +#define UFB_NT 0x10 /* access file with no translation */ +#define UFB_AP 8 /* append mode flag */ +/* +* +* UFB.ufbtyp definitions +* +*/ +#define D_DISK 0 +#define D_CON 1 +#define D_PRN 2 +#define D_AUX 3 +#define D_NULL 4 + + \ No newline at end of file diff --git a/Microsoft C v203/LIB.EXE b/Microsoft C v203/LIB.EXE new file mode 100644 index 0000000..e49532a Binary files /dev/null and b/Microsoft C v203/LIB.EXE differ diff --git a/Microsoft C v203/LINK.EXE b/Microsoft C v203/LINK.EXE new file mode 100644 index 0000000..91d3ddb Binary files /dev/null and b/Microsoft C v203/LINK.EXE differ diff --git a/Microsoft C v203/LM8086.H b/Microsoft C v203/LM8086.H new file mode 100644 index 0000000..9d73107 --- /dev/null +++ b/Microsoft C v203/LM8086.H @@ -0,0 +1,24 @@ +/** +* +* The following definitions specify which memory addressing model is in use +* for wacky chips of the Intel 8086 variety. +* +* I8086S 64K program, 64K data +* I8086D 64K program, 1M data +* I8086P 1M program, 64K data +* I8086L 1M program, 1M data +* +*/ +#define I8086L 1 + +/** +* +* The following definitions indicate which type of integer has the same size +* as a pointer. +* +* SPTR defined if sizeof(pointer) == sizeof(short int) +* LPTR defined if sizeof(pointer) == sizeof(long int) +* +*/ +#define LPTR 1 + \ No newline at end of file diff --git a/Microsoft C v203/M8086.H b/Microsoft C v203/M8086.H new file mode 100644 index 0000000..2bafe78 Binary files /dev/null and b/Microsoft C v203/M8086.H differ diff --git a/Microsoft C v203/MAIN.C b/Microsoft C v203/MAIN.C new file mode 100644 index 0000000..f559c0e --- /dev/null +++ b/Microsoft C v203/MAIN.C @@ -0,0 +1,109 @@ +#include "dos.h" +#include "stdio.h" +#include "ctype.h" +#include "ios1.h" + +#define MAXARG 32 /* maximum command line arguments */ + +extern int _stack; +extern char _iname[],_oname[]; +extern struct UFB _ufbs[]; + +int argc; /* arg count */ +char *argv[MAXARG]; /* arg pointers */ + + +/** +* +* 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 arg1 arg2 ... +* +* and builds a list of pointers to each argument. The first +* pointer is to the program name. For some environments, the +* standard I/O files are also opened, using file names that +* were set up by the OS interface module XCMAIN. +* +**/ +_main(line) +char *line; +{ +char c; +#if (UNIX | MSDOS2) == 0 +FILE *fp0, *fp1, *fp2; +extern int _bufsiz; +char *getmem(); +#endif + +/* +* +* Build argument pointer list +* +*/ +for(argc = 0; argc < MAXARG; ) + { + while(isspace(*line)) line++; + if(*line == '\0') break; + argv[argc++] = line; + while((*line != '\0') && (isspace(*line) == 0)) line++; + c = *line; + *line++ = '\0'; + if(c == '\0') break; + } +/* +* +* Open standard files +* +*/ +#if (UNIX | MSDOS2) == 0 +fp0 = freopen(_iname,"r",stdin); +if(_oname[0] != '>') fp1 = freopen(_oname,"w",stdout); +else fp1 = freopen(&_oname[1],"a",stdout); +fp2 = freopen("","a",stderr); +if (fp2 == NULL) _exit(1); +if (fp0 == NULL) + { + fputs("Can't open stdin file\n", fp2); + exit(1); + } +setbuf(fp0, getmem(_bufsiz)); /* set stdin buffered */ +fp0->_flag &= ~_IOMYBUF; /* allow rlsmem if later set unbuff'd */ +if (fp1 == NULL) + { + fputs("Can't open stdout file\n", fp2); + exit(1); + } +#endif +#ifdef MSDOS2 +stdin->_file = 0; +stdin->_flag = _IOREAD; +stdout->_file = 1; +stdout->_flag = _IOWRT; +stderr->_file = 2; +stderr->_flag = _IOWRT | _IONBF; + +_ufbs[0].ufbflg = UFB_OP | UFB_RA; +_ufbs[1].ufbfh = 1; +_ufbs[1].ufbflg = UFB_OP | UFB_WA; +_ufbs[2].ufbfh = 2; +_ufbs[2].ufbflg = UFB_OP | UFB_WA; +if (_fgdi(1) & 0x80) stdout->_flag |= _IONBF; +#endif + + +/* +* +* Call user's main program +* +*/ +main(argc,argv); /* call main function */ +exit(0); +} + \ No newline at end of file diff --git a/Microsoft C v203/MC1.EXE b/Microsoft C v203/MC1.EXE new file mode 100644 index 0000000..f4bac11 Binary files /dev/null and b/Microsoft C v203/MC1.EXE differ diff --git a/Microsoft C v203/MC2.EXE b/Microsoft C v203/MC2.EXE new file mode 100644 index 0000000..df716ae Binary files /dev/null and b/Microsoft C v203/MC2.EXE differ diff --git a/Microsoft C v203/MCS.LIB b/Microsoft C v203/MCS.LIB new file mode 100644 index 0000000..9e6b706 Binary files /dev/null and b/Microsoft C v203/MCS.LIB differ diff --git a/Microsoft C v203/MM.C b/Microsoft C v203/MM.C new file mode 100644 index 0000000..b1c2e6f --- /dev/null +++ b/Microsoft C v203/MM.C @@ -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 + +#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; +} + + + diff --git a/Microsoft C v203/MSDOS.H b/Microsoft C v203/MSDOS.H new file mode 100644 index 0000000..a0e8df8 --- /dev/null +++ b/Microsoft C v203/MSDOS.H @@ -0,0 +1,8 @@ +/** +* +* This module contains definitions for MSDOS Version 2 +* +*/ +#define MSDOS2 1 + + \ No newline at end of file diff --git a/Microsoft C v203/OMD.EXE b/Microsoft C v203/OMD.EXE new file mode 100644 index 0000000..5c180e6 Binary files /dev/null and b/Microsoft C v203/OMD.EXE differ diff --git a/Microsoft C v203/PM8086.H b/Microsoft C v203/PM8086.H new file mode 100644 index 0000000..ff87178 --- /dev/null +++ b/Microsoft C v203/PM8086.H @@ -0,0 +1,24 @@ +/** +* +* The following definitions specify which memory addressing model is in use +* for wacky chips of the Intel 8086 variety. +* +* I8086S 64K program, 64K data +* I8086D 64K program, 1M data +* I8086P 1M program, 64K data +* I8086L 1M program, 1M data +* +*/ +#define I8086P 1 + +/** +* +* The following definitions indicate which type of integer has the same size +* as a pointer. +* +* SPTR defined if sizeof(pointer) == sizeof(short int) +* LPTR defined if sizeof(pointer) == sizeof(long int) +* +*/ +#define SPTR 1 + \ No newline at end of file diff --git a/Microsoft C v203/SIEVE.C b/Microsoft C v203/SIEVE.C new file mode 100644 index 0000000..2ea58b0 --- /dev/null +++ b/Microsoft C v203/SIEVE.C @@ -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); + } + \ No newline at end of file diff --git a/Microsoft C v203/SM8086.H b/Microsoft C v203/SM8086.H new file mode 100644 index 0000000..ac2c211 --- /dev/null +++ b/Microsoft C v203/SM8086.H @@ -0,0 +1,24 @@ +/** +* +* The following definitions specify which memory addressing model is in use +* for wacky chips of the Intel 8086 variety. +* +* I8086S 64K program, 64K data +* I8086D 64K program, 1M data +* I8086P 1M program, 64K data +* I8086L 1M program, 1M data +* +*/ +#define I8086S 1 + +/** +* +* The following definitions indicate which type of integer has the same size +* as a pointer. +* +* SPTR defined if sizeof(pointer) == sizeof(short int) +* LPTR defined if sizeof(pointer) == sizeof(long int) +* +*/ +#define SPTR 1 + \ No newline at end of file diff --git a/Microsoft C v203/STDIO.H b/Microsoft C v203/STDIO.H new file mode 100644 index 0000000..10f2af3 --- /dev/null +++ b/Microsoft C v203/STDIO.H @@ -0,0 +1,61 @@ +/** +* +* This header file defines the information used by the standard I/O +* package. +* +**/ +#define _BUFSIZ 512 /* standard buffer size */ +#define BUFSIZ 512 /* standard buffer size */ +#define _NFILE 20 /* maximum number of files */ + +struct _iobuf +{ +char *_ptr; /* current buffer pointer */ +int _rcnt; /* current byte count for reading */ +int _wcnt; /* current byte count for writing */ +char *_base; /* base address of I/O buffer */ +char _flag; /* control flags */ +char _file; /* file number */ +int _size; /* size of buffer */ +char _cbuff; /* single char buffer */ +char _pad; /* (pad to even number of bytes) */ +}; + +extern struct _iobuf _iob[_NFILE]; + +#define _IOREAD 1 /* read flag */ +#define _IOWRT 2 /* write flag */ +#define _IONBF 4 /* non-buffered flag */ +#define _IOMYBUF 8 /* private buffer flag */ +#define _IOEOF 16 /* end-of-file flag */ +#define _IOERR 32 /* error flag */ +#define _IOSTRG 64 +#define _IORW 128 /* read-write (update) flag */ + +#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)->_rcnt>=0? *(p)->_ptr++:_filbf(p)) +#define getchar() getc(stdin) +#define putc(c,p) (--(p)->_wcnt>=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)) + + \ No newline at end of file diff --git a/Microsoft C v203/TINYMAIN.C b/Microsoft C v203/TINYMAIN.C new file mode 100644 index 0000000..46abc5e --- /dev/null +++ b/Microsoft C v203/TINYMAIN.C @@ -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'; + \ No newline at end of file diff --git a/Microsoft C v203/e.c b/Microsoft C v203/e.c new file mode 100644 index 0000000..e748b7f --- /dev/null +++ b/Microsoft C v203/e.c @@ -0,0 +1,33 @@ +/*#include */ +#include +/*#include */ + +#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; +} diff --git a/Microsoft C v203/m.bat b/Microsoft C v203/m.bat new file mode 100644 index 0000000..e97ddfa --- /dev/null +++ b/Microsoft C v203/m.bat @@ -0,0 +1,11 @@ +rem errorlevel can't be used because all 3 apps use the value-less cp/m exit function + +del %1.exe 1>nul 2>nul + +ntvdm mc1 %1 + +ntvdm mc2 %1 + +ntvdm link %1 + cs + gettm,, %1.map, mcs + + diff --git a/Microsoft C v203/tm.c b/Microsoft C v203/tm.c new file mode 100644 index 0000000..5aec9e0 --- /dev/null +++ b/Microsoft C v203/tm.c @@ -0,0 +1,171 @@ +#include + +#ifdef AZTEC86 +#include +#endif + +#ifdef HISOFTC +#include +#endif + +#define OLDMSC +#ifdef OLDMSC +#define unsigned +#define void int +#endif + +#ifdef WATCOM +#include +#include +#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; +} diff --git a/Microsoft C v203/tphi.c b/Microsoft C v203/tphi.c new file mode 100644 index 0000000..fbd4b3f --- /dev/null +++ b/Microsoft C v203/tphi.c @@ -0,0 +1,31 @@ +#include + +#define unsigned + +typedef unsigned long uint32_t; + +int main() +{ + uint32_t limit = 40; + uint32_t prev2 = 1; + uint32_t prev1 = 1; + uint32_t next, i, last_shown = 0; + + printf( "should tend towards 1.61803398874989484820458683436563811772030\n" ); + + for ( i = 1; i <= limit; i++ ) + { + next = prev1 + prev2; + prev2 = prev1; + prev1 = next; + + if ( i == ( last_shown + 5 ) ) + { + last_shown = i; + printf( " at %2lu iterations: %lf\n", i, (double) prev1 / (double) prev2 ); + } + } + + printf( "done\n" ); + return 0; +} diff --git a/Microsoft C v203/tpi.c b/Microsoft C v203/tpi.c new file mode 100644 index 0000000..07055b0 --- /dev/null +++ b/Microsoft C v203/tpi.c @@ -0,0 +1,46 @@ +#include + +#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; +} diff --git a/Microsoft C v203/ttt.c b/Microsoft C v203/ttt.c new file mode 100644 index 0000000..6d4d2c2 --- /dev/null +++ b/Microsoft C v203/ttt.c @@ -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 + +#ifdef DOSTIME +#include +#include +#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*/ +