/*
   File: util.c
   Defines utility functions for agflcoder
 
   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 Library 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: util.c,v 1.22 2005/09/06 10:03:16 marcs Exp $"
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#ifndef WIN32
#include <sys/times.h>
#endif

/* Libabase includes */
#include <abase_error.h>

/* Include CDL3 types */
#include <cdl3rts.h>

#include "util.h"

#ifdef DEBUG_GEN
#define DB(x) x
#else
#define DB(x)
#endif

/* 
** Word form definitions
** See also: merge, lexicon, and rts
*/

#define MAX_WF  1000

#define PREFIX_MARK		'\1'
#define SUFFIX_MARK		'\2'
#define INFIX_MARK		'\3'
#define MULTI_TOKEN_MARK	'\4'


/*
* make copy of s, return copy
* - reduce multiple spaces or tabs to one space
* - strip hyphens from prefixes, suffixes and infixes,
* - replace \- with -
* - optionally insert code indicating word form type
* 
* NOTE: qoutes and backslash conventions are dealt with in cdl3 code
*
* WARNING: adaptions to wordform_cpy() should also be applied to
*          merge, lexicon, and rts.
*/
char* wordform_cpy(char *wf, int line_nr)
{
  int c;
  char *p;
  char *q;
  char *s;
  int layout = 1;
  int prefix = 0;
  int suffix = 0;
  int multi_token = 0;
  int len;
  char tmp[MAX_WF];
  static char buf[MAX_WF];

  /* copy word form; flex pukes when yytext is altered */
  strncpy(tmp, wf, MAX_WF);
  len = strlen(wf);
  if (len > MAX_WF - 2)
    abs_fatal ("(line %d): word form %s is too long\n", line_nr, wf);

  /* strip quotes */
  s = tmp + 1, len--;
  s[--len] = '\0';

  /* strip trailing and leading layout */
  while ((c = *s), (c == ' ') || (c == '\t')) {
    s++, len--;
  }

  while ((c = s[len - 1]), (c == ' ') || (c == '\t')) {
    s[--len] = '\0';
  }

  /* check for prefixes and suffixes */
  if (*s == '-') {
    suffix = 1;
    s++, len--;
  };

  if ((s[len - 1] == '-') && (s[len - 2] != '\\')) {
    prefix = 1;
    s[--len] = '\0';
  };

  /* strip trailing and leading layout */
  while ((c = *s), (c == ' ') || (c == '\t'))
    s++, len--;
  while ((c = s[len - 1]), (c == ' ') || (c == '\t'))
    s[--len] = '\0';

  /* maybe there were only hyphens in wordform */
  if (!*s)
  {
    if (prefix && suffix)
      strcpy(buf, "\"--\"");
    else if (prefix || suffix)
      strcpy(buf, "\"-\"");
    else
      strcpy(buf, "\"\"");
    return buf;
  };

  /* check for multi token */
  q = s;
  while ((c = *q++))
  {
    if ((c == ' ') || (c == '\t'))
    {
      multi_token = 1;
      break;
    };
  };

  /*  insert leading quote */
  p = buf;
  *p++ = '\"';

  /* mark word form with type */
  if (multi_token)
  {
    *p++ = MULTI_TOKEN_MARK;
    if (prefix || suffix)
      fprintf(stderr, "Warning (line %d): stripped hyphens from multi-token"
                      " word form %s\n", line_nr, wf);
  }
  else if (prefix && suffix)
    *p++ = INFIX_MARK;
  else if (prefix)
    *p++ = PREFIX_MARK;
  else if (suffix)
    *p++ = SUFFIX_MARK;

  /* copy word form */
  q = s;
  while ((c = *q++))
  {
    switch(c)
    {
      case ' ':
      case '\t':
        if (!layout)
        {
          *p++ = ' ';
          layout = 1;
        };
        break;
      case '\\':
        c = *q++;
        switch (c)
        {
          case '-':
            break;
          default:
            *p++ = '\\';
        };
        *p++ = c;
        layout = 0;
        break;
      default:
        *p++ = c;
        layout = 0;
    };
  };

  /* insert trailing quote */
  *p++ = '\"';
  *p = '\0';

  return buf;
}

/*
** Cdl3 support
*/

/*
** FUNCTION copy word form (>TEXT1, >INT, TEXT2>)
*/
void E218_copy_word_form_TEXT_INT_TEXT(value v_TEXT1, value v_INT, value* v_TEXT2)
{
    char* wf = Text(v_TEXT1);
    int line_nr = Int(v_INT);
    char* result;
    
    DB(fprintf(stderr, "E218_copy_word_form from: \"%s\"\n", wf));

    result = wordform_cpy(wf, line_nr);         /* C_TEXT makes copy */

    DB(fprintf(stderr, "E218_copy_word_form to: \"%s\"\n", result));

    *v_TEXT2 = C_TEXT(result);
}


/*------------------------------------------------------------------------------
// FUNCTION watch(INT>)
//
// Description:
//	Return time elapsed since previous call of watch();
//	INT:	elapsed time in deci-seconds.
//
// Side effects:
//	Watch stores the current time as local state.
//
// TODO: Timer for WIN32 always returns 0.
//----------------------------------------------------------------------------*/
void E216_watch_INT(value *v_INT)
{
#ifdef WIN32
  *v_INT=C_INT(0);
#else
  static struct timeval old;
  struct timeval new;
  gettimeofday(&new,NULL);
  *v_INT=C_INT((new.tv_sec-old.tv_sec)*10+(new.tv_usec-old.tv_usec)/100000);
  old.tv_sec=new.tv_sec;
  old.tv_usec=new.tv_usec;
#endif
}

/* FUNCTION get config version (TEXT>): 300 */
void E300_get_config_version_TEXT(value* cdl_txt)
{
    *cdl_txt = C_TEXT(VERSION);
}

/* ACTION show memory usage: 301 */
void E301_show_memory_usage()
{
    abs_report_meminfo ();
}
