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