1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include <stdio.h> 43 #include <ctype.h> 44 #include <string.h> 45 #include <stdlib.h> 46 #include "print.h" 47 48 #define BACKSLASH '\\' 49 #define BACKBACK "\\\\" 50 51 extern char *strcat(); 52 53 static char retbuffer[1024]; 54 static char ret2buffer[1024]; 55 56 /* 57 * Remove the padding sequences from the input string. 58 * Return the new string without the padding sequences 59 * and the padding itself in padbuffer. 60 */ 61 char 62 *rmpadding(char *str, char *padbuffer, int *padding) 63 { 64 static char rmbuffer[1024]; 65 register char ch; 66 register char *pbufptr; 67 register char *retptr = rmbuffer; 68 char *svbufptr; 69 int padbylines = 0; 70 int paddigits = 0; 71 int paddecimal = 0; 72 73 padbuffer[0] = rmbuffer[0] = '\0'; 74 if (padding) 75 *padding = 0; 76 if (str == NULL) 77 return (rmbuffer); 78 79 while (ch = (*str++ & 0377)) 80 switch (ch) { 81 case '$': 82 if (*str == '<') { 83 svbufptr = ++str; /* skip '<' */ 84 85 /* copy number */ 86 pbufptr = padbuffer; 87 for (; *str && isdigit(*str); str++) { 88 *svbufptr++ = *str; 89 *pbufptr++ = *str; 90 } 91 *pbufptr = '\0'; 92 paddigits += atoi(padbuffer); 93 /* check for decimal */ 94 if (*str == '.') { 95 str++; 96 pbufptr = padbuffer; 97 for (; *str && isdigit(ch); 98 str++) { 99 *svbufptr++ = *str; 100 *pbufptr++ = *str; 101 } 102 *pbufptr = '\0'; 103 paddecimal += atoi(padbuffer); 104 } 105 for (; (*str == '*') || (*str == '/'); 106 str++) { 107 if (*str == '*') 108 padbylines = 1; 109 /* Termcap does not support mandatory padding */ 110 /* marked with /. Just remove it. */ 111 else { 112 extern char *progname; 113 (void) fprintf(stderr, 114 "%s: mandatory " 115 "padding removed\n", 116 progname); 117 } 118 } 119 /* oops, not a padding spec after all */ 120 /* put us back after the '$<' */ 121 if (*str != '>') { 122 str = svbufptr; 123 *retptr++ = '$'; 124 *retptr++ = '<'; 125 } else 126 str++; /* skip the '>' */ 127 /* Flag padding info that is not at the end */ 128 /* of the string. */ 129 if (*str != '\0') { 130 extern char *progname; 131 (void) fprintf(stderr, 132 "%s: padding information " 133 "moved to end\n", progname); 134 } 135 } else 136 *retptr++ = ch; 137 break; 138 139 default: 140 *retptr++ = ch; 141 } 142 *retptr = '\0'; 143 144 if (paddecimal > 10) { 145 paddigits += paddecimal / 10; 146 paddecimal %= 10; 147 } 148 149 if (paddigits > 0 && paddecimal > 0) 150 (void) sprintf(padbuffer, "%d.%d", paddigits, paddecimal); 151 else if (paddigits > 0) 152 (void) sprintf(padbuffer, "%d", paddigits); 153 else if (paddecimal > 0) 154 (void) sprintf(padbuffer, ".%d", paddecimal); 155 if (padbylines) 156 (void) strcat(padbuffer, "*"); 157 if (padding) 158 *padding = paddecimal; 159 return (rmbuffer); 160 } 161 162 /* 163 * Convert a character, making appropriate changes to make it printable 164 * for a termcap source entry. Change escape, tab, etc., into their 165 * appropriate equivalents. Return the number of characters printed. 166 */ 167 char 168 *cconvert(char *string) 169 { 170 register int c; 171 register char *retptr = retbuffer; 172 173 retbuffer[0] = '\0'; 174 if (string == NULL) 175 return (retbuffer); 176 177 while (c = *string++) { 178 /* should check here to make sure that there is enough room */ 179 /* in retbuffer and realloc it if necessary. */ 180 c &= 0377; 181 /* we ignore the return value from sprintf because BSD/V7 */ 182 /* systems return a (char *) rather than an int. */ 183 if (c >= 0200) { 184 (void) sprintf(retptr, "\\%.3o", c); retptr += 4; } 185 else if (c == '\033') { 186 (void) sprintf(retptr, "\\E"); retptr += 2; } 187 else if (c == '\t') { 188 (void) sprintf(retptr, "\\t"); retptr += 2; } 189 else if (c == '\b') { 190 (void) sprintf(retptr, "\\b"); retptr += 2; } 191 else if (c == '\f') { 192 (void) sprintf(retptr, "\\f"); retptr += 2; } 193 else if (c == '\n') { 194 (void) sprintf(retptr, "\\n"); retptr += 2; } 195 else if (c == '\r') { 196 (void) sprintf(retptr, "\\r"); retptr += 2; } 197 198 /* unfortunately \: did not work */ 199 else if (c == ':') { 200 (void) sprintf(retptr, "\\072"); retptr += 4; } 201 else if (c == '^') { 202 (void) sprintf(retptr, "\\^"); retptr += 2; } 203 else if (c == BACKSLASH) { 204 (void) sprintf(retptr, BACKBACK); retptr += 2; } 205 else if (c < ' ' || c == 0177) { 206 (void) sprintf(retptr, "^%c", c ^ 0100); retptr += 2; } 207 else { 208 (void) sprintf(retptr, "%c", c); retptr++; } 209 } 210 *retptr = '\0'; 211 return (retbuffer); 212 } 213 214 /* 215 * Convert the terminfo string into a termcap string. 216 * Most of the work is done by rmpadding() above and cconvert(); this 217 * function mainly just pieces things back together. A pointer to the 218 * return buffer is returned. 219 * 220 * NOTE: Some things can not be done at all: converting the terminfo 221 * parameterized strings into termcap parameterized strings. 222 */ 223 224 char 225 *cexpand(char *str) 226 { 227 char padbuffer[512]; 228 char *retptr; 229 230 retptr = rmpadding(str, padbuffer, (int *)0); 231 (void) sprintf(ret2buffer, "%s%s", padbuffer, cconvert(retptr)); 232 233 return (ret2buffer); 234 } 235 236 /* 237 * Print out a string onto a stream, changing unprintables into 238 * termcap printables. 239 */ 240 int 241 cpr(FILE *stream, char *string) 242 { 243 register char *ret; 244 if (string != NULL) { 245 ret = cexpand(string); 246 (void) fprintf(stream, "%s", ret); 247 return (strlen(ret)); 248 } else 249 return (0); 250 } 251