/* $Id: package.c,v 1.19 2002/06/23 20:28:31 richdawe Exp $ */

/*
 *  package.c - Package functions for pakke
 *  Copyright (C) 1999-2002 by Richard Dawe
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "common.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* libpakke includes */
#include <libpakke/package.h>

/* Sanity checks */
#if PACKAGE_VERSION_N_HAS != 14
#error "Need to update code to cope with PACKAGE_VERSION's has_*"
#endif

#if PACKAGE_VERSION_N_DATA != 21
#error "Need to update code to cope with PACKAGE_VERSION's data fields"
#endif

/* ---------------------------
 * - package_operator_string -
 * --------------------------- */

char *
package_operator_string (const int op)
{
  switch(op) {
  default:
  case DEP_OP_NONE:         return(" ");    break;
  case DEP_OP_EQUAL:        return(" == "); break;
  case DEP_OP_LESSEQUAL:    return(" <= "); break;
  case DEP_OP_GREATEREQUAL: return(" >= "); break;
  case DEP_OP_NOTEQUAL:     return(" != "); break;
  case DEP_OP_LESS:         return(" < ");  break;
  case DEP_OP_GREATER:      return(" > ");  break;
  }

  return(NULL);
}

/* -----------------------------
 * - package_version_l0_string -
 * ----------------------------- */

char *
package_version_l0_string (const int n)
{
/* If you want more leading zeros than this, you're probably strange. */
#define L0_MAX 16
	   
  static char z[L0_MAX + 1];
  int i, nmax;

  nmax = (n > L0_MAX) ? L0_MAX : n;
  for (i = 0; i < nmax; i++) { z[i] = '0'; }
  z[i] = '\0';

  return(z);
}

/* --------------------------
 * - package_version_string -
 * -------------------------- */

/* This converts a package version structure into a string, using a static
 * buffer. */

char *
package_version_string (const PACKAGE_VERSION *packver)
{
  static char ver[256];
  char buf[256];
  int needspace = 0;

  /* No version => no string */
  if (packver == NULL) return(NULL);

  memset(ver, 0, sizeof(ver));
  memset(buf, 0, sizeof(buf));

  if (packver->has_major) {
    sprintf(ver, "%d", packver->major);
    needspace = 1;
  }

  if (packver->has_minor) {
    strcpy(buf, ver);
    sprintf(ver, "%s.%s%d", buf,
	    package_version_l0_string(packver->minor_l0),
	    packver->minor);
    needspace = 1;
  }

  if (packver->has_subminor) {
    strcpy(buf, ver);
    sprintf(ver, "%s.%s%d", buf,
	    package_version_l0_string(packver->subminor_l0),
	    packver->subminor);
    needspace = 1;
  }

  if (packver->has_subsubminor) {
    strcpy(buf, ver);
    sprintf(ver, "%s.%s%d", buf,
	    package_version_l0_string(packver->subsubminor_l0),
	    packver->subsubminor);
    needspace = 1;
  }

  if (packver->has_alpha) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%salpha %d", buf, packver->alpha);
    needspace = 1;
  }

  if (packver->has_beta) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%sbeta %d", buf, packver->beta);
    needspace = 1;
  }

  if (packver->has_pre) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%spre %d", buf, packver->pre);
    needspace = 1;
  }

  if (packver->has_revision) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%srevision %d", buf, packver->revision);
    needspace = 1;
  }

  if (packver->has_patchlevel) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%spatchlevel %d", buf, packver->patchlevel);
    needspace = 1;
  }

  if (packver->has_snapshot) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%ssnapshot %04i%02i%02i", buf,
	    packver->snapshot_year,
	    packver->snapshot_month,
	    packver->snapshot_day);
    needspace = 1;
  }

  if (packver->has_release) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%srelease %d", buf, packver->release);
    needspace = 1;
  }

  if (packver->has_platform) {
    strcpy(buf, ver);
    if (needspace) strcat(buf, " ");
    sprintf(ver, "%splatform %s-%s-", buf,
	    packver->platform_cpu,
	    packver->platform_manufacturer);
    if (packver->platform_kernel != NULL) {
      strcat(ver, packver->platform_kernel);
      strcat(ver, "-");
    }
    strcat(ver, packver->platform_os);
    needspace = 1;
  }

  /* Always include the package type */
  if (needspace) strcat(ver, " ");
  strcat(ver, "(");
  strcat(ver, package_type_string(packver));
  strcat(ver, ")");
  needspace = 1;

  return(ver);
}

