<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugzilla.yoctoproject.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.6"
          urlbase="https://bugzilla.yoctoproject.org/"
          
          maintainer="it-coreprojects-helpdesk@linuxfoundation.org"
>

    <bug>
          <bug_id>3403</bug_id>
          
          <creation_ts>2012-11-09 07:46:39 +0000</creation_ts>
          <short_desc>bitbake parse does not handle } in the beginning of a function line correctly</short_desc>
          <delta_ts>2013-05-02 07:57:53 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>9</classification_id>
          <classification>Documentation</classification>
          <product>Reference</product>
          <component>handbook</component>
          <version>1.4</version>
          <rep_platform>x86</rep_platform>
          <op_sys>Multiple</op_sys>
          <bug_status>VERIFIED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc>http://git.yoctoproject.org/cgit.cgi/yocto-docs/commit/?id=a1c0972083751444a8cc89aa8a026f273d98e23e</bug_file_loc>
          <status_whiteboard>1 March 2013: In Progress Review</status_whiteboard>
          <keywords></keywords>
          <priority>Medium</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>1.4 M3</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Hongxu Jia">hongxu.jia</reporter>
          <assigned_to name="Scott Rifenbark">srifenbark</assigned_to>
          <cc>corneliux.stoicescu</cc>
    
    <cc>jessica.zhang</cc>
    
    <cc>kai.kang</cc>
    
    <cc>liezhi.yang</cc>
    
    <cc>poky.bs.watcher</cc>
    
    <cc>poky.doc.watcher</cc>
    
    <cc>poky.watcher</cc>
    
    <cc>Qi.Chen</cc>
    
    <cc>richard.purdie</cc>
    
    <cc>sgw</cc>
    
    <cc>yi.zhao</cc>
    
    <cc>zhenfeng.zhao</cc>
          
          
          <cf_os>---</cf_os>
          <cf_regression_type>---</cf_regression_type>
          
          <cf_docchange>---</cf_docchange>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>27319</commentid>
    <comment_count>0</comment_count>
    <who name="Hongxu Jia">hongxu.jia</who>
    <bug_when>2012-11-09 07:46:39 +0000</bug_when>
    <thetext>* Problem

Define a function in a the recipe, such as meta/classes/populate_sdk_base.bbclass:

fakeroot create_shar() {
    cat &lt;&lt; &quot;EOF&quot; &gt; ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
usage()
{
    echo &quot;test&quot;
 ######The below &quot;}&quot; causes error######
}
EOF
}

There would be an error because of the &quot;}&quot; before the last EOF:

&lt;&lt;Running result&gt;&gt;
jiahongxu:build$ bitbake meta-toolchain
Loading cache: 100% |###########################################|
ETA:  00:00:00
Loaded 1117 entries from dependency cache.
ERROR: ParseError at /home/jiahongxu/yocto/poky/meta/classes/popu
late_sdk_base.bbclass:127: unparsed line: &apos;INST_ARCH=$(uname -m |
sed -e &quot;s/i[3-6]86/ix86/&quot; -e &quot;s/x86[-_]64/x86_64/&quot;)&apos;
ERROR: Command execution failed: Exited with 1

This is because the lib/bb/parse/parse_py/BBHandler.py treats the
beginning &quot;}&quot; as the end of the function.

* Resolution:

1) Check whether the &quot;}&quot; is the end of the function or not would fix the problem. See the patch below for details.

2) Another solution is that don&apos;t use the &quot;}&quot; at the beginning of the
line inside the function, just keep some spaces before &quot;}&quot;.


diff --git a/bitbake/lib/bb/parse/parse_py/BBHandler.py b/bitbake/lib/bb/parse/parse_py/BBHandler.py
index 2e0647b..dcf45c6 100644
--- a/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -46,6 +46,20 @@ __addhandler_regexp__    = re.compile( r&quot;addhandler\s+(.+)&quot; )
 __def_regexp__           = re.compile( r&quot;def\s+(\w+).*:&quot; )
 __python_func_regexp__   = re.compile( r&quot;(\s+.*)|(^$)&quot; )
 
