This repository has been archived on 2024-03-20. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
ContactBook/CExpr/Cexpr.cpp
2024-03-20 09:28:18 -05:00

1229 lines
26 KiB
C++

/*
* File: cexpr.cpp
* Purpose: Prolog-like file I/O
* Author: Julian Smart
* Created: 1993
* Updated:
* Copyright: (c) 1993
*/
static const char sccsid[] = "%W% %G%";
#include "stdafx.h"
#include <fstream.h>
#include <stdarg.h>
#include <ctype.h>
#include "expr.h"
#include "cexpr.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern "C" void add_expr(char *);
extern "C" void LexFromFile(FILE *fd);
extern "C" void LexFromString(char *buf);
CExprDatabase *theCExprDatabase = NULL;
CExprErrorHandler currentCExprErrorHandler;
IMPLEMENT_DYNAMIC(CExprDatabase, wxList)
CExpr::CExpr(const CString& functor)
{
type = CExprList;
next = NULL;
last = NULL;
value.first = NULL;
CExpr *pfunctor = new CExpr(CExprWord, functor);
Append(pfunctor);
client_data = NULL;
}
CExpr::CExpr(CExprType the_type, const CString& word_or_string)
{
type = the_type;
switch (the_type)
{
case CExprWord:
value.word = copystring((const char *)word_or_string);
break;
case CExprString:
value.string = copystring((const char *)word_or_string);
break;
case CExprList:
last = NULL;
value.first = NULL;
break;
case CExprReal:
case CExprInteger:
case CExprNull:
break;
}
client_data = NULL;
next = NULL;
}
CExpr::CExpr(CExprType the_type, char *word_or_string, BOOL allocate)
{
type = the_type;
switch (the_type)
{
case CExprWord:
value.word = allocate ? copystring(word_or_string) : word_or_string;
break;
case CExprString:
value.string = allocate ? copystring(word_or_string) : word_or_string;
break;
case CExprList:
last = NULL;
value.first = NULL;
break;
case CExprReal:
case CExprInteger:
case CExprNull:
break;
}
client_data = NULL;
next = NULL;
}
CExpr::CExpr(long the_integer)
{
type = CExprInteger;
value.integer = the_integer;
client_data = NULL;
next = NULL;
}
CExpr::CExpr(float the_real)
{
type = CExprReal;
value.real = the_real;
client_data = NULL;
next = NULL;
}
CExpr::CExpr(wxList *the_list)
{
type = CExprList;
client_data = NULL;
last = NULL;
value.first = NULL;
CExpr *listExpr = new CExpr(CExprList);
wxNode *node = the_list->First();
while (node)
{
CExpr *expr = (CExpr *)node->Data();
listExpr->Append(expr);
node = node->Next();
}
Append(listExpr);
delete the_list;
}
CExpr::~CExpr(void)
{
switch (type)
{
case CExprInteger:
case CExprReal:
{
break;
}
case CExprString:
{
delete[] value.string;
break;
}
case CExprWord:
{
delete[] value.word;
break;
}
case CExprList:
{
CExpr *expr = value.first;
while (expr)
{
CExpr *expr1 = expr->next;
delete expr;
expr = expr1;
}
break;
}
case CExprNull: break;
}
}
void CExpr::Append(CExpr *expr)
{
if (!value.first)
value.first = expr;
if (last)
last->next = expr;
last = expr;
}
void CExpr::Insert(CExpr *expr)
{
expr->next = value.first;
value.first = expr;
if (!last)
last = expr;
}
CExpr *CExpr::Copy(void)
{
// This seems to get round an optimizer bug when
// using Watcom C++ 10a in WIN32 compilation mode.
// If these lines not present, the type seems to be
// interpreted wrongly as an integer.
// I don't want to turn optimization off since it's needed
// for reading in files quickly.
#if defined(__WATCOMC__)
char buf[2];
sprintf(buf, "");
#endif
switch (type)
{
case CExprInteger:
return new CExpr(value.integer);
case CExprReal:
return new CExpr(value.real);
case CExprString:
return new CExpr(CExprString, CString(value.string));
case CExprWord:
return new CExpr(CExprWord, CString(value.word));
case CExprList:
{
CExpr *expr = value.first;
CExpr *new_list = new CExpr(CExprList);
while (expr)
{
CExpr *expr2 = expr->Copy();
new_list->Append(expr2);
expr = expr->next;
}
return new_list;
}
case CExprNull:
break;
}
return NULL;
}
// Get the CExpr (containing (= CExpr Value) form) for the given word
// or string, assuming that we have Attribute=Value, ...
CExpr *CExpr::GetAttributeValueNode(const CString& word) // Use only for a clause or list
{
if (type != CExprList)
return NULL;
CExpr *expr = value.first;
while (expr)
{
if (expr->type == CExprList)
{
CExpr *firstNode = expr->value.first;
if ((firstNode->type == CExprWord) && (firstNode->value.word[0] == '='))
{
CExpr *secondNode = firstNode->next;
if ((secondNode->type == CExprWord) &&
(strcmp((const char *)word, secondNode->value.word) == 0))
{
return expr;
}
}
}
expr = expr->next;
}
return NULL;
}
// Get the value (in CExpr form) for the given word or string, assuming
// that we have Attribute=Value, ...
CExpr *CExpr::AttributeValue(const CString& word) // Use only for a clause or list
{
if (type != CExprList)
return NULL;
CExpr *attExpr = GetAttributeValueNode(word);
if (attExpr && attExpr->value.first && attExpr->value.first->next)
return attExpr->value.first->next->next;
else return NULL;
}
CString CExpr::Functor(void) // Use only for a clause
{
if ((type != CExprList) || !value.first)
return CString("");
if (value.first->type == CExprWord)
return CString(value.first->value.word);
else
return CString("");
}
BOOL CExpr::IsFunctor(const CString& f) // Use only for a clause
{
if ((type != CExprList) || !value.first)
return FALSE;
return (value.first->type == CExprWord &&
(strcmp((const char *)f, value.first->value.word) == 0));
}
// Return nth argument of a clause (starting from 1)
CExpr *CExpr::Arg(CExprType theType, int arg)
{
CExpr *expr = value.first;
int i;
for (i = 1; i < arg; i++)
if (expr)
expr = expr->next;
if (expr && (expr->type == theType))
return expr;
else
return NULL;
}
// Return nth argument of a list expression (starting from zero)
CExpr *CExpr::Nth(int arg)
{
if (type != CExprList)
return NULL;
CExpr *expr = value.first;
int i;
for (i = 0; i < arg; i++)
if (expr)
expr = expr->next;
else return NULL;
if (expr)
return expr;
else
return NULL;
}
// Returns the number of elements in a list expression
int CExpr::Number(void)
{
if (type != CExprList)
return 0;
int i = 0;
CExpr *expr = value.first;
while (expr)
{
expr = expr->next;
i ++;
}
return i;
}
void CExpr::DeleteAttributeValue(const CString& attribute)
{
if (type != CExprList)
return;
CExpr *expr = value.first;
CExpr *lastExpr = this;
while (expr)
{
if (expr->type == CExprList)
{
CExpr *firstNode = expr->value.first;
if ((firstNode->type == CExprWord) && (firstNode->value.word[0] == '='))
{
CExpr *secondNode = firstNode->next;
if ((secondNode->type == CExprWord) &&
(strcmp((const char *)attribute, secondNode->value.word) == 0))
{
CExpr *nextExpr = expr->next;
delete expr;
lastExpr->next = nextExpr;
if (last == expr)
last = lastExpr;
return;
}
}
}
lastExpr = expr;
expr = expr->next;
}
return;
}
void CExpr::AddAttributeValue(const CString& attribute, CExpr *val)
{
if (type != CExprList)
{
// cout << "Error! tried to add an attribute-value pair to a nonlist CExpr expression\n";
return;
}
// Warning - existing code may assume that any existing value
// is deleted first. For efficiency, we leave this to the application.
// DeleteAttributeValue(attribute);
CExpr *patt = new CExpr(CExprWord, attribute);
CExpr *pequals = new CExpr(CExprWord, "=");
CExpr *listExpr = new CExpr(CExprList);
listExpr->Append(pequals);
listExpr->Append(patt);
listExpr->Append(val);
Append(listExpr);
}
void CExpr::AddAttributeValue(const CString& attribute, long val)
{
if (type != CExprList)
{
// cout << "Error! tried to add an attribute-value pair to a nonlist CExpr expression\n";
return;
}
// Warning - existing code may assume that any existing value
// is deleted first. For efficiency, we leave this to the application.
// DeleteAttributeValue(attribute);
CExpr *patt = new CExpr(CExprWord, attribute);
CExpr *pval = new CExpr(val);
CExpr *pequals = new CExpr(CExprWord, "=");
CExpr *listExpr = new CExpr(CExprList);
listExpr->Append(pequals);
listExpr->Append(patt);
listExpr->Append(pval);
Append(listExpr);
}
void CExpr::AddAttributeValue(const CString& attribute, float val)
{
if (type != CExprList)
{
// cout << "Error! tried to add an attribute-value pair to a nonlist CExpr expression\n";
return;
}
// DeleteAttributeValue(attribute);
CExpr *patt = new CExpr(CExprWord, attribute);
CExpr *pval = new CExpr(val);
CExpr *pequals = new CExpr(CExprWord, "=");
CExpr *listExpr = new CExpr(CExprList);
listExpr->Append(pequals);
listExpr->Append(patt);
listExpr->Append(pval);
Append(listExpr);
}
void CExpr::AddAttributeValueString(const CString& attribute, const CString& val)
{
if (type != CExprList)
{
// cout << "Error! tried to add an attribute-value pair to a nonlist CExpr expression\n";
return;
}
// DeleteAttributeValue(attribute);
CExpr *patt = new CExpr(CExprWord, attribute);
CExpr *pval = new CExpr(CExprString, val);
CExpr *pequals = new CExpr(CExprWord, "=");
CExpr *listExpr = new CExpr(CExprList);
listExpr->Append(pequals);
listExpr->Append(patt);
listExpr->Append(pval);
Append(listExpr);
}
void CExpr::AddAttributeValueWord(const CString& attribute, const CString& val)
{
if (type != CExprList)
{
// cout << "Error! tried to add an attribute-value pair to a nonlist CExpr expression\n";
return;
}
// DeleteAttributeValue(attribute);
CExpr *patt = new CExpr(CExprWord, attribute);
CExpr *pval = new CExpr(CExprWord, val);
CExpr *pequals = new CExpr(CExprWord, "=");
CExpr *listExpr = new CExpr(CExprList);
listExpr->Append(pequals);
listExpr->Append(patt);
listExpr->Append(pval);
Append(listExpr);
}
void CExpr::AddAttributeValue(const CString& attribute, wxList *val)
{
if (type != CExprList)
{
// cout << "Error! tried to add an attribute-value pair to a nonlist CExpr expression\n";
return;
}
if (!val)
return;
// DeleteAttributeValue(attribute);
CExpr *patt = new CExpr(CExprWord, attribute);
CExpr *pval = new CExpr(val);
CExpr *pequals = new CExpr(CExprWord, "=");
CExpr *listExpr = new CExpr(CExprList);
listExpr->Append(pequals);
listExpr->Append(patt);
listExpr->Append(pval);
Append(listExpr);
}
void CExpr::AddAttributeValueStringList(const CString& attribute, wxList *string_list)
{
if (type != CExprList)
{
// cout << "Error! tried to add an attribute-value pair to a nonlist CExpr expression\n";
return;
}
if (!string_list)
return;
// DeleteAttributeValue(attribute);
// First make a list of CExpr strings
CExpr *listExpr = new CExpr(CExprList);
wxNode *node = string_list->First();
while (node)
{
char *string = (char *)node->Data();
CExpr *expr = new CExpr(CExprString, CString(string));
listExpr->Append(expr);
node = node->Next();
}
// Now make an (=, Att, Value) triple
CExpr *patt = new CExpr(CExprWord, attribute);
CExpr *pequals = new CExpr(CExprWord, "=");
CExpr *listExpr2 = new CExpr(CExprList);
listExpr2->Append(pequals);
listExpr2->Append(patt);
listExpr2->Append(listExpr);
Append(listExpr2);
}
BOOL CExpr::GetAttributeValue(const CString& att, int& var)
{
CExpr *expr = AttributeValue(att);
if (expr && (expr->Type() == CExprInteger || expr->Type() == CExprReal))
{
var = (int)(expr->IntegerValue());
return TRUE;
}
else
return FALSE;
}
BOOL CExpr::GetAttributeValue(const CString& att, long& var)
{
CExpr *expr = AttributeValue(att);
if (expr && (expr->Type() == CExprInteger || expr->Type() == CExprReal))
{
var = expr->IntegerValue();
return TRUE;
}
else
return FALSE;
}
BOOL CExpr::GetAttributeValue(const CString& att, float& var)
{
CExpr *expr = AttributeValue(att);
if (expr && (expr->Type() == CExprInteger || expr->Type() == CExprReal))
{
var = expr->RealValue();
return TRUE;
}
else
return FALSE;
}
BOOL CExpr::GetAttributeValue(const CString& att, CString& var) // Word OR string -> string
{
CExpr *expr = AttributeValue(att);
if (expr && expr->Type() == CExprWord)
{
var = expr->WordValue();
return TRUE;
}
else if (expr && expr->Type() == CExprString)
{
var = expr->StringValue();
return TRUE;
}
else
return FALSE;
}
BOOL CExpr::GetAttributeValue(const CString& att, CExpr **var)
{
CExpr *expr = AttributeValue(att);
if (expr)
{
*var = expr;
return TRUE;
}
else
return FALSE;
}
BOOL CExpr::GetAttributeValueStringList(const CString& att, wxList *var)
{
CExpr *expr = AttributeValue(att);
if (expr && expr->Type() == CExprList)
{
CExpr *string_expr = expr->value.first;
while (string_expr)
{
if (string_expr->Type() == CExprString)
var->Append((CObject *)copystring(string_expr->StringValue()));
string_expr = string_expr->next;
}
return TRUE;
}
else
return FALSE;
}
void CExpr::WriteClause(ostream& stream) // Write this expression as a top-level clause
{
if (type != CExprList)
return;
CExpr *node = value.first;
if (node)
{
node->WriteExpr(stream);
stream << "(";
node = node->next;
BOOL first = TRUE;
while (node)
{
if (!first)
stream << " ";
node->WriteExpr(stream);
node = node->next;
if (node) stream << ",\n";
first = FALSE;
}
stream << ").\n\n";
}
}
void CExpr::WriteExpr(ostream& stream) // Write as any other subexpression
{
// This seems to get round an optimizer bug when
// using Watcom C++ 10a in WIN32 compilation mode.
// If these lines not present, the type seems to be
// interpreted wrongly as an integer.
// I don't want to turn optimization off since it's needed
// for reading in files quickly.
#if defined(__WATCOMC__)
char buf[2];
sprintf(buf, "");
#endif
switch (type)
{
case CExprInteger:
{
stream << value.integer;
break;
}
case CExprReal:
{
float f = value.real;
/* Now the parser can cope with this.
// Prevent printing in 'e' notation. Any better way?
if (fabs(f) < 0.00001)
f = 0.0;
*/
char buf[40];
sprintf(buf, "%.6g", f);
stream << buf;
break;
}
case CExprString:
{
stream << "\"";
int i;
int len = strlen(value.string);
for (i = 0; i < len; i++)
{
char ch = value.string[i];
if (ch == '"' || ch == '\\')
stream << "\\";
stream << ch;
}
stream << "\"";
break;
}
case CExprWord:
{
BOOL quote_it = FALSE;
int len = strlen(value.word);
if ((len == 0) || (len > 0 && (value.word[0] > 64 && value.word[0] < 91)))
quote_it = TRUE;
else
{
int i;
for (i = 0; i < len; i++)
if ((!isalpha(value.word[i])) && (!isdigit(value.word[i])) &&
(value.word[i] != '_'))
{ quote_it = TRUE; i = len; }
}
if (quote_it)
stream << "'";
stream << value.word;
if (quote_it)
stream << "'";
break;
}
case CExprList:
{
if (!value.first)
stream << "[]";
else
{
CExpr *expr = value.first;
if ((expr->Type() == CExprWord) && (strcmp(expr->WordValue(), "=") == 0))
{
CExpr *arg1 = expr->next;
CExpr *arg2 = arg1->next;
arg1->WriteExpr(stream);
stream << " = ";
arg2->WriteExpr(stream);
}
else
{
stream << "[";
while (expr)
{
expr->WriteExpr(stream);
expr = expr->next;
if (expr) stream << ", ";
}
stream << "]";
}
}
break;
}
case CExprNull: break;
}
}
void CExpr::WriteLispExpr(ostream& stream)
{
switch (type)
{
case CExprInteger:
{
stream << value.integer;
break;
}
case CExprReal:
{
stream << value.real;
break;
}
case CExprString:
{
stream << "\"" << value.string << "\"";
break;
}
case CExprWord:
{
stream << value.word;
break;
}
case CExprList:
{
CExpr *expr = value.first;
stream << "(";
while (expr)
{
expr->WriteLispExpr(stream);
expr = expr->next;
if (expr) stream << " ";
}
stream << ")";
break;
}
case CExprNull: break;
}
}
// CExpr 'database' (list of expressions)
CExprDatabase::CExprDatabase(CExprErrorHandler handler)
{
position = NULL;
hash_table = NULL;
currentCExprErrorHandler = handler;
noErrors = 0;
}
CExprDatabase::CExprDatabase(CExprType type, const CString& attribute, int size,
CExprErrorHandler handler)
{
position = NULL;
attribute_to_hash = attribute;
if (type == CExprString)
hash_table = new wxHashTable(wxKEY_STRING, size);
else if (type == CExprInteger)
hash_table = new wxHashTable(wxKEY_INTEGER, size);
else hash_table = NULL;
currentCExprErrorHandler = handler;
noErrors = 0;
}
CExprDatabase::~CExprDatabase(void)
{
ClearDatabase();
if (hash_table)
delete hash_table;
}
int CExprDatabase::GetItemCount(void) // get count of possible items
{
int z = 0;
wxNode *node = First();
while (node)
{
z++;
node = node->Next();
}
return z;
}
void CExprDatabase::BeginFind(void) // Initialise a search
{
position = First();
}
CExpr *CExprDatabase::FindClause(long id) // Find a term based on an integer id attribute
// e.g. node(id=23, type=rectangle, ....).
{
CExpr *found = NULL;
while (position && !found)
{
CExpr *term = (CExpr *)position->Data();
if (term->Type() == CExprList)
{
CExpr *value = term->AttributeValue("id");
if (value->Type() == CExprInteger && value->IntegerValue() == id)
found = term;
}
position = position->Next();
}
return found;
}
// Find on basis of attribute/value pairs, e.g. type=rectangle
CExpr *CExprDatabase::FindClause(const CString& word, const CString& val)
{
CExpr *found = NULL;
while (position && !found)
{
CExpr *term = (CExpr *)position->Data();
if (term->Type() == CExprList)
{
CExpr *value = term->AttributeValue(word);
if ((value->Type() == CExprWord && value->WordValue() == val) ||
(value->Type() == CExprString && value->StringValue() == val))
found = term;
}
position = position->Next();
}
return found;
}
CExpr *CExprDatabase::FindClause(const CString& word, long val)
{
CExpr *found = NULL;
while (position && !found)
{
CExpr *term = (CExpr *)position->Data();
if (term->Type() == CExprList)
{
CExpr *value = term->AttributeValue(word);
if ((value->Type() == CExprInteger) && (value->IntegerValue() == val))
found = term;
}
position = position->Next();
}
return found;
}
CExpr *CExprDatabase::FindClause(const CString& word, float val)
{
CExpr *found = NULL;
while (position && !found)
{
CExpr *term = (CExpr *)position->Data();
if (term->Type() == CExprList)
{
CExpr *value = term->AttributeValue(word);
if ((value->Type() == CExprReal) && (value->RealValue() == val))
found = term;
}
position = position->Next();
}
return found;
}
CExpr *CExprDatabase::FindClauseByFunctor(const CString& functor)
{
CExpr *found = NULL;
while (position && !found)
{
CExpr *term = (CExpr *)position->Data();
if (term->Type() == CExprList)
{
if (term->Functor() == functor)
found = term;
}
position = position->Next();
}
return found;
}
// If hashing is on, must store in hash table too
void CExprDatabase::Append(CExpr *clause)
{
wxList::Append((CObject *)clause);
if (hash_table)
{
CString functor(clause->Functor());
CExpr *expr = clause->AttributeValue(attribute_to_hash);
if (expr)
{
long functor_key = hash_table->MakeKey((char *)(const char *)functor);
long value_key = 0;
if (expr && expr->Type() == CExprString)
{
value_key = hash_table->MakeKey((char *)(const char *)expr->StringValue());
hash_table->Put(functor_key + value_key, (char *)(const char *)expr->StringValue(), (CObject *)clause);
}
else if (expr && expr->Type() == CExprInteger)
{
value_key = expr->IntegerValue();
hash_table->Put(functor_key + value_key, expr->IntegerValue(), (CObject *)clause);
}
}
}
}
CExpr *CExprDatabase::HashFind(const CString& functor, long value)
{
long key = hash_table->MakeKey((char *)(const char *)functor) + value;
// The key alone isn't guaranteed to be unique:
// must supply value too. Let's assume the value of the
// id is going to be reasonably unique.
return (CExpr *)hash_table->Get(key, value);
}
CExpr *CExprDatabase::HashFind(const CString& functor, const CString& value)
{
long key = hash_table->MakeKey((char *)(const char *)functor) + hash_table->MakeKey((char *)(const char *)value);
return (CExpr *)hash_table->Get(key, (char *)(const char *)value);
}
void CExprDatabase::ClearDatabase(void)
{
noErrors = 0;
wxNode *node = First();
while (node)
{
CExpr *expr = (CExpr *)node->Data();
delete expr;
delete node;
node = First();
}
if (hash_table)
hash_table->Clear();
}
BOOL CExprDatabase::Read(const CString& filename)
{
noErrors = 0;
FILE *f = fopen((const char *)filename, "r");
if (f)
{
theCExprDatabase = this;
LexFromFile(f);
yyparse();
fclose(f);
CExprCleanUp();
return (noErrors == 0);
}
else
{
return FALSE;
}
}
BOOL CExprDatabase::ReadFromString(const CString& buffer)
{
noErrors = 0;
theCExprDatabase = this;
LexFromString((char *)(const char *)buffer);
yyparse();
CExprCleanUp();
return (noErrors == 0);
}
BOOL CExprDatabase::Write(const CString& fileName)
{
ofstream str((char *)(const char *)fileName);
if (str.bad())
return FALSE;
return Write(str);
}
BOOL CExprDatabase::Write(ostream& stream)
{
noErrors = 0;
wxNode *node = First();
while (node)
{
CExpr *expr = (CExpr *)node->Data();
expr->WriteClause(stream);
node = node->Next();
}
return (noErrors == 0);
}
void CExprDatabase::WriteLisp(ostream& stream)
{
noErrors = 0;
wxNode *node = First();
while (node)
{
CExpr *expr = (CExpr *)node->Data();
expr->WriteLispExpr(stream);
stream << "\n\n";
node = node->Next();
}
}
void add_expr(CExpr * expr)
{
theCExprDatabase->Append(expr);
}
// Checks functor
BOOL CExprIsFunctor(CExpr *expr, const CString& functor)
{
if (expr && (expr->Type() == CExprList))
{
CExpr *first_expr = expr->value.first;
if (first_expr && (first_expr->Type() == CExprWord) &&
(first_expr->WordValue() == functor))
return TRUE;
else
return FALSE;
}
else
return FALSE;
}
/*
* Called from parser
*
*/
char *make_integer(char *str)
{
CExpr *x = new CExpr(atol(str));
return (char *)x;
}
char *make_real(char *str1, char *str2)
{
char buf[50];
sprintf(buf, "%s.%s", str1, str2);
float f = (float)atof(buf);
CExpr *x = new CExpr(f);
return (char *)x;
}
// extern "C" double exp10(double);
char *make_exp(char *str1, char *str2)
{
double mantissa = (double)atoi(str1);
double exponent = (double)atoi(str2);
double d = mantissa * pow(10.0, exponent);
CExpr *x = new CExpr((float)d);
return (char *)x;
}
char *make_exp2(char *str1, char *str2, char *str3)
{
char buf[50];
sprintf(buf, "%s.%s", str1, str2);
double mantissa = (double)atof(buf);
double exponent = (double)atoi(str3);
double d = mantissa * pow(10.0, exponent);
CExpr *x = new CExpr((float)d);
return (char *)x;
}
char *make_word(char *str)
{
CExpr *x = new CExpr(CExprWord, str);
return (char *)x;
}
char *make_string(char *str)
{
char *s, *t;
int len, i;
str++; /* skip leading quote */
len = strlen(str) - 1; /* ignore trailing quote */
s = new char[len + 1];
t = s;
for(i=0; i<len; i++)
{
if (str[i] == '\\' && str[i+1] == '"')
{
*t++ = '"';
i ++;
}
else if (str[i] == '\\' && str[i+1] == '\\')
{
*t++ = '\\';
i ++;
}
else
*t++ = str[i];
}
*t = '\0';
CExpr *x = new CExpr(CExprString, s, FALSE);
return (char *)x;
}
char *cexpr_cons(char * ccar, char * ccdr)
{
CExpr *car = (CExpr *)ccar;
CExpr *cdr = (CExpr *)ccdr;
if (cdr == NULL)
{
cdr = new CExpr(CExprList);
}
if (car)
cdr->Insert(car);
return (char *)cdr;
}
void process_command(char * cexpr)
{
CExpr *expr = (CExpr *)cexpr;
add_expr(expr);
}
void syntax_error(char *s)
{
if (currentCExprErrorHandler)
(void)(*(currentCExprErrorHandler))(CEXPR_ERROR_SYNTAX, "syntax error");
if (theCExprDatabase) theCExprDatabase->noErrors += 1;
}
#ifdef _WINDLL
char *__cdecl strdup(const char *s)
{
int len = strlen(s);
char *new_s = (char *)malloc(sizeof(char)*(len+1));
strcpy(new_s, s);
return new_s;
}
#endif