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