I am reading REBOL source code and I can't understand the purpose of the following statement:
/***********************************************************************
**
*/ int main(int argc, char **argv)
/*
***********************************************************************/
{
char *cmd;
// Parse command line arguments. Done early. May affect REBOL boot.
Parse_Args(argc, argv, &Main_Args);
Print_Str("REBOL 3.0\n");
REBOL_Init(&Main_Args);
// Evaluate user input:
while (TRUE) {
cmd = Prompt_User();
REBOL_Do_String(cmd);
if (!IS_UNSET(DS_TOP)) {
//if (DSP > 0) {
if (!IS_ERROR(DS_TOP)) {
Prin("== ");
Print_Value(DS_TOP, 0, TRUE);
} else
Print_Value(DS_TOP, 0, FALSE);
//}
}
//DS_DROP; // result
}
return 0;
}
In Parse_Args function:
/***********************************************************************
**
*/ void Parse_Args(int argc, REBCHR **argv, REBARGS *rargs)
/*
** Parse REBOL's command line arguments, setting options
** and values in the provided args structure.
**
***********************************************************************/
{
REBCHR *arg;
REBCHR *args = 0; // holds trailing args
int flag;
int i;
CLEARS(rargs);
....
And CLEARS is defined:
#define CLEARS(m) memset((void*)(m), 0, sizeof(*m));
So my question is why memset is being used here?
It looks like rargs is some kind of struct containing options for the program. CLEARS() and memset() is used to fill that struct with zero values to initiate it.
memset sets a block of memory to a given value.
It is normally written in hand optimized assembly and is expected to be blindingly fast.
Related
When using the auto completion with the Readline library in C, the prompt is reprinted when typing the tab key twice:
(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1 NAME_OF_FILE2 (suggestions by Readline)
(prompt) view NAME_OF_F
I'd like to suppress the reprinting of the prompt on the 3rd line by keeping the first line printed with the suggestions below it like such:
(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1 NAME_OF_FILE2 (suggestions by Readline)
I'd like the cursor back at the end of the first line that has the prompt.
Compiled with gcc -Wall -O0 -ggdb -fno-builtin rline.c -o rline -lreadline -ltermcap.
Here's a code sample:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <readline/readline.h>
int execute_line(char *line);
void initialize_readline();
static char **fileman_completion(char *text, int start, int end);
static char *command_generator(char *text, int state);
char *command[] = { "view", "quit", (char *)NULL };
int done; /* When non-zero, this global means the user is done using this program. */
int main(int argc, char **argv)
{
char *line;
initialize_readline(); /* Bind our completer. */
for ( ; done == 0; ) {
line = readline("> ");
if (!line)
break;
if (*line)
execute_line(line);
free(line);
}
return 0;
}
/* String to pass to system(). This is for the VIEW command. */
static char syscom[1024];
int execute_line(char *line)
{
int i = 0;
char *word;
/* Isolate the command word. */
while (line[i] && whitespace(line[i]))
i++;
word = line + i;
while (line[i] && !whitespace(line[i])) i++;
if (line[i]) line[i++] = '\0';
if (strcmp(word, "quit") == 0) {
done = 1;
return 0;
} else if (strcmp(word, "view")) {
fprintf(stderr, "%s: Choose only \"view FILE\" or \"quit\" as your command.\n", word);
return -1;
}
/* Get argument to command, if any. */
while (whitespace(line[i])) i++;
word = line + i;
if(!word || !*word) {
fprintf(stderr, "view: Argument required.\n");
return -1;
}
sprintf(syscom, "more %s", word);
return system(syscom);
}
void initialize_readline()
{
rl_readline_name = "rline";
rl_attempted_completion_function = (rl_completion_func_t *)fileman_completion;
}
static char **fileman_completion(char *text, int start, int end)
{
if (start == 0)
return rl_completion_matches(text, (rl_compentry_func_t *)*command_generator);
return NULL;
}
static char *command_generator(char *text, int state)
{
static int list_index, len;
char *name;
if (!state) {
list_index = 0;
len = strlen(text);
}
while ((name = command[list_index++]))
if (strncmp(name, text, len) == 0)
return strdup(name);
return NULL;
}
The program only accepts the commands view FILE_NAME to view the contents of a file and quit to exit the program.
The example is a shortened version of a sample program found here.
I don't think that readline has anything like that built in, but it does provide a lot of customisation possibilities if you want to try to write the logic yourself.
You could try writing a custom rl_completion_display_matches_hook to display the completion list. But it's not entirely clear to me how you would restore the cursor position afterwards. I don't think readline has a public interface for either finding or resetting the cursor position. (And, of course, it's possible that the completion list was so big that the original command scrolled off the screen.)
As an alternative, I was able use the hook to print the completion list over top of the current line and then redisplay the prompt after the completion list (although I cheated by assuming that the current input is always just one line). That's not quite what you asked for, but it may be useful for demonstration purposes. I used the following custom match printer:
static void display_matches(char** matches, int len, int max) {
putp(carriage_return);
putp(clr_eol);
putp(cursor_up);
rl_display_match_list(matches, len, max);
rl_forced_update_display();
}
I also added the following to the initialisation function:
rl_completion_display_matches_hook = display_matches;
setupterm(NULL, 1, (int*)0);
Thanks #rici for the inspiration. I got it working with his function with some modifications.
In order for this to work properly you need to download the readline library. In the rlprivate.h file from readline, I removed the lines char **lines;, and the line #include "realdine.h" from display.c. Then in your own .c you must have an #include </PATH/TO/display.c>. In that display.c, an #include points to the modified rlprivate.h. All of this so that I can have access to _rl_move_vert(1).
static void display_matches(char** matches, int len, int max)
{
int saved_point = rl_point;
char *saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0); // Clear the previous text
putp(cursor_up);
_rl_move_vert(1);
rl_display_match_list(matches, len, max);
putp(cursor_up);
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
putp(cursor_down);
free(saved_line);
}
I am aware that getopt should be used to parse command line arguments, and not strings.
However, I am confused by the fact that if I pass it an array of strings that "looks like" the argv variable, getopt_long seems to work, but only the first time that I call it. For the second, and all the subsequent times, that I call it it ignores any arguments and returns the default ones.
The reason I am doing this is that I am turning an application that used to take command line arguments in an "interactive" version of it that asks the user for some arguments, then does some actions based on those arguments, then asks for more arguments and so on.
The following code is a minimal example that reproduces the error
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
struct input_parameters{
char * d; // data set
};
int solver_help(int argc, char* const argv[], struct input_parameters * p)
{
int c;
p->d = "default name";
while (1)
{
static struct option long_options[] =
{
{"data", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "d:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 'd': p->d = optarg;
break;
default:
printf("wrong option specification\n");
exit(-1);
}
}
return 0 ;
}
int main () {
int argc_first = 3;
char * const argv_first[] = { "getopt_test", "--data", "first" };
struct input_parameters first_input;
solver_help(argc_first, argv_first, &first_input);
printf("I think the data is: %s\n", first_input.d);
int argc_second = 3;
char * const argv_second[] = { "getopt_test","--data", "second" };
struct input_parameters second_input;
solver_help(argc_second, argv_second, &second_input);
printf("I think the data is: %s\n", second_input.d);
return 0;
}
The output of this code is
I think the data is: first
I think the data is: default name
From the manual page for getopt:
In order to use getopt() to evaluate multiple sets of arguments, or
to evaluate a single set of arguments multiple times, the variable
optreset must be set to 1 before the second and each additional
set of calls to getopt(), and the variable optind must be
reinitialized.
Modifying your code slightly gives you the desired results:
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
struct input_parameters {
char * d; // data set
};
int solver_help(int argc, char* const argv[], struct input_parameters * p)
{
p->d = "default name";
static struct option long_options[] =
{
{"data", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
int option_index = 0;
optreset = 1; /* ADD THIS */
optind = 1; /* ADD THIS */
int c = getopt_long(argc, argv, "d:",
long_options, &option_index);
switch ( c )
{
case -1:
break;
case 'd':
p->d = optarg;
break;
default:
printf("in default case...\n");
printf("wrong option specification\n");
exit(EXIT_FAILURE);
}
return 0;
}
int main(void) {
int argc_first = 3;
char * const argv_first[] = { "getopt_test", "--data", "first" };
struct input_parameters first_input;
solver_help(argc_first, argv_first, &first_input);
printf("I think the data is: %s\n", first_input.d);
int argc_second = 3;
char * const argv_second[] = { "getopt_test","--data", "second" };
struct input_parameters second_input;
solver_help(argc_second, argv_second, &second_input);
printf("I think the data is: %s\n", second_input.d);
return 0;
}
with output:
paul#horus:~/src/sandbox$ ./go
I think the data is: first
I think the data is: second
paul#horus:~/src/sandbox$
Guys so I'm working on the web service assignment and I have the server dishing out random stuff and reading the uri but now i want to have the server run a different function depending on what it reads in the uri. I understand that we can do this with function pointers but i'm not exactly sure how to read char* and assign it to a function pointer and have it invoke that function.
Example of what I'm trying to do: http://pastebin.com/FadCVH0h
I could use a switch statement i believe but wondering if there's a better way.
For such a thing, you will need a table that maps char * strings to function pointers. The program segfaults when you assign a function pointer to string because technically, a function pointer is not a string.
Note: the following program is for demonstration purpose only. No bounds checking is involved, and it contains hard-coded values and magic numbers
Now:
void print1()
{
printf("here");
}
void print2()
{
printf("Hello world");
}
struct Table {
char ptr[100];
void (*funcptr)(void)
}table[100] = {
{"here", print1},
{"hw", helloWorld}
};
int main(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < 2; i++){
if(!strcmp(argv[1],table[i].ptr) { table[i].funcptr(); return 0;}
}
return 0;
}
I'm gonna give you a quite simple example, that I think, is useful to understand how good can be functions pointers in C. (If for example you would like to make a shell)
For example if you had a struct like this:
typedef struct s_function_pointer
{
char* cmp_string;
int (*function)(char* line);
} t_function_pointer;
Then, you could set up a t_function_pointer array which you'll browse:
int ls_function(char* line)
{
// do whatever you want with your ls function to parse line
return 0;
}
int echo_function(char* line)
{
// do whatever you want with your echo function to parse line
return 0;
}
void treat_input(t_function_pointer* functions, char* line)
{
int counter;
int builtin_size;
builtin_size = 0;
counter = 0;
while (functions[counter].cmp_string != NULL)
{
builtin_size = strlen(functions[counter].cmp_string);
if (strncmp(functions[counter].cmp_string, line, builtin_size) == 0)
{
if (functions[counter].function(line + builtin_size) < 0)
printf("An error has occured\n");
}
counter = counter + 1;
}
}
int main(void)
{
t_function_pointer functions[] = {{"ls", &ls_function},
{"echo", &echo_function},
{NULL, NULL}};
// Of course i'm not gonna do the input treatment part, but just guess it was here, and you'd call treat_input with each line you receive.
treat_input(functions, "ls -laR");
treat_input(functions, "echo helloworld");
return 0;
}
Hope this helps !
struct Message
{
char type;
double idNum;
char *Time;
char *asset;
bool BS;
float price1;
int shares1;
float price2;
int shares2;
};
typedef struct Message Message;
struct Asset
{
oBook *OrderBook;
Trade *TradeBook; //will point to the latest trade
int QtyTraded;
float ValueTraded;
char* Time;
};
typedef struct Asset Asset;
int main(int argc, char*argv[])
{
Message* newMessage;
Asset* Check;
//manipulation and initialization of Check, so that it holds proper values.
newMessage = parser("N,2376,01/02/2011 09:15:01.342,JPASSOCIAT FUTSTK 24FEB2011,B,84.05,2000,0,0",newMessage);
// MessageProcess(newMessage,AssetMap);
printf("LAST TRADE ADDRESS %p LAST TRADE TIME %s\n",Check->TradeBook,Check->Time);
}
Message* parser(char *message,Message* new_Message)
{
char a[9][256];
char* tmp =message;
bool inQuote=0;
int counter=0;
int counter2=0;
new_Message = (Message*)malloc(sizeof(Message));
while(*tmp!='\0')
{
switch(*tmp)
{
case ',': if(!inQuote)
{
a[counter][counter2]='\0';
counter++;
counter2=0;
}
break;
case '"':
inQuote=!inQuote;
break;
default:
a[counter][counter2]=*tmp;
counter2++;
break;
}
tmp++;
}
a[counter][counter2]='\0';
new_Message->type = *a[0];
new_Message->Time = &a[2][11];
new_Message->asset = a[3];
if(*a[4]=='S')
new_Message->BS = 0;
else
new_Message->BS = 1;
new_Message->price1=atof(a[5]);
new_Message->shares1=atol(a[6]);
new_Message->price2=atof(a[7]);
new_Message->shares2=atol(a[8]);
new_Message->idNum = atoi(a[1]);
return(new_Message);
}
Here there is a serious memory clash, in two variables of different scope. I have investigated using gdb and it seems the address of new_Message->Time is equalling to the address of Check->Time.
They both are structures of different types I am trying to resolve this issue, because, when parser changes the value of new_Message->Time it manipulates the contents of Check->Time
Please do suggest how to solve this problem. I have lost(spent) around 10 hours and counting to resolve this issue, and tons of hair.
Soham
EDIT STRUCTURE DEF ADDED
You're using an address of the stack allocated object to initialize new_Message->Time = &a[2][11];
Although you don't show us how you initialize Check which limits the amount of help we can give, there is an unnecessary parameter to parse() which you can remove.
int main(int argc, char **argv)
{
Message *newMessage;
Asset *Check;
[...]
newMessage = parser("N,2376...,0,0", newMessage);
[...]
}
Message *parser(char *message, Message *new_Message)
{
[...]
new_Message = (Message *)malloc(sizeof(Message));
[...]
return(new_Message);
}
When you look at that skeleton, it may be easier to see that:
a. The value in main() passed to parser() as newMessage is undefined because the local variable has not been initialized, but
b. It doesn't matter much because the first thing that happens in parser() is that a value is allocated and assigned to the function's copy of the uninitialized value (new_Message), thus initializing the value used in parser().
So, the code is 'safe', but could be written as:
int main(int argc, char **argv)
{
Message *newMessage;
Asset *Check;
[...]
newMessage = parser("N,2376...,0,0");
[...]
}
Message *parser(char *message)
{
[...]
Message *new_Message = (Message *)malloc(sizeof(Message));
[...]
return(new_Message);
}
It is best not to pass values to functions that are not used.
Also, most people either use underscores to separate words in names or use camelCase names, but not usually camel_Case which combines both.
In my programming project I want to parse command line attributes using flex/bison. My program is called like this:
./prog -a "(1, 2, 3)(4, 5)(6, 7, 8)" filename
Is it possible to parse this string using flex/bison without writing it to a file and parsing that file?
See this question String input to flex lexer
I think you can achieve something like that (I did a similar thing) by using fmemopen to create a stream from a char*and then replace that to stdin
Something like that (not sure if it's fully functional since I'm actually trying to remember available syscalls but it would be something similar to this)
char* args = "(1,2,3)(4,5)(6,7,8)"
FILE *newstdin = fmemopen (args, strlen (args), "r");
FILE *oldstdin = fdup(stdin);
stdin = newstdin;
// do parsing
stdin = oldstdin;
Here is a complete flex example.
%%
<<EOF>> return 0;
. return 1;
%%
int yywrap()
{
return (1);
}
int main(int argc, const char* const argv[])
{
YY_BUFFER_STATE bufferState = yy_scan_string("abcdef");
// This is a flex source. For yacc/bison use yyparse() here ...
int token;
do {
token = yylex();
} while (token != 0);
// Do not forget to tell flex to clean up after itself. Lest
// ye leak memory.
yy_delete_buffer(bufferState);
return (EXIT_SUCCESS);
}
another example. this one redefines the YY_INPUT macro:
%{
int myinput (char *buf, int buflen);
char *string;
int offset;
#define YY_INPUT(buf, result, buflen) (result = myinput(buf, buflen));
%}
%%
[0-9]+ {printf("a number! %s\n", yytext);}
. ;
%%
int main () {
string = "(1, 2, 3)(4, 5)(6, 7, 8)";
yylex();
}
int myinput (char *buf, int buflen) {
int i;
for (i = 0; i < buflen; i++) {
buf[i] = string[offset + i];
if (!buf[i]) {
break;
}
}
offset += i;
return i;
}
The answer is "Yes". See the O'Reilly publication called "lex & yacc", 2nd Edition by Doug Brown, John Levine, Tony Mason. Refer to Chapter 6, the section "Input from Strings".
I also just noticed that there are some good instructions in the section "Input from Strings", Chapter 5 of "flex and bison", by John Levine. Look out for routines yy_scan_bytes(char *bytes, int len), yy_scan_string("string"), and yy_scan_buffer(char *base, yy_size_t size). I have not scanned from strings myself, but will be trying it soon.