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