Ejemplo n.º 1
0
static int makeTempFiles(void)
{
#if defined(DEBUGGING)
  psFileName = DEBUG_FILE("prehtml-ps");
  regionFileName = DEBUG_FILE("prehtml-region");
  imagePageName = DEBUG_FILE("prehtml-page");
  psPageName = DEBUG_FILE("prehtml-psn");
  troffFileName = DEBUG_FILE("prehtml-troff");
  htmlFileName = DEBUG_FILE("prehtml-html");
#else /* not DEBUGGING */
  FILE *f;

  /* psPageName contains a single page of postscript */
  f = xtmpfile(&psPageName,
	       PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT,
	       TRUE);
  if (f == NULL) {
    sys_fatal("xtmpfile");
    return -1;
  }
  fclose(f);

  /* imagePageName contains a bitmap image of the single postscript page */
  f = xtmpfile(&imagePageName,
	       PAGE_TEMPLATE_LONG, PAGE_TEMPLATE_SHORT,
	       TRUE);
  if (f == NULL) {
    sys_fatal("xtmpfile");
    return -1;
  }
  fclose(f);

  /* psFileName contains a postscript file of the complete document */
  f = xtmpfile(&psFileName,
	       PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT,
	       TRUE);
  if (f == NULL) {
    sys_fatal("xtmpfile");
    return -1;
  }
  fclose(f);

  /* regionFileName contains a list of the images and their boxed coordinates */
  f = xtmpfile(&regionFileName,
	       REGION_TEMPLATE_LONG, REGION_TEMPLATE_SHORT,
	       TRUE);
  if (f == NULL) {
    sys_fatal("xtmpfile");
    return -1;
  }
  fclose(f);

#endif /* not DEBUGGING */
  return 0;
}
Ejemplo n.º 2
0
FILE *xopen_seekable (const char *name, const char *mode)
{
	/* If it's seekable, good.  If not, we need to make it seekable. */
	FILE *f = xopen (name, mode);

	if (fseek (f, 0L, SEEK_SET) != 0) {
		const size_t buflen = 64 * 1024;
		char *buffer = xmalloc (buflen);
		FILE *tmp = xtmpfile();

		while (!feof (f)) {
			size_t count = fread (buffer, 1, buflen, f);
			if (count < 1)
				break;
			fwrite (buffer, count, 1, tmp);
		}

		free (buffer);
		fclose (f);

		f = tmp;
		fseek (f, 0L, SEEK_SET);
	}

	return f;
}
Ejemplo n.º 3
0
/* unzip if needed */
FILE *xopen_unzip (const char *name, const char *mode)
{
	char *p, *zprog = NULL;
	FILE *fi, *fo;
	const size_t buflen = 64 * 1024;
	char *buffer;
	pid_t pid;
	int status;
	int any_data = 0;

	p = strrchr(name, '.');
	if (p != NULL) {
		if (!strcmp (p, ".bz2"))
			zprog = "bzcat";
		else if (!strcmp(p, ".gz"))
			zprog = "zcat";
	}
	if (zprog == NULL)
		return xopen_seekable (name, mode);
	
	buffer = xmalloc (buflen);
	fo = xtmpfile();
	fi = xpipe(zprog, &pid, "r", zprog, name, NULL);
	
	while (!feof (fi)) {
		size_t count = fread (buffer, 1, buflen, fi);
		if (ferror (fi)) {
			perror(name);
			exit(1);
		}
		if (count < 1)
			break;
		
		fwrite (buffer, count, 1, fo);
		if (ferror (fo))
			error (EXIT_FAILURE, errno, "writing temp file");

		any_data = 1;
	}
	
	free (buffer);
	fclose (fi);
	
	waitpid (pid, &status, 0);
	if (any_data == 0 && WEXITSTATUS (status) != 0)
	{
		fclose (fo);
		exit (1);
	}

	fseek (fo, 0L, SEEK_SET);

	return fo;
}
Ejemplo n.º 4
0
int
mklock(char *file, pid_t pid, int uucpstyle)
{
	char	*tmp;
	int	retcode = FALSE;

	dprintf("%s: trying lock <%s> for process %ld\n", Pname, file,
	    (u_long)pid);
	if ((tmp = xtmpfile(file, pid, uucpstyle)) == (char *)NULL)
		return(FALSE);

linkloop:
	if (link(tmp, file) < 0) {
		switch(errno) {
		case EEXIST:
			dprintf("%s: lock <%s> already exists\n", Pname, file);
			if (cklock(file, uucpstyle)) {
				dprintf("%s: extant lock is valid\n", Pname);
				break;
			} else {
				dprintf("%s: lock is invalid, removing\n",
					Pname);
				if (unlink(file) < 0) {
					fprintf(stderr, E_unlk,
						Pname, file, strerror(errno));
					break;
				}
			}
			/*
			** I hereby profane the god of structured programming,
			** Edsgar Dijkstra
			*/
			goto linkloop;
		default:
			fprintf(stderr, "%s: link(%s, %s): %s\n",
				Pname, tmp, file, strerror(errno));
			break;
		}
	} else {
		dprintf("%s: got lock <%s>\n", Pname, file);
		retcode = TRUE;
	}
	if (unlink(tmp) < 0) {
		fprintf(stderr, E_unlk, Pname, tmp, strerror(errno));
	}
	return(retcode);
}
Ejemplo n.º 5
0
// `pl' is in inches
ps_printer::ps_printer(double pl)
: out(0, MAX_LINE_LENGTH),
  pages_output(0),
  sbuf_len(0),
  subencodings(0),
  output_hpos(-1),
  output_vpos(-1),
  line_thickness(-1),
  ndefined_styles(0),
  next_encoding_index(0),
  next_subencoding_index(0),
  ndefs(0),
  invis_count(0)
{
  tempfp = xtmpfile();
  out.set_file(tempfp);
  if (linewidth < 0)
    linewidth = DEFAULT_LINEWIDTH;
  if (font::hor != 1)
    fatal("horizontal resolution must be 1");
  if (font::vert != 1)
    fatal("vertical resolution must be 1");
  if (font::res % (font::sizescale*72) != 0)
    fatal("res must be a multiple of 72*sizescale");
  int r = font::res;
  int point = 0;
  while (r % 10 == 0) {
    r /= 10;
    point++;
  }
  res = r;
  out.set_fixed_point(point);
  space_glyph = name_to_glyph("space");
  if (pl == 0)
    paper_length = font::paperlength;
  else
    paper_length = int(pl * font::res + 0.5);
  if (paper_length == 0)
    paper_length = 11 * font::res;
  equalise_spaces = font::res >= 72000;
}
Ejemplo n.º 6
0
/*
 * Given a valid huffman mode, this function will generate the compression table that lists the codes for each
 * of the ascii characters that the compression scheme uses.  That table is placed into the pOutTable passed
 * in by the caller.
 *
 * Table will have 256 entries and look like:
 * 01001
 * 001
 * 0111
 * ...
 * 00001
 */
