~peter-pearse/ubuntu/natty/diffutils/prop001

« back to all changes in this revision

Viewing changes to src/util.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2010-05-04 20:38:00 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100504203800-f67xd9rsa9xl9qqj
Tags: 1:3.0-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Support routines for GNU DIFF.
2
2
 
3
 
   Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002
 
3
   Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2010
4
4
   Free Software Foundation, Inc.
5
5
 
6
6
   This file is part of GNU DIFF.
7
7
 
8
 
   GNU DIFF is free software; you can redistribute it and/or modify
 
8
   This program is free software: you can redistribute it and/or modify
9
9
   it under the terms of the GNU General Public License as published by
10
 
   the Free Software Foundation; either version 2, or (at your option)
11
 
   any later version.
 
10
   the Free Software Foundation, either version 3 of the License, or
 
11
   (at your option) any later version.
12
12
 
13
 
   GNU DIFF is distributed in the hope that it will be useful,
 
13
   This program is distributed in the hope that it will be useful,
14
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
16
   GNU General Public License for more details.
17
17
 
18
18
   You should have received a copy of the GNU General Public License
19
 
   along with this program; see the file COPYING.
20
 
   If not, write to the Free Software Foundation,
21
 
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
20
 
23
21
#include "diff.h"
24
22
#include <dirname.h>
25
23
#include <error.h>
26
 
#include <quotesys.h>
27
 
#include <regex.h>
 
24
#include <sh-quote.h>
28
25
#include <xalloc.h>
29
26
 
30
27
char const pr_program[] = PR_PROGRAM;
216
213
              }
217
214
 
218
215
            execl (pr_program, pr_program, "-h", name, (char *) 0);
219
 
            _exit (errno == ENOEXEC ? 126 : 127);
 
216
            _exit (errno == ENOENT ? 127 : 126);
220
217
          }
221
218
        else
222
219
          {
227
224
          }
228
225
#else
229
226
        char *command = xmalloc (sizeof pr_program - 1 + 7
230
 
                                 + quote_system_arg ((char *) 0, name) + 1);
 
227
                                 + shell_quote_length (name) + 1);
231
228
        char *p;
232
229
        sprintf (command, "%s -f -h ", pr_program);
233
230
        p = command + sizeof pr_program - 1 + 7;
234
 
        p += quote_system_arg (p, name);
 
231
        p = shell_quote_copy (p, name);
235
232
        *p = 0;
236
233
        errno = 0;
237
234
        outfile = popen (command, "w");
260
257
  switch (output_style)
