Command Line Interface (CLI): your recommendations

W

Walter Roberson

I'm implementing simple CLI
Here is code implementing part of this algorithm. The problem I came across
is if pressing 'Enter' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it's printed repeatedly in a line.
const char *PROMPT = "CLI>";
int main(void)
{
char buf[BUFSIZ] = {0};
cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };

while (1) {
printf("%s", PROMPT);

There is in \n in your PROMPT, and you do not fflush()
the output, so your prompt is not certain to appear at any
particular place relative to the input. It might not appear at
all until you happen to output a \n for other reasons.

if ( fgets(buf, BUFSIZ, stdin) ) {
/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' || buf[0]
== '\t')
continue;

That continue is relative to the while(), and you do not print
anything out in the case of the empty line. Thus if you have
a series of \n in your buffer, you will end up doing repeated
printf("%s", PROMPT) and since there is no \n in that, the several
prompts will all come out on one line.
 
R

Roman Mashak

Hello, All!

I'm implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:

1) get whole string of input line
2) preset table of strings matching <command>
3) preset table of function calls
4) scan <command> table for string, if match - call matching function (I
declare ALL callback functions as having the same format)

Here is code implementing part of this algorithm. The problem I came across
is if pressing 'Enter' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it's printed repeatedly in a line.

Before I went too far, I would like to ask your opinion about concept I'm
using and recommendations if possible:

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define COUNT(a) (sizeof(a) / sizeof(a[0]))

const char *PROMPT = "CLI>";

enum errCodes { RC_SUCCESS = 0, RC_ERROR = -1 };

/* table of <commands> */
const char *commands[] = {
"show",
"version",
"help",
"port",
"exit"
};

/* callback function */
typedef int (*handler_ptr_t)(int, char**);

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20
char command[MAX_NAME];
#define MAX_ARGS 4
char params[MAX_ARGS];
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

int cliShow(int argc, char *argv[])
{
puts("cliShow() stub");
return 0;
}

int cliVersion(int argc, char *argv[])
{
puts("cliVersion() stub");
return 0;
}

int cliHelp(int argc, char *argv[])
{
puts("cliHelp() stub");
return 0;
}

int cliPort(int argc, char *argv[])
{
puts("cliPort() stub");
return 0;
}

int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCESS);
}

/* define table functions pointers */
handler_ptr_t ftable[] = { cliShow, cliVersion, cliHelp, cliPort, cliExit };

/* parse command line and fill structure */
static int
cliParseCommandLine(char *buf, cmdLineEntry_t *cli)
{
const char delim[] = " \t\n";
unsigned int i;
char *token;

memset(cli, 0, sizeof *cli);

token = strtok(buf, delim);
for (i = 0; i < COUNT(commands); i++) {
if (!strcmp(token, commands)) {
strcpy(cli->command, token);
cli->cmd_handler = ftable;
i = 0;
for (token = strtok(NULL, delim); token != NULL; ) {
cli->params[i++] = token;
token = strtok(NULL, delim);
}
cli->params_num = i;
return 0;
}
}
return -1;
}

int main(void)
{
char buf[BUFSIZ] = {0};
cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };

while (1) {
printf("%s", PROMPT);
if ( fgets(buf, BUFSIZ, stdin) ) {
/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' || buf[0]
== '\t')
continue;

/* parse stream */
if ( cliParseCommandLine(buf, &cli) < 0 ) {
printf("Error : invalid command!\n");
continue;
}
else {
cli.cmd_handler(cli.params_num, cli.params);
}
}
else continue; /* EOL */
} /* while */

return 0;
}

TIA!


With best regards, Roman Mashak. E-mail: (e-mail address removed)
 
R

Rod Pemberton

Roman Mashak said:
Hello, All!

I'm implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:

Does this compile cleanly for you? If I gcc -Wall, I get two errors.

