|
|
1.1 root 1: /*
2: * char * getline(ifp, lineno) FILE *ifp; int *lineno;
3: *
4: * Function to get lines from an input file.
5: * Returns the address of the line, or NULL for eof.
6: *
7: * lineno should usually be started at 1. lineno will
8: * be incremented by the number of lines in the previous call.
9: * Thus lineno will be the number of the line just gotten.
10: *
11: * # to end of line is ignored.
12: * \ whitespace through end of line is ignored.
13: * \n newline
14: * \p #
15: * \b backspace
16: * \r carrage return
17: * \f form feed
18: * \t tab
19: * \\ backslash
20: * \ddd octal number
21: * all other \ sequences are errors.
22: */
23: #include <misc.h>
24:
25: static char outSpace[] = "Out of space";
26: static char *line = NULL;
27: static int i;
28: static int size = 0;
29: static int oldline = 0;
30:
31: static void
32: addchr(c)
33: {
34: extern char *realloc();
35:
36: while (i >= size)
37: if (NULL == (line = realloc(line, size += 80)))
38: fatal("Out of space");
39: line[i++] = c;
40: }
41:
42: char *
43: getline(ifp, lineno)
44: FILE *ifp;
45: int *lineno;
46: {
47: int c, octacc, octcnt;
48: enum state { normal, incont, incomm, bsl, octdig } state;
49:
50: *lineno += oldline;
51: for (state = normal, oldline = i = 0;;) {
52: if (EOF == (c = fgetc(ifp))) {
53: if (i)
54: fprintf(stderr,
55: "line %d truncated at end\n",
56: *lineno + oldline);
57: return (NULL);
58: }
59:
60: switch (state) {
61: case normal:
62: switch (c) {
63: case '\\':
64: state = bsl;
65: continue;
66:
67: case '#':
68: state = incomm;
69: continue;
70:
71: case '\n':
72: oldline++;
73: addchr(0);
74: return (line);
75: }
76:
77: addchr(c);
78: continue;
79:
80: case incont:
81: if ('\n' == c) {
82: oldline++;
83: state = normal;
84: }
85: continue;
86:
87: case incomm:
88: if ('\n' == c) {
89: state = normal;
90: oldline++;
91: addchr(0);
92: return (line);
93: }
94: continue;
95:
96: case bsl:
97: switch (c) {
98: case 'b':
99: c = '\b';
100:
101: case '\\':
102: break;
103:
104: case 'p':
105: c = '#';
106: break;
107:
108: case 'f':
109: c = '\f';
110: break;
111:
112: case 'a':
113: c = '\a';
114: break;
115:
116: case 'r':
117: c = '\r';
118: break;
119:
120: case 't':
121: c = '\t';
122: break;
123:
124: case 'n':
125: c = '\n';
126: break;
127:
128: case ' ':
129: case '\t':
130: state = incont;
131: continue;
132:
133: case '\n':
134: oldline++;
135: state = normal;
136: continue;
137:
138: default:
139: if (('0' <= c) && ('7' >= c)) {
140: state = octdig;
141: octcnt = 1;
142: octacc = c - '0';
143: continue;
144: }
145: fprintf(stderr,
146: "%d: '%c' 0x%2x after \\\n",
147: *lineno + oldline, c, c);
148: }
149: state = normal;
150: addchr(c);
151: continue;
152:
153: case octdig:
154: if (('0' <= c) && ('7' >= c)) {
155: octacc *= 8;
156: octacc += c - '0';
157: if (3 == ++octcnt) {
158: state = normal;
159: addchr(octacc);
160: }
161: }
162: else {
163: ungetc(c, ifp);
164: state = normal;
165: addchr(octacc);
166: }
167: continue;
168: }
169: }
170:
171: }
172:
173: #ifdef TEST
174: main()
175: {
176: int line = 1;
177: char *got;
178:
179: for (;;) {
180: if (NULL == (got = getline(stdin, &line)))
181: exit(0);
182: printf("%d: %s\n", line, got);
183: }
184: }
185: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.