Add resident.conf(5) and varsym.conf(5) manual pages.
[dragonfly/vkernel-mp.git] / usr.bin / tconv / tconv.c
blobb43e18dc118eec05c18c6f9292a770369531da2a
1 /*
2 * tconv.c
4 * Ross Ridge
5 * Public Domain
6 * 92/02/01 07:30:23
8 * tconv [-b] [-c [-OUGd]] [-i] [-B [-D dir]] [-I] [-k] [-V] [-t term] [file]
10 * -c convert from termcap
11 * -i convert from terminfo source
12 * -b convert from terminfo binary
13 * -B convert to terminfo binary
14 * -I convert to terminfo source
15 * -V print version info
17 * The following switches are available when converting from termcap:
18 * -d don't supply any defaults for missing capabilities
19 * -O include obsolete termcap capabilities
20 * -G include GNU capabilities
21 * -U include UW capabilities
23 * -k keep comments
24 * -D dir directory to put terminfo binaries in
26 * -t term name of terminal to translate
27 * file filename of termcap/terminfo database to use
29 * If a file is specifed and no terminal is given the entire file we be
30 * translated.
31 * If no terminal and no file is specified then the terminal name will be
32 * taken from the environment variable TERM.
33 * Unless compiling to a terminfo binary, output is to stdout.
35 * @(#) mytinfo tconv.c 3.2 92/02/01 public domain, By Ross Ridge
36 * $FreeBSD: src/usr.bin/tconv/tconv.c,v 1.5.2.1 2001/03/04 09:07:50 kris Exp $
37 * $DragonFly: src/usr.bin/tconv/tconv.c,v 1.5 2004/01/22 04:22:53 rob Exp $
40 #define NOTLIB
41 #include "defs.h"
42 #define SINGLE
43 #include <term.h>
45 #include <ctype.h>
46 #include <fcntl.h>
47 #ifdef USE_STDDEF
48 #include <sys/types.h>
49 #endif
50 #include <sys/stat.h>
51 #if defined(__DragonFly__)
52 #include <unistd.h>
53 #endif
55 #if !defined(__DragonFly__)
56 #include "strtok.c"
57 #include "mkdir.c"
58 #endif
60 /* the right margin of the output */
61 #define LINELEN 76
63 struct term_path *path; /* returned from _buildpath */
65 TERMINAL _term_buf;
66 char buf[MAX_BUF+1]; /* buffer for the termcap entry */
68 int noOT = 1; /* -O */
69 int noGNU = 1; /* -G */
70 int noUW = 1; /* -W */
71 int dodefault = 1; /* -d */
72 int keepcomments = 0; /* -k */
73 int compile = 0; /* -B */
74 int from_tcap = 0; /* -c */
75 int from_tinfo = 0; /* -i */
76 int from_tbin = 0; /* -b */
77 char *directory = NULL; /* -D */
79 int continued = 0;
80 int termcap = 1;
82 int lineno = 0; /* current line number */
84 /* print the first part of a warning message */
85 void
86 warn(void) {
87 if (lineno == 0)
88 fprintf(stderr, "warning: ");
89 else
90 fprintf(stderr, "(%s)%d: warning: ",
91 _term_buf.name_long, lineno);
94 /* output a string indenting at the beginning of a line, and wraping
95 * at the right margin.
97 void
98 putstr(char *s)
100 static pos = 0;
101 int l;
103 if (s == NULL) {
104 if (pos != 0) {
105 pos = 0;
106 putchar('\n');
108 return;
111 if (termcap && noOT && *s == 'O')
112 return;
113 if (termcap && noGNU && *s == 'G')
114 return;
115 if (termcap && noUW && *s == 'U')
116 return;
118 l = strlen(s) + 2;
120 if (l + pos > LINELEN && pos != 0) {
121 putchar('\n');
122 pos = 0;
125 if (pos == 0) {
126 putchar('\t');
127 pos = 8;
128 } else
129 putchar(' ');
131 printf("%s,", s);
133 pos += l;
136 #ifndef MAX_PUSHED
137 /* maximum # of parameters that can be pushed onto the stack */
138 #define MAX_PUSHED 16
139 #endif
141 int stack[MAX_PUSHED]; /* the stack */
142 int stackptr; /* the next empty place on the stack */
143 int onstack; /* the top of stack */
144 int seenm; /* seen a %m */
145 int seenn; /* seen a %n */
146 int seenr; /* seen a %r */
147 int param; /* current parameter */
148 char *dp; /* pointer to the end of the converted string */
150 /* push onstack on to the stack */
151 void
152 push(void)
154 if (stackptr > MAX_PUSHED) {
155 warn();
156 fprintf(stderr, "string to complex to convert\n");
157 } else
158 stack[stackptr++] = onstack;
161 /* pop the top of the stack into onstack */
162 void
163 pop(void)
165 if (stackptr == 0)
166 if (onstack == 0) {
167 warn();
168 fprintf(stderr, "I'm confused\n");
169 } else
170 onstack = 0;
171 else
172 onstack = stack[--stackptr];
173 param++;
176 /* convert a character to a terminfo push */
177 static int
178 cvtchar(register char *sp)
180 char c;
181 int l;
183 switch(*sp) {
184 case '\\':
185 switch(*++sp) {
186 case '\'':
187 case '$':
188 case '\\':
189 case '%':
190 c = *sp;
191 l = 2;
192 break;
193 case '\0':
194 c = '\\';
195 l = 1;
196 break;
197 case '0':
198 if (sp[1] == '0' && sp[2] == '0') {
199 c = '\0';
200 l = 4;
201 } else {
202 c = '\200'; /* '\0' ???? */
203 l = 2;
205 break;
206 default:
207 c = *sp;
208 l = 2;
209 break;
211 break;
212 default:
213 c = *sp;
214 l = 1;
216 c &= 0177;
217 if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') {
218 *dp++ = '%'; *dp++ = '\''; *dp++ = c; *dp++ = '\'';
219 } else {
220 *dp++ = '%'; *dp++ = '{';
221 if (c > 99)
222 *dp++ = c / 100 + '0';
223 if (c > 9)
224 *dp++ = (c / 10) % 10 + '0';
225 *dp++ = c % 10 + '0';
226 *dp++ = '}';
228 return l;
231 /* push n copies of param on the terminfo stack if not already there */
232 void
233 getparm(int parm, int n)
235 if (seenr) {
236 if (parm == 1)
237 parm = 2;
238 else if (parm == 2)
239 parm = 1;
241 if (onstack == parm) {
242 if (n > 1) {
243 warn();
244 fprintf(stderr, "string may not be optimal");
245 *dp++ = '%'; *dp++ = 'P'; *dp++ = 'a';
246 while(n--) {
247 *dp++ = '%'; *dp++ = 'g'; *dp++ = 'a';
250 return;
252 if (onstack != 0)
253 push();
255 onstack = parm;
257 while(n--) { /* %p0 */
258 *dp++ = '%'; *dp++ = 'p'; *dp++ = '0' + parm;
261 if (seenn && parm < 3) { /* %{96}%^ */
262 *dp++ = '%'; *dp++ = '{'; *dp++ = '9'; *dp++ = '6'; *dp++ = '}';
263 *dp++ = '%'; *dp++ = '^';
266 if (seenm && parm < 3) { /* %{127}%^ */
267 *dp++ = '%'; *dp++ = '{'; *dp++ = '1'; *dp++ = '2'; *dp++ = '7';
268 *dp++ = '}'; *dp++ = '%'; *dp++ = '^';
272 /* convert a string to terminfo format */
273 char *
274 convstr(register char *s, int i)
276 static char line[MAX_LINE];
277 register char *cap;
278 int nocode = 0;
280 stackptr = 0;
281 onstack = 0;
282 seenm = 0;
283 seenn = 0;
284 seenr = 0;
285 param = 1;
287 dp = line;
288 cap = strnames[i];
289 #if 0
290 if (cap[0] == 'k'
291 || ((cap[0] == 'i' || cap[0] == 'r') && cap[1] == 's'
292 && (cap[2] == '1' || cap[2] == '2' || cap[2] == '3')))
293 /* if (k.* || [ir]s[123]) */
294 nocode = 1;
295 #else
296 if (_strflags[i] != 'G')
297 nocode = 1;
298 #endif
299 if (!nocode) {
300 char *d = s;
301 while(*s != '\0') {
302 if (s[0] == '\\' && s[1] != '\0')
303 s++;
304 else if (s[0] == '%' && s[1] != '\0') {
305 if (s[1] == 'p') {
306 if (termcap) {
307 warn();
308 fprintf(stderr,
309 "string '%s' already in terminfo format\n", strcodes[i]);
310 nocode = 1;
311 break;
312 } else
313 nocode = 1;
315 s++;
317 s++;
319 if (!nocode && !termcap) {
320 warn();
321 fprintf(stderr,
322 "string '%s' not in terminfo format, converting...\n", cap);
324 s = d;
326 while(*s != '\0') {
327 switch(*s) {
328 case '%':
329 s++;
330 if (nocode) {
331 *dp++ = '%';
332 break;
334 switch(*s++) {
335 case '%': *dp++ = '%'; break;
336 case 'r':
337 if (seenr++ == 1) {
338 warn();
339 fprintf(stderr, "seen %%r twice\n");
341 break;
342 case 'm':
343 if (seenm++ == 1) {
344 warn();
345 fprintf(stderr, "seen %%m twice\n");
347 break;
348 case 'n':
349 if (seenn++ == 1) {
350 warn();
351 fprintf(stderr, "seen %%n twice\n");
353 break;
354 case 'i': *dp++ = '%'; *dp++ = 'i'; break;
355 case '6':
356 case 'B':
357 getparm(param, 2);
358 /* %{6}%*%+ */
359 *dp++ = '%'; *dp++ = '{'; *dp++ = '6';
360 *dp++ = '}'; *dp++ = '%'; *dp++ = '*';
361 *dp++ = '%'; *dp++ = '+';
362 break;
363 case '8':
364 case 'D':
365 getparm(param, 2);
366 /* %{2}%*%- */
367 *dp++ = '%'; *dp++ = '{'; *dp++ = '2';
368 *dp++ = '}'; *dp++ = '%'; *dp++ = '*';
369 *dp++ = '%'; *dp++ = '-';
370 break;
371 case '>':
372 getparm(param, 2);
373 /* %?%{x}%>%t%{y}%+%; */
374 *dp++ = '%'; *dp++ = '?';
375 s += cvtchar(s);
376 *dp++ = '%'; *dp++ = '>';
377 *dp++ = '%'; *dp++ = 't';
378 s += cvtchar(s);
379 *dp++ = '%'; *dp++ = '+';
380 *dp++ = '%'; *dp++ = ';';
381 break;
382 case 'a':
383 if ((*s == '=' || *s == '+' || *s == '-'
384 || *s == '*' || *s == '/')
385 && (s[1] == 'p' || s[1] == 'c')
386 && s[2] != '\0') {
387 int l;
388 l = 2;
389 if (*s != '=')
390 getparm(param, 1);
391 if (s[1] == 'p') {
392 getparm(param + s[2] - '@', 1);
393 if (param != onstack) {
394 pop();
395 param--;
397 l++;
398 } else
399 l += cvtchar(s + 2);
400 switch(*s) {
401 case '+':
402 *dp++ = '%'; *dp++ = '+';
403 break;
404 case '-':
405 *dp++ = '%'; *dp++ = '-';
406 break;
407 case '*':
408 *dp++ = '%'; *dp++ = '*';
409 break;
410 case '/':
411 *dp++ = '%'; *dp++ = '/';
412 break;
413 case '=':
414 if (seenr)
415 if (param == 1)
416 onstack = 2;
417 else if (param == 2)
418 onstack = 1;
419 else
420 onstack = param;
421 else
422 onstack = param;
423 break;
425 s += l;
426 break;
428 getparm(param, 1);
429 s += cvtchar(s);
430 *dp++ = '%'; *dp++ = '+';
431 break;
432 case '+':
433 getparm(param, 1);
434 s += cvtchar(s);
435 *dp++ = '%'; *dp++ = '+';
436 *dp++ = '%'; *dp++ = 'c';
437 pop();
438 break;
439 case 's':
440 s += cvtchar(s);
441 getparm(param, 1);
442 *dp++ = '%'; *dp++ = '-';
443 break;
444 case '-':
445 s += cvtchar(s);
446 getparm(param, 1);
447 *dp++ = '%'; *dp++ = '-';
448 *dp++ = '%'; *dp++ = 'c';
449 pop();
450 break;
451 case '.':
452 getparm(param, 1);
453 *dp++ = '%'; *dp++ = 'c';
454 pop();
455 break;
456 case '2':
457 getparm(param, 1);
458 *dp++ = '%'; *dp++ = '0';
459 *dp++ = '2'; *dp++ = 'd';
460 pop();
461 break;
462 case '3':
463 getparm(param, 1);
464 *dp++ = '%'; *dp++ = '0';
465 *dp++ = '3'; *dp++ = 'd';
466 pop();
467 break;
468 case 'd':
469 getparm(param, 1);
470 *dp++ = '%'; *dp++ = 'd';
471 pop();
472 break;
473 case 'f':
474 param++;
475 break;
476 case 'b':
477 param--;
478 break;
479 default:
480 warn();
481 *dp++ = '%';
482 s--;
483 fprintf(stderr, "'%s' unknown %% code %c",
484 strcodes[i], *s);
485 if (*s >= 0 && *s < 32)
486 fprintf(stderr, "^%c\n", *s + '@');
487 else if (*s < 0 || *s >= 127)
488 fprintf(stderr, "\\%03o\n", *s & 0377);
489 else
490 fprintf(stderr, "%c\n", *s);
491 break;
493 break;
494 case '\\':
495 if (!compile) {*dp++ = *s++; *dp++ = *s++; break;}
496 /* FALLTHROUGH */
497 case '\n':
498 if (!compile) {*dp++ = '\\'; *dp++ = 'n'; s++; break;}
499 /* FALLTHROUGH */
500 case '\t':
501 if (!compile) {*dp++ = '\\'; *dp++ = 't'; s++; break;}
502 /* FALLTHROUGH */
503 case '\r':
504 if (!compile) {*dp++ = '\\'; *dp++ = 'r'; s++; break;}
505 /* FALLTHROUGH */
506 case '\200':
507 if (!compile) {*dp++ = '\\'; *dp++ = '0'; s++; break;}
508 /* FALLTHROUGH */
509 case '\f':
510 if (!compile) {*dp++ = '\\'; *dp++ = 'f'; s++; break;}
511 /* FALLTHROUGH */
512 case '\b':
513 if (!compile) {*dp++ = '\\'; *dp++ = 'b'; s++; break;}
514 /* FALLTHROUGH */
515 case ' ':
516 if (!compile) {*dp++ = '\\'; *dp++ = 's'; s++; break;}
517 /* FALLTHROUGH */
518 case '^':
519 if (!compile) {*dp++ = '\\'; *dp++ = '^'; s++; break;}
520 /* FALLTHROUGH */
521 case ':':
522 if (!compile) {*dp++ = '\\'; *dp++ = ':'; s++; break;}
523 /* FALLTHROUGH */
524 case ',':
525 if (!compile) {*dp++ = '\\'; *dp++ = ','; s++; break;}
526 /* FALLTHROUGH */
527 #if 0
528 case '\'':
529 if (!compile) {*dp++ = '\\'; *dp++ = '\''; s++; break;}
530 /* FALLTHROUGH */
531 #endif
532 default:
533 if (compile)
534 *dp++ = *s++;
535 else if (*s > 0 && *s < 32) {
536 *dp++ = '^';
537 *dp++ = *s + '@';
538 s++;
539 } else if (*s <= 0 || *s >= 127) {
540 *dp++ = '\\';
541 *dp++ = ((*s & 0300) >> 6) + '0';
542 *dp++ = ((*s & 0070) >> 3) + '0';
543 *dp++ = (*s & 0007) + '0';
544 s++;
545 } else
546 *dp++ = *s++;
547 break;
550 *dp = '\0';
551 return line;
554 #define LSB(n) ((unsigned) (n) & 0377)
555 #define MSB(n) (((unsigned) (n) >> 8) & 0377)
557 void
558 writebin(int fd, char *name)
560 static char bin[MAX_BUF + 1];
561 register char *s;
562 register char *d;
563 register int i;
564 register char *t;
565 register int n;
566 char *strtbl;
567 int sz_name, n_bools, n_nums, n_offs, sz_strs;
568 extern int _boolorder[], _numorder[], _strorder[];
570 strncpy(bin + 12, name, 127);
571 bin[12 + 128] = '\0';
572 sz_name = strlen(name) + 1;
573 if (sz_name > 128)
574 sz_name = 128;
576 s = bin + 12 + sz_name;
577 for(i = 0; _boolorder[i] != -1; i++) {
578 switch(_term_buf.bools[i]) {
579 case -1: *s++ = 0; break;
580 case 0: *s++ = 0377; break;
581 default: *s++ = 1; break;
584 n_bools = i;
585 if ((sz_name + n_bools) & 1)
586 n_bools++;
588 s = bin + 12 + sz_name + n_bools;
589 for(i = 0; _numorder[i] != -1; i++) {
590 n = _term_buf.nums[_numorder[i]];
591 switch(n) {
592 case -2: *s++ = 0377; *s++ = 0377; break;
593 case -1: *s++ = 0376; *s++ = 0377; break;
594 default:
595 *s++ = LSB(n);
596 *s++ = MSB(n);
599 n_nums = i;
601 s = bin + 12 + sz_name + n_bools + n_nums * 2;
602 for(i = 0; _strorder[i] != -1; i++) {
603 if (_term_buf.strs[_strorder[i]] == (char *) 0) {
604 *s++ = 0376; *s++ = 0377;
605 } else {
606 *s++ = 0377; *s++ = 0377;
609 n_offs = i;
611 s = bin + 12 + sz_name + n_bools + n_nums * 2;
612 strtbl = d = s + n_offs * 2;
613 for(i = 0; _strorder[i] != -1; i++) {
614 t = _term_buf.strs[_strorder[i]];
615 if (t == (char *) -1 || t == (char *) 0)
616 s += 2;
617 else {
618 n = d - strtbl;
619 *s++ = LSB(n);
620 *s++ = MSB(n);
621 t = convstr(t, _strorder[i]);
622 while(*t != '\0') {
623 *d++ = *t++;
624 if (d >= bin + MAX_BUF - 1) {
625 warn();
626 fprintf(stderr,
627 "compiled entry to big\n");
628 *d++ = '\0';
629 goto toobig;
632 *d++ = '\0';
636 toobig:
637 sz_strs = d - strtbl;
639 bin[0] = 032;
640 bin[1] = 01;
641 bin[2] = LSB(sz_name);
642 bin[3] = MSB(sz_name);
643 bin[4] = LSB(n_bools);
644 bin[5] = MSB(n_bools);
645 bin[6] = LSB(n_nums);
646 bin[7] = MSB(n_nums);
647 bin[8] = LSB(n_offs);
648 bin[9] = MSB(n_offs);
649 bin[10] = LSB(sz_strs);
650 bin[11] = MSB(sz_strs);
652 if (write(fd, bin, d - bin) == -1)
653 quit(errno, "can't write binary file");
655 return;
658 void
659 find_directory(void)
661 struct term_path *p;
662 struct stat st;
664 if (directory != NULL)
665 return;
667 p = path;
668 while(p->type != -1 && p->file != NULL) {
669 if (stat(p->file, &st) == 0) {
670 if ((st.st_mode & 0170000) == 0040000) {
671 directory = p->file;
672 return;
675 p++;
677 quit(-1, "can't find a terminfo directory");
680 /* convert a terminal name to a binary filename */
681 char *
682 binfile(char *name)
684 static char line[MAX_LINE+1];
686 sprintf(line, "%s/%c/%s", directory, *name, name);
687 return line;
690 char *
691 bindir(char *name)
693 static char line[MAX_LINE+1];
695 sprintf(line, "%s/%c", directory, *name);
696 return line;
700 badname(char *name)
702 while(*name) {
703 if (*name == '/' || !isgraph(*name))
704 return 1;
705 name++;
707 return 0;
710 /* output a terminfo binary */
711 void
712 outputbin(char *name)
714 register char *s, *d, *last;
715 char tmp[MAX_LINE+1];
716 char line[MAX_LINE+1];
717 int fd;
719 find_directory();
721 s = name;
722 d = line;
723 while(*s != '\0' && d < line + MAX_LINE) {
724 *d++ = *s++;
727 while(d > line && d[-1] == '|') {
728 d--;
731 *d = '\0';
733 s = strtok(line, "|");
734 last = NULL;
736 while(s != NULL && last == NULL) {
737 if (*s == '\0') {
739 } else if (badname(s)) {
740 if (lineno)
741 warn();
742 fprintf(stderr, "bad terminal name '%s', ignored.\n",
744 } else {
745 if (access(bindir(s), 2) == -1) {
746 if (errno != ENOENT)
747 quit(errno,
748 "can't access directory '%s'",
749 bindir(s));
750 if (mkdir(bindir(s), 0777) == -1)
751 quit(errno, "can't make directory '%s'",
752 bindir(s));
754 fd = open(binfile(s), O_WRONLY | O_CREAT | O_EXCL,
755 0666);
756 if (fd == -1) {
757 if (errno != EEXIST)
758 quit(errno, "can't open file '%s'",
759 binfile(s));
760 if (unlink(binfile(s)) == -1)
761 quit(errno, "can't unlink file '%s'",
762 binfile(s));
763 fd = open(binfile(s),
764 O_WRONLY | O_CREAT | O_EXCL, 0666);
765 if (fd == -1)
766 quit(errno, "can't create file '%s'",
767 binfile(s));
769 writebin(fd, name);
770 close(fd);
771 last = s;
773 s = strtok(NULL, "|");
776 if (last == NULL) {
777 if (lineno)
778 warn();
779 fprintf(stderr, "no terminal name, entry ignored.\n");
780 return;
783 while(s != NULL && s + strlen(s) != d) {
784 if (*s == '\0' || strcmp(s, last) == 0) {
786 } else if (badname(s)) {
787 if (lineno)
788 warn();
789 fprintf(stderr, "bad terminal name '%s', ignored.\n",
791 } else {
792 if (access(bindir(s), 2) == -1) {
793 if (errno != ENOENT)
794 quit(errno,
795 "can't access directory '%s'",
796 bindir(s));
797 if (mkdir(bindir(s), 0777) == -1)
798 quit(errno, "can't make directory '%s'",
799 bindir(s));
801 if (access(binfile(s), 0) == -1) {
802 if (errno != ENOENT)
803 quit(errno, "can't access file '%s'",
804 binfile(s));
805 } else if (unlink(binfile(s)) == -1) {
806 quit(errno, "can't unlink file '%s'",
807 binfile(s));
809 strcpy(tmp, binfile(last));
810 if (link(tmp, binfile(s)) == -1) {
811 quit(errno, "can't link '%s' to '%s'",
812 last, binfile(s));
815 s = strtok(NULL, "|");
817 return;
820 /* output an entry in terminfo source format */
821 void
822 outputinfo(char *name)
824 int i;
825 char line[MAX_LINE];
827 printf("%s,\n", name);
829 for(i = 0; i < NUM_OF_BOOLS; i++)
830 if (_term_buf.bools[i] == 0) {
831 sprintf(line, "%s@", boolnames[i]);
832 putstr(line);
833 } else if (_term_buf.bools[i] != -1)
834 putstr(boolnames[i]);
836 for(i = 0; i < NUM_OF_NUMS; i++)
837 if (_term_buf.nums[i] == -1) {
838 sprintf(line, "%s@", numnames[i]);
839 putstr(line);
840 } else if (_term_buf.nums[i] != -2) {
841 sprintf(line, "%s#%d", numnames[i], _term_buf.nums[i]);
842 putstr(line);
845 for(i = 0; i < NUM_OF_STRS; i++)
846 if (_term_buf.strs[i] == NULL) {
847 sprintf(line, "%s@", strnames[i]);
848 putstr(line);
849 } else if (_term_buf.strs[i] != (char *) -1) {
850 sprintf(line, "%s=%s", strnames[i],
851 convstr(_term_buf.strs[i], i));
852 putstr(line);
854 putstr(NULL);
857 /* convert a terminfo entry to binary format */
858 void
859 convtinfo(void)
861 int i, r;
863 termcap = 0;
865 for(i = 0; i < NUM_OF_BOOLS; i++)
866 _term_buf.bools[i] = -1;
867 for(i = 0; i < NUM_OF_NUMS; i++)
868 _term_buf.nums[i] = -2;
869 for(i = 0; i < NUM_OF_STRS; i++)
870 _term_buf.strs[i] = (char *) -1;
872 _term_buf.name_all = NULL;
874 r = _gettinfo(buf, &_term_buf, path);
875 if (r != 0) {
876 if (lineno == 0)
877 quit(-1, "problem reading entry");
878 else {
879 warn();
880 fprintf(stderr, "problem reading entry\n");
884 if (compile)
885 outputbin(_term_buf.name_all);
886 else
887 outputinfo(_term_buf.name_all);
888 return;
891 /* convert a terminfo binary to terminfo source */
892 void
893 convtbin(void)
895 int i, r;
897 termcap = 0;
899 for(i = 0; i < NUM_OF_BOOLS; i++)
900 _term_buf.bools[i] = -1;
901 for(i = 0; i < NUM_OF_NUMS; i++)
902 _term_buf.nums[i] = -2;
903 for(i = 0; i < NUM_OF_STRS; i++)
904 _term_buf.strs[i] = (char *) -1;
906 _term_buf.name_all = NULL;
908 r = _gettbin(buf, &_term_buf);
909 if (r != 0) {
910 if (lineno == 0)
911 quit(-1, "problem reading entry");
912 else {
913 warn();
914 fprintf(stderr, "problem reading entry\n");
918 outputinfo(_term_buf.name_all);
920 return;
923 /* convert a termcap entry to terminfo format */
924 void
925 convtcap(void)
927 int i, r;
928 char *name;
930 termcap = 1;
932 for(i = 0; i < NUM_OF_BOOLS; i++)
933 _term_buf.bools[i] = -1;
934 for(i = 0; i < NUM_OF_NUMS; i++)
935 _term_buf.nums[i] = -2;
936 for(i = 0; i < NUM_OF_STRS; i++)
937 _term_buf.strs[i] = (char *) -1;
939 _term_buf.name_all = NULL;
942 #if DEBUG
943 printf("%s\n", buf);
944 #endif
945 r = _gettcap(buf, &_term_buf, path);
946 if (r != 0) {
947 if (lineno == 0)
948 quit(-1, "problem reading entry");
949 else {
950 warn();
951 fprintf(stderr, "problem reading entry\n");
955 if (dodefault && !continued)
956 _tcapdefault();
958 _tcapconv();
960 name = _term_buf.name_all;
961 #if DEBUG
962 printf("...%s\n", name);
963 #endif
964 if (name[0] != '\0' && name[1] != '\0' && name[2] == '|')
965 name += 3; /* skip the 2 letter code */
967 if (compile)
968 outputbin(name);
969 else
970 outputinfo(name);
973 void
974 convbinfile(char *file)
976 register FILE *f;
977 int r;
979 f = fopen(file, "r");
981 if (f == NULL)
982 quit(errno, "can't open '%s'", file);
984 r = fread(buf, sizeof(char), MAX_BUF, f);
985 if (r < 12 || buf[0] != 032 || buf[1] != 01)
986 quit(-1, "file '%s' corrupted", file);
988 convtbin();
991 /* convert a termcap file to terminfo format */
992 void
993 convtcfile(char *file)
995 int nocolon;
996 register int c;
997 register char *d;
998 register FILE *f;
1000 f = fopen(file, "r");
1002 if (f == NULL)
1003 quit(errno, "can't open '%s'", file);
1005 d = buf;
1006 c = getc(f);
1007 while(c != EOF) {
1008 lineno++;
1009 if (c == '#') {
1010 if (keepcomments) {
1011 do {
1012 putchar(c);
1013 c = getc(f);
1014 } while(c != '\n' && c != EOF);
1015 putchar('\n');
1016 } else
1018 c = getc(f);
1019 while(c != '\n' && c != EOF);
1020 if (c != EOF)
1021 c = getc(f);
1022 continue;
1024 while(isspace(c) && c != '\n')
1025 c = getc(f);
1026 if (c == '\n' && buf == d) {
1027 c = getc(f);
1028 continue;
1031 while(c != EOF) {
1032 if (c == '\\') {
1033 c = getc(f);
1034 if (c == EOF)
1035 break;
1036 if (c == '\n') {
1037 c = getc(f);
1038 break;
1040 *d++ = '\\';
1041 *d++ = c;
1042 } else if (c == '\n') {
1043 *d = '\0';
1044 if (*--d == ':') {
1045 nocolon = 0;
1046 *d-- = '\0';
1047 } else {
1048 nocolon = 1;
1050 while(d > buf && *d != ':')
1051 d--;
1052 if (d[1] == 't' && d[2] == 'c' && d[3] == '=') {
1053 continued = 1;
1054 d[1] = '\0';
1055 } else
1056 continued = 0;
1057 convtcap();
1058 if (nocolon) {
1059 warn();
1060 fprintf(stderr,
1061 "entry doesn't end with :\n");
1063 _term_buf.strbuf = _endstr();
1064 _del_strs(&_term_buf);
1065 if (continued) {
1066 printf("\tuse=%s,\n", d + 4);
1068 d = buf;
1069 c = getc(f);
1070 break;
1071 } else
1072 *d++ = c;
1073 c = getc(f);
1078 static int
1079 getln(FILE *f, register char *buf, int len)
1081 register int c, i = 0;
1083 while((c = getc(f)) == '#') {
1084 lineno++;
1085 if (keepcomments) {
1086 putchar('#');
1087 while((c = getc(f)) != '\n') {
1088 if (c == EOF)
1089 return -1;
1090 putchar(c);
1092 putchar('\n');
1093 } else {
1094 while((c = getc(f)) != '\n')
1095 if (c == EOF)
1096 return -1;
1100 lineno++;
1101 while(c != '\n') {
1102 if (c == EOF)
1103 return -1;
1104 if (i < len) {
1105 i++;
1106 *buf++ = c;
1108 c = getc(f);
1111 while(isspace(*(buf-1))) {
1112 buf--;
1113 i--;
1116 *buf = '\0';
1117 return i;
1120 void
1121 convtifile(char *file)
1123 static char line[MAX_LINE+1];
1124 int l;
1125 int n;
1126 register FILE *f;
1128 f = fopen(file, "r");
1130 if (f == NULL)
1131 quit(errno, "can't open '%s'", file);
1133 lineno = 0;
1135 l = getln(f, line, MAX_LINE);
1136 while(l != -1) {
1137 if (line[l-1] == ':') {
1138 strncpy(buf, line, MAX_BUF);
1139 convtcap();
1140 } else if (line[l-1] == '\\') {
1141 n = MAX_BUF;
1142 do {
1143 line[--l] = '\0';
1144 if (n > 0)
1145 strncpy(buf + MAX_BUF - n, line, n);
1146 n -= l;
1147 l = getln(f, line, MAX_LINE);
1148 } while(l != -1 && line[l-1] == '\\');
1149 if (n > 0 && l != -1)
1150 strncpy(buf + MAX_BUF - n, line, n);
1151 convtcap();
1152 } else if (line[l-1] == ',') {
1153 n = MAX_BUF;
1154 do {
1155 if (n > 0)
1156 strncpy(buf + MAX_BUF - n, line, n);
1157 n -= l;
1158 l = getln(f, line, MAX_LINE);
1159 } while(l != -1 && isspace(line[0]));
1160 #if 0
1161 printf("buf = '%s'\n", buf);
1162 #endif
1163 convtinfo();
1164 continue;
1165 } else if (line[0] != '\0') {
1166 warn();
1167 fprintf(stderr, "malformed line\n");
1168 if (keepcomments) {
1169 printf("%s\n", line);
1172 l = getln(f, line, MAX_LINE);
1174 return;
1177 /* dummy routine for quit */
1178 /* ARGSUSED */
1179 void
1180 do_cleanup(int e)
1182 return;
1185 /* print out usage, called by quit */
1186 /* ARGSUSED */
1187 void
1188 usage(int e)
1190 fprintf(stderr, "%s\n%s\n%s\n%s\n",
1191 "usage: tconv [-b] [-c [-OUGd]] [-i] [-B [-D dir]] [-I] [-k] [-V]",
1192 " [-t term] [file]",
1193 " tic [file]",
1194 " captoinfo [-t term] [-OUGdk] [file]");
1195 return;
1199 main(int argc, char **argv)
1201 char *term = NULL;
1202 char *file = NULL;
1203 int r;
1204 char c;
1205 int pversion = 0;
1207 prg_name = strrchr(argv[0], '/');
1208 if (prg_name == NULL)
1209 prg_name = argv[0];
1210 else
1211 prg_name++;
1213 cleanup = usage;
1215 opterr = 0;
1217 if (strcmp(prg_name, "tic") == 0)
1218 compile = 1;
1220 while ((c = getopt(argc, argv, "bciBIOGUdkVD:t:")) != -1) {
1221 switch(c) {
1222 case 'O':
1223 noOT = 0;
1224 break;
1225 case 'G':
1226 noGNU = 0;
1227 break;
1228 case 'U':
1229 noUW = 0;
1230 break;
1231 case 'D':
1232 if (directory != NULL)
1233 quit(-1, "more than one directory specified");
1234 directory = optarg;
1235 break;
1236 case 't':
1237 if (term != NULL)
1238 quit(-1, "more than one terminal specified");
1239 term = optarg;
1240 break;
1241 case 'd': dodefault = 0; break;
1242 case 'k': keepcomments = 1; break;
1243 case 'b': from_tbin = 1; break;
1244 case 'c': from_tcap = 1; break;
1245 case 'i': from_tinfo = 1; break;
1246 case 'B': compile = 1; break;
1247 case 'I': compile = 0; break;
1248 case 'V': pversion = 1; break;
1249 case '?':
1250 default:
1251 quit(-1, "bad or missing command line argument");
1255 if (pversion) {
1256 quit(0, "%s\n%s", _mytinfo_version, SCCSid);
1259 if (optind == argc - 1)
1260 file = argv[optind];
1261 else if (optind != argc)
1262 quit(-1, "wrong number of arguments");
1264 if (from_tbin + from_tcap + from_tinfo > 1)
1265 quit(-1, "more than one input file type specified");
1267 if (!from_tcap && !from_tinfo && !from_tbin && file != NULL) {
1268 if (strcmp(prg_name, "cap2info") == 0
1269 || strcmp(prg_name, "captoinfo") == 0)
1270 from_tcap = 1;
1271 else if (strcmp(prg_name, "tic") == 0)
1272 from_tinfo = 1;
1273 else
1274 quit(-1, "no input file type specified");
1277 if (from_tbin && compile)
1278 quit(-1, "can't convert from binary to binary");
1280 if (file != NULL) {
1281 if (from_tbin) {
1282 cleanup = do_cleanup;
1283 convbinfile(file);
1284 exit(0);
1286 if (!compile)
1287 path = _buildpath(file, 0, NULL, -1);
1288 else {
1289 path = _buildpath(file, 0,
1290 "$TERMINFO", 2,
1291 "$MYTERMINFO", 2,
1292 #ifdef TERMINFODIR
1293 TERMINFODIR, 0,
1294 #endif
1295 NULL, -1);
1297 if (path == NULL)
1298 quit(-1, "can't build path");
1299 if (term == NULL) {
1300 cleanup = do_cleanup;
1301 if (from_tcap && !compile)
1302 convtcfile(file);
1303 else
1304 convtifile(file);
1305 exit(0);
1307 } else if (from_tcap && !compile)
1308 path = _buildpath("$TERMCAP", 1,
1309 #ifdef TERMCAPFILE
1310 TERMCAPFILE, 0,
1311 #endif
1312 NULL, -1);
1313 else if (from_tinfo || from_tbin)
1314 path = _buildpath("$TERMINFO", 2,
1315 "$MYTERMINFO", 2,
1316 #ifdef TERMINFODIR
1317 TERMINFODIR, 0,
1318 #endif
1319 #ifdef TERMINFOSRC
1320 TERMINFOSRC, 0,
1321 #endif
1322 NULL, -1);
1323 else if (from_tcap)
1324 path = _buildpath("$TERMCAP", 1,
1325 #ifdef TERMCAPFILE
1326 TERMCAPFILE, 0,
1327 #endif
1328 "$TERMINFO", 2,
1329 "$MYTERMINFO", 2,
1330 #ifdef TERMINFODIR
1331 TERMINFODIR, 0,
1332 #endif
1333 NULL, -1);
1334 else
1335 path = _buildpath(
1336 #ifdef USE_TERMINFO
1337 "$MYTERMINFO", 2,
1338 "$TERMINFO", 2,
1339 #ifdef TERMINFODIR
1340 TERMINFODIR, 0,
1341 #endif
1342 #ifdef TERMINFOSRC
1343 TERMINFOSRC, 0,
1344 #endif
1345 #endif
1346 #ifdef USE_TERMCAP
1347 "$TERMCAP", 1,
1348 #ifdef TERMCAPFILE
1349 TERMCAPFILE, 0,
1350 #endif
1351 #endif
1352 NULL, -1);
1353 if (term == NULL) {
1354 term = getenv("TERM");
1355 if (term == NULL)
1356 quit(-1, "no terminal type given");
1359 cleanup = do_cleanup;
1361 r = _findterm(term, path, buf);
1362 switch(r) {
1363 case 1:
1364 convtcap();
1365 break;
1366 case 2:
1367 convtinfo();
1368 break;
1369 case 3:
1370 if (compile)
1371 quit(-1, "entry is already compiled");
1372 convtbin();
1373 break;
1374 default:
1375 quit(-1, "can't find a terminal entry for '%s'", term);
1378 exit(0);
1379 return 0;