/* $Id: escstr.c,v 1.2 2009/01/04 15:42:14 kiesling Exp $ -*-c-*-*/

/*
  This file is part of Ctalk.
  Copyright © 2005-2009  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  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 General Public License
  along with this program; if not, write to the Free Software Foundation, 
  Inc., 51 Franklin St., Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "object.h"
#include "message.h"
#include "ctalk.h"

#ifndef MAXMSG
#define MAXMSG 8192
#endif

/* From ctalk.h */
#define TRIM_LITERAL(s) (substrcpy (s, s, 1, strlen (s) - 2))
void _warning (char *, ...);
char *substrcpy (char *, char *, int, int);

/*
 *  Escape the opening and closing quotes of a string.
 *  The easiest way to do this is to chop the quotes
 *  and re-format with escaped quotes.
 */

char *escape_str (char *s) {
  static char buf[MAXMSG+1];
  char s_copy[MAXMSG+1];
  int len;
  strcpy (s_copy, s);
  len = strlen (s_copy);
  if (s_copy[0] != '"' || s_copy[len-1] != '"') {
    _warning ("Bad string in escape_str ().\n");
    return NULL;
  }
  TRIM_LITERAL (s_copy);
  sprintf (buf, "\\\"%s\\\"", s_copy);
  return buf;
}

char *escape_str_quotes (char *s) {

  int i, j;
  static char buf[MAXMSG+1];

  memset ((void *)buf, 0, MAXMSG);

  for (i = 0, j = 0; s[i]; i++, j++) {
    switch (s[i]) 
      {
      case '\\':
	if (!ESC_SEQUENCE_CHAR(s[i+1]))
	  buf[j++] = '\\';
	buf[j] = s[i];
	break;
      case '\"':
        buf[j++] = '\\';
	buf[j] = s[i];
	break;
      default:
	buf[j] = s[i];
      }
  }

  return buf;
}

char *unescape_str_quotes (char *s) {

  int i, 
    j,
    esc_chr;
  static char buf[MAXMSG+1];

  memset ((void *)buf, 0, MAXMSG);

  for (i = 0, j = 0, esc_chr = -3; s[i]; i++) {
    switch (s[i])
      {
      case '\\':
	if (esc_chr == (i - 1)) {
	  buf[j++] = s[i];
	  esc_chr = -3;
	} else {
	  esc_chr = i;
	}
        break;
      case '\"':
	if (esc_chr == (i - 1))
	  buf[j++] = s[i];
	break;
      default:
        buf[j++] = s[i];
        break;
      }
  }

  return buf;
}

/*
 *  This function is only called by generate_store_arg_call ().
 *  As long as it is only called by output.c functions, it
 *  should be all right to use the e_messages stack.
 */

char *esc_expr_quotes (char *expr) {

  int stack_start,
    stack_end,
    i;
  MESSAGE_STACK messages;
  static char buf[MAXMSG];

  messages = _get_e_messages ();
  stack_start = _get_e_message_ptr ();
  stack_end = tokenize (e_message_push, expr);

  for (i = stack_start, *buf = 0; i >=stack_end; i--) {

    switch (messages[i] -> tokentype)
      {
      case LITERAL:
	strcat (buf, escape_str_quotes (M_NAME(messages[i])));
	break;
      default:
	strcat (buf, M_NAME(messages[i]));
	break;
      }
  }

  for (i = stack_end; i <= stack_start; i++) {
    MESSAGE *n;
    n = e_message_pop ();
    delete_message (n);
  }

  return buf;
}

void de_newline_buf (char *s) {
  char *p;

  while ((p = index (s, '\n')) != NULL)
    *p = ' ';
}

