bug-textutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

patch: textutils-2.1/src/join.c: support field ranges with `-o'


From: Toomas Rosin
Subject: patch: textutils-2.1/src/join.c: support field ranges with `-o'
Date: Sun Sep 15 16:56:03 2002

Hello!

I have a script that does, at one point, something like this:

   join -a1 -a2 -e- -13 -26                              \
       -o 1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.10,1.11  \
       -o 2.1,2.2,2.3,2.4,2.5,2.6,2.7                    \
       file1 file2

(horrors!).  The appended patch makes it possible to do the same thing
as follows:

   join -a1 -a2 -e- -13 -26 -o1.1-11,2.1-7 file1 file2

.  I am not very sure that my patch has no bugs, but the patched
`join' has already worked correctly for me in several situations, and
it passes "make check".  It also differs from the original `join' in
that it tolerates redundant field separator characters ([, \t]).
(This could be reverted by rewriting the check for "*q == '\0'" (line
658 in the patched join.c).)

As `cut' recognizes field ranges, should `join' not?

Have a nice day,
Toomas.

--- textutils-2.1/src/join.c.orig       Tue Jul  2 07:15:06 2002
+++ textutils-2.1/src/join.c    Sun Sep 15 22:48:17 2002
@@ -615,63 +615,7 @@
   /* Add to the end of the list so the fields are in the right order.  */
   outlist_end->next = o;
   outlist_end = o;
-}
-
-/* Convert a single field specifier string, S, to a *FILE_INDEX, *FIELD_INDEX
-   pair.  In S, the field index string is 1-based; *FIELD_INDEX is zero-based.
-   If S is valid, return zero.  Otherwise, give a diagnostic, don't update
-   *FILE_INDEX or *FIELD_INDEX, and return nonzero.  */
-
-static int
-decode_field_spec (const char *s, int *file_index, int *field_index)
-{
-  int invalid = 1;
-
-  /* The first character must be 0, 1, or 2.  */
-  switch (s[0])
-    {
-    case '0':
-      if (s[1] == '\0')
-       {
-         *file_index = 0;
-         /* Give *field_index an invalid value.  */
-         *field_index = -1;
-         invalid = 0;
-       }
-      else
-        {
-         /* `0' must be all alone -- no `.FIELD'.  */
-         error (0, 0, _("invalid field specifier: `%s'"), s);
-       }
-      break;
-
-    case '1':
-    case '2':
-      if (s[1] == '.' && s[2] != '\0')
-        {
-         strtol_error s_err;
-         long int tmp_long;
-
-         s_err = xstrtol (s + 2, NULL, 10, &tmp_long, "");
-         if (s_err != LONGINT_OK || tmp_long <= 0 || tmp_long > INT_MAX)
-           {
-             error (0, 0, _("invalid field number: `%s'"), s + 2);
-           }
-         else
-           {
-             *file_index = s[0] - '0';
-             /* Convert to a zero-based index.  */
-             *field_index = (int) tmp_long - 1;
-             invalid = 0;
-           }
-       }
-      break;
-
-    default:
-      error (0, 0, _("invalid file number in field spec: `%s'"), s);
-      break;
-    }
-  return invalid;
+  uni_blank.nfields = max (uni_blank.nfields, field);
 }
 
 /* Add the comma or blank separated field spec(s) in STR to `outlist'.
@@ -686,23 +630,84 @@
   str = (char *) alloca (strlen (c_str) + 1);
   strcpy (str, c_str);
 
+#define FIELDSPEC_ASSERT(condition)                         \
+      do                                                    \
+        {                                                   \
+          if (condition)                                    \
+            break;                                          \
+          error (0, 0, _("invalid field specifier: `%s'"),  \
+                 spec_item);                                \
+          return 1;                                         \
+        }                                                   \
+      while (0)
+
   p = str;
   do
     {
-      int invalid;
       int file_index, field_index;
-      char *spec_item = p;
-
+      char *spec_item, *q;
+      strtol_error s_err;
+      long lo, hi;
+      
+      lo = hi = 0;
+      q = spec_item = p;
       p = strpbrk (p, ", \t");
       if (p)
         *p++ = 0;
-      invalid = decode_field_spec (spec_item, &file_index, &field_index);
-      if (invalid)
-       return 1;
-      add_field (file_index, field_index);
-      uni_blank.nfields = max (uni_blank.nfields, field_index);
+
+      if (*q == '\0')
+        {
+          /* Redundant separator.  */
+          continue;
+        }
+
+      if (*q == '0')
+        {
+          add_field (0, -1);
+          /* `0' must be all alone -- no `.FIELD'.  */
+          FIELDSPEC_ASSERT (*++q == 0);
+          continue;
+        }
+
+      FIELDSPEC_ASSERT ((*q == '1') || (*q == '2'));
+      file_index = *q - '0';
+      FIELDSPEC_ASSERT (*++q == '.');
+
+      FIELDSPEC_ASSERT (isdigit (*++q));
+      s_err = xstrtol (q, &q, 10, &lo, NULL);
+      FIELDSPEC_ASSERT ((s_err == LONGINT_OK) &&
+                        (lo > 0) &&
+                        (lo <= INT_MAX));
+
+      if (*q == '\0')
+        {
+          /* A single field.  */
+          add_field (file_index, lo - 1);
+          continue;
+        }
+
+      FIELDSPEC_ASSERT (*q == '-');
+      FIELDSPEC_ASSERT (isdigit (*++q));
+
+      /* Field range.  */
+      s_err = xstrtol (q, &q, 10, &hi, "");
+      FIELDSPEC_ASSERT ((s_err == LONGINT_OK) &&
+                        (hi >= lo) &&
+                        (hi <= INT_MAX) &&
+                        (*q == 0));
+
+      /* Convert to a zero-based index.  */
+      hi--, lo--;
+
+      for (; lo <= hi; lo ++)
+        {
+          add_field (file_index, lo);
+        }
     }
   while (p);
+
+#undef FIELDSPEC_ASSERT
+
   return 0;
 }
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]