Version:
~ [ 1.0 ] ~
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "platform.h"
6
7 #define true 1
8 #define false 0
9 #define TABSIZE 4
10
11 #define DOS_CRLF 0
12 #define UNIX_LF 1
13 #define MAC_CR 2
14
15 typedef struct
16 {
17 Bool pushed;
18 int tabs;
19 int curcol;
20 int lastcol;
21 int maxcol;
22 int curline;
23 int pushed_char;
24 uint size;
25 uint length;
26 char *buf;
27 FILE *fp;
28 } Stream;
29
30 static int tabsize = TABSIZE;
31 static int endline = DOS_CRLF;
32 static Bool tabs = false;
33
34 /*
35 Memory allocation functions vary from one environment to
36 the next, and experience shows that wrapping the local
37 mechanisms up provides for greater flexibility and allows
38 out of memory conditions to be detected in one place.
39 */
40 void *MemAlloc(size_t size)
41 {
42 void *p;
43
44 p = malloc(size);
45
46 if (!p)
47 {
48 fprintf(stderr, "***** Out of memory! *****\n");
49 exit(1);
50 }
51
52 return p;
53 }
54
55 void *MemRealloc(void *old, size_t size)
56 {
57 void *p;
58
59 p = realloc(old, size);
60
61 if (!p)
62 {
63 fprintf(stderr, "***** Out of memory! *****\n");
64 return NULL;
65 }
66
67 return p;
68 }
69
70 void MemFree(void *p)
71 {
72 free(p);
73 p = NULL;
74 }
75
76 static Stream *NewStream(FILE *fp)
77 {
78 Stream *in;
79
80 in = (Stream *)MemAlloc(sizeof(Stream));
81
82 memset(in, 0, sizeof(Stream));
83 in->fp = fp;
84 return in;
85 }
86
87 static void FreeStream(Stream *in)
88 {
89 if (in->buf)
90 MemFree(in->buf);
91
92 MemFree(in);
93 }
94
95 static void AddByte(Stream *in, uint c)
96 {
97 if (in->size + 1 >= in->length)
98 {
99 while (in->size + 1 >= in->length)
100 {
101 if (in->length == 0)
102 in->length = 8192;
103 else
104 in->length = in->length * 2;
105 }
106
107 in->buf = (char *)MemRealloc(in->buf, in->length*sizeof(char));
108 }
109
110 in->buf[in->size++] = (char)c;
111 in->buf[in->size] = '\0'; /* debug */
112 }
113
114
115
116 /*
117 Read a character from a stream, keeping track
118 of lines, columns etc. This is used for parsing
119 markup and plain text etc. A single level
120 pushback is allowed with UngetChar(c, in).
121 Returns EndOfStream if there's nothing more to read.
122 */
123 static int ReadChar(Stream *in)
124 {
125 int c;
126
127 if (in->pushed)
128 {
129 in->pushed = false;
130
131 if (in->pushed_char == '\n')
132 in->curline--;
133
134 return in->pushed_char;
135 }
136
137 in->lastcol = in->curcol;
138
139 /* expanding tab ? */
140 if (in->tabs > 0)
141 {
142 in->curcol++;
143 in->tabs--;
144 return ' ';
145 }
146
147 /* Else go on with normal buffer: */
148 for (;;)
149 {
150 c = getc(in->fp);
151
152 /* end of file? */
153 if (c == EOF)
154 break;
155
156 /* coerce \r\n and isolated \r as equivalent to \n : */
157 if (c == '\r')
158 {
159 c = getc(in->fp);
160
161 if (c != '\n')
162 ungetc(c, in->fp);
163
164 c = '\n';
165 }
166
167 if (c == '\n')
168 {
169 if (in->maxcol < in->curcol)
170 in->maxcol = in->curcol;
171
172 in->curcol = 1;
173 in->curline++;
174 break;
175 }
176
177 if (c == '\t')
178 {
179 if (tabs)
180 in->curcol += tabsize - ((in->curcol - 1) % tabsize);
181 else /* expand to spaces */
182 {
183 in->tabs = tabsize - ((in->curcol - 1) % tabsize) - 1;
184 in->curcol++;
185 c = ' ';
186 }
187
188 break;
189 }
190
191 if (c == '\033')
192 break;
193
194 /* strip control characters including '\r' */
195
196 if (0 < c && c < 32)
197 continue;
198
199 in->curcol++;
200 break;
201 }
202
203 return c;
204 }
205
206 static Stream *ReadFile(FILE *fin)
207 {
208 int c;
209 Stream *in = NewStream(fin);
210
211 while ((c = ReadChar(in)) >= 0)
212 AddByte(in, (uint)c);
213
214 return in;
215 }
216
217 static void WriteFile(Stream *in, FILE *fout)
218 {
219 int i, c;
220 char *p;
221
222 i = in->size;
223 p = in->buf;
224
225 while (i--)
226 {
227 c = *p++;
228
229 if (c == '\n')
230 {
231 if (endline == DOS_CRLF)
232 {
233 putc('\r', fout);
234 putc('\n', fout);
235 }
236 else if (endline == UNIX_LF)
237 putc('\n', fout);
238 else if (endline == MAC_CR)
239 putc('\r', fout);
240
241 continue;
242 }
243
244 putc(c, fout);
245 }
246 }
247
248 static void HelpText(FILE *errout, char *prog)
249 {
250 fprintf(errout, "%s: [options] [infile [outfile]] ...\n", prog);
251 fprintf(errout, "Utility to expand tabs and ensure consistent line endings\n");
252 fprintf(errout, "options for tab2space vers: 6th February 2003\n");
253 fprintf(errout, " -help or -h display this help message\n");
254 fprintf(errout, " -dos or -crlf set line ends to CRLF (PC-DOS/Windows - default)\n");
255 fprintf(errout, " -mac or -cr set line ends to CR (classic Mac OS)\n");
256 fprintf(errout, " -unix or -lf set line ends to LF (Unix)\n");
257 fprintf(errout, " -tabs preserve tabs, e.g. for Makefile\n");
258 fprintf(errout, " -t<n> set tabs to <n> (default is 4) spaces\n");
259 fprintf(errout, "\nNote this utility doesn't map spaces to tabs!\n");
260 }
261
262 int main(int argc, char **argv)
263 {
264 char const *infile, *outfile;
265 char *prog;
266 FILE *fin, *fout;
267 Stream *in = NULL;
268
269 prog = argv[0];
270
271 while (argc > 0)
272 {
273 if (argc > 1 && argv[1][0] == '-')
274 {
275 if (strcmp(argv[1], "-help") == 0 || argv[1][1] == 'h')
276 {
277 HelpText(stdout, prog);
278 return 1;
279 }
280
281 if (strcmp(argv[1], "-dos") == 0 ||
282 strcmp(argv[1], "-crlf") == 0)
283 endline = DOS_CRLF;
284
285 else if (strcmp(argv[1], "-mac") == 0 ||
286 strcmp(argv[1], "-cr") == 0)
287 endline = MAC_CR;
288
289 else if (strcmp(argv[1], "-unix") == 0 ||
290 strcmp(argv[1], "-lf") == 0)
291 endline = UNIX_LF;
292
293 else if (strcmp(argv[1], "-tabs") == 0)
294 tabs = true;
295
296 else if (strncmp(argv[1], "-t", 2) == 0)
297 sscanf(argv[1]+2, "%d", &tabsize);
298
299 --argc;
300 ++argv;
301 continue;
302 }
303
304 if (argc > 1)
305 {
306 infile = argv[1];
307 fin = fopen(infile, "rb");
308 }
309 else
310 {
311 infile = "stdin";
312 fin = stdin;
313 }
314
315 if (argc > 2)
316 {
317 outfile = argv[2];
318 fout = NULL;
319 --argc;
320 ++argv;
321 }
322 else
323 {
324 outfile = "stdout";
325 fout = stdout;
326 }
327
328 if (fin)
329 {
330 in = ReadFile(fin);
331
332 if (fin != stdin)
333 fclose(fin);
334
335 if (fout != stdout)
336 fout = fopen(outfile, "wb");
337
338 if (fout)
339 {
340 WriteFile(in, fout);
341
342 if (fout != stdout)
343 fclose(fout);
344 }
345 else
346 fprintf(stderr, "%s - can't open \"%s\" for writing\n", prog, outfile);
347
348 FreeStream(in);
349 }
350 else
351 fprintf(stderr, "%s - can't open \"%s\" for reading\n", prog, infile);
352
353 --argc;
354 ++argv;
355
356 if (argc <= 1)
357 break;
358 }
359
360 return 0;
361 }
362
363
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.