163 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * cstring.c -- parse and print strings using the C escape sequences
 | |
|  */
 | |
| 
 | |
| #include "config.h"
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <ctype.h>
 | |
| #ifdef HAVE_GETOPT_H
 | |
| #include <getopt.h>
 | |
| #endif
 | |
| #include <string.h>
 | |
| 
 | |
| #include "cstring.h"
 | |
| 
 | |
| int parse_c_string(char *str)
 | |
| {
 | |
| 	char *to, *from, ch;
 | |
| 	int v;
 | |
| 
 | |
| 	to = from = str;
 | |
| 
 | |
| 	for (to = from = (char *) str;
 | |
| 	     *from && *from != '"'; to++, from++) {
 | |
| 		if (*from == '\\') {
 | |
| 			ch = *(++from);
 | |
| 			switch (ch) {
 | |
| 			case 'a':
 | |
| 				*to = '\a';
 | |
| 				break;
 | |
| 			case 'b':
 | |
| 				*to = '\b';
 | |
| 				break;
 | |
| 			case 'f':
 | |
| 				*to = '\f';
 | |
| 				break;
 | |
| 			case 'n':
 | |
| 				*to = '\n';
 | |
| 				break;
 | |
| 			case 't':
 | |
| 				*to = '\t';
 | |
| 				break;
 | |
| 			case 'v':
 | |
| 				*to = '\v';
 | |
| 				break;
 | |
| 			case 'x':
 | |
| 				ch = *(from + 1);
 | |
| 				if (ch >= 'a' && ch <= 'f')
 | |
| 					ch = ch - 'a' + 'A';
 | |
| 				if (ch >= '0' && ch <= '9')
 | |
| 					v = ch - '0';
 | |
| 				else if (ch >= 'A' && ch <= 'F')
 | |
| 					v = ch + 10 - 'A';
 | |
| 				else {
 | |
| 					*to = 'x';
 | |
| 					break;
 | |
| 				}
 | |
| 				from++;
 | |
| 				ch = *(from + 1);
 | |
| 				if (ch >= 'a' && ch <= 'f')
 | |
| 					ch = ch - 'a' + 'A';
 | |
| 				if (ch >= '0' && ch <= '9')
 | |
| 					v = (v * 16) + (ch - '0');
 | |
| 				else if (ch >= 'A' && ch <= 'F')
 | |
| 					v = (v * 16) + (ch + 10 - 'A');
 | |
| 				else {
 | |
| 					*to = 'x';
 | |
| 					from--;
 | |
| 					break;
 | |
| 				}
 | |
| 				from++;
 | |
| 				*to = v;
 | |
| 				break;
 | |
| 			default:
 | |
| 				if (ch >= '0' && ch <= '9') {
 | |
| 					v = ch - '0';
 | |
| 					ch = *(from + 1);
 | |
| 					if (ch >= '0' && ch <= '9') {
 | |
| 						from++;
 | |
| 						v = (8 * v) + (ch - '0');
 | |
| 						ch = *(from + 1);
 | |
| 						if (ch >= '0' && ch <= '9') {
 | |
| 							from++;
 | |
| 							v = (8 * v) + (ch - '0');
 | |
| 						}
 | |
| 					}
 | |
| 					ch = v;
 | |
| 				}
 | |
| 				*to = ch;
 | |
| 			}
 | |
| 			continue;
 | |
| 		}
 | |
| 		*to = *from;
 | |
| 	}
 | |
| 	*to = '\0';
 | |
| 	return to - (char *) str;
 | |
| }
 | |
| 
 | |
| void print_c_string(FILE *f, const char *cp, int len)
 | |
| {
 | |
| 	unsigned char	ch;
 | |
| 
 | |
| 	if (len < 0)
 | |
| 		len = strlen(cp);
 | |
| 
 | |
| 	while (len--) {
 | |
| 		ch = *cp++;
 | |
| 		if (ch == '\a')
 | |
| 			fputs("\\a", f);
 | |
| 		else if (ch == '\b')
 | |
| 			fputs("\\b", f);
 | |
| 		else if (ch == '\f')
 | |
| 			fputs("\\f", f);
 | |
| 		else if (ch == '\n')
 | |
| 			fputs("\\n", f);
 | |
| 		else if (ch == '\t')
 | |
| 			fputs("\\t", f);
 | |
| 		else if (ch == '\v')
 | |
| 			fputs("\\v", f);
 | |
| 		else if (ch == '\\')
 | |
| 			fputs("\\\\", f);
 | |
| 		else if (ch == '\'')
 | |
| 			fputs("\\\'", f);
 | |
| 		else if (ch == '\"')
 | |
| 			fputs("\\\"", f);
 | |
| 		else if ((ch < 32) || (ch > 126))
 | |
| 			fprintf(f, "\\%03o", ch);
 | |
| 		else
 | |
| 			fputc(ch, f);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #ifdef DEBUG_PROGRAM
 | |
| int main(int argc, char **argv)
 | |
| {
 | |
| 	char buf[4096];
 | |
| 	int c, raw = 0;
 | |
| 
 | |
| 	while ((c = getopt(argc, argv, "r")) != EOF) {
 | |
| 		switch (c) {
 | |
| 		case 'r':
 | |
| 			raw++;
 | |
| 			break;
 | |
| 		default:
 | |
| 			fprintf(stderr, "Usage: %s [-r]\n", argv[0]);
 | |
| 			exit(1);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	while (!feof(stdin)) {
 | |
| 		if (fgets(buf, sizeof(buf), stdin) == NULL)
 | |
| 			break;
 | |
| 		c = parse_c_string(buf);
 | |
| 		if (raw)
 | |
| 			fputs(buf, stdout);
 | |
| 		else {
 | |
| 			print_c_string(stdout, buf, c);
 | |
| 			printf(" <%d>\n", c);
 | |
| 		}
 | |
| 	}
 | |
| }	
 | |
| #endif
 |