module.cpp
来自「Shorthand是一个强大的脚本语言」· C++ 代码 · 共 655 行 · 第 1/2 页
CPP
655 行
///////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/module.cpp 6 2/14/03 4:20a Arm $
//-----------------------------------------------------------------------------
// Project: ShortHand interpreter
// Author: Andrei Remenchuk <andrei@remenchuk.com>
//-----------------------------------------------------------------------------
// module.cpp: implementation of ShortHand Module - highest-level execution unit
///////////////////////////////////////////////////////////////////////////////
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
#include <direct.h>
#else
#include <unistd.h>
#include <ctype.h>
#endif
#include "module.h"
#include "yydef.h"
#include "parser.h"
#include "object.h"
#include "nodes.h"
#include "shsql.h"
#include "regexx.h"
#include "cookie.h"
#include "smtpo.h"
#include "fileo.h"
#include "builtins.h"
#include "sharray.h"
#include "hash.h"
#ifdef _DEBUG
#include <typeinfo>
#endif
#ifdef WIN32
#define SLASH "\\"
#else
#define SLASH "/"
#endif
ShhModule::ShhModule(const char* script_name, ShhModule* parent)
: m_script_name(script_name), m_parent(parent)
{
m_entry = NULL;
m_current_loop = NULL;
m_lexer = NULL;
m_return_value = NULL;
m_locals = NULL;
if (parent != NULL)
{
m_context = parent->m_context;
m_http_stream = parent->m_http_stream;
}
else
{
m_context = &m_own_context;
m_http_stream = &m_stdio_stream;
}
#ifdef WIN32
m_script_name.translate('/', '\\');
#endif
}
/**
* Module's yylex() function - translates to the call to yylex() on C++ lexer
* (m_lexer).
*/
int ShhModule::module_yylex(void* yylval, void* yylloc)
{
m_lexer->yylval = ( YYSTYPE* ) yylval;
int token = m_lexer->yylex();
memcpy(yylloc, &m_lexer->yylloc, sizeof(YYLTYPE));
return token;
}
int ShhModule::module_yyerror(char* s)
{
throw new ShhException(1091, "<BR><B>%s</B>(%d:%d): %s\n", getName(), m_lexer->yyline, m_lexer->yypos, s );
//printf("<BR><B>%s</B>(%d:%d): %s\n", getName(), m_lexer->yyline, m_lexer->yypos, s );
//return 0;
}
/**
* Prints text to the HTTP output stream.
*/
int ShhModule::vprintf(const char* format, va_list args)
{
string s; s.vprintf(format, args);
return puts(s);
}
/**
* Prints text to the HTTP output stream.
*/
int ShhModule::printf(const char* format, ...)
{
va_list args; va_start(args, format);
string s; s.vprintf(format, args);
return m_http_stream->http_write_chunk(s.cstr(), s.length());
}
/**
* Prints text to the HTTP output stream.
*/
int ShhModule::puts(const char* s)
{
return m_http_stream->http_write_chunk(s, strlen(s));
}
/**
* Parses script. The result of the parsing is internal Syntax Tree
* that represents syntax elements by instances of objects derived from
* ShhNode.
*/
int ShhModule::parse_script(const char* content)
{
//yy_buffer_state* yybuffer = yy_scan_string( content );
mstream input;
input.write(content, strlen(content));
input.rewind();
ShortHandLexer lexer(input);
//lexer.set_debug(10);
m_lexer = &lexer;
int status = yyparse(this);
m_lexer = NULL;
return status;
}
/**
* Higest level script execution.
*
*/
int ShhModule::execute_script(const char* content, HttpStream* http_stream)
{
m_http_stream = http_stream ? http_stream : &m_stdio_stream;
int rc = parse_script(content);
if (rc != 0) return rc;
try
{
execute_body();
}
catch(...)
{
throw;
}
return 0;
}
int ShhModule::execute_file(FILE* file)
{
string content;
char buf[2048]; int count;
while((count = fread(buf, 1, sizeof(buf), file)) > 0)
{
content.append(buf, count);
}
return execute_script(content);
}
ShhVariable* ShhModule::findVariable(const char* name)
{
ShhModule* top_module = (ShhModule*) top();
if (top_module->m_locals != NULL)
{
for(int i=0,n=top_module->m_locals->size(); i<n; i++)
{
ShhVariable* var = top_module->m_locals->get(i);
if (stricmp(var->getName(), name) == 0) return var;
}
}
for(int i=0,n=m_context->m_variables.size(); i<n; i++)
{
ShhVariable* var = m_context->m_variables.get(i);
if (stricmp(var->getName(), name) == 0) return var;
}
return NULL;
}
ShhNode* ShhModule::include(ShhNode* node)
{
node->m_module = this;
node->m_index = m_nodes.add(node);
node->m_location = m_lexer->yylloc;
TRACE((22, "ShhModule::include(%s::0x%08x,[%d])\n", typeid(*node).name(), node, node->m_index ));
return node;
}
void ShhModule::clear()
{
m_own_context.m_variables.clear();
m_nodes.clear();
}
// provides variable (finds existing or creates new one)
ShhVariable* ShhModule::var(const char* name)
{
ShhVariable* v = findVariable(name);
if (v == NULL)
{
v = new ShhVariable(name);
m_context->m_variables.add(v);
}
return v;
}
ShhModule::~ShhModule()
{
}
/**
* Creates new object (constructor is not called at this point).
* This method works as objects factory.
*/
ShhObject* ShhModule::createObject(const char* type, const YYLTYPE& ctor_location)
{
ShhObject* object;
if (stricmp(type, "CONNECTION") == 0)
{
object = new ShhConnection(*this, ctor_location);
}
else if (stricmp(type, "DDL") == 0)
{
object = new ShhDDL(*this, ctor_location);
}
else if (stricmp(type, "RECORDSET") == 0)
{
object = new ShhRecordSet(*this, ctor_location);
}
else if (stricmp(type, "COOKIE") == 0)
{
object = new ShhCookie(*this, ctor_location);
}
else if (stricmp(type, "SMTP") == 0)
{
object = new ShhSMTP(*this, ctor_location);
}
else if (stricmp(type, "FILE") == 0)
{
object = new ShhFile(*this, ctor_location);
}
else if (stricmp(type, "ARRAY") == 0)
{
object = new ShhArray(*this, ctor_location);
}
else if (stricmp(type, "HASH") == 0)
{
object = new ShhHash(*this, ctor_location);
}
else
{
throw new ShhObjectException(1060, "Unknown object type: %s", type);
}
m_context->m_objects.add(object);
return object;
}
/**
* Returns the value of GET CGI variable. NULL if variable is not defined.
*/
const char* ShhModule::GET(const char* name)
{
char** v = (char**) m_context->m_get_fields.get(name);
return v != NULL ? *v : NULL;
}
/**
* Returns the value of POST CGI variable. NULL if variable is not defined.
*/
const char* ShhModule::POST(const char* name)
{
char** v = (char**) m_context->m_put_fields.get(name);
return v != NULL ? *v : NULL;
}
const char* ShhModule::getField(const char* name)
{
char** v = (char**) m_context->m_get_fields.get(name);
if (v != NULL && *v != NULL && **v != '\0') return *v;
v = (char**) m_context->m_put_fields.get(name);
return v != NULL ? *v : NULL;
}
/**
* Parses QUERY_STRING CGI environment variable.
*/
void ShhModule::parse_query_string()
{
string origin;
const char* qs = safe_getenv("QUERY_STRING", origin);
char* source = (char*) origin.cstr();
TRACE((3, "QUERY_STRING=%s\n", source));
parse_vars_into_map(source, m_context->m_get_fields);
TRACE((3, "parsed QUERY_STRING\n"));
}
/**
* Reads and parses posted data (if any).
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?