BLARSON@ECLA.USC.EDU (Bob Larson) (05/26/88)
comp.sources.misc: Volume 3, Issue 32 Submitted-By: "Bob Larson" <BLARSON@ECLA.USC.EDU> Archive-Name: mg2a/Part08 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # sys/default/README # sys/default/alloca.c # sys/default/chrdef.h # sys/default/cinfo.c # sys/default/tty.c # sys/default/ttydef.h # sys/default/ttykbd.c # sys/default/varargs.h # sys/prime/cinfo.c # sys/prime/fileio.c # sys/prime/make.cpl # sys/prime/mg.64v.options.c # sys/prime/mg.options.c # sys/prime/readme # sys/prime/spawn.c # sys/prime/stackptr$.pma # sys/prime/sysdef.h # sys/prime/ttyio.c # sys/prime/varargs.h.ins.cc # This archive created: Sun May 22 02:24:06 1988 # By: blarson if test -d sys then true else mkdir sys fi if test -d sys/default then true else mkdir sys/default fi if test -d sys/prime then true else mkdir sys/prime fi cat << \SHAR_EOF > sys/default/README MG Termcap Terminal Driver The termcap library needs to know where to get the terminal type and termcap capibilities file from. UNIX and Os9/68k users should setenv TERM term-type to their terminal type, and setenv TERMCAP termcap-file if they are using a non-standard termcap file. VMS users should see [.SYS.VMS]AAAREADME.1ST for information on how to define the logical names TERM and ETC to point to the termcap definition file. Users of other operating systems should do the aproprate thing. For an example of a termcap file, UNIX users may look in /etc/termcap, Os9/68k users may look at /dd/sys/termcap (if present), and VMS users should see the file [.SYS.VMS.TERMCAP]TERMCAP. MG requires that certain terminal capabilities exist in the specified termcap entry. The "cm" (cursor motion) capability *must* be available to use MG. (Yes, it is possible to fake cm with some other capibilities, but MG doesn't try.) If your terminal is one that uses control characters in the paramater portion of the "cm" string, the "up" and "bc" capabilites may also be needed. (See your termlib documentation for when this is so.) If the following capabilities are available, they are used. The AL and DL sequences are not totally standard, but having them improves the performance of the editor, since it doesn't have to redraw the screen to delete a line. They should not be used if they need control characters as paramaters. cd -- clear display ce -- clear to end of line al -- insert 1 line dl -- delete 1 line AL -- insert multiple lines (note capitalization) DL -- delete multiple lines (note capitalization) ti -- cursor movement initialization string te -- cursor movement end string The cs capability is not as standard as some of the other capibilities, but is used by MG when available. It is used to define a "scrolling region", which defines a window within the screen where all the action takes place. A newline character at the bottom of this area scrolls the rest of the text in the area up one line, just like the normal screen; a reverse linefeed (sr) at the top of the window moves all the text in the area down a line. MG does not properly handle "cs" if your terminal needs control characters as paramaters, and in this case "cs" should not be defined. If the cs and sr capabilities are available, the termcap driver uses these to make the insert/delete line functions work more smoothly. If only the cs capability is present, it is still used for the delete line function, but not for inserting lines. Use of the cs capability is often desirable, but is not a win on bit-mapped screens such as Sun workstation console windows. This is because it takes longer to scroll the window than to redraw it. If you are using a workstation window, you might consider using a termcap entry that doesn't have the cs capability. The definition of the cs capability is: the first parameter in the sequence defines the first row (origin 0) that is in the scrolling region, and the second argument defines the last row to include in the scrolling region. cs -- set scrolling region (arg1 = top, arg2 = bottom) sr -- reverse index The following capabilities provide for an enhanced (reverse-video or otherwise rendered) mode line. The sg entry should not be present on terminals that do this to characters as they are placed on the screen. Terminals that put a region of the screen in the standout mode should have sg defined as numeric: :sg#0: for terminals that do this on regions but don't take any character positions to do this, (this may be a non-standard interprition of the meaning of sg) and the number of character positions taken by any other terminal. so -- enter standout mode se -- leave standout mode sg -- number of character positions used by standout Terminal-specific initialization file If the MG termcap terminal driver is compiled with XKEYS defined, and the startup file option is enabled as well, MG will look for a terminal-specific initialization file. The name of the terminal initialization file varies between operating systems, but will usually look like .mg-TERM, where TERM represents your terminal type. For example, a terminal initialization file under Unix and VMS for the DEC VT100 terminal (termcap type vt100) would have the name ".mg-vt100". The terminal-specific startup file has the same format as the mg startup file, and is executed immediately after the startup file during mg's startup phase. An example vt100 initialization file follows, which globally binds the key sequences sent by the VT100 terminal (in keypad mode) to the appropriate functions. ----------------------------------CUT HERE----------------------------------- ; ; Small key definition file for VT100 terminals using the termcap ; driver. This only works if XKEYS is defined during compilation. ; (global-set-key "\eOA" 'previous-line) ; up arrow (global-set-key "\eOB" 'next-line) ; down arrow (global-set-key "\eOC" 'forward-char) ; right arrow (global-set-key "\eOD" 'backward-char) ; left arrow SHAR_EOF cat << \SHAR_EOF > sys/default/alloca.c /* alloca -- (mostly) portable public-domain implementation last edit: 86/01/26 D A Gwyn This implementation of the PWB library alloca() function, which is used to allocate space off the run-time stack so that it is automatically reclaimed upon procedure exit, was inspired by discussions with J. Q. Johnson of Cornell. It should work under any C implementation that uses an actual procedure stack (as opposed to a linked list of frames). There are some preprocessor constants that can be defined when compiling for your specific system, for improved efficiency; however, the defaults should be okay. The general concept of this implementation is to keep track of all alloca()-allocated blocks, and reclaim any that are found to be deeper in the stack than the current invocation. This heuristic does not reclaim storage as soon as it becomes invalid, but it will do so eventually. As a special case, alloca(0) reclaims storage without allocating any. It is a good idea to use alloca(0) in your main control loop, etc. to force garbage collection. */ #ifndef lint static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */ #endif #ifdef X3J11 typedef void *pointer; /* generic pointer type */ #else typedef char *pointer; /* generic pointer type */ #endif #define NULL 0 /* null pointer constant */ extern void free(); extern pointer malloc(); /* Define STACK_DIRECTION if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #ifndef STACK_DIRECTION #define STACK_DIRECTION 0 /* direction unknown */ #endif #if STACK_DIRECTION != 0 #define STACK_DIR STACK_DIRECTION /* known at compile-time */ #else /* STACK_DIRECTION == 0; need run-time code */ static int stack_dir = 0; /* 1 or -1 once known */ #define STACK_DIR stack_dir static void find_stack_direction( /* void */ ) { static char *addr = NULL; /* address of first `dummy', once known */ auto char dummy; /* to get stack address */ if ( addr == NULL ) { /* initial entry */ addr = &dummy; find_stack_direction(); /* recurse once */ } else /* second entry */ if ( &dummy > addr ) stack_dir = 1; /* stack grew upward */ else stack_dir = -1; /* stack grew downward */ } #endif /* STACK_DIRECTION == 0 */ /* An "alloca header" is used to: (a) chain together all alloca()ed blocks; (b) keep track of stack depth. It is very important that sizeof(header) agree with malloc() alignment chunk size. The following default should work okay. */ #ifndef ALIGN_SIZE #define ALIGN_SIZE sizeof(double) #endif typedef union hdr { char align[ALIGN_SIZE]; /* to force sizeof(header) */ struct { union hdr *next; /* for chaining headers */ char *deep; /* for stack depth measure */ } h; } header; /* alloca( size ) returns a pointer to at least `size' bytes of storage which will be automatically reclaimed upon exit from the procedure that called alloca(). Originally, this space was supposed to be taken from the current stack frame of the caller, but that method cannot be made to work for some implementations of C, for example under Gould's UTX/32. */ pointer alloca( size ) /* returns pointer to storage */ unsigned size; /* # bytes to allocate */ { static header *last = NULL; /* -> last alloca header */ auto char probe; /* probes stack depth: */ register char *depth = &probe; #if STACK_DIRECTION == 0 if ( STACK_DIR == 0 ) /* unknown growth direction */ find_stack_direction(); #endif /* Reclaim garbage, defined as all alloca()ed storage that was allocated from deeper in the stack than currently. */ { register header *hp; /* traverses linked list */ for ( hp = last; hp != NULL; ) if ( STACK_DIR > 0 && hp->h.deep > depth || STACK_DIR < 0 && hp->h.deep < depth ) { register header *np = hp->h.next; free( (pointer)hp ); /* collect garbage */ hp = np; /* -> next header */ } else break; /* rest are not deeper */ last = hp; /* -> last valid storage */ } if ( size == 0 ) return NULL; /* no allocation required */ /* Allocate combined header + user data storage. */ { register pointer new = malloc( sizeof(header) + size ); /* address of header */ if ( new == NULL ) return NULL; /* abort() is traditional */ ((header *)new)->h.next = last; ((header *)new)->h.deep = depth; last = (header *)new; /* User storage begins just after header. */ return (pointer)((char *)new + sizeof(header)); } } SHAR_EOF cat << \SHAR_EOF > sys/default/chrdef.h /* * sys/default/chardef.h: character set specific #defines for mg 2a * Warning: System specific ones exist */ #ifndef CHARMASK /* * casting should be at least as efficent as anding with 0xff, * and won't have the size problems. Override in sysdef.h if no * unsigned char type. */ #define CHARMASK(c) ((unsigned char) (c)) #endif /* * These flags, and the macros below them, * make up a do-it-yourself set of "ctype" macros that * understand the DEC multinational set, and let me ask * a slightly different set of questions. */ #define _W 0x01 /* Word. */ #define _U 0x02 /* Upper case letter. */ #define _L 0x04 /* Lower case letter. */ #define _C 0x08 /* Control. */ #define _P 0x10 /* end of sentence punctuation */ #define _D 0x20 /* is decimal digit */ #define ISWORD(c) ((cinfo[CHARMASK(c)]&_W)!=0) #define ISCTRL(c) ((cinfo[CHARMASK(c)]&_C)!=0) #define ISUPPER(c) ((cinfo[CHARMASK(c)]&_U)!=0) #define ISLOWER(c) ((cinfo[CHARMASK(c)]&_L)!=0) #define ISEOSP(c) ((cinfo[CHARMASK(c)]&_P)!=0) #define ISDIGIT(c) ((cinfo[CHARMASK(c)]&_D)!=0) #define TOUPPER(c) ((c)-0x20) #define TOLOWER(c) ((c)+0x20) /* * generally useful thing for chars */ #define CCHR(x) ((x) ^ 0x40) /* CCHR('?') == DEL */ #ifndef METACH #define METACH CCHR('[') #endif #ifdef XKEYS #define K00 256 #define K01 257 #define K02 258 #define K03 259 #define K04 260 #define K05 261 #define K06 262 #define K07 263 #define K08 264 #define K09 265 #define K0A 266 #define K0B 267 #define K0C 268 #define K0D 269 #define K0E 270 #define K0F 271 #define K10 272 #define K11 273 #define K12 274 #define K13 275 #define K14 276 #define K15 277 #define K16 278 #define K17 279 #define K18 280 #define K19 281 #define K1A 282 #define K1B 283 #define K1C 284 #define K1D 285 #define K1E 286 #define K1F 287 #endif SHAR_EOF cat << \SHAR_EOF > sys/default/cinfo.c /* * Character class tables. * Do it yourself character classification * macros, that understand the multinational character set, * and let me ask some questions the standard macros (in * ctype.h) don't let you ask. */ #include "def.h" /* * This table, indexed by a character drawn * from the 256 member character set, is used by my * own character type macros to answer questions about the * type of a character. It handles the full multinational * character set, and lets me ask some questions that the * standard "ctype" macros cannot ask. */ char cinfo[256] = { _C, _C, _C, _C, /* 0x0X */ _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, /* 0x1X */ _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, 0, _P, 0, 0, /* 0x2X */ _W, _W, 0, _W, 0, 0, 0, 0, 0, 0, _P, 0, _D|_W, _D|_W, _D|_W, _D|_W, /* 0x3X */ _D|_W, _D|_W, _D|_W, _D|_W, _D|_W, _D|_W, 0, 0, 0, 0, 0, _P, 0, _U|_W, _U|_W, _U|_W, /* 0x4X */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, /* 0x5X */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, 0, 0, 0, 0, 0, 0, _L|_W, _L|_W, _L|_W, /* 0x6X */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, /* 0x7X */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, 0, 0, 0, 0, _C, 0, 0, 0, 0, /* 0x8X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xAX */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xBX */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _U|_W, _U|_W, _U|_W, _U|_W, /* 0xCX */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, 0, _U|_W, _U|_W, _U|_W, /* 0xDX */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, 0, _W, _L|_W, _L|_W, _L|_W, _L|_W, /* 0xEX */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, 0, _L|_W, _L|_W, _L|_W, /* 0xFX */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, 0, 0 }; /* * Find the name of a keystroke. Needs to be changed to handle 8-bit printing * characters and function keys better. Returns a pointer to the terminating * '\0'. */ char *keyname(cp, k) register char *cp; register int k; { register char *np; #ifdef FKEYS extern char *keystrings[]; #endif if(k < 0) k = CHARMASK(k); /* sign extended char */ switch(k) { case CCHR('@'): np = "NUL"; break; case CCHR('I'): np = "TAB"; break; case CCHR('J'): np = "LFD"; break; /* yuck, but that's what GNU calls it */ case CCHR('M'): np = "RET"; break; case CCHR('['): np = "ESC"; break; case ' ': np = "SPC"; break; /* yuck again */ case CCHR('?'): np = "DEL"; break; default: #ifdef FKEYS if(k >= KFIRST && k <= KLAST && (np = keystrings[k - KFIRST]) != NULL) break; #endif if(k > CCHR('?')) { *cp++ = '0'; *cp++ = ((k>>6)&7) + '0'; *cp++ = ((k>>3)&7) + '0'; *cp++ = (k&7) + '0'; *cp = '\0'; return cp; } if(k < ' ') { *cp++ = 'C'; *cp++ = '-'; k = CCHR(k); if(ISUPPER(k)) k = TOLOWER(k); } *cp++ = k; *cp = '\0'; return cp; } (VOID) strcpy(cp, np); return cp + strlen(cp); } SHAR_EOF cat << \SHAR_EOF > sys/default/tty.c /* * Termcap/terminfo display driver * * Termcap is a terminal information database and routines to describe * terminals on most UNIX systems. Many other systems have adopted * this as a reasonable way to allow for widly varying and ever changing * varieties of terminal types. This should be used where practical. */ /* Known problems: * If you have a terminal with no clear to end of screen and * memory of lines below the ones visible on the screen, display * will be wrong in some cases. I doubt that any such terminal * was ever made, but I thought everyone with delete line would * have clear to end of screen too... * * Code for terminals without clear to end of screen and/or clear * to end of line has not been extensivly tested. * * Cost calculations are very rough. Costs of insert/delete line * may be far from the truth. This is accentuated by display.c * not knowing about multi-line insert/delete. * * Using scrolling region vs insert/delete line should probably * be based on cost rather than the assuption that scrolling * region operations look better. */ #include "def.h" #define BEL 0x07 /* BEL character. */ extern int ttrow; extern int ttcol; extern int tttop; extern int ttbot; extern int tthue; int tceeol; /* Costs are set later */ int tcinsl; int tcdell; static int insdel; /* Do we have both insert & delete line? */ #ifdef NO_RESIZE static setttysize(); #endif char *tgetstr(); char *tgoto(); int ttputc(); #define TCAPSLEN 1024 char tcapbuf[TCAPSLEN]; /* PC, UP, and BC are used by termlib, so must be extern and have these * names unless you have a non-standard termlib. */ int LI; /* standard # lines */ char PC, *CM, *CE, *UP, *BC, *IM, /* insert mode */ *IC, /* insert a single space */ *EI, /* end insert mode */ *DC, *AL, /* add line */ *DL, /* del line */ *pAL, /* parameterized add line */ *pDL, /* parameterized delete line */ *TI, /* term init -- start using cursor motion */ *TE, /* term end --- end using cursor motion */ *SO, *SE, *CD, *CS, /* set scroll region */ *SF, /* forw index (used with scroll region) */ *SR; /* back index (used with scroll region) */ #ifdef XKEYS char *KS, *KE; /* enter keypad mode, exit keypad mode */ #endif int SG; /* number of glitches, 0 for invisible, -1 for none */ /* (yes virginia, there are terminals with invisible glitches) */ /* * Initialize the terminal when the editor * gets started up. */ static char tcbuf[1024]; ttinit() { char *tv_stype; char *t, *p, *tgetstr(); #ifndef gettermtype /* (avoid declaration if #define) */ char *gettermtype(); /* system dependent function to determin terminal type */ #endif if((tv_stype = gettermtype()) == NULL) panic("Could not determine terminal type"); if((tgetent(tcbuf, tv_stype)) != 1) { (VOID) strcpy(tcbuf, "Unknown terminal type "); (VOID) strcat(tcbuf, tv_stype); panic(tcbuf); } p = tcapbuf; t = tgetstr("pc", &p); if(t) PC = *t; LI = tgetnum("li"); CD = tgetstr("cd", &p); CM = tgetstr("cm", &p); CE = tgetstr("ce", &p); UP = tgetstr("up", &p); BC = tgetstr("bc", &p); IM = tgetstr("im", &p); IC = tgetstr("ic", &p); EI = tgetstr("ei", &p); DC = tgetstr("dc", &p); AL = tgetstr("al", &p); DL = tgetstr("dl", &p); pAL= tgetstr("AL", &p); /* parameterized insert and del. line */ pDL= tgetstr("DL", &p); TI = tgetstr("ti", &p); TE = tgetstr("te", &p); SO = tgetstr("so", &p); SE = tgetstr("se", &p); CS = tgetstr("cs", &p); /* set scrolling region */ SF = tgetstr("sf", &p); if(!SF || !*SF) { /* this is what GNU Emacs does */ SF = tgetstr("do", &p); if(!SF || !*SF) { SF = tgetstr("nl", &p); if(!SF || !*SF) SF = "\n"; } } SR = tgetstr("sr", &p); SG = tgetnum("sg"); /* standout glitch */ #ifdef XKEYS KS = tgetstr("ks", &p); /* keypad start, keypad end */ KE = tgetstr("ke", &p); #endif if(CM == NULL || UP == NULL) panic("This terminal is to stupid to run MicroGnuEmacs\n"); ttresize(); /* set nrow & ncol */ /* watch out for empty capabilities (sure to be wrong) */ if (CE && !*CE) CE = NULL; if (CS && !*CS) CS = NULL; if (SR && !*SR) SR = NULL; if (AL && !*AL) AL = NULL; if (DL && !*DL) DL = NULL; if (pAL && !*pAL) pAL = NULL; if (pDL && !*pDL) pDL = NULL; if (CD && !*CD) CD = NULL; if(!CE) tceeol = ncol; else tceeol = charcost(CE); /* Estimate cost of inserting a line */ if (CS && SR) tcinsl = charcost(CS)*2 + charcost(SR); else if (pAL) tcinsl = charcost(pAL); else if (AL) tcinsl = charcost(AL); else tcinsl = NROW * NCOL; /* make this cost high enough */ /* Estimate cost of deleting a line */ if (CS) tcdell = charcost(CS)*2 + charcost(SF); else if (pDL) tcdell = charcost(pDL); else if (DL) tcdell = charcost(DL); else tcdell = NROW * NCOL; /* make this cost high enough */ /* Flag to indicate that we can both insert and delete lines */ insdel = (AL || pAL) && (DL || pDL); if (p >= &tcapbuf[TCAPSLEN]) panic("Terminal description too big!\n"); if (TI && *TI) putpad(TI, 1); /* init the term */ } /* * Clean up the terminal, in anticipation of * a return to the command interpreter. This is a no-op * on the ANSI display. On the SCALD display, it sets the * window back to half screen scrolling. Perhaps it should * query the display for the increment, and put it * back to what it was. */ tttidy() { if (TE && *TE) putpad(TE, 1); /* set the term back to normal mode */ #ifdef XKEYS ttykeymaptidy(); #endif } /* * Move the cursor to the specified * origin 0 row and column position. Try to * optimize out extra moves; redisplay may * have left the cursor in the right * location last time! */ ttmove(row, col) { char *tgoto(); if (ttrow!=row || ttcol!=col) { putpad(tgoto(CM, col, row), 1); ttrow = row; ttcol = col; } } /* * Erase to end of line. */ tteeol() { if(CE) putpad(CE, 1); else { register int i=ncol-ttcol; while(i--) ttputc(' '); ttrow = ttcol = HUGE; } } /* * Erase to end of page. */ tteeop() { if(CD) putpad(CD, nrow - ttrow); else { putpad(CE, 1); if (insdel) ttdell(ttrow + 1, LI, LI - ttrow - 1); else { /* do it by hand */ register int line; for (line = ttrow + 1; line <= LI; ++line) { ttmove(line, 0); tteeol(); } } ttrow = ttcol = HUGE; } } /* * Make a noise. */ ttbeep() { ttputc(BEL); ttflush(); } /* * Insert nchunk blank line(s) onto the * screen, scrolling the last line on the * screen off the bottom. Use the scrolling * region if possible for a smoother display. * If no scrolling region, use a set * of insert and delete line sequences */ ttinsl(row, bot, nchunk) { register int i, nl; if (row == bot) { /* Case of one line insert is */ ttmove(row, 0); /* special */ tteeol(); return; } if (CS && SR) { /* Use scroll region and back index */ nl = bot - row; ttwindow(row,bot); ttmove(row, 0); while (nchunk--) putpad(SR, nl); ttnowindow(); return; } else if (insdel) { ttmove(1+bot-nchunk, 0); nl = nrow - ttrow; if (pDL) putpad(tgoto(pDL, 0, nchunk), nl); else for (i=0; i<nchunk; i++) /* For all lines in the chunk */ putpad(DL, nl); ttmove(row, 0); nl = nrow - ttrow; /* ttmove() changes ttrow */ if (pAL) putpad(tgoto(pAL, 0, nchunk), nl); else for (i=0; i<nchunk; i++) /* For all lines in the chunk */ putpad(AL, nl); ttrow = HUGE; ttcol = HUGE; } else panic("ttinsl: Can't insert/delete line"); } /* * Delete nchunk line(s) from "row", replacing the * bottom line on the screen with a blank line. * Unless we're using the scrolling region, this is * done with a crafty sequences of insert and delete * lines. The presence of the echo area makes a * boundry condition go away. */ ttdell(row, bot, nchunk) { register int i, nl; if (row == bot) { /* One line special case */ ttmove(row, 0); tteeol(); return; } if (CS) { /* scrolling region */ nl = bot - row; ttwindow(row, bot); ttmove(bot, 0); while (nchunk--) putpad(SF, nl); ttnowindow(); } else if(insdel) { ttmove(row, 0); /* Else use insert/delete line */ nl = nrow - ttrow; if (pDL) putpad(tgoto(pDL, 0, nchunk), nl); else for (i=0; i<nchunk; i++) /* For all lines in the chunk */ putpad(DL, nl); ttmove(1+bot-nchunk,0); nl = nrow - ttrow; /* ttmove() changes ttrow */ if (pAL) putpad(tgoto(pAL, 0, nchunk), nl); else for (i=0; i<nchunk; i++) /* For all lines in the chunk */ putpad(AL, nl); ttrow = HUGE; ttcol = HUGE; } else panic("ttdell: Can't insert/delete line"); } /* * This routine sets the scrolling window * on the display to go from line "top" to line * "bot" (origin 0, inclusive). The caller checks * for the pathalogical 1 line scroll window that * doesn't work right, and avoids it. The "ttrow" * and "ttcol" variables are set to a crazy value * to ensure that the next call to "ttmove" does * not turn into a no-op (the window adjustment * moves the cursor). * */ ttwindow(top, bot) { if (CS && (tttop!=top || ttbot!=bot)) { putpad(tgoto(CS, bot, top), nrow - ttrow); ttrow = HUGE; /* Unknown. */ ttcol = HUGE; tttop = top; /* Remember region. */ ttbot = bot; } } /* * Switch to full screen scroll. This is * used by "spawn.c" just before is suspends the * editor, and by "display.c" when it is getting ready * to exit. This function gets to full screen scroll * by telling the terminal to set a scrolling regin * that is LI or nrow rows high, whichever is larger. * This behavior seems to work right on systems * where you can set your terminal size. */ ttnowindow() { if (CS) { putpad(tgoto(CS, (nrow > LI ? nrow : LI) - 1, 0), nrow - ttrow); ttrow = HUGE; /* Unknown. */ ttcol = HUGE; tttop = HUGE; /* No scroll region. */ ttbot = HUGE; } } /* * Set the current writing color to the * specified color. Watch for color changes that are * not going to do anything (the color is already right) * and don't send anything to the display. * The rainbow version does this in putline.s on a * line by line basis, so don't bother sending * out the color shift. */ ttcolor(color) register int color; { if (color != tthue) { if (color == CTEXT) { /* Normal video. */ putpad(SE, 1); } else if (color == CMODE) { /* Reverse video. */ putpad(SO, 1); } tthue = color; /* Save the color. */ } } /* * This routine is called by the * "refresh the screen" command to try and resize * the display. The new size, which must be deadstopped * to not exceed the NROW and NCOL limits, it stored * back into "nrow" and "ncol". Display can always deal * with a screen NROW by NCOL. Look in "window.c" to * see how the caller deals with a change. */ ttresize() { setttysize(); /* found in "ttyio.c", */ /* ask OS for tty size */ if (nrow < 1) /* Check limits. */ nrow = 1; else if (nrow > NROW) nrow = NROW; if (ncol < 1) ncol = 1; else if (ncol > NCOL) ncol = NCOL; } #ifdef NO_RESIZE static setttysize() { nrow = tgetnum("li"); ncol = tgetnum("co"); } #endif static int cci; /*ARGSUSED*/ static int /* fake char output for charcost() */ fakec(c) char c; { cci++; } /* calculate the cost of doing string s */ charcost (s) char *s; { cci = 0; tputs(s, nrow, fakec); return cci; } SHAR_EOF cat << \SHAR_EOF > sys/default/ttydef.h /* * Termcap terminal file, nothing special, just make it big * enough for windowing systems. */ #define GOSLING /* Compile in fancy display. */ /* #define MEMMAP */ /* Not memory mapped video. */ #define NROW 66 /* (maximum) Rows. */ #define NCOL 132 /* (maximum) Columns. */ /* #define MOVE_STANDOUT /* don't move in standout mode */ #define STANDOUT_GLITCH /* possible standout glitch */ #define TERMCAP /* for possible use in ttyio.c */ #define getkbd() (ttgetc()) #ifndef XKEYS #define ttykeymapinit() {} #endif extern int tputs(); #define putpad(str, num) tputs(str, num, ttputc) #define KFIRST K00 #define KLAST K00 SHAR_EOF cat << \SHAR_EOF > sys/default/ttykbd.c /* * Name: MG 2a * Termcap keyboard driver using key files * Created: 22-Nov-1987 Mic Kaczmarczik (mic@emx.cc.utexas.edu) */ #include "def.h" #ifdef XKEYS /* * Get keyboard character. Very simple if you use keymaps and keys files. * Bob was right -- the old XKEYS code is not the right solution. * FKEYS code is not usefull other than to help debug FKEYS code in * extend.c. */ #ifdef FKEYS char *keystrings[] = { NULL } ; #endif /* * Turn on function keys using KS, then load a keys file, if available. * The keys file is located in the same manner as the startup file is, * depending on what startupfile() does on your system. */ extern int ttputc(); ttykeymapinit() { extern char *KS; #ifndef NO_STARTUP char *cp, *startupfile(); if (cp = gettermtype()) { if (((cp = startupfile(cp)) != NULL) && (load(cp) != TRUE)) ewprintf("Error reading key initialization file"); } #endif if (KS && *KS) /* turn on keypad */ putpad(KS, 1); } /* * Clean up the keyboard -- called by tttidy() */ ttykeymaptidy() { extern char *KE; if (KE && *KE) putpad(KE, 1); /* turn off keypad */ } #endif SHAR_EOF cat << \SHAR_EOF > sys/default/varargs.h /* varargs.h for MicroGnuEmacs 2a. This one will work on systems that */ /* the non-varargs version of mg 1 did. */ /* based on the one I wrote for os9/68k . I did not look at the bsd code. */ /* by Robert A. Larson */ /* assumptions made about how arguments are passed: */ /* arguments are stored in a block of memory with no padding between. */ /* The first argument will have the lowest address */ /* varargs is a "portable" way to write a routine that takes a variable */ /* number of arguements. This implemination agrees with both the 4.2bsd*/ /* and Sys V documentation of varargs. Note that just because varargs.h*/ /* is used does not mean that it is used properly. */ #define va_dcl unsigned va_alist; typedef char *va_list; #define va_start(pvar) ((pvar) = (char *)&va_alist) #define va_arg(pvar,type) (((pvar)+=sizeof(type)),*(((type *)(pvar)) - 1)) #define va_end(pvar) /* va_end is simple */ SHAR_EOF cat << \SHAR_EOF > sys/prime/cinfo.c /* * Character class tables. * Do it yourself character classification * macros, that understand the multinational character set, * and let me ask some questions the standard macros (in * ctype.h) don't let you ask. * * primos specific version */ #include "def.h" /* * This table, indexed by a character drawn * from the 256 member character set, is used by my * own character type macros to answer questions about the * type of a character. It handles the full multinational * character set, and lets me ask some questions that the * standard "ctype" macros cannot ask. */ char cinfo[256] = { _C, _C, _C, _C, /* 0x0X */ _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, /* 0x1X */ _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, 0, _P, 0, 0, /* 0x2X */ _W, _W, 0, _W, 0, 0, 0, 0, 0, 0, _P, 0, _D|_W, _D|_W, _D|_W, _D|_W, /* 0x3X */ _D|_W, _D|_W, _D|_W, _D|_W, _D|_W, _D|_W, 0, 0, 0, 0, 0, _P, 0, _U|_W, _U|_W, _U|_W, /* 0x4X */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, /* 0x5X */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, 0, 0, 0, 0, 0, 0, _L|_W, _L|_W, _L|_W, /* 0x6X */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, /* 0x7X */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, 0, 0, 0, 0, _C, _C, _C, _C, _C, /* 0x8X */ _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, /* 0x9X */ _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, 0, _P, 0, 0, /* 0xAX */ _W, _W, 0, _W, 0, 0, 0, 0, 0, 0, _P, 0, _D|_W, _D|_W, _D|_W, _D|_W, /* 0xbX */ _D|_W, _D|_W, _D|_W, _D|_W, _D|_W, _D|_W, 0, 0, 0, 0, 0, _P, 0, _U|_W, _U|_W, _U|_W, /* 0xCX */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, /* 0xDX */ _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, _U|_W, 0, 0, 0, 0, 0, 0, _L|_W, _L|_W, _L|_W, /* 0xEX */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, /* 0xFX */ _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, _L|_W, 0, 0, 0, 0, _C, }; /* * Find the name of a keystroke. Needs to be changed to handle 8-bit printing * characters and function keys better. Returns a pointer to the terminating * '\0'. */ char *keyname(cp, k) register char *cp; register int k; { register char *np; #ifdef FKEYS extern char *keystrings[]; #endif if(k < 0) k = CHARMASK(k); /* sign extended char */ switch(k) { case CCHR('@'): np = "NUL"; break; case CCHR('I'): np = "TAB"; break; case CCHR('J'): np = "LFD"; break; /* yuck, but that's what GNU calls it */ case CCHR('M'): np = "RET"; break; case CCHR('['): np = "ESC"; break; case ' ': np = "SPC"; break; /* yuck again */ case CCHR('?'): np = "DEL"; break; default: #ifdef FKEYS if(k >= KFIRST && k <= KLAST && (np = keystrings[k - KFIRST]) != NULL) break; #endif if(k < CCHR('@')) { *cp++ = '0'; *cp++ = ((k>>6)&7) + '0'; *cp++ = ((k>>3)&7) + '0'; *cp++ = (k&7) + '0'; *cp = '\0'; return cp; } if(k < ' ') { *cp++ = 'C'; *cp++ = '-'; k = CCHR(k); if(ISUPPER(k)) k = TOLOWER(k); } *cp++ = k; *cp = '\0'; return cp; } (VOID) strcpy(cp, np); return cp + strlen(cp); } SHAR_EOF cat << \SHAR_EOF > sys/prime/fileio.c /* * Prime fileio.c for MicroGnuEmacs by Robert A. Larson * system dependent file io routines * * Prime keeps the parity bit of every character set, as does mg 2a for primos. */ #include <errd.ins.cc> #include <keys.ins.cc> #include "def.h" static FILE *ffp; char *index(), *rindex(); fortran void cnam$$(), at$(), at$abs(), at$any(), at$hom(), clo$fu(); fortran void gpath$(), dir$se(), cv$fdv(); fortran long srsfx$(); /* * Open a file for reading. */ ffropen(fn) char *fn; { if ((ffp=fopen(fn, "r")) == NULL) return (FIOFNF); return (FIOSUC); } /* * Open a file for writing. * Return TRUE if all is well, and * FALSE on error (cannot create). */ ffwopen(fn) char *fn; { short unit, type, sfu, code; struct {short len; char data[128];} fnb; register char *cp = &fnb.data[0]; struct {short len; char data[32];} basename; /* most of this is to get a SAM rather than DAM file ... */ (void) strcpy(fnb.data, fn); fnb.len = strlen(fnb.data); (void) srsfx$((short)(k$writ+k$getu+k$nsam), fnb, unit, type, (short)0, (short)0, basename, sfu, code); #ifdef OPEN_BUG if(code==0) { clo$fu(unit, code); fnb.data[fnb.len] = '\0'; if((ffp=fopen(fnb.data, "w"))!=NULL) return FIOSUC; } ewprintf("Cannot open file for writing"); return FIOERR; #else if (code != 0 || (ffp=fdopen(open("", -2, unit), "w")) == NULL) { ewprintf("Cannot open file for writing"); if(code==0) clo$fu(unit, code); return (FIOERR); } return (FIOSUC); #endif } /* * Close a file. * Should look at the status. */ ffclose() { fclose(ffp); return (FIOSUC); } /* * Write a buffer to the already * opened file. bp points to the * buffer. Return the status. * Check only at the newline and * end of buffer. */ ffputbuf(bp) BUFFER *bp; { register char *cp; register char *cpend; register LINE *lp; register LINE *lpend; lpend = bp->b_linep; lp = lforw(lpend); do { cp = <ext(lp)[0]; /* begining of line */ cpend = &cp[llength(lp)]; /* end of line */ while(cp != cpend) { putc(*cp, ffp); cp++; /* putc may evalualte arguments more than once */ } lp = lforw(lp); if(lp == lpend) break; /* no implied newline on last line */ putc('\n', ffp); } while(!ferror(ffp)); if(ferror(ffp)) { ewprintf("Write I/O error"); return FIOERR; } return FIOSUC; } /* * Read a line from a file, and store the bytes * in the supplied buffer. Stop on end of file or end of * line. When FIOEOF is returned, there is a valid line * of data without the normally implied \n. */ ffgetline(buf, nbuf, nbytes) register char *buf; register int nbuf; register int *nbytes; { register int c; register int i; i = 0; while((c = getc(ffp))!=EOF && c!='\n') { buf[i++] = c; if (i >= nbuf) return FIOLONG; } if (c == EOF && ferror(ffp) != FALSE) { ewprintf("File read error"); return FIOERR; } *nbytes = i; return c==EOF ? FIOEOF : FIOSUC; } #ifndef NO_BACKUP /* * Rename the file "fname" into a backup copy. */ fbackupfile(fname) char *fname; { struct {short len; char data[128];} back; struct {short len; char data[32];} ent; register char *cp; short code = 0, i; strcpy(back.data, fname); strcat(back.data, ".BAK"); (void) delete(back.data); if((cp = rindex(back.data, '>'))!=NULL) { if(back.data[0]==('<') && index(back.data, '>')==cp) { strncpy(ent.data, back.data+1, ent.len = (cp - back.data) - 1); at$abs((short)k$setc, ent, (short)0, code); } else { back.len = (cp - back.data); if(index(back.data, '>') == cp) at$any((short)k$setc, back, code); else at$((short)k$setc, back, code); } if(code) return FALSE; cp++; /* cnam$$ needs word aligned strings */ strncpy(ent.data, cp, back.len = strlen(cp)); cp = ent.data; } else back.len = strlen(cp = back.data); cnam$$((char [])cp, (short)(back.len - 4), (char [])cp, back.len, code); at$hom(i); return code == 0; } #endif /* * The string "fn" is a file name. Prepend the directory name if * it's relative to the current directory. */ #ifndef NO_DIR extern char *wdir; #endif char *adjustname(fn) register char *fn; { static char fnb[NFILEN]; register char *cp = fnb; register char *cp2; #ifndef NO_DIR if((fn[0] == '*' && fn[1] == '>') || index(fn, '>')==NULL) { cp2 = wdir; while(*cp2) { *cp = *cp2; cp++; cp2++; } *cp++ = '>'; if(fn[1]=='>') fn+=2; } #endif while(*fn) { *cp = ISUPPER(*fn) ? TOLOWER(*fn) : *fn; cp++; fn++; } *cp = '\0'; return fnb; } #ifndef NO_STARTUP char *startupfile(suffix) char *suffix; { short code, len; static char startname[128]; register char *cp; gpath$((short)k$inia, (short)-3, (char [])startname, (short)(128 - 5), len, code); if (code==0) { strcpy(startname + len, ">.MG"); if(suffix) { startname[len+4] = '.'; strcpy(startname + len + 5, suffix); } if(access(startname, 4)==0) return startname; } strcpy(startname, "MG*>.MG"); if(suffix) { startname[7] = '.'; strcpy(startname+8, suffix); } if(access(startname, 4)==0) return startname; return (char *)NULL; } #endif /* compare file names */ fncmp(fn1, fn2) register char *fn1, *fn2; { /* ignore disk name if on one but not the other */ if(*fn1 != *fn2) { if(*fn1 == '<') { fn1 = index(fn1, '>'); if(fn1 == NULL) return -1; fn1++; } else if(*fn2 == '<') { fn2 = index(fn2, '>'); if(fn2 == NULL) return -1; fn2++; } else return -1; } else fn1++, fn2++; /* compare ignoring case */ while(*fn1) { if((*fn1 != *fn2) && (!ISUPPER(*fn1) || (TOLOWER(*fn1) == *fn2)) && (!ISUPPER(*fn2) || (TOLOWER(*fn2) == *fn1))) return -1; fn1++; fn2++; } return *fn2; } #ifndef NO_DIRED #include "kbd.h" BUFFER *dired_(dirname) char *dirname; { register BUFFER *bp; LINE *lp, *blp; BUFFER *findbuffer(); short dirunit, j, code, type, init, counts[4], i, nent; struct {short len; char dat[128];} dir; struct ent {short len; char dat[32];} base; static struct ent wild[1] = {{2, {'@','@'}}}; static struct { short vers; struct ent *wp; short count; struct {unsigned dirs:1, seg_dirs:1, files:1, acats:1, rbf:1, spare:11;} desired; long mb, ma, bb, ba, cb, ca, ab, aa; } sel = { 1, &wild[0], 1, {1, 1, 1, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, }, *s = &sel; #define MAXSE 16 struct { struct {unsigned type:8, length:8;} ecw; struct ent name; struct {unsigned spare:5, odel:1, owrite:1, oread:1, delp:1, spare2:4, nodel:1, nowrite:1, noread:1;} prot; struct {unsigned lrat:1, dumped:1, dos:1, spec:1, rwl: 2, spare:2, type:8;} info; long dtm; short nondefault, logical_type, trunc; long dtb, dtc, dta; } ret[MAXSE], *r = &ret[0]; static char *types[] = {"SAM", "DAM", "SEGSAM", "SEGDAM", "UFD", "ACAT", "CAM"}; static char *rwlock[] = {"sys", "excl", "updt", "none"}; if((dirname = adjustname(dirname)) == NULL) { ewprintf("Bad directory name"); return NULL; } (void) strncpy(dir.dat, dirname, dir.len = strlen(dirname)); if(dir.dat[dir.len-1]=='>') dir.len--; else strcat(dirname, ">"); if((bp = findbuffer(dirname)) == NULL) { ewprintf("Could not create directory buffer"); return NULL; } if(bclear(bp) != TRUE) return NULL; (void) srsfx$((short)(k$read+k$getu), dir, dirunit, type, (short)0, (short)0, base, j, code); if(code!=0) { ewprintf("Could not open directory '%s'", dirname); return NULL; } if(type<2 || type > 4) { clo$fu(dirunit, code); ewprintf("Not a directory '%s'", dirname); return NULL; } for(init = 0x8000; ; init = 0) { dir$se(dirunit, type, init, s, r, (short)MAXSE, (short)((sizeof ret[0])/2), nent, (short [])counts, (short)4, code); if(code!=0 && (code!=e$eof || nent==0)) break; for(i=0; i < nent; i++) { cv$fdv(ret[i].dtm, j, base); for(j=0; j<ret[i].name.len; j++) if(ISUPPER(ret[i].name.dat[j])) ret[i].name.dat[j] = TOLOWER(ret[i].name.dat[j]); #define D_FILEPOS 36 if((lp = lalloc(D_FILEPOS + 1 + ret[i].name.len)) != NULL) { sprintf(lp->l_text, " %-6s %-4s %.18s %.*s", types[ret[i].info.type], rwlock[ret[i].info.rwl], base.dat, ret[i].name.len, ret[i].name.dat); llength(lp)--; for(blp=bp->b_linep->l_fp; blp!=bp->b_linep; blp=blp->l_fp) { j = strncmp(ret[i].name.dat, &blp->l_text[D_FILEPOS], ret[i].name.len); if(j < 0 || (j==0 && ret[i].name.len <= llength(blp)-D_FILEPOS)) break; } lp->l_fp = blp; lp->l_bp = blp->l_bp; blp->l_bp = lp; lp->l_bp->l_fp = lp; } else { clo$fu(dirunit, code); return NULL; } } } if(code!=e$eof) ewprintf("Directory read error %d", code); clo$fu(dirunit, code); bp->b_dotp = lforw(bp->b_linep); bp->b_doto = 0; bp->b_markp = NULL; strncpy(bp->b_fname, dirname, NFILEN); if((bp->b_modes[0] = name_mode("dired")) == NULL) { bp->b_modes[0] = &map_table[0]; ewprintf("Could not find mode dired"); return NULL; } bp->b_nmodes = 0; return bp; } d_makename(lp, fn) register LINE *lp; register char *fn; { register char *cp; if(llength(lp) <= D_FILEPOS) return ABORT; (VOID) strcpy(fn, curbp->b_fname); cp = fn + strlen(fn); bcopy(&lp->l_text[D_FILEPOS], cp, llength(lp) - D_FILEPOS); cp[llength(lp) - D_FILEPOS] = '\0'; return strncmp(&lp->l_text[2], "UFD", 3)==0 || strncmp(&lp->l_text[2], "SEG", 3)==0; } rename(old, new) char *old, *new; { struct {short len; char dat[128];} f; struct {short len; char dat[32];} oldent; char *cp; short code; old = adjustname(old); cp = rindex(old, '>'); strncpy(f.dat, old, f.len = cp - old); at$((short)k$setc, f, code); if(code!=0) return -1; cp++; strncpy(oldent.dat, cp, oldent.len = strlen(cp)); strncpy(f.dat, new, f.len = strlen(new)); cnam$$((char [])oldent.dat, oldent.len, (char [])f.dat, f.len, code); if(code!=0) { at$hom(code); return -1; } at$hom(code); return 0; } #endif #ifndef NO_DIR char *getwd(cwd) char *cwd; { char homedir[128]; /* cwd may not be word alligned */ short len, code; register char *cp1, *cp2; gpath$((short)k$homa, (short)-2, (char [])homedir, (short)128, len, code); if(code!=0) return NULL; cp1 = cwd; cp2 = homedir; while(len--) { *cp1 = ISUPPER(*cp2) ? TOLOWER(*cp2) : *cp2; cp1++; cp2++; } *cp1 = '\0'; return cwd; } #endif SHAR_EOF cat << \SHAR_EOF > sys/prime/make.cpl /* make for micrognuemacs on primos /* by Robert A. Larson &args como:-como; ph:-ph; v64v: -64v; &if ^ [null %como%] &then como make.como &if ^ [null %ph%] &then &do chap idle &end &do f &list *>sys>prime>sysdef.h *>sys>default>ttydef.h *>sys>default>chrdef.h &if ^ [exists [entryname %f%]] &then copy %f% -rpt &else &if [attrib [entryname %f%] -dtm] < [attrib %f% -dtm] ~ &then copy %f% -nq -rpt &end &set_var w := [attrib def.h -dtm] &if %w% < [attrib sysdef.h -dtm] &then &set_var w := [attrib sysdef.h -dtm] &if %w% < [attrib ttydef.h -dtm] &then &set_var w := [attrib ttydef.h -dtm] &if %w% < [attrib chrdef.h -dtm] &then &set_var w := [attrib chrdef.h -dtm] &if [null %v64v%] &then &do &if %w% < [attrib *>sys>prime>mg.options.c -dtm] ~ &then &set_var w := [attrib *>sys>prime>mg.options.c -dtm] &set_var binext := .bin &end &else &do &if %w% < [attrib *>sys>prime>mg.64v.options.c -dtm] ~ &then &set_var w := [attrib *>sys>prime>mg.64v.options.c -dtm] &set_var binext := .64v.bin &set_var m := ^ [exists stackptr$.64v.bin] &if ^ %m% &then &do &set_var bw := [attrib stackptr$.64v.bin -dtm] &set_var m := [attrib *>sys>prime>stackptr$.pma -dtm] > %bw% | %w% > %bw% &end &if %m% &then pma *>sys>prime>stackptr$.pma -list no -bin stackptr$.64v.bin &end &s dir := * &do f &list basic.c buffer.c dir.c dired.c display.c echo.c extend.c file.c ~ help.c kbd.c keymap.c line.c macro.c main.c match.c modes.c paragraph.c ~ random.c region.c search.c version.c window.c word.c &call compile &end &s dir := *>sys>prime &do f &list cinfo.c fileio.c spawn.c ttyio.c &call compile &end &s dir := *>sys>default &do f &list tty.c &call compile &end &s dir := *>termlib &do f &list fgetlr.c tgetent.c tgetflag.c tgetnum.c tgetstr.c tgoto.c tputs.c &call compile &end date time &set_var u := 0 &data bind version mg 2a no_wildcard no_iteration li ccmain &do f &items [wild @%binext% -single u] lo %f% &end li c_lib li dynt -all rdc &if [null %v64v%] &then &do map mg.map file mg.run &end &else &do map mg.64v.map file mg.64v.run &end &end date time &if ^ [null %como%] &then como -end &return &routine compile &set_var b := [before %f% '.']%binext% &set_var f := %dir%>%f% &set_var m := ^ [exists %b%] &if ^ %m% &then &do /* avoid attrib on non-existant file &set_var bw := [attrib %b% -dtm] &set_var m := [attrib %f% -dtm] > %bw% | %w% > %bw% &end &if %m% &then &do type %f% date &if [null %v64v%] &then &do ci %f% -optionsfile *>sys>prime>mg.options.c -bin %b% &end &else &do cc %f% -optionsfile *>sys>prime>mg.64v.options.c -bin %b% &end &end &return SHAR_EOF cat << \SHAR_EOF > sys/prime/mg.64v.options.c /* options for Primos Mg by Robert A. Larson /* 64v mode version -64v -newfortran /* define to indicate primos -define __50SERIES /* get routine names in stack dump -store_owner_field /* tell it to run fast -standardintrinsics -optimize /* find varargs.h in *>sys>prime -include *>sys>prime /* real options -define NO_DIRED /* no 64v mode support in dired code -define PREFIXREGION -define NOTAB SHAR_EOF cat << \SHAR_EOF > sys/prime/mg.options.c /* options for Prime MicroGnuEmacs by Robert A. Larson -32ix /* get routine names in stack dump -store_owner_field /* tell it to run fast -standardintrinsics -optimize 1 /* -pbstring was broken, and either got fixed or the other changes... -pbstring /* find varargs.h in *>sys>prime -include *>sys>prime /* real options -define PREFIXREGION -define NOTAB SHAR_EOF cat << \SHAR_EOF > sys/prime/readme MicroGnuEmacs 2a for primos This version has only been tested under primos 21.0 (.0, .1, .2s) in 32ix mode. The dired code does not run in 64v mode. (pl1 type ptr options(short) is a pain to simulate in 64v mode C.) The pre-rev 21 code should work, but ^p, ^j, and a true meta key will be unusable. One major problem has been descovered: mg will always fail if it is already in memory. (access violations, illegal segno, etc.) This is a bug that has been reported to prime. I recomend aliasing mg to remepf mg;mg . (Further oddity: sometime remepf gets access violations!) To get your line back to a normal mode after this has happended, set your terminal's parity to mark and type "set_async -pro tty -echo -xoff" followed by a linefeed. Some pre-21 verisons of the C library had a bug in open(), there is code that can be included with a #define in fileio.c to avoid this problem. The -pbstring option is broken in some Prime C compiler versions, if you notice strange problems try recompiling with -lbstring. The rev 21 version will not run over primenet since the terminal line cannot be conditioned properly. Support for Prime's extended character set rather than a meta key should not be hard to add. (chrdef.h, cinfo.c, and ttyio.c are what would need changes.) Installation: copy *>sys>prime>make.cpl ph make -ph -como [add -64v if 64v mode is needed.] When phantom is finished: copy mg.run cmdnc0>== [32ix mode] or copy mg.64v.run cmdnc0>=.run [64v mode] Global variable .termcap (or .termcap$) should be set to the pathname of the termcap file if the default of mg*>termcap is inappropraite, and .terminal_type$ (or .term) should be set to your terminal type. (Global variables are manipulated with the primos commands define_gvar, set_var, and list_var.) The C library must be in your search rules. Your .mg initalization file should be located in your inital attach point, if you don't have one the one in mg* will be used if available. (Terminal specific files may also be used.) Prime emacs's termcap file does not work well with mg. On pre-rev 21 systems, due to primos limitations, neither ^P or ^J are usable input, and true meta keys are not supported. If ^P is accidentaly typed and you have break enabled, mg may be resumed with the start command (and the screen should be refreshed with the recenter command ^L). Primos programs other than mg and the C compiler do not understand tab characters, so use of notab mode is recomended. The options to make.cpl are: -ph chap -idle -como create como file make.como -64v create 64v rather than 32ix mode version Compilation options are in the files mg.options.c and mg.64v.options.c. Warnings to potential modifiers: The source to mg contains tab characters. These should be converted to spaces before printing or editing with an editor that does not cope with tabs. Make.cpl does not have all dependencies, if one of the new .h files is changed, delete all applicable .bin files. SHAR_EOF cat << \SHAR_EOF > sys/prime/spawn.c /* * prime spawn.c for micrognuemacs */ #include "def.h" spawncli(f, n) { fortran void comlv$(); ttcolor(CTEXT); ttnowindow(); ttmove(nrow-1, 0); if (epresf != FALSE) { tteeol(); epresf = FALSE; } ttclose(); comlv$(); sgarbf = TRUE; /* Force repaint. */ ttopen(); #ifndef NO_DIR (void) dirinit(); /* current directory may have changed */ #endif return (TRUE); } SHAR_EOF cat << \SHAR_EOF > sys/prime/stackptr$.pma * stackptr$.pma -- used by 64v varargs.h.ins.cc * 02/22/87 Robert Larson Name chagned to avoid potention conflict SEG SYML RLIT ENT STACKPTR$ START EAXB SB%+4,* PRTN LINK STACKPTR$ ECB START END SHAR_EOF cat << \SHAR_EOF > sys/prime/sysdef.h /* * Prime specific definitions for MicroGnuEmacs 2a */ #include <stdio.h> #define PCC /* "[]" gets an error. */ #define KBLOCK 1024 /* Kill grow. */ #define GOOD 0 /* Good exit status. */ #define NO_RESIZE /* screen size is constant */ #define MAXPATH 256 /* typedefs for gnu version */ typedef int RSIZE; /* Type for file/region sizes */ typedef short KCHAR; /* Type for internal keystrokes */ /* * Macros used by the buffer name making code. * Start at the end of the file name, scan to the left * until BDC1 (or BDC2, if defined) is reached. The buffer * name starts just to the right of that location, and * stops at end of string (or at the next BDC3 character, * if defined). BDC2 and BDC3 are mainly for VMS. */ #define BDC1 '>' #define bcopy(from,to,len) if(1) {\ register char *from_=from, *to_=to; register int len_=len;\ while(len_--) *to_++ = *from_++;} else #define MALLOCROUND(m) (m+=7, m&=~7) /* round to 8 byte boundary */ char *gettermtype(); /* #define fails because of static storage */ #define unlink(f) delete(f) #define unlinkdir(f) delete(f) #ifdef DO_METAKEY #define METABIT 0400 #endif SHAR_EOF cat << \SHAR_EOF > sys/prime/ttyio.c /* * sys>prime>ttyio.c by Robert A. Larson * * The functions in this file * negotiate with the operating system for * keyboard characters, and write characters to * the display in a barely buffered fashion. */ #include "def.h" #define NOBUF 512 /* Output buffer size. */ char obuf[NOBUF]; /* Output buffer. */ short nobuf; /* characters in obuf */ int nrow; /* Terminal size, rows. */ int ncol; /* Terminal size, columns. */ short ospeed; /* Terminal speed, for termlib.l */ #ifndef PRE21 /* use undocumented calls to set terminal modes */ #define NSETTINGS 6 fortran void as$lin(), as$get(), as$set(); static short myline = 0; static short reset[NSETTINGS][2]; #else /* do the best we can without undocumented calls */ fortran short duplx$(); fortran void break$(); short duplx; #endif /* * This function gets called once, to set up * the terminal channel. */ ttopen() { #ifndef PRE21 short code, vers, len, bad; static short settings[NSETTINGS][2] = { {1, 0}, /* no echo */ {2, 0}, /* don't echo line feed for cr */ {3, 0}, /* disable ^S/^Q processing */ {11, 0}, /* parity: none */ {12, 3}, /* character length: 8 */ {15, 1}, /* tran protocol */ }; short plist[38][2]; short *p; register int i; if(myline==0) { as$lin(myline, code); if(code!=0) panic("Can't get terminal line"); /* do io to get terminal type before setting modes */ (void) gettermtype(); } p = &plist[0][0]; as$get(myline, vers, p, len, code); if(code!=0) panic("Can't determine current settings"); ospeed = plist[9-1][1]; for(i=0; i < NSETTINGS; i++) { reset[i][0] = settings[i][0]; reset[i][1] = plist[settings[i][0]-1][1]; } p = &settings[0][0]; as$set(myline, (short)0, p, (short)NSETTINGS, code, bad); if(code!=0) panic("Can't set terminal modes"); #else (void) gettermtype(); duplx = duplx$((short)-1); (void) duplx$((unsigned short)0140000); ospeed = 4; /* assume 9600 for debugging */ #endif nobuf = 0; } /* * This function gets called just * before we go back home to the shell. Put all of * the terminal parameters back. */ ttclose() { #ifndef PRE21 short code, bad; short *p; #endif ttflush(); #ifndef PRE21 p = &reset[0][0]; as$set(myline, (short)0, p, (short)NSETTINGS, code, bad); if(code!=0) { printf("Can't reset terminal modes: code: %d bad: %d\n", code, bad); exit(1); } #else (void) duplx$(duplx); #endif } /* * Write character to the display. * Characters are buffered up, to make things * a little bit more efficient. */ ttputc(c) { if (nobuf >= NOBUF) ttflush(); obuf[nobuf++] = c; } /* * Flush output. */ ttflush() { fortran void tnoua(); if (nobuf != 0) { tnoua((char [])obuf, nobuf); nobuf = 0; } } /* * Read character from terminal. * Parity bit is stripped, to be normal */ ttgetc() { fortran void t1in(); short c; t1in(c); #ifdef DO_METAKEY if(c&0200) c |= METABIT; #endif c |= 0200; #ifdef PRE21 if(c=='\n') return '\r'; /* fix repping done by primos */ #ifdef DO_METAKEY if(c==('\n'|METABIT)) return '\r'|METABIT; #endif #endif return c; } int typeahead() { fortran short tty$in(); return tty$in() < 0; } panic(s) char *s; { fortran void tnoua(), tnou(); ttclose(); tnoua((char [])"Panic: ", (short)7); tnou((char [])s, (short)strlen(s)); exit(1); } #ifndef NO_DPROMPT ttwait() { register short i = 20; fortran short tty$in(); fortran void sleep$(); while(i--) { if(tty$in()<0) return FALSE; sleep$((long)100); } return tty$in() >= 0; } #endif char *gettermtype() { register char *cp; char *gvget(); static char termtype[64] = ""; if(termtype[0]!='\0') return termtype; cp = gvget(".TERMINAL_TYPE$"); /* get terminal type */ if(cp==NULL) cp = gvget(".TERM"); if(cp != NULL) { strncpy(termtype, cp, 64); return termtype; } fputs("Terminal type? ", stdout); fgets(termtype, 64, stdin); putchar('\n'); termtype[strlen(termtype)-1] = '\0'; /* chop off \n */ return termtype; } SHAR_EOF cat << \SHAR_EOF > sys/prime/varargs.h.ins.cc /* varargs.h.ins.cc -- varargs for both 32ix and 64v mode C unser primos */ /* 02/22/87 Robert Larson Cleanup (Variable name changes to avoid conflicts) */ #ifdef __CI /* varargs.h for 32ix mode on a Prime 9955 */ /* Modified from the Primix varargs.h by James M Synge. */ typedef char *va_list; #define va_alist _va_arg1 #define va_dcl char va_alist; #define va_start(list) list = ((va_list)(&_va_arg1)) #define va_end(list) #define va_arg(list,mode) ((mode *)((list) += sizeof(mode)))[-1] #else typedef int **va_list; extern short *stackptr$(); #define va_alist \ /* first argument at SB%+45 */ \ _v0,_v1,_v2,_v3,_v4,_v5,_v6,_v7,_v8,_v9,_v10, \ _v11,_v12,_v13,_v14,_v15,_v16,_v17,_v18,_v19,_v20, \ _v21,_v22,_v23,_v24,_v25,_v26,_v27,_v28,_v29,_v30, \ _v31,_v32,_v33,_v34,_v35,_v36,_v37,_v38,_v39,_v40, \ _v41,_v42,_v43,_v44,_v45,_v46,_v47,_v48,_v49,_v50, \ _v51,_v52,_v53,_v54,_v55,_v56,_v57,_v58,_v59,_v60, \ _v61,_v62,_v63,_v64,_v65,_v66,_v67,_v68,_v69 #define va_dcl int *_v0; #define va_start(list) list = ((va_list)(stackptr$() + 042)) #define va_end(list) #define va_arg(list, mode) ( (sizeof(mode) == sizeof(char *)) ? \ ((**(mode **)((list)++))) : \ ((mode) (**((list)++))) ) #endif SHAR_EOF # End of shell archive exit 0 -------