BLARSON@ECLA.USC.EDU (Bob Larson) (05/26/88)
comp.sources.misc: Volume 3, Issue 35 Submitted-By: "Bob Larson" <BLARSON@ECLA.USC.EDU> Archive-Name: mg2a/Part11 # 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: # termlib/fgetlr.c # termlib/isdigit.c # termlib/testtcp.c # termlib/tgetent.c # termlib/tgetflag.c # termlib/tgetnum.c # termlib/tgetstr.c # termlib/tgoto.c # termlib/tputs.c # termlib/ttest.c # This archive created: Tue May 17 21:42:47 1988 # By: blarson if test -d termlib then true else mkdir termlib fi cat << \SHAR_EOF > termlib/fgetlr.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* * LIBRARY FUNCTION * * fgetlr get logical record from a file * * KEY WORDS * * fgetlr * string functions * * SYNOPSIS * * char *fgetlr(bp,bpsize,fp) * char *bp; * int bpsize; * FILE *fp; * * DESCRIPTION * * Reads the next logical record from stream "fp" into buffer "bp" * until next unescaped newline, "bpsize" minus one characters * have been read, end of file, or read error. * The last character read is followed by a NULL. * * A logical record may span several physical records by having * each newline escaped with the standard C escape character * (backslash). * * This is particularly useful for things like the termcap * file, where a single entry is too long for one physical * line, yet needs to be treated as a single record. * * Returns its first argument unless an end of file or read * error occurs prior to any characters being read. * * BUGS * * The only way to know if read was terminated due to buffer size * limitation is to test for a newline before the terminating * null. * */ #include <stdio.h> /* * PSEUDO CODE * * Begin fgetlr * If read fails then * Return NULL. * Else * Find out how many characters were read. * Initialize pointer to terminating null. * If last char read was newline then * If newline was escaped then * Replace backslash with the newline. * Replace newline with null. * Read and append more. * End if * End if * Return buffer pointer. * End if * End fgetlr * */ char *fgetlr(bp,bpsize,fp) char *bp; int bpsize; FILE *fp; { int numch; char *cp; if (fgets(bp,bpsize,fp) == NULL) { return(NULL); } else { numch = strlen(bp); cp = &bp[numch]; if (*--cp == '\n') { if (numch > 1 && *--cp == '\\') { *cp++ = '\n'; *cp = NULL; fgetlr(cp,bpsize-numch+1,fp); } } return(bp); } } SHAR_EOF cat << \SHAR_EOF > termlib/isdigit.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* * LIBRARY FUNCTION * * isdigit test character for numeric property * * SYNOPSIS * * int isdigit(ch) * char ch; * * DESCRIPTION * * Returns TRUE or FALSE depending upon whether the specified * character is a numeric character or not. * * BUGS * * May fail on machines in which native character set is not ASCII. * */ #include <stdio.h> #define TRUE 1 #define FALSE 0 int isdigit(ch) char ch; { if (ch > '9' || ch < '0') { return(FALSE); } else { return(TRUE); } } SHAR_EOF cat << \SHAR_EOF > termlib/testtcp.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* * TEST PROGRAM * * testtcp test termcap functions * * KEY WORDS * * test routines * termcap test * * SYNOPSIS * * termcap [-efns] terminal [capability [capability ...]] * * -e => expand string capability given by -s * -f => determine boolean capabilities for terminal * -n => determine numeric capabilities for terminal * -s => determine string capabilities for terminal * * terminal => terminal name as given in termcap file * capability => a boolean, numeric, or string capability * * NOTE: All capabilities must be of same type, as * given by [-fns]. * * If terminal is only argument then entire entry is * printed. * * DESCRIPTION * * Provides way to test termcap functions. Can find * and print an entire termcap terminal entry, or various * capabilities from the entry. * * AUTHOR * * Fred Fish * */ #include <stdio.h> #define TRUE 1 #define FALSE 0 #define NO_FILE -1 /* Returned if can't open file */ #define NO_ENTRY 0 /* Returned if can't find entry */ #define SUCCESS 1 /* Returned if entry found ok */ #define TRUNCATED 2 /* Returned if entry found but trunc */ #define BUFFER_SIZE 1024 int eflag = FALSE; int fflag = FALSE; int nflag = FALSE; int sflag = FALSE; int got_terminal = FALSE; int got_capability = FALSE; /* * FUNCTION * * main termcap test entry point * * KEY WORDS * * main * * SYNOPSIS * * main(argc,argv) * int argc; * char *argv[]; * * DESCRIPTION * * This is where the termcap test starts executing. All argument list * switches are processed first, then all the specified * capability identification strings are processed. * */ /* * PSEUDO CODE * * Begin main * Process command line options. * For each argument list field * If field was not erased during option processing * If terminal name field not yet processed then * Process an assumed terminal name field. * Set terminal name processed flag. * Else * Process a capability field. * Set capability field processed flag. * End if * End if * End for * If no capabilities processed then * Simply dump buffer. * End if * End main * */ main(argc, argv) int argc; char *argv[]; { char *argp; int argnum; char buffer[BUFFER_SIZE]; options(argc,argv); for (argnum = 1; argnum < argc; argnum++) { if ((argp = argv[argnum]) != NULL) { if (!got_terminal) { terminal(buffer,argp); got_terminal = TRUE; } else { capability(argp); got_capability = TRUE; } } } if (got_terminal && !got_capability) { printf("%s",buffer); } } /* * FUNCTION * * options process command line options * * SYNOPSIS * * options(argc,argv) * int argc; * char *argv[]; * * DESCRIPTION * * Scans argument list, processing each switch as it is * found. The pointer to each switch string is then * replaced with a NULL to effectively erase the switch * argument. * */ /* * PSEUDO CODE * * Begin options * For each argument in the argument list * Get pointer to first char of argument. * If the argument is a switch then * Replace argument pointer with NULL. * Look at next argument character. * While there is another argument character * Switch on the argument character * Case "EXPAND": * Set expand (e) flag. * Break out of switch. * Case "BOOLEAN": * Set boolean (f) flag. * Break out of switch. * Case "NUMERIC": * Set numeric flag. * Break out of switch. * Case "STRING": * Set string flag. * Break out of switch. * Default: * Abort with usage message. * End switch * End while * End if * End for * End options * */ options(argc, argv) int argc; char *argv[]; { int i; char c; /* 1st char of current command-line argument */ char *cp; /* current argument pointer */ for (i=1; i<argc; i++) { cp = argv[i]; if (*cp == '-') { argv[i] = NULL; cp++; while (c = *cp++) { switch (c) { case 'e': eflag = TRUE; break; case 'f': fflag = TRUE; break; case 'n': nflag = TRUE; break; case 's': sflag = TRUE; break; default: usage(); } } } } } /* * FUNCTION * * usage give usage message and abort * * KEY WORDS * * usage * help processing * abort locations * * SYNOPSIS * * usage() * * DESCRIPTION * * Usage is typically called when a problem has been * detected in the argument list. * It prints a usage message and exits. * */ /* * PSEUDO CODE * * Begin usage * Print usage message. * Exit. * End usage * */ usage() { printf("Usage: termcap [-fns] terminal [capability [capability ... ]]\n"); exit(); } terminal(buffer,name) char *buffer; char *name; { int status; status = tgetent(buffer,name); switch (status) { case NO_FILE: fprintf(stderr,"Can't find a termcap data base file.\n"); exit(); case NO_ENTRY: fprintf(stderr,"Can't find entry \"%s\"\n",name); exit(); case TRUNCATED: fprintf(stderr,"Warning --- entry \"%s\" too long\n",name); break; case SUCCESS: break; default: fprintf(stderr,"? tgetent returned illegal status %d\n",status); exit(); } } capability(id) char *id; { int value; char buffer[256]; char *area; char *ep, *tgoto(); if (fflag) { value = tgetflag(id); if (value) { printf("%s TRUE\n",id); } else { printf("%s FALSE\n",id); } } else if (nflag) { value = tgetnum(id); printf("%s = %o octal %d decimal\n",id,value,value); } else if (sflag) { area = buffer; tgetstr(id,&area); if (eflag) { ep = tgoto(buffer,75,23); } doprint(id,buffer); if (eflag) { doprint(id,ep); ep = tgoto(buffer,1,2); doprint(id,ep); } } } doprint(id,cp) char *id; char *cp; { printf("%s = \"",id); for ( ; *cp != NULL; cp++) { if (*cp < 040) { printf("^%c",*cp |= 0100); } else { printf("%c",*cp); } } printf("\"\n"); } SHAR_EOF cat << \SHAR_EOF > termlib/tgetent.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* * Modified: * 30-Apr-86 Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic * Instead of using VAX C getenv("TERM"), which does not * return the value of logical name "TERM", translate the * logical name by hand. * 11-Oct-86 Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic * Support tc capability to allow the library to use standard * termcaps. Rewrote tgetent to look for tc capability * and add new terminal definition to the caller's buffer. * This makes it rather possible to overflow the caller's * buffer, but the library doesn't make any claim that it * won't overwrite the buffer anyway... * 27-Jan-88 Bob Larson blarson@ecla.usc.edu * Add primos (__50SERIES) support. * 1-Feb-88 Sandra Loosemore (sandra@cs.utah.edu) * Change default termcap file for VMS to be the same place * that GNU puts it. * 23-Apr-88 Bob Larson * merge primos and vms changes */ /* * LIBRARY FUNCTION * * tgetent load buffer with entry for specified terminal * * KEY WORDS * * termcap functions * utility routines * * SYNOPSIS * * int tgetent(bp,name) * char *bp; * char *name; * * DESCRIPTION * * Extracts the entry for terminal <name> from the termcap file * and places it in the character buffer <bp>. It is currently * assumed that bp is at least 1024 characters. If the entry in * the termcap file is larger than 1023 characters the excess * characters will be discarded and appropriate status will * be returned. * * Also note that since bp is used by other termcap * routines, the storage associated with the termcap entry * cannot be freed until all termcap calls are completed. * * Tgetent can be directed to look in a file other than * the default (/etc/termcap) by defining an environment * variable called TERMCAP to be the pathname of the desired * termcap file. This is useful for debugging new entries. * NOTE: the pathname MUST begin with a '/' character. * * Also, if the string assigned to TERMCAP does not begin with * a '/' and if the environment variable TERM matches <name> then * the string assigned to TERMCAP is copied to buffer <bp> * instead of reading a termcap file. * * RETURNS * * -1 if the termcap file cannot be opened * 0 if no entry in termcap file matches <name> * 1 if extraction is successful with no errors * 2 if extraction is successful but entry truncated * * SEE ALSO * * tgetnum extract numeric type capability * tgetflag test boolean type capability * tgetstr get string value of capability * * AUTHOR * * Fred Fish * */ #include <stdio.h> #define TRUE 1 #define FALSE 0 #define BUFSIZE 1024 /* Assumed size of external buffer */ #define NO_FILE -1 /* Returned if can't open file */ #define NO_ENTRY 0 /* Returned if can't find entry */ #define SUCCESS 1 /* Returned if entry found ok */ #define TRUNCATED 2 /* Returned if entry found but trunc */ #ifdef __50SERIES #define DEFAULT_FILE "mg*>termcap" #else #define DEFAULT_FILE "/etc/termcap" /* default termcap filename */ #ifdef VAXC #define index strchr #endif #endif char *_tcpbuf; /* Place to remember buffer pointer */ FILE *fp; /* Termcap file */ static FILE *find_file(); extern char *index(); /* * PSEUDO CODE * * Begin tgetent * Erase any previous buffer contents. * Remember the buffer pointer. * If termcap file is not found then * If buffer was filled anyway then * Return SUCCESS. * Else * Return NO_FILE. * End if * Else * Find entry associated with name * While an entry was found and limit not reached * If no tc capability found Then * Exit while loop with status = SUCCESS * Else * Call getent to get entry indicated by tc= * If entry not found then * Exit loop with status != SUCCESS * End if * Concatenate entry into buffer * End If * End while * End if * Close termcap file * Return status code * End tgetent * */ static int getent(); int tgetent(bp,name) char *bp; char *name; { char *tc, *tcbufp, tcbuf[80], termbuf[BUFSIZE], *tgetstr(); char *bufp, *cp; /* current start of buffer */ int limit = 10; /* maximum nesting */ int status; /* return from getent() */ *bp = '\0'; /* clear buffer */ _tcpbuf = bp; /* save base of buffer */ /* Look for termcap file. If NULL, find_file may have found a */ /* a valid termcap string in the environment variable TERMCAP. */ /* If non-null, attempt to find the entry in the termcap file */ if ((fp = find_file(bp)) == NULL) { if (*bp != NULL) return(SUCCESS); else return(NO_FILE); } status = getent(bp, name);/* look for main entry */ /* Start looking for tc capabilities in the termcap. If * found, concatenate the entry for the new terminal to the * current buffer and try again. To avoid infinite loops, * allow only 10 loops through this process. */ while ((status == SUCCESS) && limit--) { /* look for tc capability. If none found, exit loop */ tcbufp = tcbuf; if (((tc = tgetstr("tc",&tcbufp)) == NULL) || (*tc == '\0')) { status = SUCCESS;/* no more tc= entries */ break; } /* Attempt to get next entry. Exit loop if unsuccessful */ if ((status = getent(termbuf, tcbuf)) != SUCCESS) break; /* Copy new entry into buffer, right at "tc=" */ for (bufp = bp; *bufp; bufp++) /* find tc= */ if ((*bufp=='t') && (bufp[1]=='c') && (bufp[2]=='=')) break; if ((cp = index(termbuf,':')) == NULL) cp = termbuf; strcpy(bufp, cp + 1); } /* close termcap file and return the status */ fclose(fp); return status; } /* * INTERNAL FUNCTION * * getent find termcap entry in termcap file * * KEY WORDS * * internal functions * getent * * SYNOPSIS * * static int getent(bp,name) * char *bp; * char *name; * * DESCRIPTION * * Getent is called by tgetent each time tgetent attempts to * read a capability from the termcap database file. Places * the entry in the buffer pointed to by bp * * * PSEUDOCODE * * Begin Getent * Seek to beginning of termcap file * Clear buffer * While records left to process * If this is entry is what we want then * If entry was truncated then * Return TRUNCATED status * Else * Return SUCCESS status. * End if * End if * End while * Return NO_ENTRY status. * End */ static int getent(bp,name) char *bp; /* Pointer to buffer (1024 char min) */ char *name; /* Pointer to terminal entry to find */ { *bp = '\0'; /* clear buffer */ lseek(fileno(fp), 0L, 0l); /* rewind termcap file */ while (fgetlr(bp,BUFSIZE,fp)) { if (gotcha(bp,name)) { if (bp[strlen(bp)-1] != '\n') { return(TRUNCATED); } else { return(SUCCESS); } } } return(NO_ENTRY); } /* * INTERNAL FUNCTION * * find_file find the termcap file and open it if possible * * KEY WORDS * * internal functions * find_file * * SYNOPSIS * * static FILE *find_file(bp) * char *bp; * * DESCRIPTION * * Attempts to locate and open the termcap file. Also handles * using the environment TERMCAP string as the actual buffer * (that's why bp has to be an input parameter). * * If TERMCAP is defined an begins with a '/' character then * it is taken to be the pathname of the termcap file and * an attempt is made to open it. If this fails then * the default termcap file is used instead. * * If TERMCAP is defined but does not begin with a '/' then * it is assumed to be the actual buffer contents provided * that <name> matches the environment variable TERM. * * BUGS * * There is currently no way to be sure which termcap * file was opened since the default will always be * tried. * */ /* * PSEUDO CODE * * Begin find_file * If there is a TERMCAP environment string then * If the string is not null then * If the string is a pathname then * If that file is opened successfully then * Return its pointer. * End if * Else * If there is a TERM environment string then * If TERM matches <name> then * Copy TERMCAP string to buffer. * Return NULL for no file. * End if * End if * End if * End if * End if * Open default termcap file and return results. * End find_file * */ #ifdef __50SERIES static FILE *find_file(bp) char *bp; { char *cp; char *gvget(); if((cp = gvget(".TERMCAP")) != NULL && *cp) return fopen(cp, "r"); if((cp = gvget(".TERMCAP$")) != NULL && *cp) return fopen(cp, "r"); return fopen(DEFAULT_FILE, "r"); } #else #ifdef VAXC char *trnlnm(); #endif static FILE *find_file(bp) char *bp; { FILE *fp, *fopen(); char *cp, *ncp, *getenv(), vmsname[132]; if ((cp = getenv("TERMCAP")) != NULL) { if (*cp != NULL) { if (*cp == '/') { if ((fp = fopen(cp,"r")) != NULL) { return(fp); } } else { #ifdef VAXC if ((ncp = trnlnm("TERM")) != NULL) { #else if ((ncp = getenv("TERM")) != NULL) { #endif if (strcmp(cp,ncp) == 0) { strcpy(bp,cp); return((FILE *)NULL); } } } } } #ifdef VAXC if ((fp = fopen("emacs_library:[etc]termcap.dat","r")) != NULL) return(fp); #endif return(fopen(DEFAULT_FILE,"r")); } #endif /* __50SERIES */ /* * INTERNAL FUNCTION * * gotcha test to see if entry is for specified terminal * * SYNOPSIS * * gotcha(bp,name) * char *bp; * char *name; * * DESCRIPTION * * Tests to see if the entry in buffer bp matches the terminal * specified by name. Returns TRUE if match is detected, FALSE * otherwise. * */ /* * PSEUDO CODE * * Begin gotcha * If buffer character is comment character then * Return FALSE since remainder is comment * Else * Initialize name scan pointer. * Compare name and buffer until end or mismatch. * If valid terminators for both name and buffer strings * Return TRUE since a match was found. * Else * Find next non-name character in buffer. * If not an alternate name separater character * Return FALSE since no more names to check. * Else * Test next name and return results. * End if * End if * End if * End gotcha * */ gotcha(bp,name) char *bp; char *name; { char *np; if (*bp == '#') { return(FALSE); } else { np = name; while (*np == *bp && *np != NULL) {np++; bp++;} if (*np == NULL && (*bp == NULL || *bp == '|' || *bp == ':')) { return(TRUE); } else { while (*bp != NULL && *bp != ':' && *bp != '|') {bp++;} if (*bp != '|') { return(FALSE); } else { return(gotcha(++bp,name)); } } } } SHAR_EOF cat << \SHAR_EOF > termlib/tgetflag.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* * Modified: * 30-Apr-86 Mic Kaczmarczik * #define index to strchr if VAX C * */ /* * LIBRARY FUNCTION * * tgetflag extract boolean termcap capability * * KEY WORDS * * termcap * * SYNOPSIS * * tgetflag(id) * char *id; * * DESCRIPTION * * Returns TRUE if specified id is present in terminal * entry, FALSE otherwise. * */ #include <stdio.h> #ifdef VAXC #define index strchr #endif #define TRUE 1 #define FALSE 0 extern char *_tcpbuf; /* Termcap entry buffer pointer */ /* * PSEUDO CODE * * Begin tgetflag * Initialize pointer to the termcap entry buffer. * While there is a field to process * Skip over the field separator character. * If this is the entry we want then * If entry is identifier only then * Return TRUE * Else * Return FALSE * End if * End if * End while * Return FALSE as default. * End tgetflag * */ tgetflag(id) char *id; { char *bp; extern char *index(); bp = _tcpbuf; while ((bp = index(bp,':')) != NULL) { bp++; if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) { if (*bp == NULL || *bp++ == ':') { return(TRUE); } else { return(FALSE); } } } return(FALSE); } SHAR_EOF cat << \SHAR_EOF > termlib/tgetnum.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* Modified: * 30-Apr-86 Mic Kaczmarczik * Use ctype.h macros instead of the function isdigit(). * #define index to strchr if VAXC */ /* * LIBRARY FUNCTION * * tgetnum extract numeric option from termcap entry * * KEY WORDS * * termcap * ce functions * * SYNOPSIS * * tgetnum(id) * char *id; * * DESCRIPTION * * Returns numeric value of capability <id>, or -1 if <id> * is not found. Knows about octal numbers, which * begin with 0. * */ #include <stdio.h> #include <ctype.h> #ifdef VAXC #define index strchr #endif extern char *_tcpbuf; /* Termcap entry buffer pointer */ /* * PSEUDO CODE * * Begin tgetnum * Initialize pointer to the termcap entry buffer. * While there is a field to process * Skip over the field separator character. * If this is the entry we want then * If the entry is not a numeric then * Return failure value. * Else * Initialize value to zero. * If number begins with zero then * Set accumulation base to 8. * Else * Set accumulation base to 10. * End if * While there is a numeric character * Accumulate the value. * End while * Return value. * End if * End if * End while * Return failure value. * End tgetnum * */ tgetnum(id) char *id; { int value, base; char *bp; extern char *index(); bp = _tcpbuf; while ((bp = index(bp,':')) != NULL) { bp++; if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) { if (*bp != NULL && *bp++ != '#') { return(-1); } else { value = 0; if (*bp == '0') { base = 8; } else { base = 10; } while (isdigit(*bp)) { value *= base; value += (*bp++ - '0'); } return(value); } } } return(-1); } SHAR_EOF cat << \SHAR_EOF > termlib/tgetstr.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* Modified: * 30-Apr-86 Mic Kaczmarczik * Use ctype.h macros instead of the function isdigit(). * #define index() to be strchr() if VAX C */ /* * LIBRARY FUNCTION * * tgetstr extract string capability from termcap entry * * KEY WORDS * * termcap * * SYNOPSIS * * char *tgetstr(id,area) * char *id; * char **area; * * DESCRIPTION * * Gets the string capability for <id>, placing it in * the buffer at *area, and advancing *area to point * to next available storage. * * For example, if the following capabilities are * in the termcap file: * * ZZ=zzzz * YY=yyyyyy * WW=www * * then successive calls using YY, ZZ, and WW will * build the following buffer: * * yyyyyy0zzzz0www0 * * The first call will return a pointer to yyyyyy, the * second will return a pointer to zzzz and the third * will return a pointer to www. Note that each * string is null terminated, as are all C strings. * * Characters preceded by the carot character (\136) * are mapped into the corresponding control character. * For example, the two character sequence ^A becomes * a single control-A (\001) character. * * The escape character is the normal C backslash and * the normal C escape sequences are recognized, along * with a special sequence for the ASCII escape character * (\033). The recognized sequences are: * * \E => '\033' (ASCII escape character) * \b => '\010' (ASCII backspace character) * \f => '\014' (ASCII form feed character) * \n => '\012' (ASCII newline/linefeed char) * \r => '\015' (ASCII carriage return char) * \t => '\011' (ASCII tab character) * \ddd => '\ddd' (arbitrary ASCII digit) * \x => 'x' (ordinary ASCII character) * */ #include <stdio.h> #include <ctype.h> #ifdef VAXC #define index strchr #endif extern char *_tcpbuf; /* Termcap entry buffer pointer */ /* * PSEUDO CODE * * Begin tgetstr * Initialize pointer to the termcap entry buffer. * While there is a field to process * Skip over the field separator character. * If this is the entry we want then * If the entry is not a string then * Return NULL. * Else * Transfer string and rtn pointer. * End if * End if * End while * Return NULL * End tgetstr * */ char *tgetstr(id,area) char *id; char **area; { char *bp; extern char *index(); static char *decode(); bp = _tcpbuf; while ((bp = index(bp,':')) != NULL) { if (*++bp == NULL) break; if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) { if (*bp != NULL && *bp++ != '=') { return(NULL); } else { return(decode(bp,area)); } } } **area = NULL; bp = (*area)++; return(bp); } /* * INTERNAL FUNCTION * * decode transfer string capability, decoding escapes * * SYNOPSIS * * static char *decode(bp,area) * char *bp; * char **area; * * DESCRIPTION * * Transfers the string capability, up to the next ':' * character, or null, to the buffer pointed to by * the pointer in *area. Note that the initial * value of *area and *area is updated to point * to the next available location after the null * terminating the transfered string. * * BUGS * * There is no overflow checking done on the destination * buffer, so it better be large enough to hold * all expected strings. * */ /* * PSEUDO CODE * * Begin decode * Initialize the transfer pointer. * While there is an input character left to process * Switch on input character * Case ESCAPE: * Decode and xfer the escaped sequence. * Break * Case CONTROLIFY: * Controlify and xfer the next character. * Advance the buffer pointer. * Break * Default: * Xfer a normal character. * End switch * End while * Null terminate the output string. * Remember where the output string starts. * Update the output buffer pointer. * Return pointer to the output string. * End decode * */ static char *decode(bp,area) char *bp; char **area; { char *cp, *bgn; char *do_esc(); cp = *area; while (*bp != NULL && *bp != ':') { switch(*bp) { case '\\': bp = do_esc(cp++,++bp); break; case '^': *cp++ = *++bp & 037; bp++; break; default: *cp++ = *bp++; break; } } *cp++ = NULL; bgn = *area; *area = cp; return(bgn); } /* * INTERNAL FUNCTION * * do_esc process an escaped sequence * * SYNOPSIS * * char *do_esc(out,in); * char *out; * char *in; * * DESCRIPTION * * Processes an escape sequence pointed to by * in, transfering it to location pointed to * by out, and updating the pointer to in. * */ /* * PSEUDO CODE * * Begin do_esc * If the first character is not a NULL then * If is a digit then * Set value to zero. * For up to 3 digits * Accumulate the sum. * End for * Transfer the sum. * Else if character is in remap list then * Transfer the remapped character. * Advance the input pointer once. * Else * Simply transfer the character. * End if * End if * Return updated input pointer. * End do_esc * */ static char *maplist = { "E\033b\bf\fn\nr\rt\t" }; char *do_esc(out,in) char *out; char *in; { int count; char ch; extern char *index(); char *cp; if (*in != NULL) { if (isdigit(*in)) { ch = 0; for (count = 0; count < 3 && isdigit(*in); in++) { ch <<= 3; ch |= (*in - '0'); } *out++ = ch; } else if ((cp = index(maplist,*in)) != NULL) { *out++ = *++cp; in++; } else { *out++ = *in++; } } return(in); } SHAR_EOF cat << \SHAR_EOF > termlib/tgoto.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* * Modified: * 1 May 86 ...!ihnp4!ut-sally!ut-ngp!mic * Now forces a '\0' at end of tgoto string. Tgoto wasn't, * and this screwed up VT100-style (i.e. variable) cursor * addressing. */ /* * LIBRARY FUNCTION * * tgoto expand cursor addressing string from cm capability * * KEY WORDS * * termcap * * SYNOPSIS * * char *tgoto(cm,destcol,destline) * char *cm; * int destcol; * int destline; * * DESCRIPTION * * Returns cursor addressing string, decoded from the cm * capability string, to move cursor to column destcol on * line destline. * * The following sequences uses one input argument, either * line or column, and place the appropriate substitution * in the output string: * * %d substitute decimal value (in ASCII) * %2 like %d but forces field width to 2 * %3 like %d but forces field width to 3 * %. like %c * %+x like %c but adds ASCII value of x * * The following sequences cause processing modifications * but do not "use up" one of the arguments. If they * act on an argument they act on the next one to * be converted. * * %>xy if next value to be converted is * greater than value of ASCII char x * then add value of ASCII char y. * %r reverse substitution of line * and column (line is substituted * first by default). * %i causes input values destcol and * destline to be incremented. * %% gives single % character in output. * * BUGS * * Does not implement some of the more arcane sequences for * radically weird terminals (specifically %n, %B, & %D). * If you have one of these you deserve whatever happens. * */ /* * Miscellaneous stuff */ #include <stdio.h> #define MAXARGS 2 static char *in; /* Internal copy of input string pointer */ static char *out; /* Pointer to output array */ static int args[MAXARGS]; /* Maximum number of args to convert */ static int pcount; /* Count of args processed */ static char output[64]; /* Converted string */ /* * PSEUDO CODE * * Begin tgoto * If no string to process then * Return pointer to error string. * Else * Initialize pointer to input string. * Initialize pointer to result string. * First arg is line number by default. * Second arg is col number by default. * No arguments processed yet. * While there is another character to process * If character is a not a % character then * Simply copy to output. * Else * Process the control sequence. * End if * End while * Return pointer to static output string. * End if * End tgoto * */ char *tgoto(cm,destcol,destline) char *cm; int destcol; int destline; { static int process(); if (cm == NULL) { return("OOPS"); } else { in = cm; out = output; args[0] = destline; args[1] = destcol; pcount = 0; while (*in != NULL) { if (*in != '%') { *out++ = *in++; } else { process(); } } *out = NULL; /* Just to make sure */ return(output); } } /* * INTERNAL FUNCTION * * process process the conversion/command sequence * * SYNOPSIS * * static process() * * DESCRIPTION * * Processes the sequence beginning with the % character. * Directly manipulates the input string pointer, the * output string pointer, and the arguments. Leaves * the input string pointer pointing to the next character * to be processed, and the output string pointer pointing * to the next output location. If conversion of * one of the numeric arguments occurs, then the pcount * is incremented. * */ /* * PSEUDO CODE * * Begin process * Skip over the % character. * Switch on next character after % * Case 'd': * Process %d type conversion (variable width). * Reinitialize output pointer. * Break; * Case '2': * Process %d type conversion (width 2). * Reinitialize output pointer. * Break; * Case '3': * Process %d type conversion (width 3). * Reinitialize output pointer. * Break; * Case '.' * Process %c type conversion. * Break; * Case '+': * Process %c type conversion with offset. * Break; * Case '>': * Process argument modification. * Break; * Case 'r': * Process argument reversal. * Break; * Case 'i': * Increment argument values. * Break; * Case '%': * Copy to output, incrementing pointers. * Break; * End switch * End process * */ static process() { int temp; in++; switch(*in++) { case 'd': sprintf(out,"%d",args[pcount++]); out = &output[strlen(output)]; break; case '2': sprintf(out,"%02d",args[pcount++]); out = &output[strlen(output)]; break; case '3': sprintf(out,"%03d",args[pcount++]); out = &output[strlen(output)]; break; case '.': *out++ = args[pcount++]; break; case '+': *out++ = args[pcount++] + *in++; break; case '>': if (args[pcount] > *in++) { args[pcount] += *in++; } else { in++; } break; case 'r': temp = args[pcount]; args[pcount] = args[pcount+1]; args[pcount+1] = temp; break; case 'i': args[pcount]++; args[pcount+1]++; break; case '%': *out++ = '%'; break; } } SHAR_EOF cat << \SHAR_EOF > termlib/tputs.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* Modified: * 30-Apr-86 Mic Kaczmarczik * - Use ctype.h macros instead of the function isdigit(). * - Use VMS speed value for ospeed -- in microEmacs * this is obtainted by ttinit(). */ /* * LIBRARY FUNCTION * * tputs output string with appropriate padding * * KEY WORDS * * termcap * * SYNOPSIS * * tputs(cp,affcnt,outc) * char *cp; * int affcnt; * int (*outc)(); * * DESCRIPTION * * Outputs string pointed to by cp, using function outc, and * following it with the appropriate number of padding characters. * Affcnt contains the number of lines affected, which is used * as a multiplier for the specified per line pad time. If * per line pad count is not applicable, affcnt should be 1, * NOT zero. * * The format of the string pointed to by cp is: * * [pad time][*]<string to send> * * where: pad time => time to delay in milliseconds * * => specifies that time is per line * * The pad character is assumed to reside in the external * variable "PC". Also, the external variable "ospeed" * should contain the output speed of the terminal as * encoded in /usr/include/sgtty.h (B0-B9600). * * SYSTEM DEPENDENCIES * * On VMS, the external variable "ospeed" should contain the * output speed of the terminal as obtained from byte 3 of * the iosb status buffer, using the IO$_SENSEMODE QIO. * The table times[] compiles into the correct values for VMS, * and, happily, also handles 19200 baud. * * BUGS * * If ospeed is 0 for some reason, there is the chance of a * divide by 0 operation. * */ /* * Miscellaneous stuff */ #include <stdio.h> #include <ctype.h> extern char PC; /* Pad character to use */ extern short ospeed; /* Encoding of output speed */ #if VMS static int times[] = { 10000, /* Tenths of ms per char 0 baud (bogus) */ 2000, /* Tenths of ms per char 50 baud */ 1333, /* Tenths of ms per char 75 baud */ 909, /* Tenths of ms per char 110 baud */ 743, /* Tenths of ms per char 134 baud */ 666, /* Tenths of ms per char 150 baud */ 333, /* Tenths of ms per char 300 baud */ 166, /* Tenths of ms per char 600 baud */ 83, /* Tenths of ms per char 1200 baud */ 55, /* Tenths of ms per char 1800 baud */ 50, /* Tenths of ms per char 2000 baud */ 41, /* Tenths of ms per char 2400 baud */ 28, /* Tenths of ms per char 3600 baud */ 20, /* Tenths of ms per char 4800 baud */ 14, /* Tenths of ms per char 7200 baud */ 10, /* Tenths of ms per char 9600 baud */ 5 /* Tenths of ms per char 19200 baud */ }; #else /* Times for Unix */ static int times[] = { 0, /* Tenths of ms per char 0 baud */ 2000, /* Tenths of ms per char 50 baud */ 1333, /* Tenths of ms per char 75 baud */ 909, /* Tenths of ms per char 110 baud */ 743, /* Tenths of ms per char 134 baud */ 666, /* Tenths of ms per char 150 baud */ 500, /* Tenths of ms per char 200 baud */ 333, /* Tenths of ms per char 300 baud */ 166, /* Tenths of ms per char 600 baud */ 83, /* Tenths of ms per char 1200 baud */ 55, /* Tenths of ms per char 1800 baud */ 41, /* Tenths of ms per char 2400 baud */ 20, /* Tenths of ms per char 4800 baud */ 10 /* Tenths of ms per char 9600 baud */ }; #endif /* * PSEUDO CODE * * Begin tgoto * If string pointer is invalid then * Return without doing anything. * Else * For each pad digit (if any) * Do decimal left shift. * Accumulate the lower digit. * End for * Adjust scale to tenths of milliseconds * If there is a fractional field * Skip the decimal point. * If there is a valid tenths digit * Accumulate the tenths. * End if * Discard remaining digits. * End if * If per line is specified then * Adjust the pad time. * Discard the per line flag char. * End if * While there are any characters left * Send them out via output function. * End while * Transmit any padding required. * End if * End tgoto * */ tputs(cp,affcnt,outc) char *cp; int affcnt; int (*outc)(); { int ptime; /* Pad time in tenths of milliseconds */ static do_padding(); if (cp == NULL || *cp == NULL) { return; } else { for (ptime = 0; isdigit(*cp); cp++) { ptime *= 10; ptime += (*cp - '0'); } ptime *= 10; if (*cp == '.') { cp++; if (isdigit(*cp)) { ptime += (*cp++ - '0'); } while (isdigit(*cp)) {cp++;} } if (*cp == '*') { ptime *= affcnt; cp++; } while (*cp != NULL) { (*outc)(*cp++); } do_padding(ptime,outc); } } /* * FUNCTION * * do_padding transmit any pad characters required * * SYNOPSIS * * static do_padding(ptime,outc) * int ptime; * int (*outc)(); * * DESCRIPTION * * Does any padding required as specified by ptime (in tenths * of milliseconds), the output speed given in the external * variable ospeed, and the pad character given in the * external variable PC. * */ /* * PSEUDO CODE * * Begin do_padding * If there is a non-zero pad time then * If the external speed is in range then * Look up the delay per pad character. * Round pad time up by half a character. * Compute number of characters to send. * For each pad character to send * Transmit the pad character. * End for * End if * End if * End do_padding * */ static do_padding(ptime,outc) int ptime; int (*outc)(); { register int nchars; register int tpc; if (ptime >= 0) { if (ospeed >= 0 && ospeed <= (sizeof(times)/ sizeof(int))) { tpc = times[ospeed]; ptime += (tpc / 2); nchars = ptime / tpc; for ( ; nchars > 0; --nchars) { (*outc)(PC); } } } } SHAR_EOF cat << \SHAR_EOF > termlib/ttest.c /************************************************************************ * * * Copyright (c) 1982, Fred Fish * * All Rights Reserved * * * * This software and/or documentation is released for public * * distribution for personal, non-commercial use only. * * Limited rights to use, modify, and redistribute are hereby * * granted for non-commercial purposes, provided that all * * copyright notices remain intact and all changes are clearly * * documented. The author makes no warranty of any kind with * * respect to this product and explicitly disclaims any implied * * warranties of merchantability or fitness for any particular * * purpose. * * * ************************************************************************ */ /* * TEST PROGRAM * * testtcp test termcap functions * * KEY WORDS * * test routines * termcap test * * SYNOPSIS * * termcap [-efns] terminal [capability [capability ...]] * * -e => expand string capability given by -s * -f => determine boolean capabilities for terminal * -n => determine numeric capabilities for terminal * -s => determine string capabilities for terminal * * terminal => terminal name as given in termcap file * capability => a boolean, numeric, or string capability * * NOTE: All capabilities must be of same type, as * given by [-fns]. * * If terminal is only argument then entire entry is * printed. * * DESCRIPTION * * Provides way to test termcap functions. Can find * and print an entire termcap terminal entry, or various * capabilities from the entry. * * AUTHOR * * Fred Fish * */ #include <stdio.h> #define TRUE 1 #define FALSE 0 #define NO_FILE -1 /* Returned if can't open file */ #define NO_ENTRY 0 /* Returned if can't find entry */ #define SUCCESS 1 /* Returned if entry found ok */ #define TRUNCATED 2 /* Returned if entry found but trunc */ #define BUFFER_SIZE 1024 int eflag = FALSE; int fflag = FALSE; int nflag = FALSE; int sflag = FALSE; int got_terminal = FALSE; int got_capability = FALSE; int ospeed = 15; /* fake lots of padding */ /* * FUNCTION * * main termcap test entry point * * KEY WORDS * * main * * SYNOPSIS * * main(argc,argv) * int argc; * char *argv[]; * * DESCRIPTION * * This is where the termcap test starts executing. All argument list * switches are processed first, then all the specified * capability identification strings are processed. * */ /* * PSEUDO CODE * * Begin main * Process command line options. * For each argument list field * If field was not erased during option processing * If terminal name field not yet processed then * Process an assumed terminal name field. * Set terminal name processed flag. * Else * Process a capability field. * Set capability field processed flag. * End if * End if * End for * If no capabilities processed then * Simply dump buffer. * End if * End main * */ main(argc, argv) int argc; char *argv[]; { char *argp; int argnum; char buffer[BUFFER_SIZE]; options(argc,argv); for (argnum = 1; argnum < argc; argnum++) { if ((argp = argv[argnum]) != NULL) { if (!got_terminal) { terminal(buffer,argp); got_terminal = TRUE; } else { capability(argp); got_capability = TRUE; } } } if (got_terminal && !got_capability) { printf("size = %d\n%s",strlen(buffer),buffer); } } /* * FUNCTION * * options process command line options * * SYNOPSIS * * options(argc,argv) * int argc; * char *argv[]; * * DESCRIPTION * * Scans argument list, processing each switch as it is * found. The pointer to each switch string is then * replaced with a NULL to effectively erase the switch * argument. * */ /* * PSEUDO CODE * * Begin options * For each argument in the argument list * Get pointer to first char of argument. * If the argument is a switch then * Replace argument pointer with NULL. * Look at next argument character. * While there is another argument character * Switch on the argument character * Case "EXPAND": * Set expand (e) flag. * Break out of switch. * Case "BOOLEAN": * Set boolean (f) flag. * Break out of switch. * Case "NUMERIC": * Set numeric flag. * Break out of switch. * Case "STRING": * Set string flag. * Break out of switch. * Default: * Abort with usage message. * End switch * End while * End if * End for * End options * */ options(argc, argv) int argc; char *argv[]; { int i; char c; /* 1st char of current command-line argument */ char *cp; /* current argument pointer */ for (i=1; i<argc; i++) { cp = argv[i]; if (*cp == '-') { argv[i] = NULL; cp++; while (c = *cp++) { switch (c) { case 'e': eflag = TRUE; break; case 'f': fflag = TRUE; break; case 'n': nflag = TRUE; break; case 's': sflag = TRUE; break; default: usage(); } } } } } /* * FUNCTION * * usage give usage message and abort * * KEY WORDS * * usage * help processing * abort locations * * SYNOPSIS * * usage() * * DESCRIPTION * * Usage is typically called when a problem has been * detected in the argument list. * It prints a usage message and exits. * */ /* * PSEUDO CODE * * Begin usage * Print usage message. * Exit. * End usage * */ usage() { printf("Usage: termcap [-fns] terminal [capability [capability ... ]]\n"); exit(); } terminal(buffer,name) char *buffer; char *name; { int status; status = tgetent(buffer,name); switch (status) { case NO_FILE: fprintf(stderr,"Can't find a termcap data base file.\n"); exit(); case NO_ENTRY: fprintf(stderr,"Can't find entry \"%s\"\n",name); exit(); case TRUNCATED: fprintf(stderr,"Warning --- entry \"%s\" too long\n",name); break; case SUCCESS: break; default: fprintf(stderr,"? tgetent returned illegal status %d\n",status); exit(); } } capability(id) char *id; { int value; char buffer[256]; char *area; char *ep, *tgoto(); if (fflag) { value = tgetflag(id); if (value) { printf("%s TRUE\n",id); } else { printf("%s FALSE\n",id); } } else if (nflag) { value = tgetnum(id); printf("%s = %o octal %d decimal\n",id,value,value); } else if (sflag) { area = buffer; tgetstr(id,&area); if (eflag) { ep = tgoto(buffer,75,23); } doprint(id,buffer); if (eflag) { doprint(id,ep); ep = tgoto(buffer,1,2); doprint(id,ep); } } } /* * Use tputs to get a clearer picture of exactly what * goes out to the terminal.... */ princ(c) int c; { if (c < 040) printf("^%c",c |= 0100); else printf("%c",c); } doprint(id,cp) char *id; char *cp; { printf("%s = \"",id); tputs(cp, 1, princ); printf("\"\n"); } SHAR_EOF # End of shell archive exit 0 -------