473,326 Members | 2,168 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Command Line Interface (CLI): your recommendations

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[i])) {
strcpy(cli->command, token);
cli->cmd_handler = ftable[i];
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: mr*@tusur.ru
Feb 11 '06 #1
34 6806
In article <ds**********@relay.tomsk.ru>, Roman Mashak <mr*@tusur.ru> wrote:
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.
--
Okay, buzzwords only. Two syllables, tops. -- Laurie Anderson
Feb 11 '06 #2

"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds**********@relay.tomsk.ru...
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


Feb 11 '06 #3

"Rod Pemberton" <do*********@sorry.bitbucket.cmm> wrote in message
news:43********@news.bea.com...

"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds**********@relay.tomsk.ru...
Hello, All!

I'm implementing simple CLI (flat model, no tree-style menu etc.).

Command

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

setbuf(stdin,NULL);
setbuf(stdout,NULL);
Rod Pemberton
Feb 11 '06 #4
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: mr*@tusur.ru
Feb 12 '06 #5
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: mr*@tusur.ru
Feb 12 '06 #6
"Roman Mashak" <mr*@tusur.ru> writes:
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).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 12 '06 #7
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: mr*@tusur.ru
Feb 12 '06 #8
"Roman Mashak" <mr*@tusur.ru> writes:
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?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 12 '06 #9
On Sun, 12 Feb 2006 01:14:51 +0700, "Roman Mashak" <mr*@tusur.ru>
wrote:
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;

}
Feb 12 '06 #10

"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds***********@relay.tomsk.ru...
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
Feb 12 '06 #11
On Sun, 12 Feb 2006 01:14:51 +0700, "Roman Mashak" <mr*@tusur.ru>
wrote:
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[i])) {
strcpy(cli->command, token);
cli->cmd_handler = ftable[i];
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[i] 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
Feb 12 '06 #12
On Sun, 12 Feb 2006 12:33:22 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

; 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;
}

Feb 12 '06 #13
On Mon, 13 Feb 2006 00:16:32 +0100, in comp.lang.c , RSoIsCaIrLiIoA
<zz@zz.z> wrote:
On Sun, 12 Feb 2006 12:33:22 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

; 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
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Feb 13 '06 #14
In article <h3********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.net> wrote:
On Mon, 13 Feb 2006 00:16:32 +0100, in comp.lang.c , RSoIsCaIrLiIoA
<zz@zz.z> wrote:
On Sun, 12 Feb 2006 12:33:22 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

; nasmw -f obj this_file.asm
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.
*plonk*


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

Feb 13 '06 #15
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: mr*@tusur.ru
Feb 13 '06 #16
"Roman Mashak" <mr*@tusur.ru> writes:
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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 13 '06 #17
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: mr*@tusur.ru
Feb 13 '06 #18
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: mr*@tusur.ru
Feb 13 '06 #19
"Roman Mashak" <mr*@tusur.ru> writes:
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>

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 13 '06 #20
Hello, Barry!
You wrote on Sun, 12 Feb 2006 11:08:48 -0800:

Thank you very much for useful tips.

[skip]
BS> But you are inconsistent. You actually copy the command but only
BS> store the argument addresses. What about the command is so special
BS> that you need to store the actual characters in cli->command rather
BS> than simply the address of the command in buf?
??>> while (1) {
??>> printf("%s", PROMPT);

BS> 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')

BS> Look up the isspace() function if you really want to do this. Are you
BS> sure you want to do this since the strtoken call in
BS> cliParseCommandLine() will very happily skip over leading white space
BS> for you?
Actually true, but my intention was to skip input consisting only of '\t',
'\n', ' ' and '\r'. That's isspace() is much better here.

With best regards, Roman Mashak. E-mail: mr*@tusur.ru
Feb 13 '06 #21
Rod Pemberton wrote:
"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds***********@relay.tomsk.ru...
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:


the OP code was

/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' ||
buf[0]
== '\t')
I would change this line, extra spaces deleted:
why remove the space, is that to reduce clarity or just for posting
purposes?
if (buf[0]=='\n'||buf[0]==' '||buf[0]=='\r'||buf[0]=='\t')


how is this different from the OP's code?
To this, to specifically catch an ASCII carriage return and newline:
if buf[0]==0x0A||buf[0]==0x0D||buf[0]==' '||buf[0]=='\t')
why? How do you know he's using ASCII? Your code is *less* clear
than the original! Why don't you replace ' ' and \t with hex values?
<rant> they were writing programming guides in '50's explaining why
this was a bad idea! <end rant>

ok, I exagerate... a little.
Or, to this:
if (strtok(buf,"\x0D\x0A\t ")==NULL)


or strchr()

<snip>

--
Nick Keighley

The Elements of Programming Style (Paperback)
by Brian W. Kernighan, P. J. Plauger

