|
|
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 <stdio.h> ! 27: #include <ctype.h> ! 28: #include "asd.h" ! 29: ! 30: #define CHUNK 64 ! 31: ! 32: static char *r; ! 33: static unsigned size; ! 34: ! 35: char * ! 36: getpath (file) ! 37: register FILE *file; ! 38: { ! 39: register int c; ! 40: register int len = 0; ! 41: ! 42: c = getc (file); ! 43: ! 44: while (!isspace(c) && c != EOF) { ! 45: register int i = 0, n = 0; ! 46: ! 47: /* determine the next input character */ ! 48: if (c == '\\') { ! 49: c = getc (file); ! 50: switch (c) { ! 51: ! 52: case '\\': ! 53: break; ! 54: ! 55: case 'n': ! 56: c = '\n'; ! 57: break; ! 58: ! 59: case 'r': ! 60: c = '\r'; ! 61: break; ! 62: ! 63: case 't': ! 64: c = '\t'; ! 65: break; ! 66: ! 67: case 'b': ! 68: c = '\b'; ! 69: break; ! 70: ! 71: case 'f': ! 72: c = '\f'; ! 73: break; ! 74: ! 75: case 'v': ! 76: c = '\v'; ! 77: break; ! 78: ! 79: case ' ': ! 80: /* c = ' '; */ ! 81: break; ! 82: ! 83: default: ! 84: while (c >= '0' && c <= '7' && i < 3) { ! 85: n = (n << 3) + c - '0'; ! 86: i++; ! 87: c = getc (file); ! 88: } ! 89: ungetc (c, file); ! 90: c = n; ! 91: break; ! 92: } ! 93: } ! 94: ! 95: /* ensure there's room in the buffer */ ! 96: if (len >= size) ! 97: r = ralloc (r, size += CHUNK); ! 98: ! 99: /* put the character in the buffer */ ! 100: r[len++] = c; ! 101: ! 102: /* read the next character */ ! 103: c = getc (file); ! 104: } ! 105: ! 106: /* unless we hit eof, we read one character too far. */ ! 107: if (c != EOF) ! 108: ungetc (c, file); ! 109: ! 110: /* put a final null into the buffer */ ! 111: if (len >= size) ! 112: r = ralloc (r, size += CHUNK); ! 113: r[len] = '\0'; ! 114: ! 115: return r; ! 116: } ! 117: ! 118: void ! 119: putpath (file, path) ! 120: register FILE *file; ! 121: char *path; ! 122: { ! 123: register char *p = path; ! 124: register int c; ! 125: ! 126: while ((c = *p++) != NULL) { ! 127: switch (c) { ! 128: ! 129: case '\n': ! 130: fprintf (file, "\\n"); ! 131: break; ! 132: ! 133: case '\r': ! 134: fprintf (file, "\\r"); ! 135: break; ! 136: ! 137: case '\b': ! 138: fprintf (file, "\\b"); ! 139: break; ! 140: ! 141: case '\t': ! 142: fprintf (file, "\\t"); ! 143: break; ! 144: ! 145: case '\f': ! 146: fprintf (file, "\\f"); ! 147: break; ! 148: ! 149: case '\v': ! 150: fprintf (file, "\\v"); ! 151: break; ! 152: ! 153: case '\\': ! 154: fprintf (file, "\\\\"); ! 155: break; ! 156: ! 157: case ' ': ! 158: fprintf (file, "\\ "); ! 159: break; ! 160: ! 161: default: ! 162: if (iscntrl (c)) ! 163: fprintf (file, ! 164: *p >= '0' && *p <= '7'? "\\%.3o": "\\%o", ! 165: c); ! 166: else ! 167: putc (c, file); ! 168: break; ! 169: } ! 170: } ! 171: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.