eFileCode GenerateTableAndCompressOrDecompress(eMode huffmanMode, const char *fileName)
{
    eFileCode fileCode; // And error code which tells if the operation was successful or not.

    FILE *pFile = fopen(fileName, "r"); // Open file for reading.
    fileCode = FILE_SUCCESS;

    // Check that file was successfully opened.  If not, return an error code.
    if (pFile == NULL)
    {
        return FILE_MISSING;
    }

    switch(huffmanMode)
    {
        case DECOMPRESS_MODE:
        {
            // If the file is a compressed huffman file, then use the get table for huff function to open it.
            char huffmanEncodings[ENTRIES * ENTRY_LENGTH];
            unsigned long long lengthOfFile =
                huffmanEncodingsFromFile(pFile, huffmanEncodings);

            huffResult resultArray[ENTRIES];
            createHuffResultArrayFromFileEncodings(huffmanEncodings, resultArray);
            huffNode huffmanTree[ENTRIES + ENTRIES - 1];
            createDecodeTreeFromResultArray(resultArray, huffmanTree);
            FILE *rle_file = xtmpfile();
            writeCompressedFileToNonCompressedOutput(pFile, rle_file, lengthOfFile, &huffmanTree[0]);

            rewind(rle_file);
            int nameLength = strlen(fileName) - strlen(".hurl");
            char newFileName[nameLength + 1];
            strncpy(newFileName, fileName, nameLength);
            newFileName[nameLength] = 0;
            FILE *pNewFile = xfopen(newFileName, "w");
            rle_decode(rle_file, pNewFile);

            fclose(rle_file);
            fclose(pNewFile);
            break;
        }

        case TABLE_MODE_HURL:
        {
            // If we want a table and the file is .hurl, it may or may not be the same .hurl we want it to be.
            // We'll try to treat it as a .hurl but if it's the wrong format, we will treat it like a generic
            // file.
            char huffmanEncodings[ENTRIES * ENTRY_LENGTH];
            huffmanEncodingsFromFile(pFile, huffmanEncodings);
            if (huffmanEncodings[0] != 0)
            {
                huffResult resultArray[ENTRIES];
                createHuffResultArrayFromFileEncodings(huffmanEncodings, resultArray);
                printHuffResultArray(resultArray);
            }
            else
            {
                // File was a .hurl, but internally format doesn't fit. Oh well, we can still generate a compression table.
                // Maybe someone else in the world created their own .hurl file format. We need to handle that format.
                fseek(pFile, 0, SEEK_SET);

                // The frequency of occurrence of each character in the uncompressed file.
                unsigned long long pFrequencies[ENTRIES];
                memset(pFrequencies, 0, sizeof(pFrequencies));
                if (GenerateFrequenciesForGeneric(pFile, pFrequencies) == FILE_SUCCESS)
                {
                    huffResult resultArray[ENTRIES];
                    fileCode = GetTableForGeneric(pFrequencies, resultArray);
                }
                else
                {
                    fileCode = FILE_INVALID_FORMAT;
                }
            }
            break;
        }

        case TABLE_MODE_GENERIC:
        {
            // If the file is not a .hurl, then generate frequencies and then a table for the file.
            // The frequency of occurrence of each character in the uncompressed file.
            unsigned long long pFrequencies[ENTRIES];
            memset(pFrequencies, 0, sizeof(pFrequencies));
            if (GenerateFrequenciesForGeneric(pFile, pFrequencies) == FILE_SUCCESS)
            {
                huffResult resultArray[ENTRIES];
                fileCode = GetTableForGeneric(pFrequencies, resultArray);
                printHuffResultArray(resultArray);
            }
            else
            {
                fileCode = FILE_INVALID_FORMAT;
            }
            break;
        }

        case COMPRESS_MODE:
        {
            FILE *rle_file = xtmpfile();

            rle_encode(pFile, rle_file);

            rewind(rle_file);
            unsigned long long pFrequencies[ENTRIES];
            memset(pFrequencies, 0, sizeof(pFrequencies));
            if (GenerateFrequenciesForGeneric(rle_file, pFrequencies) != FILE_SUCCESS)
            {
                fileCode = FILE_INVALID_FORMAT;
                break;
            }
            huffResult resultArray[ENTRIES];
            fileCode = GetTableForGeneric(pFrequencies, resultArray);
            char newFileName[strlen(fileName) + 6];
            strcpy(newFileName, fileName);
            FILE *pNewFile = fopen(strcat(newFileName, ".hurl"), "w+");

            if (pNewFile == NULL)
            {
                fileCode = FILE_INVALID_FORMAT;
                break;
            }
            writeNonCompressedFileToCompressedOutput(rle_file, pNewFile, resultArray);
            fclose(rle_file);
            fclose(pNewFile);
            break;
        }

        default:
        {
            // File must not be valid for the specified commandline options if we get this far.
            fileCode = FILE_INVALID_FORMAT;
            break;
        }
    }

    fclose(pFile);
    return fileCode;
}
Ejemplo n.º 7
0
static int
do_context (FILE *f, char **header, unsigned int num_headers,
            int match, char **line,
	    size_t *linelen, unsigned long *linenum,
	    unsigned long start_linenum, char status,
	    const char *bestname, const char *patchname,
	    int *orig_file_exists, int *new_file_exists)
{
	/* Skip before and after segments. */
	unsigned long line_start, line_end, line_count;
	unsigned long hunknum = 0;
	unsigned long track_linenum = 0;
	unsigned long changed[2];
	long munge_offset = 0;
	int header_displayed = 0;
	char *n, *end;
	int i;
	int hunk_match = 0;
	int displayed_filename = 0;
	unsigned long last_hunkmatch = 0;
	unsigned long hunk_linenum = *linenum;
	FILE *match_tmpf = NULL;
	int grepmatch = 0;
	int ret = 0;
	unsigned long unchanged;
	int first_hunk = 0;
	int orig_is_empty = 1, new_is_empty = 1; /* assume until otherwise */
	size_t got = 0;

	/* Context diff hunks are like this:
	 *
	 * *************** [GNU diff can put stuff here]
	 * *** start[,end] **** [we sometimes put stuff here]
	 *   from lines... (omitted if there are only insertions)
	 *[*************** [GNU diff can put stuff here]]
	 * --- start[,end] ----
	 *   to lines... (omitted if there are only deletions)
	 *[*** start[,end] ****
	 * ...]
	 *
	 * Both from and to lines may end with:
	 * \ No newline at end of file
	 */

	if (getline (line, linelen, f) == -1)
		return EOF;
	++*linenum;

	if (strncmp (*line, "***************", 15))
		return 1;

	if (getline (line, linelen, f) == -1)
		return EOF;
	++*linenum;

	if (output_matching == output_file)
		match_tmpf = xtmpfile ();

 next_hunk:
	unchanged = 0;
	changed[0] = changed[1] = 0; // for munge calculation

	for (i = 0; i < 2; i++) {
		int first = 1;

		if (i == 0)
			first_hunk = !header_displayed;

		if (!i && !strncmp (*line, "***************", 15)) {
			/* Some diffs seem to have this for every
			 * set of changes.  SuSV2 says not to,
			 * but the GNU diff info page disagrees. */
			i--;

			if (getline (line, linelen, f) == -1) {
			    ret = EOF;
			    goto out;
			}

			++*linenum;
			continue;
		}

		if (strncmp (*line, i ? "--- " : "*** ", 4)) {
			ret = 1;
			goto out;
		}

		if (!i) {
			hunknum++;
			hunk_linenum = *linenum;
			if (output_matching != output_file)
				grepmatch = 0;
			if (output_matching == output_hunk) {
				if (match_tmpf)
					fclose (match_tmpf);
				match_tmpf = xtmpfile ();
			}
		}

	do_line_counts:
		n = *line + 4;
		line_start = strtoul (n, &end, 10);
		if (n == end) {
			ret = 1;
			goto out;
		}

		if (*end == ',') {
			n = end + 1;
			line_end = strtoul (n, &end, 10);
			if (n == end) {
				ret = 1;
				goto out;
			}

			if (line_start > line_end) {
				ret = 1;
				goto out;
			}

			line_count = line_end - line_start + 1;
		} else {
			line_end = line_start;
			line_count = line_start ? 1 : 0;
		}

		n = strchr (n, '*');
		if (n)
			n += 4;

		if (!i) {
			if (match)
				hunk_match = hunk_matches (line_start,
							   line_count,
							   hunknum);
			else hunk_match = 0;

			if (hunk_match && numbering && verbose &&
			    mode != mode_grep) {
				if (print_patchnames)
					printf ("%s-", patchname);
				printf ("\t%lu\tHunk #%lu\n",
					hunk_linenum, hunknum);
			}
		}

		if (hunk_match &&
		    (mode == mode_filter || output_matching != output_none)) {
			FILE *output_to= stdout;

			if (mode == mode_grep && !grepmatch)
				output_to = match_tmpf;

			// Display the line counts.
			if (!header_displayed && mode == mode_filter) {
                                unsigned int i;
                                for (i = 0; i < num_headers - 2; i++)
                                        output_header_line (header[i]);
				if (number_lines != After)
					output_header_line (header[num_headers - 2]);
				if (number_lines != Before)
					output_header_line (header[num_headers - 1]);
				header_displayed = 1;
			}

			if (number_lines == None) switch (i) {
			case 0:
				fputs ("***************\n", output_to);
				fprintf (output_to, "*** %lu", line_start);
				if (line_end != line_start)
					fprintf (output_to, ",%lu", line_end);
				fputs (" ****", output_to);

				if (annotating)
					fprintf (output_to,
						 " Hunk #%lu, %s\n",
						 hunknum, bestname);
				else if (n)
					fputs (n, output_to);
				else
					fputc ('\n', output_to);

				break;
			case 1:
				fprintf (output_to, "--- %lu",
					 line_start + munge_offset);
				if (line_end != line_start)
					fprintf (output_to, ",%lu",
						 line_end + munge_offset);
				fputs (" ----\n", output_to);
				break;
			}

			switch (number_lines) {
			case None:
				break;

			case Before:
				if (i != 0)
					break;

				// Note the initial line number.
				track_linenum = line_start;
				if (!first_hunk ||
				    (output_matching == output_file &&
				     hunknum > 1))
					fputs ("...\n", output_to);
				break;

			case After:
				if (i != 1)
					break;

				track_linenum = line_start + munge_offset;
				if (!first_hunk ||
				    (output_matching == output_file &&
				     hunknum > 1))
					fputs ("...\n", output_to);
				break;
			}
		}

		got = getline (line, linelen, f);
		if (got == -1) {
			ret = EOF;
			goto out;
		}

		++*linenum;

		if (i && line_count == unchanged)
			break;

		while ((line_count == 0 && **line == '\\') ||
		       line_count--) {
			if (hunk_match && mode == mode_grep &&
			    !regexecs (regex, num_regex, *line + 2,
				       0, NULL, 0)) {
				if (output_matching == output_none) {
					if (!displayed_filename) {
						displayed_filename = 1;
						display_filename(start_linenum,
								 status,
								 bestname,
								 patchname);
					}

					if (numbering && verbose &&
					    hunknum > last_hunkmatch) {
						last_hunkmatch = hunknum;
						if (print_patchnames)
							printf ("%s-",
								patchname);
						printf ("\t%lu\tHunk #%lu\n",
							hunk_linenum, hunknum);
					}
				} else {
					if (!header_displayed) {
                                                unsigned int i;
                                                for (i = 0; i < num_headers - 2; i++)
                                                        output_header_line (header[i]);
						if (number_lines != After)
							output_header_line (header[num_headers - 2]);
						if (number_lines != Before)
							output_header_line (header[num_headers - 1]);
						header_displayed = 1;
					}

					if (match_tmpf) {
						rewind (match_tmpf);
						while (!feof (match_tmpf)) {
							int ch;
							ch = fgetc(match_tmpf);
							if (ch == EOF)
								break;
							putchar (ch);
						}
						fclose (match_tmpf);
						match_tmpf = NULL;
					}

					grepmatch = 1;
				}
			}

			if (!i && first) {
				first = 0;
				if (!strncmp (*line, "--- ", 4)) {
					/* From lines were
					 * omitted. */
					i++;
					goto do_line_counts;
				}
			}

			if (**line == ' ')
				unchanged++;

			if (empty_files_as_absent) switch (**line) {
			case ' ':
			case '!':
				new_is_empty = orig_is_empty = 0;
				break;
			case '+':
				new_is_empty = 0;
				break;
			case '-':
				orig_is_empty = 0;
				break;
			}

			if (hunk_match &&
			    (mode == mode_filter ||
			     output_matching != output_none)) {
				FILE *output_to = stdout;
				if (mode == mode_grep && !grepmatch)
					output_to = match_tmpf;

				if (number_lines == None)
					fwrite (*line, (size_t) got,
						1, output_to);
				else if ((number_lines == Before && !i) ||
					 (number_lines == After && i)) {
					fprintf (output_to, "%lu\t:",
						 track_linenum++);
					fwrite (2 + *line, (size_t) got - 2,
						1, output_to);
				}
			}

			if ((mode == mode_filter && !hunk_match) ||
			    output_matching == output_hunk)
				switch (**line) {
				case '!':
				case '\\':
					changed[i]++;
					break;
				case '+':
					changed[1]++;
					break;
				case '-':
					changed[0]++;
					break;
				}

			got = getline (line, linelen, f);
			if (got == -1) {
				ret = EOF;
				goto out;
			}

			++*linenum;
		}
	}

	if (output_matching != output_hunk || !grepmatch)
		munge_offset += changed[0] - changed[1];
	goto next_hunk;

out:
	if (match_tmpf)
		fclose (match_tmpf);

	if (empty_files_as_absent) {
		if (orig_file_exists != NULL && orig_is_empty)
			*orig_file_exists = 0;
		if (new_file_exists != NULL && new_is_empty)
			*new_file_exists = 0;
	}

	return ret;
}
Ejemplo n.º 8
0
static int
do_unified (FILE *f, char **header, unsigned int num_headers,
            int match, char **line,
	    size_t *linelen, unsigned long *linenum,
	    unsigned long start_linenum, char status,
	    const char *bestname, const char *patchname,
	    int *orig_file_exists, int *new_file_exists)
{
	/* Skip hunk. */
	unsigned long orig_count = 0, new_count = 0;
	unsigned long orig_offset, new_offset;
	unsigned long hunknum = 0;
	unsigned long track_linenum = 0;
	int header_displayed = 0;
	int hunk_match = match;
	long munge_offset = 0;
	int displayed_filename = 0;
	unsigned long last_hunkmatch = 0;
	unsigned long hunk_linenum = *linenum;
	FILE *match_tmpf = NULL;
	int grepmatch = 0;
	long delayed_munge = 0;
	int ret = 0;
	int orig_is_empty = 1, new_is_empty = 1; /* assume until otherwise */

	if (output_matching == output_file)
		match_tmpf = xtmpfile ();

	for (;;) {
		ssize_t got = getline (line, linelen, f);
		if (got == -1) {
			ret = EOF;
			goto out;
		}
		++*linenum;

		if (!orig_count && !new_count && **line != '\\') {
			char *trailing;

			if (strncmp (*line, "@@ ", 3))
				break;

			/* Next chunk. */
			hunknum++;
			hunk_linenum = *linenum;

			if (output_matching == output_hunk && !grepmatch)
				// We are missing this hunk out, but
				// we need to remember how many lines
				// it would have added or removed.
				munge_offset += delayed_munge;

			if (output_matching != output_file)
				grepmatch = 0;
			if (output_matching == output_hunk) {
				if (match_tmpf)
					fclose (match_tmpf);
				match_tmpf = xtmpfile ();
			}

			if (read_atatline (*line, &orig_offset, &orig_count,
					   &new_offset, &new_count))
				error (EXIT_FAILURE, 0,
				      "line not understood: %s", *line);

			if (orig_count)
				orig_is_empty = 0;
			if (new_count)
				new_is_empty = 0;

			// Decide if this hunk matches.
			if (match)
				hunk_match = hunk_matches (orig_offset,
							   orig_count,
							   hunknum);
			else hunk_match = 0;

			trailing = strchr (*line, '+');
			trailing += strcspn (trailing, " \n");
			if (*trailing == ' ')
				trailing++;
			trailing += strspn (trailing, "@");

			if (hunk_match && numbering && verbose &&
			    mode != mode_grep) {
				if (print_patchnames)
					printf ("%s-", patchname);
				printf ("\t%lu\tHunk #%lu",
					hunk_linenum, hunknum);
				if (verbose > 1) {
					char *p = trailing;
					if (*p != '\n')
						p++;
					printf ("\t%s", p);
				} else
					putchar ('\n');
			}

			if (hunk_match &&
			    (mode == mode_filter ||
			     output_matching != output_none)) {
				int first_hunk = !header_displayed;
				FILE *output_to = stdout;

				if (mode == mode_grep) {
					delayed_munge = orig_count - new_count;
					if (!grepmatch)
						output_to = match_tmpf;
				}

				if (!header_displayed &&
				    mode != mode_grep) {
					// Display the header.
                                        unsigned int i;
                                        for (i = 0; i < num_headers - 2; i++)
                                                output_header_line (header[i]);
					if (number_lines != After)
						output_header_line (header[num_headers - 2]);
					if (number_lines != Before)
						output_header_line (header[num_headers - 1]);
					header_displayed = 1;
				}
				switch (number_lines) {
				case None:
					// Display the offsets and
					// counts, adjusting for any
					// hunks we've previously
					// missed out.
					fprintf (output_to,
						 "@@ -%lu", orig_offset);
					if (orig_count != 1)
						fprintf (output_to,
							 ",%lu", orig_count);
					fprintf (output_to, " +%lu",
						 new_offset + munge_offset);
					if (new_count != 1)
						fprintf (output_to,
							 ",%lu", new_count);
					fprintf (output_to, " @@");

					if (annotating)
						fprintf (output_to,
							 " Hunk #%lu, %s",
							 hunknum, bestname);

					if (clean_comments)
						fputs ("\n", output_to);
					else {
						int idx = trailing - *line;
						fwrite (trailing, (size_t) got-idx,
							1, output_to);
					}
					break;
				case Before:
					// Note the initial line number
					track_linenum = orig_offset;
					if (!first_hunk ||
					    (output_matching == output_file &&
					     hunknum > 1))
						fputs ("...\n", output_to);
					break;
				case After:
					// Note the initial line number
					track_linenum = (new_offset +
							 munge_offset);
					if (!first_hunk ||
					    (output_matching == output_file &&
					     hunknum > 1))
						fputs ("...\n", output_to);
					break;
				}
			} else if (mode == mode_filter)
				// We are missing this hunk out, but
				// we need to remember how many lines
				// it would have added or removed.
				munge_offset += orig_count - new_count;

			continue;
		}

		if (**line != '\\') {
			if (orig_count && **line != '+')
				orig_count--;
			if (new_count && **line != '-')
				new_count--;
		}

		if (hunk_match && mode == mode_grep &&
		    !regexecs (regex, num_regex, *line + 1, 0, NULL, 0)) {
			if (output_matching == output_none) {
				if (!displayed_filename) {
					displayed_filename = 1;
					display_filename (start_linenum,
							  status, bestname,
							  patchname);
				}

				if (numbering && verbose &&
				    hunknum > last_hunkmatch) {
					last_hunkmatch = hunknum;
					if (print_patchnames)
						printf ("%s-", patchname);
					printf ("\t%lu\tHunk #%lu\n",
						hunk_linenum, hunknum);
				}
			} else {
				if (match_tmpf) {
                                        if (!header_displayed) {
                                                unsigned int i;
                                                for (i = 0; i < num_headers - 2; i++)
                                                        output_header_line (header[i]);
                                                if (number_lines != After)
                                                        output_header_line (header[num_headers - 2]);
                                                if (number_lines != Before)
                                                        output_header_line (header[num_headers - 1]);
						header_displayed = 1;
                                        }

					rewind (match_tmpf);
					while (!feof (match_tmpf)) {
						int ch = fgetc (match_tmpf);
						if (ch == EOF)
							break;
						putchar (ch);
					}
					fclose (match_tmpf);
					match_tmpf = NULL;
				}
				grepmatch = 1;
			}
		}

		if (hunk_match &&
		    (mode == mode_filter ||
		     output_matching != output_none)) {
			FILE *output_to = stdout;
			if (mode == mode_grep && !grepmatch)
				output_to = match_tmpf;
			if (number_lines == None)
				// Just display each line.
				fwrite (*line, (size_t) got, 1, output_to);
			else if ((number_lines == Before && **line != '+') ||
				 (number_lines == After && **line != '-')) {
				// Numbered line.
                                const char *rest = *line;
                                if (rest[0] != '\n')
                                        // Handle whitespace damage
                                        rest++;

				fprintf (output_to, "%lu\t:%s",
					 track_linenum++, rest);
                        }
		}
	}

 out:
	if (match_tmpf)
		fclose (match_tmpf);

	if (empty_files_as_absent) {
		if (orig_file_exists != NULL && orig_is_empty)
			*orig_file_exists = 0;
		if (new_file_exists != NULL && new_is_empty)
			*new_file_exists = 0;
	}

	return ret;
}