BEGIN {

  read_index_file(orig_files_loc_of, orig_files_tag_of, orig_files_full_index_file);
  read_index_file(orig_dirs_loc_of, orig_dirs_tag_of, orig_dirs_full_index_file);
  read_index_file(mod_files_loc_of, mod_files_tag_of, mod_files_full_index_file);
  read_index_file(mod_dirs_loc_of, mod_dirs_tag_of, mod_dirs_full_index_file);

  read_list_file(changed_files, changed_files_file);
  read_list_file(changed_dirs, changed_dirs_file);

  record_basenames_and_container_tags(mod_file_container_tag_of_tag, mod_files_tag_of, mod_dirs_tag_of);
  record_basenames_and_container_tags(mod_dir_container_tag_of_tag, mod_dirs_tag_of, mod_dirs_tag_of);

  record_basenames_and_container_tags(orig_file_container_tag_of_tag, orig_files_tag_of, orig_dirs_tag_of);
  record_basenames_and_container_tags(orig_dir_container_tag_of_tag, orig_dirs_tag_of, orig_dirs_tag_of);

  orig_file_index_output = "sort -u -k 2 > " orig_file_index_output_file;
  orig_dir_index_output = "sort -u -k 2 > " orig_dir_index_output_file;
  mod_file_index_output = "sort -u -k 2 > " mod_file_index_output_file;
  mod_dir_index_output = "sort -u -k 2 > " mod_dir_index_output_file;

  # write index entries for modified 
  # files
  #
  for (mod_loc in changed_files)
    {
      tag = mod_files_tag_of[mod_loc];
      orig_loc = orig_files_loc_of[tag];

      printf "%s %s\n", mod_loc, tag | mod_file_index_output;
      printf "%s %s\n", orig_loc, tag | orig_file_index_output;

      orig_dir_tag = orig_file_container_tag_of_tag[tag];
      mod_dir_tag = mod_file_container_tag_of_tag[tag];

      enqueue_needed_dir_tag(orig_dir_tag);
      enqueue_needed_dir_tag(mod_dir_tag);
    }

  # look for new or renamed files
  # 
  for (tag in mod_files_loc_of)
    {

      mod_loc = mod_files_loc_of[tag];
      orig_loc = orig_files_loc_of[tag];

      if ("" == orig_loc)
        {
          # an added file

          printf "%s %s\n", mod_loc, tag | mod_file_index_output;

          container_tag = mod_file_container_tag_of_tag[tag];

          enqueue_needed_dir_tag(container_tag);
        }
      else
        {
          orig_tail = basename(orig_loc);
          mod_tail = basename(mod_loc);

          mod_container_tag = mod_file_container_tag_of_tag[tag];
          orig_container_tag = orig_file_container_tag_of_tag[tag];

          if ((orig_tail != mod_tail) || (mod_container_tag != orig_container_tag))
            {
              printf "%s %s\n", mod_loc, tag | mod_file_index_output;
              printf "%s %s\n", orig_loc, tag | orig_file_index_output;

              enqueue_needed_dir_tag(mod_container_tag);
              enqueue_needed_dir_tag(orig_container_tag);
            }
        }
    }


  # look for deleted files
  # 
  for (tag in orig_files_loc_of)
    {
      mod_loc = mod_files_loc_of[tag];
      orig_loc = orig_files_loc_of[tag];

      if ("" == mod_loc)
        {
          # a deleted file

          printf "%s %s\n", orig_loc, tag | orig_file_index_output;

          container_tag = orig_file_container_tag_of_tag[tag];

          enqueue_needed_dir_tag(container_tag);
        }
    }

  # write index entries for modified 
  # dirs
  #
  for (mod_loc in changed_dirs)
    {
      tag = mod_dirs_tag_of[mod_loc];
      orig_loc = orig_dirs_loc_of[tag];

      printf "%s %s\n", mod_loc, tag | mod_dir_index_output;
      printf "%s %s\n", orig_loc, tag | orig_dir_index_output;

      orig_dir_tag = orig_dir_container_tag_of_tag[tag];
      mod_dir_tag = mod_dir_container_tag_of_tag[tag];

      enqueue_needed_dir_tag(orig_dir_tag);
      enqueue_needed_dir_tag(mod_dir_tag);
    }

  # look for new or renamed dirs
  # 
  for (tag in mod_dirs_loc_of)
    {
      mod_loc = mod_dirs_loc_of[tag];
      orig_loc = orig_dirs_loc_of[tag];

      if ("" == orig_loc)
        {
          # an added dir

          printf "%s %s\n", mod_loc, tag | mod_dir_index_output;

          container_tag = mod_dir_container_tag_of_tag[tag];

          enqueue_needed_dir_tag(container_tag);
        }
      else
        {
          orig_tail = basename(orig_loc);
          mod_tail = basename(mod_loc);

          mod_container_tag = mod_dir_container_tag_of_tag[tag];
          orig_container_tag = orig_dir_container_tag_of_tag[orig];

          if ((orig_tail != mod_tail) || (mod_container_tag != orig_container_tag))
            {
              printf "%s %s\n", mod_loc, tag | mod_dir_index_output;
              printf "%s %s\n", orig_loc, tag | orig_dir_index_output;

              enqueue_needed_dir_tag(mod_container_tag);
              enqueue_needed_dir_tag(orig_container_tag);
            }
        }
    }

  # look for deleted dirs
  # 
  for (tag in orig_dirs_loc_of)
    {
      mod_loc = mod_dirs_loc_of[tag];
      orig_loc = orig_dirs_loc_of[tag];

      if ("" == mod_loc)
        {
          # a deleted dir

          printf "%s %s\n", orig_loc, tag | orig_dir_index_output;

          container_tag = orig_dir_container_tag_of_tag[tag];

          enqueue_needed_dir_tag(container_tag);
        }
    }


  # do the mest up mutual transitive closure of .. via tags of 
  # directories that earlier versions of mkpatch.sh get so consistently wrong
  # 
  while ("" != (tag = dequeue_needed_dir_tag()))
    {
      orig_loc = orig_dirs_loc_of[tag];
      mod_loc = mod_dirs_loc_of[tag];

      orig_container_tag = orig_dir_container_tag_of_tag[tag];
      mod_container_tag = mod_dir_container_tag_of_tag[tag];

      if (mod_loc != "")
        {
          printf "%s %s\n", mod_loc, tag | mod_dir_index_output;
        }

      if (orig_loc != "")
        {
          printf "%s %s\n", orig_loc, tag | orig_dir_index_output;
        }

      enqueue_needed_dir_tag(orig_container_tag);
      enqueue_needed_dir_tag(mod_container_tag);
    }

  close(mod_file_index_output);
  close(mod_dir_index_output);
  close(orig_file_index_output);
  close(orig_dir_index_output);

  exit 0;
}