/* ----------------------
 * - package_dep_string -
 * ---------------------- */

/* Format a package/feature dependency in a standard way. A static buffer is
 * used, so be careful. */

char *
package_dep_string (const PACKAGE_DEP *dep)
{
  static char str[1024];
  
  /* Bad dep */
  if (dep->name == NULL)
    return(NULL);

  strcpy(str, dep->name);
  strcat(str, package_operator_string(dep->op));
  strcat(str, package_version_string(&dep->version));

  if (dep->qualifier != NULL) {
    strcat(str, ": ");
    strcat(str, dep->qualifier);
  }

  return(str);
}

/* ---------------------------
 * - package_dep_type_string -
 * --------------------------- */

const char *
package_dep_type_string (const int dep_type)
{
  switch(dep_type) {
  case PACKAGE_DEP_REQUIRES:
    return("requires");

  case PACKAGE_DEP_DEPENDS_ON:
    return("depends-on");

  case PACKAGE_DEP_CONFLICTS_WITH:
    return("conflicts-with");

  case PACKAGE_DEP_REPLACES:
    return("replaces");

  case PACKAGE_DEP_PROVIDES:
    return("provides");

  case PACKAGE_DEP_INSTALL_BEFORE:
    return("install-before");

  case PACKAGE_DEP_INSTALL_AFTER:
    return("install-after");

  default:
    return("");
  }
}

/* -----------------------
 * - package_type_string -
 * ----------------------- */

char *
package_type_string (const PACKAGE_VERSION *ver)
{
  int type = TYPE_NONE;

  if (ver->has_type)
    type = ver->type;

  switch(type) {
  case TYPE_BINARIES:      return("binaries");	
  case TYPE_SOURCES:       return("sources");	
  case TYPE_DOCUMENTATION: return("documentation");
  case TYPE_VIRTUAL:       return("virtual");
  case TYPE_GROUP:         return("group");
  default:                 return("unknown");
  }

  return(NULL);
}

/* ----------------------------
 * - package_version_wildcard -
 * ---------------------------- */

/* This function sets all fields to wildcards in 'ver'. */

int
package_version_wildcard (PACKAGE_VERSION *ver)
{
  ver->has_version     = 1;

  ver->has_major       = 1;
  ver->has_minor       = 1;
  ver->has_subminor    = 1;
  ver->has_subsubminor = 1;
  ver->has_alpha       = 1;
  ver->has_beta        = 1;
  ver->has_pre         = 1;
  ver->has_revision    = 1;
  ver->has_patchlevel  = 1;
  ver->has_snapshot    = 1;
  ver->has_release     = 1;
  ver->has_type        = 1;

/* I'm lazy, so use 'WVAL' to mean wildcard value. */
#define WVAL PACKAGE_VERSION_WILDCARD

  ver->major          = WVAL;
  ver->minor          = WVAL;
  ver->subminor       = WVAL;
  ver->subsubminor    = WVAL;
  ver->alpha          = WVAL;
  ver->beta           = WVAL;
  ver->pre            = WVAL;
  ver->revision       = WVAL;
  ver->patchlevel     = WVAL;
  ver->snapshot_year  = WVAL;
  ver->snapshot_month = WVAL;
  ver->snapshot_day   = WVAL;
  ver->release        = WVAL;

#undef WVAL

  ver->type           = TYPE_WILDCARD;

  return(1);
}

/* -------------------
 * - package_namecmp -
 * ------------------- */

/*
 * This is just a wrapper for a case-insensitive string comparator.
 * We provide this so the code doesn't have to "know" how to compare
 * the package names - just use this standard function instead.
 */

int
package_namecmp (const char *name1, const char *name2)
{
  return(strcasecmp(name1, name2));
}

/* -----------
 * - verdiff -
 * ----------- */

/* This is an internal function used by package_vercmp() and
 * package_vercmp_partial(). */

