]>
Commit | Line | Data |
---|---|---|
316670eb A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
0a7de745 | 5 | * |
316670eb A |
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. | |
0a7de745 | 13 | * |
316670eb A |
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." | |
0a7de745 | 21 | * |
316670eb A |
22 | * @APPLE_LICENSE_HEADER_END@ |
23 | */ | |
24 | /* | |
25 | * decomment.c | |
26 | * | |
0a7de745 | 27 | * Removes all comments and (optionally) whitespace from an input file. |
316670eb A |
28 | * Writes result on stdout. |
29 | */ | |
0a7de745 | 30 | |
316670eb | 31 | #include <stdio.h> |
0a7de745 | 32 | #include <ctype.h> /* for isspace */ |
316670eb A |
33 | #include <libc.h> |
34 | ||
35 | /* | |
36 | * State of input scanner. | |
37 | */ | |
38 | typedef enum { | |
39 | IS_NORMAL, | |
0a7de745 A |
40 | IS_SLASH, // encountered opening '/' |
41 | IS_IN_COMMENT, // within / * * / comment | |
42 | IS_STAR, // encountered closing '*' | |
43 | IS_IN_END_COMMENT // within / / comment | |
316670eb A |
44 | } input_state_t; |
45 | ||
46 | static void usage(char **argv); | |
47 | ||
0a7de745 A |
48 | int |
49 | main(int argc, char **argv) | |
316670eb A |
50 | { |
51 | FILE *fp; | |
52 | char bufchar; | |
53 | input_state_t input_state = IS_NORMAL; | |
54 | int exit_code = 0; | |
55 | int remove_whitespace = 0; | |
56 | int arg; | |
0a7de745 A |
57 | |
58 | if (argc < 2) { | |
316670eb | 59 | usage(argv); |
0a7de745 A |
60 | } |
61 | for (arg = 2; arg < argc; arg++) { | |
62 | switch (argv[arg][0]) { | |
63 | case 'r': | |
64 | remove_whitespace++; | |
316670eb | 65 | break; |
0a7de745 A |
66 | default: |
67 | usage(argv); | |
316670eb | 68 | } |
0a7de745 A |
69 | } |
70 | ||
316670eb | 71 | fp = fopen(argv[1], "r"); |
0a7de745 | 72 | if (!fp) { |
316670eb A |
73 | fprintf(stderr, "Error opening %s\n", argv[1]); |
74 | perror("fopen"); | |
75 | exit(1); | |
76 | } | |
0a7de745 | 77 | for (;;) { |
316670eb | 78 | bufchar = getc_unlocked(fp); |
0a7de745 | 79 | if (bufchar == EOF) { |
316670eb | 80 | break; |
0a7de745 | 81 | } |
316670eb | 82 | |
0a7de745 A |
83 | switch (input_state) { |
84 | case IS_NORMAL: | |
85 | if (bufchar == '/') { | |
86 | /* | |
316670eb A |
87 | * Might be start of a comment. |
88 | */ | |
89 | input_state = IS_SLASH; | |
0a7de745 A |
90 | } else { |
91 | if (!(remove_whitespace && isspace(bufchar))) { | |
316670eb A |
92 | putchar_unlocked(bufchar); |
93 | } | |
94 | } | |
95 | break; | |
0a7de745 A |
96 | |
97 | case IS_SLASH: | |
98 | switch (bufchar) { | |
99 | case '*': | |
100 | /* | |
316670eb A |
101 | * Start of normal comment. |
102 | */ | |
103 | input_state = IS_IN_COMMENT; | |
104 | break; | |
0a7de745 A |
105 | |
106 | case '/': | |
107 | /* | |
316670eb A |
108 | * Start of 'to-end-of-line' comment. |
109 | */ | |
110 | input_state = IS_IN_END_COMMENT; | |
111 | break; | |
0a7de745 A |
112 | |
113 | default: | |
114 | /* | |
316670eb A |
115 | * Not the start of comment. Emit the '/' |
116 | * we skipped last char in case we were | |
117 | * entering a comment this time, then the | |
118 | * current char. | |
119 | */ | |
120 | putchar_unlocked('/'); | |
0a7de745 | 121 | if (!(remove_whitespace && isspace(bufchar))) { |
316670eb A |
122 | putchar_unlocked(bufchar); |
123 | } | |
124 | input_state = IS_NORMAL; | |
125 | break; | |
126 | } | |
127 | break; | |
0a7de745 A |
128 | |
129 | case IS_IN_COMMENT: | |
130 | if (bufchar == '*') { | |
131 | /* | |
316670eb A |
132 | * Maybe ending comment... |
133 | */ | |
0a7de745 | 134 | input_state = IS_STAR; |
316670eb | 135 | } |
0a7de745 A |
136 | break; |
137 | ||
138 | ||
139 | case IS_STAR: | |
140 | switch (bufchar) { | |
141 | case '/': | |
316670eb A |
142 | /* |
143 | * End of normal comment. | |
144 | */ | |
145 | input_state = IS_NORMAL; | |
146 | break; | |
0a7de745 A |
147 | |
148 | case '*': | |
149 | /* | |
316670eb A |
150 | * Still could be one char away from end |
151 | * of comment. | |
152 | */ | |
153 | break; | |
0a7de745 A |
154 | |
155 | default: | |
156 | /* | |
316670eb A |
157 | * Still inside comment, no end in sight. |
158 | */ | |
159 | input_state = IS_IN_COMMENT; | |
160 | break; | |
161 | } | |
162 | break; | |
0a7de745 A |
163 | |
164 | case IS_IN_END_COMMENT: | |
165 | if (bufchar == '\n') { | |
316670eb | 166 | /* |
0a7de745 | 167 | * End of comment. Emit the newline if |
316670eb A |
168 | * appropriate. |
169 | */ | |
0a7de745 | 170 | if (!remove_whitespace) { |
316670eb A |
171 | putchar_unlocked(bufchar); |
172 | } | |
173 | input_state = IS_NORMAL; | |
174 | } | |
175 | break; | |
316670eb | 176 | } /* switch input_state */ |
0a7de745 A |
177 | } /* main read loop */ |
178 | ||
316670eb A |
179 | /* |
180 | * Done. | |
181 | */ | |
0a7de745 | 182 | return exit_code; |
316670eb A |
183 | } |
184 | ||
0a7de745 A |
185 | static void |
186 | usage(char **argv) | |
316670eb A |
187 | { |
188 | printf("usage: %s infile [r(emove whitespace)]\n", argv[0]); | |
189 | exit(1); | |
190 | } |