ok so it was 1978... only 30 years ago

Feb 13 '06 #22

"Nick Keighley" <ni******************@hotmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
Rod Pemberton wrote:
"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds***********@relay.tomsk.ru...
Hello, Rod!
Sorry I made typo in first post, right definition of "cmdLineEntry_t" is: Some suggestions:


the OP code was

/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' ||
buf[0]
== '\t')
I would change this line, extra spaces deleted:


why remove the space, is that to reduce clarity or just for posting
purposes?


I was just letting him know I had removed the spaces and he needed to locate
the same line in his program. Nothing more.
if (buf[0]=='\n'||buf[0]==' '||buf[0]=='\r'||buf[0]=='\t')
how is this different from the OP's code?


It isn't. It's his line. It's the line he needs to locate, with spaces, to
implement the following suggestion.
To this, to specifically catch an ASCII carriage return and newline:
if buf[0]==0x0A||buf[0]==0x0D||buf[0]==' '||buf[0]=='\t')


why?


Because '\r' and '\n' map to environment specific values. Those values may
not match his character set creating an unexpected result. '\n' can map to
many things. For Windows and DOS machines using ASCII, it usually maps to
0x0D 0x0A. For Linux, Unix, Posix using ASCII, it usually maps to 0x0A.
For Macintoshes using ASCII, it maps to 0x0D. For IBM mainframes using
EBCDIC, it maps to 0x15.
How do you know he's using ASCII?
I don't. But, to show him how to correctly code for the hexadecimal
sequences, I used ASCII as noted.
Your code is *less* clear
than the original!
Yes, but it corrects a common programming error: trapping C's value for '\r'
or '\n' instead of the character generated by the keyboard.
Why don't you replace ' ' and \t with hex values?
Because they don't cause problems as noted above.
<rant> they were writing programming guides in '50's explaining why
this was a bad idea! <end rant>


Does the code created by following the style guide work correctly for a
specific environment? Or, does it generate errors?
Or, to this:
if (strtok(buf,"\x0D\x0A\t ")==NULL)


or strchr()


strchr() will only allow him to check for one char at a time. strtok() will
do all at once. He'll need to test to see if it's faster or slower than the
multiple if's.

Rod Pemberton
Feb 13 '06 #23
On 2006-02-13, Rod Pemberton <do*********@sorry.bitbucket.cmm> wrote:

"Nick Keighley" <ni******************@hotmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
Rod Pemberton wrote:
> "Roman Mashak" <mr*@tusur.ru> wrote in message
> news:ds***********@relay.tomsk.ru...
> > Hello, Rod!
> > Sorry I made typo in first post, right definition of "cmdLineEntry_t" is: > >
> Some suggestions:
the OP code was

/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' ||
buf[0]
== '\t')
> I would change this line, extra spaces deleted:


why remove the space, is that to reduce clarity or just for posting
purposes?


I was just letting him know I had removed the spaces and he needed to locate
the same line in his program. Nothing more.
> > if (buf[0]=='\n'||buf[0]==' '||buf[0]=='\r'||buf[0]=='\t')


how is this different from the OP's code?


It isn't. It's his line. It's the line he needs to locate, with spaces, to
implement the following suggestion.
> To this, to specifically catch an ASCII carriage return and newline:
> if buf[0]==0x0A||buf[0]==0x0D||buf[0]==' '||buf[0]=='\t')


why?


Because '\r' and '\n' map to environment specific values. Those values may
not match his character set creating an unexpected result. '\n' can map to
many things. For Windows and DOS machines using ASCII, it usually maps to
0x0D 0x0A.


Yes, on text file output. No, anywhere else. '\n' does not map to a pair
of two character values. It may be returned by getchar when getchar sees
those two values, but nowhere else.
For Linux, Unix, Posix using ASCII, it usually maps to 0x0A. For Macintoshes using ASCII, it maps to 0x0D.
I doubt that [other than reading/writing to files opened in text mode as
noted above.]
For IBM mainframes using EBCDIC, it maps to 0x15.
Bullshit, as noted below.
How do you know he's using ASCII?


I don't. But, to show him how to correctly code for the hexadecimal
sequences, I used ASCII as noted.
Your code is *less* clear
than the original!


Yes, but it corrects a common programming error: trapping C's value for '\r'
or '\n' instead of the character generated by the keyboard.
Why don't you replace ' ' and \t with hex values?


Because they don't cause problems as noted above.


They do on "IBM mainframes using EBCDIC".
<rant> they were writing programming guides in '50's explaining why
this was a bad idea! <end rant>


Does the code created by following the style guide work correctly for a
specific environment? Or, does it generate errors?
> Or, to this:
> if (strtok(buf,"\x0D\x0A\t ")==NULL)


or strchr()