The first error is here:
for (token = strtok(NULL, delim); token != NULL; ) {
cli->params[i++] = token;
token = strtok(NULL, delim);

I think the middle line should be:
cli->params[i++] = *token;

The second error is here:
else {
cli.cmd_handler(cli.params_num, cli.params);

cli.params is an array of char, but the handler_pointer_t functions accept a
pointer to array of char, 'char *argv[]', for the second argument.


Rod Pemberton
 
R

Rod Pemberton

Command

After thought, you might want a setbuf() or two:

setbuf(stdin,NULL);
setbuf(stdout,NULL);


Rod Pemberton
 
K

Keith Thompson

Roman Mashak said:
Hello, Walter!
You wrote on Sat, 11 Feb 2006 18:02:16 +0000 (UTC):
??>> const char *PROMPT = "CLI>"; [...]
??>> printf("%s", PROMPT);

WR> There is in \n in your PROMPT,
Why do I need '\n' in PROMP? Otherwise cursor jumps next line, which is
wrong...
I don't get you here, please clarify.

He already did:
WR> and you do not fflush() the output, so your prompt is not certain to
WR> appear at any particular place relative to the input. It might not
WR> appear at all until you happen to output a \n for other reasons.

stdout is typically line-buffered, so the prompt won't necessarily
appear until you either print a new-line character *or* call
fflush(stdout).
 
R

Roman Mashak

Hello, Rod!
You wrote on Sat, 11 Feb 2006 15:48:55 -0500:

RP> The first error is here:
??>> for (token = strtok(NULL, delim); token != NULL; ) {
??>> cli->params[i++] = token;
??>> token = strtok(NULL, delim);

RP> I think the middle line should be:
RP> cli->params[i++] = *token;

RP> The second error is here:
??>> else {
??>> cli.cmd_handler(cli.params_num, cli.params);

RP> cli.params is an array of char, but the handler_pointer_t functions
RP> accept a pointer to array of char, 'char *argv[]', for the second
RP> argument.
Sorry I made typo in first post, right definition of "cmdLineEntry_t" is:

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20
char command[MAX_NAME];
#define MAX_ARGS 10
char *params[MAX_ARGS];
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

i.e. params is array of pointers to char.

With best regards, Roman Mashak. E-mail: (e-mail address removed)
 
R

Roman Mashak

Hello, Walter!
You wrote on Sat, 11 Feb 2006 18:02:16 +0000 (UTC):

??>> const char *PROMPT = "CLI>";

??>> int main(void)
??>> {
??>> char buf[BUFSIZ] = {0};
??>> cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };
??>>
??>> while (1) {
??>> printf("%s", PROMPT);

WR> There is in \n in your PROMPT,
Why do I need '\n' in PROMP? Otherwise cursor jumps next line, which is
wrong...
I don't get you here, please clarify.
WR> and you do not fflush() the output, so your prompt is not certain to
WR> appear at any particular place relative to the input. It might not
WR> appear at all until you happen to output a \n for other reasons.

??>> if ( fgets(buf, BUFSIZ, stdin) ) {
??>> /* skip LF/CR/TAB/SP */
??>> if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' ||
??>> buf[0] == '\t') continue;

WR> That continue is relative to the while(), and you do not print
WR> anything out in the case of the empty line. Thus if you have
If I press only 'Enter', it generates '\n' into buffer and according to
'continue' flow will jump back to 'while' loop, where PROMPT is printed.
I can't grasp your idea, unfortunately...
WR> a series of \n in your buffer, you will end up doing repeated
WR> printf("%s", PROMPT) and since there is no \n in that, the several
WR> prompts will all come out on one line.

With best regards, Roman Mashak. E-mail: (e-mail address removed)
 
K

Keith Thompson

Roman Mashak said:
You wrote on Sun, 12 Feb 2006 07:48:24 GMT:

WR>>> and you do not fflush() the output, so your prompt is not certain to
WR>>> appear at any particular place relative to the input. It might not
WR>>> appear at all until you happen to output a \n for other reasons.

KT> stdout is typically line-buffered, so the prompt won't necessarily
KT> appear until you either print a new-line character *or* call
KT> fflush(stdout).
Ok, I simplified my code to minimum in order to catch error, but same effect
remained, here it is:

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

static const char *PROMPT = "CLI>";

int main(void)
{
char buf[BUFSIZ] = {0};

while (1) {
printf("%s", PROMPT);
fflush(stdout);

if ( fgets(buf, BUFSIZ, stdin) ) {
/* do something */
}
else continue; /* EOL */
} /* while */

return 0;
}

<unistd.h> isn't a standard C header, and _GNU_SOURCE isn't standard C
either, but your program doesn't seem to depend on either of them.

I don't know what you mean by "same effect remained". Is there a
problem?
 
R

Roman Mashak

Hello, Keith!
You wrote on Sun, 12 Feb 2006 07:48:24 GMT:

WR>>> and you do not fflush() the output, so your prompt is not certain to
WR>>> appear at any particular place relative to the input. It might not
WR>>> appear at all until you happen to output a \n for other reasons.

KT> stdout is typically line-buffered, so the prompt won't necessarily
KT> appear until you either print a new-line character *or* call
KT> fflush(stdout).
Ok, I simplified my code to minimum in order to catch error, but same effect
remained, here it is:

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

static const char *PROMPT = "CLI>";

int main(void)
{
char buf[BUFSIZ] = {0};

while (1) {
printf("%s", PROMPT);
fflush(stdout);

if ( fgets(buf, BUFSIZ, stdin) ) {
/* do something */
}
else continue; /* EOL */
} /* while */

return 0;
}

With best regards, Roman Mashak. E-mail: (e-mail address removed)
 
R

RSoIsCaIrLiIoA

Hello, All!

I'm implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:

1) get whole string of input line
2) preset table of strings matching <command>
3) preset table of function calls
4) scan <command> table for string, if match - call matching function (I
declare ALL callback functions as having the same format)

Here is code implementing part of this algorithm. The problem I came across
is if pressing 'Enter' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it's printed repeatedly in a line.

i don't see where the problem is

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define UC unsigned char

static const char *pc = "CLI[\"vexit\" to end]>";

struct you{
char* name;
char* pointer;
unsigned npar;
struct you* prev;
};

struct you *last=0;

int inserisci(const char* name, char* pointer)
{struct you *tm;
char *tmp;
unsigned sz;
///////////////////
if( name==0 ||(sz=strlen(name))==0 )
return 0;
if( (tm =malloc(sizeof(struct you)))==0 )
return 0;
if( (tmp=malloc(sizeof(sz+2)))==0 )
{free(tm); return 0;}
tm->name=tmp; strcpy(tm->name, name);
tm->pointer= pointer; tm->npar=0;
tm->prev=last; last=tm;
return 1;
}

void free_list(void)
{struct you *p=last, *v;
while(1) {if(p==0) break;
v=p; p=p->prev;
free(v->name); free(v);
}
}


int show(int aargc, char** aargv){puts("cliShow() stub");return 0;}
int version(int aargc, char** aargv){puts("cliVersion() stub");return
0;}
int help(int aargc, char** aargv){puts("cliHelp() stub");return 0;}
int port(int aargc, char** aargv){puts("cliPort() stub"); return
0;}
void vexit(int aargc, char** aargv)
{puts("cliExit() stub");
free_list();
exit(0);
}

int main(void)
{char buf[BUFSIZ] = {0}, *cp, *cp1;
struct you *p;
/////////////////////////////////
inserisci("show",(char*) show);
inserisci("version", (char*) version);
inserisci("help", (char*) help);
inserisci("port", (char*) port);
inserisci("vexit",(char*) vexit);

while (1) {printf("%s", pc); fflush(stdout);
if ( fgets(buf, BUFSIZ, stdin)!=0 )
{for(cp=buf; isspace((UC)*cp); ++cp);
if(*cp!=0)
{for(cp1=cp; !isspace((UC)*cp1) && *cp1!=0; ++cp1);
if(*cp1!=0) *cp1=0;
for(p=last; p ;p=p->prev)
if(strcmp(p->name, cp)==0)
switch(p->npar)
{case 0:
( ( void (*)(void) ) (p->pointer))( );
break;
case 1:
( ( void (*)(int) )(p->pointer))(1);
break;
}
}
}
}
return 0;

}
 
R

Rod Pemberton

Roman Mashak said:
Hello, Rod!
Sorry I made typo in first post, right definition of "cmdLineEntry_t" is:

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20
char command[MAX_NAME];
#define MAX_ARGS 10
char *params[MAX_ARGS];
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

i.e. params is array of pointers to char.

Some suggestions:

I would change this line, extra spaces deleted:
if (buf[0]=='\n'||buf[0]==' '||buf[0]=='\r'||buf[0]=='\t')

To this, to specifically catch an ASCII carriage return and newline:
if buf[0]==0x0A||buf[0]==0x0D||buf[0]==' '||buf[0]=='\t')

