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

//構造体YJの定義
typedef struct yj
{
        int numdot;
        int lastdot;
        int nextdot;
        char word[256];
        struct yj *next;
}YJ;


//領域確保用の関数
YJ *newyj()
{
        YJ *p;
        p=(YJ *)malloc(sizeof(YJ));

        if(p==NULL)
        {
                fputs("malloc failedn\n",stderr);
                exit(1);
        }
        else
        {
                return p;
        }
}

//この構造体を配列にしてマージソートに使いたい
typedef struct list
{
        YJ *dom;//すでに上で定義した構造体型のポインタ
}LIST;

void printlist(YJ *top)
{
	YJ *now;
	now=top;
        now=top;
        while(now->next!=NULL)
        {
                printf("%d,%s\n",now->numdot,now->word);
                now=now->next;
        }

}

YJ *makelist(char filename[256])
{

        FILE *fp;
        fp=fopen(filename,"r");//ファイル開く
        //エラー処理
        if(fp==NULL)
        {
                printf("file open failed(%s)\n",filename);
        }

        int c;//ファイルから読み取った文字を格納
        int i=0;
        YJ *top,*now,*new;
        //入力順にリスト作成開始
        new=newyj();
        now=new;
        top=now;

        now->numdot=0;//初期化
        now->lastdot=-1;//文字列の最初の１つ前ににdotがあると仮定
        while((c=fgetc(fp))!=EOF)
        {
                if(c!='\n')
                {
                        if(c=='.')
                        {
                                (now->numdot)++;
                        }
                        now->word[i]=c;
                        i++;
                }
                else if(c=='\n')
                {
                        now->word[i]='\0';
                        new=newyj();//新しい領域確保
                        now->next=new;//これにより、現在のnowの指す領域のnextは上で確保した領域となる
                        now=new;//次のループに向け、nowを上で確保した領域に再指定

                        i=0;
                        now->numdot=0;//初期化
                        now->lastdot=-1;//最初の１つ前にdotがあると仮定
                }
        }
        now->next=NULL;
        fclose(fp);
        return top;
}

void resetdom(LIST *marge)
{
	int i;
        for(i=0;i<27;i++)
        {
                (marge[i]).dom=NULL;
        }
}

void findmaxdot(YJ *top,int *maxdot)
{
        YJ *now;
        now=top;
        while(now->next!=NULL)
        {
                if(*maxdot<(now->numdot))
                {
                        *maxdot=now->numdot;
                }
                now=now->next;
        }
        printf("Maxdot:%d\n",*maxdot);
}

void findmaxword(YJ *top,int *maxw,int i)
{
        YJ *now;
        now=top;
        int l;
        int maxtemp;
	*maxw=0;
        while(now->next!=NULL)
        {
                maxtemp=0;
                l=(now->lastdot)+1;
                while(1)
                {
                        printf("%c",now->word[l]);
                        //行の区画数が不足の時
                        if((now->numdot)<i)
                        {
                                break;
                        }

                        //行の端ordotまで読んだ時
                        if(((now->word[l])=='\0')||((now->word[l])=='.'))
                        {
                                now->nextdot=l;//現在の区画の終了の添字
                                break;
                        }
                        else
                        {
                                maxtemp++;
                                l++;
                        }
                }
                printf("@");
                //大小比較
                if(maxtemp>(*maxw))
                {
                        (*maxw)=maxtemp;
                }
                now=now->next;
                printf("maxw:%d\n",*maxw);
        }
}

void setlastdot(YJ *top,int i)
{
        YJ *now;
        now=top;
        while(now->next!=NULL)
        {
                if((now->numdot)<i)
                {
                        //区画数が足りない場合はそのまま
                }
                else
                {
                        now->lastdot=now->nextdot;//置き換え
                }
                now=now->next;
        }
}

void putin(YJ *now,LIST *marge,YJ *lastm[27],int l)
{
	int asc;
	YJ *temp;
	while(now->next!=NULL)
	{
        	if(l>=(now->nextdot))
        	{
        		asc=96;
        	}//大文字
        	else if((65<=(now->word[l]))&&((now->word[l])<=90))
        	{
        		asc=(now->word[l])+32;
        	}//小文字
        	else if((97<=(now->word[l]))&&((now->word[l])<=122))
        	{
        		asc=now->word[l];
        	}
		printf("\n");
		printf("@@@%c@@@\n",asc);

		temp=now->next;//退避
		//バケットソート用配列に入れる操作---------------------------------------
	        asc=asc-96;//これでascは0~26になる
	        if((marge[asc]).dom==NULL)//何もリストが連結されていないとき
	        {
                        printf("-------------\n");
                        printf("%s\n",now->word);
	                (marge[asc]).dom=now;
	                lastm[asc]=now;
	                lastm[asc]->next=NULL;
                        printf("---------------\n");

	        }
                else
	        {
			printf("-------------\n");
			printf("%s\n",now->word);
	                lastm[asc]->next=now;
	                lastm[asc]=now;
	                lastm[asc]->next=NULL;
			printf("---------------\n");
	        }
		//--------------------------------------------------------------------

		now=temp;

	}
}

YJ *joint(LIST *marge,YJ *lastm[27])
{
	int i;
	int temp;
	YJ *now,*top;
	top=NULL;
	for(i=0;i<=26;i++)
	{
		if(((marge[i]).dom)!=NULL)//LISt型配列の最初のYJ型リストへのポインタがNULLでない場合
		{	//表示させる
			temp=i+96;//
			printf("joint:::%c\n",temp);

			if(top==NULL)//まだtopが見つかってない時
			{
				
				now=(marge[i]).dom;
				top=now;
			}
			else//もう以前のループでtopが見つかった時
			{
				now->next=(marge[i]).dom;
			}
			now=lastm[i];
		}
	}
	now=now->next;
	now->next=NULL;
	return top;
}

void sort(char filename[256])
{
	YJ *top,*now;
	top=makelist(filename);
	now=top;
        //とりあえずデバッグのために表示
        printlist(top);

	//バケットソート用配列
        LIST marge[27];//アルファベット用
        YJ *lastm[27];//ソート用のリストの最後の要素を指すポインタ(アルファベット用)
	resetdom(marge);

	int maxdot=0;
	findmaxdot(top,&maxdot);

	printf("\n");
	int i,maxw;
	int l,j,asc;
	YJ *temp;
	for(i=maxdot;i>=0;i--)
	{
		findmaxword(top,&maxw,i);
		for(j=maxw;j>=1;j--)
		{
			now=top;
			l=(now->lastdot)+j;
			putin(now,marge,lastm,l);//各配列にリストとしてつなげる
			top=joint(marge,lastm);//各配列からtopから辿れるように繋げなおす
			resetdom(marge);//各配列のYJ型リストへのポインタをNULLとする
			printlist(top);
		}
		printf("\n");
		setlastdot(top,i);

	}
}

int main(int argc,char *argv[])
{
	sort(argv[1]);
	return 0;
}
