home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / utils / hwgrcs / hwgdiff / rcs.rcsfiles / diff.c,v < prev    next >
Encoding:
Text File  |  1993-02-20  |  19.8 KB  |  852 lines

  1. head    1.3;
  2. access;
  3. symbols
  4.     HWGDIFF_Fish:1.3
  5.     HWGDIFF:1.2;
  6. locks; strict;
  7. comment    @ * @;
  8.  
  9.  
  10. 1.3
  11. date    93.02.07.16.23.28;    author heinz;    state Exp;
  12. branches;
  13. next    1.2;
  14.  
  15. 1.2
  16. date    93.01.19.14.32.45;    author heinz;    state Exp;
  17. branches;
  18. next    1.1;
  19.  
  20. 1.1
  21. date    93.01.19.14.04.33;    author heinz;    state Exp;
  22. branches;
  23. next    ;
  24.  
  25.  
  26. desc
  27. @RCS for the first time ...
  28. @
  29.  
  30.  
  31. 1.3
  32. log
  33. @Stupid error. I left unix directory handling in there. Messed up
  34. Amiga directory names.
  35. @
  36. text
  37. @/* GNU DIFF main routine.
  38.    Copyright (C) 1988, 1989 Free Software Foundation, Inc.
  39.  
  40. This file is part of GNU DIFF.
  41.  
  42. GNU DIFF is free software; you can redistribute it and/or modify
  43. it under the terms of the GNU General Public License as published by
  44. the Free Software Foundation; either version 1, or (at your option)
  45. any later version.
  46.  
  47. GNU DIFF is distributed in the hope that it will be useful,
  48. but WITHOUT ANY WARRANTY; without even the implied warranty of
  49. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  50. GNU General Public License for more details.
  51.  
  52. You should have received a copy of the GNU General Public License
  53. along with GNU DIFF; see the file COPYING.  If not, write to
  54. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  55.  
  56. /* GNU DIFF was written by Mike Haertel, David Hayes,
  57.    Richard Stallman and Len Tower.  */
  58.  
  59. #define GDIFF_MAIN
  60. #include "regex.h"
  61. #include "diff.h"
  62. #include "getopt.h"
  63.  
  64. #ifdef AMIGA
  65. /* This is a good place for this! */
  66. char HWGversion[] = "\0$VER: GNUDIFF 1.15 (19.1.93) Changes (C)1993 by HWG, For Joan";
  67.  
  68. struct file_data files[2];
  69. #endif
  70.  
  71. /* Nonzero for -r: if comparing two directories,
  72.    compare their common subdirectories recursively.  */
  73.  
  74. int recursive;
  75.  
  76. /* For debugging: don't do discard_confusing_lines.  */
  77.  
  78. int no_discards;
  79.  
  80. /* Return a string containing the command options with which diff was invoked.
  81.    Spaces appear between what were separate ARGV-elements.
  82.    There is a space at the beginning but none at the end.
  83.    If there were no options, the result is an empty string.
  84.  
  85.    Arguments: OPTIONVEC, a vector containing separate ARGV-elements, and COUNT,
  86.    the length of that vector.  */
  87.  
  88. static char *
  89. option_list (optionvec, count)
  90.      char **optionvec;    /* Was `vector', but that collides on Alliant.  */
  91.      int count;
  92. {
  93.   int i;
  94.   int length = 0;
  95.   char *result;
  96.  
  97.   for (i = 0; i < count; i++)
  98.     length += strlen (optionvec[i]) + 1;
  99.  
  100.   result = (char *) xmalloc (length + 1);
  101.   result[0] = 0;
  102.  
  103.   for (i = 0; i < count; i++)
  104.     {
  105.       strcat (result, " ");
  106.       strcat (result, optionvec[i]);
  107.     }
  108.  
  109.   return result;
  110. }
  111.  
  112. /* The numbers 129 and 130 that appear in the fourth element
  113.    for the context and unidiff entries are used as a way of
  114.    telling the big switch in `main' how to process those options.  */
  115.  
  116. static struct option longopts[] =
  117. {
  118.   {"ignore-blank-lines", 0, 0, 'B'},
  119.   {"context", 2, 0, 129},
  120.   {"ifdef", 1, 0, 'D'},
  121.   {"show-function-line", 1, 0, 'F'},
  122.   {"speed-large-files", 0, 0, 'H'},
  123.   {"ignore-matching-lines", 1, 0, 'I'},
  124.   {"file-label", 1, 0, 'L'},
  125.   {"entire-new-files", 0, 0, 'N'},
  126.   {"new-files", 0, 0, 'N'},
  127.   {"starting-file", 1, 0, 'S'},
  128.   {"initial-tab", 0, 0, 'T'},
  129.   {"text", 0, 0, 'a'},
  130.   {"all-text", 0, 0, 'a'},
  131.   {"ascii", 0, 0, 'a'},
  132.   {"ignore-space-change", 0, 0, 'b'},
  133.   {"minimal", 0, 0, 'd'},
  134.   {"ed", 0, 0, 'e'},
  135.   {"reversed-ed", 0, 0, 'f'},
  136.   {"ignore-case", 0, 0, 'i'},
  137.   {"print", 0, 0, 'l'},
  138.   {"rcs", 0, 0, 'n'},
  139.   {"show-c-function", 0, 0, 'p'},
  140.   {"binary", 0, 0, 'q'},
  141.   {"brief", 0, 0, 'q'},
  142.   {"recursive", 0, 0, 'r'},
  143.   {"report-identical-files", 0, 0, 's'},
  144.   {"expand-tabs", 0, 0, 't'},
  145.   {"ignore-all-space", 0, 0, 'w'},
  146.   {"unified", 2, 0, 130},
  147.   {"version", 0, 0, 'v'},
  148.   {0, 0, 0, 0}
  149. };
  150.  
  151. main (argc, argv)
  152.      int argc;
  153.      char *argv[];
  154. {
  155.   int val;
  156.   int c;
  157.   int prev = -1;
  158.   int longind;
  159.   extern char *version_string;
  160.  
  161.   program = argv[0];
  162.  
  163.   /* Do our initializations. */
  164.   output_style = OUTPUT_NORMAL;
  165.   always_text_flag = FALSE;
  166.   ignore_space_change_flag = FALSE;
  167.   ignore_all_space_flag = FALSE;
  168.   length_varies = FALSE;
  169.   ignore_case_flag = FALSE;
  170.   ignore_blank_lines_flag = FALSE;
  171.   ignore_regexp = 0;
  172.   function_regexp = 0;
  173.   print_file_same_flag = FALSE;
  174.   entire_new_file_flag = FALSE;
  175.   no_details_flag = FALSE;
  176.   context = -1;
  177.   line_end_char = '\n';
  178.   tab_align_flag = FALSE;
  179.   tab_expand_flag = FALSE;
  180.   recursive = FALSE;
  181.   paginate_flag = FALSE;
  182.   ifdef_string = NULL;
  183.   heuristic = FALSE;
  184.   dir_start_file = NULL;
  185.   msg_chain = NULL;
  186.   msg_chain_end = NULL;
  187.   no_discards = 0;
  188.  
  189.   /* Decode the options.  */
  190.  
  191.   while ((c = getopt_long (argc, argv,
  192.                "0123456789abBcC:dD:efF:hHiI:lL:nNpqrsS:tTuvw",
  193.                longopts, &longind)) != EOF)
  194.     {
  195.       if (c == 0)               /* Long option. */
  196.     c = longopts[longind].val;
  197.       switch (c)
  198.     {
  199.       /* All digits combine in decimal to specify the context-size.  */
  200.     case '1':
  201.     case '2':
  202.     case '3':
  203.     case '4':
  204.     case '5':
  205.     case '6':
  206.     case '7':
  207.     case '8':
  208.     case '9':
  209.     case '0':
  210.       if (context == -1)
  211.         context = 0;
  212.       /* If a context length has already been specified,
  213.          more digits allowed only if they follow right after the others.
  214.          Reject two separate runs of digits, or digits after -C.  */
  215.       else if (prev < '0' || prev > '9')
  216.         fatal ("context length specified twice");
  217.  
  218.       context = context * 10 + c - '0';
  219.       break;
  220.  
  221.     case 'a':
  222.       /* Treat all files as text files; never treat as binary.  */
  223.       always_text_flag = 1;
  224.       break;
  225.  
  226.     case 'b':
  227.       /* Ignore changes in amount of whitespace.  */
  228.       ignore_space_change_flag = 1;
  229.       length_varies = 1;
  230.       break;
  231.  
  232.     case 'B':
  233.       /* Ignore changes affecting only blank lines.  */
  234.       ignore_blank_lines_flag = 1;
  235.       break;
  236.  
  237.     case 'C':
  238.     case 129:        /* +context[=lines] */
  239.     case 130:        /* +unified[=lines] */
  240.       if (optarg)
  241.         {
  242.           if (context >= 0)
  243.         fatal ("context length specified twice");
  244.           {
  245.         char *p;
  246.         for (p = optarg; *p; p++)
  247.           if (*p < '0' || *p > '9')
  248.             fatal ("invalid context length argument");
  249.           }
  250.           context = atoi (optarg);
  251.         }
  252.  
  253.       /* Falls through.  */
  254.     case 'c':
  255.       /* Make context-style output.  */
  256.       specify_style (c == 130 ? OUTPUT_UNIFIED : OUTPUT_CONTEXT);
  257.       break;
  258.  
  259.     case 'd':
  260.       /* Don't discard lines.  This makes things slower (sometimes much
  261.          slower) but will find a guaranteed minimal set of changes.  */
  262.       no_discards = 1;
  263.       break;
  264.  
  265.     case 'D':
  266.       /* Make merged #ifdef output.  */
  267.       specify_style (OUTPUT_IFDEF);
  268.       ifdef_string = optarg;
  269.       break;
  270.  
  271.     case 'e':
  272.       /* Make output that is a valid `ed' script.  */
  273.       specify_style (OUTPUT_ED);
  274.       break;
  275.  
  276.     case 'f':
  277.       /* Make output that looks vaguely like an `ed' script
  278.          but has changes in the order they appear in the file.  */
  279.       specify_style (OUTPUT_FORWARD_ED);
  280.       break;
  281.  
  282.     case 'F':
  283.       /* Show, for each set of changes, the previous line that
  284.          matches the specified regexp.  Currently affects only
  285.          context-style output.  */
  286.       function_regexp = optarg;
  287.       break;
  288.  
  289.     case 'h':
  290.       /* Split the files into chunks of around 1500 lines
  291.          for faster processing.  Usually does not change the result.
  292.  
  293.          This currently has no effect.  */
  294.       break;
  295.  
  296.     case 'H':
  297.       /* Turn on heuristics that speed processing of large files
  298.          with a small density of changes.  */
  299.       heuristic = 1;
  300.       break;
  301.  
  302.     case 'i':
  303.       /* Ignore changes in case.  */
  304.       ignore_case_flag = 1;
  305.       break;
  306.  
  307.     case 'I':
  308.       /* Ignore changes affecting only lines that match the
  309.          specified regexp.    */
  310.       ignore_regexp = optarg;
  311.       break;
  312.  
  313.     case 'l':
  314.       /* Pass the output through `pr' to paginate it.  */
  315.       paginate_flag = 1;
  316.       break;
  317.  
  318.     case 'L':
  319.       /* Specify file labels for `-c' output headers.  */
  320.       if (!file_label[0])
  321.         file_label[0] = optarg;
  322.       else if (!file_label[1])
  323.         file_label[1] = optarg;
  324.       else
  325.         fatal ("too many file label options");
  326.       break;
  327.  
  328.     case 'n':
  329.       /* Output RCS-style diffs, like `-f' except that each command
  330.          specifies the number of lines affected.  */
  331.       specify_style (OUTPUT_RCS);
  332.       break;
  333.  
  334.     case 'N':
  335.       /* When comparing directories, if a file appears only in one
  336.          directory, treat it as present but empty in the other.  */
  337.       entire_new_file_flag = 1;
  338.       break;
  339.  
  340.     case 'p':
  341.       /* Make context-style output and show name of last C function.  */
  342.       specify_style (OUTPUT_CONTEXT);
  343.       function_regexp = "^[_a-zA-Z]";
  344.       break;
  345.  
  346.     case 'q':
  347.       no_details_flag = 1;
  348.       break;
  349.  
  350.     case 'r':
  351.       /* When comparing directories,
  352.          recursively compare any subdirectories found.  */
  353.       recursive = 1;
  354.       break;
  355.  
  356.     case 's':
  357.       /* Print a message if the files are the same.  */
  358.       print_file_same_flag = 1;
  359.       break;
  360.  
  361.     case 'S':
  362.       /* When comparing directories, start with the specified
  363.          file name.  This is used for resuming an aborted comparison.  */
  364.       dir_start_file = optarg;
  365.       break;
  366.  
  367.     case 't':
  368.       /* Expand tabs to spaces in the output so that it preserves
  369.          the alignment of the input files.    */
  370.       tab_expand_flag = 1;
  371.       break;
  372.  
  373.     case 'T':
  374.       /* Use a tab in the output, rather than a space, before the
  375.          text of an input line, so as to keep the proper alignment
  376.          in the input line without changing the characters in it.  */
  377.       tab_align_flag = 1;
  378.       break;
  379.  
  380.     case 'v':
  381.       printf ("GNU diff version %s\n", version_string);
  382.       break;
  383.  
  384.     case 'u':
  385.       /* Output the context diff in unidiff format.  */
  386.       specify_style (OUTPUT_UNIFIED);
  387.       break;
  388.  
  389.     case 'w':
  390.       /* Ignore horizontal whitespace when comparing lines.  */
  391.       ignore_all_space_flag = 1;
  392.       length_varies = 1;
  393.       break;
  394.  
  395.     default:
  396.       usage ();
  397.     }
  398.       prev = c;
  399.     }
  400.  
  401.   if (optind != argc - 2)
  402.     usage ();
  403.  
  404.   if (ignore_regexp)
  405.     {
  406.       char *val;
  407.       bzero (&ignore_regexp_compiled, sizeof ignore_regexp_compiled);
  408.       val = re_compile_pattern (ignore_regexp, strlen (ignore_regexp),
  409.                 &ignore_regexp_compiled);
  410.       if (val != 0)
  411.     error ("%s: %s", ignore_regexp, val);
  412.       ignore_regexp_compiled.fastmap = (char *) xmalloc (256);
  413.     }
  414.  
  415.   if (function_regexp)
  416.     {
  417.       char *val;
  418.       bzero (&function_regexp_compiled, sizeof function_regexp_compiled);
  419.       val = re_compile_pattern (function_regexp, strlen (function_regexp),
  420.                 &function_regexp_compiled);
  421.       if (val != 0)
  422.     error ("%s: %s", function_regexp, val);
  423.       function_regexp_compiled.fastmap = (char *) xmalloc (256);
  424.     }
  425.  
  426.   if (output_style != OUTPUT_CONTEXT && output_style != OUTPUT_UNIFIED)
  427.     context = 0;
  428.   else if (context == -1)
  429.     /* Default amount of context for -c.  */
  430.     context = 3;
  431.  
  432.   switch_string = option_list (argv + 1, optind - 1);
  433.  
  434.   val = compare_files (0, argv[optind], 0, argv[optind + 1], 0);
  435.  
  436.   /* Print any messages that were saved up for last.  */
  437.   print_message_queue ();
  438.  
  439.   if (ferror (stdout) || fclose (stdout) != 0)
  440.     fatal ("write error");
  441.   exit (val);
  442. }
  443.  
  444. usage ()
  445. {
  446.   fprintf (stderr, "\
  447. Usage: diff [-#] [-abBcdefhHilnNprstTuvw] [-C lines] [-F regexp] [-I regexp]\n\
  448.        [-L label [-L label]] [-S file] [-D symbol] [+ignore-blank-lines]\n\
  449.        [+context[=lines]] [+unified[=lines]] [+ifdef=symbol]\n\
  450.        [+show-function-line=regexp]\n");
  451.   fprintf (stderr, "\
  452.        [+speed-large-files] [+ignore-matching-lines=regexp] [+new-file]\n\
  453.        [+initial-tab] [+starting-file=file] [+text] [+all-text] [+ascii]\n\
  454.        [+minimal] [+ignore-space-change] [+ed] [+reversed-ed] [+ignore-case]\n");
  455.   fprintf (stderr, "\
  456.        [+print] [+rcs] [+show-c-function] [+binary] [+brief] [+recursive]\n\
  457.        [+report-identical-files] [+expand-tabs] [+ignore-all-space]\n\
  458.        [+file-label=label [+file-label=label]] [+version] path1 path2\n");
  459.   exit (2);
  460. }
  461.  
  462. specify_style (style)
  463.      enum output_style style;
  464. {
  465.   if (output_style != OUTPUT_NORMAL
  466.       && output_style != style)
  467.     error ("conflicting specifications of output style");
  468.   output_style = style;
  469. }
  470.  
  471. /* Compare two files (or dirs) with specified names
  472.    DIR0/NAME0 and DIR1/NAME1, at level DEPTH in directory recursion.
  473.    (if DIR0 is 0, then the name is just NAME0, etc.)
  474.    This is self-contained; it opens the files and closes them.
  475.  
  476.    Value is 0 if files are identical, 1 if different,
  477.    2 if there is a problem opening them.  */
  478.  
  479. int
  480. compare_files (dir0, name0, dir1, name1, depth)
  481.      char *dir0, *dir1;
  482.      char *name0, *name1;
  483.      int depth;
  484. {
  485.   static char Standard_Input[] = "Standard Input";
  486.   struct file_data inf[2];
  487.   register int i;
  488.   int val;
  489.   int errorcount = 0;
  490.   int stat_result[2];
  491. #ifdef AMIGA
  492.   char *dirsep0="/", *dirsep1="/";
  493. #endif
  494.  
  495.   /* If this is directory comparison, perhaps we have a file
  496.      that exists only in one of the directories.
  497.      If so, just print a message to that effect.  */
  498.  
  499.   if (! entire_new_file_flag && (name0 == 0 || name1 == 0))
  500.     {
  501.       char *name = name0 == 0 ? name1 : name0;
  502.       char *dir = name0 == 0 ? dir1 : dir0;
  503.       message ("Only in %s: %s\n", dir, name);
  504.       /* Return 1 so that diff_dirs will return 1 ("some files differ").  */
  505.       return 1;
  506.     }
  507.  
  508.   /* Mark any nonexistent file with -1 in the desc field.  */
  509.   /* Mark unopened files (i.e. directories) with -2. */
  510.  
  511.   inf[0].desc = name0 == 0 ? -1 : -2;
  512.   inf[1].desc = name1 == 0 ? -1 : -2;
  513.  
  514.   /* Now record the full name of each file, including nonexistent ones.  */
  515.  
  516.   if (name0 == 0)
  517.     name0 = name1;
  518.   if (name1 == 0)
  519.     name1 = name0;
  520.  
  521. #ifdef AMIGA
  522.   if(dir0)
  523.   {
  524.       if(dir0[0])
  525.       {
  526.       char c = dir0[strlen(dir0)-1];
  527.  
  528.       if(c == ':' || c == '/')
  529.       {
  530.           dirsep0 = "";
  531.       } /* if */
  532.       }
  533.       else
  534.       {
  535.       dirsep0 = "";
  536.       } /* if */
  537.   } /* if */
  538.  
  539.   if(dir1)
  540.   {
  541.       if(dir1[0])
  542.       {
  543.       char c = dir1[strlen(dir1)-1];
  544.  
  545.       if(c == ':' || c == '/')
  546.       {
  547.           dirsep1 = "";
  548.       } /* if */
  549.       }
  550.       else
  551.       {
  552.       dirsep1 = "";
  553.       } /* if */
  554.   } /* if */
  555.  
  556.   inf[0].name = dir0 == 0 ? name0 : concat (dir0, dirsep0, name0);
  557.   inf[1].name = dir1 == 0 ? name1 : concat (dir1, dirsep1, name1);
  558. #else
  559.   inf[0].name = dir0 == 0 ? name0 : concat (dir0, "/", name0);
  560.   inf[1].name = dir1 == 0 ? name1 : concat (dir1, "/", name1);
  561. #endif
  562.  
  563.   /* Stat the files.  Record whether they are directories.
  564.      Record in stat_result whether stat fails.    */
  565.  
  566.   for (i = 0; i <= 1; i++)
  567.     {
  568.       bzero (&inf[i].stat, sizeof(struct stat));
  569.       inf[i].dir_p = 0;
  570.       stat_result[i] = 0;
  571.  
  572.       if (inf[i].desc != -1)
  573.     {
  574.       char *filename = inf[i].name;
  575.  
  576.       stat_result[i] =
  577.         strcmp (filename, "-")
  578.           ? stat (filename, &inf[i].stat)
  579.           : fstat (0, &inf[i].stat);
  580.  
  581.       if (stat_result[i] < 0)
  582.         {
  583.           perror_with_name (filename);
  584.           errorcount = 1;
  585.         }
  586.       else
  587.         inf[i].dir_p =
  588.           S_IFDIR == (inf[i].stat.st_mode & S_IFMT)
  589.           && strcmp (filename, "-");
  590.     }
  591.     }
  592.  
  593.   /* See if the two named files are actually the same physical file.
  594.      If so, we know they are identical without actually reading them.  */
  595.  
  596.   if (output_style != OUTPUT_IFDEF
  597.       && inf[0].stat.st_ino == inf[1].stat.st_ino
  598.       && inf[0].stat.st_dev == inf[1].stat.st_dev
  599.       && stat_result[0] == 0
  600.       && stat_result[1] == 0)
  601.     {
  602.       val = 0;
  603.       goto done;
  604.     }
  605.  
  606.   if (name0 == 0)
  607.     inf[0].dir_p = inf[1].dir_p;
  608.   if (name1 == 0)
  609.     inf[1].dir_p = inf[0].dir_p;
  610.  
  611.   /* Open the files and record their descriptors.  */
  612.  
  613.   for (i = 0; i <= 1; i++)
  614.     {
  615.       if (inf[i].desc == -1)
  616.     ;
  617.       else if (!strcmp (inf[i].name, "-"))
  618.     {
  619.       inf[i].desc = 0;
  620.       inf[i].name = Standard_Input;
  621.     }
  622.       /* Don't bother opening if stat already failed.  */
  623.       else if (stat_result[i] == 0 && ! inf[i].dir_p)
  624.     {
  625.       char *filename = inf[i].name;
  626.  
  627.       inf[i].desc = open (filename, O_RDONLY, 0);
  628.       if (0 > inf[i].desc)
  629.         {
  630.           perror_with_name (filename);
  631.           errorcount = 1;
  632.         }
  633.     }
  634.     }
  635.  
  636.   if (errorcount)
  637.     {
  638.  
  639.       /* If either file should exist but fails to be opened, return 2.    */
  640.  
  641.       val = 2;
  642.  
  643.     }
  644.   else if (inf[0].dir_p && inf[1].dir_p)
  645.     {
  646.       if (output_style == OUTPUT_IFDEF)
  647.     fatal ("-D option not supported with directories");
  648.  
  649.       /* If both are directories, compare the files in them.  */
  650.  
  651.       if (depth > 0 && !recursive)
  652.     {
  653.       /* But don't compare dir contents one level down
  654.          unless -r was specified.  */
  655.       message ("Common subdirectories: %s and %s\n",
  656.            inf[0].name, inf[1].name);
  657.       val = 0;
  658.     }
  659.       else
  660.     {
  661.       val = diff_dirs (inf[0].name, inf[1].name,
  662.                compare_files, depth, 0, 0);
  663.     }
  664.  
  665.     }
  666.   else if (depth == 0 && (inf[0].dir_p || inf[1].dir_p))
  667.     {
  668.  
  669.       /* If only one is a directory, and it was specified in the command line,
  670.      use the file in that dir whose basename matches the other file.  */
  671.  
  672.       int dir_arg = (inf[0].dir_p ? 0 : 1);
  673.       int fnm_arg = (inf[0].dir_p ? 1 : 0);
  674. #ifdef AMIGA
  675.       char *p;
  676.       char *dirsep = (dir_arg) ? dirsep1 : dirsep0;
  677.       char *filename;
  678.  
  679.       p = rindex (inf[fnm_arg].name, '/');
  680.       if(p == 0)
  681.       {
  682.       p = rindex (inf[fnm_arg].name, ':');
  683.       } /* if */
  684.  
  685.       filename = concat (inf[dir_arg].name,  dirsep,
  686.              (p ? p+1 : inf[fnm_arg].name));
  687. #else
  688.       char *p = rindex (inf[fnm_arg].name, '/');
  689.       char *filename = concat (inf[dir_arg].name,  "/",
  690.                    (p ? p+1 : inf[fnm_arg].name));
  691. #endif
  692.  
  693.       if (inf[fnm_arg].name == Standard_Input)
  694.     fatal ("can't compare - to a directory");
  695.  
  696.       inf[dir_arg].desc = open (filename, O_RDONLY, 0);
  697.  
  698.       if (0 > inf[dir_arg].desc)
  699.     {
  700.       perror_with_name (filename);
  701.       val = 2;
  702.     }
  703.       else
  704.     {
  705.       /* JF: patch from the net to check and make sure we can really free
  706.          this.  If it's from argv[], freeing it is a *really* bad idea */
  707.       if (0 != (dir_arg ? dir1 : dir0))
  708.         free (inf[dir_arg].name);
  709.       inf[dir_arg].name = filename;
  710.       if (fstat (inf[dir_arg].desc, &inf[dir_arg].stat) < 0)
  711.         pfatal_with_name (inf[dir_arg].name);
  712.  
  713.       inf[dir_arg].dir_p
  714.         = (S_IFDIR == (inf[dir_arg].stat.st_mode & S_IFMT));
  715.       if (inf[dir_arg].dir_p)
  716.         {
  717.           error ("%s is a directory but %s is not",
  718.              inf[dir_arg].name, inf[fnm_arg].name);
  719.           val = 1;
  720.         }
  721.       else
  722.         val = diff_2_files (inf, depth);
  723.     }
  724.  
  725.     }
  726.   else if (depth > 0 && (inf[0].dir_p || inf[1].dir_p))
  727.     {
  728.       /* Perhaps we have a subdirectory that exists only in one directory.
  729.      If so, just print a message to that effect.  */
  730.  
  731.       if (inf[0].desc == -1 || inf[1].desc == -1)
  732.     {
  733.       if (entire_new_file_flag && recursive)
  734.         val = diff_dirs (inf[0].name, inf[1].name, compare_files, depth,
  735.                  inf[0].desc == -1, inf[1].desc == -1);
  736.       else
  737.         {
  738.           char *dir = (inf[0].desc == -1) ? dir1 : dir0;
  739.           message ("Only in %s: %s\n", dir, name0);
  740.           val = 1;
  741.         }
  742.     }
  743.       else
  744.     {
  745.       /* We have a subdirectory in one directory
  746.          and a file in the other.  */
  747.  
  748.       if (inf[0].dir_p)
  749.         message ("%s is a directory but %s is not\n",
  750.              inf[0].name, inf[1].name);
  751.       else
  752.         message ("%s is a directory but %s is not\n",
  753.              inf[1].name, inf[0].name);
  754.       /* This is a difference.  */
  755.       val = 1;
  756.     }
  757.     }
  758.   else
  759.     {
  760.  
  761.       /* Both exist and both are ordinary files.  */
  762.  
  763.       val = diff_2_files (inf, depth);
  764.  
  765.     }
  766.  
  767.   /* Now the comparison has been done, if no error prevented it,
  768.      and VAL is the value this function will return.  */
  769.  
  770.   if (inf[0].desc >= 0)
  771.     close (inf[0].desc);
  772.   if (inf[1].desc >= 0)
  773.     close (inf[1].desc);
  774.  
  775.  done:
  776.   if (val == 0 && !inf[0].dir_p)
  777.     {
  778.       if (print_file_same_flag)
  779.     message ("Files %s and %s are identical\n",
  780.          inf[0].name, inf[1].name);
  781.     }
  782.   else
  783.     fflush (stdout);
  784.  
  785.   if (dir0 != 0)
  786.     free (inf[0].name);
  787.   if (dir1 != 0)
  788.     free (inf[1].name);
  789.  
  790.   return val;
  791. }
  792. @
  793.  
  794.  
  795. 1.2
  796. log
  797. @Amiga port
  798. @
  799. text
  800. @d455 3
  801. d485 38
  802. d525 1
  803. d638 14
  804. d655 1
  805. @
  806.  
  807.  
  808. 1.1
  809. log
  810. @Initial revision
  811. @
  812. text
  813. @d28 3
  814. d32 3
  815. d54 1
  816. a54 1
  817.      char **optionvec;  /* Was `vector', but that collides on Alliant.  */
  818. d159 1
  819. a159 1
  820.       if (c == 0)        /* Long option. */
  821. d273 1
  822. a273 1
  823.          specified regexp.  */
  824. d315 1
  825. a315 1
  826.       /* When comparing directories, 
  827. d333 1
  828. a333 1
  829.          the alignment of the input files.  */
  830. d424 1
  831. a424 1
  832. d486 1
  833. a486 1
  834.      Record in stat_result whether stat fails.  */
  835. d498 1
  836. a498 1
  837.       stat_result[i] = 
  838. d502 1
  839. a502 1
  840.           
  841. d509 1
  842. a509 1
  843.         inf[i].dir_p = 
  844. d561 1
  845. a561 1
  846.       /* If either file should exist but fails to be opened, return 2.  */
  847. d583 1
  848. a583 1
  849.       val = diff_dirs (inf[0].name, inf[1].name, 
  850. @
  851.