]> git.saurik.com Git - apple/xnu.git/blob - SETUP/decomment/decomment.c
xnu-4570.71.2.tar.gz
[apple/xnu.git] / SETUP / decomment / decomment.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * decomment.c
26 *
27 * Removes all comments and (optionally) whitespace from an input file.
28 * Writes result on stdout.
29 */
30
31 #include <stdio.h>
32 #include <ctype.h> /* for isspace */
33 #include <libc.h>
34
35 /*
36 * State of input scanner.
37 */
38 typedef enum {
39 IS_NORMAL,
40 IS_SLASH, // encountered opening '/'
41 IS_IN_COMMENT, // within / * * / comment
42 IS_STAR, // encountered closing '*'
43 IS_IN_END_COMMENT // within / / comment
44 } input_state_t;
45
46 static void usage(char **argv);
47
48 int main(int argc, char **argv)
49 {
50 FILE *fp;
51 char bufchar;
52 input_state_t input_state = IS_NORMAL;
53 int exit_code = 0;
54 int remove_whitespace = 0;
55 int arg;
56
57 if(argc < 2)
58 usage(argv);
59 for(arg=2; arg<argc; arg++) {
60 switch(argv[arg][0]) {
61 case 'r':
62 remove_whitespace++;
63 break;
64 default:
65 usage(argv);
66 }
67 }
68
69 fp = fopen(argv[1], "r");
70 if(!fp) {
71 fprintf(stderr, "Error opening %s\n", argv[1]);
72 perror("fopen");
73 exit(1);
74 }
75 for(;;) {
76 bufchar = getc_unlocked(fp);
77 if (bufchar == EOF)
78 break;
79
80 switch(input_state) {
81
82 case IS_NORMAL:
83 if(bufchar == '/') {
84 /*
85 * Might be start of a comment.
86 */
87 input_state = IS_SLASH;
88 }
89 else {
90 if(!(remove_whitespace && isspace(bufchar))) {
91 putchar_unlocked(bufchar);
92 }
93 }
94 break;
95
96 case IS_SLASH:
97 switch(bufchar) {
98 case '*':
99 /*
100 * Start of normal comment.
101 */
102 input_state = IS_IN_COMMENT;
103 break;
104
105 case '/':
106 /*
107 * Start of 'to-end-of-line' comment.
108 */
109 input_state = IS_IN_END_COMMENT;
110 break;
111
112 default:
113 /*
114 * Not the start of comment. Emit the '/'
115 * we skipped last char in case we were
116 * entering a comment this time, then the
117 * current char.
118 */
119 putchar_unlocked('/');
120 if(!(remove_whitespace && isspace(bufchar))) {
121 putchar_unlocked(bufchar);
122 }
123 input_state = IS_NORMAL;
124 break;
125 }
126 break;
127
128 case IS_IN_COMMENT:
129 if(bufchar == '*') {
130 /*
131 * Maybe ending comment...
132 */
133 input_state = IS_STAR;
134 }
135 break;
136
137
138 case IS_STAR:
139 switch(bufchar) {
140 case '/':
141 /*
142 * End of normal comment.
143 */
144 input_state = IS_NORMAL;
145 break;
146
147 case '*':
148 /*
149 * Still could be one char away from end
150 * of comment.
151 */
152 break;
153
154 default:
155 /*
156 * Still inside comment, no end in sight.
157 */
158 input_state = IS_IN_COMMENT;
159 break;
160 }
161 break;
162
163 case IS_IN_END_COMMENT:
164 if(bufchar == '\n') {
165 /*
166 * End of comment. Emit the newline if
167 * appropriate.
168 */
169 if(!remove_whitespace) {
170 putchar_unlocked(bufchar);
171 }
172 input_state = IS_NORMAL;
173 }
174 break;
175
176 } /* switch input_state */
177 } /* main read loop */
178
179 /*
180 * Done.
181 */
182 return(exit_code);
183 }
184
185 static void usage(char **argv)
186 {
187 printf("usage: %s infile [r(emove whitespace)]\n", argv[0]);
188 exit(1);
189 }