2ed03c7a75181220d37f6a08f5733ccea9628d19
[framework/uifw/embryo.git] / src / lib / embryo_str.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include "embryo_private.h"
6 #include <fnmatch.h>
7
8 #define STRGET(ep, str, par) { \
9    Embryo_Cell *___cptr; \
10    str = NULL; \
11    if ((___cptr = embryo_data_address_get(ep, par))) { \
12         int ___l; \
13         ___l = embryo_data_string_length_get(ep, ___cptr); \
14         (str) = alloca(___l + 1); \
15         if (str) embryo_data_string_get(ep, ___cptr, str); \
16      } }
17 #define STRSET(ep, par, str) { \
18    Embryo_Cell *___cptr; \
19    if ((___cptr = embryo_data_address_get(ep, par))) { \
20       embryo_data_string_set(ep, str, ___cptr); \
21    } }
22
23 /* exported string api */
24
25 static Embryo_Cell
26 _embryo_str_atoi(Embryo_Program *ep, Embryo_Cell *params)
27 {
28    char *s1;
29
30    /* params[1] = str */
31    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
32    STRGET(ep, s1, params[1]);
33    if (!s1) return 0;
34    return (Embryo_Cell)atoi(s1);
35 }
36
37 static Embryo_Cell
38 _embryo_str_fnmatch(Embryo_Program *ep, Embryo_Cell *params)
39 {
40    char *s1, *s2;
41
42    /* params[1] = glob */
43    /* params[2] = str */
44    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
45    STRGET(ep, s1, params[1]);
46    STRGET(ep, s2, params[2]);
47    if ((!s1) || (!s2)) return -1;
48    return (Embryo_Cell)fnmatch(s1, s2, 0);
49 }
50
51 static Embryo_Cell
52 _embryo_str_strcmp(Embryo_Program *ep, Embryo_Cell *params)
53 {
54    char *s1, *s2;
55
56    /* params[1] = str1 */
57    /* params[2] = str2 */
58    if (params[0] != (2 * sizeof(Embryo_Cell))) return -1;
59    STRGET(ep, s1, params[1]);
60    STRGET(ep, s2, params[2]);
61    if ((!s1) || (!s2)) return -1;
62    return (Embryo_Cell)strcmp(s1, s2);
63 }
64
65 static Embryo_Cell
66 _embryo_str_strncmp(Embryo_Program *ep, Embryo_Cell *params)
67 {
68    char *s1, *s2;
69
70    /* params[1] = str1 */
71    /* params[2] = str2 */
72    /* params[3] = n */
73    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
74    if (params[3] < 0) params[3] = 0;
75    STRGET(ep, s1, params[1]);
76    STRGET(ep, s2, params[2]);
77    if ((!s1) || (!s2)) return -1;
78    return (Embryo_Cell)strncmp(s1, s2, (size_t)params[3]);
79 }
80
81 static Embryo_Cell
82 _embryo_str_strcpy(Embryo_Program *ep, Embryo_Cell *params)
83 {
84    char *s1;
85
86    /* params[1] = dst */
87    /* params[2] = str */
88    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
89    STRGET(ep, s1, params[2]);
90    if (!s1) return 0;
91    STRSET(ep, params[1], s1);
92    return 0;
93 }
94
95 static Embryo_Cell
96 _embryo_str_strncpy(Embryo_Program *ep, Embryo_Cell *params)
97 {
98    char *s1;
99    int l;
100
101    /* params[1] = dst */
102    /* params[2] = str */
103    /* params[3] = n */
104    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
105    if (params[3] < 0) params[3] = 0;
106    STRGET(ep, s1, params[2]);
107    if (!s1) return 0;
108    l = strlen(s1);
109    if (l > params[3]) s1[params[3]] = 0;
110    STRSET(ep, params[1], s1);
111    return 0;
112 }
113
114 static Embryo_Cell
115 _embryo_str_strlen(Embryo_Program *ep, Embryo_Cell *params)
116 {
117    char *s1;
118
119    /* params[1] = str */
120    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
121    STRGET(ep, s1, params[1]);
122    if (!s1) return 0;
123    return (Embryo_Cell)strlen(s1);
124 }
125
126 static Embryo_Cell
127 _embryo_str_strcat(Embryo_Program *ep, Embryo_Cell *params)
128 {
129    char *s1, *s2, *s3;
130
131    /* params[1] = dsr */
132    /* params[2] = str */
133    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
134    STRGET(ep, s1, params[1]);
135    STRGET(ep, s2, params[2]);
136    if ((!s1) || (!s2)) return 0;
137    s3 = alloca(strlen(s1) + strlen(s2) + 1);
138    if (!s3) return 0;
139    strcpy(s3, s1);
140    strcat(s3, s2);
141    STRSET(ep, params[1], s3);
142    return 0;
143 }
144
145 static Embryo_Cell
146 _embryo_str_strncat(Embryo_Program *ep, Embryo_Cell *params)
147 {
148    char *s1, *s2, *s3;
149    int l1, l2;
150
151    /* params[1] = dst */
152    /* params[2] = str */
153    /* params[3] = n */
154    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
155    if (params[3] < 0) params[3] = 0;
156    STRGET(ep, s1, params[1]);
157    STRGET(ep, s2, params[2]);
158    if ((!s1) || (!s2)) return 0;
159    l1 = strlen(s1);
160    l2 = strlen(s2);
161    s3 = alloca(l1 + l2 + 1);
162    if (!s3) return 0;
163    strcpy(s3, s1);
164    strncat(s3, s2, params[3]);
165    if (l2 >= params[3]) s3[l1 + params[3]] = 0;
166    STRSET(ep, params[1], s3);
167    return 0;
168 }
169
170 static Embryo_Cell
171 _embryo_str_strprep(Embryo_Program *ep, Embryo_Cell *params)
172 {
173    char *s1, *s2, *s3;
174
175    /* params[1] = dst */
176    /* params[2] = str */
177    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
178    STRGET(ep, s1, params[1]);
179    STRGET(ep, s2, params[2]);
180    if ((!s1) || (!s2)) return 0;
181    s3 = alloca(strlen(s1) + strlen(s2) + 1);
182    if (!s3) return 0;
183    strcpy(s3, s2);
184    strcat(s3, s1);
185    STRSET(ep, params[1], s3);
186    return 0;
187 }
188
189 static Embryo_Cell
190 _embryo_str_strnprep(Embryo_Program *ep, Embryo_Cell *params)
191 {
192    char *s1, *s2, *s3;
193    int l1, l2;
194
195    /* params[1] = dst */
196    /* params[2] = str */
197    /* params[3] = n */
198    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
199    if (params[3] < 0) params[3] = 0;
200    STRGET(ep, s1, params[1]);
201    STRGET(ep, s2, params[2]);
202    if ((!s1) || (!s2)) return 0;
203    l1 = strlen(s1);
204    l2 = strlen(s2);
205    s3 = alloca(l1 + l2 + 1);
206    if (!s3) return 0;
207    strncpy(s3, s2, params[3]);
208    if (params[3] <= l2) s3[params[3]] = 0;
209    strcat(s3, s1);
210    STRSET(ep, params[1], s3);
211    return 0;
212 }
213
214 static Embryo_Cell
215 _embryo_str_strcut(Embryo_Program *ep, Embryo_Cell *params)
216 {
217    char *s1, *s2;
218    int l1;
219
220    /* params[1] = dst */
221    /* params[2] = str */
222    /* params[3] = n */
223    /* params[4] = n2 */
224    if (params[0] != (4 * sizeof(Embryo_Cell))) return 0;
225    if (params[3] < 0) params[3] = 0;
226    if (params[4] < params[3]) params[4] = params[3];
227    STRGET(ep, s1, params[2]);
228    if (!s1) return 0;
229    l1 = strlen(s1);
230    if (params[3] >= l1) params[3] = l1;
231    if (params[4] >= l1) params[4] = l1;
232    if (params[4] == params[3])
233      {
234         STRSET(ep, params[1], "");
235         return 0;
236      }
237    s2 = alloca(params[4] - params[3] + 1);
238    strncpy(s2, s1 + params[3], params[4] - params[3]);
239    s2[params[4] - params[3]] = 0;
240    STRSET(ep, params[1], s2);
241    return 0;
242 }
243
244 static Embryo_Cell
245 _embryo_str_snprintf(Embryo_Program *ep, Embryo_Cell *params)
246 {
247    char *s1, *s2;
248    int i, o;
249    int inesc = 0;
250    int insub = 0;
251    int p, pnum;
252
253    /* params[1] = buf */
254    /* params[2] = bufsize */
255    /* params[3] = format_string */
256    /* params[4] = first arg ... */
257    if (params[0] < (3 * sizeof(Embryo_Cell))) return 0;
258    if (params[2] <= 0) return 0;
259    STRGET(ep, s1, params[3]);
260    if (!s1) return -1;
261    s2 = alloca(params[2] + 1);
262    if (!s2) return -1;
263    s2[0] = 0;
264    pnum = (params[0] / sizeof(Embryo_Cell)) - 3;
265    for (p = 0, o = 0, i = 0; (s1[i]) && (o < (params[2] - 1)) && (p < (pnum + 1)); i++)
266      {
267         if ((!inesc) && (!insub))
268           {
269              if      (s1[i] == '\\') inesc = 1;
270              else if (s1[i] == '%')  insub = 1;
271              if ((!inesc) && (!insub))
272                {
273                   s2[o] = s1[i];
274                   o++;
275                }
276           }
277         else
278           {
279              Embryo_Cell *cptr;
280
281              if (inesc)
282                {
283                   switch (s1[i])
284                     {
285                      case 't':
286                        s2[o] = '\t';
287                        o++;
288                        break;
289                      case 'n':
290                        s2[o] = '\n';
291                        o++;
292                        break;
293                      default:
294                        s2[o] = s1[i];
295                        o++;
296                        break;
297                     }
298                   inesc = 0;
299                }
300              if ((insub) && (s1[i] == '%')) pnum++;
301              if ((insub) && (p < pnum))
302                {
303                   switch (s1[i])
304                     {
305                      case '%':
306                        s2[o] = '%';
307                        o++;
308                        break;
309                      case 'c':
310                        cptr = embryo_data_address_get(ep, params[4 + p]);
311                        if (cptr) s2[o] = (char)(*cptr);
312                        p++;
313                        o++;
314                        break;
315                      case 'i':
316                      case 'd':
317                      case 'x':
318                      case 'X':
319                          {
320                             char fmt[10] = "";
321                             char tmp[256] = "";
322                             int l;
323
324                             if      (s1[i] == 'i') strcpy(fmt, "%i");
325                             else if (s1[i] == 'd') strcpy(fmt, "%d");
326                             else if (s1[i] == 'x') strcpy(fmt, "%x");
327                             else if (s1[i] == 'X') strcpy(fmt, "%08x");
328                             cptr = embryo_data_address_get(ep, params[4 + p]);
329                             if (cptr) snprintf(tmp, sizeof(tmp), fmt, (int)(*cptr));
330                             l = strlen(tmp);
331                             if ((o + l) > (params[2] - 1))
332                               {
333                                  l = params[2] - 1 - o;
334                                  if (l < 0) l = 0;
335                                  tmp[l] = 0;
336                               }
337                             strcpy(s2 + o, tmp);
338                             o += l;
339                             p++;
340                          }
341                        break;
342                      case 'f':
343                          {
344                             char tmp[256] = "";
345                             int l;
346
347                             cptr = embryo_data_address_get(ep, params[4 + p]);
348                             if (cptr) snprintf(tmp, sizeof(tmp), "%f", (double)EMBRYO_CELL_TO_FLOAT(*cptr));
349                             l = strlen(tmp);
350                             if ((o + l) > (params[2] - 1))
351                               {
352                                  l = params[2] - 1 - o;
353                                  if (l < 0) l = 0;
354                                  tmp[l] = 0;
355                               }
356                             strcpy(s2 + o, tmp);
357                             o += l;
358                             p++;
359                          }
360                        break;
361                      case 's':
362                          {
363                             char *tmp;
364                             int l;
365
366                             STRGET(ep, tmp, params[4 + p]);
367                             l = strlen(tmp);
368                             if ((o + l) > (params[2] - 1))
369                               {
370                                  l = params[2] - 1 - o;
371                                  if (l < 0) l = 0;
372                                  tmp[l] = 0;
373                               }
374                             strcpy(s2 + o, tmp);
375                             o += l;
376                             p++;
377                          }
378                        break;
379                      default:
380                        break;
381                     }
382                   insub = 0;
383                }
384              else if (insub)
385                insub = 0;
386           }
387      }
388    s2[o] = 0;
389
390    STRSET(ep, params[1], s2);
391    return o;
392 }
393
394 static Embryo_Cell
395 _embryo_str_strstr(Embryo_Program *ep, Embryo_Cell *params)
396 {
397    char *s1, *s2, *p;
398
399    /* params[1] = str */
400    /* params[2] = ndl */
401    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
402    STRGET(ep, s1, params[1]);
403    STRGET(ep, s2, params[2]);
404    if ((!s1) || (!s2)) return -1;
405    p = strstr(s1, s2);
406    if (p == NULL) return -1;
407    return (Embryo_Cell)(p - s1);
408 }
409
410 static Embryo_Cell
411 _embryo_str_strchr(Embryo_Program *ep, Embryo_Cell *params)
412 {
413    char *s1, *s2, *p;
414
415    /* params[1] = str */
416    /* params[2] = ch */
417    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
418    STRGET(ep, s1, params[1]);
419    STRGET(ep, s2, params[2]);
420    p = strchr(s1, s2[0]);
421    if (p == NULL) return -1;
422    return (Embryo_Cell)(p - s1);
423 }
424
425 static Embryo_Cell
426 _embryo_str_strrchr(Embryo_Program *ep, Embryo_Cell *params)
427 {
428    char *s1, *s2, *p;
429
430    /* params[1] = str */
431    /* params[2] = ch */
432    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
433    STRGET(ep, s1, params[1]);
434    STRGET(ep, s2, params[2]);
435    p = strrchr(s1, s2[0]);
436    if (p == NULL) return -1;
437    return (Embryo_Cell)(p - s1);
438 }
439
440 /* functions used by the rest of embryo */
441
442 void
443 _embryo_str_init(Embryo_Program *ep)
444 {
445    embryo_program_native_call_add(ep, "atoi",     _embryo_str_atoi);
446    embryo_program_native_call_add(ep, "fnmatch",  _embryo_str_fnmatch);
447    embryo_program_native_call_add(ep, "strcmp",   _embryo_str_strcmp);
448    embryo_program_native_call_add(ep, "strncmp",  _embryo_str_strncmp);
449    embryo_program_native_call_add(ep, "strcpy",   _embryo_str_strcpy);
450    embryo_program_native_call_add(ep, "strncpy",  _embryo_str_strncpy);
451    embryo_program_native_call_add(ep, "strlen",   _embryo_str_strlen);
452    embryo_program_native_call_add(ep, "strcat",   _embryo_str_strcat);
453    embryo_program_native_call_add(ep, "strncat",  _embryo_str_strncat);
454    embryo_program_native_call_add(ep, "strprep",  _embryo_str_strprep);
455    embryo_program_native_call_add(ep, "strnprep", _embryo_str_strnprep);
456    embryo_program_native_call_add(ep, "strcut",   _embryo_str_strcut);
457    embryo_program_native_call_add(ep, "snprintf", _embryo_str_snprintf);
458    embryo_program_native_call_add(ep, "strstr",   _embryo_str_strstr);
459    embryo_program_native_call_add(ep, "strchr",   _embryo_str_strchr);
460    embryo_program_native_call_add(ep, "strrchr",  _embryo_str_strrchr);
461 }