#define WINDOWS_OS !defined(__linux__) && !defined(__unix__) && !defined(__APPLE__)

#if WINDOWS_OS
#  include <fcntl.h>
#  include <io.h>
#else
#  include <sys/param.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if WINDOWS_OS
#  if defined(__BORLANDC__)
#    define _setmode(f,t)   setmode((f), (t))
#    define _O_BINARY       O_BINARY
#  endif
#  define DS_CODE           ('\\')
#else
#  define _setmode(f,t)     (0)
#  define _O_BINARY         
#  define DS_CODE           ('/')
#  define _MAX_PATH         MAXPATHLEN
#  define _fullpath(a,r,n)  realpath((r), (a))
#endif

#define ArrLen(arr)  (sizeof(arr) / sizeof((arr)[0]))

#define SIZE         (1000)
#define LF_CODE      (0x0A)
#define CR_CODE      (0x0D)
#define OUTPUT_SW    ("-o")

#define ErrCheck(e)              \
	{                            \
		if (e) {                 \
			perror(NULL);        \
			exit(EXIT_FAILURE);  \
		}                        \
	}

#define ErrDown(m)                   \
	{                                \
		usage(args[0]);              \
		fprintf(stderr, "Error: ");  \
		fprintf(stderr, m);          \
		exit(EXIT_FAILURE);          \
	}

void usage(const char arg0[]);

/* CRコードを削除する。 */

int main(int argc, char *args[]) {
	
	int ch;
	char data[SIZE + 1], out[SIZE + SIZE + 1];
	int i, sz, md, j, flag;
	FILE *input = NULL, *output = NULL;
	char path1[_MAX_PATH + 1], path2[_MAX_PATH + 1];
	
	if (argc > 4) {
		ErrDown("a lot of argument!\n");
	}
	
	if (argc > 1) {
		switch (argc) {
			case 2: {
				if ((strcmp(args[1], "--help") == 0)
						|| (strcmp(args[1], "-h") == 0)
						|| (strcmp(args[1], "-?") == 0)
						|| (strcmp(args[1], "/?") == 0)) {
					usage(args[0]);
					return 0;
				}
				input = fopen(args[1], "rb");
				ErrCheck(input == NULL);
				break;
			}
			case 3: {
				if (strcmp(args[1], OUTPUT_SW) != 0) {
					ErrDown("syntax error!\n");
				}
				output = fopen(args[2], "wb");
				ErrCheck(output == NULL);
				break;
			}
			case 4: {
				i = 1;
				j = 3;
				if (strcmp(args[1], OUTPUT_SW) == 0) {
					i = 3;
					j = 2;
				} else if (strcmp(args[2], OUTPUT_SW) != 0) {
					ErrDown("syntax error!\n");
				}
				if (_fullpath(path1, args[i], ArrLen(path1)) == NULL) {
					ErrDown("illegal input file!\n");
				}
				if (_fullpath(path2, args[j], ArrLen(path2)) == NULL) {
					ErrDown("illegal output file!\n");
				}
				if (strcmp(path1, path2) == 0) {
					ErrDown("the same input file as ouput file!\n");
				}
				input = fopen(path1, "rb");
				ErrCheck(input == NULL);
				output = fopen(path2, "wb");
				ErrCheck(output == NULL);
				break;
			}
			default: {
				break;
			}
		}
	}
	
	if (input == NULL) {
		md = _setmode(_fileno(stdin), _O_BINARY);
		ErrCheck(md == -1);
		input = stdin;
	}
	
	if (output == NULL) {
		md = _setmode(_fileno(stdout), _O_BINARY);
		ErrCheck(md == -1);
		output = stdout;
	}
	
	flag = 0;
	while ((sz = fread(data, sizeof(data[0]), ArrLen(data), input)) != 0) {
		j = 0;
		for (i = 0; i < sz; ++i) {
			if (flag == 1) {
				flag = 0;
				if (data[i] != LF_CODE) {
					out[j] = LF_CODE;
					++j;
				}
			}
			if (data[i] == CR_CODE) {
				flag = 1;
				continue;
			}
			out[j] = data[i];
			++j;
		}
		fwrite(out, sizeof(out[0]), j, output);
	}
	
	if (input != stdin) {
		fclose(input);
	}
	
	if (output != stdout) {
		fclose(output);
	}
	
	return 0;
}

void usage(const char arg0[]) {
	int i, j;
	j = 0;
	for (i = 0; arg0[i] != '\0'; ++i) {
		if (arg0[i] == DS_CODE) {
			j = i + 1;
		}
	}
	puts("Delete CR-Code(0x0D)");
	printf("  usage: %s [-o <Output File>] [<Input File>]\n", &arg0[j]);
}
