aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/embryo/embryo_str.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/embryo/embryo_str.c')
-rw-r--r--src/lib/embryo/embryo_str.c498
1 files changed, 498 insertions, 0 deletions
diff --git a/src/lib/embryo/embryo_str.c b/src/lib/embryo/embryo_str.c
new file mode 100644
index 000000000..0c2faa2d1
--- /dev/null
+++ b/src/lib/embryo/embryo_str.c
@@ -0,0 +1,498 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif !defined alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# elif defined _AIX
+# define alloca __alloca
+# elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# elif !defined HAVE_ALLOCA
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+# endif
+#endif
+
+#ifdef HAVE_EXOTIC
+# include <Exotic.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fnmatch.h>
+
+#include "Embryo.h"
+#include "embryo_private.h"
+
+#define STRGET(ep, str, par) { \
+ Embryo_Cell *___cptr; \
+ str = NULL; \
+ if ((___cptr = embryo_data_address_get(ep, par))) { \
+ int ___l; \
+ ___l = embryo_data_string_length_get(ep, ___cptr); \
+ (str) = alloca(___l + 1); \
+ if (str) embryo_data_string_get(ep, ___cptr, str); \
+ } }
+#define STRSET(ep, par, str) { \
+ Embryo_Cell *___cptr; \
+ if ((___cptr = embryo_data_address_get(ep, par))) { \
+ embryo_data_string_set(ep, str, ___cptr); \
+ } }
+
+/* exported string api */
+
+static Embryo_Cell
+_embryo_str_atoi(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1;
+
+ /* params[1] = str */
+ if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ if (!s1) return 0;
+ return (Embryo_Cell)atoi(s1);
+}
+
+static Embryo_Cell
+_embryo_str_fnmatch(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2;
+
+ /* params[1] = glob */
+ /* params[2] = str */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return -1;
+ return (Embryo_Cell)fnmatch(s1, s2, 0);
+}
+
+static Embryo_Cell
+_embryo_str_strcmp(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2;
+
+ /* params[1] = str1 */
+ /* params[2] = str2 */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return -1;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return -1;
+ return (Embryo_Cell)strcmp(s1, s2);
+}
+
+static Embryo_Cell
+_embryo_str_strncmp(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2;
+
+ /* params[1] = str1 */
+ /* params[2] = str2 */
+ /* params[3] = n */
+ if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
+ if (params[3] < 0) params[3] = 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return -1;
+ return (Embryo_Cell)strncmp(s1, s2, (size_t)params[3]);
+}
+
+static Embryo_Cell
+_embryo_str_strcpy(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1;
+
+ /* params[1] = dst */
+ /* params[2] = str */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[2]);
+ if (!s1) return 0;
+ STRSET(ep, params[1], s1);
+ return 0;
+}
+
+static Embryo_Cell
+_embryo_str_strncpy(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1;
+ int l;
+
+ /* params[1] = dst */
+ /* params[2] = str */
+ /* params[3] = n */
+ if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
+ if (params[3] < 0) params[3] = 0;
+ STRGET(ep, s1, params[2]);
+ if (!s1) return 0;
+ l = strlen(s1);
+ if (l > params[3]) s1[params[3]] = 0;
+ STRSET(ep, params[1], s1);
+ return 0;
+}
+
+static Embryo_Cell
+_embryo_str_strlen(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1;
+
+ /* params[1] = str */
+ if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ if (!s1) return 0;
+ return (Embryo_Cell)strlen(s1);
+}
+
+static Embryo_Cell
+_embryo_str_strcat(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2, *s3;
+
+ /* params[1] = dsr */
+ /* params[2] = str */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return 0;
+ s3 = alloca(strlen(s1) + strlen(s2) + 1);
+ if (!s3) return 0;
+ strcpy(s3, s1);
+ strcat(s3, s2);
+ STRSET(ep, params[1], s3);
+ return 0;
+}
+
+static Embryo_Cell
+_embryo_str_strncat(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2, *s3;
+ int l1, l2;
+
+ /* params[1] = dst */
+ /* params[2] = str */
+ /* params[3] = n */
+ if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
+ if (params[3] < 0) params[3] = 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return 0;
+ l1 = strlen(s1);
+ l2 = strlen(s2);
+ s3 = alloca(l1 + l2 + 1);
+ if (!s3) return 0;
+ strcpy(s3, s1);
+ strncat(s3, s2, params[3]);
+ if (l2 >= params[3]) s3[l1 + params[3]] = 0;
+ STRSET(ep, params[1], s3);
+ return 0;
+}
+
+static Embryo_Cell
+_embryo_str_strprep(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2, *s3;
+
+ /* params[1] = dst */
+ /* params[2] = str */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return 0;
+ s3 = alloca(strlen(s1) + strlen(s2) + 1);
+ if (!s3) return 0;
+ strcpy(s3, s2);
+ strcat(s3, s1);
+ STRSET(ep, params[1], s3);
+ return 0;
+}
+
+static Embryo_Cell
+_embryo_str_strnprep(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2, *s3;
+ int l1, l2;
+
+ /* params[1] = dst */
+ /* params[2] = str */
+ /* params[3] = n */
+ if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
+ if (params[3] < 0) params[3] = 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return 0;
+ l1 = strlen(s1);
+ l2 = strlen(s2);
+ s3 = alloca(l1 + l2 + 1);
+ if (!s3) return 0;
+ strncpy(s3, s2, params[3]);
+ if (params[3] <= l2) s3[params[3]] = 0;
+ strcat(s3, s1);
+ STRSET(ep, params[1], s3);
+ return 0;
+}
+
+static Embryo_Cell
+_embryo_str_strcut(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2;
+ int l1;
+
+ /* params[1] = dst */
+ /* params[2] = str */
+ /* params[3] = n */
+ /* params[4] = n2 */
+ if (params[0] != (4 * sizeof(Embryo_Cell))) return 0;
+ if (params[3] < 0) params[3] = 0;
+ if (params[4] < params[3]) params[4] = params[3];
+ STRGET(ep, s1, params[2]);
+ if (!s1) return 0;
+ l1 = strlen(s1);
+ if (params[3] >= l1) params[3] = l1;
+ if (params[4] >= l1) params[4] = l1;
+ if (params[4] == params[3])
+ {
+ STRSET(ep, params[1], "");
+ return 0;
+ }
+ s2 = alloca(params[4] - params[3] + 1);
+ strncpy(s2, s1 + params[3], params[4] - params[3]);
+ s2[params[4] - params[3]] = 0;
+ STRSET(ep, params[1], s2);
+ return 0;
+}
+
+static Embryo_Cell
+_embryo_str_snprintf(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2;
+ int i, o;
+ int inesc = 0;
+ int insub = 0;
+ int p, pnum;
+
+ /* params[1] = buf */
+ /* params[2] = bufsize */
+ /* params[3] = format_string */
+ /* params[4] = first arg ... */
+ if (params[0] < (Embryo_Cell)(3 * sizeof(Embryo_Cell))) return 0;
+ if (params[2] <= 0) return 0;
+ STRGET(ep, s1, params[3]);
+ if (!s1) return -1;
+ s2 = alloca(params[2] + 1);
+ if (!s2) return -1;
+ s2[0] = 0;
+ pnum = (params[0] / sizeof(Embryo_Cell)) - 3;
+ for (p = 0, o = 0, i = 0; (s1[i]) && (o < (params[2] - 1)) && (p < (pnum + 1)); i++)
+ {
+ if ((!inesc) && (!insub))
+ {
+ if (s1[i] == '\\') inesc = 1;
+ else if (s1[i] == '%') insub = 1;
+ if ((!inesc) && (!insub))
+ {
+ s2[o] = s1[i];
+ o++;
+ }
+ }
+ else
+ {
+ Embryo_Cell *cptr;
+
+ if (inesc)
+ {
+ switch (s1[i])
+ {
+ case 't':
+ s2[o] = '\t';
+ o++;
+ break;
+ case 'n':
+ s2[o] = '\n';
+ o++;
+ break;
+ default:
+ s2[o] = s1[i];
+ o++;
+ break;
+ }
+ inesc = 0;
+ }
+ if ((insub) && (s1[i] == '%')) pnum++;
+ if ((insub) && (p < pnum))
+ {
+ switch (s1[i])
+ {
+ case '%':
+ s2[o] = '%';
+ o++;
+ break;
+ case 'c':
+ cptr = embryo_data_address_get(ep, params[4 + p]);
+ if (cptr) s2[o] = (char)(*cptr);
+ p++;
+ o++;
+ break;
+ case 'i':
+ case 'd':
+ case 'x':
+ case 'X':
+ {
+ char fmt[10] = "";
+ char tmp[256] = "";
+ int l;
+
+ if (s1[i] == 'i') strcpy(fmt, "%i");
+ else if (s1[i] == 'd') strcpy(fmt, "%d");
+ else if (s1[i] == 'x') strcpy(fmt, "%x");
+ else if (s1[i] == 'X') strcpy(fmt, "%08x");
+ cptr = embryo_data_address_get(ep, params[4 + p]);
+ if (cptr) snprintf(tmp, sizeof(tmp), fmt, (int)(*cptr));
+ l = strlen(tmp);
+ if ((o + l) > (params[2] - 1))
+ {
+ l = params[2] - 1 - o;
+ if (l < 0) l = 0;
+ tmp[l] = 0;
+ }
+ strcpy(s2 + o, tmp);
+ o += l;
+ p++;
+ }
+ break;
+ case 'f':
+ {
+ char tmp[256] = "";
+ int l;
+
+ cptr = embryo_data_address_get(ep, params[4 + p]);
+ if (cptr) snprintf(tmp, sizeof(tmp), "%f", (double)EMBRYO_CELL_TO_FLOAT(*cptr));
+ l = strlen(tmp);
+ if ((o + l) > (params[2] - 1))
+ {
+ l = params[2] - 1 - o;
+ if (l < 0) l = 0;
+ tmp[l] = 0;
+ }
+ strcpy(s2 + o, tmp);
+ o += l;
+ p++;
+ }
+ break;
+ case 's':
+ {
+ char *tmp;
+ int l;
+
+ STRGET(ep, tmp, params[4 + p]);
+ l = strlen(tmp);
+ if ((o + l) > (params[2] - 1))
+ {
+ l = params[2] - 1 - o;
+ if (l < 0) l = 0;
+ tmp[l] = 0;
+ }
+ strcpy(s2 + o, tmp);
+ o += l;
+ p++;
+ }
+ break;
+ default:
+ break;
+ }
+ insub = 0;
+ }
+ else if (insub)
+ insub = 0;
+ }
+ }
+ s2[o] = 0;
+
+ STRSET(ep, params[1], s2);
+ return o;
+}
+
+static Embryo_Cell
+_embryo_str_strstr(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2, *p;
+
+ /* params[1] = str */
+ /* params[2] = ndl */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return -1;
+ p = strstr(s1, s2);
+ if (!p) return -1;
+ return (Embryo_Cell)(p - s1);
+}
+
+static Embryo_Cell
+_embryo_str_strchr(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2, *p;
+
+ /* params[1] = str */
+ /* params[2] = ch */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return -1;
+ p = strchr(s1, s2[0]);
+ if (!p) return -1;
+ return (Embryo_Cell)(p - s1);
+}
+
+static Embryo_Cell
+_embryo_str_strrchr(Embryo_Program *ep, Embryo_Cell *params)
+{
+ char *s1, *s2, *p;
+
+ /* params[1] = str */
+ /* params[2] = ch */
+ if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
+ STRGET(ep, s1, params[1]);
+ STRGET(ep, s2, params[2]);
+ if ((!s1) || (!s2)) return -1;
+ p = strrchr(s1, s2[0]);
+ if (!p) return -1;
+ return (Embryo_Cell)(p - s1);
+}
+
+/* functions used by the rest of embryo */
+
+void
+_embryo_str_init(Embryo_Program *ep)
+{
+ embryo_program_native_call_add(ep, "atoi", _embryo_str_atoi);
+ embryo_program_native_call_add(ep, "fnmatch", _embryo_str_fnmatch);
+ embryo_program_native_call_add(ep, "strcmp", _embryo_str_strcmp);
+ embryo_program_native_call_add(ep, "strncmp", _embryo_str_strncmp);
+ embryo_program_native_call_add(ep, "strcpy", _embryo_str_strcpy);
+ embryo_program_native_call_add(ep, "strncpy", _embryo_str_strncpy);
+ embryo_program_native_call_add(ep, "strlen", _embryo_str_strlen);
+ embryo_program_native_call_add(ep, "strcat", _embryo_str_strcat);
+ embryo_program_native_call_add(ep, "strncat", _embryo_str_strncat);
+ embryo_program_native_call_add(ep, "strprep", _embryo_str_strprep);
+ embryo_program_native_call_add(ep, "strnprep", _embryo_str_strnprep);
+ embryo_program_native_call_add(ep, "strcut", _embryo_str_strcut);
+ embryo_program_native_call_add(ep, "snprintf", _embryo_str_snprintf);
+ embryo_program_native_call_add(ep, "strstr", _embryo_str_strstr);
+ embryo_program_native_call_add(ep, "strchr", _embryo_str_strchr);
+ embryo_program_native_call_add(ep, "strrchr", _embryo_str_strrchr);
+}