Parsing a .conf file with single function call in c - c

is there an elegant way of parsing .conf file in a c program? say, if i have normal text file -
param1 = 22
param2 = 99
param34 = 11
param11 = 15
...
it'd be nice to get access in one function call, smth like:
int c = xfunction(my.conf, param34);
and now c = 11. Many thanks in advance.

#include <stdio.h>
#include <stdlib.h>
#define xfunction(file, param) \
system("awk '/^" #param " = [0-9]+$/{ num = $3 };END { exit num }' " #file)
int main(void){
int c = xfunction(my.conf, param34);
printf("%d\n", c);
return 0;
}

It is better if you use a linked list as follow
struct node
{
char *key;
int value;
};
and assign all the key value pair to node and you can add as many node during parsing of conf file to the linked list.
later when you search you can simply traverse the linked list and check for the key by a simple strcmp() and get the value.

Related

Reading array size from file

I have a program which should adjust number of elements to number of devices it is working with. I have a config *.txt file that contains some parameters that allows users who don't know programming language to adjust program to their needs.
For example till now everything have been handled like this. In header file:
enum
{
// number of input and output channels
kMaxInputChannels = 8,
kMaxOutputChannels = 8
};
typedef struct AudioDriverSettings
{
(...)
ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels];
ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels];
(...)
} AudioDriverSettings;
typedef struct AudioFileConfig
{
(...)
int inputId[kMaxInputChannels];
int outputId[kMaxOutputChannels];
bool shouldMixInput[kMaxInputChannels];
bool shouldRecordChannel[kMaxInputChannels];
(...)
} AudioFileConfig;
In *.txt there are variables:
NUM_CHANNELS_IN 8
NUM_CHANNELS_OUT 8
And on program start I am reading it and writing to variable:
if (!strcmp(tmp_str, "NUM_CHANNELS_IN"))
NUM_CHANNELS_IN = atoi(token);
if (!strcmp(tmp_str, "NUM_CHANNELS_OUT"))
NUM_CHANNELS_OUT = atoi(token);
I would like to get effect as below but variable needs to be const so it isn't working.
int NUM_CHANNELS_IN;
int NUM_CHANNELS_OUT;
typedef struct AudioDriverSettings
{
(...)
ASIOBufferInfo bufferInfos[NUM_CHANNELS_IN + NUM_CHANNELS_OUT];
ASIOChannelInfo channelInfos[NUM_CHANNELS_IN + NUM_CHANNELS_OUT];
(...)
} AudioDriverSettings;
typedef struct AudioFileConfig
{
(...)
int inputId[NUM_CHANNELS_IN];
int outputId[NUM_CHANNELS_OUT];
bool shouldMixInput[NUM_CHANNELS_IN];
bool shouldRecordChannel[NUM_CHANNELS_IN];
(...)
} AudioFileConfig;
Is there any simple way to handle it?
If this is C, you need to allocate your arrays dynamically:
ASIOBufferInfo *bufferInfos;
...
bufferInfos = malloc(sizeof(ASIOBufferInfo) * (NUM_CHANNELS_IN + NUM_CHANNELS_OUT));
If this is C++, use the std::vector class:
std::vector<ASIOBufferInfo> bufferInfos;
...
bufferInfos.reserve(NUM_CHANNELS_IN + NUM_CHANNELS_OUT);
and then push_back to the vector. Or:
std::vector<ASIOBufferInfo> bufferInfos(NUM_CHANNELS_IN + NUM_CHANNELS_OUT);
and then just access the elements like bufferInfos.at(i).
I Believe the answer you are looking for is to use pointers. By changing from:
int NUM_CHANNELS_IN;
int NUM_CHANNELS_OUT;
to:
int *NUM_CHANNELS_IN;
int *NUM_CHANNELS_OUT;
You will be able to pass your variable out of functions etc. I cannot say the exact changes you will need to make to your code, you may need to brush up on the proper syntax for pointers, But i believe this is the simplest way to achieve what you are trying to do if I have correctly interpreted your question.
Hope this helps!

How to navigate around a linked list?