strchr() will only allow him to check for one char at a time. strtok() will
do all at once. He'll need to test to see if it's faster or slower than the
multiple if's.


strpbrk(), then. strtok is evil for other reasons.


note: on ANY ascii-based system, \r is 13 and \n is 10. NO MATTER HOW
the system represents linebreaks in text files or as a keyboard code.

Also - reading from stdin - whenever the user presses enter, that will
appear to getchar() or fgets() or whatever else is used to read it as
'\n', regardless of whether the enter key actually sends 0x0D or 42 or
396.
Feb 13 '06 #24
On Sun, 12 Feb 2006 09:55:42 -0500, "Rod Pemberton"
<do*********@sorry.bitbucket.cmm> wrote:

"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds***********@relay.tomsk.ru...
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')


Why be inconsistent? Use 0x20 for ' ' and 0x09 for '\t'

Why assume the program is executed on an ASCII system? \n and \r are
guaranteed to work on all systems.

Remove del for email
Feb 14 '06 #25
On Mon, 13 Feb 2006 00:16:32 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:
On Sun, 12 Feb 2006 12:33:22 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

; 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(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);
}
last=0;
}
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=0, aa2=0;
sscanf(a1, "%d", &aa1);
sscanf(a2, "%d", &aa2);
printf("%d\n", aa1+aa2);
}

void sub(char* a1, char* a2)
{int aa1=0, aa2=0;
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:
break;
}
}
}
}
return 0;
}

Feb 17 '06 #26
#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;
char* descrizione;
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, char*
descrizione)
{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(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;
tm->descrizione = descrizione;
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);
}
last=0;
}
void show(void){puts("cliShow() stub"); }
void version(void){puts("cliVersion() stub");}
void help(void)
{U i;
struct you *p=last, *v;
puts("Comandi(parametri)");
while(1) {if(p==0) break;
v=p; p=p->prev;
printf("%s(%u): %s\n",
v->name, v->npar, v->descrizione);
}
}

void port(void){puts("cliPort() stub");}
void vexit(void)
{puts("cliExit() stub");
free_list();
exit(0);
}

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

void sub(char* a1, char* a2)
{int aa1=0, aa2=0;
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, "mostra etc");
inserisci("version", (char*) version, 0, "mostra versione");
inserisci("help", (char*) help, 0, "help");
inserisci("h", (char*) help, 0, "help");
inserisci("-h", (char*) help, 0, "help");
inserisci("port", (char*) port, 0, "port");
inserisci("vexit",(char*) vexit, 0, "esce dal sistema");
inserisci("add",(char*) add, 2, "somma due numeri");
inserisci("sub",(char*) sub, 2, "fa differenza di due numeri");

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:
break;
}
}
}
}
return 0;
}
Feb 17 '06 #27
On Fri, 17 Feb 2006 09:47:16 +0100, in comp.lang.c , RSoIsCaIrLiIoA
<zz@zz.z> wrote:

#define UC unsigned char
#define U unsigned


you are so killfiled its not true.
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Feb 17 '06 #28
On Fri, 17 Feb 2006 21:19:05 +0000, Mark McIntyre
<ma**********@spamcop.net> wrote:
On Fri, 17 Feb 2006 09:47:16 +0100, in comp.lang.c , RSoIsCaIrLiIoA
<zz@zz.z> wrote:

#define UC unsigned char
#define U unsigned
you are so killfiled its not true.
Mark McIntyre


what does it means?
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan


this above means do you see any error?

Feb 18 '06 #29
#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;
char* descrizione;
unsigned npar;
struct you* prev;
};

struct you *last=0;

/*limit sono i parametri + 1 (nome della funzione) */
int popola(char** v, char* buf, int limit);

void skip_line(FILE* pf)
{int c; while( (c=fgetc(pf))!='\n' && c!=EOF );}

int
inserisci(const char* name, char* pointer, U par, char*
descrizione)
{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(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;
tm->descrizione = descrizione;
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);
}
last=0;
}
void
insert_f(char* name, char* pointer, char* par, char* descrizione)
{char *pn=0;
U paru=0;
int k;

k=sscanf(pointer, "%p", &pn);
if(k!=1) {printf("parametro \"pointer\" non accettato\n"); return;}
k=sscanf(par , "%u", &paru);
if(k!=1) {printf("parametro \"parametri\" non accettato\n"); return;}
k=inserisci(name, pn, paru, descrizione);
if(k!=1){printf("problemi di memoria\n"); return;}
}

void show(void){puts("cliShow() stub"); }
void version(void){puts("cliVersion() stub");}
void help(void)
{U i;
struct you *p=last, *v;
puts("Comandi(parametri)");
while(1) {if(p==0) break;
v=p; p=p->prev;
printf("%p %s(%u): %s\n",
(void*)(v->pointer), v->name, v->npar, v->descrizione);
}
}

