mirror of
				https://github.com/ElvishArtisan/rivendell.git
				synced 2025-11-03 23:53:59 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			276 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* jsmin.c
 | 
						|
   2008-08-03
 | 
						|
 | 
						|
Copyright (c) 2002 Douglas Crockford  (www.crockford.com)
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
						|
this software and associated documentation files (the "Software"), to deal in
 | 
						|
the Software without restriction, including without limitation the rights to
 | 
						|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 | 
						|
of the Software, and to permit persons to whom the Software is furnished to do
 | 
						|
so, subject to the following conditions:
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in all
 | 
						|
copies or substantial portions of the Software.
 | 
						|
 | 
						|
The Software shall be used for Good, not Evil.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
						|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
SOFTWARE.
 | 
						|
*/
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
static int   theA;
 | 
						|
static int   theB;
 | 
						|
static int   theLookahead = EOF;
 | 
						|
 | 
						|
 | 
						|
/* isAlphanum -- return true if the character is a letter, digit, underscore,
 | 
						|
        dollar sign, or non-ASCII character.
 | 
						|
*/
 | 
						|
 | 
						|
static int
 | 
						|
isAlphanum(int c)
 | 
						|
{
 | 
						|
    return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
 | 
						|
        (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' ||
 | 
						|
        c > 126);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* get -- return the next character from stdin. Watch out for lookahead. If
 | 
						|
        the character is a control character, translate it to a space or
 | 
						|
        linefeed.
 | 
						|
*/
 | 
						|
 | 
						|
static int
 | 
						|
get()
 | 
						|
{
 | 
						|
    int c = theLookahead;
 | 
						|
    theLookahead = EOF;
 | 
						|
    if (c == EOF) {
 | 
						|
        c = getc(stdin);
 | 
						|
    }
 | 
						|
    if (c >= ' ' || c == '\n' || c == EOF) {
 | 
						|
        return c;
 | 
						|
    }
 | 
						|
    if (c == '\r') {
 | 
						|
        return '\n';
 | 
						|
    }
 | 
						|
    return ' ';
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* peek -- get the next character without getting it.
 | 
						|
*/
 | 
						|
 | 
						|
static int
 | 
						|
peek()
 | 
						|
{
 | 
						|
    theLookahead = get();
 | 
						|
    return theLookahead;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* next -- get the next character, excluding comments. peek() is used to see
 | 
						|
        if a '/' is followed by a '/' or '*'.
 | 
						|
*/
 | 
						|
 | 
						|
static int
 | 
						|
next()
 | 
						|
{
 | 
						|
    int c = get();
 | 
						|
    if  (c == '/') {
 | 
						|
        switch (peek()) {
 | 
						|
        case '/':
 | 
						|
            for (;;) {
 | 
						|
                c = get();
 | 
						|
                if (c <= '\n') {
 | 
						|
                    return c;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        case '*':
 | 
						|
            get();
 | 
						|
            for (;;) {
 | 
						|
                switch (get()) {
 | 
						|
                case '*':
 | 
						|
                    if (peek() == '/') {
 | 
						|
                        get();
 | 
						|
                        return ' ';
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
                case EOF:
 | 
						|
                    fprintf(stderr, "Error: JSMIN Unterminated comment.\n");
 | 
						|
                    exit(1);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        default:
 | 
						|
            return c;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return c;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* action -- do something! What you do is determined by the argument:
 | 
						|
        1   Output A. Copy B to A. Get the next B.
 | 
						|
        2   Copy B to A. Get the next B. (Delete A).
 | 
						|
        3   Get the next B. (Delete B).
 | 
						|
   action treats a string as a single character. Wow!
 | 
						|
   action recognizes a regular expression if it is preceded by ( or , or =.
 | 
						|
*/
 | 
						|
 | 
						|
static void
 | 
						|
action(int d)
 | 
						|
{
 | 
						|
    switch (d) {
 | 
						|
    case 1:
 | 
						|
        putc(theA, stdout);
 | 
						|
    case 2:
 | 
						|
        theA = theB;
 | 
						|
        if (theA == '\'' || theA == '"') {
 | 
						|
            for (;;) {
 | 
						|
                putc(theA, stdout);
 | 
						|
                theA = get();
 | 
						|
                if (theA == theB) {
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                if (theA == '\\') {
 | 
						|
                    putc(theA, stdout);
 | 
						|
                    theA = get();
 | 
						|
                }
 | 
						|
                if (theA == EOF) {
 | 
						|
                    fprintf(stderr, "Error: JSMIN unterminated string literal.");
 | 
						|
                    exit(1);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    case 3:
 | 
						|
        theB = next();
 | 
						|
        if (theB == '/' && (theA == '(' || theA == ',' || theA == '=' ||
 | 
						|
                            theA == ':' || theA == '[' || theA == '!' ||
 | 
						|
                            theA == '&' || theA == '|' || theA == '?' ||
 | 
						|
                            theA == '{' || theA == '}' || theA == ';' ||
 | 
						|
                            theA == '\n')) {
 | 
						|
            putc(theA, stdout);
 | 
						|
            putc(theB, stdout);
 | 
						|
            for (;;) {
 | 
						|
                theA = get();
 | 
						|
                if (theA == '/') {
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                if (theA =='\\') {
 | 
						|
                    putc(theA, stdout);
 | 
						|
                    theA = get();
 | 
						|
                }
 | 
						|
                if (theA == EOF) {
 | 
						|
                    fprintf(stderr,
 | 
						|
"Error: JSMIN unterminated Regular Expression literal.\n");
 | 
						|
                    exit(1);
 | 
						|
                }
 | 
						|
                putc(theA, stdout);
 | 
						|
            }
 | 
						|
            theB = next();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* jsmin -- Copy the input to the output, deleting the characters which are
 | 
						|
        insignificant to JavaScript. Comments will be removed. Tabs will be
 | 
						|
        replaced with spaces. Carriage returns will be replaced with linefeeds.
 | 
						|
        Most spaces and linefeeds will be removed.
 | 
						|
*/
 | 
						|
 | 
						|
static void
 | 
						|
jsmin()
 | 
						|
{
 | 
						|
    theA = '\n';
 | 
						|
    action(3);
 | 
						|
    while (theA != EOF) {
 | 
						|
        switch (theA) {
 | 
						|
        case ' ':
 | 
						|
            if (isAlphanum(theB)) {
 | 
						|
                action(1);
 | 
						|
            } else {
 | 
						|
                action(2);
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        case '\n':
 | 
						|
            switch (theB) {
 | 
						|
            case '{':
 | 
						|
            case '[':
 | 
						|
            case '(':
 | 
						|
            case '+':
 | 
						|
            case '-':
 | 
						|
                action(1);
 | 
						|
                break;
 | 
						|
            case ' ':
 | 
						|
                action(3);
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                if (isAlphanum(theB)) {
 | 
						|
                    action(1);
 | 
						|
                } else {
 | 
						|
                    action(2);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            switch (theB) {
 | 
						|
            case ' ':
 | 
						|
                if (isAlphanum(theA)) {
 | 
						|
                    action(1);
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                action(3);
 | 
						|
                break;
 | 
						|
            case '\n':
 | 
						|
                switch (theA) {
 | 
						|
                case '}':
 | 
						|
                case ']':
 | 
						|
                case ')':
 | 
						|
                case '+':
 | 
						|
                case '-':
 | 
						|
                case '"':
 | 
						|
                case '\'':
 | 
						|
                    action(1);
 | 
						|
                    break;
 | 
						|
                default:
 | 
						|
                    if (isAlphanum(theA)) {
 | 
						|
                        action(1);
 | 
						|
                    } else {
 | 
						|
                        action(3);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                action(1);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* main -- Output any command line arguments as comments
 | 
						|
        and then minify the input.
 | 
						|
*/
 | 
						|
extern int
 | 
						|
main(int argc, char* argv[])
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    for (i = 1; i < argc; i += 1) {
 | 
						|
        fprintf(stdout, "// %s\n", argv[i]);
 | 
						|
    }
 | 
						|
    jsmin();
 | 
						|
    return 0;
 | 
						|
}
 |