add missing include
[indent.git] / indent.c
CommitLineData
b811a28a
LM
1/* depend: */
2/* cflags: */
3/* linker: debug.o */
4
5#include <assert.h>
795a1c1c 6#include <errno.h>
b811a28a
LM
7#include <getopt.h>
8#include <malloc.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "debug.h"
14
15/* macros */
16
17#define CEIL(x, y) (((x) + (y) - 1) / (y))
18#define MIN(x, y) (((x) < (y)) ? (x) : (y))
19#define MAX(x, y) (((x) > (y)) ? (x) : (y))
20
21//#define BUFFERSIZE 4096
22#define BUFFERSIZE 256
b51fe422 23#define TABSIZE 2
222cc715
LM
24
25/* type definition */
26
27typedef enum {
28 e_unknown = 0,
29 e_ansi,
30 e_kr
31} cmode_t;
b811a28a
LM
32
33/* gobal variables */
34
35char *progname = NULL;
36
37/* help function */
38
39void usage (int ret)
40{
41 FILE *fd = ret ? stderr : stdout;
42 fprintf (fd, "usage: %s [-i file] [-h] [-m k&r|ansi|c99] [-o file] [-v]\n", progname);
43 fprintf (fd, " -i : input file\n");
44 fprintf (fd, " -h : help message\n");
45 fprintf (fd, " -m : indent mode\n");
46 fprintf (fd, " -o : output file\n");
47 fprintf (fd, " -v : verbose level (%d)\n", verbose);
48
49 exit (ret);
50}
51
52/* indent function */
53
222cc715
LM
54int indent (FILE *fin, FILE *fout, cmode_t cmode) {
55 char bufin[BUFFERSIZE + 1] = {0};
56 char bufout[BUFFERSIZE * TABSIZE + 1] = {0};
57 size_t i, nb;
b51fe422
LM
58 size_t nbindent = 0;
59 int begin = 1;
60 int parent = 0;
61 int comment = 0;
62 int newline = 0;
63 int string = 0;
64 int character = 0;
65 int special = 0;
43be90d1 66 int space = 0;
b811a28a 67
b811a28a 68 while (!feof (fin)) {
b51fe422
LM
69 memset (bufin, 0, sizeof (bufin));
70 memset (bufout, 0, sizeof (bufout));
222cc715
LM
71
72 /* read file */
73 nb = fread (bufin, 1, BUFFERSIZE, fin);
943fa96e 74 VERBOSE (DEBUG, fprintf (stdout, "buffer in: %d\n", nb));
222cc715 75 if (errno != 0) {
943fa96e 76 VERBOSE (ERROR, fprintf (stderr, "can't read file (%d)\n", errno));
222cc715
LM
77 exit (1);
78 }
79
80 /* process line */
81 char *ptin = bufin;
82 char *ptout = bufout;
83 while (*ptin != '\0') {
b51fe422
LM
84 VERBOSE (DEBUG, fprintf (stdout, "caracter: %c\n", *ptin));
85
86 /* manage comment */
87 if (comment > 0) {
88 if (((comment == 1) && (*ptin == '\n')) ||
89 ((comment == 2) && ((*ptin == '*') && (ptin[1] == '/')))) {
90 comment = 0;
91 }
92 special = 0;
93 *ptout++ = *ptin++;
94 continue;
95 }
96
97 /* manage indent */
222cc715 98 switch (*ptin) {
b51fe422
LM
99 case '/':
100 comment = (ptin[1] == '/') ? 1 : (ptin[1] == '*') ? 2 : 0;
101 if (begin) {
102 for (i = 0; i < nbindent * TABSIZE; i++) {
103 *ptout++ = ' ';
104 }
105 begin = 0;
106 }
107 *ptout++ = *ptin;
108 break;
109 case ' ':
222cc715 110 case '\t':
b51fe422 111 if (begin == 0) {
43be90d1
LM
112 if ((string) || (!space)) {
113 *ptout++ = *ptin;
114 }
222cc715
LM
115 }
116 break;
117 case '{':
b51fe422
LM
118 *ptout++ = '\n';
119 for (i = 0; i < nbindent * TABSIZE; i++) {
120 *ptout++ = ' ';
121 }
122 *ptout++ = *ptin;
123 *ptout++ = '\n';
124 nbindent++;
125 newline = 1;
126 begin = 1;
127 break;
222cc715 128 case '}':
b51fe422
LM
129 *ptout++ = '\n';
130 nbindent--;
131 for (i = 0; i < nbindent * TABSIZE; i++) {
132 *ptout++ = ' ';
133 }
134 *ptout++ = *ptin;
135 if (ptin[1] != ';') {
136 *ptout++ = '\n';
137 }
138 newline = 1;
139 begin = 1;
140 break;
222cc715
LM
141 case ';':
142 *ptout++ = *ptin;
b51fe422
LM
143 if (parent) {
144 break;
145 }
222cc715 146 *ptout++ = '\n';
b51fe422
LM
147 newline = 1;
148 begin = 1;
149 break;
150 case '\n':
151 if (newline == 1) {
152 newline = 0;
153 } else {
154 *ptout++ = '\n';
155 }
156 begin = 1;
157 break;
158 case '\r':
222cc715
LM
159 break;
160 default:
b51fe422
LM
161 if ((*ptin == '"') && (!character) && (!special)) {
162 string ^= 1;
163 }
164 if ((*ptin == '\'') && (!string) && (!special)) {
165 character ^= 1;
166 }
167 if (begin) {
168 for (i = 0; i < nbindent * TABSIZE; i++) {
169 *ptout++ = ' ';
170 }
171 begin = 0;
172 }
222cc715 173 *ptout++ = *ptin;
b811a28a 174 }
43be90d1 175 space = ((*ptin == ' ') || (*ptin == '\t'));
b51fe422
LM
176 special = (*ptin == '\\');
177 parent += (*ptin == '(') ? +1 : (*ptin == ')') ? -1 : 0;
222cc715 178 ptin++;
b811a28a 179 }
222cc715
LM
180 ptout = '\0';
181
182 /* write file */
943fa96e 183 VERBOSE (DEBUG, fprintf (stdout, "buffer out: %d\n", strlen (bufout)));
222cc715 184 ptout = bufout;
b51fe422
LM
185 while ((nb = fwrite (ptout, 1, strlen (ptout), fout)) != strlen (ptout)) {
186 VERBOSE (DEBUG, fprintf (stdout, "buffer out: %d/%d\n", nb, strlen (ptout)));
222cc715 187 if (errno != 0) {
943fa96e 188 VERBOSE (ERROR, fprintf (stderr, "can't write file (%d)\n", errno));
222cc715 189 exit (1);
b811a28a 190 }
222cc715
LM
191 ptout += nb;
192 }
b811a28a
LM
193 }
194
195 /* close all */
196 fclose (fin);
197 fclose (fout);
198
199 return 0;
200}
201
202/* main function */
203
204int main (int argc, char *argv[])
205{
222cc715 206 cmode_t cmode = e_unknown;
b811a28a
LM
207 char *input = NULL;
208 char *mode = "ansi";
209 char *output = NULL;
210
211 /* get basename */
212 char *pt = progname = argv[0];
213 while (*pt) {
214 if ((*pt == '/') || (*pt == '\\')) {
215 progname = pt + 1;
216 }
217 pt++;
218 }
219
220 int c;
221 while ((c = getopt(argc, argv, "i:hm:o:v:")) != EOF) {
222 switch (c) {
223 case 'i':
224 input = optarg;
225 break;
226 case 'm':
227 mode = optarg;
228 break;
229 case 'o':
230 output = optarg;
231 break;
232 case 'v':
233 verbose = atoi (optarg);
234 break;
235 case 'h':
236 default:
237 usage (c != 'h');
238 }
239 }
240 if (argc - optind != 0) {
241 fprintf (stderr, "%s: invalid option -- %s\n", progname, argv[optind]);
242 usage (1);
243 }
244
245 /* check input */
246 FILE *fin = NULL;
247 if (input) {
248 fin = fopen (input, "rb");
249 if (!fin) {
250 VERBOSE (ERROR, fprintf (stderr, "error: can't open file '%s'\n", input));
251 }
252 } else {
253 fin = stdin;
254 }
255
256 /* check output */
257 FILE *fout = NULL;
258 if (output) {
b51fe422 259 fout = fopen (output, "wb");
b811a28a
LM
260 if (!fout) {
261 VERBOSE (ERROR, fprintf (stderr, "error: can't open file '%s'\n", output));
262 fclose (fin);
263 }
264 } else {
265 fout = stdout;
266 }
267
222cc715
LM
268 /* check mode */
269 if (strcmp (mode, "ansi") == 0) {
270 cmode = e_ansi;
271 } else if (strcmp (mode, "k&r") == 0) {
272 cmode = e_kr;
273 } else {
274 VERBOSE (ERROR, fprintf (stderr, "error: mode '%s' unknown\n", mode));
275 }
276
277 return indent (fin, fout, cmode);
b811a28a
LM
278}
279
280// test: indent.exe -h
281// test: indent.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
282// test: indent.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }'
283// test: indent.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
284
285/* vim: set ts=4 sw=4 et: */