void port(void){puts("cliPort() stub");}
void vexit(void)
{puts("cliExit() stub");
free_list();
exit(0);
}

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

void sub(char* a1, char* a2)
{int aa1=0, aa2=0;
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, led;
/////////////////////////////////
inserisci("show",(char*) show, 0, "mostra etc");
inserisci("version", (char*) version, 0, "mostra versione");
inserisci("help", (char*) help, 0, "help");
inserisci("h", (char*) help, 0, "help");
inserisci("-h", (char*) help, 0, "help");
inserisci("port", (char*) port, 0, "port");
inserisci("vexit",(char*) vexit, 0, "esce dal sistema");
inserisci("add",(char*) add, 2, "somma due numeri");
inserisci("sub",(char*) sub, 2, "fa differenza di due numeri");
inserisci("inserisci",(char*) insert_f, 4,
"inserisce una funzione:\ninserisci(name, pointer_to_fun,
parametri, descrizione)");

la:;
while (1)
{printf("%s", pc); fflush(stdout);
buf[BUFSIZ-2]=0; /* massimo BUFSIZ-2 chars */
if( fgets(buf, BUFSIZ, stdin )!=0 )
{if(buf[BUFSIZ-2]!=0)
{printf("Linea troppo lunga\n");
if(feof(stdin)) vexit();
skip_line(stdin);
if(feof(stdin)) vexit();
goto la;
}
cv=popola(a, buf, 8);
if(cv<=0 || cv>8) goto la1;
else --cv;
for(p=last, led=0; led==0 && p!=0 ;p=p->prev)
{if(strcmp(p->name, a[0])==0)
{if(p->npar!=(U)cv)
{la1:; printf("Parametri non corretti\n"); goto la;}
switch(p->npar)
{case 0:
( (void (*)(void))(p->pointer) )( );
led=1;
break;
case 1:
( (void (*)(char*))(p->pointer) )(a[1]);
led=1;
break;
case 2:
( (void (*)(char*, char*))(p->pointer) )
(a[1], a[2]);
led=1;
break;
case 3:
( (void (*)(char*, char*, char*))(p->pointer) )
(a[1], a[2], a[3]);
led=1;
break;
case 4:
( (void (*)(char*, char*, char*, char*) )
(p->pointer) ) (a[1], a[2], a[3], a[4]);
led=1;
break;
case 5:
( (void (*)(char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5]);
led=1;
break;
case 6:
( (void (*)(char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6]);
led=1;
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]);
led=1;
break;
default:
break;
}//end switch
}//if
}//for
if(led!=1) printf("funzione non presente\n");
}// if fgets
if(feof(stdin)) vexit();
}//while
return 0;
}

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

; nasmw -f obj this_file.asm
; bcc32 this_file.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
mov edi, -1
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
Feb 19 '06 #30
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define UC unsigned char
#define U unsigned

#define BUFSIZ_ BUFSIZ

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

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

struct you *last=0;

/*limit sono i parametri + 1 (nome della funzione) */
int popola(char** v, char* buf, int limit);

void skip_line(FILE* pf)
{int c; while( (c=fgetc(pf))!='\n' && c!=EOF );}

int cerca(const char* name, U par)
{U i;
struct you *p=last, *v;
while(1) {if(p==0) break;
v=p; p=p->prev;
if( v->npar==par && strcmp(v->name, name)==0 )
return 1;
}
return 0;
}

