summary refs log blame commit diff stats
path: root/doc/examples/plugin_chmod_keybindings.py
blob: 0ab975ed61413e307124474b64a9cb972c6366d7 (plain) (tree)
1
2
3
4
5
6
7
8
9

                              



                                                                            

                                    
 
                  
                     
 

                                                         
                                    


                                                               
 
                                
# Compatible with ranger 1.6.*
#
# This plugin serves as an example for adding key bindings through a plugin.
# It could replace the ten lines in the rc.conf that create the key bindings
# for the "chmod" command.

import ranger.api
old_hook_init = ranger.api.hook_init

def hook_init(fm):
    old_hook_init(fm)

    # Generate key bindings for the chmod command
    command = "map {0}{1}{2} shell -d chmod {1}{0}{2} %s"
    for mode in list('ugoa') + ['']:
        for perm in "rwxXst":
            fm.execute_console(command.format('-', mode, perm))
            fm.execute_console(command.format('+', mode, perm))

ranger.api.hook_init = hook_init
="na">name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> <meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> <meta name="colorscheme" content="minimal"> <style type="text/css"> <!-- pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 12pt; font-size: 1em; } .Constant { color: #00a0a0; } .cSpecial { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #800080; } .Special { color: #c00000; } .Identifier { color: #fcb165; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } --> </style> <script type='text/javascript'> <!-- --> </script> </head> <body> <pre id='vimCodeElement'> <span class="Comment">//: Clean syntax to manipulate and check the file system in scenarios.</span> <span class="Comment">//: Instructions 'assume-filesystem' and 'filesystem-should-contain' implicitly create</span> <span class="Comment">//: a variable called 'filesystem' that is accessible to later instructions in</span> <span class="Comment">//: the scenario. 'filesystem-should-contain' can check unicode characters in</span> <span class="Comment">//: the fake filesystem</span> <span class="Delimiter">:(scenarios run_mu_scenario)</span> <span class="Delimiter">:(scenario simple_filesystem)</span> scenario assume-filesystem [ local-scope assume-filesystem [ <span class="Comment"># file 'a' containing two lines of data</span> [a]<span class="Special"> &lt;- </span>[ |a bc| |de f| ] <span class="Comment"># directory 'b' containing two files, 'c' and 'd'</span> [b/c]<span class="Special"> &lt;- </span>[] [b/d]<span class="Special"> &lt;- </span>[ |xyz| ] ] <span class="Normal">data</span>:address:array:file-mapping<span class="Special"> &lt;- </span>get *filesystem:address:filesystem<span class="Delimiter">,</span> data:offset <span class="Normal">file1</span>:file-mapping<span class="Special"> &lt;- </span>index *data<span class="Delimiter">,</span> <span class="Constant">0</span> file1-name:address:array:character<span class="Special"> &lt;- </span>get file1<span class="Delimiter">,</span> name:offset <span class="Constant">10</span>:array:character/<span class="Special">raw &lt;- </span>copy *file1-name file1-contents:address:array:character<span class="Special"> &lt;- </span>get file1<span class="Delimiter">,</span> contents:offset <span class="Constant">100</span>:array:character/<span class="Special">raw &lt;- </span>copy *file1-contents <span class="Normal">file2</span>:file-mapping<span class="Special"> &lt;- </span>index *data<span class="Delimiter">,</span> <span class="Constant">1</span> file2-name:address:array:character<span class="Special"> &lt;- </span>get file2<span class="Delimiter">,</span> name:offset <span class="Constant">30</span>:array:character/<span class="Special">raw &lt;- </span>copy *file2-name file2-contents:address:array:character<span class="Special"> &lt;- </span>get file2<span class="Delimiter">,</span> contents:offset <span class="Constant">40</span>:array:character/<span class="Special">raw &lt;- </span>copy *file2-contents <span class="Normal">file3</span>:file-mapping<span class="Special"> &lt;- </span>index *data<span class="Delimiter">,</span> <span class="Constant">2</span> file3-name:address:array:character<span class="Special"> &lt;- </span>get file3<span class="Delimiter">,</span> name:offset <span class="Constant">50</span>:array:character/<span class="Special">raw &lt;- </span>copy *file3-name file3-contents:address:array:character<span class="Special"> &lt;- </span>get file3<span class="Delimiter">,</span> contents:offset <span class="Constant">60</span>:array:character/<span class="Special">raw &lt;- </span>copy *file3-contents memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>[a] <span class="Constant">100</span>:array:character<span class="Special"> &lt;- </span>[a bc de f ] <span class="Constant">30</span>:array:character<span class="Special"> &lt;- </span>[b/c] <span class="Constant">40</span>:array:character<span class="Special"> &lt;- </span>[] <span class="Constant">50</span>:array:character<span class="Special"> &lt;- </span>[b/d] <span class="Constant">60</span>:array:character<span class="Special"> &lt;- </span>[xyz ] ] ] <span class="Delimiter">:(scenario escaping_file_contents)</span> scenario assume-filesystem [ local-scope assume-filesystem [ <span class="Comment"># file 'a' containing a '|'</span> <span class="Comment"># need to escape '\' once for each block</span> [a]<span class="Special"> &lt;- </span>[ |x\\\\|yz| ] ] <span class="Normal">data</span>:address:array:file-mapping<span class="Special"> &lt;- </span>get *filesystem:address:filesystem<span class="Delimiter">,</span> data:offset <span class="Normal">file1</span>:file-mapping<span class="Special"> &lt;- </span>index *data<span class="Delimiter">,</span> <span class="Constant">0</span> file1-name:address:array:character<span class="Special"> &lt;- </span>get file1<span class="Delimiter">,</span> name:offset <span class="Constant">10</span>:array:character/<span class="Special">raw &lt;- </span>copy *file1-name file1-contents:address:array:character<span class="Special"> &lt;- </span>get file1<span class="Delimiter">,</span> contents:offset <span class="Constant">20</span>:array:character/<span class="Special">raw &lt;- </span>copy *file1-contents memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>[a] <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span>[x|yz ] ] ] <span class="Delimiter">:(before &quot;End Globals&quot;)</span> <span class="Normal">const</span> <span class="Normal">int</span> FILESYSTEM = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span> <span class="Comment">//: give 'filesystem' a fixed location in scenarios</span> <span class="Delimiter">:(before &quot;End Special Scenario Variable Names(r)&quot;)</span> Name[r][<span class="Constant">&quot;filesystem&quot;</span>] = FILESYSTEM<span class="Delimiter">;</span> <span class="Comment">//: make 'filesystem' always a raw location in scenarios</span> <span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>s == <span class="Constant">&quot;filesystem&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End initialize_transform_rewrite_literal_string_to_text()&quot;)</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">&quot;assume-filesystem&quot;</span><span class="Delimiter">);</span> <span class="Comment">//: screen-should-contain is a regular instruction</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> ASSUME_FILESYSTEM<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;assume-filesystem&quot;</span><span class="Delimiter">,</span> ASSUME_FILESYSTEM<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> <span class="Normal">case</span> ASSUME_FILESYSTEM: <span class="Delimiter">{</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> <span class="Normal">case</span> ASSUME_FILESYSTEM: <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> assume_filesystem<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">,</span> current_recipe_name<span class="Delimiter">());</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> assume_filesystem<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; data<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> map&lt;string<span class="Delimiter">,</span> string&gt; contents<span class="Delimiter">;</span> parse_filesystem<span class="Delimiter">(</span>data<span class="Delimiter">,</span> contents<span class="Delimiter">,</span> caller<span class="Delimiter">);</span> construct_filesystem_object<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">void</span> parse_filesystem<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; data<span class="Delimiter">,</span> map&lt;string<span class="Delimiter">,</span> string&gt;&amp; out<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> istringstream in<span class="Delimiter">(</span>data<span class="Delimiter">);</span> in &gt;&gt; std::noskipws<span class="Delimiter">;</span> <span class="Normal">while</span> <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> string filename = next_filesystem_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>*filename<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;' must begin with a '['</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>*filename<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> != <span class="Constant">']'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;' must end with a ']'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> filename<span class="Delimiter">.</span>erase<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> filename<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>filename<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: no data for filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> string arrow = next_filesystem_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>arrow != <span class="Constant">&quot;&lt;-&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: expected '&lt;-' after filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;' but got '&quot;</span> &lt;&lt; arrow &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: no data for filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;' after '&lt;-'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> string contents = next_filesystem_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>*contents<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: file contents '&quot;</span> &lt;&lt; contents &lt;&lt; <span class="Constant">&quot;' for filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;' must begin with a '['</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>*contents<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> != <span class="Constant">']'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: file contents '&quot;</span> &lt;&lt; contents &lt;&lt; <span class="Constant">&quot;' for filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;' must end with a ']'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> contents<span class="Delimiter">.</span>erase<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> contents<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">);</span> put<span class="Delimiter">(</span>out<span class="Delimiter">,</span> filename<span class="Delimiter">,</span> munge_filesystem_contents<span class="Delimiter">(</span>contents<span class="Delimiter">,</span> filename<span class="Delimiter">,</span> caller<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> string munge_filesystem_contents<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; data<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; filename<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>data<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span> istringstream in<span class="Delimiter">(</span>data<span class="Delimiter">);</span> in &gt;&gt; std::noskipws<span class="Delimiter">;</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> ostringstream out<span class="Delimiter">;</span> <span class="Normal">while</span> <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="Constant">'|'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: file contents for filename '&quot;</span> &lt;&lt; filename &lt;&lt; <span class="Constant">&quot;' must be delimited in '|'s</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Comment">// skip leading '|'</span> string line<span class="Delimiter">;</span> getline<span class="Delimiter">(</span>in<span class="Delimiter">,</span> line<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>line<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>line<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == <span class="Constant">'|'</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>line<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == <span class="cSpecial">'\\'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> ++i<span class="Delimiter">;</span> <span class="Comment">// skip</span> <span class="Normal">if</span> <span class="Delimiter">(</span>i == SIZE<span class="Delimiter">(</span>line<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise &lt;&lt; caller &lt;&lt; <span class="Constant">&quot;: assume-filesystem: file contents can't end a line with '</span><span class="cSpecial">\\</span><span class="Constant">'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> out &lt;&lt; line<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// todo: some way to represent a file without a final newline</span> out &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Normal">void</span> construct_filesystem_object<span class="Delimiter">(</span><span class="Normal">const</span> map&lt;string<span class="Delimiter">,</span> string&gt;&amp; contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">int</span> filesystem_data_address = allocate<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">)</span>*<span class="Constant">2</span> + <span class="Comment">/*</span><span class="Comment">array length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> <span class="Normal">int</span> curr = filesystem_data_address + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> + <span class="Comment">/*</span><span class="Comment">skip array length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Normal">for</span> <span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> string&gt;::const_iterator p = contents<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != contents<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">,</span> new_mu_string<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>first<span class="Delimiter">));</span> curr++<span class="Delimiter">;</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">,</span> new_mu_string<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">));</span> curr++<span class="Delimiter">;</span> <span class="Delimiter">}</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> filesystem_data_address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">));</span> <span class="Comment">// size of array</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> filesystem_data_address<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// initialize refcount</span> <span class="Comment">// wrap the filesystem data in a filesystem object</span> <span class="Normal">int</span> filesystem_address = allocate<span class="Delimiter">(</span>size_of_filesystem<span class="Delimiter">());</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> filesystem_address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> filesystem_data_address<span class="Delimiter">);</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> filesystem_address<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// initialize refcount</span> <span class="Comment">// save in product</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> FILESYSTEM<span class="Delimiter">,</span> filesystem_address<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">int</span> size_of_filesystem<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Comment">// memoize result if already computed</span> <span class="Normal">static</span> <span class="Normal">int</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>result<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;filesystem&quot;</span><span class="Delimiter">));</span> type_tree* type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">&quot;filesystem&quot;</span><span class="Delimiter">);</span> result = size_of<span class="Delimiter">(</span>type<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Normal">delete</span> type<span class="Delimiter">;</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> string next_filesystem_word<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> string result = slurp_quoted<span class="Delimiter">(</span>in<span class="Delimiter">);</span> skip_whitespace_and_comments_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> ostringstream out<span class="Delimiter">;</span> slurp_word<span class="Delimiter">(</span>in<span class="Delimiter">,</span> out<span class="Delimiter">);</span> skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Normal">void</span> skip_whitespace<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">while</span> <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()))</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> <span class="Normal">else</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> </pre> </body> </html> <!-- vim: set foldmethod=manual : -->