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 + -
显示快捷键?