int
inserisci(const char* name, char* pointer, U par, char*
descrizione)
{struct you *tm;
char *tmp;
unsigned sz;
///////////////////
if( name==0 || (sz=strlen(name))==0 )
return 0;
if( cerca(name, par)==1 )
return 0;
if( (tm =malloc(sizeof(struct you)))==0 )
return 0;
if( (tmp=malloc(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;
tm->descrizione = descrizione;
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);
}
last=0;
}
void
insert_f(char* name, char* pointer, char* par, char* descrizione)
{char *pn=0;
U paru=0;
int k;

k=sscanf(pointer, "%p", &pn);
if(k!=1) {printf("parametro \"pointer\" non accettato\n"); return;}
k=sscanf(par , "%u", &paru);
if(k!=1) {printf("parametro \"parametri\" non accettato\n"); return;}
k=inserisci(name, pn, paru, descrizione);
if(k!=1){printf("problemi di memoria o nome gia\' scelto\n");
return;
}
}

void show(void){puts("cliShow() stub"); }
void version(void){puts("cliVersion() stub");}
void help(void)
{U i;
struct you *p=last, *v;
puts("Comandi(parametri)");
while(1) {if(p==0) break;
v=p; p=p->prev;
printf("%p %s(%u): %s\n",
(void*)(v->pointer), v->name, v->npar, v->descrizione);
}
}

void port(void){puts("cliPort() stub");}
void vexit(void)
{puts("cliExit() stub");
free_list();
exit(0);
}

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

void sub(char* a1, char* a2)
{int aa1=0, aa2=0;
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, led;
/////////////////////////////////
inserisci("show",(char*) show, 0, "mostra etc");
inserisci("version", (char*) version, 0, "mostra versione");
inserisci("help", (char*) help, 0, "help");
inserisci("h", (char*) help, 0, "help");
inserisci("-h", (char*) help, 0, "help");
inserisci("port", (char*) port, 0, "port");
inserisci("vexit",(char*) vexit, 0, "esce dal sistema");
inserisci("add",(char*) add, 2, "somma due numeri");
inserisci("sub",(char*) sub, 2, "fa differenza di due numeri");
inserisci("inserisci",(char*) insert_f, 4,
"inserisce una funzione:\ninserisci(name, pointer_to_fun,
parametri, descrizione)");

la:;
while (1)
{printf("%s", pc); fflush(stdout);
buf[BUFSIZ_-2]=0; /* massimo BUFSIZ_-1 chars */
if( fgets(buf, BUFSIZ_, stdin )!=0 )
{if(buf[BUFSIZ_-2]!=0 && buf[BUFSIZ_-2]!='\n')
{printf("Linea troppo lunga\n");
if(feof(stdin)) vexit();
skip_line(stdin);
if(feof(stdin)) vexit();
goto la;
}
cv=popola(a, buf, 8);
if(cv<=0 || cv>8) goto la1;
else --cv;
for(p=last, led=0; led==0 && p!=0 ;p=p->prev)
{if(strcmp(p->name, a[0])==0)
{if(p->npar!=(U)cv)
{la1:; printf("Parametri non corretti\n"); goto la;}
switch(p->npar)
{case 0:
( (void (*)(void))(p->pointer) )( );
led=1;
break;
case 1:
( (void (*)(char*))(p->pointer) )(a[1]);
led=1;
break;
case 2:
( (void (*)(char*, char*))(p->pointer) )
(a[1], a[2]);
led=1;
break;
case 3:
( (void (*)(char*, char*, char*))(p->pointer) )
(a[1], a[2], a[3]);
led=1;
break;
case 4:
( (void (*)(char*, char*, char*, char*) )
(p->pointer) ) (a[1], a[2], a[3], a[4]);
led=1;
break;
case 5:
( (void (*)(char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5]);
led=1;
break;
case 6:
( (void (*)(char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6]);
led=1;
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]);
led=1;
break;
default:
break;
}//end switch
}//if
}//for
if(led!=1) printf("funzione non presente\n");
}// if fgets
if(feof(stdin)) vexit();
}//while
return 0;
}
Feb 19 '06 #31
On Mon, 13 Feb 2006 10:57:06 -0500, "Rod Pemberton"
<do*********@sorry.bitbucket.cmm> wrote:

"Nick Keighley" <ni******************@hotmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...

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


why?


Because '\r' and '\n' map to environment specific values. Those values may
not match his character set creating an unexpected result. '\n' can map to
many things. For Windows and DOS machines using ASCII, it usually maps to
0x0D 0x0A. For Linux, Unix, Posix using ASCII, it usually maps to 0x0A.
For Macintoshes using ASCII, it maps to 0x0D. For IBM mainframes using
EBCDIC, it maps to 0x15.

Well, they certainly match the platform's character set (or more
precisely code), that's the purpose of the mapping. I think you're
saying his _data_ may not match his platform. Which is possible,
although it is possible in so many ways it's not clear to me that
fixing only this one is worth it.
Why don't you replace ' ' and \t with hex values?


Because they don't cause problems as noted above.

They are different and do cause this problem for EBCDIC vs ASCII,
whereas CR by coincidence is 0x0D in both and does not.
Or, to this:
if (strtok(buf,"\x0D\x0A\t ")==NULL)


or strchr()


strchr() will only allow him to check for one char at a time. strtok() will
do all at once. He'll need to test to see if it's faster or slower than the
multiple if's.

And strspn() does it all at once without modifying the data, if that's
an issue, although in this (OP) case he definitely has a modifiable
buffer and AFAICS doesn't need the data afterwards.

Agree about testing, although in this case I very much doubt the
difference is even detectable much less significant.

- David.Thompson1 at worldnet.att.net
Feb 20 '06 #32

do you like my CLI (Command Line Interface)? :))

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define UC unsigned char
#define U unsigned

#define BUFSIZ_ BUFSIZ

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

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

struct you *last=0;

/*limit sono i parametri + 1 (nome della funzione) */
int popola(char** v, char* buf, int limit);

int skip_line(FILE* pf)
{int c; while( (c=fgetc(pf))!='\n' && c!=EOF ); return c;}

