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