1c6c9aed4Sab196087 /* 2c6c9aed4Sab196087 * CDDL HEADER START 3c6c9aed4Sab196087 * 4c6c9aed4Sab196087 * The contents of this file are subject to the terms of the 5c6c9aed4Sab196087 * Common Development and Distribution License (the "License"). 6c6c9aed4Sab196087 * You may not use this file except in compliance with the License. 7c6c9aed4Sab196087 * 8c6c9aed4Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c6c9aed4Sab196087 * or http://www.opensolaris.org/os/licensing. 10c6c9aed4Sab196087 * See the License for the specific language governing permissions 11c6c9aed4Sab196087 * and limitations under the License. 12c6c9aed4Sab196087 * 13c6c9aed4Sab196087 * When distributing Covered Code, include this CDDL HEADER in each 14c6c9aed4Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c6c9aed4Sab196087 * If applicable, add the following below this CDDL HEADER, with the 16c6c9aed4Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying 17c6c9aed4Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner] 18c6c9aed4Sab196087 * 19c6c9aed4Sab196087 * CDDL HEADER END 20c6c9aed4Sab196087 */ 21c6c9aed4Sab196087 22c6c9aed4Sab196087 /* 23*69112eddSAli Bahrami * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24c6c9aed4Sab196087 * Use is subject to license terms. 25c6c9aed4Sab196087 */ 26c6c9aed4Sab196087 27c6c9aed4Sab196087 28c6c9aed4Sab196087 /* 29c6c9aed4Sab196087 * Translate a string into C literal string constant notation. 30c6c9aed4Sab196087 */ 31c6c9aed4Sab196087 32c6c9aed4Sab196087 #include <stdio.h> 33c6c9aed4Sab196087 #include <ctype.h> 34c6c9aed4Sab196087 #include <_conv.h> 35c6c9aed4Sab196087 #include <c_literal_msg.h> 36c6c9aed4Sab196087 37c6c9aed4Sab196087 38c6c9aed4Sab196087 /* 39c6c9aed4Sab196087 * Convert characters to the form used by the C language to represent 40c6c9aed4Sab196087 * literal strings: 41c6c9aed4Sab196087 * - Printable characters are shown as themselves 42c6c9aed4Sab196087 * - Convert special characters to their 2-character escaped forms: 43c6c9aed4Sab196087 * alert (bell) \a 44c6c9aed4Sab196087 * backspace \b 45c6c9aed4Sab196087 * formfeed \f 46c6c9aed4Sab196087 * newline \n 47c6c9aed4Sab196087 * return \r 48c6c9aed4Sab196087 * horizontal tab \t 49c6c9aed4Sab196087 * vertical tab \v 50c6c9aed4Sab196087 * backspace \\ 51c6c9aed4Sab196087 * single quote \' 52c6c9aed4Sab196087 * double quote \" 53c6c9aed4Sab196087 * - Display other non-printable characters as 4-character escaped 54c6c9aed4Sab196087 * octal constants. 55c6c9aed4Sab196087 * 56c6c9aed4Sab196087 * entry: 57c6c9aed4Sab196087 * buf - Buffer of characters to be processed 58c6c9aed4Sab196087 * n # of characters in buf to be processed 59c6c9aed4Sab196087 * outfunc - Function to be called to move output characters. 60c6c9aed4Sab196087 * uvalue - User value. This argument is passed to outfunc without 61c6c9aed4Sab196087 * examination. The caller can use it to pass additional 62c6c9aed4Sab196087 * information required by the callback. 63c6c9aed4Sab196087 * 64c6c9aed4Sab196087 * exit: 65c6c9aed4Sab196087 * The string has been processed, with the resulting data passed 66c6c9aed4Sab196087 * to outfunc for processing. 67c6c9aed4Sab196087 */ 68c6c9aed4Sab196087 void 69c6c9aed4Sab196087 conv_str_to_c_literal(const char *buf, size_t n, 70c6c9aed4Sab196087 Conv_str_to_c_literal_func_t *outfunc, void *uvalue) 71c6c9aed4Sab196087 { 72c6c9aed4Sab196087 char bs_buf[2]; /* For two-character backslash codes */ 73c6c9aed4Sab196087 char octal_buf[10]; /* For \000 style octal constants */ 74c6c9aed4Sab196087 75c6c9aed4Sab196087 bs_buf[0] = '\\'; 76c6c9aed4Sab196087 while (n > 0) { 77c6c9aed4Sab196087 switch (*buf) { 78c6c9aed4Sab196087 case '\0': 79c6c9aed4Sab196087 bs_buf[1] = '0'; 80c6c9aed4Sab196087 break; 81c6c9aed4Sab196087 case '\a': 82c6c9aed4Sab196087 bs_buf[1] = 'a'; 83c6c9aed4Sab196087 break; 84c6c9aed4Sab196087 case '\b': 85c6c9aed4Sab196087 bs_buf[1] = 'b'; 86c6c9aed4Sab196087 break; 87c6c9aed4Sab196087 case '\f': 88c6c9aed4Sab196087 bs_buf[1] = 'f'; 89c6c9aed4Sab196087 break; 90c6c9aed4Sab196087 case '\n': 91c6c9aed4Sab196087 bs_buf[1] = 'n'; 92c6c9aed4Sab196087 break; 93c6c9aed4Sab196087 case '\r': 94c6c9aed4Sab196087 bs_buf[1] = 'r'; 95c6c9aed4Sab196087 break; 96c6c9aed4Sab196087 case '\t': 97c6c9aed4Sab196087 bs_buf[1] = 't'; 98c6c9aed4Sab196087 break; 99c6c9aed4Sab196087 case '\v': 100c6c9aed4Sab196087 bs_buf[1] = 'v'; 101c6c9aed4Sab196087 break; 102c6c9aed4Sab196087 case '\\': 103c6c9aed4Sab196087 bs_buf[1] = '\\'; 104c6c9aed4Sab196087 break; 105c6c9aed4Sab196087 case '\'': 106c6c9aed4Sab196087 bs_buf[1] = '\''; 107c6c9aed4Sab196087 break; 108c6c9aed4Sab196087 case '"': 109c6c9aed4Sab196087 bs_buf[1] = '"'; 110c6c9aed4Sab196087 break; 111c6c9aed4Sab196087 default: 112c6c9aed4Sab196087 bs_buf[1] = '\0'; 113c6c9aed4Sab196087 } 114c6c9aed4Sab196087 115c6c9aed4Sab196087 if (bs_buf[1] != '\0') { 116c6c9aed4Sab196087 (*outfunc)(bs_buf, 2, uvalue); 117c6c9aed4Sab196087 buf++; 118c6c9aed4Sab196087 n--; 119c6c9aed4Sab196087 } else if (isprint(*buf)) { 120c6c9aed4Sab196087 /* 121c6c9aed4Sab196087 * Output the entire sequence of printable 122c6c9aed4Sab196087 * characters in a single shot. 123c6c9aed4Sab196087 */ 124c6c9aed4Sab196087 const char *start = buf; 125c6c9aed4Sab196087 size_t outlen = 0; 126c6c9aed4Sab196087 127c6c9aed4Sab196087 for (start = buf; (n > 0) && isprint(*buf); buf++, n--) 128c6c9aed4Sab196087 outlen++; 129c6c9aed4Sab196087 (*outfunc)(start, outlen, uvalue); 130c6c9aed4Sab196087 } else { 131c6c9aed4Sab196087 /* Generic unprintable character: Use octal notation */ 132c6c9aed4Sab196087 (void) snprintf(octal_buf, sizeof (octal_buf), 1331da7e599SAli Bahrami MSG_ORIG(MSG_FMT_OCTCONST), (uchar_t)*buf); 134c6c9aed4Sab196087 (*outfunc)(octal_buf, strlen(octal_buf), uvalue); 135c6c9aed4Sab196087 buf++; 136c6c9aed4Sab196087 n--; 137c6c9aed4Sab196087 } 138c6c9aed4Sab196087 } 139c6c9aed4Sab196087 } 140*69112eddSAli Bahrami 141*69112eddSAli Bahrami /* 142*69112eddSAli Bahrami * Given the pointer to the character following a '\' character in 143*69112eddSAli Bahrami * a C style literal, return the ASCII character code it represents, 144*69112eddSAli Bahrami * and advance the string pointer to the character following the last 145*69112eddSAli Bahrami * character in the escape sequence. 146*69112eddSAli Bahrami * 147*69112eddSAli Bahrami * entry: 148*69112eddSAli Bahrami * str - Address of string pointer to first character following 149*69112eddSAli Bahrami * the backslash. 150*69112eddSAli Bahrami * 151*69112eddSAli Bahrami * exit: 152*69112eddSAli Bahrami * If the character is not valid, -1 is returned. Otherwise 153*69112eddSAli Bahrami * it returns the ASCII code for the translated character, and 154*69112eddSAli Bahrami * *str has been advanced. 155*69112eddSAli Bahrami */ 156*69112eddSAli Bahrami int 157*69112eddSAli Bahrami conv_translate_c_esc(char **str) 158*69112eddSAli Bahrami { 159*69112eddSAli Bahrami char *s = *str; 160*69112eddSAli Bahrami int ch, i; 161*69112eddSAli Bahrami 162*69112eddSAli Bahrami ch = *s++; 163*69112eddSAli Bahrami switch (ch) { 164*69112eddSAli Bahrami case 'a': 165*69112eddSAli Bahrami ch = '\a'; 166*69112eddSAli Bahrami break; 167*69112eddSAli Bahrami case 'b': 168*69112eddSAli Bahrami ch = '\b'; 169*69112eddSAli Bahrami break; 170*69112eddSAli Bahrami case 'f': 171*69112eddSAli Bahrami ch = '\f'; 172*69112eddSAli Bahrami break; 173*69112eddSAli Bahrami case 'n': 174*69112eddSAli Bahrami ch = '\n'; 175*69112eddSAli Bahrami break; 176*69112eddSAli Bahrami case 'r': 177*69112eddSAli Bahrami ch = '\r'; 178*69112eddSAli Bahrami break; 179*69112eddSAli Bahrami case 't': 180*69112eddSAli Bahrami ch = '\t'; 181*69112eddSAli Bahrami break; 182*69112eddSAli Bahrami case 'v': 183*69112eddSAli Bahrami ch = '\v'; 184*69112eddSAli Bahrami break; 185*69112eddSAli Bahrami 186*69112eddSAli Bahrami case '0': 187*69112eddSAli Bahrami case '1': 188*69112eddSAli Bahrami case '2': 189*69112eddSAli Bahrami case '3': 190*69112eddSAli Bahrami case '4': 191*69112eddSAli Bahrami case '5': 192*69112eddSAli Bahrami case '6': 193*69112eddSAli Bahrami case '7': 194*69112eddSAli Bahrami /* Octal constant: There can be up to 3 digits */ 195*69112eddSAli Bahrami ch -= '0'; 196*69112eddSAli Bahrami for (i = 0; i < 2; i++) { 197*69112eddSAli Bahrami if ((*s < '0') || (*s > '7')) 198*69112eddSAli Bahrami break; 199*69112eddSAli Bahrami ch = (ch << 3) + (*s++ - '0'); 200*69112eddSAli Bahrami } 201*69112eddSAli Bahrami break; 202*69112eddSAli Bahrami 203*69112eddSAli Bahrami /* 204*69112eddSAli Bahrami * There are some cases where ch already has the desired value. 205*69112eddSAli Bahrami * These cases exist simply to remove the special meaning that 206*69112eddSAli Bahrami * character would otherwise have. We need to match them to 207*69112eddSAli Bahrami * prevent them from falling into the default error case. 208*69112eddSAli Bahrami */ 209*69112eddSAli Bahrami case '\\': 210*69112eddSAli Bahrami case '\'': 211*69112eddSAli Bahrami case '"': 212*69112eddSAli Bahrami break; 213*69112eddSAli Bahrami 214*69112eddSAli Bahrami default: 215*69112eddSAli Bahrami ch = -1; 216*69112eddSAli Bahrami break; 217*69112eddSAli Bahrami } 218*69112eddSAli Bahrami 219*69112eddSAli Bahrami *str = s; 220*69112eddSAli Bahrami return (ch); 221*69112eddSAli Bahrami } 222