Annotation of 43BSD/contrib/emacs/src/termcap.c, revision 1.1

1.1     ! root        1: /* Work-alike for termcap, plus extra features.
        !             2:    Copyright (C) 1985 Richard M. Stallman.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU Emacs, but only under the conditions described in the
        !            15: GNU Emacs General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU Emacs so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: 
        !            23: /* BUFSIZE is the initial size allocated for the buffer
        !            24:    for reading the termcap file.
        !            25:    It is not a limit.
        !            26:    Make it large normally for speed.
        !            27:    Make it variable when debugging, so can exercise
        !            28:    increasing the space dynamically.  */
        !            29: 
        !            30: #ifndef BUFSIZE
        !            31: #ifdef DEBUG
        !            32: #define BUFSIZE bufsize
        !            33: 
        !            34: int bufsize = 128;
        !            35: #else
        !            36: #define BUFSIZE 2048
        !            37: #endif
        !            38: #endif
        !            39: 
        !            40: static
        !            41: memory_out ()
        !            42: {
        !            43:   write (2, "Virtual memory exhausted\n", 25);
        !            44:   exit (1);
        !            45: }
        !            46: 
        !            47: static int
        !            48: xmalloc (size)
        !            49:      int size;
        !            50: {
        !            51:   register tem = malloc (size);
        !            52:   if (!tem)
        !            53:     memory_out ();
        !            54:   return tem;
        !            55: }
        !            56: 
        !            57: static int
        !            58: xrealloc (ptr, size)
        !            59:      int ptr;
        !            60:      int size;
        !            61: {
        !            62:   register tem = realloc (ptr, size);
        !            63:   if (!tem)
        !            64:     memory_out ();
        !            65:   return tem;
        !            66: }
        !            67: 
        !            68: /* Looking up capabilities in the entry already found */
        !            69: 
        !            70: /* The pointer to the data made by tgetent is left here
        !            71:    for tgetnum, tgetflag and tgetstr to find.  */
        !            72: 
        !            73: static char *term_entry;
        !            74: 
        !            75: static char *tgetst1 ();
        !            76: 
        !            77: /* This is the main subroutine that is used to search
        !            78:    an entry for a particular capability */
        !            79: 
        !            80: static char *
        !            81: find_capability (bp, cap)
        !            82:      register char *bp, *cap;
        !            83: {
        !            84:   for (; *bp; bp++)
        !            85:     if (bp[0] == ':'
        !            86:        && bp[1] == cap[0]
        !            87:        && bp[2] == cap[1])
        !            88:       return &bp[4];
        !            89:   return 0;
        !            90: }
        !            91: 
        !            92: int
        !            93: tgetnum (cap)
        !            94:      char *cap;
        !            95: {
        !            96:   register char *ptr = find_capability (term_entry, cap);
        !            97:   if (!ptr || ptr[-1] != '#')
        !            98:     return -1;
        !            99:   return atoi (ptr);
        !           100: }
        !           101: 
        !           102: int
        !           103: tgetflag (cap)
        !           104:      char *cap;
        !           105: {
        !           106:   register char *ptr = find_capability (term_entry, cap);
        !           107:   return 0 != ptr && ptr[-1] == ':';
        !           108: }
        !           109: 
        !           110: /* Look up a string-valued capability `cap'.
        !           111:    If `area' is nonzero, it points to a pointer to a block in which
        !           112:    to store the string.  That pointer is advanced over the space used.
        !           113:    If `area' is zero, space is allocated with `malloc'.  */
        !           114: 
        !           115: char *
        !           116: tgetstr (cap, area)
        !           117:      char *cap;
        !           118:      char **area;
        !           119: {
        !           120:   register char *ptr = find_capability (term_entry, cap);
        !           121:   if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
        !           122:     return 0;
        !           123:   return tgetst1 (ptr, area);
        !           124: }
        !           125: 
        !           126: /* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted,
        !           127:    gives meaning of character following \, or a space if no special meaning.
        !           128:    Eight characters per line within the string.  */
        !           129: 
        !           130: static char esctab[]
        !           131:   = " \007\010  \033\014 \
        !           132:       \012 \
        !           133:   \015 \011 \013 \
        !           134:         ";
        !           135: 
        !           136: /* Given a pointer to a string value inside a termcap entry (`ptr'),
        !           137:    copy the value and process \ and ^ abbreviations.
        !           138:    Copy into block that *area points to,
        !           139:    or to newly allocated storage if area is 0.  */
        !           140: 
        !           141: static char *
        !           142: tgetst1 (ptr, area)
        !           143:      char *ptr;
        !           144:      char **area;
        !           145: {
        !           146:   register char *p, *r;
        !           147:   register int c;
        !           148:   register int size;
        !           149:   char *ret;
        !           150:   register int c1;
        !           151: 
        !           152:   if (!ptr)
        !           153:     return 0;
        !           154: 
        !           155:   /* `ret' gets address of where to store the string */
        !           156:   if (!area)
        !           157:     {
        !           158:       /* Compute size of block needed (may overestimate) */
        !           159:       p = ptr;
        !           160:       while ((c = *p++) && c != ':');
        !           161:       ret = (char *) xmalloc (p - ptr + 1);
        !           162:     }
        !           163:   else
        !           164:     ret = *area;
        !           165: 
        !           166:   /* Copy the string value, stopping at null or colon.  */
        !           167:   /* Also process ^ and \ abbreviations.  */
        !           168:   p = ptr;
        !           169:   r = ret;
        !           170:   while ((c = *p++) && c != ':')
        !           171:     {
        !           172:       if (c == '^')
        !           173:        c = *p++ & 037;
        !           174:       else if (c == '\\')
        !           175:        {
        !           176:          c = *p++;
        !           177:          if (c >= '0' && c <= '7')
        !           178:            {
        !           179:              c -= '0';
        !           180:              size = 0;
        !           181: 
        !           182:              while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
        !           183:                {
        !           184:                  c *= 8;
        !           185:                  c += c1 - '0';
        !           186:                  p++;
        !           187:                }
        !           188:            }
        !           189:          else if (c >= 0100 && c < 0200)
        !           190:            {
        !           191:              c1 = esctab[(c & ~040) - 0100];
        !           192:              if (c1 != ' ')
        !           193:                c = c1;
        !           194:            }
        !           195:        }
        !           196:       *r++ = c;
        !           197:     }
        !           198:   *r = 0;
        !           199:   /* Update *area */
        !           200:   if (area)
        !           201:     *area = r + 1;
        !           202:   return ret;
        !           203: }
        !           204: 
        !           205: /* Outputting a string with padding */
        !           206: 
        !           207: short ospeed;
        !           208: char PC;
        !           209: 
        !           210: /* Actual baud rate if positive;
        !           211:    - baud rate / 100 if negative.  */
        !           212: 
        !           213: static short speeds[] =
        !           214:   {
        !           215:     0, 50, 75, 110, 135, 150, 200, -3, -6, -12,
        !           216:     -18, -24, -48, -96, -192, -384
        !           217:   };
        !           218: 
        !           219: tputs (string, nlines, outfun)
        !           220:      register char *string;
        !           221:      int nlines;
        !           222:      register int (*outfun) ();
        !           223: {
        !           224:   register int padcount = 0;
        !           225: 
        !           226:   if (string == (char *) 0)
        !           227:     return;
        !           228:   while (*string >= '0' && *string <= '9')
        !           229:     {
        !           230:       padcount += *string++ - '0';
        !           231:       padcount *= 10;
        !           232:     }
        !           233:   if (*string == '.')
        !           234:     {
        !           235:       string++;
        !           236:       padcount += *string++ - '0';
        !           237:     }
        !           238:   if (*string == '*')
        !           239:     {
        !           240:       string++;
        !           241:       padcount *= nlines;
        !           242:     }
        !           243:   while (*string)
        !           244:     (*outfun) (*string++);
        !           245: 
        !           246:   /* padcount is now in units of tenths of msec.  */
        !           247:   padcount *= speeds[ospeed];
        !           248:   padcount /= 1000;
        !           249:   if (speeds[ospeed] < 0)
        !           250:     padcount = -padcount;
        !           251:   else
        !           252:     padcount /= 100;
        !           253: 
        !           254:   while (padcount-- > 0)
        !           255:     (*outfun) (PC);
        !           256: }
        !           257: 
        !           258: /* Finding the termcap entry in the termcap data base */
        !           259: 
        !           260: struct buffer
        !           261:   {
        !           262:     char *beg;
        !           263:     int size;
        !           264:     char *ptr;
        !           265:     int ateof;
        !           266:     int full;
        !           267:   };
        !           268: 
        !           269: /* Forward declarations of static functions */
        !           270: 
        !           271: static int scan_file ();
        !           272: static char *gobble_line ();
        !           273: static int compare_contin ();
        !           274: static int name_match ();
        !           275: 
        !           276: /* Find the termcap entry data for terminal type `name'
        !           277:    and store it in the block that `bp' points to.
        !           278:    Record its address for future use.
        !           279: 
        !           280:    If `bp' is zero, space is dynamically allocated.  */
        !           281: 
        !           282: int
        !           283: tgetent (bp, name)
        !           284:      char *bp, *name;
        !           285: {
        !           286:   register char *tem;
        !           287:   register int fd;
        !           288:   struct buffer buf;
        !           289:   register char *bp1;
        !           290:   char *bp2;
        !           291:   char *term;
        !           292:   int malloc_size = 0;
        !           293:   register int c;
        !           294: 
        !           295:   tem = (char *) getenv ("TERMCAP");
        !           296: 
        !           297:   /* If tem is non-null and starts with /,
        !           298:      it is a file name to use instead of /etc/termcap.
        !           299:      If it is non-null and does not start with /,
        !           300:      it is the entry itself, but only if it contains
        !           301:      a name matching NAME.  */
        !           302: 
        !           303:   if (tem && *tem != '/' && name_match (tem, name))
        !           304:     {
        !           305:       if (!bp)
        !           306:        bp = tem;
        !           307:       else
        !           308:        strcpy (bp, tem);
        !           309:       goto ret;
        !           310:     }
        !           311: 
        !           312:   if (!tem)
        !           313:     tem = "/etc/termcap";
        !           314: 
        !           315:   /* Here we know we must search a file and tem has its name.  */
        !           316: 
        !           317:   fd = open (tem, 0, 0);
        !           318:   if (fd < 0)
        !           319:     return -1;
        !           320: 
        !           321:   buf.size = BUFSIZE;
        !           322:   buf.beg = (char *) xmalloc (buf.size);
        !           323:   term = name;
        !           324: 
        !           325:   if (!bp)
        !           326:     {
        !           327:       malloc_size = buf.size;
        !           328:       bp = (char *) xmalloc (malloc_size);
        !           329:     }
        !           330:   bp1 = bp;
        !           331: 
        !           332:   while (term)
        !           333:     {
        !           334:       /* Scan file, reading it via buf, till find start of main entry */
        !           335:       if (scan_file (term, fd, &buf) == 0)
        !           336:        return 0;
        !           337: 
        !           338:       /* Free old `term' if appropriate.  */
        !           339:       if (term != name)
        !           340:        free (term);
        !           341: 
        !           342:       /* If `bp' is malloc'd by us, make sure it is big enough.  */
        !           343:       if (malloc_size)
        !           344:        {
        !           345:          malloc_size = bp1 - bp + buf.size;
        !           346:          tem = (char *) xrealloc (bp, malloc_size);
        !           347:          bp1 += tem - bp;
        !           348:          bp = tem;
        !           349:        }
        !           350: 
        !           351:       bp2 = bp1;
        !           352: 
        !           353:       /* Copy the line of the entry from buf into bp.  */
        !           354:       tem = buf.ptr;
        !           355:       while ((*bp1++ = c = *tem++) && c != '\n')
        !           356:        /* Drop out any \ newline sequence, and following whitespace */
        !           357:        if (c == '\\' && *tem == '\n')
        !           358:          {
        !           359:            bp1--;
        !           360:            tem++;
        !           361:            while ((c = *tem++) == ' ' || c == '\t');
        !           362:            tem--;
        !           363:          }
        !           364:       *bp1 = 0;
        !           365: 
        !           366:       /* Does this entry refer to another terminal type's entry?  */
        !           367:       /* If something is found, copy it into heap and null-terminate it */
        !           368:       term = tgetst1 (find_capability (bp2, "tc", '='), 0);
        !           369:     }
        !           370: 
        !           371:   close (fd);
        !           372:   free (buf.beg);
        !           373: 
        !           374:   if (malloc_size)
        !           375:     {
        !           376:       bp = (char *) xrealloc (bp, bp1 - bp + 1);
        !           377:     }
        !           378: 
        !           379:  ret:
        !           380:   term_entry = bp;
        !           381:   if (malloc_size)
        !           382:     return (int) bp;
        !           383:   return 1;
        !           384: }
        !           385: 
        !           386: /* Given file open on `fd' and buffer `bufp',
        !           387:    scan the file from the beginning until a line is found
        !           388:    that starts the entry for terminal type `string'.
        !           389:    Returns 1 if successful, with that line in `bufp',
        !           390:    or returns 0 if no entry found in the file.  */
        !           391: 
        !           392: static int
        !           393: scan_file (string, fd, bufp)
        !           394:      char *string;
        !           395:      int fd;
        !           396:      register struct buffer *bufp;
        !           397: {
        !           398:   register char *tem;
        !           399:   register char *end;
        !           400: 
        !           401:   bufp->ptr = bufp->beg;
        !           402:   bufp->full = 0;
        !           403:   bufp->ateof = 0;
        !           404:   *bufp->ptr = 0;
        !           405: 
        !           406:   lseek (fd, 0L, 0);
        !           407: 
        !           408:   while (!bufp->ateof)
        !           409:     {
        !           410:       /* Read a line into the buffer */
        !           411:       end = 0;
        !           412:       do
        !           413:        {
        !           414:          /* if it is continued, append another line to it,
        !           415:             until a non-continued line ends */
        !           416:          end = gobble_line (fd, bufp, end);
        !           417:        }
        !           418:       while (!bufp->ateof && end[-2] == '\\');
        !           419: 
        !           420:       if (*bufp->ptr != '#'
        !           421:          && name_match (bufp->ptr, string))
        !           422:        return 1;
        !           423: 
        !           424:       /* Discard the line just processed */
        !           425:       bufp->ptr = end;
        !           426:     }
        !           427:   return 0;
        !           428: }
        !           429: 
        !           430: /* Return nonzero if NAME is one of the names specified
        !           431:    by termcap entry LINE.  */
        !           432: 
        !           433: static int
        !           434: name_match (line, name)
        !           435:      char *line, *name;
        !           436: {
        !           437:   register char *tem;
        !           438: 
        !           439:   if (!compare_contin (line, name))
        !           440:     return 1;
        !           441:   /* This line starts an entry.  Is it the right one?  */
        !           442:   for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++)
        !           443:     if (*tem == '|' && !compare_contin (tem + 1, name))
        !           444:       return 1;
        !           445: 
        !           446:   return 0;
        !           447: }
        !           448: 
        !           449: static int
        !           450: compare_contin (str1, str2)
        !           451:      register char *str1, *str2;
        !           452: {
        !           453:   register int c1, c2;
        !           454:   while (1)
        !           455:     {
        !           456:       c1 = *str1++;
        !           457:       c2 = *str2++;
        !           458:       while (c1 == '\\' && *str1 == '\n')
        !           459:        {
        !           460:          str1++;
        !           461:          while ((c1 = *str1++) == ' ' || c1 == '\t');
        !           462:        }
        !           463:       if (c2 == '\0')          /* end of type being looked up */
        !           464:        {
        !           465:          if (c1 == '|' || c1 == ':') /* If end of name in data base, */
        !           466:            return 0;           /* we win. */
        !           467:          else
        !           468:            return 1;
        !           469:         }
        !           470:       else if (c1 != c2)
        !           471:        return 1;
        !           472:     }
        !           473: }
        !           474: 
        !           475: /* Make sure that the buffer <- `bufp' contains a full line
        !           476:    of the file open on `fd', starting at the place `bufp->ptr'
        !           477:    points to.  Can read more of the file, discard stuff before
        !           478:    `bufp->ptr', or make the buffer bigger.
        !           479: 
        !           480:    Returns the pointer to after the newline ending the line,
        !           481:    or to the end of the file, if there is no newline to end it.
        !           482: 
        !           483:    Can also merge on continuation lines.  If `append_end' is
        !           484:    nonzero, it points past the newline of a line that is
        !           485:    continued; we add another line onto it and regard the whole
        !           486:    thing as one line.  The caller decides when a line is continued.  */
        !           487: 
        !           488: static char *
        !           489: gobble_line (fd, bufp, append_end)
        !           490:      int fd;
        !           491:      register struct buffer *bufp;
        !           492:      char *append_end;
        !           493: {
        !           494:   register char *end;
        !           495:   register int nread;
        !           496:   register char *buf = bufp->beg;
        !           497:   register char *tem;
        !           498: 
        !           499:   if (append_end == 0)
        !           500:     append_end = bufp->ptr;
        !           501: 
        !           502:   while (1)
        !           503:     {
        !           504:       end = append_end;
        !           505:       while (*end && *end != '\n') end++;
        !           506:       if (*end)
        !           507:         break;
        !           508:       if (bufp->ateof)
        !           509:        return buf + bufp->full;
        !           510:       if (bufp->ptr == buf)
        !           511:        {
        !           512:          if (bufp->full == bufp->size)
        !           513:            {
        !           514:              bufp->size *= 2;
        !           515:              tem = (char *) xrealloc (buf, bufp->size);
        !           516:              bufp->ptr += tem - buf;
        !           517:              append_end += tem - buf;
        !           518:              bufp->beg = buf = tem;
        !           519:            }
        !           520:        }
        !           521:       else
        !           522:        {
        !           523:          append_end -= bufp->ptr - buf;
        !           524:          bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf);
        !           525:          bufp->ptr = buf;
        !           526:        }
        !           527:       if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
        !           528:        bufp->ateof = 1;
        !           529:       bufp->full += nread;
        !           530:       if (bufp->full != bufp->size)
        !           531:        buf[bufp->full] = 0;
        !           532:     }
        !           533:   return end + 1;
        !           534: }
        !           535: 
        !           536: #ifdef DEBUG
        !           537: 
        !           538: #include <stdio.h>
        !           539: 
        !           540: main (argc, argv)
        !           541:      int argc;
        !           542:      char **argv;
        !           543: {
        !           544:   char *term;
        !           545:   char *buf;
        !           546: 
        !           547:   if (!strcmp (argv[1], "-f"))
        !           548:     {
        !           549:       argv++;
        !           550:       bufsize = 2048;
        !           551:     }
        !           552:   term = argv[1];
        !           553:   printf ("TERM: %s\n", term);
        !           554: 
        !           555:   buf = (char *) tgetent (0, term);
        !           556:   if ((int) buf <= 0)
        !           557:     {
        !           558:       printf ("No entry.\n");
        !           559:       return 0;
        !           560:     }
        !           561: 
        !           562:   printf ("Entry: %s\n", buf);
        !           563: 
        !           564:   tprint ("cm");
        !           565:   tprint ("AL");
        !           566: 
        !           567:   printf ("co: %d\n", tgetnum ("co"));
        !           568:   printf ("am: %d\n", tgetflag ("am"));
        !           569: }
        !           570: 
        !           571: tprint (cap)
        !           572:      char *cap;
        !           573: {
        !           574:   char *x = tgetstr (cap, 0);
        !           575:   register char *y;
        !           576: 
        !           577:   printf ("%s: ", cap);
        !           578:   if (x)
        !           579:     {
        !           580:       for (y = x; *y; y++)
        !           581:        if (*y <= ' ' || *y == 0177)
        !           582:          printf ("\\%0o", *y);
        !           583:        else
        !           584:          putchar (*y);
        !           585:       free (x);
        !           586:     }
        !           587:   else
        !           588:     printf ("none");
        !           589:   putchar ('\n');
        !           590: }
        !           591: 
        !           592: #endif /* DEBUG */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.