/* This file is part of cqual.
   Copyright (C) 2000-2002 The Regents of the University of California.

cqual 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.

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

#include <string.h>
#include "location.h"
#include "utils.h"
#include "typed_map.h"

unsigned long location_hash(location loc)
{
  unsigned long h;

  h = 0;
  h = loc->lineno;
  h = 33*h + 720 + loc->filepos;
  h = 33*h + 720 + string_hash(loc->filename);
  return h;
}

bool location_eq(location loc1, location loc2)
{
  return (loc1->lineno == loc2->lineno &&
	  loc1->filepos == loc2->filepos &&
	  loc1->in_system_header == loc2->in_system_header &&
	  !strcmp(loc1->filename, loc2->filename));
}

int location_cmp(location loc1, location loc2)
{
  int result;

  result = strcmp(loc1->filename, loc2->filename);
  if (!result)
    result = loc1->filepos - loc2->filepos;
  return result;
}

int location_index(location loc)
{
  return loc->location_index;
}


DEFINE_MAP(file_orig_file_map, const char *, const char *, string_hash, string_eq);
#define scan_file_orig_file_map(kvar, dvar, scanner, map) \
for (file_orig_file_map_scan(map, &scanner); \
     file_orig_file_map_next(&scanner, &kvar, &dvar);)

static region file_region = NULL;
static file_orig_file_map file_orig_files = NULL;

/* Set the original .c file that a preprocessed output
   file was derived from. */
void file_set_orig_name(const char *name, const char *orig_name)
{
  if (!file_orig_files) 
    {
      if (!file_region)
	file_region = newregion();
      file_orig_files = make_file_orig_file_map(file_region, 37);
    }
  insist(file_orig_file_map_insert(file_orig_files, name, orig_name));
}

const char *file_get_orig_name(const char *name)
{
  const char *orig_name;
  if (!file_orig_files)
    return NULL;
  else if (file_orig_file_map_lookup(file_orig_files, name, &orig_name))
    return orig_name;
  else
    return NULL;
}

DEFINE_MAP(file_isprelude_map, const char *, intptr_t, string_hash, string_eq);
#define scan_file_isprelude_map(kvar, dvar, scanner, map) \
for (file_isprelude_map_scan(map, &scanner); \
     file_isprelude_map_next(&scanner, &kvar, &dvar);)

static file_isprelude_map preludes_map;

/* Mark a file as a prelude file */
void file_set_isprelude(const char *name, bool isprelude)
{
  intptr_t iisprelude = isprelude;
  if (!preludes_map)
    {
      if (!file_region)
	file_region = newregion();
      preludes_map = make_file_isprelude_map(file_region, 37);
    }
  insist(file_isprelude_map_insert(preludes_map, name, iisprelude));
}

bool file_get_isprelude(const char *name)
{
  intptr_t isprelude;
  if (!preludes_map)
    return FALSE;
  else if (file_isprelude_map_lookup(preludes_map, name, &isprelude))
    return (int)isprelude;
  else
    return FALSE;
}

