
Deprecated: Function set_magic_quotes_runtime() is deprecated in /DISK2/WWW/lokiware.info/mff/wakka.php on line 35
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>


enum{
	AllocStep	= 32
};

#define isSep(c)	((c)==' ' || (c)=='\t' || (c)=='\n')
#define isAlign(c)	((c)=='R' || (c)=='L' || (c)=='C')

#define usage(errl)	fprintf(stderr, "%sUsage: ftable <nazev_souboru> [cislo_sloupce] [{R|C|L}]\n", (errl))

typedef struct Cell{
	size_t	size;
	char*	string;
} Cell;

typedef struct Row{
	Cell**	cells;
} Row;

typedef struct Table{
	size_t	rowSize;
	size_t	size;
	Row**	rows;
	size_t*	cellSizes;
} Table;

static Cell* readCell(FILE* f);
static void freeCell(Cell* c);
static Row* readRow(FILE* f, size_t* rowSize);
static void freeRow(Row* r, size_t s);

static Table* readTable(FILE* f);
static void freeTable(Table* t);
static void printTable(FILE* f, const Table* t, const char* align, size_t an);

static int		sortCol	= 0;
static int	rowCmp(const void* a, const void* b);

int main(int argc, const char** argv){
	
	FILE*	f;
	Table*	table;
	char*	align	= NULL;

	if(argc == 1){
		usage("");
		exit(EXIT_FAILURE);
	}


	f = fopen(argv[1], "r");

	if(!f){
		usage("Cannot open\n");
		exit(EXIT_FAILURE);
	}

	if( argc > 2 && isdigit(argv[2][0])){
		sortCol = atoi(argv[2]);
		argv++;
		argc--;
	}

	if( argc > 2){
		int i;

		argc-=2;
		argv+=2;

		align	= calloc(argc+1, sizeof(char));	/* trailing zero */

		for(i = 0; i < argc ; i++){
			if(!isAlign(argv[i][0]) || argv[i][1] !='\0'){
				usage("Bad align\n");
				exit(EXIT_FAILURE);
			}
			align[i] = argv[i][0];
		}
	}

	table	=	readTable(f);

	if(sortCol)
		qsort(table->rows, table->size, sizeof(Row*), rowCmp);

	printTable(stdout, table, align, (align) ? argc : 0);

	freeTable(table);

	fclose(f);

	return 0;
}


static Cell* readCell(FILE* f){
	int	c;
	Cell*	cell = NULL;


	do{
		c = fgetc(f);
	}while(c==' ' || c=='\t');

	if(c == '\n' || c == EOF)
		return NULL;

	cell	= calloc(1, sizeof(Cell));
	cell->string	= malloc(AllocStep);

	do{
		cell->string[cell->size++]	= c;
		if( ! (cell->size % AllocStep) )
			cell->string = realloc(cell->string, cell->size + AllocStep);
		c = fgetc(f);
	}while( ! isSep( c ) );

	ungetc(c,f);

	cell->string[cell->size]		= '\0';


	return cell;

}

static void freeCell(Cell* c){
	free(c->string);
	free(c);
}

static Row* readRow(FILE* f, size_t* rowSize){


	Row*	row		= calloc(1, sizeof(Row));
	Cell*	c;
	size_t	i;


	if(*rowSize)
		row->cells	= calloc(*rowSize, sizeof(Cell*));
	else
		row->cells	= calloc(AllocStep, sizeof(Cell*));

	for(i= 0; c = readCell(f) ; i++){
		if(!*rowSize && !(i % AllocStep) )
			row->cells	= realloc(row->cells, (i+AllocStep)*sizeof(Cell*));
		row->cells[i]	= c;
	}

	if(!*rowSize)
		*rowSize = i;

	if(feof(f)){
		freeRow(row,i);
		if(i)
			fprintf(stderr, "Ignoring last row, missing terminating new line\n");
		return NULL;
	}

	return row;

}

static void freeRow(Row* r, size_t s){
	size_t i;
	for(i= 0; i < s ; i++)
		freeCell(r->cells[i]);
	free(r->cells);
	free(r);
}

static Table* readTable(FILE* f){
	
	Table*	table	= calloc(1, sizeof(Table));
	Row*	r;
	size_t	i;
	size_t	s		= 0;
	size_t*	maxs	= NULL;

	table->rows		= calloc(AllocStep, sizeof(Row*));

	for(i= 0; r = readRow(f,&s) ; i++){
		size_t j;
		if( !(i % AllocStep) )
			table->rows	= realloc(table->rows, (i+AllocStep)*sizeof(Row*));
		table->rows[i]	= r;
		if(!maxs)
			maxs		= calloc(s, sizeof(size_t));
		for( j = 0; j < s ; j++){
			if(r->cells[j]->size > maxs[j])
				maxs[j]	= r->cells[j]->size;
		}
	}

	table->cellSizes	= maxs;
	table->rowSize		= s;
	table->size			= i;

	return table;

}

static void freeTable(Table* t){
	size_t i;
	for(i= 0; i < t->size ; i++)
		freeRow(t->rows[i],t->rowSize);
	free(t->rows);
	free(t->cellSizes);
	free(t);
}

static int	rowCmp(const void* a, const void* b){
	char* s	=	(*(Row**)a)->cells[sortCol-1]->string;
	char* t	=	(*(Row**)b)->cells[sortCol-1]->string;
	return strcmp(s,t);
}

#define getAlign(a,an,i)	( ((i)<(an)) ? (a)[(i)] : 'R' )

static void printTable(FILE* f, const Table* t, const char* align, size_t an){
	size_t	i;
	size_t	j;

	for( i = 0; i < t->size; i++){
		for( j = 0; j < t->rowSize; j++){
			size_t	l;
			switch(getAlign(align, an, j)){
				case 'L':
					printf(" %-*s", t->cellSizes[j], t->rows[i]->cells[j]->string);
					break;
				case 'C':
					l = t->rows[i]->cells[j]->size + t->cellSizes[j];
					printf(" %*s", l/2,	t->rows[i]->cells[j]->string);
					printf("%*s", l/2 - t->rows[i]->cells[j]->size + l%2, "");
					break;
				default:	/* R */
					printf(" %*s", t->cellSizes[j], t->rows[i]->cells[j]->string);
					break;
			}
		}
		fputc('\n',f);
	}

}