https://github.com/akkartik/mu/blob/main/124next-token.subx
   1 # Some tokenization primitives.
   2 
   3 == code
   4 #   instruction                     effective address                                                   register    displacement    immediate
   5 # . op          subop               mod             rm32          base        index         scale       r32
   6 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
   7 
   8 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary)
   9 # on reaching end of file, return an empty interval
  10 next-token:  # in: (addr stream byte), delimiter: byte, out: (addr slice)
  11     # . prologue
  12     55/push-ebp
  13     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
  14     # . save registers
  15     50/push-eax
  16     51/push-ecx
  17     56/push-esi
  18     57/push-edi
  19     # esi = in
  20     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
  21     # edi = out
  22     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   0x10/disp8      .                 # copy *(ebp+16) to edi
  23     # skip-chars-matching(in, delimiter)
  24     # . . push args
  25     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
  26     56/push-esi
  27     # . . call
  28     e8/call  skip-chars-matching/disp32
  29     # . . discard args
  30     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
  31     # out->start = &in->data[in->read]
  32     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
  33     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   0xc/disp8       .                 # copy esi+ecx+12 to eax
  34     89/copy                         0/mod/indirect  7/rm32/edi    .           .             .           0/r32/eax   .               .                 # copy eax to *edi
  35     # skip-chars-not-matching(in, delimiter)
  36     # . . push args
  37     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
  38     56/push-esi
  39     # . . call
  40     e8/call  skip-chars-not-matching/disp32
  41     # . . discard args
  42     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
  43     # out->end = &in->data[in->read]
  44     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
  45     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/eax   0xc/disp8       .                 # copy esi+ecx+12 to eax
  46     89/copy                         1/mod/*+disp8   7/rm32/edi    .           .             .           0/r32/eax   4/disp8         .                 # copy eax to *(edi+4)
  47     # . restore registers
  48     5f/pop-to-edi
  49     5e/pop-to-esi
  50     59/pop-to-ecx
  51     58/pop-to-eax
  52     # . epilogue
  53     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
  54     5d/pop-to-ebp
  55     c3/return
  56 
  57 test-next-token:
  58     # . prologue
  59     55/push-ebp
  60     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
  61     # setup
  62     # . clear-stream(_test-stream)
  63     # . . push args
  64     68/push  _test-stream/imm32
  65     # . . call
  66     e8/call  clear-stream/disp32
  67     # . . discard args
  68     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
  69     # var slice/ecx: slice
  70     68/push  0/imm32/end
  71     68/push  0/imm32/start
  72     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
  73     # write(_test-stream, "  ab")
  74     # . . push args
  75     68/push  "  ab"/imm32
  76     68/push  _test-stream/imm32
  77     # . . call
  78     e8/call  write/disp32
  79     # . . discard args
  80     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
  81     # next-token(_test-stream, 0x20/space, slice)
  82     # . . push args
  83     51/push-ecx
  84     68/push  0x20/imm32
  85     68/push  _test-stream/imm32
  86     # . . call
  87     e8/call  next-token/disp32
  88     # . . discard args
  89     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
  90     # check-ints-equal(slice->start - _test-stream->data, 2, msg)
  91     # . check-ints-equal(slice->start - _test-stream, 14, msg)
  92     # . . push args
  93     68/push  "F - test-next-token: start"/imm32
  94     68/push  0xe/imm32
  95     # . . push slice->start - _test-stream
  96     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # copy *ecx to eax
  97     81          5/subop/subtract    3/mod/direct    0/rm32/eax    .           .             .           .           .               _test-stream/imm32 # subtract from eax
  98     50/push-eax
  99     # . . call
 100     e8/call  check-ints-equal/disp32
 101     # . . discard args
 102     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 103     # check-ints-equal(slice->end - _test-stream->data, 4, msg)
 104     # . check-ints-equal(slice->end - _test-stream, 16, msg)
 105     # . . push args
 106     68/push  "F - test-next-token: end"/imm32
 107     68/push  0x10/imm32
 108     # . . push slice->end - _test-stream
 109     8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .             .           0/r32/eax   4/disp8         .                 # copy *(ecx+4) to eax
 110     81          5/subop/subtract    3/mod/direct    0/rm32/eax    .           .             .           .           .               _test-stream/imm32 # subtract from eax
 111     50/push-eax
 112     # . . call
 113     e8/call  check-ints-equal/disp32
 114     # . . discard args
 115     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 116     # . epilogue
 117     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 118     5d/pop-to-ebp
 119     c3/return
 120 
 121 test-next-token-Eof:
 122     # . prologue
 123     55/push-ebp
 124     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 125     # setup
 126     # . clear-stream(_test-stream)
 127     # . . push args
 128     68/push  _test-stream/imm32
 129     # . . call
 130     e8/call  clear-stream/disp32
 131     # . . discard args
 132     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 133     # var slice/ecx: slice
 134     68/push  0/imm32/end
 135     68/push  0/imm32/start
 136     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
 137     # write nothing to _test-stream
 138     # next-token(_test-stream, 0x20/space, slice)
 139     # . . push args
 140     51/push-ecx
 141     68/push  0x20/imm32
 142     68/push  _test-stream/imm32
 143     # . . call
 144     e8/call  next-token/disp32
 145     # . . discard args
 146     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 147     # check-ints-equal(slice->end, slice->start, msg)
 148     # . . push args
 149     68/push  "F - test-next-token-Eof"/imm32
 150     ff          6/subop/push        1/mod/*+disp8   1/rm32/ecx    .           .             .           .           4/disp8         .                 # push *(ecx+4)
 151     ff          6/subop/push        0/mod/indirect  1/rm32/ecx    .           .             .           .           .               .                 # push *ecx
 152     # . . call
 153     e8/call  check-ints-equal/disp32
 154     # . . discard args
 155     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 156     # . epilogue
 157     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 158     5d/pop-to-ebp
 159     c3/return
 160 
 161 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary)
 162 # on reaching end of file, return an empty interval
 163 next-token-from-slice:  # start: (addr byte), end: (addr byte), delimiter: byte, out: (addr slice)
 164     # . prologue
 165     55/push-ebp
 166     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 167     # . save registers
 168     50/push-eax
 169     51/push-ecx
 170     52/push-edx
 171     57/push-edi
 172     # ecx = end
 173     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0xc/disp8       .                 # copy *(ebp+12) to ecx
 174     # edx = delimiter
 175     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0x10/disp8      .                 # copy *(ebp+16) to edx
 176     # edi = out
 177     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   0x14/disp8      .                 # copy *(ebp+20) to edi
 178     # eax = skip-chars-matching-in-slice(start, end, delimiter)
 179     # . . push args
 180     52/push-edx
 181     51/push-ecx
 182     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
 183     # . . call
 184     e8/call  skip-chars-matching-in-slice/disp32
 185     # . . discard args
 186     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 187     # out->start = eax
 188     89/copy                         0/mod/indirect  7/rm32/edi    .           .             .           0/r32/eax   .               .                 # copy eax to *edi
 189     # eax = skip-chars-not-matching-in-slice(eax, end, delimiter)
 190     # . . push args
 191     52/push-edx
 192     51/push-ecx
 193     50/push-eax
 194     # . . call
 195     e8/call  skip-chars-not-matching-in-slice/disp32
 196     # . . discard args
 197     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 198     # out->end = eax
 199     89/copy                         1/mod/*+disp8   7/rm32/edi    .           .             .           0/r32/eax   4/disp8         .                 # copy eax to *(edi+4)
 200     # . restore registers
 201     5f/pop-to-edi
 202     5a/pop-to-edx
 203     59/pop-to-ecx
 204     58/pop-to-eax
 205     # . epilogue
 206     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 207     5d/pop-to-ebp
 208     c3/return
 209 
 210 test-next-token-from-slice:
 211     # . prologue
 212     55/push-ebp
 213     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 214     # (eax..ecx) = "  ab"
 215     b8/copy-to-eax  "  ab"/imm32
 216     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
 217     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
 218     05/add-to-eax  4/imm32
 219     # var out/edi: slice
 220     68/push  0/imm32/end
 221     68/push  0/imm32/start
 222     89/copy                         3/mod/direct    7/rm32/edi    .           .             .           4/r32/esp   .               .                 # copy esp to edi
 223     # next-token-from-slice(eax, ecx, 0x20/space, out)
 224     # . . push args
 225     57/push-edi
 226     68/push  0x20/imm32
 227     51/push-ecx
 228     50/push-eax
 229     # . . call
 230     e8/call  next-token-from-slice/disp32
 231     # . . discard args
 232     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
 233     # out->start should be at the 'a'
 234     # . check-ints-equal(out->start - in->start, 2, msg)
 235     # . . push args
 236     68/push  "F - test-next-token-from-slice: start"/imm32
 237     68/push  2/imm32
 238     # . . push out->start - in->start
 239     8b/copy                         0/mod/indirect  7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # copy *edi to ecx
 240     2b/subtract                     3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # subtract eax from ecx
 241     51/push-ecx
 242     # . . call
 243     e8/call  check-ints-equal/disp32
 244     # . . discard args
 245     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 246     # out->end should be after the 'b'
 247     # check-ints-equal(out->end - in->start, 4, msg)
 248     # . . push args
 249     68/push  "F - test-next-token-from-slice: end"/imm32
 250     68/push  4/imm32
 251     # . . push out->end - in->start
 252     8b/copy                         1/mod/*+disp8   7/rm32/edi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(edi+4) to ecx
 253     2b/subtract                     3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # subtract eax from ecx
 254     51/push-ecx
 255     # . . call
 256     e8/call  check-ints-equal/disp32
 257     # . . discard args
 258     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 259     # . epilogue
 260     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 261     5d/pop-to-ebp
 262     c3/return
 263 
 264 test-next-token-from-slice-Eof:
 265     # . prologue
 266     55/push-ebp
 267     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 268     # var out/edi: slice
 269     68/push  0/imm32/end
 270     68/push  0/imm32/start
 271     89/copy                         3/mod/direct    7/rm32/edi    .           .             .           4/r32/esp   .               .                 # copy esp to edi
 272     # next-token-from-slice(0, 0, 0x20/space, out)
 273     # . . push args
 274     57/push-edi
 275     68/push  0x20/imm32
 276     68/push  0/imm32
 277     68/push  0/imm32
 278     # . . call
 279     e8/call  next-token-from-slice/disp32
 280     # . . discard args
 281     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
 282     # out should be empty
 283     # . check-ints-equal(out->end - out->start, 0, msg)
 284     # . . push args
 285     68/push  "F - test-next-token-from-slice-Eof"/imm32
 286     68/push  0/imm32
 287     # . . push out->start - in->start
 288     8b/copy                         1/mod/*+disp8   7/rm32/edi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(edi+4) to ecx
 289     2b/subtract                     0/mod/indirect  7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # subtract *edi from ecx
 290     51/push-ecx
 291     # . . call
 292     e8/call  check-ints-equal/disp32
 293     # . . discard args
 294     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 295     # . epilogue
 296     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 297     5d/pop-to-ebp
 298     c3/return
 299 
 300 test-next-token-from-slice-nothing:
 301     # . prologue
 302     55/push-ebp
 303     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 304     # (eax..ecx) = "    "
 305     b8/copy-to-eax  "    "/imm32
 306     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
 307     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
 308     05/add-to-eax  4/imm32
 309     # var out/edi: slice
 310     68/push  0/imm32/end
 311     68/push  0/imm32/start
 312     89/copy                         3/mod/direct    7/rm32/edi    .           .             .           4/r32/esp   .               .                 # copy esp to edi
 313     # next-token-from-slice(in, 0x20/space, out)
 314     # . . push args
 315     57/push-edi
 316     68/push  0x20/imm32
 317     51/push-ecx
 318     50/push-eax
 319     # . . call
 320     e8/call  next-token-from-slice/disp32
 321     # . . discard args
 322     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
 323     # out should be empty
 324     # . check-ints-equal(out->end - out->start, 0, msg)
 325     # . . push args
 326     68/push  "F - test-next-token-from-slice-Eof"/imm32
 327     68/push  0/imm32
 328     # . . push out->start - in->start
 329     8b/copy                         1/mod/*+disp8   7/rm32/edi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(edi+4) to ecx
 330     2b/subtract                     0/mod/indirect  7/rm32/edi    .           .             .           1/r32/ecx   .               .                 # subtract *edi from ecx
 331     51/push-ecx
 332     # . . call
 333     e8/call  check-ints-equal/disp32
 334     # . . discard args
 335     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 336     # . epilogue
 337     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 338     5d/pop-to-ebp
 339     c3/return
 340 
 341 skip-chars-matching:  # in: (addr stream byte), delimiter: byte
 342     # . prologue
 343     55/push-ebp
 344     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 345     # . save registers
 346     50/push-eax
 347     51/push-ecx
 348     52/push-edx
 349     53/push-ebx
 350     56/push-esi
 351     # esi = in
 352     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
 353     # ecx = in->read
 354     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
 355     # ebx = in->write
 356     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           3/r32/ebx   .               .                 # copy *esi to ebx
 357     # edx = delimiter
 358     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
 359 $skip-chars-matching:loop:
 360     # if (in->read >= in->write) break
 361     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           3/r32/ebx   .               .                 # compare ecx with ebx
 362     7d/jump-if->=  $skip-chars-matching:end/disp8
 363     # eax = in->data[in->read]
 364     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
 365     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
 366     # if (eax != delimiter) break
 367     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax and edx
 368     75/jump-if-!=  $skip-chars-matching:end/disp8
 369     # ++in->read
 370     41/increment-ecx
 371     eb/jump  $skip-chars-matching:loop/disp8
 372 $skip-chars-matching:end:
 373     # persist in->read
 374     89/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy ecx to *(esi+4)
 375     # . restore registers
 376     5e/pop-to-esi
 377     5b/pop-to-ebx
 378     5a/pop-to-edx
 379     59/pop-to-ecx
 380     58/pop-to-eax
 381     # . epilogue
 382     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 383     5d/pop-to-ebp
 384     c3/return
 385 
 386 test-skip-chars-matching:
 387     # setup
 388     # . clear-stream(_test-stream)
 389     # . . push args
 390     68/push  _test-stream/imm32
 391     # . . call
 392     e8/call  clear-stream/disp32
 393     # . . discard args
 394     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 395     # write(_test-stream, "  ab")
 396     # . . push args
 397     68/push  "  ab"/imm32
 398     68/push  _test-stream/imm32
 399     # . . call
 400     e8/call  write/disp32
 401     # . . discard args
 402     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 403     # skip-chars-matching(_test-stream, 0x20/space)
 404     # . . push args
 405     68/push  0x20/imm32
 406     68/push  _test-stream/imm32
 407     # . . call
 408     e8/call  skip-chars-matching/disp32
 409     # . . discard args
 410     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 411     # check-ints-equal(_test-stream->read, 2, msg)
 412     # . . push args
 413     68/push  "F - test-skip-chars-matching"/imm32
 414     68/push  2/imm32
 415     # . . push *_test-stream->read
 416     b8/copy-to-eax  _test-stream/imm32
 417     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
 418     # . . call
 419     e8/call  check-ints-equal/disp32
 420     # . . discard args
 421     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 422     # end
 423     c3/return
 424 
 425 test-skip-chars-matching-none:
 426     # setup
 427     # . clear-stream(_test-stream)
 428     # . . push args
 429     68/push  _test-stream/imm32
 430     # . . call
 431     e8/call  clear-stream/disp32
 432     # . . discard args
 433     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 434     # write(_test-stream, "ab")
 435     # . . push args
 436     68/push  "ab"/imm32
 437     68/push  _test-stream/imm32
 438     # . . call
 439     e8/call  write/disp32
 440     # . . discard args
 441     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 442     # skip-chars-matching(_test-stream, 0x20/space)
 443     # . . push args
 444     68/push  0x20/imm32
 445     68/push  _test-stream/imm32
 446     # . . call
 447     e8/call  skip-chars-matching/disp32
 448     # . . discard args
 449     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 450     # check-ints-equal(_test-stream->read, 0, msg)
 451     # . . push args
 452     68/push  "F - test-skip-chars-matching-none"/imm32
 453     68/push  0/imm32
 454     # . . push *_test-stream->read
 455     b8/copy-to-eax  _test-stream/imm32
 456     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
 457     # . . call
 458     e8/call  check-ints-equal/disp32
 459     # . . discard args
 460     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 461     # end
 462     c3/return
 463 
 464 skip-chars-matching-whitespace:  # in: (addr stream byte)
 465     # . prologue
 466     55/push-ebp
 467     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 468     # . save registers
 469     50/push-eax
 470     51/push-ecx
 471     53/push-ebx
 472     56/push-esi
 473     # esi = in
 474     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
 475     # ecx = in->read
 476     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
 477     # ebx = in->write
 478     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           3/r32/ebx   .               .                 # copy *esi to ebx
 479 $skip-chars-matching-whitespace:loop:
 480     # if (in->read >= in->write) break
 481     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           3/r32/ebx   .               .                 # compare ecx with ebx
 482     7d/jump-if->=  $skip-chars-matching-whitespace:end/disp8
 483     # eax = in->data[in->read]
 484     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
 485     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
 486     # if (eax == ' ') goto body
 487     3d/compare-eax-and  0x20/imm32/space
 488     74/jump-if-=  $skip-chars-matching-whitespace:body/disp8
 489     # if (eax == '\n') goto body
 490     3d/compare-eax-and  0x0a/imm32/newline
 491     74/jump-if-=  $skip-chars-matching-whitespace:body/disp8
 492     # if (eax == '\t') goto body
 493     3d/compare-eax-and  0x09/imm32/tab
 494     74/jump-if-=  $skip-chars-matching-whitespace:body/disp8
 495     # if (eax != '\r') break
 496     3d/compare-eax-and  0x0d/imm32/cr
 497     75/jump-if-!=  $skip-chars-matching-whitespace:end/disp8
 498 $skip-chars-matching-whitespace:body:
 499     # ++in->read
 500     41/increment-ecx
 501     eb/jump  $skip-chars-matching-whitespace:loop/disp8
 502 $skip-chars-matching-whitespace:end:
 503     # persist in->read
 504     89/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy ecx to *(esi+4)
 505     # . restore registers
 506     5e/pop-to-esi
 507     5b/pop-to-ebx
 508     59/pop-to-ecx
 509     58/pop-to-eax
 510     # . epilogue
 511     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 512     5d/pop-to-ebp
 513     c3/return
 514 
 515 test-skip-chars-matching-whitespace:
 516     # setup
 517     # . clear-stream(_test-stream)
 518     # . . push args
 519     68/push  _test-stream/imm32
 520     # . . call
 521     e8/call  clear-stream/disp32
 522     # . . discard args
 523     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 524     # write(_test-stream, " \nab")
 525     # . . push args
 526     68/push  " \nab"/imm32
 527     68/push  _test-stream/imm32
 528     # . . call
 529     e8/call  write/disp32
 530     # . . discard args
 531     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 532     # skip-chars-matching-whitespace(_test-stream)
 533     # . . push args
 534     68/push  _test-stream/imm32
 535     # . . call
 536     e8/call  skip-chars-matching-whitespace/disp32
 537     # . . discard args
 538     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 539     # check-ints-equal(_test-stream->read, 2, msg)
 540     # . . push args
 541     68/push  "F - test-skip-chars-matching-whitespace"/imm32
 542     68/push  2/imm32
 543     # . . push *_test-stream->read
 544     b8/copy-to-eax  _test-stream/imm32
 545     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
 546     # . . call
 547     e8/call  check-ints-equal/disp32
 548     # . . discard args
 549     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 550     # end
 551     c3/return
 552 
 553 # minor fork of 'skip-chars-matching'
 554 skip-chars-not-matching:  # in: (addr stream byte), delimiter: byte
 555     # . prologue
 556     55/push-ebp
 557     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 558     # . save registers
 559     50/push-eax
 560     51/push-ecx
 561     52/push-edx
 562     53/push-ebx
 563     56/push-esi
 564     # esi = in
 565     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
 566     # ecx = in->read
 567     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
 568     # ebx = in->write
 569     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           3/r32/ebx   .               .                 # copy *esi to ebx
 570     # edx = delimiter
 571     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
 572 $skip-chars-not-matching:loop:
 573     # if (in->read >= in->write) break
 574     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           3/r32/ebx   .               .                 # compare ecx with ebx
 575     7d/jump-if->=  $skip-chars-not-matching:end/disp8
 576     # eax = in->data[in->read]
 577     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
 578     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
 579     # if (eax == delimiter) break
 580     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax and edx
 581     74/jump-if-=  $skip-chars-not-matching:end/disp8
 582     # ++in->read
 583     41/increment-ecx
 584     eb/jump  $skip-chars-not-matching:loop/disp8
 585 $skip-chars-not-matching:end:
 586     # persist in->read
 587     89/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy ecx to *(esi+4)
 588     # . restore registers
 589     5e/pop-to-esi
 590     5b/pop-to-ebx
 591     5a/pop-to-edx
 592     59/pop-to-ecx
 593     58/pop-to-eax
 594     # . epilogue
 595     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 596     5d/pop-to-ebp
 597     c3/return
 598 
 599 test-skip-chars-not-matching:
 600     # setup
 601     # . clear-stream(_test-stream)
 602     # . . push args
 603     68/push  _test-stream/imm32
 604     # . . call
 605     e8/call  clear-stream/disp32
 606     # . . discard args
 607     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 608     # write(_test-stream, "ab ")
 609     # . . push args
 610     68/push  "ab "/imm32
 611     68/push  _test-stream/imm32
 612     # . . call
 613     e8/call  write/disp32
 614     # . . discard args
 615     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 616     # skip-chars-not-matching(_test-stream, 0x20/space)
 617     # . . push args
 618     68/push  0x20/imm32
 619     68/push  _test-stream/imm32
 620     # . . call
 621     e8/call  skip-chars-not-matching/disp32
 622     # . . discard args
 623     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 624     # check-ints-equal(_test-stream->read, 2, msg)
 625     # . . push args
 626     68/push  "F - test-skip-chars-not-matching"/imm32
 627     68/push  2/imm32
 628     # . . push *_test-stream->read
 629     b8/copy-to-eax  _test-stream/imm32
 630     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
 631     # . . call
 632     e8/call  check-ints-equal/disp32
 633     # . . discard args
 634     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 635     # end
 636     c3/return
 637 
 638 test-skip-chars-not-matching-none:
 639     # setup
 640     # . clear-stream(_test-stream)
 641     # . . push args
 642     68/push  _test-stream/imm32
 643     # . . call
 644     e8/call  clear-stream/disp32
 645     # . . discard args
 646     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 647     # write(_test-stream, " ab")
 648     # . . push args
 649     68/push  " ab"/imm32
 650     68/push  _test-stream/imm32
 651     # . . call
 652     e8/call  write/disp32
 653     # . . discard args
 654     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 655     # skip-chars-not-matching(_test-stream, 0x20/space)
 656     # . . push args
 657     68/push  0x20/imm32
 658     68/push  _test-stream/imm32
 659     # . . call
 660     e8/call  skip-chars-not-matching/disp32
 661     # . . discard args
 662     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 663     # check-ints-equal(_test-stream->read, 0, msg)
 664     # . . push args
 665     68/push  "F - test-skip-chars-not-matching-none"/imm32
 666     68/push  0/imm32
 667     # . . push *_test-stream->read
 668     b8/copy-to-eax  _test-stream/imm32
 669     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
 670     # . . call
 671     e8/call  check-ints-equal/disp32
 672     # . . discard args
 673     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 674     # end
 675     c3/return
 676 
 677 test-skip-chars-not-matching-all:
 678     # setup
 679     # . clear-stream(_test-stream)
 680     # . . push args
 681     68/push  _test-stream/imm32
 682     # . . call
 683     e8/call  clear-stream/disp32
 684     # . . discard args
 685     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 686     # write(_test-stream, "ab")
 687     # . . push args
 688     68/push  "ab"/imm32
 689     68/push  _test-stream/imm32
 690     # . . call
 691     e8/call  write/disp32
 692     # . . discard args
 693     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 694     # skip-chars-not-matching(_test-stream, 0x20/space)
 695     # . . push args
 696     68/push  0x20/imm32
 697     68/push  _test-stream/imm32
 698     # . . call
 699     e8/call  skip-chars-not-matching/disp32
 700     # . . discard args
 701     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 702     # check-ints-equal(_test-stream->read, 2, msg)
 703     # . . push args
 704     68/push  "F - test-skip-chars-not-matching-all"/imm32
 705     68/push  2/imm32
 706     # . . push *_test-stream->read
 707     b8/copy-to-eax  _test-stream/imm32
 708     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
 709     # . . call
 710     e8/call  check-ints-equal/disp32
 711     # . . discard args
 712     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 713     # end
 714     c3/return
 715 
 716 skip-chars-not-matching-whitespace:  # in: (addr stream byte)
 717     # . prologue
 718     55/push-ebp
 719     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 720     # . save registers
 721     50/push-eax
 722     51/push-ecx
 723     53/push-ebx
 724     56/push-esi
 725     # esi = in
 726     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
 727     # ecx = in->read
 728     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
 729     # ebx = in->write
 730     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           3/r32/ebx   .               .                 # copy *esi to ebx
 731 $skip-chars-not-matching-whitespace:loop:
 732     # if (in->read >= in->write) break
 733     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           3/r32/ebx   .               .                 # compare ecx with ebx
 734     7d/jump-if->=  $skip-chars-not-matching-whitespace:end/disp8
 735     # eax = in->data[in->read]
 736     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
 737     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
 738     # if (eax == ' ') break
 739     3d/compare-eax-and  0x20/imm32/space
 740     74/jump-if-=  $skip-chars-not-matching-whitespace:end/disp8
 741     # if (eax == '\n') break
 742     3d/compare-eax-and  0x0a/imm32/newline
 743     74/jump-if-=  $skip-chars-not-matching-whitespace:end/disp8
 744     # if (eax == '\t') break
 745     3d/compare-eax-and  0x09/imm32/tab
 746     74/jump-if-=  $skip-chars-not-matching-whitespace:end/disp8
 747     # if (eax == '\r') break
 748     3d/compare-eax-and  0x0d/imm32/cr
 749     74/jump-if-=  $skip-chars-not-matching-whitespace:end/disp8
 750     # ++in->read
 751     41/increment-ecx
 752     eb/jump  $skip-chars-not-matching-whitespace:loop/disp8
 753 $skip-chars-not-matching-whitespace:end:
 754     # persist in->read
 755     89/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy ecx to *(esi+4)
 756     # . restore registers
 757     5e/pop-to-esi
 758     5b/pop-to-ebx
 759     59/pop-to-ecx
 760     58/pop-to-eax
 761     # . epilogue
 762     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 763     5d/pop-to-ebp
 764     c3/return
 765 
 766 test-skip-chars-not-matching-whitespace:
 767     # setup
 768     # . clear-stream(_test-stream)
 769     # . . push args
 770     68/push  _test-stream/imm32
 771     # . . call
 772     e8/call  clear-stream/disp32
 773     # . . discard args
 774     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 775     # write(_test-stream, "ab\n")
 776     # . . push args
 777     68/push  "ab\n"/imm32
 778     68/push  _test-stream/imm32
 779     # . . call
 780     e8/call  write/disp32
 781     # . . discard args
 782     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 783     # skip-chars-not-matching-whitespace(_test-stream)
 784     # . . push args
 785     68/push  _test-stream/imm32
 786     # . . call
 787     e8/call  skip-chars-not-matching-whitespace/disp32
 788     # . . discard args
 789     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
 790     # check-ints-equal(_test-stream->read, 2, msg)
 791     # . . push args
 792     68/push  "F - test-skip-chars-not-matching-whitespace"/imm32
 793     68/push  2/imm32
 794     # . . push *_test-stream->read
 795     b8/copy-to-eax  _test-stream/imm32
 796     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
 797     # . . call
 798     e8/call  check-ints-equal/disp32
 799     # . . discard args
 800     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 801     # end
 802     c3/return
 803 
 804 skip-chars-matching-in-slice:  # curr: (addr byte), end: (addr byte), delimiter: byte -> curr/eax: (addr byte)
 805     # . prologue
 806     55/push-ebp
 807     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 808     # . save registers
 809     51/push-ecx
 810     52/push-edx
 811     53/push-ebx
 812     # eax = curr
 813     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
 814     # ecx = end
 815     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0xc/disp8       .                 # copy *(ebp+12) to ecx
 816     # edx = delimiter
 817     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0x10/disp8       .                 # copy *(ebp+16) to edx
 818     # var c/ebx: byte = 0
 819     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
 820 $skip-chars-matching-in-slice:loop:
 821     # if (curr >= end) break
 822     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # compare eax with ecx
 823     73/jump-if-addr>=  $skip-chars-matching-in-slice:end/disp8
 824     # c = *curr
 825     8a/copy-byte                    0/mod/indirect  0/rm32/eax    .           .             .           3/r32/BL    .               .                 # copy byte at *eax to BL
 826     # if (c != delimiter) break
 827     39/compare                      3/mod/direct    3/rm32/ebx    .           .             .           2/r32/edx   .               .                 # compare ebx and edx
 828     75/jump-if-!=  $skip-chars-matching-in-slice:end/disp8
 829     # ++curr
 830     40/increment-eax
 831     eb/jump  $skip-chars-matching-in-slice:loop/disp8
 832 $skip-chars-matching-in-slice:end:
 833     # . restore registers
 834     5b/pop-to-ebx
 835     5a/pop-to-edx
 836     59/pop-to-ecx
 837     # . epilogue
 838     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 839     5d/pop-to-ebp
 840     c3/return
 841 
 842 test-skip-chars-matching-in-slice:
 843     # (eax..ecx) = "  ab"
 844     b8/copy-to-eax  "  ab"/imm32
 845     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
 846     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
 847     05/add-to-eax  4/imm32
 848     # eax = skip-chars-matching-in-slice(eax, ecx, 0x20/space)
 849     # . . push args
 850     68/push  0x20/imm32/space
 851     51/push-ecx
 852     50/push-eax
 853     # . . call
 854     e8/call  skip-chars-matching-in-slice/disp32
 855     # . . discard args
 856     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 857     # check-ints-equal(ecx-eax, 2, msg)
 858     # . . push args
 859     68/push  "F - test-skip-chars-matching-in-slice"/imm32
 860     68/push  2/imm32
 861     # . . push ecx-eax
 862     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
 863     51/push-ecx
 864     # . . call
 865     e8/call  check-ints-equal/disp32
 866     # . . discard args
 867     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 868     # end
 869     c3/return
 870 
 871 test-skip-chars-matching-in-slice-none:
 872     # (eax..ecx) = "ab"
 873     b8/copy-to-eax  "ab"/imm32
 874     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
 875     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
 876     05/add-to-eax  4/imm32
 877     # eax = skip-chars-matching-in-slice(eax, ecx, 0x20/space)
 878     # . . push args
 879     68/push  0x20/imm32/space
 880     51/push-ecx
 881     50/push-eax
 882     # . . call
 883     e8/call  skip-chars-matching-in-slice/disp32
 884     # . . discard args
 885     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 886     # check-ints-equal(ecx-eax, 2, msg)
 887     # . . push args
 888     68/push  "F - test-skip-chars-matching-in-slice-none"/imm32
 889     68/push  2/imm32
 890     # . . push ecx-eax
 891     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
 892     51/push-ecx
 893     # . . call
 894     e8/call  check-ints-equal/disp32
 895     # . . discard args
 896     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 897     # end
 898     c3/return
 899 
 900 skip-chars-matching-whitespace-in-slice:  # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte)
 901     # . prologue
 902     55/push-ebp
 903     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 904     # . save registers
 905     51/push-ecx
 906     53/push-ebx
 907     # eax = curr
 908     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
 909     # ecx = end
 910     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0xc/disp8       .                 # copy *(ebp+12) to ecx
 911     # var c/ebx: byte = 0
 912     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
 913 $skip-chars-matching-whitespace-in-slice:loop:
 914     # if (curr >= end) break
 915     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # compare eax with ecx
 916     0f 83/jump-if-addr>=  $skip-chars-matching-in-slice:end/disp32
 917     # c = *curr
 918     8a/copy-byte                    0/mod/indirect  0/rm32/eax    .           .             .           3/r32/BL    .               .                 # copy byte at *eax to BL
 919     # if (c == ' ') goto body
 920     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x20/imm32/space  # compare ebx
 921     74/jump-if-=  $skip-chars-matching-whitespace-in-slice:body/disp8
 922     # if (c == '\n') goto body
 923     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x0a/imm32/newline  # compare ebx
 924     74/jump-if-=  $skip-chars-matching-whitespace-in-slice:body/disp8
 925     # if (c == '\t') goto body
 926     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x09/imm32/tab    # compare ebx
 927     74/jump-if-=  $skip-chars-matching-whitespace-in-slice:body/disp8
 928     # if (c != '\r') break
 929     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x0d/imm32/cr     # compare ebx
 930     75/jump-if-!=  $skip-chars-matching-whitespace-in-slice:end/disp8
 931 $skip-chars-matching-whitespace-in-slice:body:
 932     # ++curr
 933     40/increment-eax
 934     eb/jump  $skip-chars-matching-whitespace-in-slice:loop/disp8
 935 $skip-chars-matching-whitespace-in-slice:end:
 936     # . restore registers
 937     5b/pop-to-ebx
 938     59/pop-to-ecx
 939     # . epilogue
 940     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 941     5d/pop-to-ebp
 942     c3/return
 943 
 944 test-skip-chars-matching-whitespace-in-slice:
 945     # (eax..ecx) = " \nab"
 946     b8/copy-to-eax  " \nab"/imm32
 947     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
 948     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
 949     05/add-to-eax  4/imm32
 950     # eax = skip-chars-matching-whitespace-in-slice(eax, ecx)
 951     # . . push args
 952     51/push-ecx
 953     50/push-eax
 954     # . . call
 955     e8/call  skip-chars-matching-whitespace-in-slice/disp32
 956     # . . discard args
 957     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
 958     # check-ints-equal(ecx-eax, 2, msg)
 959     # . . push args
 960     68/push  "F - test-skip-chars-matching-whitespace-in-slice"/imm32
 961     68/push  2/imm32
 962     # . . push ecx-eax
 963     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
 964     51/push-ecx
 965     # . . call
 966     e8/call  check-ints-equal/disp32
 967     # . . discard args
 968     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
 969     # end
 970     c3/return
 971 
 972 # minor fork of 'skip-chars-matching-in-slice'
 973 skip-chars-not-matching-in-slice:  # curr: (addr byte), end: (addr byte), delimiter: byte -> curr/eax: (addr byte)
 974     # . prologue
 975     55/push-ebp
 976     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 977     # . save registers
 978     51/push-ecx
 979     52/push-edx
 980     53/push-ebx
 981     # eax = curr
 982     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
 983     # ecx = end
 984     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0xc/disp8       .                 # copy *(ebp+12) to ecx
 985     # edx = delimiter
 986     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0x10/disp8       .                 # copy *(ebp+16) to edx
 987     # var c/ebx: byte = 0
 988     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
 989 $skip-chars-not-matching-in-slice:loop:
 990     # if (curr >= end) break
 991     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # compare eax with ecx
 992     73/jump-if-addr>=  $skip-chars-not-matching-in-slice:end/disp8
 993     # c = *curr
 994     8a/copy-byte                    0/mod/indirect  0/rm32/eax    .           .             .           3/r32/BL    .               .                 # copy byte at *eax to BL
 995     # if (c == delimiter) break
 996     39/compare                      3/mod/direct    3/rm32/ebx    .           .             .           2/r32/edx   .               .                 # compare ebx and edx
 997     74/jump-if-=  $skip-chars-not-matching-in-slice:end/disp8
 998     # ++curr
 999     40/increment-eax
1000     eb/jump  $skip-chars-not-matching-in-slice:loop/disp8
1001 $skip-chars-not-matching-in-slice:end:
1002     # . restore registers
1003     5b/pop-to-ebx
1004     5a/pop-to-edx
1005     59/pop-to-ecx
1006     # . epilogue
1007     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1008     5d/pop-to-ebp
1009     c3/return
1010 
1011 test-skip-chars-not-matching-in-slice:
1012     # (eax..ecx) = "ab "
1013     b8/copy-to-eax  "ab "/imm32
1014     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
1015     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
1016     05/add-to-eax  4/imm32
1017     # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space)
1018     # . . push args
1019     68/push  0x20/imm32/space
1020     51/push-ecx
1021     50/push-eax
1022     # . . call
1023     e8/call  skip-chars-not-matching-in-slice/disp32
1024     # . . discard args
1025     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1026     # check-ints-equal(ecx-eax, 1, msg)
1027     # . . push args
1028     68/push  "F - test-skip-chars-not-matching-in-slice"/imm32
1029     68/push  1/imm32
1030     # . . push ecx-eax
1031     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
1032     51/push-ecx
1033     # . . call
1034     e8/call  check-ints-equal/disp32
1035     # . . discard args
1036     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1037     # end
1038     c3/return
1039 
1040 test-skip-chars-not-matching-in-slice-none:
1041     # (eax..ecx) = " ab"
1042     b8/copy-to-eax  " ab"/imm32
1043     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
1044     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
1045     05/add-to-eax  4/imm32
1046     # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space)
1047     # . . push args
1048     68/push  0x20/imm32/space
1049     51/push-ecx
1050     50/push-eax
1051     # . . call
1052     e8/call  skip-chars-not-matching-in-slice/disp32
1053     # . . discard args
1054     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1055     # check-ints-equal(ecx-eax, 3, msg)
1056     # . . push args
1057     68/push  "F - test-skip-chars-not-matching-in-slice-none"/imm32
1058     68/push  3/imm32
1059     # . . push ecx-eax
1060     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
1061     51/push-ecx
1062     # . . call
1063     e8/call  check-ints-equal/disp32
1064     # . . discard args
1065     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1066     # end
1067     c3/return
1068 
1069 test-skip-chars-not-matching-in-slice-all:
1070     # (eax..ecx) = "ab"
1071     b8/copy-to-eax  "ab"/imm32
1072     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
1073     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
1074     05/add-to-eax  4/imm32
1075     # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space)
1076     # . . push args
1077     68/push  0x20/imm32/space
1078     51/push-ecx
1079     50/push-eax
1080     # . . call
1081     e8/call  skip-chars-not-matching-in-slice/disp32
1082     # . . discard args
1083     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1084     # check-ints-equal(ecx-eax, 0, msg)
1085     # . . push args
1086     68/push  "F - test-skip-chars-not-matching-in-slice-all"/imm32
1087     68/push  0/imm32
1088     # . . push ecx-eax
1089     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
1090     51/push-ecx
1091     # . . call
1092     e8/call  check-ints-equal/disp32
1093     # . . discard args
1094     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1095     # end
1096     c3/return
1097 
1098 skip-chars-not-matching-whitespace-in-slice:  # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte)
1099     # . prologue
1100     55/push-ebp
1101     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1102     # . save registers
1103     51/push-ecx
1104     53/push-ebx
1105     # eax = curr
1106     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
1107     # ecx = end
1108     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0xc/disp8       .                 # copy *(ebp+12) to ecx
1109     # var c/ebx: byte = 0
1110     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
1111 $skip-chars-not-matching-whitespace-in-slice:loop:
1112     # if (curr >= end) break
1113     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # compare eax with ecx
1114     0f 83/jump-if-addr>=  $skip-chars-not-matching-in-slice:end/disp32
1115     # c = *curr
1116     8a/copy-byte                    0/mod/indirect  0/rm32/eax    .           .             .           3/r32/BL    .               .                 # copy byte at *eax to BL
1117     # if (c == ' ') break
1118     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x20/imm32/space  # compare ebx
1119     74/jump-if-=  $skip-chars-not-matching-whitespace-in-slice:end/disp8
1120     # if (c == '\n') break
1121     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x0a/imm32/newline  # compare ebx
1122     74/jump-if-=  $skip-chars-not-matching-whitespace-in-slice:end/disp8
1123     # if (c == '\t') break
1124     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x09/imm32/tab    # compare ebx
1125     74/jump-if-=  $skip-chars-not-matching-whitespace-in-slice:end/disp8
1126     # if (c == '\r') break
1127     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x0d/imm32/cr     # compare ebx
1128     74/jump-if-=  $skip-chars-not-matching-whitespace-in-slice:end/disp8
1129     # ++curr
1130     40/increment-eax
1131     eb/jump  $skip-chars-not-matching-whitespace-in-slice:loop/disp8
1132 $skip-chars-not-matching-whitespace-in-slice:end:
1133     # . restore registers
1134     5b/pop-to-ebx
1135     59/pop-to-ecx
1136     # . epilogue
1137     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1138     5d/pop-to-ebp
1139     c3/return
1140 
1141 test-skip-chars-not-matching-whitespace-in-slice:
1142     # (eax..ecx) = "ab\n"
1143     b8/copy-to-eax  "ab\n"/imm32
1144     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
1145     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
1146     05/add-to-eax  4/imm32
1147     # eax = skip-chars-not-matching-whitespace-in-slice(eax, ecx)
1148     # . . push args
1149     51/push-ecx
1150     50/push-eax
1151     # . . call
1152     e8/call  skip-chars-not-matching-whitespace-in-slice/disp32
1153     # . . discard args
1154     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1155     # check-ints-equal(ecx-eax, 1, msg)
1156     # . . push args
1157     68/push  "F - test-skip-chars-not-matching-whitespace-in-slice"/imm32
1158     68/push  1/imm32
1159     # . . push ecx-eax
1160     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
1161     51/push-ecx
1162     # . . call
1163     e8/call  check-ints-equal/disp32
1164     # . . discard args
1165     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1166     # end
1167     c3/return
1168 
1169 # update line->read to end of string literal surrounded by double quotes
1170 # line->read must start out at a double-quote
1171 skip-string:  # line: (addr stream byte)
1172     # . prologue
1173     55/push-ebp
1174     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1175     # . save registers
1176     50/push-eax
1177     51/push-ecx
1178     52/push-edx
1179     # ecx = line
1180     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
1181     # eax = skip-string-in-slice(&line->data[line->read], &line->data[line->write])
1182     # . . push &line->data[line->write]
1183     8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .                         2/r32/edx   8/disp8         .                 # copy *(ecx+8) to edx
1184     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ecx  2/index/edx   .           2/r32/edx   0xc/disp8       .                 # copy ecx+edx+12 to edx
1185     52/push-edx
1186     # . . push &line->data[line->read]
1187     8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .                         2/r32/edx   4/disp8         .                 # copy *(ecx+4) to edx
1188     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ecx  2/index/edx   .           2/r32/edx   0xc/disp8       .                 # copy ecx+edx+12 to edx
1189     52/push-edx
1190     # . . call
1191     e8/call  skip-string-in-slice/disp32
1192     # . . discard args
1193     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1194     # line->read = eax - line->data
1195     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # subtract ecx from eax
1196     2d/subtract-from-eax  0xc/imm32
1197     89/copy                         1/mod/*+disp8   1/rm32/ecx    .           .                         0/r32/eax   4/disp8         .                 # copy eax to *(ecx+4)
1198 $skip-string:end:
1199     # . restore registers
1200     5a/pop-to-edx
1201     59/pop-to-ecx
1202     58/pop-to-eax
1203     # . epilogue
1204     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1205     5d/pop-to-ebp
1206     c3/return
1207 
1208 test-skip-string:
1209     # . prologue
1210     55/push-ebp
1211     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1212     # setup
1213     # . clear-stream(_test-input-stream)
1214     # . . push args
1215     68/push  _test-input-stream/imm32
1216     # . . call
1217     e8/call  clear-stream/disp32
1218     # . . discard args
1219     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1220     # . write(_test-input-stream, "\"abc\" def")
1221     # .                   indices:  0123 45
1222     # . . push args
1223     68/push  "\"abc\" def"/imm32
1224     68/push  _test-input-stream/imm32
1225     # . . call
1226     e8/call  write/disp32
1227     # . . discard args
1228     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1229     # precondition: line->read == 0
1230     # . . push args
1231     68/push  "F - test-skip-string/precondition"/imm32
1232     68/push  0/imm32
1233     b8/copy-to-eax  _test-input-stream/imm32
1234     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
1235     # . . call
1236     e8/call  check-ints-equal/disp32
1237     # . . discard args
1238     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1239     # skip-string(_test-input-stream)
1240     # . . push args
1241     68/push  _test-input-stream/imm32
1242     # . . call
1243     e8/call  skip-string/disp32
1244     # . . discard args
1245     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1246     # check-ints-equal(line->read, 5, msg)
1247     # . . push args
1248     68/push  "F - test-skip-string"/imm32
1249     68/push  5/imm32
1250     b8/copy-to-eax  _test-input-stream/imm32
1251     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
1252     # . . call
1253     e8/call  check-ints-equal/disp32
1254     # . . discard args
1255     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1256     # . epilogue
1257     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1258     5d/pop-to-ebp
1259     c3/return
1260 
1261 test-skip-string-ignores-spaces:
1262     # . prologue
1263     55/push-ebp
1264     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1265     # setup
1266     # . clear-stream(_test-input-stream)
1267     # . . push args
1268     68/push  _test-input-stream/imm32
1269     # . . call
1270     e8/call  clear-stream/disp32
1271     # . . discard args
1272     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1273     # . write(_test-input-stream, "\"a b\"/yz")
1274     # .                   indices:  0123 45
1275     # . . push args
1276     68/push  "\"a b\"/yz"/imm32
1277     68/push  _test-input-stream/imm32
1278     # . . call
1279     e8/call  write/disp32
1280     # . . discard args
1281     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1282     # precondition: line->read == 0
1283     # . . push args
1284     68/push  "F - test-skip-string-ignores-spaces/precondition"/imm32
1285     68/push  0/imm32
1286     b8/copy-to-eax  _test-input-stream/imm32
1287     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
1288     # . . call
1289     e8/call  check-ints-equal/disp32
1290     # . . discard args
1291     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1292     # skip-string(_test-input-stream)
1293     # . . push args
1294     68/push  _test-input-stream/imm32
1295     # . . call
1296     e8/call  skip-string/disp32
1297     # . . discard args
1298     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1299     # check-ints-equal(line->read, 5, msg)
1300     # . . push args
1301     68/push  "F - test-skip-string-ignores-spaces"/imm32
1302     68/push  5/imm32
1303     b8/copy-to-eax  _test-input-stream/imm32
1304     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
1305     # . . call
1306     e8/call  check-ints-equal/disp32
1307     # . . discard args
1308     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1309     # . epilogue
1310     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1311     5d/pop-to-ebp
1312     c3/return
1313 
1314 test-skip-string-ignores-escapes:
1315     # . prologue
1316     55/push-ebp
1317     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1318     # setup
1319     # . clear-stream(_test-input-stream)
1320     # . . push args
1321     68/push  _test-input-stream/imm32
1322     # . . call
1323     e8/call  clear-stream/disp32
1324     # . . discard args
1325     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1326     # . write(_test-input-stream, "\"a\\\"b\"/yz")
1327     # .                   indices:  01 2 34 56
1328     # . . push args
1329     68/push  "\"a\\\"b\"/yz"/imm32
1330     68/push  _test-input-stream/imm32
1331     # . . call
1332     e8/call  write/disp32
1333     # . . discard args
1334     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1335     # precondition: line->read == 0
1336     # . . push args
1337     68/push  "F - test-skip-string-ignores-escapes/precondition"/imm32
1338     68/push  0/imm32
1339     b8/copy-to-eax  _test-input-stream/imm32
1340     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
1341     # . . call
1342     e8/call  check-ints-equal/disp32
1343     # . . discard args
1344     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1345     # skip-string(_test-input-stream)
1346     # . . push args
1347     68/push  _test-input-stream/imm32
1348     # . . call
1349     e8/call  skip-string/disp32
1350     # . . discard args
1351     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1352     # check-ints-equal(line->read, 6, msg)
1353     # . . push args
1354     68/push  "F - test-skip-string-ignores-escapes"/imm32
1355     68/push  6/imm32
1356     b8/copy-to-eax  _test-input-stream/imm32
1357     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
1358     # . . call
1359     e8/call  check-ints-equal/disp32
1360     # . . discard args
1361     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1362     # . epilogue
1363     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1364     5d/pop-to-ebp
1365     c3/return
1366 
1367 test-skip-string-works-from-mid-stream:
1368     # . prologue
1369     55/push-ebp
1370     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1371     # setup
1372     # . clear-stream(_test-input-stream)
1373     # . . push args
1374     68/push  _test-input-stream/imm32
1375     # . . call
1376     e8/call  clear-stream/disp32
1377     # . . discard args
1378     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1379     # . write(_test-input-stream, "0 \"a\\\"b\"/yz")
1380     # .                   indices:  01 2 34 56
1381     # . . push args
1382     68/push  "0 \"a\\\"b\"/yz"/imm32
1383     68/push  _test-input-stream/imm32
1384     # . . call
1385     e8/call  write/disp32
1386     # . . discard args
1387     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1388     # precondition: line->read == 2
1389     b8/copy-to-eax  _test-input-stream/imm32
1390     c7          0/subop/copy        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         2/imm32           # copy to *(eax+4)
1391     # skip-string(_test-input-stream)
1392     # . . push args
1393     68/push  _test-input-stream/imm32
1394     # . . call
1395     e8/call  skip-string/disp32
1396     # . . discard args
1397     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
1398     # check-ints-equal(line->read, 8, msg)
1399     # . . push args
1400     68/push  "F - test-skip-string-works-from-mid-stream"/imm32
1401     68/push  8/imm32
1402     b8/copy-to-eax  _test-input-stream/imm32
1403     ff          6/subop/push        1/mod/*+disp8   0/rm32/eax    .           .             .           .           4/disp8         .                 # push *(eax+4)
1404     # . . call
1405     e8/call  check-ints-equal/disp32
1406     # . . discard args
1407     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1408     # . epilogue
1409     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1410     5d/pop-to-ebp
1411     c3/return
1412 
1413 skip-string-in-slice:  # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte)
1414     # . prologue
1415     55/push-ebp
1416     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1417     # . save registers
1418     51/push-ecx
1419     52/push-edx
1420     53/push-ebx
1421     # ecx = curr
1422     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
1423     # edx = end
1424     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         2/r32/edx   0xc/disp8         .               # copy *(ebp+12) to edx
1425     # var c/eax: byte = 0
1426     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
1427     # skip initial dquote
1428     41/increment-ecx
1429 $skip-string-in-slice:loop:
1430     # if (curr >= end) return curr
1431     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
1432     73/jump-if-addr>=  $skip-string-in-slice:return-curr/disp8
1433     # c = *curr
1434     8a/copy-byte                    0/mod/indirect  1/rm32/ecx    .           .             .           0/r32/AL    .               .                 # copy byte at *ecx to AL
1435 $skip-string-in-slice:dquote:
1436     # if (c == '"') break
1437     3d/compare-eax-and  0x22/imm32/double-quote
1438     74/jump-if-=  $skip-string-in-slice:break/disp8
1439 $skip-string-in-slice:check-for-escape:
1440     # if (c == '\') escape next char
1441     3d/compare-eax-and  0x5c/imm32/backslash
1442     75/jump-if-!=  $skip-string-in-slice:continue/disp8
1443 $skip-string-in-slice:escape:
1444     41/increment-ecx
1445 $skip-string-in-slice:continue:
1446     # ++curr
1447     41/increment-ecx
1448     eb/jump  $skip-string-in-slice:loop/disp8
1449 $skip-string-in-slice:break:
1450     # skip final dquote
1451     41/increment-ecx
1452 $skip-string-in-slice:return-curr:
1453     # return curr
1454     89/copy                         3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to eax
1455 $skip-string-in-slice:end:
1456     # . restore registers
1457     5b/pop-to-ebx
1458     5a/pop-to-edx
1459     59/pop-to-ecx
1460     # . epilogue
1461     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1462     5d/pop-to-ebp
1463     c3/return
1464 
1465 test-skip-string-in-slice:
1466     # . prologue
1467     55/push-ebp
1468     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1469     # setup: (eax..ecx) = "\"abc\" def"
1470     b8/copy-to-eax  "\"abc\" def"/imm32
1471     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
1472     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
1473     05/add-to-eax  4/imm32
1474     # eax = skip-string-in-slice(eax, ecx)
1475     # . . push args
1476     51/push-ecx
1477     50/push-eax
1478     # . . call
1479     e8/call  skip-string-in-slice/disp32
1480     # . . discard args
1481     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1482     # check-ints-equal(ecx-eax, 4, msg)  # number of chars remaining after the string literal
1483     # . . push args
1484     68/push  "F - test-skip-string-in-slice"/imm32
1485     68/push  4/imm32
1486     # . . push ecx-eax
1487     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
1488     51/push-ecx
1489     # . . call
1490     e8/call  check-ints-equal/disp32
1491     # . . discard args
1492     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1493     # . epilogue
1494     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1495     5d/pop-to-ebp
1496     c3/return
1497 
1498 test-skip-string-in-slice-ignores-spaces:
1499     # . prologue
1500     55/push-ebp
1501     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1502     # setup: (eax..ecx) = "\"a b\"/yz"
1503     b8/copy-to-eax  "\"a b\"/yz"/imm32
1504     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
1505     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
1506     05/add-to-eax  4/imm32
1507     # eax = skip-string-in-slice(eax, ecx)
1508     # . . push args
1509     51/push-ecx
1510     50/push-eax
1511     # . . call
1512     e8/call  skip-string-in-slice/disp32
1513     # . . discard args
1514     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1515     # check-ints-equal(ecx-eax, 3, msg)  # number of chars remaining after the string literal
1516     # . . push args
1517     68/push  "F - test-skip-string-in-slice-ignores-spaces"/imm32
1518     68/push  3/imm32
1519     # . . push ecx-eax
1520     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
1521     51/push-ecx
1522     # . . call
1523     e8/call  check-ints-equal/disp32
1524     # . . discard args
1525     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
1526     # . epilogue
1527     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
1528     5d/pop-to-ebp
1529     c3/return
1530 
1531 test-skip-string-in-slice-ignores-escapes:
1532     # . prologue
1533     55/push-ebp
1534     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
1535     # setup: (eax..ecx) = "\"a\\\"b\"/yz"
1536     b8/copy-to-eax  "\"a\\\"b\"/yz"/imm32
1537     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
1538     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
1539     05/add-to-eax  4/imm32
1540     # eax = skip-string-in-slice(eax, ecx)
1541     # . . push args
1542     51/push-ecx
1543     50/push-eax
1544     # . . call
1545     e8/call  skip-string-in-slice/disp32
1546     # . . discard args
1547     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
1548     # check-ints-equal(ecx-eax, 3, msg)  # number of chars remaining after the string literal
1549     # . . push args
1550     68/push  "F - test-skip-string-in-slice-ignores-escapes"/imm32
1551     68/push  3/imm32
1552     # . . push ecx-eax
1553     29/subtract                     3/mod/direct    1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # subtract eax from ecx
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module ranger.gui.widgets.console</title>
</head><body bgcolor="#f0f0f8">

<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="ranger.html"><font color="#ffffff">ranger</font></a>.<a href="ranger.gui.html"><font color="#ffffff">gui</font></a>.<a href="ranger.gui.widgets.html"><font color="#ffffff">widgets</font></a>.console</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/ranger/gui/widgets/console.py">/home/hut/ranger/ranger/gui/widgets/console.py</a></font></td></tr></table>
    <p><tt>The&nbsp;<a href="#Console">Console</a>&nbsp;widget&nbsp;implements&nbsp;a&nbsp;vim-like&nbsp;console&nbsp;for&nbsp;entering<br>
commands,&nbsp;searching&nbsp;and&nbsp;executing&nbsp;files.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
    
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="ranger.defaults.commands.html">ranger.defaults.commands</a><br>
</td><td width="25%" valign=top><a href="curses.html">curses</a><br>
</td><td width="25%" valign=top><a href="ranger.html">ranger</a><br>
</td><td width="25%" valign=top><a href="string.html">string</a><br>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
    
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.html#Widget">ranger.gui.widgets.Widget</a>(<a href="ranger.gui.displayable.html#Displayable">ranger.gui.displayable.Displayable</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#Console">Console</a>
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a>
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#CommandConsole">CommandConsole</a>
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#QuickCommandConsole">QuickCommandConsole</a>
</font></dt></dl>
</dd>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#OpenConsole">OpenConsole</a>
</font></dt><dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#QuickOpenConsole">QuickOpenConsole</a>
</font></dt></dl>
</dd>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#SearchConsole">SearchConsole</a>
</font></dt></dl>
</dd>
</dl>
</dd>
</dl>
 <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="CommandConsole">class <strong>CommandConsole</strong></a>(<a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a>)</font></td></tr>
    
<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="ranger.gui.widgets.console.html#CommandConsole">CommandConsole</a></dd>
<dd><a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a></dd>
<dd><a href="ranger.gui.widgets.console.html#Console">Console</a></dd>
<dd><a href="ranger.gui.widgets.html#Widget">ranger.gui.widgets.Widget</a></dd>
<dd><a href="ranger.gui.displayable.html#Displayable">ranger.gui.displayable.Displayable</a></dd>
<dd><a href="ranger.shared.html#EnvironmentAware">ranger.shared.EnvironmentAware</a></dd>
<dd><a href="ranger.shared.html#FileManagerAware">ranger.shared.FileManagerAware</a></dd>
<dd><a href="ranger.shared.html#Awareness">ranger.shared.Awareness</a></dd>
<dd><a href="ranger.gui.curses_shortcuts.html#CursesShortcuts">ranger.gui.curses_shortcuts.CursesShortcuts</a></dd>
<dd><a href="ranger.shared.settings.html#SettingsAware">ranger.shared.settings.SettingsAware</a></dd>
<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
</dl>
<hr>
Methods defined here:<br>
<dl><dt><a name="CommandConsole-execute"><strong>execute</strong></a>(self, cmd<font color="#909090">=None</font>)</dt></dl>

<hr>
Data and other attributes defined here:<br>
<dl><dt><strong>prompt</strong> = ':'</dl>

<hr>
Methods inherited from <a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a>:<br>
<dl><dt><a name="CommandConsole-tab"><strong>tab</strong></a>(self, n<font color="#909090">=1</font>)</dt></dl>

<hr>
Methods inherited from <a href="ranger.gui.widgets.console.html#Console">Console</a>:<br>
<dl><dt><a name="CommandConsole-__init__"><strong>__init__</strong></a>(self, win)</dt></dl>

<dl><dt><a name="CommandConsole-add_to_history"><strong>add_to_history</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-clear"><strong>clear</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-close"><strong>close</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-delete"><strong>delete</strong></a>(self, mod)</dt></dl>

<dl><dt><a name="CommandConsole-delete_rest"><strong>delete_rest</strong></a>(self, direction)</dt></dl>

<dl><dt><a name="CommandConsole-delete_word"><strong>delete_word</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-destroy"><strong>destroy</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-draw"><strong>draw</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-finalize"><strong>finalize</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-history_move"><strong>history_move</strong></a>(self, n)</dt></dl>

<dl><dt><a name="CommandConsole-init"><strong>init</strong></a>(self)</dt><dd><tt>override&nbsp;this.&nbsp;Called&nbsp;directly&nbsp;after&nbsp;class&nbsp;change</tt></dd></dl>

<dl><dt><a name="CommandConsole-move"><strong>move</strong></a>(self, relative<font color="#909090">=0</font>, absolute<font color="#909090">=None</font>)</dt></dl>

<dl><dt><a name="CommandConsole-on_line_change"><strong>on_line_change</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-open"><strong>open</strong></a>(self, mode, string<font color="#909090">=''</font>)</dt></dl>

<dl><dt><a name="CommandConsole-paste"><strong>paste</strong></a>(self)</dt></dl>

<dl><dt><a name="CommandConsole-press"><strong>press</strong></a>(self, key)</dt></dl>

<dl><dt><a name="CommandConsole-type_key"><strong>type_key</strong></a>(self, key)</dt></dl>

<hr>
Data and other attributes inherited from <a href="ranger.gui.widgets.console.html#Console">Console</a>:<br>
<dl><dt><strong>allow_close</strong> = False</dl>

<dl><dt><strong>commandlist</strong> = None</dl>

<dl><dt><strong>copy</strong> = ''</dl>

<dl><dt><strong>histories</strong> = None</dl>

<dl><dt><strong>history</strong> = None</dl>

<dl><dt><strong>historypaths</strong> = []</dl>

<dl><dt><strong>last_cursor_mode</strong> = None</dl>

<dl><dt><strong>mode</strong> = None</dl>

<dl><dt><strong>original_line</strong> = None</dl>

<dl><dt><strong>override</strong> = None</dl>

<dl><dt><strong>tab_deque</strong> = None</dl>

<dl><dt><strong