1*0b459c2cSDavid du Colombier /* Shared definitions for GNU DIFF 2*0b459c2cSDavid du Colombier Copyright (C) 1988, 89, 91, 92, 93 Free Software Foundation, Inc. 3*0b459c2cSDavid du Colombier 4*0b459c2cSDavid du Colombier This file is part of GNU DIFF. 5*0b459c2cSDavid du Colombier 6*0b459c2cSDavid du Colombier GNU DIFF is free software; you can redistribute it and/or modify 7*0b459c2cSDavid du Colombier it under the terms of the GNU General Public License as published by 8*0b459c2cSDavid du Colombier the Free Software Foundation; either version 2, or (at your option) 9*0b459c2cSDavid du Colombier any later version. 10*0b459c2cSDavid du Colombier 11*0b459c2cSDavid du Colombier GNU DIFF is distributed in the hope that it will be useful, 12*0b459c2cSDavid du Colombier but WITHOUT ANY WARRANTY; without even the implied warranty of 13*0b459c2cSDavid du Colombier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*0b459c2cSDavid du Colombier GNU General Public License for more details. 15*0b459c2cSDavid du Colombier 16*0b459c2cSDavid du Colombier You should have received a copy of the GNU General Public License 17*0b459c2cSDavid du Colombier along with GNU DIFF; see the file COPYING. If not, write to 18*0b459c2cSDavid du Colombier the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19*0b459c2cSDavid du Colombier 20*0b459c2cSDavid du Colombier #include "system.h" 21*0b459c2cSDavid du Colombier #include <stdio.h> 22*0b459c2cSDavid du Colombier #ifdef __FreeBSD__ 23*0b459c2cSDavid du Colombier #include <gnuregex.h> 24*0b459c2cSDavid du Colombier #else 25*0b459c2cSDavid du Colombier #include "regex.h" 26*0b459c2cSDavid du Colombier #endif 27*0b459c2cSDavid du Colombier 28*0b459c2cSDavid du Colombier #define TAB_WIDTH 8 29*0b459c2cSDavid du Colombier 30*0b459c2cSDavid du Colombier /* Variables for command line options */ 31*0b459c2cSDavid du Colombier 32*0b459c2cSDavid du Colombier #ifndef GDIFF_MAIN 33*0b459c2cSDavid du Colombier #define EXTERN extern 34*0b459c2cSDavid du Colombier #else 35*0b459c2cSDavid du Colombier #define EXTERN 36*0b459c2cSDavid du Colombier #endif 37*0b459c2cSDavid du Colombier 38*0b459c2cSDavid du Colombier enum output_style { 39*0b459c2cSDavid du Colombier /* Default output style. */ 40*0b459c2cSDavid du Colombier OUTPUT_NORMAL, 41*0b459c2cSDavid du Colombier /* Output the differences with lines of context before and after (-c). */ 42*0b459c2cSDavid du Colombier OUTPUT_CONTEXT, 43*0b459c2cSDavid du Colombier /* Output the differences in a unified context diff format (-u). */ 44*0b459c2cSDavid du Colombier OUTPUT_UNIFIED, 45*0b459c2cSDavid du Colombier /* Output the differences as commands suitable for `ed' (-e). */ 46*0b459c2cSDavid du Colombier OUTPUT_ED, 47*0b459c2cSDavid du Colombier /* Output the diff as a forward ed script (-f). */ 48*0b459c2cSDavid du Colombier OUTPUT_FORWARD_ED, 49*0b459c2cSDavid du Colombier /* Like -f, but output a count of changed lines in each "command" (-n). */ 50*0b459c2cSDavid du Colombier OUTPUT_RCS, 51*0b459c2cSDavid du Colombier /* Output merged #ifdef'd file (-D). */ 52*0b459c2cSDavid du Colombier OUTPUT_IFDEF, 53*0b459c2cSDavid du Colombier /* Output sdiff style (-y). */ 54*0b459c2cSDavid du Colombier OUTPUT_SDIFF 55*0b459c2cSDavid du Colombier }; 56*0b459c2cSDavid du Colombier 57*0b459c2cSDavid du Colombier /* True for output styles that are robust, 58*0b459c2cSDavid du Colombier i.e. can handle a file that ends in a non-newline. */ 59*0b459c2cSDavid du Colombier #define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED) 60*0b459c2cSDavid du Colombier 61*0b459c2cSDavid du Colombier EXTERN enum output_style output_style; 62*0b459c2cSDavid du Colombier 63*0b459c2cSDavid du Colombier /* Nonzero if output cannot be generated for identical files. */ 64*0b459c2cSDavid du Colombier EXTERN int no_diff_means_no_output; 65*0b459c2cSDavid du Colombier 66*0b459c2cSDavid du Colombier /* Number of lines of context to show in each set of diffs. 67*0b459c2cSDavid du Colombier This is zero when context is not to be shown. */ 68*0b459c2cSDavid du Colombier EXTERN int context; 69*0b459c2cSDavid du Colombier 70*0b459c2cSDavid du Colombier /* Consider all files as text files (-a). 71*0b459c2cSDavid du Colombier Don't interpret codes over 0177 as implying a "binary file". */ 72*0b459c2cSDavid du Colombier EXTERN int always_text_flag; 73*0b459c2cSDavid du Colombier 74*0b459c2cSDavid du Colombier /* Number of lines to keep in identical prefix and suffix. */ 75*0b459c2cSDavid du Colombier EXTERN int horizon_lines; 76*0b459c2cSDavid du Colombier 77*0b459c2cSDavid du Colombier /* Ignore changes in horizontal white space (-b). */ 78*0b459c2cSDavid du Colombier EXTERN int ignore_space_change_flag; 79*0b459c2cSDavid du Colombier 80*0b459c2cSDavid du Colombier /* Ignore all horizontal white space (-w). */ 81*0b459c2cSDavid du Colombier EXTERN int ignore_all_space_flag; 82*0b459c2cSDavid du Colombier 83*0b459c2cSDavid du Colombier /* Ignore changes that affect only blank lines (-B). */ 84*0b459c2cSDavid du Colombier EXTERN int ignore_blank_lines_flag; 85*0b459c2cSDavid du Colombier 86*0b459c2cSDavid du Colombier /* 1 if lines may match even if their contents do not match exactly. 87*0b459c2cSDavid du Colombier This depends on various options. */ 88*0b459c2cSDavid du Colombier EXTERN int ignore_some_line_changes; 89*0b459c2cSDavid du Colombier 90*0b459c2cSDavid du Colombier /* 1 if files may match even if their contents are not byte-for-byte identical. 91*0b459c2cSDavid du Colombier This depends on various options. */ 92*0b459c2cSDavid du Colombier EXTERN int ignore_some_changes; 93*0b459c2cSDavid du Colombier 94*0b459c2cSDavid du Colombier /* Ignore differences in case of letters (-i). */ 95*0b459c2cSDavid du Colombier EXTERN int ignore_case_flag; 96*0b459c2cSDavid du Colombier 97*0b459c2cSDavid du Colombier /* File labels for `-c' output headers (-L). */ 98*0b459c2cSDavid du Colombier EXTERN char *file_label[2]; 99*0b459c2cSDavid du Colombier 100*0b459c2cSDavid du Colombier struct regexp_list 101*0b459c2cSDavid du Colombier { 102*0b459c2cSDavid du Colombier struct re_pattern_buffer buf; 103*0b459c2cSDavid du Colombier struct regexp_list *next; 104*0b459c2cSDavid du Colombier }; 105*0b459c2cSDavid du Colombier 106*0b459c2cSDavid du Colombier /* Regexp to identify function-header lines (-F). */ 107*0b459c2cSDavid du Colombier EXTERN struct regexp_list *function_regexp_list; 108*0b459c2cSDavid du Colombier 109*0b459c2cSDavid du Colombier /* Ignore changes that affect only lines matching this regexp (-I). */ 110*0b459c2cSDavid du Colombier EXTERN struct regexp_list *ignore_regexp_list; 111*0b459c2cSDavid du Colombier 112*0b459c2cSDavid du Colombier /* Say only whether files differ, not how (-q). */ 113*0b459c2cSDavid du Colombier EXTERN int no_details_flag; 114*0b459c2cSDavid du Colombier 115*0b459c2cSDavid du Colombier /* Report files compared that match (-s). 116*0b459c2cSDavid du Colombier Normally nothing is output when that happens. */ 117*0b459c2cSDavid du Colombier EXTERN int print_file_same_flag; 118*0b459c2cSDavid du Colombier 119*0b459c2cSDavid du Colombier /* Output the differences with exactly 8 columns added to each line 120*0b459c2cSDavid du Colombier so that any tabs in the text line up properly (-T). */ 121*0b459c2cSDavid du Colombier EXTERN int tab_align_flag; 122*0b459c2cSDavid du Colombier 123*0b459c2cSDavid du Colombier /* Expand tabs in the output so the text lines up properly 124*0b459c2cSDavid du Colombier despite the characters added to the front of each line (-t). */ 125*0b459c2cSDavid du Colombier EXTERN int tab_expand_flag; 126*0b459c2cSDavid du Colombier 127*0b459c2cSDavid du Colombier /* In directory comparison, specify file to start with (-S). 128*0b459c2cSDavid du Colombier All file names less than this name are ignored. */ 129*0b459c2cSDavid du Colombier EXTERN char *dir_start_file; 130*0b459c2cSDavid du Colombier 131*0b459c2cSDavid du Colombier /* If a file is new (appears in only one dir) 132*0b459c2cSDavid du Colombier include its entire contents (-N). 133*0b459c2cSDavid du Colombier Then `patch' would create the file with appropriate contents. */ 134*0b459c2cSDavid du Colombier EXTERN int entire_new_file_flag; 135*0b459c2cSDavid du Colombier 136*0b459c2cSDavid du Colombier /* If a file is new (appears in only the second dir) 137*0b459c2cSDavid du Colombier include its entire contents (-P). 138*0b459c2cSDavid du Colombier Then `patch' would create the file with appropriate contents. */ 139*0b459c2cSDavid du Colombier EXTERN int unidirectional_new_file_flag; 140*0b459c2cSDavid du Colombier 141*0b459c2cSDavid du Colombier /* Pipe each file's output through pr (-l). */ 142*0b459c2cSDavid du Colombier EXTERN int paginate_flag; 143*0b459c2cSDavid du Colombier 144*0b459c2cSDavid du Colombier enum line_class { 145*0b459c2cSDavid du Colombier /* Lines taken from just the first file. */ 146*0b459c2cSDavid du Colombier OLD, 147*0b459c2cSDavid du Colombier /* Lines taken from just the second file. */ 148*0b459c2cSDavid du Colombier NEW, 149*0b459c2cSDavid du Colombier /* Lines common to both files. */ 150*0b459c2cSDavid du Colombier UNCHANGED, 151*0b459c2cSDavid du Colombier /* A hunk containing both old and new lines (line groups only). */ 152*0b459c2cSDavid du Colombier CHANGED 153*0b459c2cSDavid du Colombier }; 154*0b459c2cSDavid du Colombier 155*0b459c2cSDavid du Colombier /* Line group formats for old, new, unchanged, and changed groups. */ 156*0b459c2cSDavid du Colombier EXTERN char *group_format[CHANGED + 1]; 157*0b459c2cSDavid du Colombier 158*0b459c2cSDavid du Colombier /* Line formats for old, new, and unchanged lines. */ 159*0b459c2cSDavid du Colombier EXTERN char *line_format[UNCHANGED + 1]; 160*0b459c2cSDavid du Colombier 161*0b459c2cSDavid du Colombier /* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */ 162*0b459c2cSDavid du Colombier EXTERN int sdiff_help_sdiff; 163*0b459c2cSDavid du Colombier 164*0b459c2cSDavid du Colombier /* Tell OUTPUT_SDIFF to show only the left version of common lines. */ 165*0b459c2cSDavid du Colombier EXTERN int sdiff_left_only; 166*0b459c2cSDavid du Colombier 167*0b459c2cSDavid du Colombier /* Tell OUTPUT_SDIFF to not show common lines. */ 168*0b459c2cSDavid du Colombier EXTERN int sdiff_skip_common_lines; 169*0b459c2cSDavid du Colombier 170*0b459c2cSDavid du Colombier /* The half line width and column 2 offset for OUTPUT_SDIFF. */ 171*0b459c2cSDavid du Colombier EXTERN unsigned sdiff_half_width; 172*0b459c2cSDavid du Colombier EXTERN unsigned sdiff_column2_offset; 173*0b459c2cSDavid du Colombier 174*0b459c2cSDavid du Colombier /* String containing all the command options diff received, 175*0b459c2cSDavid du Colombier with spaces between and at the beginning but none at the end. 176*0b459c2cSDavid du Colombier If there were no options given, this string is empty. */ 177*0b459c2cSDavid du Colombier EXTERN char * switch_string; 178*0b459c2cSDavid du Colombier 179*0b459c2cSDavid du Colombier /* Nonzero means use heuristics for better speed. */ 180*0b459c2cSDavid du Colombier EXTERN int heuristic; 181*0b459c2cSDavid du Colombier 182*0b459c2cSDavid du Colombier /* Name of program the user invoked (for error messages). */ 183*0b459c2cSDavid du Colombier EXTERN char *program_name; 184*0b459c2cSDavid du Colombier 185*0b459c2cSDavid du Colombier /* The result of comparison is an "edit script": a chain of `struct change'. 186*0b459c2cSDavid du Colombier Each `struct change' represents one place where some lines are deleted 187*0b459c2cSDavid du Colombier and some are inserted. 188*0b459c2cSDavid du Colombier 189*0b459c2cSDavid du Colombier LINE0 and LINE1 are the first affected lines in the two files (origin 0). 190*0b459c2cSDavid du Colombier DELETED is the number of lines deleted here from file 0. 191*0b459c2cSDavid du Colombier INSERTED is the number of lines inserted here in file 1. 192*0b459c2cSDavid du Colombier 193*0b459c2cSDavid du Colombier If DELETED is 0 then LINE0 is the number of the line before 194*0b459c2cSDavid du Colombier which the insertion was done; vice versa for INSERTED and LINE1. */ 195*0b459c2cSDavid du Colombier 196*0b459c2cSDavid du Colombier struct change 197*0b459c2cSDavid du Colombier { 198*0b459c2cSDavid du Colombier struct change *link; /* Previous or next edit command */ 199*0b459c2cSDavid du Colombier int inserted; /* # lines of file 1 changed here. */ 200*0b459c2cSDavid du Colombier int deleted; /* # lines of file 0 changed here. */ 201*0b459c2cSDavid du Colombier int line0; /* Line number of 1st deleted line. */ 202*0b459c2cSDavid du Colombier int line1; /* Line number of 1st inserted line. */ 203*0b459c2cSDavid du Colombier char ignore; /* Flag used in context.c */ 204*0b459c2cSDavid du Colombier }; 205*0b459c2cSDavid du Colombier 206*0b459c2cSDavid du Colombier /* Structures that describe the input files. */ 207*0b459c2cSDavid du Colombier 208*0b459c2cSDavid du Colombier /* Data on one input file being compared. */ 209*0b459c2cSDavid du Colombier 210*0b459c2cSDavid du Colombier struct file_data { 211*0b459c2cSDavid du Colombier int desc; /* File descriptor */ 212*0b459c2cSDavid du Colombier char const *name; /* File name */ 213*0b459c2cSDavid du Colombier struct stat stat; /* File status from fstat() */ 214*0b459c2cSDavid du Colombier int dir_p; /* nonzero if file is a directory */ 215*0b459c2cSDavid du Colombier 216*0b459c2cSDavid du Colombier /* Buffer in which text of file is read. */ 217*0b459c2cSDavid du Colombier char * buffer; 218*0b459c2cSDavid du Colombier /* Allocated size of buffer. */ 219*0b459c2cSDavid du Colombier size_t bufsize; 220*0b459c2cSDavid du Colombier /* Number of valid characters now in the buffer. */ 221*0b459c2cSDavid du Colombier size_t buffered_chars; 222*0b459c2cSDavid du Colombier 223*0b459c2cSDavid du Colombier /* Array of pointers to lines in the file. */ 224*0b459c2cSDavid du Colombier char const **linbuf; 225*0b459c2cSDavid du Colombier 226*0b459c2cSDavid du Colombier /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines. 227*0b459c2cSDavid du Colombier linebuf[linbuf_base ... buffered_lines - 1] are possibly differing. 228*0b459c2cSDavid du Colombier linebuf[linbuf_base ... valid_lines - 1] contain valid data. 229*0b459c2cSDavid du Colombier linebuf[linbuf_base ... alloc_lines - 1] are allocated. */ 230*0b459c2cSDavid du Colombier int linbuf_base, buffered_lines, valid_lines, alloc_lines; 231*0b459c2cSDavid du Colombier 232*0b459c2cSDavid du Colombier /* Pointer to end of prefix of this file to ignore when hashing. */ 233*0b459c2cSDavid du Colombier char const *prefix_end; 234*0b459c2cSDavid du Colombier 235*0b459c2cSDavid du Colombier /* Count of lines in the prefix. 236*0b459c2cSDavid du Colombier There are this many lines in the file before linbuf[0]. */ 237*0b459c2cSDavid du Colombier int prefix_lines; 238*0b459c2cSDavid du Colombier 239*0b459c2cSDavid du Colombier /* Pointer to start of suffix of this file to ignore when hashing. */ 240*0b459c2cSDavid du Colombier char const *suffix_begin; 241*0b459c2cSDavid du Colombier 242*0b459c2cSDavid du Colombier /* Vector, indexed by line number, containing an equivalence code for 243*0b459c2cSDavid du Colombier each line. It is this vector that is actually compared with that 244*0b459c2cSDavid du Colombier of another file to generate differences. */ 245*0b459c2cSDavid du Colombier int *equivs; 246*0b459c2cSDavid du Colombier 247*0b459c2cSDavid du Colombier /* Vector, like the previous one except that 248*0b459c2cSDavid du Colombier the elements for discarded lines have been squeezed out. */ 249*0b459c2cSDavid du Colombier int *undiscarded; 250*0b459c2cSDavid du Colombier 251*0b459c2cSDavid du Colombier /* Vector mapping virtual line numbers (not counting discarded lines) 252*0b459c2cSDavid du Colombier to real ones (counting those lines). Both are origin-0. */ 253*0b459c2cSDavid du Colombier int *realindexes; 254*0b459c2cSDavid du Colombier 255*0b459c2cSDavid du Colombier /* Total number of nondiscarded lines. */ 256*0b459c2cSDavid du Colombier int nondiscarded_lines; 257*0b459c2cSDavid du Colombier 258*0b459c2cSDavid du Colombier /* Vector, indexed by real origin-0 line number, 259*0b459c2cSDavid du Colombier containing 1 for a line that is an insertion or a deletion. 260*0b459c2cSDavid du Colombier The results of comparison are stored here. */ 261*0b459c2cSDavid du Colombier char *changed_flag; 262*0b459c2cSDavid du Colombier 263*0b459c2cSDavid du Colombier /* 1 if file ends in a line with no final newline. */ 264*0b459c2cSDavid du Colombier int missing_newline; 265*0b459c2cSDavid du Colombier 266*0b459c2cSDavid du Colombier /* 1 more than the maximum equivalence value used for this or its 267*0b459c2cSDavid du Colombier sibling file. */ 268*0b459c2cSDavid du Colombier int equiv_max; 269*0b459c2cSDavid du Colombier }; 270*0b459c2cSDavid du Colombier 271*0b459c2cSDavid du Colombier /* Describe the two files currently being compared. */ 272*0b459c2cSDavid du Colombier 273*0b459c2cSDavid du Colombier EXTERN struct file_data files[2]; 274*0b459c2cSDavid du Colombier 275*0b459c2cSDavid du Colombier /* Stdio stream to output diffs to. */ 276*0b459c2cSDavid du Colombier 277*0b459c2cSDavid du Colombier EXTERN FILE *outfile; 278*0b459c2cSDavid du Colombier 279*0b459c2cSDavid du Colombier /* Declare various functions. */ 280*0b459c2cSDavid du Colombier 281*0b459c2cSDavid du Colombier /* analyze.c */ 282*0b459c2cSDavid du Colombier int diff_2_files PARAMS((struct file_data[], int)); 283*0b459c2cSDavid du Colombier 284*0b459c2cSDavid du Colombier /* context.c */ 285*0b459c2cSDavid du Colombier void print_context_header PARAMS((struct file_data[], int)); 286*0b459c2cSDavid du Colombier void print_context_script PARAMS((struct change *, int)); 287*0b459c2cSDavid du Colombier 288*0b459c2cSDavid du Colombier /* diff.c */ 289*0b459c2cSDavid du Colombier int excluded_filename PARAMS((char const *)); 290*0b459c2cSDavid du Colombier 291*0b459c2cSDavid du Colombier /* dir.c */ 292*0b459c2cSDavid du Colombier int diff_dirs PARAMS((struct file_data const[], int (*) PARAMS((char const *, char const *, char const *, char const *, int)), int)); 293*0b459c2cSDavid du Colombier 294*0b459c2cSDavid du Colombier /* ed.c */ 295*0b459c2cSDavid du Colombier void print_ed_script PARAMS((struct change *)); 296*0b459c2cSDavid du Colombier void pr_forward_ed_script PARAMS((struct change *)); 297*0b459c2cSDavid du Colombier 298*0b459c2cSDavid du Colombier /* ifdef.c */ 299*0b459c2cSDavid du Colombier void print_ifdef_script PARAMS((struct change *)); 300*0b459c2cSDavid du Colombier 301*0b459c2cSDavid du Colombier /* io.c */ 302*0b459c2cSDavid du Colombier int read_files PARAMS((struct file_data[], int)); 303*0b459c2cSDavid du Colombier int sip PARAMS((struct file_data *, int)); 304*0b459c2cSDavid du Colombier void slurp PARAMS((struct file_data *)); 305*0b459c2cSDavid du Colombier 306*0b459c2cSDavid du Colombier /* normal.c */ 307*0b459c2cSDavid du Colombier void print_normal_script PARAMS((struct change *)); 308*0b459c2cSDavid du Colombier 309*0b459c2cSDavid du Colombier /* rcs.c */ 310*0b459c2cSDavid du Colombier void print_rcs_script PARAMS((struct change *)); 311*0b459c2cSDavid du Colombier 312*0b459c2cSDavid du Colombier /* side.c */ 313*0b459c2cSDavid du Colombier void print_sdiff_script PARAMS((struct change *)); 314*0b459c2cSDavid du Colombier 315*0b459c2cSDavid du Colombier /* util.c */ 316*0b459c2cSDavid du Colombier VOID *xmalloc PARAMS((size_t)); 317*0b459c2cSDavid du Colombier VOID *xrealloc PARAMS((VOID *, size_t)); 318*0b459c2cSDavid du Colombier char *concat PARAMS((char const *, char const *, char const *)); 319*0b459c2cSDavid du Colombier char *dir_file_pathname PARAMS((char const *, char const *)); 320*0b459c2cSDavid du Colombier int change_letter PARAMS((int, int)); 321*0b459c2cSDavid du Colombier int line_cmp PARAMS((char const *, char const *)); 322*0b459c2cSDavid du Colombier int translate_line_number PARAMS((struct file_data const *, int)); 323*0b459c2cSDavid du Colombier struct change *find_change PARAMS((struct change *)); 324*0b459c2cSDavid du Colombier struct change *find_reverse_change PARAMS((struct change *)); 325*0b459c2cSDavid du Colombier void analyze_hunk PARAMS((struct change *, int *, int *, int *, int *, int *, int *)); 326*0b459c2cSDavid du Colombier void begin_output PARAMS((void)); 327*0b459c2cSDavid du Colombier void debug_script PARAMS((struct change *)); 328*0b459c2cSDavid du Colombier void error PARAMS((char const *, char const *, char const *)); 329*0b459c2cSDavid du Colombier void fatal PARAMS((char const *)); 330*0b459c2cSDavid du Colombier void finish_output PARAMS((void)); 331*0b459c2cSDavid du Colombier void message PARAMS((char const *, char const *, char const *)); 332*0b459c2cSDavid du Colombier void message5 PARAMS((char const *, char const *, char const *, char const *, char const *)); 333*0b459c2cSDavid du Colombier void output_1_line PARAMS((char const *, char const *, char const *, char const *)); 334*0b459c2cSDavid du Colombier void perror_with_name PARAMS((char const *)); 335*0b459c2cSDavid du Colombier void pfatal_with_name PARAMS((char const *)); 336*0b459c2cSDavid du Colombier void print_1_line PARAMS((char const *, char const * const *)); 337*0b459c2cSDavid du Colombier void print_message_queue PARAMS((void)); 338*0b459c2cSDavid du Colombier void print_number_range PARAMS((int, struct file_data *, int, int)); 339*0b459c2cSDavid du Colombier void print_script PARAMS((struct change *, struct change * (*) PARAMS((struct change *)), void (*) PARAMS((struct change *)))); 340*0b459c2cSDavid du Colombier void setup_output PARAMS((char const *, char const *, int)); 341*0b459c2cSDavid du Colombier void translate_range PARAMS((struct file_data const *, int, int, int *, int *)); 342*0b459c2cSDavid du Colombier 343*0b459c2cSDavid du Colombier /* version.c */ 344*0b459c2cSDavid du Colombier extern char const version_string[]; 345