From 39d3496f4b4037a53d455d0a8aef5d51c5f2fe5b Mon Sep 17 00:00:00 2001 From: ceriel Date: Tue, 26 Apr 1988 18:23:40 +0000 Subject: [PATCH] Added termcap.c --- lang/cem/libcc/stdio/LIST | 1 + lang/cem/libcc/stdio/termcap.c | 432 +++++++++++++++++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 lang/cem/libcc/stdio/termcap.c diff --git a/lang/cem/libcc/stdio/LIST b/lang/cem/libcc/stdio/LIST index 98d3ee268..a9249f2b2 100644 --- a/lang/cem/libcc/stdio/LIST +++ b/lang/cem/libcc/stdio/LIST @@ -1,4 +1,5 @@ tail_cc.1s.a +termcap.c clearerr.c fgetc.c fgets.c diff --git a/lang/cem/libcc/stdio/termcap.c b/lang/cem/libcc/stdio/termcap.c new file mode 100644 index 000000000..835e50be8 --- /dev/null +++ b/lang/cem/libcc/stdio/termcap.c @@ -0,0 +1,432 @@ +/* + * termcap.c 1.1 20/7/87 agc Joypace Ltd + * + * Copyright Joypace Ltd, London, UK, 1987. All rights reserved. + * This file may be freely distributed provided that this notice + * remains attached. + * + * A public domain implementation of the termcap(3) routines. + * + * Made fully functional by Ceriel J.H. Jacobs. + * + * BUGS: + * - does not check termcap entry sizes + * - not fully tested + */ +#include + +#define CAPABLEN 2 + +#define ISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n') +#define ISDIGIT(x) ((x) >= '0' && (x) <= '9') + +short ospeed; /* output speed */ +char PC; /* padding character */ +char *BC; /* back cursor movement */ +char *UP; /* up cursor movement */ + +static char *capab; /* the capability itself */ +static int check_for_tc(); +static int match_name(); + +extern char *getenv(); /* new, improved getenv */ +extern FILE *fopen(); /* old fopen */ + +/* + * tgetent - get the termcap entry for terminal name, and put it + * in bp (which must be an array of 1024 chars). Returns 1 if + * termcap entry found, 0 if not found, and -1 if file not found. + */ +int +tgetent(bp, name) +char *bp; +char *name; +{ + FILE *fp; + char *file; + char *cp; + short len = strlen(name); + char buf[1024]; + + capab = bp; + if ((file = getenv("TERMCAP")) != (char *) NULL) { + if (*file != '/' && + (cp = getenv("TERM")) != NULL && strcmp(name, cp) == 0) { + (void) strcpy(bp, file); + return(1); + } + } else + file = "/etc/termcap"; + if ((fp = fopen(file, "r")) == (FILE *) NULL) + return(-1); + while (fgets(buf, 1024, fp) != NULL) { + if (buf[0] == '#') continue; + while (*(cp = &buf[strlen(buf) - 2]) == '\\') + if (fgets(cp, 1024, fp) == NULL) + return (0); + if (match_name(buf, name)) { + strcpy(bp, buf); + fclose(fp); + return(check_for_tc()); + } + } + fclose(fp); + return(0); +} + +/* + * Compare the terminal name with each termcap entry name; Return 1 if a + * match is found. + */ +static int +match_name(buf, name) + char *buf; + char *name; +{ + register char *tp = buf; + register char *np; + + for (;;) { + for (np = name; *np && *tp == *np; np++, tp++) { } + if (*np == 0 && (*tp == '|' || *tp == ':' || *tp == 0)) + return(1); + while (*tp != 0 && *tp != '|' && *tp != ':') tp++; + if (*tp++ != '|') return (0); + } +} + +/* + * Handle tc= definitions recursively. + */ +static int +check_for_tc() +{ + static int count = 0; + char *savcapab = capab; + char buf[1024]; + char terminalname[128]; + register char *p = capab + strlen(capab) - 2, *q; + + while (*p != ':') + if (--p < capab) + return(0); /* no : in termcap entry */ + if (p[1] != 't' || p[2] != 'c') + return(1); + if (++count > 16) return(0); /* recursion in tc= definitions */ + strcpy(terminalname, &p[4]); + q = terminalname; + while (*q && *q != ':') q++; + *q = 0; + if (tgetent(buf, terminalname) != 1) return(0); + for (q = buf; *q && *q != ':'; q++) { } + strcpy(p, q); + capab = savcapab; + return(1); +} + +/* + * tgetnum - get the numeric terminal capability corresponding + * to id. Returns the value, -1 if invalid. + */ +int +tgetnum(id) +char *id; +{ + char *cp; + int ret; + + if ((cp = capab) == NULL || id == NULL) + return(-1); + while (*++cp != ':') + ; + for (++cp ; *cp ; cp++) { + while (ISSPACE(*cp)) + cp++; + if (strncmp(cp, id, CAPABLEN) == 0) { + while (*cp && *cp != ':' && *cp != '#') + cp++; + if (*cp != '#') + return(-1); + for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++) + ret = ret * 10 + *cp - '0'; + return(ret); + } + while (*cp && *cp != ':') + cp++; + } + return(-1); +} + +/* + * tgetflag - get the boolean flag corresponding to id. Returns -1 + * if invalid, 0 if the flag is not in termcap entry, or 1 if it is + * present. + */ +int +tgetflag(id) +char *id; +{ + char *cp; + + if ((cp = capab) == NULL || id == NULL) + return(-1); + while (*++cp != ':') + ; + for (++cp ; *cp ; cp++) { + while (ISSPACE(*cp)) + cp++; + if (strncmp(cp, id, CAPABLEN) == 0) + return(1); + while (*cp && *cp != ':') + cp++; + } + return(0); +} + +/* + * tgetstr - get the string capability corresponding to id and place + * it in area (advancing area at same time). Expand escape sequences + * etc. Returns the string, or NULL if it can't do it. + */ +char * +tgetstr(id, area) +char *id; +char **area; +{ + char *cp; + char *ret; + int i; + + if ((cp = capab) == NULL || id == NULL) + return(NULL); + while (*++cp != ':') + ; + for (++cp ; *cp ; cp++) { + while (ISSPACE(*cp)) + cp++; + if (strncmp(cp, id, CAPABLEN) == 0) { + while (*cp && *cp != ':' && *cp != '=') + cp++; + if (*cp != '=') + return(NULL); + for (ret = *area, cp++; *cp && *cp != ':' ; (*area)++, cp++) + switch(*cp) { + case '^' : + **area = *++cp - 'A' + 1; + break; + case '\\' : + switch(*++cp) { + case 'E' : + **area = '\033'; + break; + case 'n' : + **area = '\n'; + break; + case 'r' : + **area = '\r'; + break; + case 't' : + **area = '\t'; + break; + case 'b' : + **area = '\b'; + break; + case 'f' : + **area = '\f'; + break; + case '0' : + case '1' : + case '2' : + case '3' : + for (i=0 ; *cp && ISDIGIT(*cp) ; cp++) + i = i * 8 + *cp - '0'; + **area = i; + cp--; + break; + case '^' : + case '\\' : + **area = *cp; + break; + } + break; + default : + **area = *cp; + } + *(*area)++ = '\0'; + return(ret); + } + while (*cp && *cp != ':') + cp++; + } + return(NULL); +} + +/* + * tgoto - given the cursor motion string cm, make up the string + * for the cursor to go to (destcol, destline), and return the string. + * Returns "OOPS" if something's gone wrong, or the string otherwise. + */ +char * +tgoto(cm, destcol, destline) +char *cm; +int destcol; +int destline; +{ + register char *rp; + static char ret[24]; + char added[16]; + int *dp = &destline; + int numval; + int swapped = 0; + + added[0] = 0; + for (rp = ret ; *cm ; cm++) { + if (*cm == '%') { + switch(*++cm) { + case '>' : + if (dp == NULL) + return("OOPS"); + cm++; + if (*dp > *cm++) { + *dp += *cm; + } + break; + case '+' : + case '.' : + if (dp == NULL) + return("OOPS"); + if (*cm == '+') *dp = *dp + *++cm; + for (;;) { + switch(*dp) { + case 0: + case 04: + case '\t': + case '\n': + /* filter these out */ + if (dp == &destcol || swapped || UP) { + strcat(added, dp == &destcol || swapped ? + (BC ? BC : "\b") : + UP); + (*dp)++; + continue; + } + } + break; + } + *rp++ = *dp; + dp = (dp == &destline) ? &destcol : NULL; + break; + + case 'r' : { + int tmp = destline; + + destline = destcol; + destcol = tmp; + swapped = 1 - swapped; + break; + } + case 'n' : + destcol ^= 0140; + destline ^= 0140; + break; + + case '%' : + *rp++ = '%'; + break; + + case 'i' : + destcol++; + destline++; + break; + + case 'B' : + if (dp == NULL) + return("OOPS"); + *dp = 16 * (*dp / 10) + *dp % 10; + break; + + case 'D' : + if (dp == NULL) + return("OOPS"); + *dp = *dp - 2 * (*dp % 16); + break; + + case 'd' : + case '2' : + case '3' : + if (dp == NULL) + return("OOPS"); + numval = *dp; + dp = (dp == &destline) ? &destcol : NULL; + if (numval >= 100) { + *rp++ = '0' + numval / 100; + } + else if (*cm == '3') { + *rp++ = ' '; + } + if (numval >= 10) { + *rp++ = '0' + ((numval%100)/10); + } + else if (*cm == '3' || *cm == '2') { + *rp++ = ' '; + } + *rp++ = '0' + (numval%10); + break; + default : + return("OOPS"); + } + } + else *rp++ = *cm; + } + *rp = '\0'; + strcpy(rp, added); + return(ret); +} + +static int tens_of_ms_p_char[] = { /* index as returned by gtty */ + /* assume 10 bits per char */ + 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 2 +}; +/* + * tputs - put the string cp out onto the terminal, using the function + * outc. Also handle padding. + */ +int +tputs(cp, affcnt, outc) +register char *cp; +int affcnt; +int (*outc)(); +{ + int delay = 0; + if (cp == NULL) + return(1); + while (ISDIGIT(*cp)) { + delay = delay * 10 + (*cp++ - '0'); + } + delay *= 10; + if (*cp == '.') { + cp++; + if (ISDIGIT(*cp)) { + delay += *cp++ - '0'; + } + while (ISDIGIT(*cp)) cp++; + } + if (*cp == '*') { + delay *= affcnt; + cp++; + } + while (*cp) + (*outc)(*cp++); + if (delay != 0 && + ospeed > 0 && + ospeed < (sizeof tens_of_ms_p_char / sizeof tens_of_ms_p_char[0])) { + delay = (delay + tens_of_ms_p_char[ospeed] - 1) / + tens_of_ms_p_char[ospeed]; + while (delay--) (*outc)(PC); + } + return(1); +} + +/* + * That's all, folks... + */ -- 2.34.1