/* Perform queries on the contents of a GNATS database.
   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
   Contributed by Brendan Kehoe (brendan@cygnus.com).

This file is part of GNU GNATS.

GNU GNATS 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.

GNU GNATS 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 GNU GNATS; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA.  */

#include "config.h"
#include "gnats.h"
#include "query.h"

/* The name this program was run with.  */
char *program_name;

/* If 1, don't allow redirection or viewing of confidential PRs.  */
int restricted = 0;

/* If 1, we're running the daemon.  */
int is_daemon = 0;

extern FILE *outfile;

struct option long_options[] =
{
  {"category", 1, NULL, 'c'},
  {"confidential", 1, NULL, 'C'},
  {"directory", 1, NULL, 'd'},
  {"full", 0, NULL, 'F'},
  {"help", 0, NULL, 'h'},
  {"multitext", 1, NULL, 'm'},
  {"originator", 1, NULL, 'O'},
  {"class", 1, NULL, 'L'},
#ifdef GNATS_RELEASE_BASED
  {"quarter", 1, NULL, 'Q'},
  {"keywords", 1, NULL, 'K'},
#endif
  {"output", 1, NULL, 'o'},
  {"priority", 1, NULL, 'p'},
  {"print-path", 0, NULL, 'P'},
  {"responsible", 1, NULL, 'r'},
  {"restricted", 0, NULL, 'R'},
  {"severity", 1, NULL, 'e'},
  {"skip-closed", 0, NULL, 'x'},
  {"sql", 0, NULL, 'i'},
  {"state", 1, NULL, 's'},
  {"summary", 0, NULL, 'q'},
  {"submitter", 1, NULL, 'S'},
  {"text", 1, NULL, 't'},
#ifdef GNATS_RELEASE_BASED
  {"required-before", 1, NULL, 'u'},
  {"required-after", 1, NULL, 'U'},
#endif
  {"arrived-before", 1, NULL, 'b'},
  {"arrived-after", 1, NULL, 'a'},
  {"list-categories", 0, NULL, 'j'},
  {"list-responsible", 0, NULL, 'k'},
  {"list-submitters", 0, NULL, 'l'},
  {"version", 0, NULL, 'V'},
  {"date", 1, NULL, 'D'},
  {"startdate", 1, NULL, 'T'},
  {"enddate", 1, NULL, 'E'},
  {NULL, 0, NULL, 0}
};

void usage (), version ();

void
start_data ()
{
  return; /* Nothing */
}

int
query_pr (p, s)
     char *p;
     Index *s;
{
  char *path;
  Index *i;
  int found = 0;

  if (p == NULL)
    {
      /* We weren't given a list of PRs to check, so we do the
	 whole shooting match.  */
      for (i = index_chain; i ; i = i->next)
	if (pr_matches (s, i) && do_pr (i))
	  {
	    found = 1;
	    fprintf (outfile, "\n");
	  }
    }
  else
    {
      if (searching || numeric (p))
	{
	  char pat[40];
	  strcpy (pat, p);
	  strcat (pat, "\\'");

	  for (i = index_chain; i ; i = i->next)
	    if (regcmp (pat, i->number) == 0)
	      {
		if (pr_matches (s, i) && do_pr (i))
		  {
		    found = 1;
		    fprintf (outfile, "\n");
		  }
	      }
	}
      else
	{
	  /* They did a plain query-pr with a list of PRs, just print
	     this one out.  */
	  if (((char *) strchr (p, '/')) == NULL)
	    path = get_category (p);
	  else
	    {
	      path = (char *) xmalloc (PATH_MAX);
	      sprintf (path, "%s/%s", gnats_root, p);
	    }

	  if (path)
	    {
	      if (do_pr_internal (path, p)
		  && ! (skip_closed
			&& strcmp (pr[STATE].value, "closed") == 0))
		{
		  found = 1;
		  print_pr (path, p, 1);
		  fprintf (outfile, "\n");
		}		  
	      xfree (path);
	    }
	}
    }

  return !found;
}

