Exemplo n.º 1
0
Arquivo: document.c Projeto: abw/hemp
HempBool
hemp_document_scan(
    HempDocument document
) {
    hemp_debug_call("hemp_document_scan(%p)\n", document);

    if (! document->dialect->scanner)
        hemp_fatal("No scanner defined for %s document\n", document->dialect->name);

    if (! document->source->text)
        hemp_source_read(document->source);

    document->scanptr = 
    document->scantok = document->source->text;
    document->scanpos = 0;

    if (! document->scantags)
        document->scantags = hemp_stack_new(HEMP_SCANTAGS_SIZE);

    return document->dialect->scanner(document)
        ? HEMP_TRUE
        : HEMP_FALSE;

//    return hemp_action_run(document->scanner, document)
//        ? HEMP_TRUE
//        : HEMP_FALSE;
}
Exemplo n.º 2
0
Arquivo: document.c Projeto: abw/hemp
HempValue
hemp_document_data(
    HempDocument document,
    HempContext  context
) {
    hemp_debug_call("hemp_document_data(%p)\n", document);
    HempBool       my_context  = HEMP_FALSE;
    HempFragment   root        = hemp_document_tree(document);
    HempValue      values;
    HempList       results;

    if (! root)
        hemp_fatal("document does not have a root element");
    
    if (! context) {
        my_context  = HEMP_TRUE;
        context     = hemp_context_new(document->hemp);
    }

    values  = root->type->values(hemp_frag_val(root), context, HempNothing);
    results = hemp_val_list(values);
    
    if (my_context)
        hemp_context_free(context);

    if (results->length > 1) {
        return values;
    }
    else if (results->length == 1) {
        return hemp_list_item(results, 0);
    }
    else {
        return HempEmpty;
    }
}
Exemplo n.º 3
0
Arquivo: document.c Projeto: abw/hemp
HempText
hemp_document_process(
    HempDocument document,
    HempContext  context,
    HempText     output
) {
    hemp_debug_call("hemp_document_process(%p)\n", document);
    HempBool       my_context  = HEMP_FALSE;
    HempFragment   root        = hemp_document_tree(document);

    if (! context) {
        my_context = HEMP_TRUE;
        context = hemp_context_new(document->hemp);
    }

    if (! root)
        hemp_fatal("document does not have a root element");

    if (! output)
        output = hemp_text_new();

    root->type->text(hemp_frag_val(root), context, hemp_text_val(output));

//    HEMP_CATCH_ALL;
//       hemp_fatal("Error processing document: %s", hemp->error->message);
//    HEMP_END;

    if (my_context)
        hemp_context_free(context);

    return output;
}
Exemplo n.º 4
0
HEMP_INLINE void
hemp_scan_number(
    HempDocument   document
) {
    HempString     src     = document->scanptr;
    HempNum        num_val = 0;
    HempInt        int_val = 0;
    HempBool       is_int  = HEMP_FALSE;
    HempFragment   fragment;

//  hemp_debug_scan("scanning number: %s\n", document->scanptr);

    /* number - try integer first */
    errno   = 0;
    int_val = strtol(document->scanptr, &src, 0);
    is_int  = HEMP_TRUE;

    /* If there's a decimal point and a digit following then it's a 
    ** floating point number.  We also look out for e/E which also
    ** indicate fp numbers in scientific notation, e.g. 1.23e6.
    ** Note that we don't accept the decimal point if the next 
    ** character is not a digit.  This is required to support methods
    ** called against numeric constants, e.g. 12345.hex 
    */
    if ( ( *src == '.' && isdigit(*(src + 1)) )
      || ( *src == 'e' || *src == 'E' )
    )  {
        is_int  = HEMP_FALSE;
        num_val = strtod(document->scanptr, &src);
    }

    if (errno == ERANGE) {
        /* TODO: trim next token out of text */
        hemp_throw(document->hemp, HEMP_ERROR_OVERFLOW, document->scanptr);
    }
    else if (errno) {
        /* should never happen (famous last words) as we pre-check 
        ** that there is at least one valid digit available to be 
        ** parsed, but we check anyway
        */
        hemp_fatal("Unknown number parsing error: %d", errno);
    }
    else if (is_int) {
        fragment = hemp_document_scanned_to(
            document, HempElementInteger, src
        );
        fragment->op.value = hemp_int_val(int_val);
    }
    else {
        fragment = hemp_document_scanned_to(
            document, HempElementNumber, src
        );
        fragment->op.value = hemp_num_val(num_val);
    }
}
Exemplo n.º 5
0
HEMP_INLINE HempFragments
hemp_fragment_fragments(
    HempFragment fragment
) {
    if (! fragment->fragments)
        hemp_fatal(
            "No fragments defined for %s fragment", 
            fragment->type->name
    );

    return fragment->fragments;
}
Exemplo n.º 6
0
HEMP_INLINE HempGrammar
hemp_fragment_grammar(
    HempFragment fragment
) {
    if (! fragment->type->grammar)
        hemp_fatal(
            "No grammar defined for %s fragment", 
            fragment->type->name
        );

    return fragment->type->grammar;
}
Exemplo n.º 7
0
Arquivo: file.c Projeto: abw/hemp
HempString
hemp_scheme_file_reader(
    HempSource source 
) {
    source->text = hemp_filesystem_read_file(source->name);

    if (! source->text) {
        hemp_fatal("failed to read file: %s\n", source->name);          // fixme
    }
    
    return source->text;
}
Exemplo n.º 8
0
Arquivo: test.c Projeto: abw/hemp
HempTestPlan 
hemp_test_global_plan(
    HempUint planned
) {
    HEMP_MUTEX_LOCK;

    if (hemp_global_test_plan)
        hemp_fatal("A global test plan is already defined");

    hemp_global_test_plan = hemp_test_plan_setup(planned);

    HEMP_MUTEX_UNLOCK;
    
    return hemp_global_test_plan;
}
Exemplo n.º 9
0
Arquivo: test.c Projeto: abw/hemp
int
hemp_test_done(
    HempTestPlan plan
) {
    if (! plan)
        plan = hemp_global_test_plan;

    if (! plan)
        hemp_fatal("No test plan defined");

    int r = hemp_test_plan_result(plan);
    hemp_test_plan_summary(plan);
    hemp_test_plan_cleanup(plan);

    return r;
}
Exemplo n.º 10
0
Arquivo: test.c Projeto: abw/hemp
void
hemp_mem_trace_ok(void)
{
    char *debug = getenv("HEMP_MEMORY_TRACE");
    HempSize size = hemp_mem_trace_report(
        debug && hemp_string_eq(debug, "1")
    );

    if (size == 0) {
        printf("%sall memory freed%s\n", HEMP_COL_PASS, HEMP_COL_TERM);
    }
    else if (size == -1) {
        printf("%smemory checks disabled%s\n", HEMP_COL_SKIP, HEMP_COL_TERM);
    }
    else {
        printf("%smemory unfreed: %lu bytes%s\n", HEMP_COL_FAIL, size, HEMP_COL_TERM);
        hemp_mem_trace_report(HEMP_TRUE);
        hemp_fatal("Fix the memory leaks!");
    }
}
Exemplo n.º 11
0
Arquivo: test.c Projeto: abw/hemp
HempUint
hemp_test_expect_text(
    HempString     language,
    HempString     dialect,
    HempString     text,
    HempString     alias,
    HempContext    context
) {
    Hemp       hemp = hemp_new();
    HempString     test, name, expect, error, end;
    HempList       list;
    HempDocument   document;
    HempText       output;
    HempSize       n;

    HEMP_TRY;
        hemp_language(hemp, language);
    HEMP_CATCH_ALL;
        hemp_fatal("Failed to load hemp language '%s': %s", language, hemp->error->message);
    HEMP_END;

    if ((test = strstr(text, HEMP_TEST_START))) {
        hemp_string_to_next_line(&test);
    }
    else {
        test = text;
    }
        
    if ((end = strstr(text, HEMP_TEST_STOP)))
        *end = HEMP_NUL;

    test = strstr(test, HEMP_TEST_MARKER);

    if (! test)
        hemp_fatal("no tests found in %s", alias);
    
    /* skip over first -- test */
    test += strlen(HEMP_TEST_MARKER);
    list = hemp_string_split(test, HEMP_TEST_MARKER);

    hemp_debug("found %d tests in %s\n", list->length, alias);

//    hemp_test_plan(list->length * 2);
    hemp_test_plan(list->length);

    for (n = 0; n < list->length; n++) {
        test = hemp_val_str( hemp_list_item(list, n) );
        
        /* skip over leading whitespace */
        while (isspace(*test)) {
            test++;
        }
        
        name = test;
        do      { test++; }
        while   (*test != HEMP_LF && *test != HEMP_CR);

        /* NUL terminate test name */
        *test = '\0';
        
        do      { test++; }
        while   (*test == HEMP_LF || *test == HEMP_CR);
        
        if ((expect = strstr(test, HEMP_EXPECT_MARKER))) {
            *expect = '\0';
            expect += strlen(HEMP_EXPECT_MARKER);
            hemp_string_to_next_line(&expect);
        }

        if ( (error = strstr(test, HEMP_ERROR_MARKER))
          || (expect && (error = strstr(expect, HEMP_ERROR_MARKER )))) {
            *error = '\0';
            error += strlen(HEMP_ERROR_MARKER);
            hemp_string_to_next_line(&error);
        }

        hemp_string_chomp(test);

//        printf(">> test %u: %s\n", n, name);
//        if (expect)
//            printf(">> expect [%s]\n", expect);
//        if (error)
//            printf(">> error [%s]\n", error);

        HEMP_TRY;

            document = hemp_document(
                hemp,
                HEMP_TT3,
                HEMP_TEXT, 
                test
            );
            output = hemp_document_render(document, context);
//          ok( output, "%s (rendered)", name);

            if (expect)
                hemp_test_output(name, output, expect);
            else if (error)
                fail("expected error but got output");

        HEMP_CATCH_ALL;
            output = hemp_error_text(hemp->error);

            if (error) {
//                pass("%s", name);
                hemp_test_error(name, output->string, error);
            }
            else {
                fail("%s (error: %s)", name, output->string);
//                fail("error: %s", output->string);
            }
        HEMP_END;

        hemp_text_free(output);
    }

    hemp_list_free(list);
    hemp_free(hemp);

    return hemp_test_done(NULL);
}
Exemplo n.º 12
0
Arquivo: test.c Projeto: abw/hemp
HempUint
hemp_test_result(
    HempTestPlan  plan,
    HempBool         ok,         /* true=pass false=fail */
    HempName         func,        
    HempName         file,       /* source file          */
    HempUint         line,       /* line number          */
    HempName         name,       /* test name            */
    ...
) {
    va_list ap;
    HempString  fullname = NULL;
    HempBool badname  = HEMP_TRUE;   /* assume the worst */
    char *c;

    HEMP_MUTEX_LOCK;
    
    if (! plan)
        plan = hemp_global_test_plan;

    if (! plan)
        hemp_fatal("No test plan");

    plan->tested++;

    /* Start by taking the test name and performing any printf()
       expansions on it */
    if (name) {
        va_start(ap, name);
        vasprintf(&fullname, name, ap);
        va_end(ap);

        /* Make sure the test name contains more than digits
           and spaces.  Emit an error message and exit if it
           does */
        if (! fullname)
            hemp_mem_fail("test name");
        
        for(c = fullname; *c != HEMP_NUL; c++) {
            if(!isdigit(*c) && !isspace(*c)) {
                badname = HEMP_FALSE;
                break;
            }
        }

        if (badname) {
            hemp_fatal(
                "    You named your test '%s'.  You shouldn't use numbers for test names.", 
                fullname
            );
        }
    }

    if (ok) {
        printf(
            "%sok %lu", 
            HEMP_COL_PASS, 
            plan->tested
        );
        plan->passed++;
    }
    else {
        printf(
            "%snot ok %lu",
            plan->todo ? HEMP_COL_SKIP : HEMP_COL_FAIL, 
            plan->tested
        );
        plan->failed++;
    }

    if (name) {
        /* Print the test name, escaping any '#' characters */
        printf(" - ");
        flockfile(stdout);
            
        for(c = fullname; *c != HEMP_NUL; c++) {
            if (*c == '#')
                fputc('\\', stdout);
            fputc((int) *c, stdout);
        }
        funlockfile(stdout);
    }

    if (plan->todo) {
        printf(" # TODO %s", plan->todo_msg);

        /* TODO items aren't considered failures, so decrement the counter */
        if (! ok)
            plan->failed--;
    }

    printf("%s\n", HEMP_COL_TERM);

    if (! ok && plan->verbose)
        hemp_debug_cyan(
            "    Failed %stest (%s:%s() at line %d)", 
            plan->todo ? "(TODO) " : "", file, func, line
        );

    if (fullname)
        free(fullname);

    if (plan->todo) {
        if (--plan->todo == 0)
            free(plan->todo_msg);
    }


    HEMP_MUTEX_UNLOCK;

    /* We only care (when testing) that ok is positive, but here we
       specifically only want to return 1 or 0 */
    return ok ? 1 : 0;
}
Exemplo n.º 13
0
HempModule
hemp_use_module(
    Hemp       hemp,
    HempString     type,
    HempString     name
) {
    hemp_debug_call("hemp_use_module(%s => %s)\n", type, name);

    HempValue  path = hemp_config_get(hemp, HEMP_CONFIG_MODPATH);
    HempString string;

    if (hemp_is_defined(path)) {
        string = hemp_to_string(path, hemp->context);
//      hemp_debug_msg("already got %s: %s\n", HEMP_CONFIG_MODPATH, string);
    }
    else {
        HempValue  dir  = hemp_config_get(hemp, HEMP_CONFIG_DIR);
        HempValue  mod  = hemp_config_get(hemp, HEMP_CONFIG_MODDIR);
        HempString dstr = hemp_to_string(dir, hemp->context);
        HempString mstr = hemp_to_string(mod, hemp->context);

        string = hemp_uri_path_join(dstr, mstr, 1);
//      hemp_debug_msg("constructed %s: %s\n", HEMP_CONFIG_MODPATH, string);

        /* ugly work-around so we can get the context to manage memory */
        HempText text = hemp_context_tmp_text_size(hemp->context, strlen(string) + 1);
        hemp_text_append_string(text, string);
        hemp_mem_free(string);
        string = text->string;
//        hemp_config_set(hemp, HEMP_CONFIG_MODPATH, hemp_text_val(text));
    }

    // TODO: need a way to save dotted path (hemp.module_path) back into config

    /* quick hack to get something working */
    HempString modpath = getenv("HEMP_MODULE_PATH");

    if (! modpath || ! *modpath) {
        modpath = string;
//        hemp_debug_msg("No HEMP_MODULE_PATH environment variable set\n");
//        return HEMP_FALSE;
    }

    /* TODO: sort this mess out */
    HempString tpath = hemp_uri_path_join(modpath, type, 1);
    HempString mpath = hemp_uri_path_join(tpath, name, 1);
    HempText   mtext = hemp_text_from_string(mpath);
    hemp_text_append_string(mtext, HEMP_MODULE_EXT);
    hemp_mem_free(mpath);
    hemp_mem_free(tpath);
//  hemp_debug_msg("constructed module path: %s\n", mtext->string);

    HempModule module = hemp_global_module(hemp->global, mtext->string);

    if (module->binder) {
        module->binder(module, hemp);
    }
    else if (module->error) {
        hemp_fatal(module->error);
    }
    else {
        /* should never happen - famous last word */
        hemp_fatal("No binder function for %s module", name);
    }

    hemp_text_free(mtext);
    return module;
}