#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define VERSION        "0.0.2"
#define TOOL_NAME      "tagcase"
#define AUTHOR_NAME    "Haruaki TAMADA"
#define AUTHOR_ADDRESS "tamada@oikaze.com"

#define TO_UPPER_CASE    1
#define TO_LOWER_CASE    2
#define TO_SWAP_CASE     4

char *nopath(char *path){
    char *p;
    p = strrchr(path, '/');
    if(p != NULL) return p + 1;
    return path;
}

void author(char *prog){
    fprintf(stdout, "%s's author is \"%s\" <mailto:%s>\n", nopath(prog), AUTHOR_NAME,
            AUTHOR_ADDRESS);
}

void version(char *prog){
    fprintf(stdout, "%s's version is \"%s\"\n", TOOL_NAME, VERSION);
}

void usage(char *prog){
    fprintf(stdout, "Usage: %s [-AHV] [-lus] [files...]\n", 
            nopath(prog));
}

void help(char *prog){
    fprintf(stdout, "Usage: %s [options...] [files...]\n\
     -a: print author information. \n\
     -h: print this message. \n\
     -v: print version. \n\

     -l: to lower case. (default) \n\
     -u: to upper case. \n\
     -s: swap case. \n\

  files: if null, read from stdin. \n", nopath(prog));
}

int parse_option(int argc, char *argv[]){
    int i, j;
    int help_flag = 0;
    int flag = 0;

    for(i = 1; i < argc; i++){
        if(argv[i][0] == '-'){
            for(j = 1; j < strlen(argv[i]); j++){
                switch(argv[i][j]){
                case 'a':
                    author(argv[0]);
                    help_flag = 1;
                    break;
                case 'h':
                    help(argv[0]);
                    help_flag = 1;
                    break;
                case 'v':
                    version(argv[0]);
                    help_flag = 1;
                    break;
                case 'u':
                    flag |= TO_UPPER_CASE;
                    break;
                case 's':
                    flag |= SWAP_CASE;
                    break;
                case 'l':
                    flag |= TO_LOWER_CASE;
                    break;
                default:
                    usage(argv[0]);
                    break;
                }
            }
        }
    }

    if(help_flag != 0){
        exit(0);
    }

    if(flag == 0) flag = TO_LOWER_CASE;

    return flag;
}

int tagcase(FILE *f, int option){
    char c;
    int flag = 0;
    int comments = 0;

    while((c = fgetc(f)) != EOF){
        /* 要素内 or コメント開始 */
        if(c == '<'){
            flag = 2;
            comments = 0;
        }
        /* 要素内 or コメント終了 */
        else if(c == '>'){
            flag = 0;
            comments = 0; /* <!-- --> 形式のコメントを表すフラグ */
        }
        /* 要素内の属性記述開始 */
        if(flag == 2 && c == '\"'){
            flag = 1;
        }
        /* 要素内の属性記述終了 */
        else if(flag == 1 && c == '\"'){
            flag = 2;
        }
        else{
            if(flag == 2 && comments == 0 && c == '!') comments = 1;

            if(comments == 0 && flag == 2 && isalpha(c) != 0){
		if((option & SWAP_CASE) == SWAP_CASE){
		    if(isupper(c))      c += ('a' - 'A');
		    else if(islower(c)) c -= ('a' - 'A');
		}
		else{
		    if(isupper(c) && (option & TO_LOWER_CASE) == TO_LOWER_CASE){
			c += ('a' - 'A');
		    }
		    if(islower(c) && (option & TO_UPPER_CASE) == TO_UPPER_CASE){
			c -= ('a' - 'A');
		    }
		}
            }
        }
        fputc(c, stdout);
    }

    return 1;
}

int tagcase_prepare(char *file, int option){
    FILE *f;
    int flag;

    if((f = fopen(file, "r")) == NULL){
        perror(file);
        return -1;
    }

    flag = tagcase(f, option);

    fclose(f);

    return flag;
}

int main(int argc, char *argv[]){
    int i;
    int do_flag = 0;
    int flag = parse_option(argc, argv);

    for(i = 1; i < argc; i++){
        if(argv[i][0] != '-'){ 
            tagcase_prepare(argv[i], flag);
            do_flag = 1;
        }
    }

    if(do_flag == 0){
        tagcase(stdin, flag);
    }
}
