1 /****************************************************************************
2  * Copyright (C) 2008-2011 by Matteo Franchin                               *
3  *                                                                          *
4  * This file is part of Box.                                                *
5  *                                                                          *
6  *   Box is free software: you can redistribute it and/or modify it         *
7  *   under the terms of the GNU Lesser General Public License as published  *
8  *   by the Free Software Foundation, either version 3 of the License, or   *
9  *   (at your option) any later version.                                    *
10  *                                                                          *
11  *   Box is distributed in the hope that it will be useful,                 *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
14  *   GNU Lesser General Public License for more details.                    *
15  *                                                                          *
16  *   You should have received a copy of the GNU Lesser General Public       *
17  *   License along with Box.  If not, see <http://www.gnu.org/licenses/>.   *
18  ****************************************************************************/
19 
20 #include <stdlib.h>
21 #include <string.h>
22 #include <assert.h>
23 
24 #include "types.h"
25 #include "combs.h"
26 #include "mem.h"
27 #include "vm_priv.h"
28 #include "print.h"
29 #include "compiler.h"
30 #include "builtins.h"
31 #include "str.h"
32 #include "bltinstr.h"
33 
34 #include "vmproc.h"
35 #include "vmsymstuff.h"
36 
37 /****************************************************************************
38  * Here we interface Str and register it for the compiler.                  *
39  ****************************************************************************/
40 
My_Concat_C_String(BoxStr * s,const char * cstr)41 static BoxException *My_Concat_C_String(BoxStr *s, const char *cstr) {
42   if (BoxStr_Concat_C_String(s, cstr) == BOXTASK_OK)
43     return NULL;
44   return BoxException_Create("Failure allocating string");
45 }
46 
My_Concat_And_Free_C_String(BoxStr * s,char * cstr)47 static BoxException *My_Concat_And_Free_C_String(BoxStr *s, char *cstr) {
48   if (cstr && BoxStr_Concat_C_String(s, cstr) == BOXTASK_OK) {
49     Box_Mem_Free(cstr);
50     return NULL;
51   }
52 
53   Box_Mem_Free(cstr);
54   return BoxException_Create("Allocation failure (bltinstr.c)");
55 }
56 
57 BOXEXPORT BoxException *
Box_Runtime_Init_At_Str(BoxPtr * parent,BoxPtr * child)58 Box_Runtime_Init_At_Str(BoxPtr *parent, BoxPtr *child) {
59   BoxStr *s = BoxPtr_Get_Target(parent);
60   BoxStr_Init(s);
61   return NULL;
62 }
63 
64 BOXEXPORT BoxException *
Box_Runtime_Finish_At_Str(BoxPtr * parent,BoxPtr * child)65 Box_Runtime_Finish_At_Str(BoxPtr *parent, BoxPtr *child) {
66   BoxStr *s = BoxPtr_Get_Target(parent);
67   BoxStr_Finish(s);
68   return NULL;
69 }
70 
71 BOXEXPORT BoxException *
Box_Runtime_Pause_At_Str(BoxPtr * parent,BoxPtr * child)72 Box_Runtime_Pause_At_Str(BoxPtr *parent, BoxPtr *child) {
73   BoxStr *s = BoxPtr_Get_Target(parent);
74   return My_Concat_C_String(s, "\n");
75 }
76 
77 BOXEXPORT BoxException *
Box_Runtime_Char_At_Str(BoxPtr * parent,BoxPtr * child)78 Box_Runtime_Char_At_Str(BoxPtr *parent, BoxPtr *child) {
79   BoxStr *s = BoxPtr_Get_Target(parent);
80   char ca[2] = {*((char *) BoxPtr_Get_Target(child)), '\0'};
81   return My_Concat_C_String(s, ca);
82 }
83 
84 BOXEXPORT BoxException *
Box_Runtime_INT_At_Str(BoxPtr * parent,BoxPtr * child)85 Box_Runtime_INT_At_Str(BoxPtr *parent, BoxPtr *child) {
86   BoxStr *s = BoxPtr_Get_Target(parent);
87   BoxInt i = *((BoxInt *) BoxPtr_Get_Target(child));
88   return My_Concat_And_Free_C_String(s, Box_SPrintF("%I", i));
89 }
90 
91 BOXEXPORT BoxException *
Box_Runtime_REAL_At_Str(BoxPtr * parent,BoxPtr * child)92 Box_Runtime_REAL_At_Str(BoxPtr *parent, BoxPtr *child) {
93   BoxStr *s = BoxPtr_Get_Target(parent);
94   BoxReal r = *((BoxReal *) BoxPtr_Get_Target(child));
95   return My_Concat_And_Free_C_String(s, Box_SPrintF("%R", r));
96 }
97 
98 BOXEXPORT BoxException *
Box_Runtime_Point_At_Str(BoxPtr * parent,BoxPtr * child)99 Box_Runtime_Point_At_Str(BoxPtr *parent, BoxPtr *child) {
100   BoxStr *s = BoxPtr_Get_Target(parent);
101   BoxPoint *p = (BoxPoint *) BoxPtr_Get_Target(child);
102   return My_Concat_And_Free_C_String(s, Box_SPrintF("(%R, %R)", p->x, p->y));
103 }
104 
105 BOXEXPORT BoxException *
Box_Runtime_Ptr_At_Str(BoxPtr * parent,BoxPtr * child)106 Box_Runtime_Ptr_At_Str(BoxPtr *parent, BoxPtr *child) {
107   BoxStr *s = BoxPtr_Get_Target(parent);
108   BoxPtr *p = BoxPtr_Get_Target(child);
109   char *cs = Box_SPrintF("Ptr[.block=%p, .data=%p]", p->block, p->ptr);
110   return My_Concat_And_Free_C_String(s, cs);
111 }
112 
113 BOXEXPORT BoxException *
Box_Runtime_CPtr_At_Str(BoxPtr * parent,BoxPtr * child)114 Box_Runtime_CPtr_At_Str(BoxPtr *parent, BoxPtr *child) {
115   BoxStr *s = BoxPtr_Get_Target(parent);
116   BoxCPtr cp = *((BoxCPtr *) BoxPtr_Get_Target(child));
117   char *cs = Box_SPrintF("CPtr[%p]", cp);
118   return My_Concat_And_Free_C_String(s, cs);
119 }
120 
121 BOXEXPORT BoxException *
Box_Runtime_Str_At_Str(BoxPtr * parent,BoxPtr * child)122 Box_Runtime_Str_At_Str(BoxPtr *parent, BoxPtr *child) {
123   BoxStr *dst = BoxPtr_Get_Target(parent);
124   BoxStr *src = BoxPtr_Get_Target(child);
125   if (src->length > 0)
126     return My_Concat_C_String(dst, src->ptr);
127   return NULL;
128 }
129 
130 BOXEXPORT BoxException *
Box_Runtime_Obj_At_Str(BoxPtr * parent,BoxPtr * child)131 Box_Runtime_Obj_At_Str(BoxPtr *parent, BoxPtr *child) {
132   BoxStr *s = BoxPtr_Get_Target(parent);
133   char *c_s = BoxPtr_Get_Target(child);
134   assert(s);
135   return My_Concat_C_String(s, c_s);
136 }
137 
138 BOXEXPORT BoxException *
Box_Runtime_Str_To_Str(BoxPtr * parent,BoxPtr * child)139 Box_Runtime_Str_To_Str(BoxPtr *parent, BoxPtr *child) {
140   BoxStr *dst = BoxPtr_Get_Target(parent),
141          *src = BoxPtr_Get_Target(child);
142 
143   char *src_text = (char *) src->ptr; /* Need this (for case: src == dest) */
144   BoxStr_Init(dst);
145   if (src->length > 0)
146     return My_Concat_C_String(dst, src_text);
147 
148   return NULL;
149 }
150 
151 BOXEXPORT BoxException *
Box_Runtime_Str_At_Num(BoxPtr * parent,BoxPtr * child)152 Box_Runtime_Str_At_Num(BoxPtr *parent, BoxPtr *child) {
153   BoxInt *len = BoxPtr_Get_Target(parent);
154   BoxStr *s = BoxPtr_Get_Target(child);
155   *len += s->length;
156   return NULL;
157 }
158 
My_Compare_Str(BoxVMX * vm)159 static BoxTask My_Compare_Str(BoxVMX *vm) {
160   BoxInt *compare = BOX_VM_THIS_PTR(vm, BoxInt);
161   struct struc_str_couple {BoxStr left, right;} *str_couple;
162   str_couple = BOX_VM_ARG_PTR(vm, struct struc_str_couple);
163   *compare = BoxStr_Compare(& str_couple->left, & str_couple->right);
164   return BOXTASK_OK;
165 }
166 
My_Register_Compare_Str(BoxCmp * c)167 static void My_Register_Compare_Str(BoxCmp *c) {
168   BoxType *str = Box_Get_Core_Type(BOXTYPEID_STR);
169   BoxType *str_couple = BoxType_Create_Structure();
170   BoxType_Add_Member_To_Structure(str_couple, str, NULL);
171   BoxType_Add_Member_To_Structure(str_couple, str, NULL);
172   Bltin_Proc_Def(Box_Get_Core_Type(BOXTYPEID_COMPARE),
173                  str_couple, My_Compare_Str);
174   (void) BoxType_Unlink(str_couple);
175 }
176 
Bltin_Str_Register_Procs(BoxCmp * c)177 void Bltin_Str_Register_Procs(BoxCmp *c) {
178   BoxType *t_str = Box_Get_Core_Type(BOXTYPEID_STR),
179           *t_num = Box_Get_Core_Type(BOXTYPEID_NUM);
180   BoxCombDef defs[] =
181     {BOXCOMBDEF_I_AT_T(BOXTYPEID_INIT, t_str, Box_Runtime_Init_At_Str),
182      BOXCOMBDEF_I_AT_T(BOXTYPEID_FINISH, t_str, Box_Runtime_Finish_At_Str),
183      BOXCOMBDEF_T_TO_T(t_str, t_str, Box_Runtime_Str_To_Str),
184      BOXCOMBDEF_I_AT_T(BOXTYPEID_PAUSE, t_str, Box_Runtime_Pause_At_Str),
185      BOXCOMBDEF_I_AT_T(BOXTYPEID_CHAR, t_str, Box_Runtime_Char_At_Str),
186      BOXCOMBDEF_I_AT_T(BOXTYPEID_INT, t_str, Box_Runtime_INT_At_Str),
187      BOXCOMBDEF_I_AT_T(BOXTYPEID_REAL, t_str, Box_Runtime_REAL_At_Str),
188      BOXCOMBDEF_I_AT_T(BOXTYPEID_SPOINT, t_str, Box_Runtime_Point_At_Str),
189      BOXCOMBDEF_T_AT_T(t_str, t_str, Box_Runtime_Str_At_Str),
190      BOXCOMBDEF_I_AT_T(BOXTYPEID_PTR, t_str, Box_Runtime_Ptr_At_Str),
191      BOXCOMBDEF_I_AT_T(BOXTYPEID_CPTR, t_str, Box_Runtime_CPtr_At_Str),
192      BOXCOMBDEF_I_AT_T(BOXTYPEID_OBJ, t_str, Box_Runtime_Obj_At_Str),
193      BOXCOMBDEF_T_AT_T(t_str, t_num, Box_Runtime_Str_At_Num)};
194   size_t num_defs = sizeof(defs)/sizeof(BoxCombDef);
195   (void) BoxCombDef_Define(defs, num_defs);
196 
197   /* String comparison */
198   My_Register_Compare_Str(c);
199 }
200