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