So let's say I have 3 nodes in my linked lists, each with a first name in it. The list is supposed to be ordered alphabetically. I need to navigate with pointers
I have a .h interface and a .c file implementation, so you can assume anything prototyped int he List.c file is not in the header file.
Let me explain what's going on logically, to make my code a bit easier to understand. ListP is a pointer to struct List that has simple attributes like logical size, physical size and a pointer to the head of the linked list. The character strings are typedefd as ListItemP for easy reconstruction to an integer linked list etc if need be.
List.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "List.h"
typedef struct Entry *EntryP;
EntryP newEntry(ListItemP thisItem);
struct List
{
int sizeL;
int sizeP;
ListItemP head;
};
struct Entry
{
ListItemP content;
struct Entry *next;
};
ListP newList()
{
ListP thisList = (ListP) malloc(sizeof(ListP));
thisList->head = 0x00;
thisList->sizeL = 0;
thisList->sizeP = 0;
return thisList;
}
void insertItemList(ListP thisList, ListItemP thisItem)
{
EntryP thisEntry = newEntry(thisItem);
thisEntry->content = thisItem;
// Make a conditional for the first condition (no items in list)
if ((thisList->head == 0x00) || (strcmp(thisItem, thisList->head) < 0)) {
thisList->head = thisEntry->content;
thisEntry->next = 0x00;
}
// The other conditional are what I don't understand, how to put go through
navigate through the list via pointers and such.
thisList->sizeL++;
thisList->sizeP++;
}
void displayList(ListP thisList)
{
printf("First Item: %s\n",thisList->head);
}
/*
* Not in the interface
*/
EntryP newEntry(ListItemP thisItem)
{
EntryP thisEntry = (EntryP) malloc(sizeof(EntryP));
thisEntry->content = thisItem;
thisEntry->next = NULL;
return thisEntry;
}
I would post my main.c (or tester.c or whatever you want to call it) but I don't really think its going to help at all, all the linked list navigation is going to occur in the List.c file.
So my question is this, assuming I have 3 or 4 or however many nodes, how can I navigate around them so I can do things like string compares and yadda yadda in order to place new strings in the linked list in alphabetical order.
Thank you!

Binary Tree of Strings returning wrong order

