jsmin.c
Go to the documentation of this file.
00001 /* jsmin.c
00002    2006-05-04
00003 
00004 Copyright (c) 2002 Douglas Crockford  (www.crockford.com)
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a copy of
00007 this software and associated documentation files (the "Software"), to deal in
00008 the Software without restriction, including without limitation the rights to
00009 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
00010 of the Software, and to permit persons to whom the Software is furnished to do
00011 so, subject to the following conditions:
00012 
00013 The above copyright notice and this permission notice shall be included in all
00014 copies or substantial portions of the Software.
00015 
00016 The Software shall be used for Good, not Evil.
00017 
00018 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00019 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00021 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00022 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00023 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00024 SOFTWARE.
00025 */
00026 
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 
00030 static int   theA;
00031 static int   theB;
00032 static int   theLookahead = EOF;
00033 
00034 
00035 /* isAlphanum -- return true if the character is a letter, digit, underscore,
00036         dollar sign, or non-ASCII character.
00037 */
00038 
00039 static int
00040 isAlphanum(int c)
00041 {
00042     return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
00043         (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' ||
00044         c > 126);
00045 }
00046 
00047 
00048 /* get -- return the next character from stdin. Watch out for lookahead. If
00049         the character is a control character, translate it to a space or
00050         linefeed.
00051 */
00052 
00053 static int
00054 get()
00055 {
00056     int c = theLookahead;
00057     theLookahead = EOF;
00058     if (c == EOF) {
00059         c = getc(stdin);
00060     }
00061     if (c >= ' ' || c == '\n' || c == EOF) {
00062         return c;
00063     }
00064     if (c == '\r') {
00065         return '\n';
00066     }
00067     return ' ';
00068 }
00069 
00070 
00071 /* peek -- get the next character without getting it.
00072 */
00073 
00074 static int
00075 peek()
00076 {
00077     theLookahead = get();
00078     return theLookahead;
00079 }
00080 
00081 
00082 /* next -- get the next character, excluding comments. peek() is used to see
00083         if a '/' is followed by a '/' or '*'.
00084 */
00085 
00086 static int
00087 next()
00088 {
00089     int c = get();
00090     if  (c == '/') {
00091         switch (peek()) {
00092         case '/':
00093             for (;;) {
00094                 c = get();
00095                 if (c <= '\n') {
00096                     return c;
00097                 }
00098             }
00099         case '*':
00100             get();
00101             for (;;) {
00102                 switch (get()) {
00103                 case '*':
00104                     if (peek() == '/') {
00105                         get();
00106                         return ' ';
00107                     }
00108                     break;
00109                 case EOF:
00110                     fprintf(stderr, "Error: JSMIN Unterminated comment.\n");
00111                     exit(1);
00112                 }
00113             }
00114         default:
00115             return c;
00116         }
00117     }
00118     return c;
00119 }
00120 
00121 
00122 /* action -- do something! What you do is determined by the argument:
00123         1   Output A. Copy B to A. Get the next B.
00124         2   Copy B to A. Get the next B. (Delete A).
00125         3   Get the next B. (Delete B).
00126    action treats a string as a single character. Wow!
00127    action recognizes a regular expression if it is preceded by ( or , or =.
00128 */
00129 
00130 static void
00131 action(int d)
00132 {
00133     switch (d) {
00134     case 1:
00135         putc(theA, stdout);
00136     case 2:
00137         theA = theB;
00138         if (theA == '\'' || theA == '"') {
00139             for (;;) {
00140                 putc(theA, stdout);
00141                 theA = get();
00142                 if (theA == theB) {
00143                     break;
00144                 }
00145                 if (theA <= '\n') {
00146                     fprintf(stderr,
00147 "Error: JSMIN unterminated string literal: %c\n", theA);
00148                     exit(1);
00149                 }
00150                 if (theA == '\\') {
00151                     putc(theA, stdout);
00152                     theA = get();
00153                 }
00154             }
00155         }
00156     case 3:
00157         theB = next();
00158         if (theB == '/' && (theA == '(' || theA == ',' || theA == '=' ||
00159                 theA == ':' || theA == '[' || theA == '!' || theA == '&' || 
00160                 theA == '|')) {
00161             putc(theA, stdout);
00162             putc(theB, stdout);
00163             for (;;) {
00164                 theA = get();
00165                 if (theA == '/') {
00166                     break;
00167                 } else if (theA =='\\') {
00168                     putc(theA, stdout);
00169                     theA = get();
00170                 } else if (theA <= '\n') {
00171                     fprintf(stderr,
00172 "Error: JSMIN unterminated Regular Expression literal.\n", theA);
00173                     exit(1);
00174                 }
00175                 putc(theA, stdout);
00176             }
00177             theB = next();
00178         }
00179     }
00180 }
00181 
00182 
00183 /* jsmin -- Copy the input to the output, deleting the characters which are
00184         insignificant to JavaScript. Comments will be removed. Tabs will be
00185         replaced with spaces. Carriage returns will be replaced with linefeeds.
00186         Most spaces and linefeeds will be removed.
00187 */
00188 
00189 static void
00190 jsmin()
00191 {
00192     theA = '\n';
00193     action(3);
00194     while (theA != EOF) {
00195         switch (theA) {
00196         case ' ':
00197             if (isAlphanum(theB)) {
00198                 action(1);
00199             } else {
00200                 action(2);
00201             }
00202             break;
00203         case '\n':
00204             switch (theB) {
00205             case '{':
00206             case '[':
00207             case '(':
00208             case '+':
00209             case '-':
00210                 action(1);
00211                 break;
00212             case ' ':
00213                 action(3);
00214                 break;
00215             default:
00216                 if (isAlphanum(theB)) {
00217                     action(1);
00218                 } else {
00219                     action(2);
00220                 }
00221             }
00222             break;
00223         default:
00224             switch (theB) {
00225             case ' ':
00226                 if (isAlphanum(theA)) {
00227                     action(1);
00228                     break;
00229                 }
00230                 action(3);
00231                 break;
00232             case '\n':
00233                 switch (theA) {
00234                 case '}':
00235                 case ']':
00236                 case ')':
00237                 case '+':
00238                 case '-':
00239                 case '"':
00240                 case '\'':
00241                     action(1);
00242                     break;
00243                 default:
00244                     if (isAlphanum(theA)) {
00245                         action(1);
00246                     } else {
00247                         action(3);
00248                     }
00249                 }
00250                 break;
00251             default:
00252                 action(1);
00253                 break;
00254             }
00255         }
00256     }
00257 }
00258 
00259 
00260 /* main -- Output any command line arguments as comments
00261         and then minify the input.
00262 */
00263 extern int
00264 main(int argc, char* argv[])
00265 {
00266     int i;
00267     for (i = 1; i < argc; i += 1) {
00268         fprintf(stdout, "// %s\n", argv[i]);
00269     }
00270     jsmin();
00271     return 0;
00272 }


websocket_gui
Author(s): Benoit Lescot and Stéphane Magnenat
autogenerated on Mon Oct 6 2014 08:54:48