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

FILE *F, *F1, *F2;
int up=1;

void ErrorExit(int N)
{
  switch (N)
  {
    case 1 : printf("Error: couldn't open file\n"); break;
    case 2 : printf("Error: incorrect parametres\n"); break;
    case 3 : printf("Error: read after end of file\n"); break;
    case 4 : printf("Error: empty file\n"); break; 
  }
  if (F) fclose(F);
  if (F1) fclose(F1);
  if (F2) fclose(F2);
  exit(N);
}

char* GetLineFile(FILE* f) //get line from current position
{
  char* S=(char*)malloc(sizeof(char));
  int c;
  int i=0;
  if ((c=fgetc(f))==-1) return NULL;
  while((c!=-1)&&(c!='\n'))
  {
    i++;
    S=(char*)realloc(S, sizeof(char)*(i+1));
    S[i-1]=c;
    c=fgetc(f);
  }
  i++;
  S=(char*)realloc(S, sizeof(char)*(i+1));
  S[i-1]='\n';
  S[i]='\0';
  return S;
}

int movfiles()
{
  char *S1, *S2;
  int pos=1;
  int chg=0;

  F=(fopen("tmp.tmp", "r"));
  F1=(fopen("tmp1.tmp", "w"));
  F2=(fopen("tmp2.tmp", "w"));

  S1=GetLineFile(F);
  if (!S1) ErrorExit(4);
  while(S2=GetLineFile(F))
  {
    fwrite(S1, sizeof(char), strlen(S1), pos?F1:F2);
    if (strcmp(S1, S2)*up>0) 
    {
      chg=1;
      pos=1-pos;
    }
    free(S1);
    S1=S2;
  }
  fwrite(S1, sizeof(char), strlen(S1), pos?F1:F2);
  free(S1);

  fclose(F);
  fclose(F1);
  fclose(F2);
  return chg;
}

int put2seq()
{
  char* S1, *S2, *S;
  long pos1, pos2;
  S1=GetLineFile(F1);
  S2=GetLineFile(F2);
  if ((!S1) && (!S2)) return 0;
  if (!S1)
  {
    fwrite(S2, sizeof(char), strlen(S2), F);
    free(S2);
    while(S2=GetLineFile(F2))
    {
      fwrite(S2, sizeof(char), strlen(S2), F);
      free(S2);
    }
    return 0;
  }
  if (!S2)
  {
    fwrite(S1, sizeof(char), strlen(S1), F);
    free(S1);
    while(S1=GetLineFile(F1))
    {
      fwrite(S1, sizeof(char), strlen(S1), F);
      free(S1);
    }
    return 0;
  }

  while(1)
  {
    if (strcmp(S1, S2)*up<=0)
    {
      fwrite(S1, sizeof(char), strlen(S1), F);
      pos1=ftell(F1);
      S=GetLineFile(F1);

      if (!S || strcmp(S, S1)*up<=0)
      {
        if (S) fseek(F1, pos1, SEEK_SET);
        free(S1);
        S1=S;
        fwrite(S2, sizeof(char), strlen(S2), F);
        pos2=ftell(F2);
        S=GetLineFile(F2);
        while(S && strcmp(S, S2)*up>0)
        {
          free(S2);
          S2=S;
          fwrite(S2, sizeof(char), strlen(S2), F);
          pos2=ftell(F2);
        }
        if (S) fseek(F2, pos2, SEEK_SET);
        free(S);
        return 1;
      }

      free(S1);
      S1=S;
    }
    else
    {
      fwrite(S2, sizeof(char), strlen(S2), F);
      pos2=ftell(F2);
      S=GetLineFile(F2);

      if (!S || strcmp(S, S2)*up<=0)
      {
        if (S) fseek(F2, pos2, SEEK_SET);
        free(S2);
        S2=S;
        fwrite(S1, sizeof(char), strlen(S1), F);
        pos1=ftell(F1);
        S=GetLineFile(F1);
        while(S && strcmp(S, S1)*up>0)
        {
          free(S1);
          S1=S;
          fwrite(S1, sizeof(char), strlen(S1), F);
          pos1=ftell(F1);
        }
        if (S) fseek(F1, pos1, SEEK_SET);
        free(S);
        return 1;
      }

      free(S2);
      S2=S;
    }
  }
}

void addfile(char* path)
{
  char* S;
  F1=fopen(path, "r");
  while(S=GetLineFile(F1))
  {
    fwrite(S, sizeof(char), strlen(S), F);
    free(S);
  }
  fclose(F1);
}

void printfile()
{
  F=fopen("tmp.tmp", "r");
  char* S;
  while(S=GetLineFile(F)) printf("%s", S);
  fclose(F);
}

int main(int argc, char** argv)
{
  char *S1, *S2, *S;
  int i=0;

  if (argc<2) ErrorExit(2);

  F=fopen("tmp.tmp", "w");
  i=1;
  if (!strcmp(argv[1], "-d"))
  {
    i=3;
    if (!strcmp(argv[2], "up")) up=1;
    else
      if (!strcmp(argv[2], "down")) up=-1;
      else ErrorExit(2);
  }
  for(; i<argc; i++)
    addfile(argv[i]);
  fclose(F);

  while(movfiles())
  {
    F=(fopen("tmp.tmp", "w"));
    F1=(fopen("tmp1.tmp", "r"));
    F2=(fopen("tmp2.tmp", "r"));
    while(put2seq());
    fclose(F);
    fclose(F1);
    fclose(F2);
  }

  printfile();

  remove("tmp.tmp");
  remove("tmp1.tmp");
  remove("tmp2.tmp");

  return 0;
}
