--- /dev/null
+/* Arithmetic for numbers greater than a long int, for GNU tar.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "system.h"
+
+/* common.h is needed to define FATAL_ERROR. It also includes arith.h. */
+#include "common.h"
+
+/* GNU tar needs handling numbers exceeding 32 bits, which is the size of
+ unsigned long ints for many C compilers. This module should provide
+ machinery for handling at least BITS_PER_TARLONG bits per number. If
+ `long long' ints are available and are sufficient for the task, they will
+ be used preferrably.
+
+ Russell Cattelan reports 165 Gb single tapes (digital video D2 tapes on
+ Ampex drives), so requiring 38 bits for the tape length in bytes. He
+ also reports breaking the terabyte limit with a single file (using SGI
+ xFS file system over 37 28GB disk arrays attached to a Power Challenge
+ XL; check out http://www.lcse.umn.edu/ for a picture), so requiring a
+ little more than 40 bits for the file size in bytes. The POSIX header
+ structure allows for 12 octal digits to represent file lengths, that is,
+ up to 36 bits for the byte size of files.
+
+ If `long long' is not supported by the compiler, SIZEOF_LONG_LONG will be
+ set to zero by configure. In this case, or if `long long' ints does not
+ have enough bits, then huge numbers are rather represented by an array of
+ longs, with the least significant super-digit at position 0. For making
+ multiplication and decimal input/output easy, the base of a super-digit
+ is an exact exponent of 10, and is such that base*base fits in a long. */
+
+#if SUPERDIGIT
+
+/*-------------------------------.
+| Check if ACCUMULATOR is zero. |
+`-------------------------------*/
+
+int
+zerop_tarlong_helper (unsigned long *accumulator)
+{
+ int counter;
+
+ for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
+ if (accumulator[counter])
+ return 0;
+
+ return 1;
+}
+
+/*----------------------------------------------.
+| Check if FIRST is strictly less than SECOND. |
+`----------------------------------------------*/
+
+int
+lessp_tarlong_helper (unsigned long *first, unsigned long *second)
+{
+ int counter;
+
+ for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
+ if (first[counter] != second[counter])
+ return first[counter] < second[counter];
+
+ return 0;
+}
+
+/*----------------------------.
+| Reset ACCUMULATOR to zero. |
+`----------------------------*/
+
+void
+clear_tarlong_helper (unsigned long *accumulator)
+{
+ int counter;
+
+ for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
+ accumulator[counter] = 0;
+}
+
+/*----------------------------.
+| To ACCUMULATOR, add VALUE. |
+`----------------------------*/
+
+void
+add_to_tarlong_helper (unsigned long *accumulator, int value)
+{
+ int counter;
+
+ if (value < 0)
+ for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
+ {
+ if (accumulator[counter] >= -value)
+ {
+ accumulator[counter] += value;
+ return;
+ }
+ accumulator[counter] += value + SUPERDIGIT;
+ value = -1;
+ }
+ else
+ for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
+ {
+ if (accumulator[counter] + value < SUPERDIGIT)
+ {
+ accumulator[counter] += value;
+ return;
+ }
+ accumulator[counter] += value - SUPERDIGIT;
+ value = 1;
+ }
+ FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
+}
+
+/*--------------------------------.
+| Multiply ACCUMULATOR by VALUE. |
+`--------------------------------*/
+
+void
+mult_tarlong_helper (unsigned long *accumulator, int value)
+{
+ int carry = 0;
+ int counter;
+
+ for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
+ {
+ carry += accumulator[counter] * value;
+ accumulator[counter] = carry % SUPERDIGIT;
+ carry /= SUPERDIGIT;
+ }
+ if (carry)
+ FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
+}
+
+/*----------------------------------------------------------.
+| Print the decimal representation of ACCUMULATOR on FILE. |
+`----------------------------------------------------------*/
+
+void
+print_tarlong_helper (unsigned long *accumulator, FILE *file)
+{
+ int counter = LONGS_PER_TARLONG - 1;
+
+ while (counter > 0 && accumulator[counter] == 0)
+ counter--;
+
+ fprintf (file, "%uld", accumulator[counter]);
+ while (counter > 0)
+ fprintf (file, TARLONG_FORMAT, accumulator[--counter]);
+}
+
+#endif /* SUPERDIGIT */