/*-
 * Copyright (c) 2000
 * Tatsuya Kudoh(CDR/TK),ROYALPANDA.    All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include<stdio.h>

#define HASHSIZE	256

typedef struct cell_t_{
	struct cell_t_ *next;
	unsigned char *data;
	int len;
}cell_t;

static cell_t Head[HASHSIZE];
int Num[HASHSIZE];

static void init( void )
{
	int i;

	for( i = 0 ; i < HASHSIZE ; i++ ){
		Head[i].next = NULL;
		Num[i] = 0;
	}
}


static int gethash( unsigned char *p )
{
	int sum;

	sum = 0;
	while( *p )
		sum += *p++;
	return sum % HASHSIZE;
}

static int readline( FILE *fp )
{
	unsigned char buf[1024];
	int len;
	int hash;
	cell_t *cp;
	unsigned char *sp;

	/* read a line ( void comment line ) */

	do{
		if( fgets(buf,1024,fp) == NULL )
			return feof(fp) ? 0 : -1;
	}while( buf[0] == ';' );


	/* get length, substitute LF to \0 */

	len = strlen(buf);
	if( buf[len-1] != '\n' )
		len++;
	buf[len-1] = 0;
	buf[len-2] = 0;


	/* substitute space and slash to \0 */

	sp = buf;
	while( *sp ){
		if( *sp == ' ' || *sp == '/' )
			*sp = 0;
		sp++;
	}

	hash = gethash(buf);

	/* chain to list */

	cp = (cell_t*)malloc(sizeof(cell_t));
	if( cp == NULL )
		return -1;
	sp = (unsigned char*)malloc(len);
	if( sp == NULL )
		return -1;
	memcpy(sp,buf,len);

	cp->data = sp;
	cp->len = len;
	cp->next = Head[hash].next;
	Head[hash].next = cp;
	Num[hash]++;

	return 1;
}

static int create_data( unsigned char **pp )
{
	int i;
	cell_t *cp;
	int totalsize;
	int size;
	unsigned char *sp;

	/* allocate data area */

	totalsize = HASHSIZE*4;
	for( i = 0 ; i < HASHSIZE ; i++ ){
		cp = Head[i].next;
		while( cp ){
			totalsize += cp->len + 2;
			cp = cp->next;
		}
	}
	sp = (unsigned char*)malloc(totalsize);
	if( sp == NULL )
		return -1;

	/* create data */

	size = HASHSIZE*4;
	for( i = 0 ; i < HASHSIZE ; i++ ){
		cp = Head[i].next;
		if( cp ){
			sp[i*4] = size & 0xff;
			sp[i*4+1] = (size >> 8) & 0xff;
			sp[i*4+2] = (size >> 16) & 0xff;
			sp[i*4+3] = (size >> 24) & 0xff;

			while( cp ){
				if( cp->next ){
					sp[size++] = (cp->len+2) & 0xff;
					sp[size++] = ((cp->len+2) >> 8) & 0xff;
				}else{
					sp[size++] = 0;
					sp[size++] = 0;
				}
				memcpy(sp+size,cp->data,cp->len);
				size += cp->len;
				cp = cp->next;
			}
		}else{
			sp[i*4] = 0;
			sp[i*4+1] = 0;
			sp[i*4+2] = 0;
			sp[i*4+3] = 0;
		}
	}
	*pp = sp;

#ifndef NDEBUG
	if( size != totalsize )
		fprintf(stderr,"size error\n");
#endif
	
	return size;
}


int main( int argc, char **argv )
{
	int i;
	unsigned char *p;

	init();
	while( (i = readline(stdin)) == 1 )
		;

	if( i < 0 ){
		fprintf(stderr,"read error\n");
		return 1;
	}

	i = create_data(&p);
	if( i < 0 ){
		fprintf(stderr,"read error\n");
		return 1;
	}

	if( fwrite(p,1,i,stdout) < i ){
		fprintf(stderr,"write error\n");
		return 1;
	}
	return 0;
}
