/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Kernel: cexp.c
*
* %Identification
* Written by: K.N.
* Date: Aug  7, 1997
* Origin: Risoe
* Release: McStas 1.6
* Version: 1.6
*
* Handle expressions used as arguments to components etc.	
*
*	$Id: cexp.c,v 1.18 2003/02/11 12:28:45 farhi Exp $
*
*	$Log: cexp.c,v $
*	Revision 1.18  2003/02/11 12:28:45  farhi
*	Variouxs bug fixes after tests in the lib directory
*	mcstas_r  : disable output with --no-out.. flag. Fix 1D McStas output
*	read_table:corrected MC_SYS_DIR -> MCSTAS define
*	monitor_nd-lib: fix Log(signal) log(coord)
*	HOPG.trm: reduce 4000 points -> 400 which is enough and faster to resample
*	Progress_bar: precent -> percent parameter
*	CS: ----------------------------------------------------------------------
*	
*	Revision 1.6  2000/07/27 09:04:59  kn
*	Support full C expressions. Now stores source line numbers within
*	expression representation, and distinguishes between values and compound
*	expressions.
*
*	Revision 1.5  2000/07/05 13:32:10  kn
*	Properly quote constant string expressions.
*
*	Revision 1.4  1998/10/02 08:35:04  kn
*	Fixed header comment.
*
*	Revision 1.3  1998/10/01 11:44:07  kn
*	Added support for string expressions.
*
*	Revision 1.2  1997/09/07 17:54:28  kn
*	Snapshot with (untested) code generation complete.
*
*	Revision 1.1  1997/08/13 09:11:24  kn
*	Initial revision
*
*******************************************************************************/
#include <stdarg.h>
#include <stdio.h>

#include "mcstas.h"

/* The internal structure implementing a C expression. */
struct cexp
  {
    char *s;		    /* String representation */
    int isvalue;	    /* True if identifier or string/number constant */
    int lineno;		    /* Starting line number, or zero */
  };

/* Create an expression from a string representing a value (either identifier,
   constant number, or constant string). */
static CExp
mkvalueexp(char *s)
{
  CExp e;
  palloc(e);
  e->s = s;
  e->isvalue = 1;
  e->lineno = 0;		/* Initially no line number set */
  return e;
}

/* Create an expression from a string not representing a value. */
static CExp
mknonvalueexp(char *s)
{
  CExp e;
  palloc(e);
  e->s = s;
  e->isvalue = 0;
  e->lineno = 0;		/* Initially no line number set */
  return e;
}

/*******************************************************************************
* Handle identifiers used as arguments to components.
* There are two types of identifiers: normal and extern. Normal identifiers
* refer to formal arguments of the instrument, and are always of type
* double. These can be varied eg. to perform a scan. Extern identifiers refer
* to user-supplied C identifiers that is typically put in the declaration and
* initialization sections of the instrument definition.
*
* The final version will distinguish (using a union) between these two types,
* and will maintain a mapping from formal parameters of the instrument to
* generated names in the generated simulation (the extern names must be
* copied unchanged). But in this first version a simpler scheme is used: all
* identifier expressions are simply strings, and all normal identifiers refer
* to instrument parameters (which have ID_PRE and "ip" prepended).
*******************************************************************************/

CExp
exp_id(char *id)
{
  return mkvalueexp(str_cat(ID_PRE, "ip", id, NULL));
}

CExp
exp_extern_id(char *id)
{
  return mkvalueexp(str_dup(id));
}

CExp
exp_number(char *n)
{
  return mkvalueexp(str_dup(n));
}

CExp
exp_string(char *s)
{
  char *quoted, *result;
  quoted = str_quote(s);
  result =  str_cat("\"", s, "\"", NULL);
  str_free(quoted);
  return mkvalueexp(result);
}

CExp
exp_ctoken(char *s)
{
  return mknonvalueexp(str_dup(s));
}

CExp
exp_compound(int n, ...)
{
  char *result, *new;
  CExp e;
  va_list ap;
  char *separator = "";		/* Token separator, initially empty */

  va_start(ap, n);
  result = str_dup("");
  while(n-- > 0)
  {
    e = va_arg(ap, CExp);
    new = str_cat(result, separator, e->s, NULL);
    str_free(result);
    result = new;
    separator = " ";		/* Now use space separator for rest. */
  }
  return mknonvalueexp(result);
}

void
exp_free(CExp e)
{
  str_free(e->s);
  memfree(e);
}

char *
exp_tostring(CExp e)
{
  char *s = e->s;
  if(s == NULL)
  {
    s = "";
    debugn((DEBUG_HIGH, "exp_tostring(): NULL cexp received.\n"));
  }
  return str_dup(s);
}

void
exp_fprint(FILE *f, CExp e)
{
  fputs(e->s, f);
}

int
exp_isvalue(CExp e)
{
  return e->isvalue;
}

void
exp_setlineno(CExp e, int n)
{
  e->lineno = n;
}

int
exp_getlineno(CExp e)
{
  return e->lineno;
}


syntax highlighted by Code2HTML, v. 0.9.1