Or, to this:
if (strtok(buf,"\x0D\x0A\t ")==NULL)

For this section, certain compilers will complain about a missing return:
int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCESS);
}

You'll need to add a fake return:
int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCESS);
return 0; /* fake return */
}

You are using 'puts' in your stubs. If you remove them, this else section
in main() will need to output a "\n":
else {
cli.cmd_handler(cli.params_num, cli.params); printf("\n");
}

Since you are using fgets(), forget about the setbuf(stdin,NULL).
If you are writing this for DOS, consider using cgets() and
setbuf(stdin,NULL).


Good Luck,

Rod Pemberton
 
B

Barry Schwarz

Hello, All!

I'm implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:

1) get whole string of input line
2) preset table of strings matching <command>
3) preset table of function calls
4) scan <command> table for string, if match - call matching function (I
declare ALL callback functions as having the same format)

Here is code implementing part of this algorithm. The problem I came across
is if pressing 'Enter' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it's printed repeatedly in a line.

How could you execute the code with all the syntax errors?
Before I went too far, I would like to ask your opinion about concept I'm
using and recommendations if possible:

You really should compile your code and correct the errors before
asking for help.
#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define COUNT(a) (sizeof(a) / sizeof(a[0]))

const char *PROMPT = "CLI>";

enum errCodes { RC_SUCCESS = 0, RC_ERROR = -1 };