int
main (argc, argv)
     int argc;
     char **argv;
{
  int optc;
  Index *s;
  int errors = 0;
  char *spec_gnats_root = 0;
  int formats = 0, lists = 0;

  program_name = basename (argv[0]);
  if (argc == 1)
    usage (1);

  s = (Index *) xmalloc (sizeof (Index));
  memset (s, 0, sizeof (Index));

  while ((optc = getopt_long (argc, argv, "c:C:d:e:L:m:o:O:p:Ps:S:r:T:E:D:t:u:U:VFixhqRjkl",
			      long_options, (int *) 0)) != EOF)
    {
      switch (optc)
	{
	case 'd':
	  spec_gnats_root = optarg;
	  break;

	case 'o':
	  if (strcmp (optarg, "-") && !restricted)
	    {
	      outfile = fopen (optarg, "w+");
	      if (outfile == (FILE *) NULL)
		{
		  fprintf (stderr, "can not read file %s", optarg);
		  exit (3);
		}
	    }
	  break;

	case 'r':
	  s->responsible = optarg;
	  searching = 1;
	  break;

	case 'R':
	  restricted = 1;
	  outfile = stdout;
	  s->confidential = "no";
	  searching = 1;
	  break;

	case 'c':
	  s->category = optarg;
	  searching = 1;
	  break;

	case 'C':
	  if (!restricted) s->confidential = optarg;
	  searching = 1;
	  break;

	case 'e':
	  s->severity = optarg;
	  searching = 1;
	  break;

	case 'L':
	  class = optarg;
	  break;

#ifdef GNATS_RELEASE_BASED
	case 'Q':
	  quarter = optarg;
	  break;

	case 'K':
	  keywords = optarg;
	  break;
#endif

	case 'm':
	  m_text_search = optarg;
	  break;

	case 'O':
	  originator = optarg;
	  break;

	case 'p':
	  s->priority = optarg;
	  searching = 1;
	  break;

	case 'P':
	  print_path = 1;
	  break;

	case 's':
	  s->state = optarg;
	  searching = 1;
	  break;

	case 'S':
	  s->submitter = optarg;
	  searching = 1;
	  break;

	case 't':
	  text_search = optarg;
	  break;

	case 'D':
	  date_search = optarg;
	  break;

	case 'T':
	  startdate_search = optarg;
	  break;

	case 'E':
	  enddate_search = optarg;
	  break;

	case 'V':
	  version ();
	  exit (0);
	  break;

	case 'F':
	  query_format = FORMAT_FULL;
	  formats++;
	  break;

	case 'i':
	  query_format = FORMAT_SQL;
	  formats++;
	  break;

	case 'q':
	  query_format = FORMAT_SUMM;
	  formats++;
	  break;

	case 'x':
	  skip_closed = 1;
	  break;

	case 'j':
	  list_format = LIST_CATEGORIES;
	  lists++;
	  break;

	case 'k':
	  list_format = LIST_RESPONSIBLE;
	  lists++;
	  break;

	case 'l':
	  list_format = LIST_SUBMITTERS;
	  lists++;
	  break;

	case 'u':
	  before = get_date (optarg, NULL);
	  if (before < 0)
	    {
	      fprintf (stderr, "%s: could not decypher `%s'\n",
		       program_name, optarg);
	      exit (1);
	    }
	  searching = 1;
	  break;

	case 'U':
	  after = get_date (optarg, NULL);
	  if (after < 0)
	    {
	      fprintf (stderr, "%s: could not decypher `%s'\n",
		       program_name, optarg);
	      exit (1);
	    }
	  searching = 1;
	  break;

	case 'h':
	  usage (0);
	  break;

	default:
	  usage (1);
	}
    }

  if (spec_gnats_root && !restricted)
    gnats_root = spec_gnats_root;

  if (formats > 1)
    {
      fprintf (stderr, "%s: only one of -i, -F, or -q may be specified\n",
	       program_name);
      exit (3);
    }

  if (lists > 1)
    {
      fprintf (stderr, "%s: only one of -j, -k, or -l may be specified alone\n",
	       program_name);
      exit (4);
    }

  configure ();
  init_gnats ();

  if (lists)
    {
      get_gnats_file (list_format, NULL);
      exit (0);
    }

  re_set_syntax ((RE_SYNTAX_POSIX_EXTENDED | RE_BK_PLUS_QM) & ~RE_DOT_NEWLINE);

  /* Don't emit any errors from get_pr.  */
  quiet = 1;

  index_chain = get_index ();
  if (index_chain == NULL)
    {
      fprintf (stderr, "%s: couldn't read the index\n", program_name);
      exit (1);
    }

  if (optind == argc)
    {
      if (! searching)
	errors += query_pr ((char *) NULL, (Index *) NULL);
      else
	errors += query_pr ((char *) NULL, s);
    }
  else
    {
      while (optind < argc)
	errors += query_pr (argv[optind++], searching ? s : (Index *) NULL);
    }

  if (errors > 0)
    fprintf (stderr, "%s: no PRs matched\n", program_name);

  /* Exit non-zero if there were any troubles.  */
  exit (errors != 0);
}

void
usage (s)
     int s;
{
#ifdef GNATS_RELEASE_BASED
  fprintf (stderr, "\
Usage: %s [-FhiPqVx] [-C confidential] [-D date] [-c category] [-d directory]\n\
       [-e severity] [-m mtext] [-O originator] [-o outfile] [-p priority]\n\
       [-L class] [-r responsible] [-S submitter] [-T startdate] [-E enddate]\n\
       [-s state] [-t text] [--full] [--help] [--sql] [--print-path] [--summary]\n\
       [--version] [--skip-closed] [--category=category] [--confidential=yes|no]\n\
       [--directory=directory] [--output=outfile] [--originator=name]\n\
       [--priority=level] [--class=class] [--responsible=person]\n\
       [--quarter=quarter] [--keywords=regexp]\n\
       [--required-before=date] [--required-after=date]\n\
       [--severity=severity] [--state=state] [--submitter=submitter]\n\
       [--list-categories] [--list-responsible] [--list-submitters] [--text=text]\n\
       [--multitext=mtext] [--date=date] [--startdate=startdate] [--enddate=enddate] [PR] [PR]...\n",
	   program_name);
#else
  fprintf (stderr, "\
Usage: %s [-FhiPqVx] [-C confidential] [-c category] [-d directory]\n\
       [-e severity] [-m mtext] [-O originator] [-o outfile] [-p priority]\n\
       [-L class] [-r responsible] [-S submitter] [-s state] [-t text]\n\
       [--full] [--help] [--sql] [--print-path] [--summary] [--version]\n\
       [--skip-closed] [--category=category] [--confidential=yes|no]\n\
       [--directory=directory] [--output=outfile] [--originator=name]\n\
       [--priority=level] [--class=class] [--responsible=person]\n\
       [--quarter=quarter] [--keywords=regexp]\n\
       [--severity=severity] [--state=state] [--submitter=submitter]\n\
       [--list-categories] [--list-responsible] [--list-submitters]\n\
       [--text=text] [--multitext=mtext] [PR] [PR]...\n",
	   program_name);
#endif
  exit (s);
}

void
version ()
{
  printf ("query-pr %s\n", version_string);
}