int cmp_from_now(char* a0, char* a1)
{int i;
for( i=0; a0[i]!=0 && a0[i]==a1[i] && !isspace(a0[i]); ++i);
if( (isspace(a0[i])||a0[i]==0) && (isspace(a1[i])||a1[i]==0))
return 1;
else return 0;
}

int cerca(const char* name, U par)
{U i;
struct you *p=last, *v;
while(1) {if(p==0) break;
v=p; p=p->prev;
if( v->npar==par && strcmp(v->name, name)==0 )
return 1;
}
return 0;
}

int
inserisci(const char* name, char* pointer, U par, char*
descrizione)
{struct you *tm;
char *tmp;
unsigned sz;
///////////////////
if( name==0 || (sz=strlen(name))==0 )
return 0;
if( cerca(name, par)==1 )
return 0;
if( (tm =malloc(sizeof(struct you)))==0 )
return 0;
if( (tmp=malloc(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;
tm->descrizione = descrizione;
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);
}
last=0;
}
void
insert_f(char* name, char* pointer, char* par, char* descrizione)
{char *pn=0;
U paru=0;
int k;

k=sscanf(pointer, "%p", &pn);
if(k!=1) {printf("parametro \"pointer\" non accettato\n"); return;}
k=sscanf(par , "%u", &paru);
if(k!=1) {printf("parametro \"parametri\" non accettato\n"); return;}
k=inserisci(name, pn, paru, descrizione);
if(k!=1){printf("problemi di memoria\n"); return;}
}
void sys(char* a1){if( system(a1)!=0 ) printf("\a"); }
void show(void){puts("cliShow() stub"); }
void version(void){puts("cliVersion() stub");}
void help(void)
{U i;
struct you *p=last, *v;
puts("Comandi(parametri)");
while(1) {if(p==0) break;
v=p; p=p->prev;
printf("%p %s(%u): %s\n",
(void*)(v->pointer), v->name, v->npar, v->descrizione);
}
}

void port(void){puts("cliPort() stub");}
void vexit(void)
{puts("cliExit() stub");
free_list();
exit(0);
}

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

void sub(char* a1, char* a2)
{int aa1=0, aa2=0;
sscanf(a1, "%d", &aa1);
sscanf(a2, "%d", &aa2);
printf("%d\n", aa1-aa2);
}
int main(void)
{char buf[BUFSIZ_] = {0}, *a[32], *pc;
struct you *p;
int cv, led;
/////////////////////////////////
inserisci("sys",(char*) sys, 1, "chiama sistema");
inserisci("show",(char*) show, 0, "mostra etc");
inserisci("version", (char*) version, 0, "mostra versione");
inserisci("help", (char*) help, 0, "help");
inserisci("h", (char*) help, 0, "help");
inserisci("-h", (char*) help, 0, "help");
inserisci("port", (char*) port, 0, "port");
inserisci("vexit",(char*) vexit, 0, "esce dal sistema");
inserisci("add",(char*) add, 2, "somma due numeri");
inserisci("sub",(char*) sub, 2, "fa differenza di due numeri");
inserisci("inserisci",(char*) insert_f, 4,
"inserisce una funzione:\ninserisci(name, pointer_to_fun,
parametri, descrizione)");

la:;
while (1)
{printf("%s", pc_pro); fflush(stdout);
buf[BUFSIZ_-2]=0; /* massimo BUFSIZ_-1 chars */
if( fgets(buf, BUFSIZ_, stdin )!=0 )
{if(buf[BUFSIZ_-2]!=0 && buf[BUFSIZ_-2]!='\n')
{printf("Linea troppo lunga\n");
if(feof(stdin)) vexit();
if( skip_line(stdin) == EOF );
vexit();
goto la;
}
for(pc=buf; isspace(*pc); ++pc);
if( cmp_from_now(pc, "sys")==1 )
{if(pc[3]==0) sys("\n");
else sys(pc+4);
goto la;
}
cv=popola(a, buf, 8);
if(cv<=0 || cv>8) goto la1;
else --cv;
for(p=last, led=0; led==0 && p!=0 ;p=p->prev)
{if(strcmp(p->name, a[0])==0)
{if(p->npar!=(U)cv)
{la1:; printf("Parametri non corretti\n"); goto la;}
switch(p->npar)
{case 0:
( (void (*)(void))(p->pointer) )( );
led=1;
break;
case 1:
( (void (*)(char*))(p->pointer) )(a[1]);
led=1;
break;
case 2:
( (void (*)(char*, char*))(p->pointer) )
(a[1], a[2]);
led=1;
break;
case 3:
( (void (*)(char*, char*, char*))(p->pointer) )
(a[1], a[2], a[3]);
led=1;
break;
case 4:
( (void (*)(char*, char*, char*, char*) )
(p->pointer) ) (a[1], a[2], a[3], a[4]);
led=1;
break;
case 5:
( (void (*)(char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5]);
led=1;
break;
case 6:
( (void (*)(char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6]);
led=1;
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]);
led=1;
break;
default:
break;
}//end switch
}//if
}//for
if(led!=1) printf("funzione non presente\n");
}// if fgets
if(feof(stdin)) vexit();
}//while
return 0;
}
Feb 20 '06 #33
On Mon, 20 Feb 2006 09:44:40 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

do you like my CLI (Command Line Interface)? :))

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