static void
verdiff (PACKAGE_VERSION *cmp,
	 const PACKAGE_VERSION *ver1, const PACKAGE_VERSION *ver2)
{
  memset(cmp, 0, sizeof(*cmp));

  /* Precedence set 1: If ver2 has, say, a minor version and ver1 doesn't,
   * then ver2 is greater. */
  /* NB: Don't include leading zeroes in the comparison, so 2.3 == 2.03. */
  cmp->major          = ver1->major          - ver2->major;
  cmp->minor          = ver1->minor          - ver2->minor;
  /*cmp->minor_l0       = ver1->minor_l0       - ver2->minor_l0;*/
  cmp->subminor       = ver1->subminor       - ver2->subminor;
  /*cmp->subminor_l0    = ver1->subminor_l0    - ver2->subminor_l0;*/
  cmp->subsubminor    = ver1->subsubminor    - ver2->subsubminor;
  /*cmp->subsubminor_l0 = ver1->subsubminor_l0 - ver2->subsubminor_l0;*/

  /* Precedence set 2: If ver2 has, say, an alpha version and ver1 doesn't,
   * then ver1 is greater. Alpha, beta and pre are different than all
   * the other version components in this respect. */
  cmp->alpha          = ver1->alpha          - ver2->alpha;
  cmp->beta           = ver1->beta           - ver2->beta;
  cmp->pre            = ver1->pre            - ver2->pre;

  /* Precedence set 1: If ver2 has, say, a revision version and ver1 doesn't,
   * then ver2 is greater. */
  cmp->revision       = ver1->revision       - ver2->revision;
  cmp->patchlevel     = ver1->patchlevel     - ver2->patchlevel;
  cmp->snapshot_year  = ver1->snapshot_year  - ver2->snapshot_year;
  cmp->snapshot_month = ver1->snapshot_month - ver2->snapshot_month;
  cmp->snapshot_day   = ver1->snapshot_day   - ver2->snapshot_day;
  cmp->release        = ver1->release        - ver2->release;
  cmp->type           = ver1->type           - ver2->type;

  /* Now handle the case where one of ver1, ver2 does not have
   * one or more of the has_* flags set. */

  /* Handle precedence set 1: If ver1 doesn't have something, but ver2 does,
   * set the cmp value to -1 (ver2 greater). If ver2 doesn't have something,
   * set the cmp value to 1 (ver1 greater). This way
   * version 4 < version 4.0. */
#define HANDLE_HAS_PSET1(h, f) \
do { \
  if (ver1->h != ver2->h) { \
    if (!ver1->h) \
      cmp->f = -1; \
    else \
      cmp->f = 1; \
  } \
} while (0)

  /* Handle precedence set 2: If ver1 doesn't have something, but ver2 does,
   * set the cmp value to 1 (ver1 greater). If ver2 doesn't have something,
   * set the cmp value to -1 (ver2 greater). This way
   * version 4 alpha 1 < version 4. */
#define HANDLE_HAS_PSET2(h, f) \
do { \
  if (ver1->h != ver2->h) { \
    if (!ver1->h) \
      cmp->f = 1; \
    else \
      cmp->f = -1; \
  } \
} while (0)

  HANDLE_HAS_PSET1(has_major,          major);
  HANDLE_HAS_PSET1(has_minor,          minor);
  HANDLE_HAS_PSET1(has_subminor,       subminor);
  HANDLE_HAS_PSET1(has_subsubminor,    subsubminor);

  HANDLE_HAS_PSET2(has_alpha,          alpha);
  HANDLE_HAS_PSET2(has_beta,           beta);
  HANDLE_HAS_PSET2(has_pre,            pre);

  HANDLE_HAS_PSET1(has_revision,       revision);
  HANDLE_HAS_PSET1(has_patchlevel,     patchlevel);
  HANDLE_HAS_PSET1(has_snapshot,       snapshot_year);
  HANDLE_HAS_PSET1(has_snapshot,       snapshot_month);
  HANDLE_HAS_PSET1(has_snapshot,       snapshot_day);
  HANDLE_HAS_PSET1(has_release,        release);
  HANDLE_HAS_PSET1(has_type,           type);

#undef HANDLE_HAS
}

/* ------------------
 * - package_vercmp -
 * ------------------ */

/* This comparison requires all the fields to be initialised in the version
 * structure. The result is equal to the first non-zero component of
 * ver1 - ver2. This, of course, assumes the version numbers are monotonically
 * increasing with development. */

