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