From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1CuxRM-0007AP-Na for mharc-grub-devel@gnu.org; Sat, 29 Jan 2005 13:35:24 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1CuxL2-0005wb-U0 for grub-devel@gnu.org; Sat, 29 Jan 2005 13:28:53 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1CuxKd-0005hZ-Bn for grub-devel@gnu.org; Sat, 29 Jan 2005 13:28:40 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1CuxKb-0005ba-7G for grub-devel@gnu.org; Sat, 29 Jan 2005 13:28:25 -0500 Received: from [194.67.23.121] (helo=mx1.mail.ru) by monty-python.gnu.org with esmtp (Exim 4.34) id 1CuwwG-0004Hv-Gc for grub-devel@gnu.org; Sat, 29 Jan 2005 13:03:17 -0500 Received: from [83.76.233.184] (port=4234 helo=[192.168.1.100]) by mx1.mail.ru with esmtp id 1CuwwC-000H61-00 for grub-devel@gnu.org; Sat, 29 Jan 2005 21:03:13 +0300 Message-ID: <41FBCFFC.8060507@list.ru> Date: Sat, 29 Jan 2005 19:03:41 +0100 From: Serbinenko Vladimir User-Agent: Mozilla Thunderbird 1.0 (X11/20041206) X-Accept-Language: en-us, en MIME-Version: 1.0 To: The development of GRUB 2 References: <200501221618.27972.okuji@enbug.org> <200501221835.25876.okuji@enbug.org> <41FB8D22.8030203@list.ru> <41FB98D9.1090309@list.ru> <871xc4rzlq.fsf@marco.marco-g.com> In-Reply-To: <871xc4rzlq.fsf@marco.marco-g.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Spam: Not detected Subject: Re: Bash pre-alpha X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Jan 2005 18:35:23 -0000 Marco Gerards wrote: >Serbinenko Vladimir writes: > > > >>I'm sorry but I had some diff issues I confused run_menu and >>run_menu_entry. Here is a patch to correct this error and update >>i386.mk >> >> > >Urgh... It seems that I do not get all my emails. The one you sent >now appears to be a follow up on an email I never received. The same >seems to be true for other emails on this list. So if I don't reply >to an email, I most likely did not receive it... > > > Perhaps you have a mail filter that filters out big messages? Spam filter? >It's our custom not to send in patches for generated files. Perhaps >it is possible to use .cvsignore to make sure they are not added, it's >annoying that I always have to remove the files before making a patch. > >So please just send in a patch for *.rmk next time. :) > > > >>./grub2pr/normal/menu.c ./grub2/normal/menu.c >>--- ./grub2pr/normal/menu.c 2005-01-29 14:55:55.000000000 +0100 >>+++ ./grub2/normal/menu.c 2005-01-29 15:00:11.000000000 +0100 >> >> > >What does this patch do? Because I missed your last email I missed >the description. I don't see that email in the archives yet. :/ > >Anyway, this patch looks interesting at least. :) > >Thanks, >Marco > > > > > I resend a text part of my message. I don't want to resend a patch because it's quite big and I suppose that not all subscribers have a broad channel. If you want I can resend it to you personally. With this mail I also send an incremental patch. It contains some bugfixing(some newline handling) and new commands '.', 'while,'until', 'break', 'continue' and 'return' About help it can be optimised as in new syntax title is not used anymore but some script commands are integrated in parse engine because they control executition and/or parsing. I could prepare a small help which will be simply printed as a text-string Best wishes Vladimir --------------------------------------------------------------------- Here I prepared first preview version of bash scripting engine. I repeat *first preview version* That means I haven't really tested it nor cleaned up or commented. This version is only for discussions. For now supported features are: arrays both syntaxes i=([0]=7 ...) and i[0] arithmetic expansion and ((...)) commands echo, ':',source Function support: [function ] name() { list; } Menu entries support like entry "" { list; } Now configuration file is parsed the same way as any script file or console entering menu is automatically shown after configfile is parsed or you can use showmenu command In arithmetical expansion some additional commands are present: i{9} means 10-th character of i "i",'i' means string i Associative arrays are supported: use z['hello']=JJJ This version is made in the goal to show my ideas and receive the critics. Please send your suggestions,critics and bug-reports. Known bugs: possible segmentation faults at incorrect constructions Not complete GCS compilance Some plans: See TODO in script.c commands clear menu and unregister_entry Bug fixing ----------------------------------------------------------------------- diff -b -B -r -u -E -N -x '*~' --expand-tabs ./grub2pr/ChangeLog ./grub2/ChangeLog --- ./grub2pr/ChangeLog 2005-01-29 15:39:33.000000000 +0100 +++ ./grub2/ChangeLog 2005-01-29 18:51:35.000000000 +0100 @@ -1,4 +1,9 @@ 2005-01-29 Serbinenko Vladimir + * include/grub/script.h: New type return reason + * normal/command.c : New commands: true,false, '.' + * normal/script.c: Bug fixed + New keywords: until, while, break,continue,return +2005-01-29 Serbinenko Vladimir Scripting support * normal/script.c: New file * include/grub/normal.h: New prototype diff -b -B -r -u -E -N -x '*~' --expand-tabs ./grub2pr/include/grub/script.h ./grub2/include/grub/script.h --- ./grub2pr/include/grub/script.h 2005-01-29 15:39:33.000000000 +0100 +++ ./grub2/include/grub/script.h 2005-01-29 17:04:57.000000000 +0100 @@ -40,6 +40,7 @@ char* (*func_do)(char*a,char*b,int opn); }; enum vartype {SCRIPT_STR,SCRIPT_VAR_NAME}; +enum returnreason {SCRIPT_NONE=0,SCRIPT_RETURN,SCRIPT_BREAK,SCRIPT_CONTINUE}; extern struct script_oper script_opers[]; int script_find_oper(char*exp,int searchleft); @@ -72,11 +73,11 @@ int script_get_strend(char*str); int -script_execute(char*cmdline,grub_err_t(*getline)(char**),char**rest); +script_execute(char*cmdline,grub_err_t(*getline)(char**),char**rest,enum returnreason*retres,int*depth); int -script_exec_file (char*fname,int argc, char**argv); +script_list_execute( grub_menu_entry_t fn,enum returnreason*retres,int*depth); int -script_list_execute(grub_menu_entry_t fn); +script_exec_file (char*fname,int argc, char**argv); grub_menu_t menu; #define EXPAND_DOLLAR 1 #define EXPAND_ALL 1 diff -b -B -r -u -E -N -x '*~' --expand-tabs ./grub2pr/normal/command.c ./grub2/normal/command.c --- ./grub2pr/normal/command.c 2005-01-29 15:39:34.000000000 +0100 +++ ./grub2/normal/command.c 2005-01-29 17:01:19.000000000 +0100 @@ -121,7 +121,7 @@ return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1); } - return script_execute(cmdline,cmdline_get,0); + return script_execute(cmdline,cmdline_get,0,0,0); } int grub_exec_norm(char*exp) @@ -350,6 +350,21 @@ return 0; } +static grub_err_t +true_command (struct grub_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + return 0; +} + +static grub_err_t +false_command (struct grub_arg_list *state __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + return 1; +} void grub_command_init (void) @@ -382,6 +397,13 @@ grub_register_command ("source", source_command, GRUB_COMMAND_FLAG_BOTH, "source FILE [ARGUMENTS ...]", "Execute script FILE.", 0); + grub_register_command (".", source_command, GRUB_COMMAND_FLAG_BOTH, + ". FILE [ARGUMENTS ...]", "Execute script FILE.", 0); + grub_register_command ("showmenu", showmenu_command, GRUB_COMMAND_FLAG_BOTH, "showmenu", "Show menu.", 0); + grub_register_command ("true", true_command, GRUB_COMMAND_FLAG_BOTH, + "true", "Return success.", 0); + grub_register_command ("false", false_command, GRUB_COMMAND_FLAG_BOTH, + "false", "Return failure.", 0); } diff -b -B -r -u -E -N -x '*~' --expand-tabs ./grub2pr/normal/menu.c ./grub2/normal/menu.c --- ./grub2pr/normal/menu.c 2005-01-29 15:39:34.000000000 +0100 +++ ./grub2/normal/menu.c 2005-01-29 17:07:57.000000000 +0100 @@ -379,8 +379,7 @@ static void run_menu_entry (grub_menu_entry_t entry) { - - script_list_execute(entry); + script_list_execute(entry,0,0); if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ grub_command_execute ("boot"); diff -b -B -r -u -E -N -x '*~' --expand-tabs ./grub2pr/normal/script.c ./grub2/normal/script.c --- ./grub2pr/normal/script.c 2005-01-29 15:39:34.000000000 +0100 +++ ./grub2/normal/script.c 2005-01-29 18:43:28.000000000 +0100 @@ -1427,9 +1427,9 @@ return rtval; } void -script_parse_list(grub_menu_entry_t fnptr,char**cmd,grub_err_t(*getline)(char**),int no1stskip) +script_parse_list(grub_menu_entry_t fnptr,char**cmd,grub_err_t(*getline)(char**),int flgs) { - grub_command_list_t listptr=0;char*lastcmd=*cmd,*bfrcmd=*cmd; + grub_command_list_t listptr=0;char*lastcmd=*cmd,*bfrcmd=0; /* Get one character from the commandline. If the caller reads beyond the end of the string a new line will be read. This function will not chech for errors, the caller has to check for @@ -1497,19 +1497,13 @@ } } char c;int brack=1;int lmin=0; - if(!no1stskip) + if(!(flgs&1)) { while(grub_isspace((c=getchar()))); switch(c) { case '{': break; - case 'd': - if(getchar()!='o') - break; - if(!script_islexend(getchar())) - break; - break; default: grub_error(GRUB_ERR_BAD_ARGUMENT,"unexpected %c '{' expected",c); return; @@ -1523,7 +1517,11 @@ while(brack) { lmin=0; - while(grub_isspace(c=getchar())); + c=getchar(); + if(grub_isspace(c)) + continue; + if(c=='\n' || c==';') + continue; if(c=='}') { brack--; @@ -1570,6 +1568,11 @@ c=getchar(); if(script_islexend(c)) { + if((flgs&2) && brack==1) + { + lmin=3; + break; + } brack++; continue; } @@ -1594,7 +1597,7 @@ while(1) { if((c=getchar())!='l') - break;; + break; c=getchar(); if(c=='s') { @@ -1630,10 +1633,13 @@ listptr->command[(*cmd)-lastcmd]=0; } if(!*cmd&& lmin) + { *cmd=bfrcmd-lmin; + listptr->command[grub_strlen(listptr->command)-lmin+1]=0; + } } int -script_list_execute( grub_menu_entry_t fn) +script_list_execute( grub_menu_entry_t fn,enum returnreason*retres,int*depth) { grub_command_list_t cmdlist=fn->command_list; grub_err_t getln(char**s) @@ -1650,7 +1656,12 @@ int rtval=0; while(cmdlist) { - rtval=script_execute(cmdlist->command,getln,0); + enum returnreason rt; + if(cmdlist->command[0])rtval=script_execute(cmdlist->command,getln,0,&rt,depth); + if(retres) + *retres=rt; + if(rt) + return rtval; if(cmdlist) cmdlist=cmdlist->next; } @@ -1754,12 +1765,12 @@ getln(&ln); if(!ln) break; - ret=script_execute(ln,getln,0); + ret=script_execute(ln,getln,0,0,0); } return ret; } int -script_execute(char*cmdline,grub_err_t(*getline)(char**),char**rest) +script_execute(char*cmdline,grub_err_t(*getline)(char**),char**rest,enum returnreason*retres,int*depth) { int rtval=0,semdel=0; int invrtval=0; @@ -1780,6 +1791,8 @@ return 1; } if(rest)*rest=0; + if(retres) + *retres=SCRIPT_NONE; while(1) { if(invrtval) @@ -1825,9 +1838,17 @@ end+=2; while(!end || !*end || grub_memcmp(end,"then",4)|| !script_islexend(end[4])) { + enum returnreason rt; if(!end || !*end) getline(&end); - ret=!script_execute(end,getline,&end); + if(*end) + { + ret=!script_execute(end,getline,&end,&rt,depth); + if(retres) + *retres=rt; + if(rt) + return rtval; + } } grub_menu_entry_t lst=grub_malloc(sizeof(*lst)); lst->num=0; @@ -1836,7 +1857,15 @@ end+=4; script_parse_list(lst,&end,getline,1); if(ret) - rtval=script_list_execute(lst); + { + enum returnreason rt; + rtval=script_list_execute(lst,&rt,depth); + script_free_list(lst); + if(retres) + *retres=rt; + if(rt) + return rtval; + } script_free_list(lst); while((!grub_memcmp(end,"else",4)&&script_islexend(end[4])) ||(!grub_memcmp(end,"elif",4)&&script_islexend(end[4]))) @@ -1851,9 +1880,17 @@ { while(!end || !*end || grub_memcmp(end,"then",4)|| !script_islexend(end[4])) { + enum returnreason rt; if(!end || !*end) getline(&end); - crtval=!script_execute(end,getline,&end); + if(*end) + { + ret=!script_execute(end,getline,&end,&rt,depth); + if(retres) + *retres=rt; + if(rt) + return rtval; + } } end+=4; } @@ -1862,14 +1899,63 @@ script_parse_list(lst,&end,getline,1); if(crtval) { - rtval=script_list_execute(lst); + enum returnreason rt; + rtval=script_list_execute(lst,&rt,depth); + script_free_list(lst); + if(retres) + *retres=rt; + if(rt) + return rtval; ret=1; } + else script_free_list(lst); } end+=2; continue; } + if((!grub_memcmp(end,"while",sizeof("while")-1)&& script_islexend(end[sizeof("while")-1])) + ||(!grub_memcmp(end,"until",sizeof("until")-1)&& script_islexend(end[sizeof("until")-1]))) + { + int invrt=(*end=='u'); + end+=sizeof("while")-1; + grub_menu_entry_t condlst=grub_malloc(sizeof(*condlst)); + grub_menu_entry_t lst=grub_malloc(sizeof(*lst)); + condlst->num=0; + condlst->title=0; + condlst->next=0; + script_parse_list(condlst,&end,getline,3); + lst->num=0; + lst->title=0; + lst->next=0; + end+=2; + script_parse_list(lst,&end,getline,1); + while(1) + { + enum returnreason rt; + int ret=script_list_execute(condlst,&rt,depth),dpth; + if(retres) + *retres=rt; + if(rt) + return rtval; + if((!ret)==invrt) + break; + rtval=script_list_execute(lst,&rt,&dpth); + if(retres) + *retres=((rt==SCRIPT_CONTINUE||rt==SCRIPT_BREAK)&&dpth==1)?SCRIPT_NONE:rt; + if(depth) + *depth=dpth-1; + if(rt && (rt!=SCRIPT_CONTINUE||dpth!=1)&&(rt!=SCRIPT_BREAK||dpth!=1)) + return rtval; + if(rt==SCRIPT_BREAK) + { + break; + } + } + script_free_list(lst); + script_free_list(condlst); + continue; + } if(end[0]=='(' && end[1]=='(') { char*exp=script_expand(end,getline,&end,EXPAND_DOLLAR); @@ -1939,6 +2025,40 @@ char*exp=script_expand(end,getline,&end,EXPAND_ALL); while(grub_isspace(*exp))exp++; char*expcur=exp; + if(!grub_memcmp("return",expcur,sizeof("return")-1)&&script_islexend(expcur[sizeof("return")-1])) + { + expcur+=sizeof("return")-1; + while(grub_isspace(*expcur))expcur++; + if(*expcur=='-' ||grub_isdigit(*expcur)) + rtval=grub_strtol(expcur,&expcur,0); + if(retres) + *retres=SCRIPT_RETURN; + return rtval; + } + if(!grub_memcmp("continue",expcur,sizeof("continue")-1)&&script_islexend(expcur[sizeof("continue")-1])) + { + expcur+=sizeof("continue")-1; + while(grub_isspace(*expcur))expcur++; + if(depth) + *depth=1; + if(depth && (*expcur=='-' ||grub_isdigit(*expcur) )) + *depth=grub_strtol(expcur,&expcur,0);; + if(retres) + *retres=SCRIPT_CONTINUE; + return rtval; + } + if(!grub_memcmp("break",expcur,sizeof("break")-1)&&script_islexend(expcur[sizeof("break")-1])) + { + expcur+=sizeof("break")-1; + while(grub_isspace(*expcur))expcur++; + if(depth) + *depth=1; + if(depth && (*expcur=='-' ||grub_isdigit(*expcur) )) + *depth=grub_strtol(expcur,&expcur,0); + if(retres) + *retres=SCRIPT_BREAK; + return rtval; + } { grub_menu_entry_t cur=funcs.entry_list; if(funcs.entry_list) @@ -1952,7 +2072,7 @@ if(cur) { expcur+=grub_strlen(cur->title); - rtval=script_list_execute(cur); + rtval=script_list_execute(cur,0,0); continue; } }