int
package_vercmp (const PACKAGE_VERSION *ver1, const PACKAGE_VERSION *ver2)
{
  PACKAGE_VERSION cmp;
  int p_c, p_m, p_k, p_o;  

  /* Calculate difference */
  verdiff(&cmp, ver1, ver2);

  /* Match the platform case-insensitively. */
  /* TODO: Check platform properly, i.e. allow regexps */
  p_c = p_m = p_k = p_o = 0;

  if ((ver1->platform_cpu != NULL) && (ver2->platform_cpu != NULL))
    p_c = strcasecmp(ver1->platform_cpu, ver2->platform_cpu);

  if (   (ver1->platform_manufacturer != NULL)
      && (ver2->platform_manufacturer != NULL) )
    p_m = strcasecmp(ver1->platform_manufacturer, ver2->platform_manufacturer);

  if ((ver1->platform_os != NULL) && (ver2->platform_os != NULL))
    p_o = strcasecmp(ver1->platform_os, ver2->platform_os);

  if ((ver1->platform_kernel != NULL) && (ver2->platform_kernel != NULL))
    p_k = strcasecmp(ver1->platform_kernel, ver2->platform_kernel);

  if (cmp.major          != 0) return(cmp.major);	
  if (cmp.minor          != 0) return(cmp.minor);
  if (cmp.minor_l0       != 0) return(cmp.minor_l0);
  if (cmp.subminor       != 0) return(cmp.subminor);
  if (cmp.subminor_l0    != 0) return(cmp.subminor_l0);
  if (cmp.subsubminor    != 0) return(cmp.subsubminor);
  if (cmp.subsubminor_l0 != 0) return(cmp.subsubminor_l0);
  if (cmp.alpha          != 0) return(cmp.alpha);
  if (cmp.beta           != 0) return(cmp.beta);
  if (cmp.pre            != 0) return(cmp.pre);
  if (cmp.revision       != 0) return(cmp.revision);
  if (cmp.patchlevel     != 0) return(cmp.patchlevel);
  if (cmp.snapshot_year  != 0) return(cmp.snapshot_year);
  if (cmp.snapshot_month != 0) return(cmp.snapshot_month);
  if (cmp.snapshot_day   != 0) return(cmp.snapshot_day);
  if (cmp.release        != 0) return(cmp.release);
  if (cmp.type           != 0) return(cmp.type);
  if (p_c                != 0) return(p_c);
  if (p_m                != 0) return(p_m);
  if (p_k                != 0) return(p_k);
  if (p_o                != 0) return(p_o);

  return(0);
}

/* --------------------------
 * - package_vercmp_partial -
 * -------------------------- */

/*
 * This performs a partial match between two versions - wildcards are
 * supported in 'ver1' in the compare.
 *
 * This comparison requires all the fields to be initialised in the version
 * structure. The result is equal to the first non-zero component of
 * ver1 - ver2. This, of course, assumes the version numbers are monotonically
 * increasing with development.
 */

