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 #include <stdio.h> 41 #include <ctype.h> 42 #include <string.h> 43 #include <stdlib.h> 44 #include "print.h" 45 46 #define BACKSLASH '\\' 47 #define BACKBACK "\\\\" 48 49 extern char *strcat(); 50 51 static char retbuffer[1024]; 52 static char ret2buffer[1024]; 53 54 /* 55 * Remove the padding sequences from the input string. 56 * Return the new string without the padding sequences 57 * and the padding itself in padbuffer. 58 */ 59 char 60 *rmpadding(char *str, char *padbuffer, int *padding) 61 { 62 static char rmbuffer[1024]; 63 register char ch; 64 register char *pbufptr; 65 register char *retptr = rmbuffer; 66 char *svbufptr; 67 int padbylines = 0; 68 int paddigits = 0; 69 int paddecimal = 0; 70 71 padbuffer[0] = rmbuffer[0] = '\0'; 72 if (padding) 73 *padding = 0; 74 if (str == NULL) 75 return (rmbuffer); 76 77 while (ch = (*str++ & 0377)) 78 switch (ch) { 79 case '$': 80 if (*str == '<') { 81 svbufptr = ++str; /* skip '<' */ 82 83 /* copy number */ 84 pbufptr = padbuffer; 85 for (; *str && isdigit(*str); str++) { 86 *svbufptr++ = *str; 87 *pbufptr++ = *str; 88 } 89 *pbufptr = '\0'; 90 paddigits += atoi(padbuffer); 91 /* check for decimal */ 92 if (*str == '.') { 93 str++; 94 pbufptr = padbuffer; 95 for (; *str && isdigit(ch); 96 str++) { 97 *svbufptr++ = *str; 98 *pbufptr++ = *str; 99 } 100 *pbufptr = '\0'; 101 paddecimal += atoi(padbuffer); 102 } 103 for (; (*str == '*') || (*str == '/'); 104 str++) { 105 if (*str == '*') 106 padbylines = 1; 107 /* Termcap does not support mandatory padding */ 108 /* marked with /. Just remove it. */ 109 else { 110 extern char *progname; 111 (void) fprintf(stderr, 112 "%s: mandatory " 113 "padding removed\n", 114 progname); 115 } 116 } 117 /* oops, not a padding spec after all */ 118 /* put us back after the '$<' */ 119 if (*str != '>') { 120 str = svbufptr; 121 *retptr++ = '$'; 122 *retptr++ = '<'; 123 } else 124 str++; /* skip the '>' */ 125 /* Flag padding info that is not at the end */ 126 /* of the string. */ 127 if (*str != '\0') { 128 extern char *progname; 129 (void) fprintf(stderr, 130 "%s: padding information " 131 "moved to end\n", progname); 132 } 133 } else 134 *retptr++ = ch; 135 break; 136 137 default: 138 *retptr++ = ch; 139 } 140 *retptr = '\0'; 141 142 if (paddecimal > 10) { 143 paddigits += paddecimal / 10; 144 paddecimal %= 10; 145 } 146 147 if (paddigits > 0 && paddecimal > 0) 148 (void) sprintf(padbuffer, "%d.%d", paddigits, paddecimal); 149 else if (paddigits > 0) 150 (void) sprintf(padbuffer, "%d", paddigits); 151 else if (paddecimal > 0) 152 (void) sprintf(padbuffer, ".%d", paddecimal); 153 if (padbylines) 154 (void) strcat(padbuffer, "*"); 155 if (padding) 156 *padding = paddecimal; 157 return (rmbuffer); 158 } 159 160 /* 161 * Convert a character, making appropriate changes to make it printable 162 * for a termcap source entry. Change escape, tab, etc., into their 163 * appropriate equivalents. Return the number of characters printed. 164 */ 165 char 166 *cconvert(char *string) 167 { 168 register int c; 169 register char *retptr = retbuffer; 170 171 retbuffer[0] = '\0'; 172 if (string == NULL) 173 return (retbuffer); 174 175 while (c = *string++) { 176 /* should check here to make sure that there is enough room */ 177 /* in retbuffer and realloc it if necessary. */ 178 c &= 0377; 179 /* we ignore the return value from sprintf because BSD/V7 */ 180 /* systems return a (char *) rather than an int. */ 181 if (c >= 0200) { 182 (void) sprintf(retptr, "\\%.3o", c); retptr += 4; } 183 else if (c == '\033') { 184 (void) sprintf(retptr, "\\E"); retptr += 2; } 185 else if (c == '\t') { 186 (void) sprintf(retptr, "\\t"); retptr += 2; } 187 else if (c == '\b') { 188 (void) sprintf(retptr, "\\b"); retptr += 2; } 189 else if (c == '\f') { 190 (void) sprintf(retptr, "\\f"); retptr += 2; } 191 else if (c == '\n') { 192 (void) sprintf(retptr, "\\n"); retptr += 2; } 193 else if (c == '\r') { 194 (void) sprintf(retptr, "\\r"); retptr += 2; } 195 196 /* unfortunately \: did not work */ 197 else if (c == ':') { 198 (void) sprintf(retptr, "\\072"); retptr += 4; } 199 else if (c == '^') { 200 (void) sprintf(retptr, "\\^"); retptr += 2; } 201 else if (c == BACKSLASH) { 202 (void) sprintf(retptr, BACKBACK); retptr += 2; } 203 else if (c < ' ' || c == 0177) { 204 (void) sprintf(retptr, "^%c", c ^ 0100); retptr += 2; } 205 else { 206 (void) sprintf(retptr, "%c", c); retptr++; } 207 } 208 *retptr = '\0'; 209 return (retbuffer); 210 } 211 212 /* 213 * Convert the terminfo string into a termcap string. 214 * Most of the work is done by rmpadding() above and cconvert(); this 215 * function mainly just pieces things back together. A pointer to the 216 * return buffer is returned. 217 * 218 * NOTE: Some things can not be done at all: converting the terminfo 219 * parameterized strings into termcap parameterized strings. 220 */ 221 222 char 223 *cexpand(char *str) 224 { 225 char padbuffer[512]; 226 char *retptr; 227 228 retptr = rmpadding(str, padbuffer, (int *)0); 229 (void) sprintf(ret2buffer, "%s%s", padbuffer, cconvert(retptr)); 230 231 return (ret2buffer); 232 } 233 234 /* 235 * Print out a string onto a stream, changing unprintables into 236 * termcap printables. 237 */ 238 int 239 cpr(FILE *stream, char *string) 240 { 241 register char *ret; 242 if (string != NULL) { 243 ret = cexpand(string); 244 (void) fprintf(stream, "%s", ret); 245 return (strlen(ret)); 246 } else 247 return (0); 248 } 249