/* table of <commands> */

If this comment were not here, would your code be any less clear? If
the comment does not add something to what is immediately obvious in
the code, it actually reduces readability.
const char *commands[] = {
"show",
"version",
"help",
"port",
"exit"
};

/* callback function */
typedef int (*handler_ptr_t)(int, char**);

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20

Move these defines to either before the typedef or to the start of
your source (your choice before or after the includes). Never disrupt
the flow of a struct declaration like this.
char command[MAX_NAME];
#define MAX_ARGS 4
char params[MAX_ARGS];

What you have here is an array of four char. Not enough space to hold
even one argument let alone four. Based on how you use it later, I am
pretty certain that you wanted
char *params[...]
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

int cliShow(int argc, char *argv[])
{
puts("cliShow() stub");
return 0;
}

int cliVersion(int argc, char *argv[])
{
puts("cliVersion() stub");
return 0;
}

int cliHelp(int argc, char *argv[])
{
puts("cliHelp() stub");
return 0;
}

int cliPort(int argc, char *argv[])
{
puts("cliPort() stub");
return 0;
}

int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCESS);
}

/* define table functions pointers */
handler_ptr_t ftable[] = { cliShow, cliVersion, cliHelp, cliPort, cliExit };

You intend for this to be a global table. You have defines, typedefs,
enum declarations, global definitions, and function definitions
interspersed with each other. When you fill in the stub functions,
you will have a hellacious time finding anything. While it is "only"
a matter of style, it will make debugging much easier if your organize
things better. My recommendation:

