root/native.c

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

DEFINITIONS

This source file includes following definitions.
  1. FOPEN_ARGUMENT_TYPE_ERR
  2. FCLOSE_ARGUMENT_TYPE_ERR
  3. FGETS_ARGUMENT_TYPE_ERR
  4. FILE_ALREADY_CLOSED_ERR
  5. FPUTS_ARGUMENT_TYPE_ERR
  6. NEW_ARRAY_ARGUMENT_TYPE_ERR
  7. NEW_ARRAY_ARGUMENT_TOO_FEW_ERR
  8. NativeErrorCode
  9. file_finalizer
  10. crb_nv_print_proc
  11. check_file_pointer
  12. crb_nv_fopen_proc
  13. crb_nv_fclose_proc
  14. crb_nv_fgets_proc
  15. crb_nv_fputs_proc
  16. new_array_sub
  17. crb_nv_new_array_proc
  18. crb_nv_new_object_proc

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

#define LINE_BUF_SIZE   (1024)

typedef enum {
    FOPEN_ARGUMENT_TYPE_ERR = 0,
    FCLOSE_ARGUMENT_TYPE_ERR,
    FGETS_ARGUMENT_TYPE_ERR,
    FILE_ALREADY_CLOSED_ERR,
    FPUTS_ARGUMENT_TYPE_ERR,
    NEW_ARRAY_ARGUMENT_TYPE_ERR,
    NEW_ARRAY_ARGUMENT_TOO_FEW_ERR,
} NativeErrorCode;

extern CRB_MessageFormat crb_native_error_message_format[];

static CRB_NativeLibInfo st_lib_info = {
    crb_native_error_message_format,
};

void file_finalizer(CRB_Interpreter *inter, CRB_Object *obj);

static CRB_NativePointerInfo st_file_type_info = {
    "crowbar.lang.file",
    file_finalizer
};

void
file_finalizer(CRB_Interpreter *inter, CRB_Object *obj)
{
    FILE *fp;

    fp = (FILE*)CRB_object_get_native_pointer(obj);
    if (fp) {
        fclose(fp);
    }
}

CRB_Value
crb_nv_print_proc(CRB_Interpreter *interpreter,
                  CRB_LocalEnvironment *env,
                  int arg_count, CRB_Value *args)
{
    CRB_Value value;
    char *str;

    value.type = CRB_NULL_VALUE;

    CRB_check_argument_count(interpreter, env, arg_count, 1);

    str = CRB_value_to_string(&args[0]);
    printf("%s", str);
    MEM_free(str);

    return value;
}

static void
check_file_pointer(CRB_Interpreter *inter, CRB_LocalEnvironment *env,
                   CRB_Object *obj)
{
    FILE *fp;

    fp = (FILE*)CRB_object_get_native_pointer(obj);
    if (fp == NULL) {
        CRB_error(inter, env, &st_lib_info, __LINE__,
                  (int)FILE_ALREADY_CLOSED_ERR,
                  CRB_MESSAGE_ARGUMENT_END);
    }
}

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

    CRB_check_argument_count(interpreter, env, arg_count, 2);

    if (args[0].type != CRB_STRING_VALUE
        || args[1].type != CRB_STRING_VALUE) {
        CRB_error(interpreter, env, &st_lib_info, __LINE__,
                  (int)FOPEN_ARGUMENT_TYPE_ERR,
                  CRB_MESSAGE_ARGUMENT_END);
    }
    
    fp = fopen(CRB_object_get_string(args[0].u.object),
               CRB_object_get_string(args[1].u.object));
    if (fp == NULL) {
        value.type = CRB_NULL_VALUE;
    } else {
        value.type = CRB_NATIVE_POINTER_VALUE;
        value.u.object
            = CRB_create_native_pointer(interpreter, fp, &st_file_type_info);
    }

    return value;
}

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

    CRB_check_argument_count(interpreter, env, arg_count, 1);

    value.type = CRB_NULL_VALUE;
    if (args[0].type != CRB_NATIVE_POINTER_VALUE
        || (!CRB_check_native_pointer_type(args[0].u.object,
                                           &st_file_type_info))) {
        CRB_error(interpreter, env, &st_lib_info, __LINE__,
                  (int)FCLOSE_ARGUMENT_TYPE_ERR,
                  CRB_MESSAGE_ARGUMENT_END);
    }
    check_file_pointer(interpreter,env, args[0].u.object);
    fp = CRB_object_get_native_pointer(args[0].u.object);
    fclose(fp);
    CRB_object_set_native_pointer(args[0].u.object, NULL);

    return value;
}

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

    CRB_check_argument_count(interpreter, env, arg_count, 1);

    if (args[0].type != CRB_NATIVE_POINTER_VALUE
        || (!CRB_check_native_pointer_type(args[0].u.object,
                                           &st_file_type_info))) {
        CRB_error(interpreter, env, &st_lib_info, __LINE__,
                  (int)FGETS_ARGUMENT_TYPE_ERR,
                  CRB_MESSAGE_ARGUMENT_END);
    }
    check_file_pointer(interpreter,env, args[0].u.object);
    fp = CRB_object_get_native_pointer(args[0].u.object);

    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,
                  CRB_LocalEnvironment *env,
                  int arg_count, CRB_Value *args)
{
    CRB_Value value;
    FILE *fp;

    CRB_check_argument_count(interpreter, env, arg_count, 2);
    value.type = CRB_NULL_VALUE;
    if (args[0].type != CRB_STRING_VALUE
        || args[1].type != CRB_NATIVE_POINTER_VALUE
        || (!CRB_check_native_pointer_type(args[1].u.object,
                                           &st_file_type_info))) {
        CRB_error(interpreter, env, &st_lib_info, __LINE__,
                  (int)FPUTS_ARGUMENT_TYPE_ERR,
                  CRB_MESSAGE_ARGUMENT_END);
    }
    check_file_pointer(interpreter,env, args[1].u.object);
    fp = CRB_object_get_native_pointer(args[1].u.object);

    fputs(CRB_object_get_string(args[0].u.object), fp);

    return value;
}

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

    if (args[arg_idx].type != CRB_INT_VALUE) {
        CRB_error(inter, env, &st_lib_info, __LINE__,
                  (int)NEW_ARRAY_ARGUMENT_TYPE_ERR,
                  CRB_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) {
        value.type = CRB_NULL_VALUE;
        for (i = 0; i < size; i++) {
            CRB_array_set(inter, env, ret.u.object, i, &value);
        }
    } else {
        for (i = 0; i < size; i++) {
            value = new_array_sub(inter, env,
                                  arg_count, args, arg_idx+1);
            CRB_array_set(inter, env, ret.u.object, i, &value);
        }
    }
    CRB_pop_value(inter);

    return ret;
}

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

    if (arg_count < 1) {
        CRB_error(interpreter, env, &st_lib_info, __LINE__,
                  (int)NEW_ARRAY_ARGUMENT_TOO_FEW_ERR,
                  CRB_MESSAGE_ARGUMENT_END);
    }

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

    return value;
}

CRB_Value
crb_nv_new_object_proc(CRB_Interpreter *interpreter,
                       CRB_LocalEnvironment *env,
                       int arg_count, CRB_Value *args)
{
    CRB_Value value;

    CRB_check_argument_count(interpreter, env, arg_count, 0);
    value.type = CRB_ASSOC_VALUE;
    value.u.object = CRB_create_assoc(interpreter);

    return value;
}

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