261
258
    {
262
259
    case OUTPUT_CONTEXT:
263
 
      print_context_header (files, 0);
 
260
      print_context_header (files, false);
264
261
      break;
265
262
 
266
263
    case OUTPUT_UNIFIED:
267
 
      print_context_header (files, 1);
 
264
      print_context_header (files, true);
268
265
      break;
269
266
 
270
267
    default:
280
277
{
281
278
  if (outfile != 0 && outfile != stdout)
282
279
    {
 
280
      int status;
283
281
      int wstatus;
284
282
      int werrno = 0;
285
283
      if (ferror (outfile))
294
292
      if (waitpid (pr_pid, &wstatus, 0) < 0)
295
293
        pfatal_with_name ("waitpid");
296
294
#endif
297
 
      if (! werrno && WIFEXITED (wstatus) && WEXITSTATUS (wstatus) == 127)
298
 
        error (EXIT_TROUBLE, 0, _("subsidiary program `%s' not found"),
299
 
               pr_program);
300
 
      if (wstatus != 0)
301
 
        error (EXIT_TROUBLE, werrno, _("subsidiary program `%s' failed"),
302
 
               pr_program);
 
295
      status = (! werrno && WIFEXITED (wstatus)
 
296
                ? WEXITSTATUS (wstatus)
 
297
                : INT_MAX);
 
298
      if (status)
 
299
        error (EXIT_TROUBLE, werrno,
 
300
               _(status == 126
 
301
                 ? "subsidiary program `%s' could not be invoked"
 
302
                 : status == 127
 
303
                 ? "subsidiary program `%s' not found"
 
304
                 : status == INT_MAX
 
305
                 ? "subsidiary program `%s' failed"
 
306
                 : "subsidiary program `%s' failed (exit status %d)"),
 
307
               pr_program, status);
303
308
    }
304
309
 
305
310
  outfile = 0;
314
319
bool
315
320
lines_differ (char const *s1, char const *s2)
316
321
{
317
 
  register unsigned char const *t1 = (unsigned char const *) s1;
318
 
  register unsigned char const *t2 = (unsigned char const *) s2;
 
322
  register char const *t1 = s1;
 
323
  register char const *t2 = s2;
319
324
  size_t column = 0;
320
325
 
321
326
  while (1)
330
335
            {
331
336
            case IGNORE_ALL_SPACE:
332
337
              /* For -w, just skip past any white space.  */
333
 
              while (ISSPACE (c1) && c1 != '\n') c1 = *t1++;
334
 
              while (ISSPACE (c2) && c2 != '\n') c2 = *t2++;
 
338
              while (isspace (c1) && c1 != '\n') c1 = *t1++;
 
339
              while (isspace (c2) && c2 != '\n') c2 = *t2++;
335
340
              break;
336
341
 
337
342
            case IGNORE_SPACE_CHANGE:
338
343
              /* For -b, advance past any sequence of white space in
339
344
                 line 1 and consider it just one space, or nothing at
340
345
                 all if it is at the end of the line.  */
341
 
              if (ISSPACE (c1))
 
346
              if (isspace (c1))
342
347
                {
343
348
                  while (c1 != '\n')
344
349
                    {
345
350
                      c1 = *t1++;
346
 
                      if (! ISSPACE (c1))
 
351
                      if (! isspace (c1))
347
352
                        {
348
353
                          --t1;
349
354
                          c1 = ' ';
353
358
                }
354
359
 
355
360
              /* Likewise for line 2.  */
356
 
              if (ISSPACE (c2))
 
361
              if (isspace (c2))
357
362
                {
358
363
                  while (c2 != '\n')
359
364
                    {
360
365
                      c2 = *t2++;
361
 
                      if (! ISSPACE (c2))
 
366
                      if (! isspace (c2))
362
367
                        {
363
368
                          --t2;
364
369
                          c2 = ' ';
373
378
                     for equality, go back to the first non-white-space
374
379
                     character in both sides and try again.  */
375
380
                  if (c2 == ' ' && c1 != '\n'
376
 
                      && (unsigned char const *) s1 + 1 < t1
377
 
                      && ISSPACE (t1[-2]))
 
381
                      && s1 + 1 < t1
 
382
                      && isspace ((unsigned char) t1[-2]))
378
383
                    {
379
384
                      --t1;
380
385
                      continue;
381
386
                    }
382
387
                  if (c1 == ' ' && c2 != '\n'
383
 
                      && (unsigned char const *) s2 + 1 < t2
384
 
                      && ISSPACE (t2[-2]))
 
388
                      && s2 + 1 < t2
 
389
                      && isspace ((unsigned char) t2[-2]))
385
390
                    {
386
391
                      --t2;
387
392
                      continue;
400
405
                      if (c1 == ' ')
401
406
                        column++;
402
407
                      else if (c1 == '\t')
403
 
                        column += TAB_WIDTH - column % TAB_WIDTH;
 
408
                        column += tabsize - column % tabsize;
404
409
                      else
405
410
                        break;
406
411
                    }
409
414
                      if (c2 == ' ')
410
415
                        column2++;
411
416
                      else if (c2 == '\t')
412
 
                        column2 += TAB_WIDTH - column2 % TAB_WIDTH;
 
417
                        column2 += tabsize - column2 % tabsize;
413
418
                      else
414
419
                        break;
415
420
                    }
416
421
                  if (column != column2)
417
 
                    return 1;
 
422
                    return true;
418
423
                }
419
424
              break;
420
425
 
426
431
 
427
432
          if (ignore_case)
428
433
            {
429
 
              c1 = TOLOWER (c1);
430
 
              c2 = TOLOWER (c2);
 
434
              c1 = tolower (c1);
 
435
              c2 = tolower (c2);
431
436
            }
432
437
 
433
438
          if (c1 != c2)
434
439
            break;
435
440
        }
436
441
      if (c1 == '\n')
437
 
        return 0;
 
442
        return false;
438
443
 
439
 
      column += c1 == '\t' ? TAB_WIDTH - column % TAB_WIDTH : 1;
 
444
      column += c1 == '\t' ? tabsize - column % tabsize : 1;
440
445
    }
441
446
 
442
 
  return 1;
 
447
  return true;
443
448
}
444
449
 
445
450
/* Find the consecutive changes at the start of the script START.
501
506
 
502
507
/* Print the text of a single line LINE,
503
508
   flagging it with the characters in LINE_FLAG (which say whether
504
 
   the line is inserted, deleted, changed, etc.).  */
 
509
   the line is inserted, deleted, changed, etc.).  LINE_FLAG must not
 
510
   end in a blank, unless it is a single blank.  */
505
511
 
506
512
void
507
513
print_1_line (char const *line_flag, char const *const *line)
512
518
 
513
519
  /* If -T was specified, use a Tab between the line-flag and the text.
514
520
     Otherwise use a Space (as Unix diff does).
515
 
     Print neither space nor tab if line-flags are empty.  */
 
521
     Print neither space nor tab if line-flags are empty.
 
522
     But omit trailing blanks if requested.  */
516
523
 
517
524
  if (line_flag && *line_flag)
518
525
    {
519
 
      flag_format = initial_tab ? "%s\t" : "%s ";
520
 
      fprintf (out, flag_format, line_flag);
 
526
      char const *flag_format_1 = flag_format = initial_tab ? "%s\t" : "%s ";
 
527
      char const *line_flag_1 = line_flag;
 
528
 
 
529
      if (suppress_blank_empty && **line == '\n')
 
530
        {
 
531
          flag_format_1 = "%s";
 
532
 
 
533
          /* This hack to omit trailing blanks takes advantage of the
 
534
             fact that the only way that LINE_FLAG can end in a blank
 
535
             is when LINE_FLAG consists of a single blank.  */
 
536
          line_flag_1 += *line_flag_1 == ' ';
 
537
        }
 
538
 
 
539
      fprintf (out, flag_format_1, line_flag_1);
521
540
    }
522
541
 
523
542
  output_1_line (base, limit, flag_format, line_flag);
536
555
               char const *line_flag)
