I'm trying to call a Lua function from C. The Lua function creates a table and then iterates through it. It works as expected when called from Lua, but not when I call it from a C program. Is there any reason why I can't do what I'm trying here?
test.lua:
function f()
t = {["a"] = "aaa", ["b"] = "bbb", ["c"] = "ccc"}
for z, v in t do
print(t .. " " .. v)
end
end
test.c:
#include <string.h>
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main(void)
{
char read_buffer[1024];
lua_State *L = lua_open();
luaL_openlibs(L);
if (luaL_loadfile(L, "test.lua") || lua_pcall(L, 0, 0, 0))
fprintf(stderr, "Error loading test.lua");
lua_getglobal(L, "f");
if(lua_pcall(L, 0, 0, 0) != 0)
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
strncpy(read_buffer, lua_tostring(L, -1), sizeof(read_buffer));
lua_pop(L, 1);
printf("got from lua: %s\n", read_buffer);
lua_close(L);
return 0;
}
Thanks!
I'm noticing a couple of issues above that's causing problems.
Over here:
function f()
t = {["a"] = "aaa", ["b"] = "bbb", ["c"] = "ccc"}
for z, v in t do
print(t .. " " .. v)
end
end
You can't use a lua table in the for in loop like that unless you make t callable in someway (eg. using __call for instance). More likely you're probably just trying to iterate through it, in which case you would use pairs:
for z, v in pairs(t) do
-- etc.
The other error is that you're trying to concat strings onto the table. Not sure what you were intending here. Perhaps you wanted to print the table address? You can use tostring for that.
The second issue I notice is in your C code:
if(lua_pcall(L, 0, 0, 0) != 0)
So you're not expecting f to return anything unless there's an error. But right after that you try to convert the top item into a string:
strncpy(read_buffer, lua_tostring(L, -1), sizeof(read_buffer));
lua_pop(L, 1);
printf("got from lua: %s\n", read_buffer);
which doesn't make a whole lot of sense -- there may not be anything on the stack at this point. This is clearly a logic error in your code. If this is suppose to be a part of the error handling you should enclose it in braces so it's properly scoped:
if(lua_pcall(L, 0, 0, 0) != 0)
{
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
strncpy(read_buffer, lua_tostring(L, -1), sizeof(read_buffer));
lua_pop(L, 1);
printf("got from lua: %s\n", read_buffer);
}
Related
I have the following character pointer
char message[100] = "START_MESSAGE hello world \r\n\r\n";
I am trying to use regex.h to parse the above message. I want to get anything between START_MESSAGE and \r\n\r\n
So, I tried the following code (by following answer of THIS SO post)
#include <stdio.h>
#include <regex.h>
#include <stdlib.h>
int main() {
regex_t regex;
int reti;
char msgbuf[100];
reti = regcomp(®ex, "START_MESSAGE*\r\n\r\n", 0);
reti = regexec(®ex, "START_MESSAGE hello world\r\n\r\n", 0, NULL, 0);
if (!reti) {
puts("Match");
} else
if (reti == REG_NOMATCH) {
puts("No match");
} else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(®ex);
return 0;
}
But, I get no match. I thought, maybe its because of the escape sequence. So, I put \\r\\n\\r\\n and still get no match. I looked for raw string literal (like r before the string in python). But, I get
error: stray ‘R’ in program
I tried removing \r\n\r\n and looked for only START_MESSAGE pattern, I get a match. How can I get \r\n\r\n to be matched or get the text between START_MESSAGE and \r\n\r\n.
I'd like to find a way to make a function return (with a specific value) the function that called it. Is it possible in C? Maybe by checking the call stack?
Abstract example: suppose we have two functions
int called() {
if (some_check_fails()) {
/* here make caller() return -1 so "Hello world!\n" is not printed */
}
}
int caller() {
called();
printf("Hello world!\n");
return 0;
}
I'm searching for something to put in the /* ... */ part.
Real-life example: the code I'm working one is a function that exports data in a SQLite file. This means a lot of calls to the SQLite API that need their return values checked each time. The result is an awfully looking and far too long function like this where the if (resp_code != SQLITE_OK) part repeats on and on:
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: cannot open database %s, %s\n", filename,
sqlite3_errmsg(db));
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Create table */
char *query_table = "DROP TABLE IF EXISTS sometable; "
"CREATE TABLE sometable "
"(value int, data TEXT);";
resp_code = sqlite3_exec(db, query_table, 0, 0, &err_msg);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Prepare statement */
char *query = "INSERT INTO sometable VALUES (#i, #s);";
sqlite3_stmt *stmt;
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Start transaction */
resp_code = sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, &err_msg);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* AND SO ON */
What I'd like is something like:
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL);
return_this_function_if_not_ok(resp_code);
/* Create table */
char *query_table = "DROP TABLE IF EXISTS sometable; "
"CREATE TABLE sometable "
"(value int, data TEXT);";
resp_code = sqlite3_exec(db, query_table, 0, 0, &err_msg);
return_this_function_if_not_ok(resp_code);
/* Prepare statement */
char *query = "INSERT INTO sometable VALUES (#i, #s);";
sqlite3_stmt *stmt;
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
return_this_function_if_not_ok(resp_code);
/* Start transaction */
resp_code = sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, &err_msg);
return_this_function_if_not_ok(resp_code);
/* AND SO ON */
EDIT 2015-12-21: I chose FUZxxl's answer as best because it's the only one actually answering my question about returning the caller function. On the other hand chux's answer (based on Rowland Shaw's and Ziffusion's) is solving my SQLite problem the way I prefer.
Big big big thanks to all of you!!
Such a thing is not possible in C, but you can get close.
The identifier __func__ is implicitly declared at the beginning of each function as
static const char __func__[];
It's value is the name of the current function as a string. You can write a function-like macro that implicitly passes the name of the caller to the callee. If the function that should receive the name of the caller is something like:
void error_check_fun(const char *function, int code, int result);
you can write a macro like this:
#define error_check(code, result) error_check_fun(__func__, code, result);
Similarly, __FILE__ and __LINE__ are macros that expand to the current source file and line respectively.
You can try something like this.
#define return_this_function_if_not_ok(db, sql_code, sql_msg, code) \
if ((sql_code) != SQLITE_OK) { \
fprintf(stderr, "SQLite error: %s\n", (*sql_msg)); \
sqlite3_free(sql_msg); \
sqlite3_close(db); \
return (code); \
}
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
&err_msg);
return_this_function_if_not_ok(db, resp_code, err_msg, OMG_ERROR_HERE);
Recommend something like Rowland Shaw and #Ziffusion
Call a function that packs in the data and handles common house-keeping.
int foo(char *err_msg, int code) {
if (msg) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
} else {
fprintf(stderr, "SQLite error: %s\n", "Default error message");
}
sqlite3_close(db);
return code;
}
resp_code = sqlite3_exec(...);
if (resp_code != SQLITE_OK) return foo(err_msg, OMG_ERROR_HERE);
...
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
if (resp_code != SQLITE_OK) return foo(NULL, OMG_ERROR_HERE);
Suggest further, include file and line number. This is something I found very useful.
int bar(char *err_msg, int code, const char *file, int line) {
fprintf(stderr, "SQLite error:%s, Code:%d, File:%s, Line%d\n",
err_msg ? err_msg : "Default error message", code, file, line);
}
sqlite3_free(err_msg);
sqlite3_close(db);
return code;
}
#define foo(err_msg, code, file, line) bar((err_msg), (code), __FILE__, __LINE__)
You can use setjmp()/longjmp() to get this effect, although not exactly like how you are wanting:
#include <setjmp.h>
#include <stdio.h>
int check_result;
int some_check_fails() {
return check_result;
}
int called(jmp_buf buf) {
if (some_check_fails()) {
longjmp(buf,1);
}
}
int caller() {
jmp_buf buf;
if (setjmp(buf)==0) {
called(buf);
printf("Hello world!\n");
return 0;
}
else {
printf("Failure\n");
return -1;
}
}
int main() {
check_result = 0;
caller();
check_result = 1;
caller();
}
Output:
Hello world!
Failure
This technique does avoid putting checks in multiple places, effectively implementing a type of exception handling mechanism. However, there are other ways to clean up the code without resorting to this.
I have different metatables in my project. But if I create a value A and assign the metatable "X" and creates a second value B and attach metatable "Y", A gets the Y metatable, too! Here is a simplified C function for demonstration:
#include <errno.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
// shoudl create t["obj"] = <userdata> with metatable = "Obj" but gets "OtherType"
int create_table_with_object(lua_State *L)
{
lua_newtable(L);
lua_pushlightuserdata(L, (void*)0x1234);
luaL_setmetatable(L, "Obj"); // This Type is already registered with lua_newmetatable()
lua_setfield(L, -2, "obj");
luaL_newmetatable(L, "OtherType");
lua_pushinteger(L, 70);
lua_setfield(L, -2, "ICameFromOtherType");
lua_pop(L, 1); // just a dummy table
// If we create another userdata object, the first one
// gets the same type as this one!
// Obj -> changes to "OtherType"
// ### CRITICAL SECTION STRT ###
lua_pushlightuserdata(L, (void*)0x5555);
luaL_setmetatable(L, "OtherType");
lua_setglobal(L, "JustADummyObj"); // this removes the value from the stack!
// ### CRITICAL SECTION END ###
return 1;
}
int main(void)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_loadfile(L, "bug.lua");
lua_pushcfunction(L, create_table_with_object);
lua_setglobal(L, "create_table_with_object");
luaL_newmetatable(L, "Obj");
lua_pop(L, 1);
int error;
if(error = lua_pcall(L, 0, 0, 0))
{
fprintf(stderr, "Fatal error: \n");
fprintf(stderr, "%s\n", lua_tostring(L, -1));
return 1;
}
lua_close(L);
return 0;
}
Lua Code:
local a = create_table_with_object()
print(getmetatable(a.obj).__name)
The output is "OtherType" but it should be "Obj". It seems that the second call to lua_setmetatable() overrides the table from other values?!
Ok, solved!
lightuserdata in Lua shares one metatable (instead of one metatable per value). So changing the table for a lightuserdata value changes all other lightuserdata values!
below is the lua table i need to read from C:
listen = {
{ port = 1234, address = "192.168.1.1", userdata = "liunx" },
{ port = 1235, address = "192.168.1.2", userdata = "liunx1" },
{ port = 1236, address = "192.168.1.3", userdata = "liunx2" }
}
below is the c code:
#include <lua.h> /* Always include this when calling Lua */
#include <lauxlib.h> /* Always include this when calling Lua */
#include <lualib.h> /* Prototype for luaL_openlibs(), */
/* always include this when calling Lua */
#include <stdlib.h> /* For function exit() */
#include <stdio.h> /* For input/output */
void bail(lua_State *L, char *msg){
fprintf(stderr, "\nFATAL ERROR:\n %s: %s\n\n",
msg, lua_tostring(L, -1));
exit(1);
}
int main(void)
{
lua_State *L;
L = luaL_newstate(); /* Create Lua state variable */
luaL_openlibs(L); /* Load Lua libraries */
if (luaL_loadfile(L, "cfg.lua"))
bail(L, "luaL_loadfile() failed");
if (lua_pcall(L, 0, 0, 0))
bail(L, "lua_pcall() failed");
// how to read???
lua_getglobal(L, "listen");
lua_close(L);
return 0;
}
I want to travel this table which may contain a few number of data in while loop, but really do not know how to do it, so any tips?
Thanks very much for your tips!Below are the worked code:
#include <lua.h> /* Always include this when calling Lua */
#include <lauxlib.h> /* Always include this when calling Lua */
#include <lualib.h> /* Prototype for luaL_openlibs(), */
/* always include this when calling Lua */
#include <stdlib.h> /* For function exit() */
#include <stdio.h> /* For input/output */
void bail(lua_State *L, char *msg)
{
fprintf(stderr, "\nFATAL ERROR:\n %s: %s\n\n",
msg, lua_tostring(L, -1));
exit(1);
}
int main(void)
{
lua_State *L;
static struct {
const char * name;
int type;
} fields[] = {
{"port", LUA_TNUMBER},
{"address", LUA_TSTRING},
{"userdata", LUA_TSTRING},
{NULL, 0}
};
L = luaL_newstate(); /* Create Lua state variable */
luaL_openlibs(L); /* Load Lua libraries */
if (luaL_loadfile(L, "cfg.lua"))
bail(L, "luaL_loadfile() failed");
if (lua_pcall(L, 0, 0, 0))
bail(L, "lua_pcall() failed");
lua_getglobal(L, "listen");
luaL_checktype(L, -1, LUA_TTABLE);
int i;
for (i = 1; ; i++) {
lua_rawgeti(L, -1, i);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
break;
}
// an element of the 'listen' table should now be at the top of the stack
luaL_checktype(L, -1, LUA_TTABLE);
// read the content of that element
int field_index;
for (field_index = 0; (fields[field_index].name != NULL
&& fields[field_index].name != NULL); field_index++) {
lua_getfield(L, -1, fields[field_index].name);
luaL_checktype(L, -1, fields[field_index].type);
// you should probably use a function pointer in the fields table.
// I am using a simple switch/case here
switch(field_index) {
case 0:
printf("port: %d\n", (int)lua_tonumber(L, -1));
// do what you want with port
break;
case 1:
printf("address: %s\n", lua_tostring(L, -1));
break;
case 2:
// handle userdata
printf("userdata: %s\n", lua_tostring(L, -1));
break;
}
// remove the field value from the top of the stack
lua_pop(L, 1);
}
// remove the element of the 'listen' table from the top of the stack.
lua_pop(L, 1);
}
lua_close(L);
return 0;
}
You are not too far. The key here is to understand how the Lua API use the stack for everything.
Here is an untested code sample which should get you going:
// this will be used to validate our table
static struct {
const char * name;
int type;
} fields[] = {
{"port", LUA_TNUMBER},
{"address", LUA_TSTRING},
{"userdata", LUA_TSTRING},
NULL
};
lua_getglobal(L, "listen");
// the 'listen' table should be at the top of the stack
luaL_checktype(L, -1, LUA_TTABLE);
// iterate the listen table
int i;
for (i = 1; ; i++) {
lua_rawgeti(L, -1, i);
// when you get nil, you're done
if (lua_isnil(L, -1)) {
lua_pop(L,1);
break;
}
// an element of the 'listen' table should now be at the top of the stack
luaL_checktype(L, -1, LUA_TTABLE);
// read the content of that element
int field_index;
for (field_index = 0; fields[field_index] != NULL; field_index++) {
lua_getfield(L, -1, fields[field_index].name);
luaL_checktype(L, -1, fields[field_index].type);
// you should probably use a function pointer in the fields table.
// I am using a simple switch/case here
switch(field_index) {
case 0:
port = lua_tonumber(L, -1);
// do what you want with port
break;
case 1:
address = lua_tostring(L, -1);
break;
case 2:
// handle userdata
break;
}
// remove the field value from the top of the stack
lua_pop(L, 1);
}
// remove the element of the 'listen' table from the top of the stack.
lua_pop(L, 1);
}
I suggest you use those documentations: Lua API table Lua API ref
I'm after some simple examples and best practices of how to use regular expressions in ANSI C. man regex.h does not provide that much help.
Regular expressions actually aren't part of ANSI C. It sounds like you might be talking about the POSIX regular expression library, which comes with most (all?) *nixes. Here's an example of using POSIX regexes in C (based on this):
#include <regex.h>
regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(®ex, "^a[[:alnum:]]", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, "abc", 0, NULL, 0);
if (!reti) {
puts("Match");
}
else if (reti == REG_NOMATCH) {
puts("No match");
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(®ex);
Alternatively, you may want to check out PCRE, a library for Perl-compatible regular expressions in C. The Perl syntax is pretty much that same syntax used in Java, Python, and a number of other languages. The POSIX syntax is the syntax used by grep, sed, vi, etc.
This is an example of using REG_EXTENDED.
This regular expression
"^(-)?([0-9]+)((,|.)([0-9]+))?\n$"
Allows you to catch decimal numbers in Spanish system and international. :)
#include <regex.h>
#include <stdlib.h>
#include <stdio.h>
regex_t regex;
int reti;
char msgbuf[100];
int main(int argc, char const *argv[])
{
while(1){
fgets( msgbuf, 100, stdin );
reti = regcomp(®ex, "^(-)?([0-9]+)((,|.)([0-9]+))?\n$", REG_EXTENDED);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
printf("%s\n", msgbuf);
reti = regexec(®ex, msgbuf, 0, NULL, 0);
if (!reti) {
puts("Match");
}
else if (reti == REG_NOMATCH) {
puts("No match");
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(®ex);
}
}
It's probably not what you want, but a tool like re2c can compile POSIX(-ish) regular expressions to ANSI C. It's written as a replacement for lex, but this approach allows you to sacrifice flexibility and legibility for the last bit of speed, if you really need it.
man regex.h doesn't show any manual entry for regex.h, but man 3 regex shows a page explaining the POSIX functions for pattern matching.
The same functions are described in The GNU C Library: Regular Expression Matching, which explains that the GNU C Library supports both the POSIX.2 interface and the interface the GNU C Library has had for many years.
For example, for an hypothetical program that prints which of the strings passed as argument matches the pattern passed as first argument, you could use code similar to the following one.
#include <errno.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_regerror (int errcode, size_t length, regex_t *compiled);
int
main (int argc, char *argv[])
{
regex_t regex;
int result;
if (argc < 3)
{
// The number of passed arguments is lower than the number of
// expected arguments.
fputs ("Missing command line arguments\n", stderr);
return EXIT_FAILURE;
}
result = regcomp (®ex, argv[1], REG_EXTENDED);
if (result)
{
// Any value different from 0 means it was not possible to
// compile the regular expression, either for memory problems
// or problems with the regular expression syntax.
if (result == REG_ESPACE)
fprintf (stderr, "%s\n", strerror(ENOMEM));
else
fputs ("Syntax error in the regular expression passed as first argument\n", stderr);
return EXIT_FAILURE;
}
for (int i = 2; i < argc; i++)
{
result = regexec (®ex, argv[i], 0, NULL, 0);
if (!result)
{
printf ("'%s' matches the regular expression\n", argv[i]);
}
else if (result == REG_NOMATCH)
{
printf ("'%s' doesn't the regular expression\n", argv[i]);
}
else
{
// The function returned an error; print the string
// describing it.
// Get the size of the buffer required for the error message.
size_t length = regerror (result, ®ex, NULL, 0);
print_regerror (result, length, ®ex);
return EXIT_FAILURE;
}
}
/* Free the memory allocated from regcomp(). */
regfree (®ex);
return EXIT_SUCCESS;
}
void
print_regerror (int errcode, size_t length, regex_t *compiled)
{
char buffer[length];
(void) regerror (errcode, compiled, buffer, length);
fprintf(stderr, "Regex match failed: %s\n", buffer);
}
The last argument of regcomp() needs to be at least REG_EXTENDED, or the functions will use basic regular expressions, which means that (for example) you would need to use a\{3\} instead of a{3} used from extended regular expressions, which is probably what you expect to use.
POSIX.2 has also another function for wildcard matching: fnmatch(). It doesn't allow to compile the regular expression, or get the substrings matching a sub-expression, but it is very specific for checking when a filename match a wildcard (e.g. it uses the FNM_PATHNAME flag).
While the answer above is good, I recommend using PCRE2. This means you can literally use all the regex examples out there now and not have to translate from some ancient regex.
I made an answer for this already, but I think it can help here too..
Regex In C To Search For Credit Card Numbers
// YOU MUST SPECIFY THE UNIT WIDTH BEFORE THE INCLUDE OF THE pcre.h
#define PCRE2_CODE_UNIT_WIDTH 8
#include <stdio.h>
#include <string.h>
#include <pcre2.h>
#include <stdbool.h>
int main(){
bool Debug = true;
bool Found = false;
pcre2_code *re;
PCRE2_SPTR pattern;
PCRE2_SPTR subject;
int errornumber;
int i;
int rc;
PCRE2_SIZE erroroffset;
PCRE2_SIZE *ovector;
size_t subject_length;
pcre2_match_data *match_data;
char * RegexStr = "(?:\\D|^)(5[1-5][0-9]{2}(?:\\ |\\-|)[0-9]{4}(?:\\ |\\-|)[0-9]{4}(?:\\ |\\-|)[0-9]{4})(?:\\D|$)";
char * source = "5111 2222 3333 4444";
pattern = (PCRE2_SPTR)RegexStr;// <<<<< This is where you pass your REGEX
subject = (PCRE2_SPTR)source;// <<<<< This is where you pass your bufer that will be checked.
subject_length = strlen((char *)subject);
re = pcre2_compile(
pattern, /* the pattern */
PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
0, /* default options */
&errornumber, /* for error number */
&erroroffset, /* for error offset */
NULL); /* use default compile context */
/* Compilation failed: print the error message and exit. */
if (re == NULL)
{
PCRE2_UCHAR buffer[256];
pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset,buffer);
return 1;
}
match_data = pcre2_match_data_create_from_pattern(re, NULL);
rc = pcre2_match(
re,
subject, /* the subject string */
subject_length, /* the length of the subject */
0, /* start at offset 0 in the subject */
0, /* default options */
match_data, /* block for storing the result */
NULL);
if (rc < 0)
{
switch(rc)
{
case PCRE2_ERROR_NOMATCH: //printf("No match\n"); //
pcre2_match_data_free(match_data);
pcre2_code_free(re);
Found = 0;
return Found;
// break;
/*
Handle other special cases if you like
*/
default: printf("Matching error %d\n", rc); //break;
}
pcre2_match_data_free(match_data); /* Release memory used for the match */
pcre2_code_free(re);
Found = 0; /* data and the compiled pattern. */
return Found;
}
if (Debug){
ovector = pcre2_get_ovector_pointer(match_data);
printf("Match succeeded at offset %d\n", (int)ovector[0]);
if (rc == 0)
printf("ovector was not big enough for all the captured substrings\n");
if (ovector[0] > ovector[1])
{
printf("\\K was used in an assertion to set the match start after its end.\n"
"From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),
(char *)(subject + ovector[1]));
printf("Run abandoned\n");
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return 0;
}
for (i = 0; i < rc; i++)
{
PCRE2_SPTR substring_start = subject + ovector[2*i];
size_t substring_length = ovector[2*i+1] - ovector[2*i];
printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);
}
}
else{
if(rc > 0){
Found = true;
}
}
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return Found;
}
Install PCRE using:
wget https://ftp.pcre.org/pub/pcre/pcre2-10.31.zip
make
sudo make install
sudo ldconfig
Compile using :
gcc foo.c -lpcre2-8 -o foo
Check my answer for more details.