root/native.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_argument_count
  2. print_value
  3. crb_nv_print_proc
  4. crb_nv_fopen_proc
  5. crb_nv_fclose_proc
  6. crb_nv_fgets_proc
  7. crb_nv_fputs_proc
  8. new_array_sub
  9. crb_nv_new_array_proc

#include <stdio.h>
#include <string.h>
#include "MEM.h"
#include "DBG.h"
#include "crowbar.h"

static void
check_argument_count(int arg_count, int true_count)
{
    if (arg_count < true_count) {
        crb_runtime_error(0, ARGUMENT_TOO_FEW_ERR,
                          MESSAGE_ARGUMENT_END);
    } else if (arg_count > true_count) {
        crb_runtime_error(0, ARGUMENT_TOO_MANY_ERR,
                          MESSAGE_ARGUMENT_END);
    }
}

static void
print_value(CRB_Value *value)
{
    int i;

    switch (value->type) {
    case CRB_BOOLEAN_VALUE:
        if (value->u.boolean_value) {
            printf("true");
        } else {
            printf("false");
        }
        break;
    case CRB_INT_VALUE:
        printf("%d", value->u.int_value);
        break;
    case CRB_DOUBLE_VALUE:
        printf("%f", value->u.double_value);
        break;
    case CRB_STRING_VALUE:
        printf("%s", value->u.object->u.string.string);
        break;
    case CRB_NATIVE_POINTER_VALUE:
        printf("(%p)", value->u.native_pointer_value);
        break;
    case CRB_NULL_VALUE:
        printf("null");
        break;
    case CRB_ARRAY_VALUE:
        printf("(");
        for (i = 0; i < value->u.object->u.array.size; i++) {
            if (i > 0) {
                printf(", ");
            }
            print_value(&value->u.object->u.array.array[i]);
        }
        printf(")");
        break;
    }
}

CRB_Value
crb_nv_print_proc(CRB_Interpreter *interpreter,
                  int arg_count, CRB_Value *args)
{
    CRB_Value value;

    value.type = CRB_NULL_VALUE;

    check_argument_count(arg_count, 1);
    print_value(&args[0]);

    return value;
}

CRB_Value
crb_nv_fopen_proc(CRB_Interpreter *interpreter,
                  int arg_count, CRB_Value *args)
{
    CRB_Value value;
    FILE *fp;

    check_argument_count(arg_count, 2);

    if (args[0].type != CRB_STRING_VALUE
        || args[1].type != CRB_STRING_VALUE) {
        crb_runtime_error(0, FOPEN_ARGUMENT_TYPE_ERR,
                          MESSAGE_ARGUMENT_END);
    }
    
    fp = fopen(args[0].u.object->u.string.string,
               args[1].u.object->u.string.string);
    if (fp == NULL) {
        value.type = CRB_NULL_VALUE;
    } else {
        value.type = CRB_NATIVE_POINTER_VALUE;
        value.u.native_pointer_value = fp;
    }

    return value;
}

CRB_Value
crb_nv_fclose_proc(CRB_Interpreter *interpreter,
                   int arg_count, CRB_Value *args)
{
    CRB_Value value;
    FILE *fp;

    check_argument_count(arg_count, 1);

    value.type = CRB_NULL_VALUE;
    if (args[0].type != CRB_NATIVE_POINTER_VALUE) {
        crb_runtime_error(0, FCLOSE_ARGUMENT_TYPE_ERR,
                          MESSAGE_ARGUMENT_END);
    }
    fp = args[0].u.native_pointer_value;
    fclose(fp);

    return value;
}

CRB_Value
crb_nv_fgets_proc(CRB_Interpreter *interpreter,
                  int arg_count, CRB_Value *args)
{
    CRB_Value value;
    FILE *fp;
    char buf[LINE_BUF_SIZE];
    char *ret_buf = NULL;
    int ret_len = 0;

    check_argument_count(arg_count, 1);

    if (args[0].type != CRB_NATIVE_POINTER_VALUE) {
        crb_runtime_error(0, FGETS_ARGUMENT_TYPE_ERR,
                          MESSAGE_ARGUMENT_END);
    }
    fp = args[0].u.native_pointer_value;

    while (fgets(buf, LINE_BUF_SIZE, fp)) {
        int new_len;
        new_len = ret_len + strlen(buf);
        ret_buf = MEM_realloc(ret_buf, new_len + 1);
        if (ret_len == 0) {
            strcpy(ret_buf, buf);
        } else {
            strcat(ret_buf, buf);
        }
        ret_len = new_len;
        if (ret_buf[ret_len-1] == '\n')
            break;
    }
    if (ret_len > 0) {
        value.type = CRB_STRING_VALUE;
        value.u.object = crb_create_crowbar_string(interpreter, ret_buf);
    } else {
        value.type = CRB_NULL_VALUE;
    }

    return value;
}

CRB_Value
crb_nv_fputs_proc(CRB_Interpreter *interpreter,
                  int arg_count, CRB_Value *args)
{
    CRB_Value value;
    FILE *fp;

    check_argument_count(arg_count, 2);
    value.type = CRB_NULL_VALUE;
    if (args[0].type != CRB_STRING_VALUE
        || args[1].type != CRB_NATIVE_POINTER_VALUE) {
        crb_runtime_error(0, FPUTS_ARGUMENT_TYPE_ERR,
                          MESSAGE_ARGUMENT_END);
    }
    fp = args[1].u.native_pointer_value;

    fputs(args[0].u.object->u.string.string, fp);

    return value;
}

CRB_Value
new_array_sub(CRB_Interpreter *inter,
              int arg_count, CRB_Value *args, int arg_idx)
{
    CRB_Value ret;
    int size;
    int i;

    if (args[arg_idx].type != CRB_INT_VALUE) {
        crb_runtime_error(0, NEW_ARRAY_ARGUMENT_TYPE_ERR,
                          MESSAGE_ARGUMENT_END);
    }

    size = args[arg_idx].u.int_value;

    ret.type = CRB_ARRAY_VALUE;
    ret.u.object = crb_create_array(inter, size);
    CRB_push_value(inter, &ret);

    if (arg_idx == arg_count-1) {
        for (i = 0; i < size; i++) {
            ret.u.object->u.array.array[i].type = CRB_NULL_VALUE;
        }
    } else {
        for (i = 0; i < size; i++) {
            ret.u.object->u.array.array[i]
                = new_array_sub(inter, arg_count, args, arg_idx+1);
        }
    }
    CRB_pop_value(inter);

    return ret;
}

CRB_Value
crb_nv_new_array_proc(CRB_Interpreter *interpreter,
                      int arg_count, CRB_Value *args)
{
    CRB_Value value;

    if (arg_count < 1) {
        crb_runtime_error(0, ARGUMENT_TOO_FEW_ERR,
                          MESSAGE_ARGUMENT_END);
    }

    value = new_array_sub(interpreter, arg_count, args, 0);

    return value;

}

/* [<][>][^][v][top][bottom][index][help] */