+# Match the shell function defined inside
+# function(){
+# }
+# 
+# or (the &quot;{&quot; in the next line)
+#
+# function()
+# {
+# }
+__left_curly_bracket_def_func_regexp__     = re.compile( r&quot;([\w]+\s*\(\s*\)\s*{\s*$)|({\s*$)&quot; )
+
+# Save the number of the curly bracket pairs which are used for inside
+# sub functions.
+__curly_bracket_pair_num__ = 0
 
 __infunc__ = &quot;&quot;
 __inpython__ = False
@@ -112,6 +126,7 @@ def handle(fn, d, include):
     __infunc__ = &quot;&quot;
     __classname__ = &quot;&quot;
     __residue__ = []
+    __curly_bracket_pair_num__ = 0
 
 
     if include == 0:
@@ -165,16 +180,59 @@ def handle(fn, d, include):
 
     return d
 
+# In function body, the following regexps should never be matched,
+# if matched, the shellstr is invalid.
+def check_shellstr_valid(shellstr):
+    m = __def_regexp__.match(shellstr)
+    if m:
+        return False
+
+    m = __export_func_regexp__.match(shellstr)
+    if m:
+        return False
+
+    m = __addtask_regexp__.match(shellstr)
+    if m:
+        return False
+
+    m = __addhandler_regexp__.match(shellstr)
+    if m:
+        return False
+
+    m = __inherit_regexp__.match(shellstr)
+    if m:
+        return False
+    return True
+
 def feeder(lineno, s, fn, root, statements):
-    global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__, __infunc__, __body__, classes, bb, __residue__
+    global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__, __infunc__, __body__, classes, bb, __residue__, __curly_bracket_pair_num__, __left_curly_bracket_def_func_regexp__
     if __infunc__:
-        if s == &apos;}&apos;:
+
+        if not check_shellstr_valid(s):
+            return ConfHandler.feeder(lineno, s, fn, statements) 
+
+        # If matched, it means the &quot;{&quot; is the start of a new shell
+        # sub function inside the function body.
+        m = __left_curly_bracket_def_func_regexp__.match(s)
+        if m:
+            __curly_bracket_pair_num__ += 1
+
+        # If matched, it means the &quot;}&quot; is the end of a new shell
+        # sub function inside the function body.
+        elif s== &apos;}&apos; and __curly_bracket_pair_num__ &gt; 0:
+            __curly_bracket_pair_num__ -= 1
+
+        # If matched, it means the &quot;}&quot; is the end of function body. 
+        elif s == &apos;}&apos; and __curly_bracket_pair_num__ == 0:
             __body__.append(&apos;&apos;)
             ast.handleMethod(statements, fn, lineno, __infunc__, __body__)
             __infunc__ = &quot;&quot;
             __body__ = []
-        else:
-            __body__.append(s)
+            return
+
+        # Except the &quot;}&quot; which is the end of function body, all other
+        # shell string should be appended to the function body
+        __body__.append(s)
         return
 
     if __inpython__:
