diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-03-29 06:19:21 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-04-23 06:51:22 +0300 |
commit | 92f964701d55ae3a7c2060da3a78fe6d3b665bcb (patch) | |
tree | 4deb210d56a018259411b2fd5f79743698b6b69b | |
parent | 93f61120ddba2093d85dbd09dff2deb42f0393e2 (diff) | |
download | videoteco-fork-92f964701d55ae3a7c2060da3a78fe6d3b665bcb.tar.gz |
MS-DOS real-mode (8086) port
It can be cross-compiled or compiled natively on 32-bit DOS
with OpenWatcom C v1.9.
Compiling on an 8086 might be possible later on - but we would
have to add support for some ancient ANSI C compiler.
-rw-r--r-- | Makefile.wcc | 41 | ||||
-rw-r--r-- | tecbuf.c | 8 | ||||
-rw-r--r-- | teccmd.c | 32 | ||||
-rw-r--r-- | tecmem.c | 2 | ||||
-rw-r--r-- | teco.c | 90 | ||||
-rw-r--r-- | teco.h | 52 | ||||
-rw-r--r-- | tecparse.c | 17 | ||||
-rw-r--r-- | tecterm.c | 45 |
8 files changed, 254 insertions, 33 deletions
diff --git a/Makefile.wcc b/Makefile.wcc new file mode 100644 index 0000000..21d1b8e --- /dev/null +++ b/Makefile.wcc @@ -0,0 +1,41 @@ +CC = $(%WATCOM)/binl64/wcc +LD = $(%WATCOM)/binl64/wlink + +# For the fastest code (C Guide, p.70): +# -onatx -oh -oi+ -ei -zp8 -0 -fpi87 +# Large data model: far code and data pointers +!ifdef DEBUG +# You can also -dDEBUG or even -dDEBUG1. +CFLAGS = -d2 +#-dDEBUG1 +LDFLAGS = debug all +!endif + +CFLAGS += -q -ze -j -os -0 -ml -bt=DOS @WCC_DEFS +LDFLAGS += format dos option map option stack=16k & + libpath $(%WATCOM)/lib286:$(%WATCOM)/lib286/dos + +.BEFORE +!ifndef %WATCOM + set WATCOM=/usr/bin/watcom +!endif + set include=$(%WATCOM)/h + set lib=$(%WATCOM)/lib286;$(%WATCOM)/lib286/dos + set WCC_DEFS=-dSTDC_HEADERS=1 -dHAVE_STDIO_H -dHAVE_CTYPE_H -dHAVE_ERRNO_H & + -dHAVE_STRING_H -dHAVE_STRINGS_H -dHAVE_FCNTL_H -dHAVE_IO_H & + -dHAVE_SYS_STAT_H -dHAVE_SIGNAL_H -dHAVE_STDLIB_H -dHAVE_UNISTD_H & + -dHAVE_STDINT_H -dHAVE_DIRECT_H -dHAVE_SBRK -dHAVE_STRCHR -dTERMCAP + +all : teco.exe .SYMBOLIC + +teco.exe : tecbuf.obj teccmd.obj tecdebug.obj tecdisp.obj tecexec.obj & + tecmem.obj teco.obj tecparse.obj tecstate.obj tecterm.obj tecundo.obj + set WLINK_OBJ=$(LDFLAGS) name $@ file { $< } + $(LD) @WLINK_OBJ + +.c.obj: + $(CC) $(CFLAGS) -fo=$@ $< + +clean: .SYMBOLIC + rm -f teco.exe + rm *.obj @@ -92,10 +92,10 @@ unsigned int hash = stringHash( name ); // printf("hash match! %s %s\n",name,bp->name); /* * This loop implements the equivalent of strcmp, except that in the - * case of VMS, it is case insensitive. + * case of VMS and MS-DOS, it is case insensitive. */ for(cp1 = name, cp2 = bp->name;;cp1++,cp2++){ -#ifdef VMS +#if defined(VMS) || defined(MSDOS) if(UPCASE(*cp1) != UPCASE(*cp2)) break; #else if(*cp1 != *cp2) break; @@ -1488,9 +1488,11 @@ char outbuf[1024]; bytes_required_for_line + INCREMENTAL_LINE_BUFFER_SIZE - 1; bytes_to_allocate -= bytes_to_allocate % INCREMENTAL_LINE_BUFFER_SIZE; +#if LARGEST_LOOKASIDE_BLOCK > 0 if(dlbp->buffer_size > LARGEST_LOOKASIDE_BLOCK){ bytes_to_allocate = dlbp->buffer_size * 2; }/* End IF */ +#endif if(bytes_to_allocate < bytes_required_for_line){ char tmp_message[1024]; @@ -1610,9 +1612,11 @@ char outbuf[1024]; bytes_required_for_line + INCREMENTAL_LINE_BUFFER_SIZE - 1; bytes_to_allocate -= bytes_to_allocate % INCREMENTAL_LINE_BUFFER_SIZE; +#if LARGEST_LOOKASIDE_BLOCK > 0 if(dlbp->buffer_size > LARGEST_LOOKASIDE_BLOCK){ bytes_to_allocate = dlbp->buffer_size * 2; }/* End IF */ +#endif if(bytes_to_allocate < bytes_required_for_line){ char tmp_message[1024]; @@ -1047,6 +1047,11 @@ int status; PREAMBLE(); + /* + * FIXME: This could be supported on MS-DOS if we + * respected DOS directory separators and + * used short filename extensions. + */ #ifdef UNIX /* * First step is to separate the path elements from the filename itself. @@ -1198,7 +1203,12 @@ register int status; PREAMBLE(); #ifndef HAVE_LONG_FILE_NAMES - if(mkdir(pathname,0777)){ +#ifdef MSDOS + i = mkdir(pathname); +#else + i = mkdir(pathname,0777); +#endif + if(i){ if(errno != EEXIST){ sprintf(tmp_message,"?Error creating subdirectory <%s>: %s", pathname,error_text(errno)); @@ -1492,8 +1502,12 @@ cmd_interrupt() if(waiting_for_input_flag == NO){ restore_tty(); fprintf(stderr,"TECO aborted...\n"); +#ifdef MSDOS + abort(); +#else signal(SIGINT,(void (*)(int))SIG_DFL); kill(getpid(),SIGINT); +#endif }/* End IF */ }/* End IF */ @@ -1937,11 +1951,7 @@ failreap: /* END OF UNIX CONDITIONAL CODE */ -#endif - - - -#ifdef VMS +#else /* UNIX */ /** * \brief Issue a command to the operating system @@ -1949,12 +1959,16 @@ failreap: * This routine is called in response to the EC command which allows the * user to execute operating system commands from within the editor. */ -cmd_oscmd(ct) -register struct cmd_token *ct; +int +cmd_oscmd(struct cmd_token *uct, int arg_count, int arg1, int arg2, char *cp) { PREAMBLE(); - error_message("?VMS Does not currently support EC"); + /* + * FIXME: We could at least implement a subset with system(), + * that would work on DOS as well. + */ + error_message("?OS Does not currently support EC"); return(FAIL); }/* End Routine */ @@ -39,7 +39,7 @@ char *tecmem_c_version = "tecmem.c: $Revision: 1.3 $"; char *starting_break; -#ifndef HAVE_UNISTD_H +#if !defined(HAVE_UNISTD_H) && !defined(HAVE_STDLIB_H) char *malloc(); void free(); void exit(); @@ -188,7 +188,7 @@ register int i; remove_checkpoint_file(); #endif /* CHECKPOINT */ -#ifdef UNIX +#if defined(UNIX) || defined(MSDOS) return(0); #endif @@ -210,7 +210,7 @@ register int i; * package a chance to initialize itself. */ void -initialize_tty() +initialize_tty( void ) { #if HAVE_TERMIOS_H struct termios tmp_tty_modes; @@ -427,8 +427,57 @@ initialize_tty() /* END OF UNIX CONDITIONAL CODE */ +#ifdef MSDOS + +void +initialize_tty( void ) +{ + tty_input_chan = 0; + tty_output_chan = 1; + + /* + * The terminal speed is checked in various situations, + * so it's important to be initialized even though we're + * not on a real serial connection. + */ + term_speed = 32000; + main_delete_character = 8; + + // Block cursor + //_settextcursor(0x0007); + +/* + * Check out the termcap description for this tty now. It makes + * no sense to go changing the terminal modes all around until + * we decide whether we can run on this terminal or not. + */ + init_term_description(); + + if(forced_height > 0) term_lines = forced_height; + if(forced_width > 0) term_columns = forced_width; + if(term_lines == 0) term_lines = 24; + if(term_columns == 0) term_columns = 80; + + if(term_lines >= SCREEN_MAX_LINES){ + char tmp_message[LINE_BUFFER_SIZE]; + sprintf( + tmp_message, + "terminal line count of %d exceeds maximum of %d", + term_lines, + SCREEN_MAX_LINES + ); + tec_error(E2BIG,tmp_message); + }/* End IF */ + + screen_init(); +}/* End Routine */ + +#endif /* MSDOS */ + +#ifndef MSDOS + #if !HAVE_TCGETATTR /** @@ -504,6 +553,8 @@ int status; #endif /* !HAVE_TCSETATTR */ +#endif /* !MSDOS */ + #ifdef VMS @@ -741,6 +792,10 @@ int err; #endif +#ifdef MSDOS + if(kbhit()) return(YES); +#endif + return(NO); }/* End Routine */ @@ -819,6 +874,16 @@ char comment_flag = NO; #endif +#ifdef MSDOS + + /* + * FIXME: We should use the location + * of teco.exe. + */ + (void) strcat(filename,".teco_ini"); + +#endif + #ifdef VMS strcpy(filename,"SYS$LOGIN:TECO.INI"); @@ -956,7 +1021,11 @@ char *cp, c; * This code handles the command line arguments to VTECO. This requires * different processing for different operating systems. */ -#ifdef UNIX +#if defined(UNIX) || defined(MSDOS) +/* + * FIXME: Perhaps DOS should have its own version with `/` arguments. + * The Watcom C runtime probably also doesn't expand wildcards. + */ int handle_command_line( int which_time, int argc, char **argv ) { @@ -1323,7 +1392,7 @@ char *cp,*sp; * * This routine returns a linked list of expanded filenames. */ -#ifdef UNIX +#if defined(UNIX) || defined(MSDOS) struct wildcard_expansion *name_list; struct wildcard_expansion *name_list_end; @@ -1339,12 +1408,16 @@ struct passwd *pw; name_list = NULL; name_list_end = NULL; + /* + * FIXME: DOS should use \ directory separators. + */ /* * Else, start branching down into the directory list he specified */ if(wildcard_string[0] == '/'){ process_directory(&wildcard_string[0],"/",2); } +#ifdef UNIX else if (wildcard_string[0] == '~'){ cp = temp_name; sp = &wildcard_string[1]; @@ -1360,6 +1433,7 @@ struct passwd *pw; strcat(temp_name,sp); process_directory(temp_name,"/",2); } +#endif else { strcpy(temp_name,"./"); strcat(temp_name,wildcard_string); @@ -1616,7 +1690,7 @@ int pattern_char; }/* End While */ }/* End Routine */ -#endif +#endif /* UNIX || MSDOS */ @@ -1699,6 +1773,8 @@ open_debug_log_file() +#ifndef MSDOS + /** * \brief Map system dependent baud fields to a standard integer * @@ -1774,6 +1850,8 @@ static int equivalent_baudrates[] = { }/* End Routine */ +#endif /* !MSDOS */ + /** @@ -1842,7 +1920,7 @@ static char *tec_errlist[] = { }/* End IF */ #endif -#ifdef UNIX +#if defined(UNIX) || defined(MSDOS) #if 0 return((char *)sys_errlist[err_num]); #endif @@ -41,8 +41,8 @@ #define BLOCKED 2 #define INVALIDATE 3 -#define VMAJOR 6 -#define VMINOR 7 +#define VMAJOR 7 +#define VMINOR 0 #define AUTO_DATE "$Date: 2007/12/10 22:13:07 $" #define TECO_FILENAME_TOTAL_LENGTH 1024 @@ -60,7 +60,12 @@ #define LINE_BUFFER_SIZE 1024 #define DEFAULT_CHECKPOINT (5*60) #define TAG_HASH_ENTRIES 1024 +#if defined(MSDOS) && !defined(__HUGE__) +/* make sure that all variables fit into 64kb */ +#define PARSER_STRING_MAX 512 +#else #define PARSER_STRING_MAX 1024 +#endif #define SEARCH_STRING_MAX PARSER_STRING_MAX #define NORMAL_TAB_WIDTH 8 #define MAX_TAB_WIDTH 16 @@ -69,8 +74,18 @@ #define INITIAL_LINE_BUFFER_SIZE 32 #define INCREMENTAL_LINE_BUFFER_SIZE 32 #define MINIMUM_ALLOCATION_BLOCK 32 +#if defined(MSDOS) && !defined(__HUGE__) +/* + * FIXME: The lookaside mechanism needs to be revised. + * It has been disabled, so that all tec_alloc() are + * more or less directly passed to malloc(). + */ +#define LOOKASIDE_COUNT 1 +#define LARGEST_LOOKASIDE_BLOCK 0 +#else #define LOOKASIDE_COUNT 32 #define LARGEST_LOOKASIDE_BLOCK (LOOKASIDE_COUNT * MINIMUM_ALLOCATION_BLOCK) +#endif #define BIG_MALLOC_HUNK_SIZE (LARGEST_LOOKASIDE_BLOCK * 64) #define NORMAL_TAB_WIDTH 8 @@ -129,12 +144,12 @@ #define TYPE_C_TAGSTR 49 #define TYPE_C_MAXTYPE 49 -#define MAGIC_SCREEN 0x01010101 -#define MAGIC_BUFFER 0x02020202 -#define MAGIC_LINE 0x03030303 -#define MAGIC_LINE_LOOKASIDE 0x04040404 -#define MAGIC_FORMAT 0x05050505 -#define MAGIC_FORMAT_LOOKASIDE 0x06060606 +#define MAGIC_SCREEN ((int)0x01010101) +#define MAGIC_BUFFER ((int)0x02020202) +#define MAGIC_LINE ((int)0x03030303) +#define MAGIC_LINE_LOOKASIDE ((int)0x04040404) +#define MAGIC_FORMAT ((int)0x05050505) +#define MAGIC_FORMAT_LOOKASIDE ((int)0x06060606) #ifdef DEBUG1 void do_preamble_checks(void); @@ -352,15 +367,22 @@ typedef unsigned long teco_ptrint_t; * vms. It lets us write our own version of functions which simply do not * exist outside of unix. */ -#ifndef VMS +#if !defined(VMS) && !defined(MSDOS) #define UNIX #define JOB_CONTROL #endif /* * Include Files From GNU Autoconf/Autoheader + * + * FIXME: The Autoconf build system does not pass down -DHAVE_CONFIG_H. + * This should be fixed by rewriting it as the original sources + * are missing. */ +//#ifdef HAVE_CONFIG_H +#ifndef __WATCOMC__ #include "config.h" +#endif #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> @@ -451,6 +473,10 @@ typedef unsigned long teco_ptrint_t; #endif #endif +#if HAVE_DIRECT_H +#include <direct.h> +#endif + #if HAVE_SYS_WAIT_H # include <sys/wait.h> #endif @@ -475,6 +501,10 @@ typedef unsigned long teco_ptrint_t; # include <termio.h> #endif +#if HAVE_IO_H +#include <io.h> +#endif + #if HAVE_FCNTL_H #include <fcntl.h> #endif @@ -565,6 +595,10 @@ typedef unsigned long teco_ptrint_t; } #endif +#ifdef MSDOS +#include <conio.h> +#endif + /* method declarations */ void error_message(char * string); void tec_release(unsigned char type, char *addr); @@ -1004,6 +1004,19 @@ char inbuf[4]; if(errno == EINTR) continue; #endif +#ifdef MSDOS + waiting_for_input_flag = YES; + /* does not echo */ + i = getch(); + waiting_for_input_flag = NO; + + intr_flag = 0; + + if(i != EOF){ + inbuf[0] = i; + break; + } +#endif #ifdef VMS waiting_for_input_flag = YES; i = sys$qiow(0,tty_input_chan,IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR, @@ -1091,7 +1104,7 @@ register struct buff_header *qbp; * The return code determines whether this was done okay or not. */ int -unpreserve_rubout_char( struct cmd_token *ct __attribute__((unused))) +unpreserve_rubout_char( struct cmd_token *ct ) { register struct buff_header *qbp; int c; @@ -1133,7 +1146,7 @@ int c; * special Q-register so that it doesn't grow without bounds. */ void -parser_clean_preserve_list() +parser_clean_preserve_list( void ) { register struct buff_header *qbp; @@ -37,6 +37,13 @@ char *tecterm_c_version = "tecterm.c: $Revision: 1.3 $"; #include <term.h> #endif +#if defined(VMS) || defined(MSDOS) +int tgetent(char *,char *); +int scan_termcap(FILE *,char *,char *); +int tgetnum(char *); +char *tgetstr(char *, char **); +#endif + /* * Global Storage is defined here for lack of a better place. */ @@ -1045,7 +1052,7 @@ term_flush() i = SCREEN_OUTPUT_BUFFER_SIZE - scr_outbuf_left; -#ifdef UNIX +#if defined(UNIX) || defined(MSDOS) if(i) write(tty_output_chan,scr_outbuf,(unsigned)i); #endif @@ -1072,7 +1079,7 @@ term_flush() * has certain basic capabilities that we require. */ int -init_term_description() +init_term_description( void ) { char termcap_description_buffer[TERMCAP_BUFFER_SIZE]; char *terminal_name; @@ -1086,7 +1093,11 @@ init_term_description() if((terminal_name = getenv("TECO_TERM")) == NULL){ if((terminal_name = getenv("TERM")) == NULL){ +#ifdef MSDOS + terminal_name = "ansi.sys"; +#else tec_error(ENOENT,"Environment variable TERM not found"); +#endif }/* End IF */ }/* End IF */ @@ -1319,7 +1330,6 @@ init_term_description() #ifdef VMS -char *current_termcap_description; char *termcap = "d1|vt100-80|vt-100|dec vt100:\ :co#80:li#24:cl=50\\E[;H\\E[2J:bs:am:cm=5\\E[%i%2;%2H:nd=2\\E[C:up=2\\E[A:\ @@ -1328,7 +1338,33 @@ char *termcap = :ku=\\E[A:kd=\\E[B:kr=\\E[C:kl=\\E[D:\ :cs=\\E[%i%d;%dr:sf=5\\ED:\ :kh=\\E[H:k1=\\EOP:k2=\\EOQ:k3=\\EOR:k4=\\EOS:pt:sr=5\\EM:xn:xv:"; +#endif + +#ifdef MSDOS +/* + * Generated via `infocmp -C ansi.sys`. + */ +char *termcap = +"ansi.sys|ANSI.SYS 3.1 and later versions:\ +:am:bs:mi:ms:xo:\ +:co#80:li#25:\ +:K1=\\0G:K2=\\0L:K3=\\0I:K4=\\0O:K5=\\0Q:ce=\\E[K:cl=\\E[2J:\ +:cm=\\E[%i%d;%dH:do=\\E[B:ho=\\E[H:is=\\E[m\\E[?7h:k1=\\0;:\ +:k2=\\0<:k3=\\0=:k4=\\0>:k5=\\0?:k6=\\0@:k7=\\0A:k8=\\0B:k9=\\0C:\ +:kD=\\0S:kI=\\0R:kN=\\0Q:kP=\\0I:kb=^H:kd=\\0P:kh=\\0G:kl=\\0K:\ +:kr=\\0M:ku=\\0H:le=^H:mb=\\E[5m:md=\\E[1m:me=\\E[0m:mr=\\E[7m:\ +:nd=\\E[C:rc=\\E[u:\ +:..sa=\\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m:\ +:sc=\\E[s:se=\\E[m:so=\\E[7m:ue=\\E[m:up=\\E[A:us=\\E[4m:" +/* + * Some extensions. + * At least Dosbox seems to have these escapes. + */ +":cd=50\\E[J:al=\\E[1L:dl=\\E[1M:ic=\\E[1@:dc=\\E[1P:"; +#endif +#if defined(VMS) || defined(MSDOS) +char *current_termcap_description; /** * \brief Version of TGETENT for Non-UNIX systems @@ -1398,6 +1434,7 @@ FILE *fd; * This routine scans the termcap file for an entry which matches our * terminal, and returns non-zero if it finds it. */ +int scan_termcap(fd,temp_buffer,term_name) FILE *fd; char *temp_buffer; @@ -1553,4 +1590,4 @@ char *buffer; /* END OF VMS CONDITIONAL CODE */ -#endif +#endif /* VMS || MSDOS */ |