|
|
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.