/****************************************************************************
* Copyright (C) 2008-2011 by Matteo Franchin *
* *
* This file is part of Box. *
* *
* Box is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* Box is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with Box. If not, see . *
****************************************************************************/
#include
#include
#include
#include "types.h"
#include "combs.h"
#include "mem.h"
#include "vm_priv.h"
#include "print.h"
#include "compiler.h"
#include "builtins.h"
#include "str.h"
#include "bltinstr.h"
#include "vmproc.h"
#include "vmsymstuff.h"
/****************************************************************************
* Here we interface Str and register it for the compiler. *
****************************************************************************/
static BoxException *My_Concat_C_String(BoxStr *s, const char *cstr) {
if (BoxStr_Concat_C_String(s, cstr) == BOXTASK_OK)
return NULL;
return BoxException_Create("Failure allocating string");
}
static BoxException *My_Concat_And_Free_C_String(BoxStr *s, char *cstr) {
if (cstr && BoxStr_Concat_C_String(s, cstr) == BOXTASK_OK) {
Box_Mem_Free(cstr);
return NULL;
}
Box_Mem_Free(cstr);
return BoxException_Create("Allocation failure (bltinstr.c)");
}
BOXEXPORT BoxException *
Box_Runtime_Init_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
BoxStr_Init(s);
return NULL;
}
BOXEXPORT BoxException *
Box_Runtime_Finish_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
BoxStr_Finish(s);
return NULL;
}
BOXEXPORT BoxException *
Box_Runtime_Pause_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
return My_Concat_C_String(s, "\n");
}
BOXEXPORT BoxException *
Box_Runtime_Char_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
char ca[2] = {*((char *) BoxPtr_Get_Target(child)), '\0'};
return My_Concat_C_String(s, ca);
}
BOXEXPORT BoxException *
Box_Runtime_INT_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
BoxInt i = *((BoxInt *) BoxPtr_Get_Target(child));
return My_Concat_And_Free_C_String(s, Box_SPrintF("%I", i));
}
BOXEXPORT BoxException *
Box_Runtime_REAL_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
BoxReal r = *((BoxReal *) BoxPtr_Get_Target(child));
return My_Concat_And_Free_C_String(s, Box_SPrintF("%R", r));
}
BOXEXPORT BoxException *
Box_Runtime_Point_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
BoxPoint *p = (BoxPoint *) BoxPtr_Get_Target(child);
return My_Concat_And_Free_C_String(s, Box_SPrintF("(%R, %R)", p->x, p->y));
}
BOXEXPORT BoxException *
Box_Runtime_Ptr_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
BoxPtr *p = BoxPtr_Get_Target(child);
char *cs = Box_SPrintF("Ptr[.block=%p, .data=%p]", p->block, p->ptr);
return My_Concat_And_Free_C_String(s, cs);
}
BOXEXPORT BoxException *
Box_Runtime_CPtr_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
BoxCPtr cp = *((BoxCPtr *) BoxPtr_Get_Target(child));
char *cs = Box_SPrintF("CPtr[%p]", cp);
return My_Concat_And_Free_C_String(s, cs);
}
BOXEXPORT BoxException *
Box_Runtime_Str_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *dst = BoxPtr_Get_Target(parent);
BoxStr *src = BoxPtr_Get_Target(child);
if (src->length > 0)
return My_Concat_C_String(dst, src->ptr);
return NULL;
}
BOXEXPORT BoxException *
Box_Runtime_Obj_At_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *s = BoxPtr_Get_Target(parent);
char *c_s = BoxPtr_Get_Target(child);
assert(s);
return My_Concat_C_String(s, c_s);
}
BOXEXPORT BoxException *
Box_Runtime_Str_To_Str(BoxPtr *parent, BoxPtr *child) {
BoxStr *dst = BoxPtr_Get_Target(parent),
*src = BoxPtr_Get_Target(child);
char *src_text = (char *) src->ptr; /* Need this (for case: src == dest) */
BoxStr_Init(dst);
if (src->length > 0)
return My_Concat_C_String(dst, src_text);
return NULL;
}
BOXEXPORT BoxException *
Box_Runtime_Str_At_Num(BoxPtr *parent, BoxPtr *child) {
BoxInt *len = BoxPtr_Get_Target(parent);
BoxStr *s = BoxPtr_Get_Target(child);
*len += s->length;
return NULL;
}
static BoxTask My_Compare_Str(BoxVMX *vm) {
BoxInt *compare = BOX_VM_THIS_PTR(vm, BoxInt);
struct struc_str_couple {BoxStr left, right;} *str_couple;
str_couple = BOX_VM_ARG_PTR(vm, struct struc_str_couple);
*compare = BoxStr_Compare(& str_couple->left, & str_couple->right);
return BOXTASK_OK;
}
static void My_Register_Compare_Str(BoxCmp *c) {
BoxType *str = Box_Get_Core_Type(BOXTYPEID_STR);
BoxType *str_couple = BoxType_Create_Structure();
BoxType_Add_Member_To_Structure(str_couple, str, NULL);
BoxType_Add_Member_To_Structure(str_couple, str, NULL);
Bltin_Proc_Def(Box_Get_Core_Type(BOXTYPEID_COMPARE),
str_couple, My_Compare_Str);
(void) BoxType_Unlink(str_couple);
}
void Bltin_Str_Register_Procs(BoxCmp *c) {
BoxType *t_str = Box_Get_Core_Type(BOXTYPEID_STR),
*t_num = Box_Get_Core_Type(BOXTYPEID_NUM);
BoxCombDef defs[] =
{BOXCOMBDEF_I_AT_T(BOXTYPEID_INIT, t_str, Box_Runtime_Init_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_FINISH, t_str, Box_Runtime_Finish_At_Str),
BOXCOMBDEF_T_TO_T(t_str, t_str, Box_Runtime_Str_To_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_PAUSE, t_str, Box_Runtime_Pause_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_CHAR, t_str, Box_Runtime_Char_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_INT, t_str, Box_Runtime_INT_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_REAL, t_str, Box_Runtime_REAL_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_SPOINT, t_str, Box_Runtime_Point_At_Str),
BOXCOMBDEF_T_AT_T(t_str, t_str, Box_Runtime_Str_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_PTR, t_str, Box_Runtime_Ptr_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_CPTR, t_str, Box_Runtime_CPtr_At_Str),
BOXCOMBDEF_I_AT_T(BOXTYPEID_OBJ, t_str, Box_Runtime_Obj_At_Str),
BOXCOMBDEF_T_AT_T(t_str, t_num, Box_Runtime_Str_At_Num)};
size_t num_defs = sizeof(defs)/sizeof(BoxCombDef);
(void) BoxCombDef_Define(defs, num_defs);
/* String comparison */
My_Register_Compare_Str(c);
}