|
|
1.1 ! root 1: /* ! 2: * getpath (file) - read a path name ! 3: * putpath (file, path) - write a path name ! 4: * ! 5: * These subroutines cater to the possibility of unprintable ! 6: * characters in the path names being read or written, by ! 7: * using the same sort of \ conventions commonly found in ! 8: * C character constants. The result of getpath is a pointer ! 9: * to a static buffer whose contents will stay around no longer ! 10: * than the next call to getpath. When getpath is called, the ! 11: * character about to be read from the input file must be the ! 12: * first character of the path name. ! 13: * ! 14: * There are a few problems, mostly relating to bugs and language ! 15: * changes, to watch out for in these routines. First of all, ! 16: * we assume that \v is known by the C compiler, even though ! 17: * it is not mentioned in Kernighan and Ritchie. The reason for ! 18: * this is that if we do not make this assumption, we run into ! 19: * a common bug in the handling of iscntrl(). Although the ! 20: * manuals all say that if c is a white-space character that is ! 21: * not a blank, then iscntrl(c) is true, several versions of the ! 22: * C library disagree with the documentation. Thus we try to ! 23: * list all the white-space characters explicitly. ! 24: */ ! 25: ! 26: #include "asd.h" ! 27: #include <ctype.h> ! 28: #include <stdio.h> ! 29: ! 30: #define CHUNK 64 ! 31: ! 32: static char *r; ! 33: static unsigned size; ! 34: ! 35: char * ! 36: getpath (FILE *file) ! 37: { ! 38: register int c; ! 39: register int len = 0; ! 40: ! 41: c = getc (file); ! 42: ! 43: while (!isspace(c) && c != EOF) { ! 44: register int i = 0, n = 0; ! 45: ! 46: /* determine the next input character */ ! 47: if (c == '\\') { ! 48: c = getc (file); ! 49: switch (c) { ! 50: ! 51: case '\\': ! 52: break; ! 53: ! 54: case 'n': ! 55: c = '\n'; ! 56: break; ! 57: ! 58: case 'r': ! 59: c = '\r'; ! 60: break; ! 61: ! 62: case 't': ! 63: c = '\t'; ! 64: break; ! 65: ! 66: case 'b': ! 67: c = '\b'; ! 68: break; ! 69: ! 70: case 'f': ! 71: c = '\f'; ! 72: break; ! 73: ! 74: case 'v': ! 75: c = '\v'; ! 76: break; ! 77: ! 78: case ' ': ! 79: /* c = ' '; */ ! 80: break; ! 81: ! 82: default: ! 83: while (c >= '0' && c <= '7' && i < 3) { ! 84: n = (n << 3) + c - '0'; ! 85: i++; ! 86: c = getc (file); ! 87: } ! 88: ungetc (c, file); ! 89: c = n; ! 90: break; ! 91: } ! 92: } ! 93: ! 94: /* ensure there's room in the buffer */ ! 95: if (len >= size) ! 96: r = ralloc (r, size += CHUNK); ! 97: ! 98: /* put the character in the buffer */ ! 99: r[len++] = c; ! 100: ! 101: /* read the next character */ ! 102: c = getc (file); ! 103: } ! 104: ! 105: /* unless we hit eof, we read one character too far. */ ! 106: if (c != EOF) ! 107: ungetc (c, file); ! 108: ! 109: /* put a final null into the buffer */ ! 110: if (len >= size) ! 111: r = ralloc (r, size += CHUNK); ! 112: r[len] = '\0'; ! 113: ! 114: return r; ! 115: } ! 116: ! 117: void ! 118: putpath (FILE *file, char *path) ! 119: { ! 120: register char *p = path; ! 121: register int c; ! 122: ! 123: while ((c = *p++) != NULL) { ! 124: switch (c) { ! 125: ! 126: case '\n': ! 127: fprintf (file, "\\n"); ! 128: break; ! 129: ! 130: case '\r': ! 131: fprintf (file, "\\r"); ! 132: break; ! 133: ! 134: case '\b': ! 135: fprintf (file, "\\b"); ! 136: break; ! 137: ! 138: case '\t': ! 139: fprintf (file, "\\t"); ! 140: break; ! 141: ! 142: case '\f': ! 143: fprintf (file, "\\f"); ! 144: break; ! 145: ! 146: case '\v': ! 147: fprintf (file, "\\v"); ! 148: break; ! 149: ! 150: case '\\': ! 151: fprintf (file, "\\\\"); ! 152: break; ! 153: ! 154: case ' ': ! 155: fprintf (file, "\\ "); ! 156: break; ! 157: ! 158: default: ! 159: if (iscntrl (c)) ! 160: fprintf (file, ! 161: *p >= '0' && *p <= '7'? "\\%.3o": "\\%o", ! 162: c); ! 163: else ! 164: putc (c, file); ! 165: break; ! 166: } ! 167: } ! 168: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.