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 *);
- #endif
- static 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;
- void
- Pass3(void) {
- if (option_set('p')) {
- show_percentages();
- }
- else {
- show_runs();
- }
- }
- static void
- show_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 void
- show_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 int
- prhead(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 int
- prs(const char *str) {
- fprintf(OutputFile, "%s", str);
- return strlen(str);
- }
- static int
- pru(unsigned int u) {
- fprintf(OutputFile, "%u", u);
- return unslen(u);
- }
- static int
- unslen(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 void
- fill_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 void
- clear_line(char ln[]) {
- /* a simple null byte will suffice */
- ln[0] = '\0';
- }
- static void
- show_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 void
- show_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_RUN
- static void db_chunk(const struct chunk *);
- static void
- db_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 void
- db_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 */
|