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
  * @ret rc		Return status code
55
  * @ret rc		Return status code
56
  */
56
  */
57
 static int process_script ( struct image *image,
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
 			    int ( * terminate ) ( int rc ) ) {
62
 			    int ( * terminate ) ( int rc ) ) {
60
 	size_t len = 0;
63
 	size_t len = 0;
61
 	char *line = NULL;
64
 	char *line = NULL;
65
+	size_t line_offset;
66
+	char *label;
67
+	char *command;
62
 	off_t eol;
68
 	off_t eol;
63
 	size_t frag_len;
69
 	size_t frag_len;
64
 	char *tmp;
70
 	char *tmp;
65
 	int rc;
71
 	int rc;
66
 
72
 
73
+	/* Initialise script and line offsets */
67
 	script_offset = 0;
74
 	script_offset = 0;
75
+	line_offset = 0;
68
 
76
 
69
 	do {
77
 	do {
70
-	
78
+
71
 		/* Find length of next line, excluding any terminating '\n' */
79
 		/* Find length of next line, excluding any terminating '\n' */
72
 		eol = memchr_user ( image->data, script_offset, '\n',
80
 		eol = memchr_user ( image->data, script_offset, '\n',
73
 				    ( image->len - script_offset ) );
81
 				    ( image->len - script_offset ) );
104
 
112
 
105
 		/* Terminate line */
113
 		/* Terminate line */
106
 		line[len] = '\0';
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
 		/* Process line */
130
 		/* Process line */
110
-		rc = process_line ( line );
131
+		rc = process_line ( image, line_offset, label, command );
111
 		if ( terminate ( rc ) )
132
 		if ( terminate ( rc ) )
112
 			goto err_process;
133
 			goto err_process;
113
 
134
 
116
 		line = NULL;
137
 		line = NULL;
117
 		len = 0;
138
 		len = 0;
118
 
139
 
140
+		/* Update line offset */
141
+		line_offset = script_offset;
142
+
119
 	} while ( script_offset < image->len );
143
 	} while ( script_offset < image->len );
120
 
144
 
121
  err_process:
145
  err_process:
136
 		 ( rc != 0 ) );
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
  * Execute script line
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
  * @ret rc		Return status code
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
 	int rc;
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
 	/* Execute command */
179
 	/* Execute command */
173
-	if ( ( rc = system ( line ) ) != 0 )
180
+	if ( ( rc = system ( command ) ) != 0 )
174
 		return rc;
181
 		return rc;
175
 
182
 
176
 	return 0;
183
 	return 0;
224
 
231
 
225
 	/* Sanity check */
232
 	/* Sanity check */
226
 	if ( image->len < sizeof ( test ) ) {
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
 		return -ENOEXEC;
235
 		return -ENOEXEC;
229
 	}
236
 	}
230
 
237
 
233
 	if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
240
 	if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
234
 		   ( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
241
 		   ( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
235
 		 isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
242
 		 isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
236
-		DBG ( "Invalid magic signature\n" );
243
+		DBGC ( image, "Invalid magic signature\n" );
237
 		return -ENOEXEC;
244
 		return -ENOEXEC;
238
 	}
245
 	}
239
 
246
 
267
 /**
274
 /**
268
  * Check for presence of label
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
  * @ret rc		Return status code
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
 	if ( ! label )
287
 	if ( ! label )
280
 		return -ENOENT;
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
 		return -ENOENT;
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
 	return 0;
298
 	return 0;
291
 }
299
 }
331
 	if ( ( rc = process_script ( current_image, goto_find_label,
339
 	if ( ( rc = process_script ( current_image, goto_find_label,
332
 				     terminate_on_label_found ) ) != 0 ) {
340
 				     terminate_on_label_found ) ) != 0 ) {
333
 		script_offset = saved_offset;
341
 		script_offset = saved_offset;
342
+		DBGC ( current_image, "[%04zx] No such label :%s\n",
343
+		       script_offset, goto_label );
334
 		return rc;
344
 		return rc;
335
 	}
345
 	}
336
 
346
 

Loading…
Cancel
Save