Paths expansion working(ish), to be integrated into the shell.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15448 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2022-02-08 13:14:41 +00:00
parent d226497cc2
commit 9857f97478
3 changed files with 122 additions and 49 deletions

View File

@ -22,6 +22,8 @@
#include "sbuser.h" #include "sbuser.h"
#include "paths.h" #include "paths.h"
#include "sglob.h"
#define SHELL_MAX_LINE_LENGTH 128 #define SHELL_MAX_LINE_LENGTH 128
#define SHELL_MAX_ARGUMENTS 20 #define SHELL_MAX_ARGUMENTS 20
#define SHELL_PROMPT_STR "> " #define SHELL_PROMPT_STR "> "
@ -162,6 +164,48 @@ static void cmd_pwd(int argc, char *argv[]) {
} }
} }
static void cmd_echo(int argc, char *argv[]) {
int i, ret;
sglob_t sglob;
(void)argv;
if (argc != 2) {
shell_usage("echo <string>");
return;
}
sglob_init(&sglob, 0);
ret = sglob_add(&sglob, argv[1]);
if (ret != 0) {
sglob_free(&sglob);
shell_error("echo: out of memory" SHELL_NEWLINE_STR);
return;
}
ret = sglob_build(&sglob);
switch (ret) {
case SGLOB_NOMATCH:
sglob_free(&sglob);
shell_write(argv[1]);
shell_write(SHELL_NEWLINE_STR);
return;
case SGLOB_NOSPACE:
sglob_free(&sglob);
shell_error("echo: out of memory" SHELL_NEWLINE_STR);
return;
}
for (i = 0; i < sglob.sgl_pathc; i++) {
shell_write(sglob.sgl_pathv[i]);
shell_write(" ");
shell_write(SHELL_NEWLINE_STR);
}
sglob_free(&sglob);
}
static void cmd_env(int argc, char *argv[]) { static void cmd_env(int argc, char *argv[]) {
extern char **environ; extern char **environ;
char **pp; char **pp;
@ -284,6 +328,7 @@ static bool shell_execute(int argc, char *argv[]) {
void (*cmdf)(int argc, char *argv[]); void (*cmdf)(int argc, char *argv[]);
} builtins[] = { } builtins[] = {
{"cd", cmd_cd}, {"cd", cmd_cd},
{"echo", cmd_echo},
{"env", cmd_env}, {"env", cmd_env},
{"exit", cmd_exit}, {"exit", cmd_exit},
{"mkdir", cmd_mkdir}, {"mkdir", cmd_mkdir},

View File

@ -74,8 +74,8 @@ static char *lsalloc(sglob_t *psglob, size_t len) {
lsp = malloc(len + sizeof (lstring_t)); lsp = malloc(len + sizeof (lstring_t));
if (lsp != NULL) { if (lsp != NULL) {
lsp->next = psglob->gl_next; lsp->next = psglob->sgl_next;
psglob->gl_next = lsp; psglob->sgl_next = lsp;
} }
return lsp->string; return lsp->string;
@ -105,32 +105,19 @@ bool match(const char *pattern, const char *text) {
void sglob_init(sglob_t *psglob, size_t offs) { void sglob_init(sglob_t *psglob, size_t offs) {
psglob->gl_offs = offs; psglob->sgl_offs = offs;
psglob->gl_buf = NULL; psglob->sgl_buf = NULL;
psglob->gl_next = NULL; psglob->sgl_next = NULL;
psglob->gl_pathc = 0; psglob->sgl_pathc = 0;
psglob->gl_pathv = NULL; psglob->sgl_pathv = NULL;
} }
void sglob_free(sglob_t *psglob) { int sglob_add(sglob_t *psglob, const char *pattern) {
lstring_t *lsp;
if (psglob->gl_buf != NULL) {
free(psglob->gl_buf);
}
while ((lsp = psglob->gl_next) != NULL) {
psglob->gl_next = lsp->next;
free(lsp);
}
}
int sglob_add(const char *pattern, sglob_t *psglob) {
int ret; int ret;
DIR *dbp; DIR *dbp;
dbp = NULL; dbp = NULL;
ret = GLOB_NOSPACE; ret = SGLOB_NOSPACE;
do { do {
char *lastp, *dirp; char *lastp, *dirp;
size_t plen, dirlen; size_t plen, dirlen;
@ -144,50 +131,49 @@ int sglob_add(const char *pattern, sglob_t *psglob) {
} }
/* Allocating a path buffer if not already done.*/ /* Allocating a path buffer if not already done.*/
if (psglob->gl_buf == NULL) { if (psglob->sgl_buf == NULL) {
psglob->gl_buf = malloc(PATH_MAX); psglob->sgl_buf = malloc(PATH_MAX);
if (psglob->gl_buf == NULL) { if (psglob->sgl_buf == NULL) {
break; break;
} }
} }
/* We need the path pattern in a writable buffer.*/ /* We need the path pattern in a writable buffer.*/
strcpy(psglob->gl_buf, pattern); strcpy(psglob->sgl_buf, pattern);
/* Finding the last element, the one to be expanded.*/ /* Finding the last element, the one to be expanded.*/
lastp = rindex(psglob->gl_buf, '/'); lastp = rindex(psglob->sgl_buf, '/');
if (lastp == NULL) { if (lastp == NULL) {
/* It is all last element.*/ /* It is all last element.*/
lastp = psglob->gl_buf; lastp = psglob->sgl_buf;
dirp = NULL; dirp = NULL;
dirlen = (size_t)0; dirlen = (size_t)0;
} }
else { else {
*lastp++ = '\0'; *lastp++ = '\0';
dirp = psglob->gl_buf; dirp = psglob->sgl_buf;
dirlen = strlen(dirp); dirlen = strlen(dirp);
} }
/* Case with no wildcards.*/ /* Case with no wildcards.*/
no_spec = (bool)((index(lastp, '?') == NULL) && (index(lastp, '*') == NULL)); no_spec = (bool)((index(lastp, '?') == NULL) &&
(index(lastp, '*') == NULL));
if (no_spec) { if (no_spec) {
char *p; char *p;
p = lsalloc(psglob, plen); p = lsalloc(psglob, plen);
if (p != NULL) { if (p != NULL) {
strcpy(p, pattern); strcpy(p, pattern);
// psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc] = p; psglob->sgl_pathc++;
// psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc + 1] = NULL;
psglob->gl_pathc++;
ret = 0; ret = 0;
} }
break; break;
} }
/* Opening the directory part of the path. If it fauls then it is not /* Opening the directory part of the path. If it faults then it is not
reported as an error but an empty sglob is returned, this can be reported as an error but an empty sglob is returned, this can be
detected from outside.*/ detected from outside.*/
dbp = opendir(dirp); dbp = opendir(dirp == NULL ? "." : dirp);
if (dbp == NULL) { if (dbp == NULL) {
ret = 0; ret = 0;
break; break;
@ -208,20 +194,62 @@ int sglob_add(const char *pattern, sglob_t *psglob) {
} }
*p = '\0'; *p = '\0';
if (dirlen > 0) { if (dirlen > 0) {
strcat(p, dirp); strcat(p, dirp); /* TODO Optimize strcat */
strcat(p, "/"); strcat(p, "/");
} }
strcat(p, dp->d_name); strcat(p, dp->d_name);
// psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc] = p; psglob->sgl_pathc++;
// psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc + 1] = NULL;
psglob->gl_pathc++;
} }
closedir(dbp); closedir(dbp);
ret = 0;
} }
while (false); while (false);
return ret; return ret;
} }
int sglob_build(sglob_t *psglob) {
lstring_t *lsp;
int i;
if (psglob->sgl_pathc == 0) {
return SGLOB_NOMATCH;
}
psglob->sgl_pathv = malloc((psglob->sgl_pathc + psglob->sgl_offs + 1) *
sizeof (char *));
if (psglob->sgl_pathv == NULL) {
return SGLOB_NOSPACE;
}
i = psglob->sgl_offs;
lsp = psglob->sgl_next;
while (lsp != NULL) {
psglob->sgl_pathv[i++] = lsp->string;
lsp = lsp->next;
}
psglob->sgl_pathv[i] = NULL;
return 0;
}
void sglob_free(sglob_t *psglob) {
lstring_t *lsp;
if (psglob->sgl_buf != NULL) {
free(psglob->sgl_buf);
}
if (psglob->sgl_pathv != NULL) {
free(psglob->sgl_pathv);
}
while ((lsp = psglob->sgl_next) != NULL) {
psglob->sgl_next = lsp->next;
free(lsp);
}
}
/** @} */ /** @} */

View File

@ -32,9 +32,8 @@
/* Module constants. */ /* Module constants. */
/*===========================================================================*/ /*===========================================================================*/
#define GLOB_NOSPACE 1 #define SGLOB_NOSPACE 1
#define GLOB_ABORTED 2 #define SGLOB_NOMATCH 3
#define GLOB_NOMATCH 3
/*===========================================================================*/ /*===========================================================================*/
/* Module pre-compile time settings. */ /* Module pre-compile time settings. */
@ -54,11 +53,11 @@ typedef struct lstring {
} lstring_t; } lstring_t;
typedef struct { typedef struct {
int gl_offs; int sgl_offs;
lstring_t *gl_next; lstring_t *sgl_next;
char *gl_buf; char *sgl_buf;
int gl_pathc; int sgl_pathc;
char **gl_pathv; char **sgl_pathv;
} sglob_t; } sglob_t;
/*===========================================================================*/ /*===========================================================================*/
@ -73,8 +72,9 @@ typedef struct {
extern "C" { extern "C" {
#endif #endif
void sglob_init(sglob_t *psglob, size_t offs); void sglob_init(sglob_t *psglob, size_t offs);
int sglob_add(const char *pattern, sglob_t *psglob); int sglob_add(sglob_t *psglob, const char *pattern);
void glob_free(sglob_t *psglob); int sglob_build(sglob_t *psglob);
void sglob_free(sglob_t *psglob);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif