Access Lua coroutine from C - lua

I have implemented a co-routine system. When I press ENTER to clear the first textbox, it calls contscript() which in turn calls lua_resume() but it doesn't continue the co-routine.
So what do I pass to lua_resume() to make the co-routine continue?
static lua_State *lua;
static int luapanic(lua_State *L)
{
allegro_exit();
const char *err = lua_tostring(L, -1);
DEBUGF("lua panic: %s\n", err);
printf("lua panic: %s\n", err);
return 0;
}
static int textbox(lua_State *L)
{
const char *str = luaL_checkstring(L, 1);
message(str);
return 1;
}
void contscript(void)
{
lua_resume(lua,NULL,0);
}
static int transfer_player(lua_State *L)
{
int x, y;
SpriteObj *p;
x = luaL_checkint(L, 1);
y = luaL_checkint(L, 2);
p = findobject(0);
setposition(p,x,y);
scrollToAndCentre(x,y);
return 1;
}
bool initscript(void)
{
lua = luaL_newstate();
lua_atpanic(lua, luapanic);
luaL_openlibs(lua);
lua_register(lua, "textbox", textbox);
lua_register(lua, "transfer_player", transfer_player);
return true;
}
Here is the script in question:
local co = coroutine.wrap(
function()
textbox("Dear me! I never knew birds could sing so\nbeautifully!")
coroutine.yield()
textbox("Text message #2")
end
)
co()

Related

Lua mount filesystem

I want to mount a filesystem on Linux using Lua, but I haven't found any capability in the lua 5.4 manual or the LuaFileSytem library. Is there some way to mount a filesystem in Lua or with an existing library?
Like most platform-dependent syscall, Lua won't provide such mapping out of the box.
So you'll need some C-API module that does the trick.
Looks like https://github.com/justincormack/ljsyscall is generic "but" focused on LuaJIT and https://luaposix.github.io/luaposix/ doesn't provide mount.
I recently had similar needs, and I ended doing the C module:
static int l_mount(lua_State* L)
{
int res = 0;
// TODO add more checks on args!
const char *source = luaL_checkstring(L, 1);
const char *target = luaL_checkstring(L, 2);
const char *type = luaL_checkstring(L, 3);
lua_Integer flags = luaL_checkinteger(L, 4);
const char *data = luaL_checkstring(L, 5);
res = mount(source, target, type, flags, data);
if ( res != 0)
{
int err = errno;
lua_pushnil(L);
lua_pushfstring(L, "mount failed: errno[%s]", strerror(err));
return 2;
}
else
{
lua_pushfstring(L, "ok");
return 1;
}
}
#define register_constant(s)\
lua_pushinteger(L, s);\
lua_setfield(L, -2, #s);
// Module functions
static const luaL_Reg R[] =
{
{ "mount", l_mount },
{ NULL, NULL }
};
int luaopen_sysutils(lua_State* L)
{
luaL_newlib(L, R);
// do more mount defines mapping, maybe in some table.
register_constant(MS_RDONLY);
//...
return 1;
}
Compile this as a C Lua module, and don't forget that you need CAP_SYS_ADMIN to call mount syscall.

insert in simple linked list doesn't get last line

I am trying to insert into a simply linked list from a file. Do you
guys have any idea why the function doesn't insert the last line in my
file?
This is the file:
10,Ghidul Ciberbobocului,Stan Daria,3,Popescu Matei,Ionescu Gigel,Ilinca Radu,100.5
2,Spring IT,Mirodene Cristina,4,Dumitru Mihai,Vasiliu Valentin,Balasa Silvia,Dumitru Ion,400.
89,Serile teatrului studentesc,Petre Ion,2,Nicolae Ramona,Stan Alberto,1000
1,Tutoring,Petre Miruna,2,Bode Cristina,Angelescu Paul,500.5
11,IT Fest,Ciurea Ion,2,Ionescu Georgiana,Neagu Bianca,100.6
My code:
struct Proiect {
int id;
char* numeProiect;
char* numeCoordonator;
unsigned int nrStudenti;
char** studenti;
float costInscriere;
};
struct nodLista {
Proiect proiect;
nodLista *next;
};
nodLista* inserareNod(nodLista *first, Proiect p) {
nodLista* newNode = new nodLista;
newNode->next = NULL;
newNode->proiect = p;
if (!first) {
return newNode;
}
nodLista* aux = first;
while (aux->next) {
aux = aux->next;
}
aux->next = newNode;
printf("%d\n", aux->proiect.id);
return first;
}
void main() {
nodLista* first = NULL;
Proiect proiect;
FILE *f = fopen("proiecte2.txt", "r");
char line[150];
int nrProiecte = 0;
if (f) {
while (fgets(line, sizeof(line), f)) {
nrProiecte++;
}
printf("Nr proiecte: %d",nrProiecte);
fclose(f);
}
else {
printf("Fisierul nu a fost gasit");
}
f = fopen("proiecte2.txt", "r");
char *token[150], sep_list[] = ",";
Proiect* listaProiecte;
listaProiecte = (Proiect*)malloc(nrProiecte * sizeof(Proiect));
int i = 0;
if (f) {
while(fgets(line, sizeof(line), f)) {
token[0] = strtok(line, sep_list);
listaProiecte[i].id = atoi(token[0]);
first = inserareNod(first, listaProiecte[i]);
i++;
}
}
else printf("Fisierul nu aputut fi deschis");
}
Output: It only displays 10 , 2, 89 and 1.
Did you make prints inside this function to check if it's doing the while correctly?
while(fgets(line, sizeof(line), f)) {
token[0] = strtok(line, sep_list);
listaProiecte[i].id = atoi(token[0]);
first = inserareNod(first, listaProiecte[i]);
i++;
}

Linked list exercise in C, what is wrong?

The code below does compile, but it doesn't run as it should.
I'm not sure what am I doing wrong, so would someone be willing to tell me what I did wrong and what I should have done better.
What do I need to change to make it run properly?
#include<stdio.h>
#include<stdlib.h>
typedef struct sub_Node
{
int value;
struct sub_Node *next;
}sub_Node;
typedef struct Node
{
char *name;
struct Node *next;
struct sub_Node *sub_start;
}Node;
Node *start;
void add_player(char *name)
{
Node *temp;
temp = (Node *)malloc(sizeof(Node));
temp->next = start;
temp->name = name;
temp->sub_start = (sub_Node *)malloc(sizeof(sub_Node));
temp->sub_start->next = NULL;
temp->sub_start->value = -1;
start = temp;
}
void initialize()
{
char *p;
p = "\0";
add_player(p);
}
void remove_player(char *name)
{
Node *p;
for(p = start; p!= NULL; p = p->next)
if(p->name == name)
{
p->name = p->next->name;
p->next = p->next->next;
}
}
sub_Node* add_descending(sub_Node* sub_start, int piece_value)
{
sub_Node *temp, *prev, *next;
temp = (sub_Node *)malloc(sizeof(sub_Node));
temp->value = piece_value;
temp->next = NULL;
prev = NULL;
next = sub_start;
while(next && next->value >= piece_value)
{
prev = next;
next = next->next;
}
if(!next)
{
prev->next = temp;
}
else
{
if(prev)
{
temp->next = prev->next;
prev->next = temp;
}
else
{
temp->next = sub_start;
sub_start = temp;
}
}
return sub_start;
}
void add_piece(char *name, int piece_value)
{
Node *p;
int c;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
p->sub_start = add_descending(p->sub_start, piece_value);
}
void print_pieces(char *name)
{
Node *p;
sub_Node *q;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
{
printf("The values of the owned pieces are:");
for(q = p->sub_start; q->value != -1; q = q->next)
printf(" %d", q->value);
}
}
int lose_piece(char *name)
{
Node *p;
sub_Node *q;
int aux;
for(p = start; p!=NULL; p = p->next)
if(p->name == name)
{
for(q = p->sub_start; q->next->value != -1; q = q->next) {}
aux = q->value;
q->value = q->next->value;
q->next = q->next->next;
return aux;
}
}
void print_players()
{
Node *p;
printf("The players are: ");
for(p = start; p->name != "\0"; p = p->next)
printf("%s ", p->name);
printf("\n");
}
int main()
{
initialize();
int y, value;
char name[20];
printf("Insert a digit to execute the desired task:\n"
"<0> end the program\n"
"<1> add a player, who doesn't own any piece yet\n"
"<2> remove a player and all his pieces\n"
"<3> print the name of all the players\n"
"<4> a player gets a piece\n"
"<5> a player loses the piece with the lowest value out of the ones that he has\n"
"<6> prints the pieces of a player in a descending order by value\n\n");
do
{
printf("digit: ");
scanf("%d", &y);
switch(y)
{
case 1:
printf("Insert the player's name: ");
scanf("%s", name);
add_player(name);
break;
case 2:
printf("Insert the player's name: ");
scanf("%s", name);
remove_player(name);
break;
case 3:
print_players();
break;
case 4:
printf("Insert the player's name: ");
scanf("%s", name);
printf("Insert the value of the piece: ");
scanf("%d", value);
add_piece(name, value);
break;
case 5:
printf("Insert the player's name: ");
scanf("%s", name);
printf("\nThe player loses the piece: %d\n", lose_piece(name));
break;
case 6:
printf("Insert the player's name: ");
scanf("%s", name);
print_pieces(name);
}
} while(y != 0);
return 0;
}
your two main problems where this scanf("%d", value); value should be passed by reference like this scanf("%d", &value); and the second is string comparison in c as in your code p->name != "\0" and if(p->name == name) this is wrong because actually you are making comparison between addresses of strings (where it resides in memory) not strings values. to compare strings in c you have to use strcmp and families.
Actually 3 main problems. for setting string values as you did in temp->name = name; is little bit more complicated than that. because you are assigning to temp->name a string from the stack that is volatile (the stack will be more likely invalid soon you return from the function) . in your case you have to alloc a new string by using malloc (and friends) or just by using strdup.
here is as a bonus a slightly rewrite of your program, you will find many advises and is a good starting point for how to structure your code for an easy maintenance.
still want to advise you to change members and variables to more declarative names as in sub_start and sub_Node can be PieceNode and pieces respectively.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct sub_Node
{
int value;
struct sub_Node *next;
}sub_Node;
typedef struct Node
{
char *name;
struct Node *next;
struct Node *prev; // this to make life easyer
struct sub_Node *sub_start;
}Node;
Node *start = NULL;
Node *find_player(char *name){
Node *tmp = start;
while( tmp ){
if(strcmp(tmp->name,name) == 0 )
break;
tmp = tmp->next;
}
return tmp;
}
// int to return Error Code
//
int add_player(char *name)
{
Node *temp;
if( find_player(name)) {
printf("player %s already exists\n", name);
return 1;
}
// do not cast malloc
temp = malloc(sizeof(Node));
if( !temp ){
printf ("not enough memory\n");
return 2;
}
temp->name = strdup ( name); // here was your error
temp->sub_start = NULL; // keep it simple
temp->prev = NULL;
temp->next = start;
if(start)
start->prev = temp;
start = temp;
return 0; // no error
}
void DestroyPieces(sub_Node* piece){
if( piece ) {
DestroyPieces( piece->next );
free( piece );
}
}
// as usual use int to return error code
int remove_player(char *name)
{
Node *player = find_player(name);
if ( !player ){
return 1; // player not found
}
if ( player->next ){
player->next->prev = player->prev;
}
if ( player->prev ){
player->prev->next = player->next;
}
DestroyPieces(player->sub_start);
free(player->name);
free(player);
return 0; // success
}
sub_Node* new_piece(int value){
sub_Node *temp = malloc( sizeof(sub_Node) );
if(temp){
temp->value = value;
temp->next = NULL;
}
return temp;
}
// int to return error code
// pass sub_start as pointer to pointer, as it might be updated
int add_descending(sub_Node** psub_start, int piece_value)
{
sub_Node *piece, *current, *prev = NULL;
if( !psub_start){
return 5; // this should not happen
}
current = *psub_start;
piece = new_piece( piece_value );
if( !piece ) return 1; // no mem
if(!current){
// this is the first and only one
*psub_start = piece;
return 0; // OK
}
while(current && current->value >= piece_value)
{
prev = current;
current = current->next;
}
if( prev )
prev->next = piece;
piece->next = current;
if( current == *psub_start ){
*psub_start = piece;
}
return 0 ; // OK
}
void add_piece(Node * player, int piece_value)
{
if ( !player) {
return ;
}
if(add_descending (&(player->sub_start), piece_value) == 0 )
return ; //OK
printf("an error occured while adding a piece (%d) to player '%s'\n",piece_value,player->name);
}
void print_pieces(Node *player)
{
sub_Node *q;
if( !player ){
return;
}
if( !player->sub_start ){
printf("Player '%s' has no pieces\n",player->name);
return;
}
printf("The values of the owned pieces are:");
for(q = player->sub_start; q != NULL; q = q->next)
printf(" %d", q->value);
printf("\n");
}
void lose_piece(Node *player)
{
if( !player ){
return;
}
sub_Node *q, *prev = NULL;
int aux;
if( !player->sub_start ){
printf("Player '%s' has no pieces\n",player->name);
return;
}
// i think you want drop the last one
for(q = player->sub_start; q->next != NULL ;prev = q, q = q->next) {
;
}
if(prev)
prev->next = NULL;
else
player->sub_start = NULL;
aux = q->value;
free(q);
printf("\nThe player loses the piece: %d\n", aux);
return;
}
void print_players()
{
Node *p;
if( !start ){
printf("there are no players, try to add some\n");
return;
}
printf("The players are: ");
for(p = start; p != NULL; p = p->next)
printf("%s ", p->name);
printf("\n");
}
void print_menu(void){
printf("Insert a digit to execute the desired task:\n"
"<0> end the program\n"
"<1> add a player, who doesn't own any piece yet\n"
"<2> remove a player and all his pieces\n"
"<3> print the name of all the players\n"
"<4> a player gets a piece\n"
"<5> a player loses the piece with the lowest value out of the ones that he has\n"
"<6> prints the pieces of a player in a descending order by value\n\n");
}
Node * get_player(char *name){
Node *player = find_player(name);
if(!player)
printf("Player '%s' do not exists\n",name);
return player;
}
int main()
{
// initialize(); no more needed
int y, value;
char name[20];
Node *player;
print_menu();
do
{
printf("digit: ");
scanf("%d", &y);
switch(y)
{
case 1:
printf("Insert the player's name: ");
scanf("%s", name);
add_player(name);
break;
case 2:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
if( player )
break;
case 3:
print_players();
break;
case 4:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
if( player ){
printf("Insert the value of the piece: ");
scanf("%d", &value);
add_piece(player, value);
}
break;
case 5:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
lose_piece(player);
break;
case 6:
printf("Insert the player's name: ");
scanf("%s", name);
player = get_player(name);
print_pieces(player);
}
} while(y != 0);
return 0;
}

Memory Leak in C and C++ Code

I am trying to return a pointer from a function and use the return in a different function but I am getting memory leak.
The test code which I wrote and detected with memory leak by CPPCheck.
########################################################################
# include < stdio.h >
# include < malloc.h >
# include < string.h >
char* replace ( char* st, char* word, char *replaceWith );
int main ( void )
{
char str[] = "Hello how are ## and what are ## doing ?";
char word[]="##";
char replaceWith[]="you";
printf("%s",replace(str,word,replaceWith));
getchar();
return 0;
}
char* replace(char* st,char* word,char *replaceWith)
{
int i = 0;
char *sr,*s,*ret;
int oldlen;
int count = 0;
int newlen;
int stlen;
s=(char *)malloc(strlen(st) + 1);
strcpy(s, st);
oldlen=strlen(word);
newlen=strlen(replaceWith);
for (i = 0; s[i]! = '\0'; )
{
if( memcmp( &s[i], word, oldlen ) == 0)
{
count++;
i+=oldlen;
}
else
{
i++;
}
}
sr= (char *) malloc (i+1+count*(newlen-oldlen));
ret = (char *) malloc (i+1+count*(newlen-oldlen));
ret=sr;
while(*s)
{
if(memcmp( s, word, oldlen) == 0)
{
memcpy(sr, replaceWith, newlen);
s+ = oldlen;
sr+ = newlen;
}
else
{
*sr++ = *s++;
}
}
*sr = '\0';
return ret;
}
Try this
#include<stdio.h>
#include<malloc.h>
#include<string.h>
char* replace ( char* st, char* word, char *replaceWith );
int main ( void )
{
char str[] = "Hello how are ## and what are ## doing ?";
char word[]="##";
char replaceWith[]="you";
char * ret = replace(str,word,replaceWith);
printf("%s",ret);
free(ret); //freeing the allocated memory
getchar();
return 0;
}
char* replace(char* st,char* word,char *replaceWith)
{
int i = 0;
char *sr,*s,*ret, *temps;
int oldlen;
int count = 0;
int newlen;
int stlen;
s=(char *)malloc(strlen(st) + 1);
temps = s; // storing the address of s in a temp location
strcpy(s, st);
oldlen=strlen(word);
newlen=strlen(replaceWith);
for (i = 0; s[i]!= '\0';)
{
if( memcmp( &s[i], word, oldlen ) == 0)
{
count++;
i+=oldlen;
}
else
{
i++;
}
}
sr= (char *) malloc (i+1+count*(newlen-oldlen));
ret=sr;
while(*s)
{
if(memcmp( s, word, oldlen) == 0)
{
memcpy(sr, replaceWith, newlen);
s += oldlen;
sr += newlen;
}
else
{
*sr++ = *s++;
}
}
*sr = '\0';
free(temps); // freeing the memory allocated for s
return ret;
}
Always free same count with malloc.
free s, sr at end of replace,
use return value of replace instead of direct use on printf
and free return value (return of ret from replace) when not needed.
I have doing lots of experimenting with the memory leak and meanwhile I wrote the following code. Please comment about the pros and cons side of it.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
// Prototype declaration of replaceAll function
static char* replaceAll(char *pSource, char *pWord, char*pWith);
/////////////////////////////////////////////////////////////////////////////
//
// NAME : main
//
// DESCRIPTION : Implementation of main which invokes the replaceAll
// function and displays the output
//
// PARAMETERS : void
//
// RETURNED VALUE : int
//
/////////////////////////////////////////////////////////////////////////////
int main( void )
{
char *finalString = NULL; // To save the base returned address
char srcString[] = "Hello how r you"; // Actual String
char pWord[] = "r"; // Word to be replaced
char pWith[] = "are"; // Word to be replaced with
printf("\n Before Calling the replaceAll function:");
printf("%s",srcString);
printf("\n");
finalString = replaceAll(srcString, pWord, pWith); //calling the replaceAll function
printf("\n After Calling the replaceAll function:");
// Checking if NULL is returned
if( finalString != NULL )
{
//printing the string
printf("%s", finalString);
}
else
{
printf("\n Error: Blank String returned ");
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
//
// NAME : replaceAll
//
// DESCRIPTION : Implementation of replaceAll function which replaces
// a word in given string with another word
//
// PARAMETERS : char *
//
// RETURNED VALUE : char *
//
/////////////////////////////////////////////////////////////////////////////
static char* replaceAll(char *pSource, char *pWord, char*pWith)
{
char *pSt = NULL; // Pointer to the source String to avoid modifying the pSource
char *pTarget = NULL; // Target pointer to be malloced
char *pTg = NULL; // Pointer to the target string
int count; // Counter
int nWord = strlen (pWord); // length of the word which needs to be replaced
int nWith = strlen (pWith); // length of the word with which the word needs to be replaced
static const char nullP = '\0'; // null character
int szTarget = 0;
// Assigning the base address of the pSource to a temporary and iterate through
for ( pSt = pSource, count = 0; *pSt != nullP; pSt++ )
{
// Count number of occurances of the Word in the String to calculate the length of the final string
if( memcmp( pSt, pWord, nWord ) == 0)
{
count++;
pSt += nWord-1;
}
}
// Calculate the required target Size
szTarget = strlen (pSource) + count * (nWith - nWord) + sizeof (nullP);
// Allocate memory for the target string
pTarget = (char *)malloc(szTarget);
// Check if the malloc function returns sucessfully
if ( pTarget != NULL)
{
// Copying the string with replacement
for (pTg = pTarget, pSt = pSource; *pSt != nullP; )
{
if( memcmp (pSt, pWord, nWord) == 0)
{
memcpy (pTg,pWith,nWith);
pSt += nWord;
pTg += nWith;
}
else
{
*pTg++ = *pSt++;
}
}
// Assigning NULL Character to the target string after copying
*pTg = '\0';
}
return pTarget;
}

lua line numbers after multiple calls to loadbuffer

I load two strings with loadbuffer into one lua_state.
if( luaL_loadbuffer( L, str.c_str(), str.size(), "line") != 0 )
{
printf( "%s\n", lua_tostring ((lua_State *)L, -1));
}
lua_pcall(L, 0, 0, 0);
if( luaL_loadbuffer( L, str2.c_str(), str2.size(), "line2") != 0 )
{
printf( "%s\n", lua_tostring ((lua_State *)L, -1));
}
lua_pcall(L, 0, 0, 0);
For example:
function f ()
print( "Hello World!")
end
and
function g ()
f(
end
The forgotten ) in the second string throws an error:
[string "line2"]:9: unexpected Symbol
But 9 is the line number from string 1 plus string 2. The line number should be 3.
Is there a way to reset the line number counter before call to loadbuffer?
I guess this link describes your situation:
http://www.corsix.org/content/common-lua-pitfall-loading-code
You are loading two chunks of information, calling the chunks will put them consecutive into the global table. The lua_pcall(L, 0, 0, 0); is not calling your f() and g(), but is constructing your lua code sequential.
Your code could possibly be simplified to:
if (luaL_dostring(L, str.c_str()))
{
printf("%s\n", lua_tostring (L, -1));
}
if (luaL_dostring(L, str2.c_str()));
{
printf("%s\n", lua_tostring (L, -1));
}
which also protects against calling a chunk when it fails to load;
You are right Enigma, the code from str2 is appended consecutive. A breakpoint in
static void statement (LexState *ls) {
in lparser.cpp shows LexState.linenumber to be 5 and 7 for str, and 5, 7, 14 and 16 for str2.
So str is lexed and added to the VM twice.
I will find a different way to put a script made of multiple files into one VM.
Just if someone would need it too.
Add this function to lauxlib.h
LUALIB_API int (luaL_loadbuffers) (lua_State *L, size_t count, const char **buff, size_t *sz,
const char **name, const char *mode);
and to lauxlib.c
#include"lzio.h"
#include"ldo.h"
#include"ltable.h"
#include"lgc.h"
LUALIB_API int luaL_loadbuffers (lua_State *L, size_t count, const char **buff, size_t *sz,
const char **name, const char *mode)
{
ZIO z;
int status;
int i;
for( i=0; i<count; i++)
{
LoadS ls;
ls.s = buff[i];
ls.size = sz[i];
lua_lock(L);
luaZ_init(L, &z, getS, &ls);
status = luaD_protectedparser(L, &z, name[i], mode);
if (status == LUA_OK) { /* no errors? */
LClosure *f = clLvalue(L->top - 1); /* get newly created function */
if (f->nupvalues == 1) { /* does it have one upvalue? */
/* get global table from registry */
Table *reg = hvalue(&G(L)->l_registry);
const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
setobj(L, f->upvals[0]->v, gt);
luaC_barrier(L, f->upvals[0], gt);
} // == 1
lua_pcall( L, 0, 0, 0);
}
lua_unlock(L);
if( status != LUA_OK )
break;
}
return status;
}
Every string/file gets its own line numnbering.
It is just a copy, almost, of lua_load in lapi.c. So easy to adjust in a new release of LUA.

Resources