I am fairly new to C and have been learning from K&R's book The C Programming Language.
After doing the exercises on Binary trees I wanted to make a header for binary trees for
char*, long and double.
There is a function in the following code that has been giving me grief - it should fill an array of character pointers with the values stored in the tree in lexicographical order however it has a bug somewhere. Here's the code for the String Tree Header btree.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/************** TYPES **************/
typedef struct ctree
{
char *name;
ctree *left;
ctree *right;
};
/************** Globals **************/
static int c_inc = 0;
/************** Function Prototypes **************/
ctree *add_to_c_tree (ctree *cnode, char *name);
void print_c_tree (ctree *cnode);
ctree *c_tree_alloc (void);
void c_tree_free (ctree *cnode);
void return_c_tree (ctree *cnode, char **array);
/************** Function Definitions **************/
/* add_to_c_tree() : Adds a new node to a *character binary tree */
ctree *add_to_c_tree (ctree *cnode, char *name){
/* If the node is null, allocate memory for it,
* copy the name and set the internal nodes to null*/
if(cnode == NULL){
cnode = c_tree_alloc();
cnode->name = strdup(name);
cnode->left = cnode->right = NULL;
}
/* If initialised then add to the left node if it is lexographically
* less that the node above it else add it to the right node */
else{
if(strcmp(name, cnode->name) < 0)
cnode->left = add_to_c_tree(cnode->left,name);
else if(strcmp(name, cnode->name) > 0)
cnode->right = add_to_c_tree(cnode->right,name);
}
return cnode;
}
/* print_c_tree() : Print out binary tree */
void print_c_tree(ctree *cnode){
if (cnode != NULL) {
print_c_tree(cnode->left);
printf("%s\n",cnode->name);
print_c_tree(cnode->right);
}
}
/* return_c_tree() : return array of strings containing all values in binary tree */
void return_c_tree (ctree *cnode, char **array){
if (cnode != NULL) {
return_c_tree (cnode->left,array+c_inc);
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
// printf("arr+%d:%s\n", c_inc-1,*(array+(c_inc-1)));
return_c_tree (cnode->right,array+c_inc);
c_tree_free(cnode->right);
}
}
/* c_tree_alloc() : Allocates space for a tree node */
ctree *c_tree_alloc(void){
return (ctree *) malloc(sizeof(ctree));
}
/* c_tree_free() : Free's Memory */
void c_tree_free (ctree *cnode){
free(cnode);
}
Which I have been testing with bt.c:
#include "btree.h"
int main(void){
ctree *node = NULL; char *arr[100];
node = add_to_c_tree(node, "foo");
node = add_to_c_tree(node, "yoo");
node = add_to_c_tree(node, "doo");
node = add_to_c_tree(node, "woo");
node = add_to_c_tree(node, "aoo");
node = add_to_c_tree(node, "boo");
node = add_to_c_tree(node, "coo");
print_c_tree(node);
return_c_tree(node,arr);
for (int i = 0; i < 7; ++i)
{
printf("%d:%s ..\n",i, arr[i]);
}
return 0;
}
The reason for this question is that I have been having issues with the return_c_tree() function, which is meant to mimic the behaviour of K&R's print_c_tree() function except instead of recursively calling itself until a NULL ptr and printing out the name of the nodes in lexicographical order it is meant to add their names to an array of character ptrs and free the nodes memory.
However the output I get when run as above is:
aoo
boo
coo
doo
foo
woo
yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which shows that the print function works fine but the return function obviously isn't.
The confusing thing is that if the call to printf() in return_c_tree() is uncommented this is the result:
aoo
boo
coo
doo
foo
woo
yoo
arr+0:aoo
arr+1:boo
arr+2:coo
arr+3:doo
arr+4:foo
arr+5:woo
arr+6:yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which implies that it actually does add the strings in the right order.
Also I have tried it without the c_inc variable -> ie just incrementing array
before passing it to the right node which the produces the same results from the printf
in return_c_tree() but different from main:
arr+-1:aoo
arr+-1:boo
arr+-1:coo
arr+-1:doo
arr+-1:foo
arr+-1:woo
arr+-1:yoo
0:foo ..
1:yoo ..
2:coo ..
3:(null) ..
4:(null) ..
5:(null) ..
6:(null) ..
I'm rather confused, so If anyone can help I would appreciate it greatly. I'm sure I'm just incrementing it in the wrong place but I can't work out where.
I thought I had finally understood pointers but apparently not.
Best
P
Your problem is how you handle your pointer to array when you recursively call. This will fix your return_c_tree function:
void return_c_tree (ctree *cnode, char **array)
{
if (cnode != NULL) {
return_c_tree (cnode->left,array); // <--- CHANGED 2ND PARAM
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
return_c_tree (cnode->right,array); // <--- AGAIN, CHANGED 2ND PARAM
c_tree_free(cnode->right);
}
}
You're using a global variable c_inc to keep track of the current index into the array. However, when you recursively called return_c_tree, you passed in array+c_inc, but you did not offset c_inc to account for this. Basically, you double-counted c_inc each time.
While this solves your particular problem, there are some other problems with your code.
In general, using global variables is asking for trouble. There's no need to do it here. Pass c_inc as a parameter to return_c_tree.
Also, mixing global variables with recursion is especially prone to problems. You really want recursive routines to keep their state on the stack.
As a commenter pointed out, all of your code in btree.h should really be in btree.c. The point of header files is to define an interface, not for code.
(This is more stylistic) Your return_c_tree function is really two distinct functions: copy the elements of the tree (in order) into the array, and free the memory used by the tree. These two operations are conceptually distinct: there are times that you'll want to do one and not both. There can be compelling performance (or other) reasons to mix the two, but wait until you have some hard evidence.

Compile Lua script to unsigned char buffer

