[scripting] Added for loops
[people/lynusvaz/gpxe.git] / src / hci / commands / if_cmd.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <gpxe/command.h>
4 #include <gpxe/gen_stack.h>
5 #include <gpxe/init.h>
6 #include <gpxe/settings.h>
7
8 struct generic_stack if_stack;
9 static struct generic_stack else_stack;
10 static struct generic_stack loop_stack;
11 struct generic_stack command_list;
12 int prog_ctr;
13 int isnum ( char *string, long *num );
14
15 int system ( const char * );
16
17 struct while_info {
18         int loop_start;
19         int if_pos;
20         int is_continue;
21         int cur_arg;
22 };
23
24 static struct while_info for_info;
25
26 static int if_exec ( int argc, char **argv ) {
27         long cond;
28         int zero = 0;
29         if ( argc != 2 ) {
30                 printf ( "Syntax: if <condition>\n" );
31                 return 1;
32         }
33         
34         if ( !isnum ( argv[1], &cond ) ) {
35                 printf ( "non-numeric condition: %s\n", argv[1] );
36                 return 1;
37         }
38         cond = TOP_GEN_STACK_INT ( &if_stack ) ? ( cond ? 1 : 0 ) : 0;
39         if ( ( push_generic_stack ( &else_stack, &zero, 0 ) < 0 ) || ( push_generic_stack ( &if_stack, &cond, 0 ) < 0 ) ) {
40                 free_generic_stack ( &if_stack, 0 );
41                 free_generic_stack ( &else_stack, 0 );
42                 return 1;
43         }
44
45         return 0;
46 }
47
48 struct command if_command __command = {
49         .name = "if",
50         .exec = if_exec,
51 };
52
53 static int fi_exec ( int argc, char **argv ) {
54         int cond;
55         if ( argc != 1 ) {
56                 printf ( "Syntax: %s\n", argv[0] );
57                 return 1;
58         }
59         
60         if ( if_stack.tos > 0 ) {       
61                 if ( pop_generic_stack ( &if_stack, &cond ) < 0 )
62                         return 1;
63         } else {
64                 printf ( "fi without if\n" );
65                 return 1;
66         }
67         return 0;               
68 }
69
70
71 struct command fi_command __command = {
72         .name = "fi",
73         .exec = fi_exec,
74 };
75
76 static int else_exec ( int argc, char **argv ) {
77         if ( argc != 1 ) {
78                 printf ( "Syntax: %s\n", argv[0] );
79                 return 1;
80         }
81
82         if ( TOP_GEN_STACK_INT ( &else_stack ) != 0 ) {
83                 printf ( "else without if\n" );
84                 return 1;
85         }
86         
87         if ( ELEMENT_GEN_STACK_INT ( &if_stack, if_stack.tos - 1 ) )
88                 TOP_GEN_STACK_INT ( &if_stack ) = !TOP_GEN_STACK_INT ( &if_stack );
89         
90         return 0;
91 }
92
93 struct command else_command __command = {
94         .name = "else",
95         .exec = else_exec,
96 };
97
98 void init_if ( void ) {
99         int one = 1;
100         init_generic_stack ( &if_stack, sizeof ( int ) );
101         init_generic_stack ( &else_stack, sizeof ( int ) );
102         init_generic_stack ( &loop_stack, sizeof ( struct while_info ) );
103         init_generic_stack ( &command_list, sizeof ( char * ) );
104         prog_ctr = 0;
105         push_generic_stack ( &if_stack, &one, 0 );
106         push_generic_stack ( &else_stack, &one, 0 );
107         return;
108 }
109
110 struct init_fn initialise_if __init_fn ( INIT_NORMAL ) = {
111         .initialise = init_if,
112 };
113
114 static int while_exec ( int argc, char **argv ) {
115         struct while_info w;
116         if ( argc != 2 ) {
117                 printf ( "Syntax: while <condition>\n" );
118                 return 1;
119         }
120         if ( if_exec ( argc, argv ) != 0 )
121                 return 1;
122         TOP_GEN_STACK_INT ( &else_stack ) = 1;
123         
124         w.loop_start = prog_ctr;
125         w.if_pos = if_stack.tos;
126         w.is_continue = 0;
127         w.cur_arg = 0;
128         
129         if ( push_generic_stack ( &loop_stack, &w, 0 ) )
130                 return 1;
131         //printf ( "pc = %d. size of loop_stack = %d\n", prog_ctr, SIZE_GEN_STACK ( &loop_stack ) );
132         return 0;
133 }
134
135 struct command while_command __command = {
136         .name = "while",
137         .exec = while_exec,
138 };
139
140 static int done_exec ( int argc, char **argv ) {
141         int cond;
142         int tmp_pc;
143         int rc = 0;
144         if ( argc != 1 ) {
145                 printf ( "Syntax: %s\n", argv[0] );
146                 return 1;
147         }
148         
149         //printf ( "size of if_stack = %d. size of loop stack = %d\n", SIZE_GEN_STACK ( &if_stack ), SIZE_GEN_STACK ( &loop_stack ) );
150         
151         if ( SIZE_GEN_STACK ( &loop_stack ) == 0 ) {
152                 printf ( "done outside a loop\n" );
153                 return 1;
154         }
155         
156         if ( pop_generic_stack ( &if_stack, &cond ) || pop_generic_stack ( &loop_stack, &for_info ) )
157                 return 1;
158         
159         while ( cond || for_info.is_continue ) {                
160                 tmp_pc = prog_ctr;
161                 prog_ctr = for_info.loop_start;
162                 
163                 while ( prog_ctr < tmp_pc ) {
164                         if ( ( rc = system ( ELEMENT_GEN_STACK_STRING ( &command_list, prog_ctr ) ) ) ) 
165                                 return rc;
166                 }
167                 if ( pop_generic_stack ( &if_stack, &cond ) || pop_generic_stack ( &loop_stack, &for_info ) )
168                         return 1;
169         }
170         for_info.cur_arg = 0;
171         return rc;
172 }
173
174 struct command done_command __command = {
175         .name = "done",
176         .exec = done_exec,
177 };
178
179 static int break_exec ( int argc, char **argv ) {
180         int pos;
181         struct while_info *w;
182         if ( argc != 1 ) {
183                 printf ( "Syntax: %s\n", argv[0] );
184                 return 1;
185         }
186         if ( SIZE_GEN_STACK ( &loop_stack ) <= 0 ) {
187                 printf ( "%s outside loop\n", argv[0] );
188         }
189         w = ( ( struct while_info * ) loop_stack.ptr + ( loop_stack.tos ) );
190         for ( pos = w->if_pos; pos < SIZE_GEN_STACK ( &if_stack ); pos++ )
191                 ELEMENT_GEN_STACK_INT ( &if_stack, pos ) = 0;
192         return 0;
193 }
194
195 struct command break_command __command = {
196         .name = "break",
197         .exec = break_exec,
198 };
199
200 static int continue_exec ( int argc, char **argv ) {
201         struct while_info *w;
202         if ( argc != 1 ) {
203                 printf ( "Syntax: %s\n", argv[0] );
204                 return 1;
205         }
206         if ( break_exec ( argc, argv ) )
207                 return 1;
208         w = ( ( struct while_info * ) loop_stack.ptr + ( loop_stack.tos ) );
209         w->is_continue = 1;
210         return 0;
211 }
212
213 struct command continue_command __command = {
214         .name = "continue",
215         .exec = continue_exec,
216 };
217
218 static int for_exec ( int argc, char **argv ) {
219         int cond;
220         int rc;
221         if ( argc < 3 ) {
222                 printf ( "Syntax: for <var> in <list>\n" );
223                 return 1;
224         }
225         
226         for_info.loop_start = prog_ctr;
227         for_info.cur_arg = for_info.cur_arg == 0 ? 3 : for_info.cur_arg + 1;                    //for_info should either be popped by a done or for_info.cur_arg = 0
228         for_info.is_continue = 0;
229         
230         cond = TOP_GEN_STACK_INT ( &if_stack ) && ( argc > for_info.cur_arg );  
231         if ( ( rc = push_generic_stack ( &if_stack, &cond, 0 ) ) == 0 )
232                 if ( ( rc = storef_named_setting ( argv[1], argv[for_info.cur_arg] ) ) == 0 ) 
233                         rc = push_generic_stack ( &loop_stack, &for_info, 0 );
234         for_info.cur_arg = 0;
235         return rc;
236 }
237
238 struct command for_command __command = {
239         .name = "for",
240         .exec = for_exec,
241 };