int main(void)
{char buf[BUFSIZ_] = {0}, *a[32], *pc;
struct you *p;
int cv, led;
/////////////////////////////////
inserisci("sys",(char*) sys, 1, "chiama sistema");
inserisci("show",(char*) show, 0, "mostra etc");
inserisci("version", (char*) version, 0, "mostra versione");
inserisci("help", (char*) help, 0, "help");
inserisci("h", (char*) help, 0, "help");
inserisci("-h", (char*) help, 0, "help");
inserisci("port", (char*) port, 0, "port");
inserisci("vexit",(char*) vexit, 0, "esce dal sistema");
inserisci("add",(char*) add, 2, "somma due numeri");
inserisci("sub",(char*) sub, 2, "fa differenza di due numeri");
inserisci("inserisci",(char*) insert_f, 4,
"inserisce una funzione:\ninserisci(name, pointer_to_fun,
parametri, descrizione)");

la:;
while (1)
{printf("%s", pc_pro); fflush(stdout);
buf[BUFSIZ_-2]=0; /* massimo BUFSIZ_-1 chars */
if( fgets(buf, BUFSIZ_, stdin )!=0 )
{if(buf[BUFSIZ_-2]!=0 && buf[BUFSIZ_-2]!='\n')
{printf("Linea troppo lunga\n");
if(feof(stdin)) vexit();
if( skip_line(stdin) == EOF );
vexit();
goto la;
}
for(pc=buf; isspace(*pc); ++pc);
if( cmp_from_now(pc, "sys")==1 )
{if(pc[3]==0) sys("\n");
else sys(pc+4);
if(feof(stdin)) vexit();
goto la;
}
cv=popola(a, buf, 8);
if(cv<=0 || cv>8) goto la1;
else --cv;
for(p=last, led=0; led==0 && p!=0 ;p=p->prev)
{if(strcmp(p->name, a[0])==0)
{if(p->npar!=(U)cv)
{la1:; printf("Parametri non corretti\n"); goto la;}
switch(p->npar)
{case 0:
( (void (*)(void))(p->pointer) )( );
led=1;
break;
case 1:
( (void (*)(char*))(p->pointer) )(a[1]);
led=1;
break;
case 2:
( (void (*)(char*, char*))(p->pointer) )
(a[1], a[2]);
led=1;
break;
case 3:
( (void (*)(char*, char*, char*))(p->pointer) )
(a[1], a[2], a[3]);
led=1;
break;
case 4:
( (void (*)(char*, char*, char*, char*) )
(p->pointer) ) (a[1], a[2], a[3], a[4]);
led=1;
break;
case 5:
( (void (*)(char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5]);
led=1;
break;
case 6:
( (void (*)(char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6]);
led=1;
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]);
led=1;
break;
default:
break;
}//end switch
}//if
}//for
if(led!=1) printf("funzione non presente\n");
}// if fgets
if(feof(stdin)) vexit();
}//while
return 0;
}


Feb 20 '06 #34

Do you like my Command Line Interface?
your is better than this? Why?

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

#define UC unsigned char
#define U unsigned

#define BUFSIZ_ BUFSIZ

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

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

struct you *last=0;

/*limit sono i parametri + 1 (nome della funzione) */
int popola(char** v, char* buf, int limit);

int skip_line(FILE* pf)
{int c; while( (c=fgetc(pf))!='\n' && c!=EOF ); return c;}

int cmp_from_now(char* a0, char* a1)
{int i;
for( i=0; a0[i]!=0 && a0[i]==a1[i] && !isspace(a0[i]); ++i);
if( (isspace(a0[i])||a0[i]==0) && (isspace(a1[i])||a1[i]==0))
return 1;
else return 0;
}

int cerca(const char* name, U par)
{U i;
struct you *p=last, *v;
while(1) {if(p==0) break;
v=p; p=p->prev;
if( v->npar==par && strcmp(v->name, name)==0 )
return 1;
}
return 0;
}

