| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 | /*	This file is part of the software similarity tester SIM.	Written by Dick Grune, Vrije Universiteit, Amsterdam.	$Id: pass3.c,v 2.11 2005/02/20 17:03:03 dick Exp $*/#include	<stdio.h>#include	<string.h>#include	<malloc.h>#include	"system.par"#include	"debug.par"#include	"sim.h"#include	"runs.h"#include	"error.h"#include	"options.h"#include	"pass3.h"#include	"percentages.h"#ifdef	DB_RUN#include	"tokenarray.h"static void db_run(const struct run *);#endifstatic FILE *open_chunk(const struct chunk *);static void fill_line(FILE *, char []);static void clear_line(char []);static void show_runs(void);static void show_run(const struct run *);static void show_2C_line(const char [], const char []);static void show_1C_line(FILE *, const char *);static int prhead(const struct chunk *);static int prs(const char *);static int pru(unsigned int);static int unslen(unsigned int);static int maxline;			/* Actual maximum line length */static char *line0;			/* by malloc() */static char *line1;voidPass3(void) {	if (option_set('p')) {		show_percentages();	}	else {		show_runs();	}}static voidshow_runs(void) {	AisoIter iter;	struct run *run;	maxline = PageWidth / 2 - 2;	line0 = malloc((unsigned int)((maxline + 1) * sizeof (char)));	line1 = malloc((unsigned int)((maxline + 1) * sizeof (char)));	if (!line0 || !line1) fatal("out of memory");	OpenIter(&iter);	while (GetAisoItem(&iter, &run)) {#ifdef	DB_RUN		db_run(run);#endif	/* DB_RUN */		show_run(run);		fprintf(OutputFile, "\n");	}	CloseIter(&iter);	free(line0); line0 = 0;	free(line1); line1 = 0;}static voidshow_run(const struct run *run) {	/* The animals came in two by two ... */	register const struct chunk *cnk0 = &run->rn_cn0;	register const struct chunk *cnk1 = &run->rn_cn1;	register unsigned int nl_cnt0 =			cnk0->ch_last.ps_nl_cnt - cnk0->ch_first.ps_nl_cnt;	register unsigned int nl_cnt1 =			cnk1->ch_last.ps_nl_cnt - cnk1->ch_first.ps_nl_cnt;	FILE *f0;	FILE *f1;	/* display heading of chunk */	if (!option_set('d')) {		/* no assumptions about the lengths of the file names! */		register unsigned int size = run->rn_size;		register int pos = 0;		pos += prhead(cnk0);		while (pos < maxline + 1) {			pos += prs(" ");		}		pos += prs("|");		pos += prhead(cnk1);		while (pos < 2*maxline - unslen(size)) {			pos += prs(" ");		}		fprintf(OutputFile, "[%u]\n", size);	}	else {		(void)prhead(cnk0);		fprintf(OutputFile, "\n");		(void)prhead(cnk1);		fprintf(OutputFile, "\n");	}	/* stop if that suffices */	if (option_set('n'))		return;			/* ... had enough so soon ... */	/* open the files that hold the chunks */	f0 = open_chunk(cnk0);	f1 = open_chunk(cnk1);	/* display the chunks in the required format */	if (!option_set('d')) {		/* fill 2-column lines and print them */		while (nl_cnt0 != 0 || nl_cnt1 != 0) {			if (nl_cnt0) {				fill_line(f0, line0);				nl_cnt0--;			}			else {				clear_line(line0);			}			if (nl_cnt1) {				fill_line(f1, line1);				nl_cnt1--;			}			else {				clear_line(line1);			}			show_2C_line(line0, line1);		}	}	else {		/* display the lines in a diff(1)-like format */		while (nl_cnt0--) {			show_1C_line(f0, "<");		}		fprintf(OutputFile, "---\n");		while (nl_cnt1--) {			show_1C_line(f1, ">");		}	}	/* close the pertinent files */	fclose(f0);	fclose(f1);}static intprhead(const struct chunk *cnk) {	register int pos = 0;	pos += prs(cnk->ch_text->tx_fname);	pos += prs(": line ");	pos += pru(cnk->ch_first.ps_nl_cnt);	pos += prs("-");	pos += pru(cnk->ch_last.ps_nl_cnt - 1);	return pos;}static intprs(const char *str) {	fprintf(OutputFile, "%s", str);	return strlen(str);}static intpru(unsigned int u) {	fprintf(OutputFile, "%u", u);	return unslen(u);}static intunslen(unsigned int u) {	register int res = 1;	while (u > 9) {		u /= 10, res++;	}	return res;}static FILE *open_chunk(const struct chunk *cnk) {	/*	opens the file in which the chunk resides, positions the		file at the beginning of the chunk and returns the file pointer	*/	register char *fname = cnk->ch_text->tx_fname;	register FILE *f = fopen(fname, "r");	register unsigned int nl_cnt;	if (!f) {		fprintf(stderr, ">>>> File %s disappeared <<<<\n", fname);		f = fopen(NULLFILE, "r");	}	nl_cnt = cnk->ch_first.ps_nl_cnt;	while (nl_cnt > 1) {		int ch = getc(f);		if (ch < 0) break;		if (ch == '\n') {			nl_cnt--;		}	}	return f;}static voidfill_line(FILE *f, char ln[]) {	/*	Reads one line from f and puts it in condensed form in ln.	*/	register int indent = 0, lpos = 0;	register int ch;	/* condense and skip initial blank */	while ((ch = getc(f)), ch == ' ' || ch == '\t') {		if (ch == '\t') {			indent = 8;		}		else {			indent++;		}		if (indent == 8) {			/* every eight blanks give one blank */			if (lpos < maxline) {				ln[lpos++] = ' ';			}			indent = 0;		}	}	/* store the rest */	while (ch >= 0 && ch != '\n') {		if (ch == '\t') {			/* replace tabs by blanks */			ch = ' ';		}		if (lpos < maxline) {			ln[lpos++] = ch;		}		ch = getc(f);	}	ln[lpos] = '\0';		/* always room for this one */}static voidclear_line(char ln[]) {	/* a simple null byte will suffice */	ln[0] = '\0';}static voidshow_2C_line(const char ln0[], const char ln1[]) {	/*	displays the contents of the two lines in a two-column		format	*/	register int i;	for (i = 0; i < maxline && ln0[i] != '\0'; i++) {		fputc(ln0[i], OutputFile);	}	for (; i < maxline; i++) {		fputc(' ', OutputFile);	}	fprintf(OutputFile, " |");	for (i = 0; i < maxline && ln1[i] != '\0'; i++) {		fputc(ln1[i], OutputFile);	}	fprintf(OutputFile, "\n");}static voidshow_1C_line(FILE *f, const char *marker) {	/*	displays one line from f, preceded by the marker	*/	register int ch;	fprintf(OutputFile, "%s", marker);	while ((ch = getc(f)), ch > 0 && ch != '\n') {		fputc(ch, OutputFile);	}	fputc('\n', OutputFile);}#ifdef	DB_RUNstatic void db_chunk(const struct chunk *);static voiddb_run(const struct run *run) {	/* prints detailed data about a run */	register const struct chunk *cnk0 = &run->rn_cn0;	register const struct chunk *cnk1 = &run->rn_cn1;	fprintf(DebugFile, "File %s / file %s:\n",		cnk0->ch_text->tx_fname,		cnk1->ch_text->tx_fname	);	fprintf(DebugFile, "from token %u/%u to %u/%u:",		cnk0->ch_first.ps_tk_cnt, cnk1->ch_first.ps_tk_cnt,		cnk0->ch_last.ps_tk_cnt, cnk1->ch_last.ps_tk_cnt	);	fprintf(DebugFile, " from lines %u/%u to %u/%u:",		cnk0->ch_first.ps_nl_cnt, cnk1->ch_first.ps_nl_cnt,		cnk0->ch_last.ps_nl_cnt, cnk1->ch_last.ps_nl_cnt	);	fprintf(DebugFile, " %u %s\n",		run->rn_size,		(run->rn_size == 1 ? "token" : "tokens")	);	db_chunk(cnk0);	db_chunk(cnk1);}static voiddb_chunk(const struct chunk *cnk) {	/*	print the tokens in the chunk, with a one-char margin	*/	unsigned int i;	const struct position *first = &cnk->ch_first;	const struct position *last = &cnk->ch_last;	unsigned int start = cnk->ch_text->tx_start;	if (first->ps_tk_cnt > 0) {		fprintf(DebugFile, "...");		print_token(stdout, TokenArray[start + first->ps_tk_cnt - 1]);		fprintf(DebugFile, "  ");	}	else {	/* create same offset as above */		fprintf(DebugFile, "       ");	}	for (i = first->ps_tk_cnt; i <= last->ps_tk_cnt; i++) {		print_token(stdout, TokenArray[start + i]);	}	if (start + last->ps_tk_cnt + 1 < cnk->ch_text->tx_limit) {		fprintf(DebugFile, "  ");		print_token(stdout, TokenArray[start + last->ps_tk_cnt + 1]);		fprintf(DebugFile, "...");	}	fprintf(DebugFile, "\n");}#endif	/* DB_RUN */
 |