Im working on a server in C that dynamically generating Lua commands on the fly and send them by socket to the clients. Right now the server is using plain text, but I would like the server to pre-compile the script before sending it to the clients.
I check luac.c but couldn't find how to be able to do something like this:
char lua_commands[ 1024 ] = { "a = 123; b = 456; c = a + b;" };
int socket
unsigned int send_buffer_size
unsigned char *send_buffer
/* Compile lua_commands and store the binary script into send_buffer without
having to write first the .out on disk then read it again in order store the content
into send_buffer */
send( socket, send_buffer, send_buffer_size, 0 );
Anybody can help me to achieve this?
[ Update ]
Ok, I think I figure it out:
#include "lua.h"
#include "lauxlib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstring.h"
#include "lundump.h"
#define toproto(L,i) (clvalue(L->top+(i))->l.p)
static int writer( lua_State *L, const void *p, size_t size, void *u ){
unsigned int i = 0;
unsigned char *d = ( unsigned char * )p;
// Print all the bytes on the console.
while( i != size ) {
printf("%d ", d[ i ] );
++i;
}
return 0;
}
void compile( lua_State *L, char *command ){
const Proto* f;
if (luaL_loadstring( L, command ) !=0 ) {
printf( "%s\n", lua_tostring( L, -1 ) );
}
f = toproto( L,-1 );
lua_lock( L );
luaU_dump( L, f, writer, NULL, 1 );
lua_unlock( L );
}
int main (int argc, const char * argv[]) {
lua_State *L = lua_open();
compile( L, "a = 123; b = 456; c = a + b; print( c );" );
lua_close( L );
return 0;
}
However that leads me to another question, do I have to close and reopen (lua_open, lua_close) the Lua state every time I'm calling my compile() function with other Lua commands or the output will only be the result of the latest luaL_loadstring?
Im not sure but look to me from the toproto macro definition that the top most stack will be returned am I correct?
You should use lua_dump() instead of internal toproto() + luaU_dump() functions. As an added bonus, this way your code will support LuaJIT 2.
It is not necessary to recreate the state each time you get the dump.
BUT. I would avoid executing Lua bytecode that came from the untrusted source (and server often is untrusted to the client). It is not safe, and may lead to severe security issues. (No such problems with source code — but you still have to sandbox it, of course.)
In general, always make sure that you check that the code you load from untrusted source is not bytecode (it is, if first byte is 27 decimal). Always execute such code in a sandbox.
If all that you need is to pass data in Lua-friendly way, pick some proper data serialization library instead. Aside of sandboxing and portability problems, loadstring() is rather slow.
For example, we're using using my luatexts library for similar purposes (make sure to pore through this list for alternatives). Luatexts supports tuples, which plays nicely with function calls. For example (in pseudocode):
Server:
my_send(luatexts.lua.save("myMethod", { param = true }, 42))
Client:
local actions = { }
function actions.myMethod(params, number)
print(params.param, number) --> true, 42
end
local function handle_action(ok, name, ...)
assert(ok, name) -- name would contain error message if not OK
local handler = assert(actions[name], "unknown action")
return handler(...)
end
local str = my_receive()
handle_action(luatexts.load(str))
Open a ticket if you want luatexts.save or streaming support implemented in C.

Can't understand this conversion from C to Assembly

I'd like to know if someone can explain me the solution to this problem:
the code is:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int c[20];
int n;
} t_coda;
t_coda coda;
void init(t_coda *coda) {
coda->n = 0;
}
void add(t_coda *coda, int x) {
if (coda->n < 20)
coda->c[(coda->n)++] = x;
}
main() {
init(&coda);
coda->n=1;
coda->c[0]=2;
add(&coda,3);
add(&coda,4);
}
And I need to know the corresponding instruction of: coda->n = 0; and coda->c[(coda->n)++] = x; in simplesem (an assembly-like semantic);
The solution is:
set D[D[0]+3]+20, 0
for the first question
and:
set D[D[0]+3]+D[D[D[0]+3]+20], D[D[0]+4]
set D[D[0]+3]+20, D[D[D[0]+3]+20] + 1
for the second one;
D is the Data stack, and D[0] return the value contained in the 0-cell of the data
Thank you
I would guess that...
D[0]+3 is a reference to the address of coda (the *coda in the function call)
D[D[0]+3] is a lookup of the data at the address where coda is stored
D[D[0]+3]+20 is an offset of 20 from where coda begins, thus moving past coda->c (which is 20 items) to get to coda->n.
That should help you to understand the first one; the same ideas can be extended to the second.

Resources