#include <stdio.h>
#include <ctype.h>
#include <io.h>
#include <string.h>
#include "../inc/getopt.h"

#define	msg(s) fputs(s, stderr)

typedef enum {
    ON = !0, OFF = 0
} flag_t;

char	*help_msg[] =
{
    "行番号フィルター　ＮＬ．ＥＸＥ\n",
    "              Y.Tsuzi[" __DATE__ "]\n",
    "  nl [-hH?] [-kc] [infile] [-o outfile]\n",
    "                 < [infile] > [outfile]\n",
    "   -hH?      ヘルプ\n",
    "   -c        ＣＯＢＯＬ　ｓｔｙｌｅ\n",
    "   -k        行番号を削除します。\n",
    "             （通常は行番号を付けます。）\n",
    "   infile    入力ファイルを指定します。\n",
    "   outfile   出力ファイルを指定します。\n",
    NULL
};

char *file[50];

int	nl(FILE *in, FILE *out, flag_t cobol);
int	nl_erase(FILE *in, FILE *out);
char	*erase_number(char *s);
int	help(void);

int	main(int argc, char **argv)
{
    int		i;
    char	*data;
    char	**fname = file;
    char	*out_file = NULL;
    FILE	*in_fp, *out_fp;
    flag_t	kill = OFF;
    flag_t	cobol = OFF;
    
    setopt(argc, argv);
    
    while((i = getopt('-', "o:kchH?", &data)) >= 0) {
	switch(i) {
	case 'h':
	case 'H':
	case '?':
	    help();
	    return 1;
	case 'o':
	    if(data != NULL)
		out_file = data;
	    break;
	case 'k':
	    kill = ON;
	    break;
	case 'c':
	    cobol = ON;
	    break;
	case 0:
	    *fname++ = data;
	    break;
	}
    }
    *fname = NULL;
    
    if(out_file != NULL) {
	if((out_fp = fopen(out_file, "w")) == NULL) {
	    msg("出力ファイルがオープンできません。\n");
	    return 1;
	}
    } else {
	out_fp = stdout;
    }
    
    fname = file;
    
    if(!isatty(fileno(stdin))) {
	if(kill == OFF) {
	    nl(stdin, out_fp, cobol);
	} else {
	    nl_erase(stdin, out_fp);
	}
    } else if(*fname == NULL) {
    	help();
	goto EXIT;
    }
    
    while(*fname != NULL) {
	if((in_fp = fopen(*fname++, "r")) == NULL) {
	    msg("ファイルがオープンできません。\n");
	    goto EXIT;
	}
	if(kill == OFF) nl(in_fp, out_fp, cobol);
	else 		nl_erase(in_fp, out_fp);
	
	fclose(in_fp);
    }

EXIT:
    if(out_file != NULL) fclose(out_fp);
    return 0;
}

int	nl(FILE *in, FILE *out, flag_t cobol)
{
    char	s[256], ns[256];
    long	n = 1;
    
    while(fgets(s, 255, in) != NULL) {
	char *nk = erase_number(s);
	
	if(cobol && (*nk == '$' || *nk == '*')) {
	    sprintf(ns, "%06ld0", n);
	} else {
	    sprintf(ns, "%06ld0 ", n);
	}
	strcat(ns, nk);
	fputs(ns, out);
	n++;
    }
    return 0;
}

int	nl_erase(FILE *in, FILE *out)
{
    char	s[256];
    
    while(fgets(s, 255, in) != NULL)
	fputs(erase_number(s), out);
    
    return 0;
}

char	*erase_number(char *s)
{
    char	*os = s;
    
    if(!isdigit(*s))
	return os;
    
    s++;
    
    while(*s) {
	if(isdigit(*s)) {
	    s++;
	} else {
	    if(*s == ' ') {
		return ++s;
	    } else {
		return s;
	    }
	}
    }
    
    return os;
}

int	help(void)
{
    char **help = help_msg;
    while(*help) msg(*help++);
    return 0;
}
