Logo Search packages:      
Sourcecode: ksh version File versions

release.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*                  Copyright (c) 1994-2005 AT&T Corp.                  *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                            by AT&T Corp.                             *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                                                                      *
***********************************************************************/
#pragma prototyped

/*
 * release -- list recent release changes
 *
 * coded for portability
 */

static char id[] = "\n@(#)$Id: release (AT&T Labs Research) 2000-01-28 $\0\n";

#if _PACKAGE_ast

#include <ast.h>
#include <error.h>

static const char usage[] =
"[-?\n@(#)$Id: release (AT&T Labs Research) 2000-01-28 $\n]"
USAGE_LICENSE
"[+NAME?release - list recent changes]"
"[+DESCRIPTION?\brelease\b lists the changes within the date range specified"
"     by the \b--from\b and \b--to\b options. The input files are assumed to"
"     contain date tag lines of the form [\acc\a]]\ayy-mm-dd\a [ \atext\a ]]"
"     (or \bdate\b(1) default format), where \acc\a is determined by a Y2K"
"     window year of 69 (we can produce an example coding dated 1991 - this"
"     can be patented?, how about 1+1=2?.) The date tag lines are followed by"
"     \areadme\a text in reverse chronological order (newer entries at the"
"     top of the file.) If no selection options are spcified then all"
"     changes are listed.]"
"[+?The entries for each \afile\a are annotated with the file directory name.]"
"[f:from?Entries older than \adate\a are omitted.]:[date]"
"[r:release?List all changes that include the first \acount\a release marks."
"     A release mark has a date tag followed by optional space and at least"
"     three \b-\b characters. Changes from release mark \acount\a+1 are not"
"     listed. If there are no release marks then the date range is used;"
"     if there is at least one release mark then the date range is ignored"
"     and at most \acount\a release marks will be listed.]#[count]"
"[t:to?Entries newer than \adate\a are omitted.]:[date]"
"[V?Print the program version and exit.]"

"\n"
"\nfile ...\n"
"\n"

"[+SEE ALSO?\bpackage\b(1)]"
;

#else

#define elementsof(x)   ((int)(sizeof(x)/sizeof(x[0])))

#define NiL       ((char*)0)

#endif

#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>

#if !_PACKAGE_ast && defined(__STDC__)
#include <stdlib.h>
#include <string.h>
#endif

static char mon[] = "janfebmaraprmayjunjulaugsepoctnovdec";
static char day[] = "sunmontuewedthufrisat";

#if !_PACKAGE_ast

static void
usage()
{
      fprintf(stderr, "Usage: release [-V] [-h hi-date] [-l lo-date] [-r count] [ file ...]\n");
      exit(2);
}

#endif

static unsigned long
number(register char* s, char** e)
{
      unsigned long     q = 0;

      while (isspace(*s))
            s++;
      while (isdigit(*s))
            q = q * 10 + *s++ - '0';
      if (e)
            *e = s;
      return q;
}

unsigned long
string(register char* s, char* tab, int num, int siz, char** e)
{
      register int      i;
      register int      j;
      char        buf[16];

      while (isspace(*s))
            s++;
      for (i = 0; i < siz; i++)
            buf[i] = isupper(s[i]) ? tolower(s[i]) : s[i];
      for (i = 0; i < num; i += siz)
            for (j = 0; j < siz && buf[j] == tab[j+i]; j++)
                  if (j == (siz - 1))
                  {
                        *e = s + siz;
                        return i / siz + 1;
                  }
      return 0;
}

static unsigned long
date(char* s, char** e)
{
      char*       t;
      unsigned long     y;
      unsigned long     m;
      unsigned long     d;

      if (isdigit(*s))
      {
            y = number(s, &t);
            if (*t != '-')
                  return 0;
            switch (t - s)
            {
            case 2:
                  y += 1900;
                  if (y <= 1969)
                        y += 100;
                  break;
            case 4:
                  if (y < 1969)
                        return 0;
                  break;
            }
            if (!(m = number(++t, &s)))
                  return 0;
            if ((s - t) != 2 || *s != '-' || m < 1 || m > 12)
                  return 0;
            if (!(d = number(++s, &t)))
                  return 0;
            if ((t - s) != 2 || d < 1 || d > 31)
                  return 0;
      }
      else
      {
            if (string(s, day, elementsof(day), 3, &t))
                  s = t;
            if (!(m = string(s, mon, elementsof(mon), 3, &t)))
                  return 0;
            if (!(d = number(t, &s)))
                  return 0;
            for (; *s; s++)
                  if ((y = number(s, &t)) && (t - s) == 4)
                  {
                        if (y < 1969)
                              return 0;
                        break;
                  }
      }
      if (e)
      {
            while (isspace(*t))
                  t++;
            *e = t;
      }
      return ((y - 1969) * 13 + m) * 32 + d;
}