function read_index_file(loc_of, tag_of, file)
{
  while (getline < file)
    {
      loc_of[$2] = $1;
      tag_of[$1] = $2;
    }
}

function read_list_file(out, file)
{
  while (getline < file)
    {
      out[$1] = 1;
    }
}

function record_basenames_and_container_tags(container_tag_of_tag, full_index, dirs_tag_of)
{
  for (loc in full_index)
    {
      tag = full_index[loc];
      dir = dirname(loc);
      dir_tag = dirs_tag_of[dir];

      if (dir != ".")
        {
          container_tag_of_tag[tag] = dir_tag;
        }
    }
}

function dirname(x)
{
  sub("/[^/]*$", "", x);
  return x;
}


function basename(x)
{
  sub("^.*/", "", x);
  return x;
}

function enqueue_needed_dir_tag(tag)
{
  if ((tag != "") && (!already_enqueued[tag]))
    {
      already_enqueued[tag] = 1;
      dir_tag_queue[dir_tag_queue_write_pos] = tag;
      ++dir_tag_queue_write_pos;
    }
}


function dequeue_needed_dir_tag()
{
  if (dir_tag_queue_read_pos >= dir_tag_queue_write_pos)
    {
      return "";
    }
  else
    {
      answer = dir_tag_queue[dir_tag_queue_read_pos];
      ++dir_tag_queue_read_pos;
      return answer;
    }
}

# tag: Tom Lord Sat May 31 14:28:30 2003 (patch-sets/mkpatch-indexes.awk)
#
