Browse Source

[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>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
31f5211035
1 changed files with 53 additions and 43 deletions
  1. 53
    43
      src/image/script.c

+ 53
- 43
src/image/script.c View File

@@ -55,19 +55,27 @@ static size_t script_offset;
55 55
  * @ret rc		Return status code
56 56
  */
57 57
 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 ),
59 62
 			    int ( * terminate ) ( int rc ) ) {
60 63
 	size_t len = 0;
61 64
 	char *line = NULL;
65
+	size_t line_offset;
66
+	char *label;
67
+	char *command;
62 68
 	off_t eol;
63 69
 	size_t frag_len;
64 70
 	char *tmp;
65 71
 	int rc;
66 72
 
73
+	/* Initialise script and line offsets */
67 74
 	script_offset = 0;
75
+	line_offset = 0;
68 76
 
69 77
 	do {
70
-	
78
+
71 79
 		/* Find length of next line, excluding any terminating '\n' */
72 80
 		eol = memchr_user ( image->data, script_offset, '\n',
73 81
 				    ( image->len - script_offset ) );
@@ -104,10 +112,23 @@ static int process_script ( struct image *image,
104 112
 
105 113
 		/* Terminate line */
106 114
 		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
+		}
108 129
 
109 130
 		/* Process line */
110
-		rc = process_line ( line );
131
+		rc = process_line ( image, line_offset, label, command );
111 132
 		if ( terminate ( rc ) )
112 133
 			goto err_process;
113 134
 
@@ -116,6 +137,9 @@ static int process_script ( struct image *image,
116 137
 		line = NULL;
117 138
 		len = 0;
118 139
 
140
+		/* Update line offset */
141
+		line_offset = script_offset;
142
+
119 143
 	} while ( script_offset < image->len );
120 144
 
121 145
  err_process:
@@ -136,41 +160,24 @@ static int terminate_on_exit_or_failure ( int rc ) {
136 160
 		 ( rc != 0 ) );
137 161
 }
138 162
 
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
-
159 163
 /**
160 164
  * Execute script line
161 165
  *
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
163 170
  * @ret rc		Return status code
164 171
  */
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 ) {
166 175
 	int rc;
167 176
 
168
-	/* Skip label lines */
169
-	if ( find_label ( line ) != NULL )
170
-		return 0;
177
+	DBGC ( image, "[%04zx] $ %s\n", offset, command );
171 178
 
172 179
 	/* Execute command */
173
-	if ( ( rc = system ( line ) ) != 0 )
180
+	if ( ( rc = system ( command ) ) != 0 )
174 181
 		return rc;
175 182
 
176 183
 	return 0;
@@ -224,7 +231,7 @@ static int script_probe ( struct image *image ) {
224 231
 
225 232
 	/* Sanity check */
226 233
 	if ( image->len < sizeof ( test ) ) {
227
-		DBG ( "Too short to be a script\n" );
234
+		DBGC ( image, "Too short to be a script\n" );
228 235
 		return -ENOEXEC;
229 236
 	}
230 237
 
@@ -233,7 +240,7 @@ static int script_probe ( struct image *image ) {
233 240
 	if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
234 241
 		   ( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
235 242
 		 isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
236
-		DBG ( "Invalid magic signature\n" );
243
+		DBGC ( image, "Invalid magic signature\n" );
237 244
 		return -ENOEXEC;
238 245
 	}
239 246
 
@@ -267,25 +274,26 @@ static const char *goto_label;
267 274
 /**
268 275
  * Check for presence of label
269 276
  *
270
- * @v line		Script line
277
+ * @v image		Script
278
+ * @v offset		Offset within script
279
+ * @v label		Label
280
+ * @v command		Command
271 281
  * @ret rc		Return status code
272 282
  */
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 ) {
276 285
 
277
-	/* Find label */
278
-	label = find_label ( line );
286
+	/* Check label exists */
279 287
 	if ( ! label )
280 288
 		return -ENOENT;
281 289
 
282
-	/* Check if label matches */
283
-	if ( strncmp ( goto_label, label, len ) != 0 )
290
+	/* Check label matches */
291
+	if ( strcmp ( goto_label, label ) != 0 )
284 292
 		return -ENOENT;
285 293
 
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 );
289 297
 
290 298
 	return 0;
291 299
 }
@@ -331,6 +339,8 @@ static int goto_exec ( int argc, char **argv ) {
331 339
 	if ( ( rc = process_script ( current_image, goto_find_label,
332 340
 				     terminate_on_label_found ) ) != 0 ) {
333 341
 		script_offset = saved_offset;
342
+		DBGC ( current_image, "[%04zx] No such label :%s\n",
343
+		       script_offset, goto_label );
334 344
 		return rc;
335 345
 	}
336 346
 

Loading…
Cancel
Save