summaryrefslogtreecommitdiffstats
path: root/src/image
diff options
context:
space:
mode:
authorMichael Brown2013-07-23 17:49:12 +0200
committerMichael Brown2013-07-25 14:22:43 +0200
commit31f5211035cf0434a1b5043f707ecd2316d4a18c (patch)
tree31e7af8257515dbc9137e2154796adda00f5de0e /src/image
parent[script] Allow initial whitespace on lines containing labels (diff)
downloadipxe-31f5211035cf0434a1b5043f707ecd2316d4a18c.tar.gz
ipxe-31f5211035cf0434a1b5043f707ecd2316d4a18c.tar.xz
ipxe-31f5211035cf0434a1b5043f707ecd2316d4a18c.zip
[script] Allow commands following a script label
Allow commands to be placed on the same line as a label. This allows for improved legibility of loop constructions by incorporating the loop check condition into the same line as the loop label. For example, to iterate over network devices using the forthcoming "inc" command: set idx:int16 0 :loop isset ${net${idx}/mac} || goto loop_done echo net${idx} is a ${net${idx}/chip} with MAC ${net${idx}/mac} inc idx && goto loop :loop_done Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/image')
-rw-r--r--src/image/script.c96
1 files changed, 53 insertions, 43 deletions
diff --git a/src/image/script.c b/src/image/script.c
index d30f2613..881d51f3 100644
--- a/src/image/script.c
+++ b/src/image/script.c
@@ -55,19 +55,27 @@ static size_t script_offset;
* @ret rc Return status code
*/
static int process_script ( struct image *image,
- int ( * process_line ) ( const char *line ),
+ int ( * process_line ) ( struct image *image,
+ size_t offset,
+ const char *label,
+ const char *command ),
int ( * terminate ) ( int rc ) ) {
size_t len = 0;
char *line = NULL;
+ size_t line_offset;
+ char *label;
+ char *command;
off_t eol;
size_t frag_len;
char *tmp;
int rc;
+ /* Initialise script and line offsets */
script_offset = 0;
+ line_offset = 0;
do {
-
+
/* Find length of next line, excluding any terminating '\n' */
eol = memchr_user ( image->data, script_offset, '\n',
( image->len - script_offset ) );
@@ -104,10 +112,23 @@ static int process_script ( struct image *image,
/* Terminate line */
line[len] = '\0';
- DBG ( "$ %s\n", line );
+
+ /* Split line into (optional) label and command */
+ command = line;
+ while ( isspace ( *command ) )
+ command++;
+ if ( *command == ':' ) {
+ label = ++command;
+ while ( *command && ! isspace ( *command ) )
+ command++;
+ if ( *command )
+ *(command++) = '\0';
+ } else {
+ label = NULL;
+ }
/* Process line */
- rc = process_line ( line );
+ rc = process_line ( image, line_offset, label, command );
if ( terminate ( rc ) )
goto err_process;
@@ -116,6 +137,9 @@ static int process_script ( struct image *image,
line = NULL;
len = 0;
+ /* Update line offset */
+ line_offset = script_offset;
+
} while ( script_offset < image->len );
err_process:
@@ -137,40 +161,23 @@ static int terminate_on_exit_or_failure ( int rc ) {
}
/**
- * Find label within script line
- *
- * @v line Line of script
- * @ret label Start of label name, or NULL if not found
- */
-static const char * find_label ( const char *line ) {
-
- /* Skip any leading whitespace */
- while ( isspace ( *line ) )
- line++;
-
- /* If first non-whitespace character is a ':', then we have a label */
- if ( *line == ':' ) {
- return ( line + 1 );
- } else {
- return NULL;
- }
-}
-
-/**
* Execute script line
*
- * @v line Line of script
+ * @v image Script
+ * @v offset Offset within script
+ * @v label Label, or NULL
+ * @v command Command
* @ret rc Return status code
*/
-static int script_exec_line ( const char *line ) {
+static int script_exec_line ( struct image *image, size_t offset,
+ const char *label __unused,
+ const char *command ) {
int rc;
- /* Skip label lines */
- if ( find_label ( line ) != NULL )
- return 0;
+ DBGC ( image, "[%04zx] $ %s\n", offset, command );
/* Execute command */
- if ( ( rc = system ( line ) ) != 0 )
+ if ( ( rc = system ( command ) ) != 0 )
return rc;
return 0;
@@ -224,7 +231,7 @@ static int script_probe ( struct image *image ) {
/* Sanity check */
if ( image->len < sizeof ( test ) ) {
- DBG ( "Too short to be a script\n" );
+ DBGC ( image, "Too short to be a script\n" );
return -ENOEXEC;
}
@@ -233,7 +240,7 @@ static int script_probe ( struct image *image ) {
if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
- DBG ( "Invalid magic signature\n" );
+ DBGC ( image, "Invalid magic signature\n" );
return -ENOEXEC;
}
@@ -267,25 +274,26 @@ static const char *goto_label;
/**
* Check for presence of label
*
- * @v line Script line
+ * @v image Script
+ * @v offset Offset within script
+ * @v label Label
+ * @v command Command
* @ret rc Return status code
*/
-static int goto_find_label ( const char *line ) {
- size_t len = strlen ( goto_label );
- const char *label;
+static int goto_find_label ( struct image *image, size_t offset,
+ const char *label, const char *command __unused ) {
- /* Find label */
- label = find_label ( line );
+ /* Check label exists */
if ( ! label )
return -ENOENT;
- /* Check if label matches */
- if ( strncmp ( goto_label, label, len ) != 0 )
+ /* Check label matches */
+ if ( strcmp ( goto_label, label ) != 0 )
return -ENOENT;
- /* Check label is terminated by a NUL or whitespace */
- if ( label[len] && ! isspace ( label[len] ) )
- return -ENOENT;
+ /* Update script offset */
+ script_offset = offset;
+ DBGC ( image, "[%04zx] Gone to :%s\n", offset, label );
return 0;
}
@@ -331,6 +339,8 @@ static int goto_exec ( int argc, char **argv ) {
if ( ( rc = process_script ( current_image, goto_find_label,
terminate_on_label_found ) ) != 0 ) {
script_offset = saved_offset;
+ DBGC ( current_image, "[%04zx] No such label :%s\n",
+ script_offset, goto_label );
return rc;
}