Put all your defines, typedefs, and declarations in a header
file. Include prototypes for all your functions. Group like
directives (all defines, then all typedefs, etc). I even include my
#include<...> directives in this header but others prefer to leave
those in their function source files.

Put each function in its own source file. If you really want
to keep them all together (such as for posting here), the order them
in some way that makes it easy for others to find. I prefer main
first and the others following alphabetically. That way, I can tell
if I have scrolled to far when looking for a function.
/* parse command line and fill structure */
static int
cliParseCommandLine(char *buf, cmdLineEntry_t *cli)
{
const char delim[] = " \t\n";
unsigned int i;
char *token;

memset(cli, 0, sizeof *cli);

Not a problem but also of no value. Just so you know, forcing a
pointer to have all bits zero is not the same as setting it to NULL.
For integers and characters all bits zero is 0 but that may not be
true for floats and doubles.
token = strtok(buf, delim);
for (i = 0; i < COUNT(commands); i++) {
if (!strcmp(token, commands)) {
strcpy(cli->command, token);
cli->cmd_handler = ftable;
i = 0;


You have a logical breakdown here. Either initialize and increment i
in your for statement or do it in individual statements in the loop,
BUT NOT BOTH.
for (token = strtok(NULL, delim); token != NULL; ) {
cli->params[i++] = token;

This is a syntax error since params is a char and token is a char*.

When you fix params, it will hold the (up to) four addresses of the
arguments in buf. This makes it obvious that you want to completely
process each input line before obtaining the next (which is consistent
with your code in main).

But you are inconsistent. You actually copy the command but only
store the argument addresses. What about the command is so special
that you need to store the actual characters in cli->command rather
than simply the address of the command in buf?
token = strtok(NULL, delim);
}
cli->params_num = i;
return 0;
}
}
return -1;
}

int main(void)
{
char buf[BUFSIZ] = {0};
cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };

Another syntax error due to the bad declaration or params. That first
NULL is not a suitable value for an array of four char.
while (1) {
printf("%s", PROMPT);

Use fflush here to force the output to your screen.
if ( fgets(buf, BUFSIZ, stdin) ) {
/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' || buf[0]
== '\t')

Look up the isspace() function if you really want to do this. Are you
sure you want to do this since the strtoken call in
cliParseCommandLine() will very happily skip over leading white space
for you?
continue;

/* parse stream */
if ( cliParseCommandLine(buf, &cli) < 0 ) {
printf("Error : invalid command!\n");
continue;
}
else {
cli.cmd_handler(cli.params_num, cli.params);

Another syntax error due to params.
}
}
else continue; /* EOL */

A continue at the end of a loop is somewhat superfluous.
} /* while */

return 0;
}


Remove del for email
 
R

RSoIsCaIrLiIoA

; nasmw -f obj this_file.asm
; bcc32 file.c this.obj

section _DATA public align=4 class=DATA use32

extern _isspace
global _popola

; global _main

section _TEXT public align=1 class=CODE use32

; int popola(char** v, char* buf, int limit)
; s=0j, 4i, 8b, 12ra, 16@v, 20@buf, 24@limit
_popola:
push ebx
push esi
push edi
%define @v esp+16
%define @buf esp+20
%define @limit esp+24
xor edi, edi
cmp dword[@v], 0
je .fn
cmp dword[@buf], 0
je .fn
cmp dword[@limit], 0
jle .fn
mov esi, [@buf]
xor ebx, ebx
..a0:
mov bl, [esi]
push ebx
call _isspace
add esp, 4
cmp eax, 0
je .a1
inc esi
jmp short .a0
..a1:
cmp ebx, 0
je .fn
cmp edi, [@limit]
jne .a2
inc edi
jmp short .fn
..a2:
mov eax, [@v]
mov dword[eax+4*edi], esi
inc edi
..a3:
mov bl, [esi]
cmp ebx, 0
je .a4
push ebx
call _isspace
add esp, 4
cmp eax, 0
jne .a4
inc esi
jmp short .a3
..a4:
cmp ebx, 0
je .fn
mov byte[esi], 0
inc esi
jmp short .a0