int
main(int argc, char** argv)
{
      register char*          s;
      register char*          u;
      register char*          v;
      char*             p;
      char*             e;
      int               i;
      unsigned long           t;
      unsigned long           lo;
      unsigned long           hi;
      int               mk;
      FILE*             f;
      char              buf[1024];

      mk = 0;
      lo = hi = 0;
#if _PACKAGE_ast
      error_info.id = "release";
      for (;;)
      {
            switch (optget(argv, usage))
            {
            case 'f':
                  if (!(lo = date(opt_info.arg, &e)) || *e)
                  {
                        error(2, "%s: invalid from date [%s]", opt_info.arg, e);
                        return 1;
                  }
                  continue;
            case 'r':
                  mk = opt_info.num + 1;
                  continue;
            case 't':
                  if (!(hi = date(opt_info.arg, &e)) || *e)
                  {
                        error(2, "%s: invalid to date [%s]", opt_info.arg, e);
                        return 1;
                  }
                  continue;
            case 'V':
                  sfprintf(sfstdout, "%s\n", id + 10);
                  return 0;
            case '?':
                  error(ERROR_USAGE|4, "%s", opt_info.arg);
                  continue;
            case ':':
                  error(2, "%s", opt_info.arg);
                  continue;
            }
            break;
      }
      if (error_info.errors)
            error(ERROR_USAGE|4, "%s", optusage(NiL));
      argv += opt_info.index;
#else
      while ((s = *++argv) && *s == '-' && *(s + 1))
      {
            if (*(s + 1) == '-')
            {
                  if (!*(s + 2))
                  {
                        argv++;
                        break;
                  }
                  usage();
                  break;
            }
            for (;;)
            {
                  switch (i = *++s)
                  {
                  case 0:
                        break;
                  case 'f':
                  case 't':
                        if (!*(v = ++s) && !(v = *++argv))
                        {
                              s = "??";
                              continue;
                        }
                        if (!(t = date(v, &e)) || *e)
                        {
                              fprintf(stderr, "release: -%c%s: invalid date [%s]\n", i, s, e);
                              return 1;
                        }
                        switch (i)
                        {
                        case 'f':
                              lo = t;
                              break;
                        case 't':
                              hi = t;
                              break;
                        }
                        break;
                  case 'r':
                        if (!*(v = ++s) && !(v = *++argv))
                        {
                              s = "??";
                              continue;
                        }
                        mk = number(v, &e) + 1;
                        if (*e)
                        {
                              fprintf(stderr, "release: -%c%s: invalid count\n", i, s);
                              return 1;
                        }
                        break;
                  case 'V':
                        fprintf(stdout, "%s\n", id + 10);
                        return 0;
                  default:
                        fprintf(stderr, "release: -%c: unknown option\n", i);
                        /*FALLTHROUGH*/
                  case '?':
                        usage();
                        break;
                  }
                  break;
            }
      }
#endif
      do
      {
            if (!(p = *argv++) || !*p || *p == '-' && !*(p + 1))
            {
                  argv--;
                  p = "";
                  f = stdin;
            }
            else if (!(f = fopen(p, "r")))
            {
                  fprintf(stderr, "release: %s: cannot read", p);
                  return 1;
            }
            while (s = fgets(buf, sizeof(buf), f))
            {
                  if (t = date(s, &e))
                  {
                        if (mk && e[0] == '-' && e[1] == '-' && e[2] == '-' && !--mk)
                              break;
                        if (t < lo)
                              break;
                        if (hi && t > hi)
                              continue;
                        if (p)
                        {
                              if (*p)
                              {
                                    for (u = v = p; *p; p++)
                                          if (*p == '/')
                                          {
                                                v = u;
                                                u = p + 1;
                                          }
                                    printf("\n:::::::: ");
                                    while ((i = *v++) && i != '/')
                                          fputc(i, stdout);
                                    printf(" ::::::::\n\n");
                              }
                              p = 0;
                        }     
                  }
                  if (!p)
                        fputs(s, stdout);
            }
            if (f == stdin)
                  break;
            fclose(f);
      } while (*argv);
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index