Skip to content

Commit 31f5211

Browse files
committed
[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>
1 parent 7fc18ea commit 31f5211

File tree

1 file changed

+53
-43
lines changed

1 file changed

+53
-43
lines changed

src/image/script.c

+53-43
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,27 @@ static size_t script_offset;
5555
* @ret rc Return status code
5656
*/
5757
static int process_script ( struct image *image,
58-
int ( * process_line ) ( const char *line ),
58+
int ( * process_line ) ( struct image *image,
59+
size_t offset,
60+
const char *label,
61+
const char *command ),
5962
int ( * terminate ) ( int rc ) ) {
6063
size_t len = 0;
6164
char *line = NULL;
65+
size_t line_offset;
66+
char *label;
67+
char *command;
6268
off_t eol;
6369
size_t frag_len;
6470
char *tmp;
6571
int rc;
6672

73+
/* Initialise script and line offsets */
6774
script_offset = 0;
75+
line_offset = 0;
6876

6977
do {
70-
78+
7179
/* Find length of next line, excluding any terminating '\n' */
7280
eol = memchr_user ( image->data, script_offset, '\n',
7381
( image->len - script_offset ) );
@@ -104,10 +112,23 @@ static int process_script ( struct image *image,
104112

105113
/* Terminate line */
106114
line[len] = '\0';
107-
DBG ( "$ %s\n", line );
115+
116+
/* Split line into (optional) label and command */
117+
command = line;
118+
while ( isspace ( *command ) )
119+
command++;
120+
if ( *command == ':' ) {
121+
label = ++command;
122+
while ( *command && ! isspace ( *command ) )
123+
command++;
124+
if ( *command )
125+
*(command++) = '\0';
126+
} else {
127+
label = NULL;
128+
}
108129

109130
/* Process line */
110-
rc = process_line ( line );
131+
rc = process_line ( image, line_offset, label, command );
111132
if ( terminate ( rc ) )
112133
goto err_process;
113134

@@ -116,6 +137,9 @@ static int process_script ( struct image *image,
116137
line = NULL;
117138
len = 0;
118139

140+
/* Update line offset */
141+
line_offset = script_offset;
142+
119143
} while ( script_offset < image->len );
120144

121145
err_process:
@@ -136,41 +160,24 @@ static int terminate_on_exit_or_failure ( int rc ) {
136160
( rc != 0 ) );
137161
}
138162

139-
/**
140-
* Find label within script line
141-
*
142-
* @v line Line of script
143-
* @ret label Start of label name, or NULL if not found
144-
*/
145-
static const char * find_label ( const char *line ) {
146-
147-
/* Skip any leading whitespace */
148-
while ( isspace ( *line ) )
149-
line++;
150-
151-
/* If first non-whitespace character is a ':', then we have a label */
152-
if ( *line == ':' ) {
153-
return ( line + 1 );
154-
} else {
155-
return NULL;
156-
}
157-
}
158-
159163
/**
160164
* Execute script line
161165
*
162-
* @v line Line of script
166+
* @v image Script
167+
* @v offset Offset within script
168+
* @v label Label, or NULL
169+
* @v command Command
163170
* @ret rc Return status code
164171
*/
165-
static int script_exec_line ( const char *line ) {
172+
static int script_exec_line ( struct image *image, size_t offset,
173+
const char *label __unused,
174+
const char *command ) {
166175
int rc;
167176

168-
/* Skip label lines */
169-
if ( find_label ( line ) != NULL )
170-
return 0;
177+
DBGC ( image, "[%04zx] $ %s\n", offset, command );
171178

172179
/* Execute command */
173-
if ( ( rc = system ( line ) ) != 0 )
180+
if ( ( rc = system ( command ) ) != 0 )
174181
return rc;
175182

176183
return 0;
@@ -224,7 +231,7 @@ static int script_probe ( struct image *image ) {
224231

225232
/* Sanity check */
226233
if ( image->len < sizeof ( test ) ) {
227-
DBG ( "Too short to be a script\n" );
234+
DBGC ( image, "Too short to be a script\n" );
228235
return -ENOEXEC;
229236
}
230237

@@ -233,7 +240,7 @@ static int script_probe ( struct image *image ) {
233240
if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
234241
( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
235242
isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
236-
DBG ( "Invalid magic signature\n" );
243+
DBGC ( image, "Invalid magic signature\n" );
237244
return -ENOEXEC;
238245
}
239246

@@ -267,25 +274,26 @@ static const char *goto_label;
267274
/**
268275
* Check for presence of label
269276
*
270-
* @v line Script line
277+
* @v image Script
278+
* @v offset Offset within script
279+
* @v label Label
280+
* @v command Command
271281
* @ret rc Return status code
272282
*/
273-
static int goto_find_label ( const char *line ) {
274-
size_t len = strlen ( goto_label );
275-
const char *label;
283+
static int goto_find_label ( struct image *image, size_t offset,
284+
const char *label, const char *command __unused ) {
276285

277-
/* Find label */
278-
label = find_label ( line );
286+
/* Check label exists */
279287
if ( ! label )
280288
return -ENOENT;
281289

282-
/* Check if label matches */
283-
if ( strncmp ( goto_label, label, len ) != 0 )
290+
/* Check label matches */
291+
if ( strcmp ( goto_label, label ) != 0 )
284292
return -ENOENT;
285293

286-
/* Check label is terminated by a NUL or whitespace */
287-
if ( label[len] && ! isspace ( label[len] ) )
288-
return -ENOENT;
294+
/* Update script offset */
295+
script_offset = offset;
296+
DBGC ( image, "[%04zx] Gone to :%s\n", offset, label );
289297

290298
return 0;
291299
}
@@ -331,6 +339,8 @@ static int goto_exec ( int argc, char **argv ) {
331339
if ( ( rc = process_script ( current_image, goto_find_label,
332340
terminate_on_label_found ) ) != 0 ) {
333341
script_offset = saved_offset;
342+
DBGC ( current_image, "[%04zx] No such label :%s\n",
343+
script_offset, goto_label );
334344
return rc;
335345
}
336346

0 commit comments

Comments
 (0)