Fun 0.41.5
The programming language that makes You have fun
Loading...
Searching...
No Matches
regex_search.c
Go to the documentation of this file.
1/*
2 * This file is part of the Fun programming language.
3 * https://fun-lang.xyz/
4 *
5 * Copyright 2025 Johannes Findeisen <you@hanez.org>
6 * Licensed under the terms of the Apache-2.0 license.
7 * https://opensource.org/license/apache-2-0
8 */
9
37/* Regex search (first match) opcode using POSIX regex */
38#ifdef __unix__
39#include <regex.h>
40#include <stdlib.h>
41#include <string.h>
42#endif
43
45 Value pattern = pop_value(vm);
46 Value str = pop_value(vm);
47 if (str.type != VAL_STRING || pattern.type != VAL_STRING) {
48 fprintf(stderr, "Runtime type error: REGEX_SEARCH expects (string, string)\n");
49 exit(1);
50 }
51#ifndef __unix__
52 /* Return default empty result on unsupported platforms */
54 (void)map_set(&m, "match", make_string(""));
55 (void)map_set(&m, "start", make_int(-1));
56 (void)map_set(&m, "end", make_int(-1));
58 (void)map_set(&m, "groups", emptyArr);
62 break;
63#else
64 regex_t rx;
65 int rc = regcomp(&rx, pattern.s ? pattern.s : "", REG_EXTENDED);
66 if (rc != 0) {
67 /* invalid regex -> empty result */
69 (void)map_set(&m, "match", make_string(""));
70 (void)map_set(&m, "start", make_int(-1));
71 (void)map_set(&m, "end", make_int(-1));
73 (void)map_set(&m, "groups", emptyArr);
76 push_value(vm, m);
77 break;
78 }
79 /* capture up to, say, 10 groups (including whole match) */
80 enum { MAX_CAP = 16 };
81 regmatch_t caps[MAX_CAP];
82 int ok = regexec(&rx, str.s ? str.s : "", MAX_CAP, caps, 0) == 0;
83 Value outMap = make_map_empty();
84 if (!ok) {
85 (void)map_set(&outMap, "match", make_string(""));
86 (void)map_set(&outMap, "start", make_int(-1));
87 (void)map_set(&outMap, "end", make_int(-1));
89 (void)map_set(&outMap, "groups", emptyArr);
90 } else {
91 int s = (int)caps[0].rm_so;
92 int e = (int)caps[0].rm_eo;
93 char *matchStr = NULL;
94 if (str.s && s >= 0 && e >= s) {
95 int len = e - s;
96 matchStr = (char *)malloc((size_t)len + 1);
97 if (matchStr) {
98 memcpy(matchStr, str.s + s, (size_t)len);
99 matchStr[len] = '\0';
100 }
101 }
102 (void)map_set(&outMap, "match", make_string(matchStr ? matchStr : ""));
103 if (matchStr) free(matchStr);
104 (void)map_set(&outMap, "start", make_int(s));
105 (void)map_set(&outMap, "end", make_int(e));
106 /* groups 1..n */
107 Value groupsArr = make_array_from_values(NULL, 0);
108 /* Count groups available */
109 int groupCount = 0;
110 for (int i = 1; i < MAX_CAP; ++i) {
111 if (caps[i].rm_so == -1 || caps[i].rm_eo == -1) break;
112 groupCount++;
113 }
114 if (groupCount > 0) {
115 Value *vals = (Value *)calloc((size_t)groupCount, sizeof(Value));
116 int vi = 0;
117 for (int i = 1; i <= groupCount; ++i) {
118 int gs = (int)caps[i].rm_so;
119 int ge = (int)caps[i].rm_eo;
120 char *gstr = NULL;
121 if (str.s && gs >= 0 && ge >= gs) {
122 int gl = ge - gs;
123 gstr = (char *)malloc((size_t)gl + 1);
124 if (gstr) {
125 memcpy(gstr, str.s + gs, (size_t)gl);
126 gstr[gl] = '\0';
127 }
128 }
129 vals[vi++] = make_string(gstr ? gstr : "");
130 if (gstr) free(gstr);
131 }
132 groupsArr = make_array_from_values(vals, groupCount);
133 for (int i = 0; i < groupCount; ++i)
134 free_value(vals[i]);
135 free(vals);
136 }
137 (void)map_set(&outMap, "groups", groupsArr);
138 }
139 regfree(&rx);
142 push_value(vm, outMap);
143 break;
144#endif
145}
@ OP_REGEX_SEARCH
Definition bytecode.h:108
int ok
Definition contains.c:38
int rc
Value m
Definition has_key.c:27
size_t len
Definition input_line.c:102
Value * vals
Definition make_array.c:39
free(vals)
int map_set(Value *vm, const char *key, Value v)
Insert or replace a key in the map.
Definition map.c:79
Value make_map_empty(void)
Construct a new empty map Value.
Definition map.c:35
Value str
Definition regex_match.c:41
Value pattern
free_value(pattern)
Value emptyArr
push_value(vm, m)
uint32_t s
Definition rol.c:31
int64_t vi
Definition sclamp.c:31
Tagged union representing a Fun value.
Definition value.h:68
Value make_string(const char *s)
Construct a string Value by duplicating the given C string.
Definition value.c:95
Value make_int(int64_t v)
Construct a Value representing a 64-bit integer.
Definition value.c:51
Value make_array_from_values(const Value *vals, int count)
Create an array Value by copying items from an input span.
Definition value.c:142
@ VAL_STRING
Definition value.h:53
#define fprintf
Definition vm.c:200
#define exit(code)
Definition vm.c:230