int
package_vercmp_partial (const PACKAGE_VERSION *ver1,
			const PACKAGE_VERSION *ver2)
{
  PACKAGE_VERSION cmp;
  int p_c, p_m, p_k, p_o;

  /* Calculate difference */
  verdiff(&cmp, ver1, ver2);

  /* Match the platform case-insensitively. */
  /* TODO: Check platform properly, i.e. allow regexps */
  /* TODO: Wildcards on platform? */
  p_c = p_m = p_k = p_o = 0;

  if ((ver1->platform_cpu != NULL) && (ver2->platform_cpu != NULL))
    p_c = strcasecmp(ver1->platform_cpu, ver2->platform_cpu);

  if (   (ver1->platform_manufacturer != NULL)
      && (ver2->platform_manufacturer != NULL) )
    p_m = strcasecmp(ver1->platform_manufacturer, ver2->platform_manufacturer);

  if ((ver1->platform_os != NULL) && (ver2->platform_os != NULL))
    p_o = strcasecmp(ver1->platform_os, ver2->platform_os);

  if ((ver1->platform_kernel != NULL) && (ver2->platform_kernel != NULL))
    p_k = strcasecmp(ver1->platform_kernel, ver2->platform_kernel);

  /* Handle wildcards - if a wildcard is found in either 'ver1' or 'ver2',
   * zero the wildcarded field. */

/* I'm lazy, so use 'WVAL' to mean wildcard value. */
#define WVAL PACKAGE_VERSION_WILDCARD

  if ((ver1->major == WVAL) || (ver2->major == WVAL))
    cmp.major = 0;

  if ((ver1->minor == WVAL) || (ver2->minor == WVAL))
    cmp.minor = 0;

  if ((ver1->minor_l0 == WVAL) || (ver2->minor_l0 == WVAL))
    cmp.minor_l0 = 0;

  if ((ver1->subminor == WVAL) || (ver2->subminor == WVAL))
    cmp.subminor = 0;

  if ((ver1->subminor_l0 == WVAL) || (ver2->subminor_l0 == WVAL))
    cmp.subminor_l0 = 0;

  if ((ver1->subsubminor == WVAL) || (ver2->subsubminor == WVAL))
    cmp.subsubminor = 0;

  if ((ver1->subsubminor_l0 == WVAL) || (ver2->subsubminor_l0 == WVAL))
    cmp.subsubminor_l0 = 0;

  if ((ver1->alpha == WVAL) || (ver2->alpha == WVAL))
    cmp.alpha = 0;

  if ((ver1->beta == WVAL) || (ver2->beta == WVAL))
    cmp.beta = 0;

  if ((ver1->pre == WVAL) || (ver2->pre == WVAL))
    cmp.pre = 0;

  if ((ver1->revision == WVAL) || (ver2->revision == WVAL))
    cmp.revision = 0;

  if ((ver1->patchlevel == WVAL) || (ver2->patchlevel == WVAL))
    cmp.patchlevel = 0;

  if ((ver1->snapshot_year == WVAL) || (ver2->snapshot_year == WVAL))
    cmp.snapshot_year = 0;

  if ((ver1->snapshot_month == WVAL) || (ver2->snapshot_month == WVAL))
    cmp.snapshot_month = 0;

  if ((ver1->snapshot_day == WVAL) || (ver2->snapshot_day == WVAL))
    cmp.snapshot_day = 0;

  if ((ver1->release == WVAL) || (ver2->release == WVAL))
    cmp.release = 0;

#undef WVAL

  if ((ver1->type == TYPE_WILDCARD) || (ver2->type == TYPE_WILDCARD))
    cmp.type = 0;

  if (cmp.major          != 0) return(cmp.major);	
  if (cmp.minor          != 0) return(cmp.minor);
  if (cmp.minor_l0       != 0) return(cmp.minor_l0);
  if (cmp.subminor       != 0) return(cmp.subminor);
  if (cmp.subminor_l0    != 0) return(cmp.subminor_l0);
  if (cmp.subsubminor    != 0) return(cmp.subsubminor);
  if (cmp.subsubminor_l0 != 0) return(cmp.subsubminor_l0);
  if (cmp.alpha          != 0) return(cmp.alpha);
  if (cmp.beta           != 0) return(cmp.beta);
  if (cmp.pre            != 0) return(cmp.pre);
  if (cmp.revision       != 0) return(cmp.revision);
  if (cmp.patchlevel     != 0) return(cmp.patchlevel);
  if (cmp.snapshot_year  != 0) return(cmp.snapshot_year);
  if (cmp.snapshot_month != 0) return(cmp.snapshot_month);
  if (cmp.snapshot_day   != 0) return(cmp.snapshot_day);
  if (cmp.type           != 0) return(cmp.type);
  if (p_c                != 0) return(p_c);
  if (p_m                != 0) return(p_m);
  if (p_k                != 0) return(p_k);
  if (p_o                != 0) return(p_o);

  return(0);
}

/* ----------------
 * - package_free -
 * ---------------- */

/* This frees all a package's child data. */