..fn:
mov eax, edi
%undef @v
%undef @buf
%undef @limit
pop edi
pop esi
pop ebx
ret

---------------------------


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define UC unsigned char
#define U unsigned

static const char *pc = "CLI[\"vexit\" to end]> ";

struct you{
char* name;
char* pointer;
unsigned npar;
struct you* prev;
};

struct you *last=0;

int popola(char** v, char* buf, int limit);


int
inserisci(const char* name, char* pointer, U par)
{struct you *tm;
char *tmp;
unsigned sz;
///////////////////
if( name==0 || (sz=strlen(name))==0 )
return 0;
if( (tm =malloc(sizeof(struct you)))==0 )
return 0;
if( (tmp=malloc(sizeof(sz+2)))==0 )
{free(tm); return 0;}
tm->name=tmp; strcpy(tm->name, name);
tm->pointer= pointer; tm->npar=par;
tm->prev=last; last=tm;
return 1;
}

void free_list(void)
{struct you *p=last, *v;
while(1) {if(p==0) break;
v=p; p=p->prev;
free(v->name); free(v);
}
}


int show(void){puts("cliShow() stub");return 0;}
int version(void){puts("cliVersion() stub");return 0;}
int help(void){puts("cliHelp() stub");return 0;}
int port(void){puts("cliPort() stub"); return 0;}
void vexit(void)
{puts("cliExit() stub");
free_list();
exit(0);
}

void add(char* a1, char* a2)
{int aa1, aa2;
sscanf(a1, "%d", &aa1);
sscanf(a2, "%d", &aa2);
printf("%d\n", aa1+aa2);
}

void sub(char* a1, char* a2)
{int aa1, aa2;
sscanf(a1, "%d", &aa1);
sscanf(a2, "%d", &aa2);
printf("%d\n", aa1-aa2);
}