diff --git a/meta/classes/populate_sdk_base.bbclass b/meta/classes/populate_sdk_base.bbclass
index dc715c4..baa0db8 100644
--- a/meta/classes/populate_sdk_base.bbclass
+++ b/meta/classes/populate_sdk_base.bbclass
@@ -117,7 +117,13 @@ fakeroot tar_sdk() {
 fakeroot create_shar() {
 	cat &lt;&lt; &quot;EOF&quot; &gt; ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
 #!/bin/bash
+usage()
+{
+value=${pwd}
+test(){
+}
 
+}
 INST_ARCH=$(uname -m | sed -e &quot;s/i[3-6]86/ix86/&quot; -e &quot;s/x86[-_]64/x86_64/&quot;)
 SDKMACHINE=$(echo ${SDKMACHINE} | sed -e &quot;s/i[5-6]86/ix86/&quot;)
 
-- 
1.7.10.4</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>27763</commentid>
    <comment_count>1</comment_count>
    <who name="Richard Purdie">richard.purdie</who>
    <bug_when>2012-11-28 08:08:34 +0000</bug_when>
    <thetext>To do this properly we&apos;d effectively need to write a shell parser.
Rather than writing our own, I&apos;d much rather use the existing shell
parsing code we have in the bitbake tree.

The trouble is that if we get this wrong, we&apos;ll create subtle bugs where
some syntax works but other valid shell syntax does not. I really don&apos;t
want to get into this as I think we&apos;ll end up with more subtle bugs and
a hugely complex parser for no real net gain.

I therefore think at least for now, stating that you must use
indentation is the way to proceed so we should document this problem.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>27894</commentid>
    <comment_count>2</comment_count>
    <who name="Hongxu Jia">hongxu.jia</who>
    <bug_when>2012-12-03 12:10:08 +0000</bug_when>
    <thetext>I agree with Richard. We should explain this in document:

In bitbake recipe files, indentation is the way to proceed.
Here is the example:
----Example file example.bb
fakeroot create_shar() {
    cat &lt;&lt; &quot;EOF&quot; &gt; ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
    usage()
    {
        echo &quot;This is really a ugly resolution.&quot;
    }
EOF
}</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>28157</commentid>
    <comment_count>3</comment_count>
    <who name="Scott Rifenbark">srifenbark</who>
    <bug_when>2012-12-11 20:56:07 +0000</bug_when>
    <thetext>Currently, there is a section in the dev-manual called &quot;Adding a Package&quot; (http://www.yoctoproject.org/docs/1.4/dev-manual/dev-manual.html#usingpoky-extend-addpkg).  I would like to add a note about this behaviour right up front where it talks about the user needing to write a recipe.  Also, there is a helloworld exmaple in the section that I don&apos;t think follows the indentation we are going to suggest. 

What would the properly indented helloworld file look like?

Scott</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>30171</commentid>
    <comment_count>4</comment_count>
    <who name="Stoicescu Cornel">corneliux.stoicescu</who>
    <bug_when>2013-02-27 15:03:57 +0000</bug_when>
    <thetext>Hongxu, can you please help Scott wrap up the documentation for this? 

Thanks!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>30221</commentid>
    <comment_count>5</comment_count>
    <who name="Hongxu Jia">hongxu.jia</who>
    <bug_when>2013-02-28 08:01:36 +0000</bug_when>
    <thetext>I think it&apos;s better to emphasize an exception about the useage of curly brace in shell function. If use a pair of curly brace in shell function, the colse curly brace must not be located at the leading line(leave some spaves ahead). Such as:

There is an exception about the useage of close curly brace in shell function:
1,Invalid------------------
fakeroot create_shar() {
    cat &lt;&lt; &quot;EOF&quot; &gt; ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
usage()
{
  echo &quot;test&quot;
  ######The below &quot;}&quot; at the leading line causes error######
}
EOF
}

2, Valid-----------------
fakeroot create_shar() {
    cat &lt;&lt; &quot;EOF&quot; &gt; ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
usage()
{
  echo &quot;test&quot;
  ######The below &quot;}&quot; leaves some spaces is ok######
 }
EOF
}</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>30346</commentid>
    <comment_count>6</comment_count>
    <who name="Scott Rifenbark">srifenbark</who>
    <bug_when>2013-03-01 21:44:14 +0000</bug_when>
    <thetext>Added a note in the overview section describing how to add a package.  The section talks about writing recipes.  Please review the note at http://www.yoctoproject.org/docs/1.4/dev-manual/dev-manual.html#usingpoky-extend-addpkg.

Scott</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>32818</commentid>
    <comment_count>7</comment_count>
    <who name="Jessica">jessica.zhang</who>
    <bug_when>2013-05-01 15:58:00 +0000</bug_when>
    <thetext>In 1.4 official doc</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>32835</commentid>
    <comment_count>8</comment_count>
    <who name="Stoicescu Cornel">corneliux.stoicescu</who>
    <bug_when>2013-05-02 07:57:53 +0000</bug_when>
    <thetext>Verified.</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>