title: Flex - create a buffer state from a string WITHOUT setting it as the active buffer
body: <p><a href="http://westes.github.io/flex/manual/Multiple-Input-Buffers.html" rel="nofollow noreferrer">Flex manual on Multiple Input Buffers</a></p>
  
  <p>You can see there:</p>
  
  <blockquote>
    <p>The following routines are available for setting up input buffers for scanning in-memory strings instead of files. All of them create a new input buffer for scanning the string, and return a corresponding YY_BUFFER_STATE handle (which you should delete with yy_delete_buffer() when done with it). They also switch to the new buffer using yy_switch_to_buffer(), so the next call to yylex() will start scanning the string. </p>
  </blockquote>
  
  <p>Then you have <code>yy_scan_string</code> and such</p>
  
  <p>Usually Flex's default settings are fine, I have one file to scan or only need the one scanner however this task is different. </p>
  
  <p>I am trying to create a scanner able to scan multiple files and some strings. It is reentrant and I've never used YY_INPUT() before.</p>
  
  <p>So my question is as follows:</p>
  
  <p>When a buffer is finished and there's nothing left to scan does Flex pop that state off the stack and if there's another state start scanning that how it left off? </p>
  
  <p>By how it left off I mean as if it were mid-way through a rule. suppose I try and match <code>ab</code>, if one state ends with <code>a</code> and another starts with <code>b</code> how is that treated? </p>
  
  <hr>
  
  <p><strong>Problem</strong></p>
  
  <pre><code>/** Pushes the new state onto the stack. The new state becomes
   *  the current state. This function will allocate the stack
   *  if necessary.
   *  @param new_buffer The new state.
   *  @param yyscanner The scanner object.
   */
  void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
  {
      struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
      if (new_buffer == NULL)
          return;
  
      yyensure_buffer_stack(yyscanner);
  
      /* This block is copied from yy_switch_to_buffer. */
      if ( YY_CURRENT_BUFFER )
          {
          /* Flush out information for old buffer. */
          *yyg-&gt;yy_c_buf_p = yyg-&gt;yy_hold_char;
          YY_CURRENT_BUFFER_LVALUE-&gt;yy_buf_pos = yyg-&gt;yy_c_buf_p;
          YY_CURRENT_BUFFER_LVALUE-&gt;yy_n_chars = yyg-&gt;yy_n_chars;
          }
  
      /* Only push if top exists. Otherwise, replace top. */
      if (YY_CURRENT_BUFFER)
          yyg-&gt;yy_buffer_stack_top++;
      YY_CURRENT_BUFFER_LVALUE = new_buffer;
  
      /* copied from yy_switch_to_buffer. */
      yy_load_buffer_state(yyscanner );
      yyg-&gt;yy_did_buffer_switch_on_eof = 1;
  }
  </code></pre>
  
  <p>Pushing null wont work</p>
  
  <h2><strong>Old stuff</strong></h2>
  
  <p><strong>What I expect</strong></p>
  
  <p>I'd hope that <code>yylex</code> returning 0 means end of buffer (and gives me a chance to manipulate them)</p>
  
  <p>I'd also hope that unless I restart the scanner it will carry on right where it left off (so <code>ab</code> would be matched if one buffer ended with a and another started with b, unless I explicitly restart the scanner)</p>
  
  <p><strong>Secondly</strong>, how can I prepare a string buffer without having flex set it as the active buffer. </p>
  
  <p>I suppose I could create a new "null" buffer (see the create buffer function in the link) push that, then push this onto the stack.</p>
  
  <p>When I go to create a buffer from a string I expect that function to set the input buffer, which is the top of the input stack, which will harmlessly delete my "null" buffer. </p>
  
  <p>This seems quite messy for something otherwise so lovely.</p>
  
  <p><strong>Reasons for asking</strong></p>
  
  <p>Testing this would be very difficult. I'd also have to assume I know how flex works correctly then design tests that pass or fail based on how I think it works to see if it really does. This'd take a long time and I could be unlucky in getting results that support my model, even if it is wrong. </p>