int main(void)
{char buf[BUFSIZ] = {0}, *a[32];
struct you *p;
int cv;
/////////////////////////////////
inserisci("show",(char*) show, 0);
inserisci("version", (char*) version, 0);
inserisci("help", (char*) help, 0);
inserisci("port", (char*) port, 0);
inserisci("vexit",(char*) vexit, 0);
inserisci("add",(char*) add, 2);
inserisci("sub",(char*) sub, 2);

la:;
while (1)
{printf("%s", pc); fflush(stdout);
if( fgets(buf, BUFSIZ, stdin)!=0 )
{cv=popola(a, buf, 7);
if(cv<=0) goto la;
else --cv;
for(p=last; p ;p=p->prev)
if(strcmp(p->name, a[0])==0)
{if(p->npar!=(U)cv) goto la;
switch(p->npar)
{case 0:
( (void (*)(void))(p->pointer) )( );
break;
case 1:
( (void (*)(char*))(p->pointer) )(a[1]);
break;
case 2:
( (void (*)(char*, char*))(p->pointer) )
(a[1], a[2]);
break;
case 3:
( (void (*)(char*, char*, char*))(p->pointer) )
(a[1], a[2], a[3]);
break;
case 4:
( (void (*)(char*, char*, char*, char*) )
(p->pointer) ) (a[1], a[2], a[3], a[4]);
break;
case 5:
( (void (*)(char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5]);
break;
case 6:
( (void (*)(char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6]);
break;
case 7:
( (void (*)(char*, char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
break;
default:
goto la;
}
}
}
}
return 0;
}
 
M

Mark McIntyre

; nasmw -f obj this_file.asm

You've alreadyt been asked several times not to post asm here.

You were looking a bit like a redeemed troll. You're not, it seems.

*plonk*
Mark McIntyre
 
K

Kenny McCormack

You've alreadyt been asked several times not to post asm here.

Be careful, you might hurt his feelings.
You were looking a bit like a redeemed troll. You're not, it seems.

Be careful, you might hurt his feelings.

Oh, look! Now, you've gone and done it. His wittle feewings have been
crushed.
 
R

Roman Mashak

Hello, Keith!
You wrote on Sun, 12 Feb 2006 10:17:54 GMT:

KT> <unistd.h> isn't a standard C header, and _GNU_SOURCE isn't standard C
KT> either, but your program doesn't seem to depend on either of them.
Yes, you're absolutely right, I forgot to remove those for this minimal
example from original code.
KT> I don't know what you mean by "same effect remained". Is there a
KT> problem?
By "same effect remained" I meant that if 'Enter' is pressed and not
released for a few seconds it ends up in 'CLI>' prompt is skipped sometimes
and printed twice in a same line. Seems like what Walter Roberson explained
here, but 'fflush(sydout)' didn't help.

What did I forget else?

With best regards, Roman Mashak. E-mail: (e-mail address removed)
 
K

Keith Thompson

Roman Mashak said:
Hello, Keith!
You wrote on Sun, 12 Feb 2006 10:17:54 GMT:

KT> <unistd.h> isn't a standard C header, and _GNU_SOURCE isn't standard C
KT> either, but your program doesn't seem to depend on either of them.
Yes, you're absolutely right, I forgot to remove those for this minimal
example from original code.
KT> I don't know what you mean by "same effect remained". Is there a
KT> problem?
By "same effect remained" I meant that if 'Enter' is pressed and not
released for a few seconds it ends up in 'CLI>' prompt is skipped sometimes
and printed twice in a same line. Seems like what Walter Roberson explained
here, but 'fflush(sydout)' didn't help.

If you hold the Enter down for a few seconds, it probably goes into
auto-repeat mode; I've seen that kind of thing cause input and output
to get out of sync.
 
K

Keith Thompson

Roman Mashak said:
Hello, Keith!
You wrote on Mon, 13 Feb 2006 04:02:34 GMT:

KT> If you hold the Enter down for a few seconds, it probably goes into
KT> auto-repeat mode; I've seen that kind of thing cause input and output
KT> to get out of sync.
[OT]
It happens only in telnet/ssh sessions, via serial cable all works fine
[/OT]

<OT>
Not surprising; there are probably more layers of buffering between
the keyboard and the program.
</OT>
 
R

Roman Mashak

Hello, Keith!
You wrote on Mon, 13 Feb 2006 04:02:34 GMT:

KT> If you hold the Enter down for a few seconds, it probably goes into
KT> auto-repeat mode; I've seen that kind of thing cause input and output
KT> to get out of sync.
[OT]
It happens only in telnet/ssh sessions, via serial cable all works fine
[/OT]

With best regards, Roman Mashak. E-mail: (e-mail address removed)
 
R

Roman Mashak

Hello, RSoIsCaIrLiIoA!
You wrote on Sun, 12 Feb 2006 12:33:22 +0100:

??>> matching function (I declare ALL callback functions as having the same
??>> format) Here is code implementing part of this algorithm. The problem
??>> I came across is if pressing 'Enter' continuously then sometimes
??>> output of PROMPT turnes out clumsy, i.e. it's printed repeatedly in a
??>> line.

R> i don't see where the problem is

R> #include <stdio.h>
R> #include <string.h>
R> #include <stdlib.h>
R> #include <ctype.h>

R> #define UC unsigned char
[skip]

Thank you for code, but I didn't ask for it :) I have my own to fix and
maintain.

With best regards, Roman Mashak. E-mail: (e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top