int
package_free (PACKAGE_INFO *p)
{
  int i;

  if (p == NULL)
    return(1);

#define FREE(v) \
    free(v), v = NULL

#define FREE_PACKAGE_VERSION(v) \
do { \
  if (v != NULL) { \
    free((v)->platform_cpu),          (v)->platform_cpu = NULL; \
    free((v)->platform_manufacturer), (v)->platform_manufacturer = NULL; \
    free((v)->platform_kernel),       (v)->platform_kernel = NULL; \
    free((v)->platform_os),           (v)->platform_os = NULL; \
  } \
} while (0)

#define FREE_STRINGS(x) \
do { \
  if (x != NULL) { \
    for (i = 0; (x)[i] != NULL; i++) { \
      free((x)[i]), (x)[i] = NULL; \
    } \
  } \
} while (0)

  /* When we switch to char ** instead of char * arrays, we'll need to
   * add "free(x);" to the above macro. */

#define FREE_LIST(x)      FREE_STRINGS(x)
#define FREE_FILE_LIST(x) FREE_STRINGS(x)

  /* DSM header details */
  FREE(p->dsm_author);
  FREE(p->dsm_author_email);
  FREE(p->dsm_author_im);
  FREE(p->dsm_author_web_site);
  FREE(p->dsm_author_ftp_site);

  FREE_PACKAGE_VERSION(&p->dsm_file_version);	
  FREE_PACKAGE_VERSION(&p->dsm_version);

  FREE(p->binaries_dsm);
  FREE(p->sources_dsm);
  FREE(p->documentation_dsm);

  /* Don't touch cross-references. */

  /* Descriptive details */
  FREE_PACKAGE_VERSION(&p->version);
  FREE(p->long_description);

  FREE(p->license);
  FREE(p->organisation);

  FREE_LIST(p->author);
  FREE_LIST(p->author_email);
  FREE_LIST(p->author_im);

  FREE_LIST(p->web_site);
  FREE_LIST(p->ftp_site);

  FREE_LIST(p->maintainer);
  FREE_LIST(p->maintainer_email);
  FREE_LIST(p->maintainer_im);
  FREE_LIST(p->maintainer_web_site);
  FREE_LIST(p->maintainer_ftp_site);
	
  FREE_LIST(p->porter);
  FREE_LIST(p->porter_email);
  FREE_LIST(p->porter_im);
  FREE_LIST(p->porting_web_site);
  FREE_LIST(p->porting_ftp_site);

  FREE_LIST(p->mailing_list);
  FREE_LIST(p->mailing_list_description);
  FREE_LIST(p->mailing_list_request);	
  FREE_LIST(p->mailing_list_administrator);
  FREE_LIST(p->mailing_list_administrator_email);
  FREE_LIST(p->mailing_list_administrator_im);
  FREE_LIST(p->mailing_list_web_site);
  FREE_LIST(p->mailing_list_ftp_site);

  FREE_LIST(p->newsgroup);
  FREE_LIST(p->newsgroup_description);
  FREE_LIST(p->newsgroup_email_gateway);
  FREE_LIST(p->newsgroup_administrator);
  FREE_LIST(p->newsgroup_administrator_email);
  FREE_LIST(p->newsgroup_administrator_im);
  FREE_LIST(p->newsgroup_web_site);
  FREE_LIST(p->newsgroup_ftp_site);

  /* Package file details. */	
  FREE_FILE_LIST(p->zip);
  FREE(p->zip_options);
  FREE_FILE_LIST(p->tar_gzip);
  FREE(p->tar_gzip_options);

  /* Installation */
  FREE(p->pre_install_readme);
  FREE(p->post_install_readme);
  FREE(p->pre_uninstall_readme);
  FREE(p->post_uninstall_readme);

  FREE(p->builtin_pre_install_script);
  FREE(p->builtin_post_install_script);
  FREE(p->builtin_pre_uninstall_script);
  FREE(p->builtin_post_uninstall_script);

  FREE(p->pre_install_script);
  FREE(p->post_install_script);
  FREE(p->pre_uninstall_script);
  FREE(p->post_uninstall_script);

  FREE_FILE_LIST(p->keep_file);

  FREE(p->prefix);

  /* Package dependencies */
  if (p->deps) {					
    for (i = 0; (p->deps)[i] != NULL; i++) { 
      FREE((p->deps)[i]->qualifier);		
      FREE_PACKAGE_VERSION(&(p->deps)[i]->version);
      FREE((p->deps)[i]);				
    }						
  }

  FREE(p->install_warning);

#undef FREE
#undef FREE_PACKAGE_VERSION
#undef FREE_STRINGS
#undef FREE_LIST
#undef FREE_FILE_LIST

  return(1);
}

/* ------------------------
 * - package_set_defaults -
 * ------------------------ */

/* Set some sensible defaults for a package. */

int
package_set_defaults (PACKAGE_INFO *package)
{
  package->duplicate_action = DUP_QUERY;

  return(1);
}
