/*
   File: rtscode.c
   Implements the interface between generator and runtime system

   Copyright 2005 Radboud University of Nijmegen
 
   This program 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 of the License, or
   (at your option) any later version.
 
   This program 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 Library General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

   CVS ID: "$Id: rtscode.c,v 1.24 2006/09/27 16:01:15 marcs Exp $"
*/

/* If we have a config.h, include it */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

/* standard includes */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

/* libabase includes */
#include <abase_error.h>
#include <abase_memalloc.h>

/* local includes */
#include "rtscode.h"
#include "rtsio.h"
#include "rtsesc.h"

/*---------------------------------------------------------------------------------
// Function:
//	void print_set_affix(unsigned long val, long domain)
//
// Description:
//	Print textual set representation of affix with value val and domain.
//      All of the following routines print on stderr or add to the transduction
//-------------------------------------------------------------------------------*/
void print_set_affix (unsigned long val, long domain, int in_transduction)
{
    long affix;
    long mask;
    long* weight;

    weight = affix_weights[domain];
    while (val != 0)
    {
        affix = *weight++;

        if (affix == -1) {
            abs_bug ("print_set_affix", "invalid affix weight");
        } else {
            mask = affix_domains[affix];

            if ((val & mask) == mask) {
		char *escd = dupstr_escaped(affix_names[affix]);

                val ^= mask;

                if (in_transduction) {
                    current_parse_add_string(affix_names[affix]);
                    if (val != 0) current_parse_add_char('|');
                } else {
                    abs_printf ("%s", escd);
                    if (val != 0) abs_printf ("|");
		}
		abs_free (escd, "print_set_affix");
            }
        }
    }
}

void print_text_affix (char* val, int in_transduction)
{ if (val == TOP_TEXT)
    { if (in_transduction) current_parse_add_string ("TEXT");
      else abs_printf ("TEXT");
    }
  else
    { char *escd = dupstr_escaped (val);
      if (in_transduction) current_parse_add_string (val);
      else abs_printf ("\"%s\"", escd);
      abs_free (escd, "print_text_affix");
    };
}

void print_integer_affix(int val, int in_transduction)
{ if (val == TOP_INT)
    { if (in_transduction) current_parse_add_string ("INT");
      else abs_printf("INT");
    }
  else
    { if (in_transduction) current_parse_add_int (val);
      else abs_printf("%d",val);
    };
}

void current_parse_add_terminal (long termnr)
{ char *escd = dupstr_escaped (term_names[termnr]);
  abs_printf ("%s", escd);
  abs_free (escd, "current_parse_add_terminal");
}

void current_parse_add_match_regexp(long termnr)
{
#if 0
    char *escd = dupstr_escaped(match_regexp_names[termnr]);
    abs_printf ("%s", escd);
    abs_free(escd, "current_parse_add_match_regexp");
#else
    /* generator now stores REs without removing backslashes (as it should) */
    abs_printf ("%s", match_regexp_names[termnr]);
#endif
}

void current_parse_add_skip_regexp(long termnr)
{
#if 0
    char *escd = dupstr_escaped(skip_regexp_names[termnr]);
    abs_printf ("%s", escd);
    abs_free(escd, "current_parse_add_skip_regexp");
#else
    /* generator now stores REs without removing backslashes (as it should) */
    abs_printf ("%s", skip_regexp_names[termnr]);
#endif
}

#if 0
/* We should have access to a list of (grammar & lexicon) nonterminal names.
// For now, rtslex gets the name from the lexicon through rtslint.
// This function intended for later use.
*/
void current_parse_add_nonterminal(long nontnr)
{ current_parse_add_string(nont_names[nontnr]);
}
#endif

long affix_get_top(unsigned nont_nr, unsigned affix_nr)
{ long* arg_array = nont_domains[nont_nr];
  long affix_type = arg_array[affix_nr];
  if(affix_type == INT_TYPE)
  {
    return (long) TOP_INT;
  }
  else if(affix_type == TEXT_TYPE)
  {
    return (long) TOP_TEXT;
  }
  else if(affix_type >= 0)
  {
    return affix_domains[affix_type];
  }
  else
  { assert((affix_type >=0)||(affix_type==TEXT_TYPE)||(affix_type==INT_TYPE));
    return 0; /* impossible to reach */
  }
}

extern long get_nr_choices()
{ return nr_choices;
}