int
inserisci(const char* name, char* pointer, U par, char*
descrizione)
{struct you *tm;
char *tmp;
unsigned sz;
///////////////////
if( name==0 || (sz=strlen(name))==0 )
return 0;
if( cerca(name, par)==1 )
return 0;
if( (tm =malloc(sizeof(struct you)))==0 )
return 0;
if( (tmp=malloc(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;
tm->descrizione = descrizione;
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);
}
last=0;
}
void
insert_f(char* name, char* pointer, char* par, char* descrizione)
{char *pn=0;
U paru=0;
int k;

k=sscanf(pointer, "%p", &pn);
if(k!=1) {printf("parametro \"pointer\" non accettato\n"); return;}
k=sscanf(par , "%u", &paru);
if(k!=1) {printf("parametro \"parametri\" non accettato\n"); return;}
k=inserisci(name, pn, paru, descrizione);
if(k!=1){printf("problemi di memoria\n"); return;}
}
void sys(char* a1){if( system(a1)!=0 ) printf("\a"); }
void show(void){puts("cliShow() stub"); }
void version(void){puts("cliVersion() stub");}
void help(void)
{U i;
struct you *p=last, *v;
puts("Comandi(parametri)");
while(1) {if(p==0) break;
v=p; p=p->prev;
printf("%p %s(%u): %s\n",
(void*)(v->pointer), v->name, v->npar, v->descrizione);
}
}

void port(void){puts("cliPort() stub");}
void vexit(void)
{puts("cliExit() stub");
free_list();
exit(0);
}

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

void sub(char* a1, char* a2)
{int aa1=0, aa2=0;
sscanf(a1, "%d", &aa1);
sscanf(a2, "%d", &aa2);
printf("%d\n", aa1-aa2);
}
int main(void)
{char buf[BUFSIZ_] = {0}, *a[32], *pc;
struct you *p;
int cv, led;
/////////////////////////////////
inserisci("sys",(char*) sys, 1, "chiama sistema");
inserisci("show",(char*) show, 0, "mostra etc");
inserisci("version", (char*) version, 0, "mostra versione");
inserisci("help", (char*) help, 0, "help");
inserisci("h", (char*) help, 0, "help");
inserisci("-h", (char*) help, 0, "help");
inserisci("port", (char*) port, 0, "port");
inserisci("vexit",(char*) vexit, 0, "esce dal sistema");
inserisci("add",(char*) add, 2, "somma due numeri");
inserisci("sub",(char*) sub, 2, "fa differenza di due numeri");
inserisci("inserisci",(char*) insert_f, 4,
"inserisce una funzione:\ninserisci(name, pointer_to_fun,
parametri, descrizione)");

la0:;
while (1)
{printf("%s", pc_pro); fflush(stdout);
buf[BUFSIZ_-2]=0; /* massimo BUFSIZ_-1 chars */
if( fgets(buf, BUFSIZ_, stdin )!=0 )
{if(buf[BUFSIZ_-2]!=0 && buf[BUFSIZ_-2]!='\n')
{printf("Linea troppo lunga\n");
if(feof(stdin)) vexit();
if( skip_line(stdin) == EOF );
vexit();
goto la0;
}
for(pc=buf; isspace(*pc); ++pc);
if( cmp_from_now(pc, "sys")==1 )
{if(pc[3]==0) sys("\n");
else sys(pc+4);
goto la;
}
cv=popola(a, buf, 8);
if(cv<=0 || cv>8) goto la1;
else --cv;
for(p=last, led=0; led==0 && p!=0 ;p=p->prev)
{if(strcmp(p->name, a[0])==0)
{if(p->npar!=(U)cv)
{la1:;
printf("Parametri non corretti\n"); goto la;
}
switch(p->npar)
{case 0:
( (void (*)(void))(p->pointer) )( );
led=1;
break;
case 1:
( (void (*)(char*))(p->pointer) )(a[1]);
led=1;
break;
case 2:
( (void (*)(char*, char*))(p->pointer) )
(a[1], a[2]);
led=1;
break;
case 3:
( (void (*)(char*, char*, char*))(p->pointer) )
(a[1], a[2], a[3]);
led=1;
break;
case 4:
( (void (*)(char*, char*, char*, char*) )
(p->pointer) ) (a[1], a[2], a[3], a[4]);
led=1;
break;
case 5:
( (void (*)(char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5]);
led=1;
break;
case 6:
( (void (*)(char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6]);
led=1;
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]);
led=1;
break;
default:
break;
}//end switch
}//if
}//for
if(led!=1) printf("funzione non presente\n");
}// if fgets
la:;
if(feof(stdin)) vexit();
}//while
return 0;
}

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

; nasmw -f obj this_file.asm
; bcc32 this_file.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
mov edi, -1
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
Feb 20 '06 #35

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: djc | last post by:
I'm new to this and was wondering what the options are for interpreting the command line using a CLI program. Specifically methods for interpreting the parameters passed to the program on the...
51
by: Ojas | last post by:
Hi!, I just out of curiosity want to know how top detect the client side application under which the script is getting run. I mean to ask the how to know whether the script is running under...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.