537
556
{
538
557
  if (!expand_tabs)
539
 
    fwrite (base, limit - base, 1, outfile);
 
558
    fwrite (base, sizeof (char), limit - base, outfile);
540
559
  else
541
560
    {
542
561
      register FILE *out = outfile;
543
562
      register unsigned char c;
544
563
      register char const *t = base;
545
 
      register unsigned int column = 0;
 
564
      register size_t column = 0;
 
565
      size_t tab_size = tabsize;
546
566
 
547
567
      while (t < limit)
548
568
        switch ((c = *t++))
549
569
          {
550
570
          case '\t':
551
571
            {
552
 
              unsigned int spaces = TAB_WIDTH - column % TAB_WIDTH;
 
572
              size_t spaces = tab_size - column % tab_size;
553
573
              column += spaces;
554
574
              do
555
575
                putc (' ', out);
572
592
            break;
573
593
 
574
594
          default:
575
 
            if (ISPRINT (c))
576
 
              column++;
 
595
            column += isprint (c) != 0;
577
596
            putc (c, out);
578
597
            break;
579
598
          }
596
615
}
597
616
 
598
617
/* Translate a line number range.  This is always done for printing,
599
 
   so for convenience translate to long rather than lin, so that the
 
618
   so for convenience translate to long int rather than lin, so that the
600
619
   caller can use printf with "%ld" without casting.  */
601
620
 
602
621
void
603
622
translate_range (struct file_data const *file,
604
623
                 lin a, lin b,
605
 
                 long *aptr, long *bptr)
 
624
                 long int *aptr, long int *bptr)
606
625
{
607
626
  *aptr = translate_line_number (file, a - 1) + 1;
608
627
  *bptr = translate_line_number (file, b + 1) - 1;
617
636
void
618
637
print_number_range (char sepchar, struct file_data *file, lin a, lin b)
619
638
{
620
 
  long trans_a, trans_b;
 
639
  long int trans_a, trans_b;
621
640
  translate_range (file, a, b, &trans_a, &trans_b);
622
641
 
623
642
  /* Note: we can have B < A in the case of a range of no lines.
652
671
  lin show_from, show_to;
653
672
  lin i;
654
673
  bool trivial = ignore_blank_lines || ignore_regexp.fastmap;
655
 
  size_t trivial_length = (int) ignore_blank_lines - 1;
 
674
  size_t trivial_length = ignore_blank_lines - 1;
656
675
    /* If 0, ignore zero-length lines;
657
676
       if SIZE_MAX, do not ignore lines just because of their length.  */
 
677
  bool skip_leading_white_space =
 
678
    (ignore_blank_lines && IGNORE_SPACE_CHANGE <= ignore_white_space);
658
679
 
659
680
  char const * const *linbuf0 = files[0].linbuf;  /* Help the compiler.  */
660
681
  char const * const *linbuf1 = files[1].linbuf;
675
696
      for (i = next->line0; i <= l0 && trivial; i++)
676
697
        {
677
698
          char const *line = linbuf0[i];
678
 
          size_t len = linbuf0[i + 1] - line - 1;
679
 
          if (len != trivial_length
 
699
          char const *newline = linbuf0[i + 1] - 1;
 
700
          size_t len = newline - line;
 
701
          char const *p = line;
 
702
          if (skip_leading_white_space)
 
703
            while (isspace ((unsigned char) *p) && *p != '\n')
 
704
              p++;
 
705
          if (newline - p != trivial_length
680
706
              && (! ignore_regexp.fastmap
681
707
                  || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
682
708
            trivial = 0;
685
711
      for (i = next->line1; i <= l1 && trivial; i++)
686
712
        {
687
713
          char const *line = linbuf1[i];
688
 
          size_t len = linbuf1[i + 1] - line - 1;
689
 
          if (len != trivial_length
 
714
          char const *newline = linbuf1[i + 1] - 1;
 
715
          size_t len = newline - line;
 
716
          char const *p = line;
 
717
          if (skip_leading_white_space)
 
718
            while (isspace ((unsigned char) *p) && *p != '\n')
 
719
              p++;
 
720
          if (newline - p != trivial_length
690
721
              && (! ignore_regexp.fastmap
691
722
                  || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
692
723
            trivial = 0;
732
763
char *
733
764
dir_file_pathname (char const *dir, char const *file)
734
765
{
735
 
  char const *base = base_name (dir);
736
 
  bool omit_slash = !*base || base[strlen (base) - 1] == '/';
 
766
  char const *base = last_component (dir);
 
767
  size_t baselen = base_len (base);
 
768
  bool omit_slash = baselen == 0 || base[baselen - 1] == '/';
737
769
  return concat (dir, "/" + omit_slash, file);
738
770
}
739
771
 
744
776
 
745
777
  for (; sp; sp = sp->link)
746
778
    {
747
 
      long line0 = sp->line0;
748
 
      long line1 = sp->line1;
749
 
      long deleted = sp->deleted;
750
 
      long inserted = sp->inserted;
 
779
      long int line0 = sp->line0;
 
780
      long int line1 = sp->line1;
 
781
      long int deleted = sp->deleted;
 
782
      long int inserted = sp->inserted;
751
783
      fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n",
752
784
               line0, line1, deleted, inserted);
753
785
    }