From de54d4735b57528754aa715c6ae2ea05f6e95577 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 30 Oct 2019 09:51:07 -0700 Subject: 5725 --- apps/mu.subx | 5 +- html/apps/braces.subx.html | 36 +-- html/apps/mu.subx.html | 739 +++++++++++++++++++++++---------------------- linkify/linkify.cc | 6 +- 4 files changed, 398 insertions(+), 388 deletions(-) diff --git a/apps/mu.subx b/apps/mu.subx index 5036103e..481ed0e7 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -263,7 +263,10 @@ parse-mu: # in : (address buffered-file) # else if slice-starts-with?(word-slice, "#") # comment # break # end of line # else if slice-equal(word-slice, "fn") - # var curr-function/ecx : (address function) + # var new-function : (address function) = new function + # populate-mu-function(in, new-function) + # *curr-function = new-function + # curr-function = &new-function->next # else # abort() # diff --git a/html/apps/braces.subx.html b/html/apps/braces.subx.html index 498489b5..f502220f 100644 --- a/html/apps/braces.subx.html +++ b/html/apps/braces.subx.html @@ -320,15 +320,15 @@ if ('onhashchange' in window) { 261 55/push-ebp 262 89/<- %ebp 4/r32/esp 263 # setup -264 (clear-stream _test-input-stream) -265 (clear-stream _test-output-stream) -266 (clear-stream _test-input-buffered-file->buffer) -267 (clear-stream _test-output-buffered-file->buffer) +264 (clear-stream _test-input-stream) +265 (clear-stream _test-output-stream) +266 (clear-stream _test-input-buffered-file->buffer) +267 (clear-stream _test-output-buffered-file->buffer) 268 # test 269 (write _test-input-stream "== abcd 0x1") -270 (subx-braces _test-input-buffered-file _test-output-buffered-file) +270 (subx-braces _test-input-buffered-file _test-output-buffered-file) 271 # check that the line just passed through -272 (flush _test-output-buffered-file) +272 (flush _test-output-buffered-file) 273 +-- 5 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 278 (check-stream-equal _test-output-stream "== abcd 0x1 \n" "F - test-subx-braces-passes-most-words-through") 279 # . epilogue @@ -353,15 +353,15 @@ if ('onhashchange' in window) { 298 55/push-ebp 299 89/<- %ebp 4/r32/esp 300 # setup -301 (clear-stream _test-input-stream) -302 (clear-stream _test-output-stream) -303 (clear-stream _test-input-buffered-file->buffer) -304 (clear-stream _test-output-buffered-file->buffer) +301 (clear-stream _test-input-stream) +302 (clear-stream _test-output-stream) +303 (clear-stream _test-input-buffered-file->buffer) +304 (clear-stream _test-output-buffered-file->buffer) 305 # test 306 (write _test-input-stream "{\nab break/imm32\ncd loop/imm32\n}") -307 (subx-braces _test-input-buffered-file _test-output-buffered-file) +307 (subx-braces _test-input-buffered-file _test-output-buffered-file) 308 # check that the line just passed through -309 (flush _test-output-buffered-file) +309 (flush _test-output-buffered-file) 310 +-- 5 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 315 (check-stream-equal _test-output-stream "_loop0x00000001:\nab _break0x00000001/imm32 \ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-1") 316 # . epilogue @@ -390,15 +390,15 @@ if ('onhashchange' in window) { 339 55/push-ebp 340 89/<- %ebp 4/r32/esp 341 # setup -342 (clear-stream _test-input-stream) -343 (clear-stream _test-output-stream) -344 (clear-stream _test-input-buffered-file->buffer) -345 (clear-stream _test-output-buffered-file->buffer) +342 (clear-stream _test-input-stream) +343 (clear-stream _test-output-stream) +344 (clear-stream _test-input-buffered-file->buffer) +345 (clear-stream _test-output-buffered-file->buffer) 346 # test 347 (write _test-input-stream "{\n{\nab break/imm32\n}\ncd loop/imm32\n}") -348 (subx-braces _test-input-buffered-file _test-output-buffered-file) +348 (subx-braces _test-input-buffered-file _test-output-buffered-file) 349 # check that the line just passed through -350 (flush _test-output-buffered-file) +350 (flush _test-output-buffered-file) 351 +-- 5 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 356 (check-stream-equal _test-output-stream "_loop0x00000001:\n_loop0x00000002:\nab _break0x00000002/imm32 \n_break0x00000002:\ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-2") 357 # . epilogue diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 753c7861..9ba938aa 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -165,8 +165,8 @@ if ('onhashchange' in window) { 105 89/<- %ebp 4/r32/esp 106 # 107 (parse-mu *(ebp+8)) -108 (check-mu-types) -109 (emit-subx *(ebp+0xc)) +108 (check-mu-types) +109 (emit-subx *(ebp+0xc)) 110 $convert-mu:end: 111 # . epilogue 112 89/<- %esp 5/r32/ebp @@ -179,13 +179,13 @@ if ('onhashchange' in window) { 119 55/push-ebp 120 89/<- %ebp 4/r32/esp 121 # setup -122 (clear-stream _test-input-stream) -123 (clear-stream _test-input-buffered-file->buffer) -124 (clear-stream _test-output-stream) -125 (clear-stream _test-output-buffered-file->buffer) +122 (clear-stream _test-input-stream) +123 (clear-stream _test-input-buffered-file->buffer) +124 (clear-stream _test-output-stream) +125 (clear-stream _test-output-buffered-file->buffer) 126 # -127 (convert-mu _test-input-buffered-file _test-output-buffered-file) -128 (flush _test-output-buffered-file) +127 (convert-mu _test-input-buffered-file _test-output-buffered-file) +128 (flush _test-output-buffered-file) 129 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") 130 # . epilogue 131 89/<- %esp 5/r32/ebp @@ -209,16 +209,16 @@ if ('onhashchange' in window) { 149 55/push-ebp 150 89/<- %ebp 4/r32/esp 151 # setup -152 (clear-stream _test-input-stream) -153 (clear-stream _test-input-buffered-file->buffer) -154 (clear-stream _test-output-stream) -155 (clear-stream _test-output-buffered-file->buffer) +152 (clear-stream _test-input-stream) +153 (clear-stream _test-input-buffered-file->buffer) +154 (clear-stream _test-output-stream) +155 (clear-stream _test-output-buffered-file->buffer) 156 # 157 (write _test-input-stream "fn foo {\n") 158 (write _test-input-stream "}\n") 159 # convert -160 (convert-mu _test-input-buffered-file _test-output-buffered-file) -161 (flush _test-output-buffered-file) +160 (convert-mu _test-input-buffered-file _test-output-buffered-file) +161 (flush _test-output-buffered-file) 162 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 168 # check output 169 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") @@ -261,18 +261,18 @@ if ('onhashchange' in window) { 206 55/push-ebp 207 89/<- %ebp 4/r32/esp 208 # setup -209 (clear-stream _test-input-stream) -210 (clear-stream _test-input-buffered-file->buffer) -211 (clear-stream _test-output-stream) -212 (clear-stream _test-output-buffered-file->buffer) +209 (clear-stream _test-input-stream) +210 (clear-stream _test-input-buffered-file->buffer) +211 (clear-stream _test-output-stream) +212 (clear-stream _test-output-buffered-file->buffer) 213 # 214 (write _test-input-stream "fn foo {\n") 215 (write _test-input-stream "}\n") 216 (write _test-input-stream "fn bar {\n") 217 (write _test-input-stream "}\n") 218 # convert -219 (convert-mu _test-input-buffered-file _test-output-buffered-file) -220 (flush _test-output-buffered-file) +219 (convert-mu _test-input-buffered-file _test-output-buffered-file) +220 (flush _test-output-buffered-file) 221 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- 227 # check first function 228 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") @@ -313,354 +313,357 @@ if ('onhashchange' in window) { 263 # else if slice-starts-with?(word-slice, "#") # comment 264 # break # end of line 265 # else if slice-equal(word-slice, "fn") -266 # var curr-function/ecx : (address function) -267 # else -268 # abort() -269 # -270 # . prologue -271 55/push-ebp -272 89/<- %ebp 4/r32/esp -273 # . save registers -274 50/push-eax -275 51/push-ecx -276 52/push-edx -277 57/push-edi -278 # var line/ecx : (stream byte 512) -279 81 5/subop/subtract %esp 0x200/imm32 -280 68/push 0x200/imm32/length -281 68/push 0/imm32/read -282 68/push 0/imm32/write -283 89/<- %ecx 4/r32/esp -284 # var word-slice/edx : slice -285 68/push 0/imm32/end -286 68/push 0/imm32/start -287 89/<- %edx 4/r32/esp -288 # var curr-function/edi : (address function) = Program -289 bf/copy-to-edi Program/imm32 -290 { -291 $parse-mu:line-loop: -292 (clear-stream %ecx) -293 (read-line-buffered *(ebp+8) %ecx) -294 # if (line->write == 0) break -295 81 7/subop/compare *ecx 0/imm32 -296 0f 84/jump-if-equal break/disp32 -297 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------- -303 { # word loop -304 $parse-mu:word-loop: -305 (next-word-or-string %ecx %edx) -306 # if (slice-empty?(word-slice)) break -307 (slice-empty? %edx) -308 3d/compare-eax-and 0/imm32 -309 0f 85/jump-if-not-equal break/disp32 -310 # if (*word-slice->start == "#") break -311 # . eax = *word-slice->start -312 8b/-> *edx 0/r32/eax -313 8a/copy-byte *eax 0/r32/AL -314 81 4/subop/and %eax 0xff/imm32 -315 # . if (eax == '#') break -316 3d/compare-eax-and 0x23/imm32/hash -317 0f 84/jump-if-equal break/disp32 -318 # if slice-equal?(word-slice, "fn") -319 { -320 (slice-equal? %edx "fn") -321 3d/compare-eax-and 0/imm32 -322 0f 84/jump-if-equal break/disp32 -323 # var new-function/eax : (address function) = populate-mu-function() -324 (allocate Heap *Function-size) # => eax -325 (populate-mu-function-header %ecx %eax) -326 (populate-mu-function-body *(ebp+8) %eax) -327 # *curr-function = new-function -328 89/<- *edi 0/r32/eax -329 # curr-function = &new-function->next -330 8d/address-> *(eax+0x10) 7/r32/edi -331 e9/jump $parse-mu:word-loop/disp32 -332 } -333 # otherwise abort -334 e9/jump $parse-mu:abort/disp32 -335 } # end word loop -336 e9/jump loop/disp32 -337 } # end line loop -338 $parse-mu:end: -339 # . reclaim locals -340 81 0/subop/add %esp 0x214/imm32 -341 # . restore registers -342 5f/pop-to-edi -343 5a/pop-to-edx -344 59/pop-to-ecx -345 58/pop-to-eax -346 # . epilogue -347 89/<- %esp 5/r32/ebp -348 5d/pop-to-ebp -349 c3/return -350 -351 $parse-mu:abort: -352 # error("unexpected top-level command: " word-slice "\n") -353 (write-buffered Stderr "unexpected top-level command: ") -354 (write-buffered Stderr %edx) -355 (write-buffered Stderr "\n") -356 (flush Stderr) -357 # . syscall(exit, 1) -358 bb/copy-to-ebx 1/imm32 -359 b8/copy-to-eax 1/imm32/exit -360 cd/syscall 0x80/imm8 -361 # never gets here -362 -363 # errors considered: -364 # fn foo { { -365 # fn foo { } -366 # fn foo { } { -367 # fn foo # no block -368 populate-mu-function-header: # first-line : (address stream byte), out : (address function) -369 # . prologue -370 55/push-ebp -371 89/<- %ebp 4/r32/esp -372 # . save registers -373 50/push-eax -374 51/push-ecx -375 57/push-edi -376 # edi = out -377 8b/-> *(ebp+0xc) 7/r32/edi -378 # var word-slice/ecx : slice -379 68/push 0/imm32/end -380 68/push 0/imm32/start -381 89/<- %ecx 4/r32/esp -382 # save function name -383 (next-word *(ebp+8) %ecx) -384 (slice-to-string Heap %ecx) # => eax -385 89/<- *edi 0/r32/eax -386 # assert that next token is '{' -387 (next-word *(ebp+8) %ecx) -388 (slice-equal? %ecx "{") -389 3d/compare-eax-and 0/imm32 -390 74/jump-if-equal $populate-mu-function-header:abort/disp8 -391 # assert that there's no further token -392 { -393 # word-slice = next-word(line) -394 (next-word *(ebp+8) %ecx) -395 # if (word-slice == '') break -396 (slice-empty? %ecx) -397 3d/compare-eax-and 0/imm32 -398 75/jump-if-not-equal break/disp8 -399 # if (slice-starts-with?(word-slice, "#")) break -400 # . eax = *word-slice->start -401 8b/-> *edx 0/r32/eax -402 8a/copy-byte *eax 0/r32/AL -403 81 4/subop/and %eax 0xff/imm32 -404 # . if (eax == '#') break -405 3d/compare-eax-and 0x23/imm32/hash -406 74/jump-if-equal break/disp8 -407 # otherwise abort -408 eb/jump $populate-mu-function-header:abort/disp8 -409 } -410 $populate-mu-function-header:end: -411 # . reclaim locals -412 81 0/subop/add %esp 8/imm32 -413 # . restore registers -414 5f/pop-to-edi -415 59/pop-to-ecx -416 58/pop-to-eax -417 # . epilogue -418 89/<- %esp 5/r32/ebp -419 5d/pop-to-ebp -420 c3/return -421 -422 $populate-mu-function-header:abort: -423 # error("function header not in form 'fn <name> {'") -424 (write-buffered Stderr "function header not in form 'fn <name> {' -- '") -425 (rewind-stream *(ebp+8)) -426 (write-stream 2 *(ebp+8)) -427 (write-buffered Stderr "'\n") -428 (flush Stderr) -429 # . syscall(exit, 1) -430 bb/copy-to-ebx 1/imm32 -431 b8/copy-to-eax 1/imm32/exit -432 cd/syscall 0x80/imm8 -433 # never gets here -434 -435 # errors considered: -436 # { abc -437 populate-mu-function-body: # in : (address buffered-file), out : (address function) -438 # . prologue -439 55/push-ebp -440 89/<- %ebp 4/r32/esp -441 # . save registers -442 50/push-eax -443 51/push-ecx -444 52/push-edx -445 53/push-ebx -446 # var line/ecx : (stream byte 512) -447 81 5/subop/subtract %esp 0x200/imm32 -448 68/push 0x200/imm32/length -449 68/push 0/imm32/read -450 68/push 0/imm32/write -451 89/<- %ecx 4/r32/esp -452 # var word-slice/edx : slice -453 68/push 0/imm32/end -454 68/push 0/imm32/start -455 89/<- %edx 4/r32/esp -456 # var open-curly-count/ebx : int = 1 -457 bb/copy-to-ebx 1/imm32 -458 { # line loop -459 $populate-mu-function-body:line-loop: -460 # if (open-curly-count == 0) break -461 81 7/subop/compare %ebx 0/imm32 -462 0f 84/jump-if-equal break/disp32 -463 # line = read-line-buffered(in) -464 (clear-stream %ecx) -465 (read-line-buffered *(ebp+8) %ecx) -466 # if (line->write == 0) break -467 81 7/subop/compare *ecx 0/imm32 -468 0f 84/jump-if-equal break/disp32 -469 # word-slice = next-word(line) -470 (next-word %ecx %edx) -471 # if slice-empty?(word-slice)) continue -472 (slice-empty? %ecx) -473 3d/compare-eax-and 0/imm32 -474 75/jump-if-not-equal loop/disp8 -475 # if (slice-starts-with?(word-slice, '#') continue -476 # . eax = *word-slice->start -477 8b/-> *edx 0/r32/eax -478 8a/copy-byte *eax 0/r32/AL -479 81 4/subop/and %eax 0xff/imm32 -480 # . if (eax == '#') continue -481 3d/compare-eax-and 0x23/imm32/hash -482 74/jump-if-equal loop/disp8 -483 { -484 # if slice-equal?(word-slice, "{") ++open-curly-count -485 { -486 (slice-equal? %ecx "{") -487 3d/compare-eax-and 0/imm32 -488 74/jump-if-equal break/disp8 -489 43/increment-ebx -490 eb/jump $curly-found:end/disp8 -491 } -492 # else if slice-equal?(word-slice, "}") --open-curly-count -493 { -494 (slice-equal? %ecx "}") -495 3d/compare-eax-and 0/imm32 -496 74/jump-if-equal break/disp8 -497 4b/decrement-ebx -498 eb/jump $curly-found:end/disp8 -499 } -500 # else break -501 eb/jump $populate-mu-function-body:end/disp8 -502 } -503 # - check for invalid tokens after curly -504 $curly-found:end: -505 # second-word-slice = next-word(line) -506 (next-word %ecx %edx) -507 # if slice-empty?(second-word-slice)) continue -508 (slice-empty? %ecx) -509 3d/compare-eax-and 0/imm32 -510 0f 85/jump-if-not-equal loop/disp32 -511 # if (slice-starts-with?(second-word-slice, '#') continue -512 # . eax = *second-word-slice->start -513 8b/-> *edx 0/r32/eax -514 8a/copy-byte *eax 0/r32/AL -515 81 4/subop/and %eax 0xff/imm32 -516 # . if (eax == '#') continue -517 3d/compare-eax-and 0x23/imm32/hash -518 0f 84/jump-if-equal loop/disp32 -519 # abort -520 eb/jump $populate-mu-function-body:abort/disp8 -521 } # end line loop -522 $populate-mu-function-body:end: -523 # . reclaim locals -524 81 0/subop/add %esp 0x214/imm32 -525 # . restore registers -526 5b/pop-to-ebx -527 5a/pop-to-edx -528 59/pop-to-ecx -529 58/pop-to-eax -530 # . epilogue -531 89/<- %esp 5/r32/ebp -532 5d/pop-to-ebp -533 c3/return -534 -535 $populate-mu-function-body:abort: -536 # error("'{' or '}' should be on its own line, but got '") -537 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -538 (rewind-stream %ecx) -539 (write-stream 2 %ecx) -540 (write-buffered Stderr "'\n") -541 (flush Stderr) -542 # . syscall(exit, 1) -543 bb/copy-to-ebx 1/imm32 -544 b8/copy-to-eax 1/imm32/exit -545 cd/syscall 0x80/imm8 -546 # never gets here -547 -548 check-mu-types: -549 # . prologue -550 55/push-ebp -551 89/<- %ebp 4/r32/esp -552 # -553 $check-types:end: -554 # . epilogue -555 89/<- %esp 5/r32/ebp -556 5d/pop-to-ebp -557 c3/return -558 -559 emit-subx: # out : (address buffered-file) -560 # . prologue -561 55/push-ebp -562 89/<- %ebp 4/r32/esp -563 # . save registers -564 50/push-eax -565 51/push-ecx -566 57/push-edi -567 # edi = out -568 8b/-> *(ebp+8) 7/r32/edi -569 # var curr/ecx : (address function) = Program -570 8b/-> *Program 1/r32/ecx -571 { -572 # if (curr == NULL) break -573 81 7/subop/compare %ecx 0/imm32 -574 0f 84/jump-if-equal break/disp32 -575 (write-buffered %edi *ecx) -576 (write-buffered %edi ":\n") -577 (emit-subx-prologue %edi) -578 (emit-subx-epilogue %edi) -579 # curr = curr->next -580 8b/-> *(ecx+0x10) 1/r32/ecx -581 e9/jump loop/disp32 -582 } -583 $emit-subx:end: -584 # . restore registers -585 5f/pop-to-edi -586 59/pop-to-ecx -587 58/pop-to-eax -588 # . epilogue -589 89/<- %esp 5/r32/ebp -590 5d/pop-to-ebp -591 c3/return -592 -593 emit-subx-prologue: # out : (address buffered-file) -594 # . prologue -595 55/push-ebp -596 89/<- %ebp 4/r32/esp -597 # -598 (write-buffered *(ebp+8) "# . prologue\n") -599 (write-buffered *(ebp+8) "55/push-ebp\n") -600 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n") -601 # . epilogue -602 89/<- %esp 5/r32/ebp -603 5d/pop-to-ebp -604 c3/return -605 -606 emit-subx-epilogue: # out : (address buffered-file) -607 # . prologue -608 55/push-ebp -609 89/<- %ebp 4/r32/esp -610 # -611 (write-buffered *(ebp+8) "# . epilogue\n") -612 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n") -613 (write-buffered *(ebp+8) "5d/pop-to-ebp\n") -614 (write-buffered *(ebp+8) "c3/return\n") -615 # . epilogue -616 89/<- %esp 5/r32/ebp -617 5d/pop-to-ebp -618 c3/return +266 # var new-function : (address function) = new function +267 # populate-mu-function(in, new-function) +268 # *curr-function = new-function +269 # curr-function = &new-function->next +270 # else +271 # abort() +272 # +273 # . prologue +274 55/push-ebp +275 89/<- %ebp 4/r32/esp +276 # . save registers +277 50/push-eax +278 51/push-ecx +279 52/push-edx +280 57/push-edi +281 # var line/ecx : (stream byte 512) +282 81 5/subop/subtract %esp 0x200/imm32 +283 68/push 0x200/imm32/length +284 68/push 0/imm32/read +285 68/push 0/imm32/write +286 89/<- %ecx 4/r32/esp +287 # var word-slice/edx : slice +288 68/push 0/imm32/end +289 68/push 0/imm32/start +290 89/<- %edx 4/r32/esp +291 # var curr-function/edi : (address function) = Program +292 bf/copy-to-edi Program/imm32 +293 { +294 $parse-mu:line-loop: +295 (clear-stream %ecx) +296 (read-line-buffered *(ebp+8) %ecx) +297 # if (line->write == 0) break +298 81 7/subop/compare *ecx 0/imm32 +299 0f 84/jump-if-equal break/disp32 +300 +-- 6 lines: #? # dump line --------------------------------------------------------------------------------------------------------------------------- +306 { # word loop +307 $parse-mu:word-loop: +308 (next-word-or-string %ecx %edx) +309 # if (slice-empty?(word-slice)) break +310 (slice-empty? %edx) +311 3d/compare-eax-and 0/imm32 +312 0f 85/jump-if-not-equal break/disp32 +313 # if (*word-slice->start == "#") break +314 # . eax = *word-slice->start +315 8b/-> *edx 0/r32/eax +316 8a/copy-byte *eax 0/r32/AL +317 81 4/subop/and %eax 0xff/imm32 +318 # . if (eax == '#') break +319 3d/compare-eax-and 0x23/imm32/hash +320 0f 84/jump-if-equal break/disp32 +321 # if slice-equal?(word-slice, "fn") +322 { +323 (slice-equal? %edx "fn") +324 3d/compare-eax-and 0/imm32 +325 0f 84/jump-if-equal break/disp32 +326 # var new-function/eax : (address function) = populate-mu-function() +327 (allocate Heap *Function-size) # => eax +328 (populate-mu-function-header %ecx %eax) +329 (populate-mu-function-body *(ebp+8) %eax) +330 # *curr-function = new-function +331 89/<- *edi 0/r32/eax +332 # curr-function = &new-function->next +333 8d/address-> *(eax+0x10) 7/r32/edi +334 e9/jump $parse-mu:word-loop/disp32 +335 } +336 # otherwise abort +337 e9/jump $parse-mu:abort/disp32 +338 } # end word loop +339 e9/jump loop/disp32 +340 } # end line loop +341 $parse-mu:end: +342 # . reclaim locals +343 81 0/subop/add %esp 0x214/imm32 +344 # . restore registers +345 5f/pop-to-edi +346 5a/pop-to-edx +347 59/pop-to-ecx +348 58/pop-to-eax +349 # . epilogue +350 89/<- %esp 5/r32/ebp +351 5d/pop-to-ebp +352 c3/return +353 +354 $parse-mu:abort: +355 # error("unexpected top-level command: " word-slice "\n") +356 (write-buffered Stderr "unexpected top-level command: ") +357 (write-buffered Stderr %edx) +358 (write-buffered Stderr "\n") +359 (flush Stderr) +360 # . syscall(exit, 1) +361 bb/copy-to-ebx 1/imm32 +362 b8/copy-to-eax 1/imm32/exit +363 cd/syscall 0x80/imm8 +364 # never gets here +365 +366 # errors considered: +367 # fn foo { { +368 # fn foo { } +369 # fn foo { } { +370 # fn foo # no block +371 populate-mu-function-header: # first-line : (address stream byte), out : (address function) +372 # . prologue +373 55/push-ebp +374 89/<- %ebp 4/r32/esp +375 # . save registers +376 50/push-eax +377 51/push-ecx +378 57/push-edi +379 # edi = out +380 8b/-> *(ebp+0xc) 7/r32/edi +381 # var word-slice/ecx : slice +382 68/push 0/imm32/end +383 68/push 0/imm32/start +384 89/<- %ecx 4/r32/esp +385 # save function name +386 (next-word *(ebp+8) %ecx) +387 (slice-to-string Heap %ecx) # => eax +388 89/<- *edi 0/r32/eax +389 # assert that next token is '{' +390 (next-word *(ebp+8) %ecx) +391 (slice-equal? %ecx "{") +392 3d/compare-eax-and 0/imm32 +393 74/jump-if-equal $populate-mu-function-header:abort/disp8 +394 # assert that there's no further token +395 { +396 # word-slice = next-word(line) +397 (next-word *(ebp+8) %ecx) +398 # if (word-slice == '') break +399 (slice-empty? %ecx) +400 3d/compare-eax-and 0/imm32 +401 75/jump-if-not-equal break/disp8 +402 # if (slice-starts-with?(word-slice, "#")) break +403 # . eax = *word-slice->start +404 8b/-> *edx 0/r32/eax +405 8a/copy-byte *eax 0/r32/AL +406 81 4/subop/and %eax 0xff/imm32 +407 # . if (eax == '#') break +408 3d/compare-eax-and 0x23/imm32/hash +409 74/jump-if-equal break/disp8 +410 # otherwise abort +411 eb/jump $populate-mu-function-header:abort/disp8 +412 } +413 $populate-mu-function-header:end: +414 # . reclaim locals +415 81 0/subop/add %esp 8/imm32 +416 # . restore registers +417 5f/pop-to-edi +418 59/pop-to-ecx +419 58/pop-to-eax +420 # . epilogue +421 89/<- %esp 5/r32/ebp +422 5d/pop-to-ebp +423 c3/return +424 +425 $populate-mu-function-header:abort: +426 # error("function header not in form 'fn <name> {'") +427 (write-buffered Stderr "function header not in form 'fn <name> {' -- '") +428 (rewind-stream *(ebp+8)) +429 (write-stream 2 *(ebp+8)) +430 (write-buffered Stderr "'\n") +431 (flush Stderr) +432 # . syscall(exit, 1) +433 bb/copy-to-ebx 1/imm32 +434 b8/copy-to-eax 1/imm32/exit +435 cd/syscall 0x80/imm8 +436 # never gets here +437 +438 # errors considered: +439 # { abc +440 populate-mu-function-body: # in : (address buffered-file), out : (address function) +441 # . prologue +442 55/push-ebp +443 89/<- %ebp 4/r32/esp +444 # . save registers +445 50/push-eax +446 51/push-ecx +447 52/push-edx +448 53/push-ebx +449 # var line/ecx : (stream byte 512) +450 81 5/subop/subtract %esp 0x200/imm32 +451 68/push 0x200/imm32/length +452 68/push 0/imm32/read +453 68/push 0/imm32/write +454 89/<- %ecx 4/r32/esp +455 # var word-slice/edx : slice +456 68/push 0/imm32/end +457 68/push 0/imm32/start +458 89/<- %edx 4/r32/esp +459 # var open-curly-count/ebx : int = 1 +460 bb/copy-to-ebx 1/imm32 +461 { # line loop +462 $populate-mu-function-body:line-loop: +463 # if (open-curly-count == 0) break +464 81 7/subop/compare %ebx 0/imm32 +465 0f 84/jump-if-equal break/disp32 +466 # line = read-line-buffered(in) +467 (clear-stream %ecx) +468 (read-line-buffered *(ebp+8) %ecx) +469 # if (line->write == 0) break +470 81 7/subop/compare *ecx 0/imm32 +471 0f 84/jump-if-equal break/disp32 +472 # word-slice = next-word(line) +473 (next-word %ecx %edx) +474 # if slice-empty?(word-slice)) continue +475 (slice-empty? %ecx) +476 3d/compare-eax-and 0/imm32 +477 75/jump-if-not-equal loop/disp8 +478 # if (slice-starts-with?(word-slice, '#') continue +479 # . eax = *word-slice->start +480 8b/-> *edx 0/r32/eax +481 8a/copy-byte *eax 0/r32/AL +482 81 4/subop/and %eax 0xff/imm32 +483 # . if (eax == '#') continue +484 3d/compare-eax-and 0x23/imm32/hash +485 74/jump-if-equal loop/disp8 +486 { +487 # if slice-equal?(word-slice, "{") ++open-curly-count +488 { +489 (slice-equal? %ecx "{") +490 3d/compare-eax-and 0/imm32 +491 74/jump-if-equal break/disp8 +492 43/increment-ebx +493 eb/jump $curly-found:end/disp8 +494 } +495 # else if slice-equal?(word-slice, "}") --open-curly-count +496 { +497 (slice-equal? %ecx "}") +498 3d/compare-eax-and 0/imm32 +499 74/jump-if-equal break/disp8 +500 4b/decrement-ebx +501 eb/jump $curly-found:end/disp8 +502 } +503 # else break +504 eb/jump $populate-mu-function-body:end/disp8 +505 } +506 # - check for invalid tokens after curly +507 $curly-found:end: +508 # second-word-slice = next-word(line) +509 (next-word %ecx %edx) +510 # if slice-empty?(second-word-slice)) continue +511 (slice-empty? %ecx) +512 3d/compare-eax-and 0/imm32 +513 0f 85/jump-if-not-equal loop/disp32 +514 # if (slice-starts-with?(second-word-slice, '#') continue +515 # . eax = *second-word-slice->start +516 8b/-> *edx 0/r32/eax +517 8a/copy-byte *eax 0/r32/AL +518 81 4/subop/and %eax 0xff/imm32 +519 # . if (eax == '#') continue +520 3d/compare-eax-and 0x23/imm32/hash +521 0f 84/jump-if-equal loop/disp32 +522 # abort +523 eb/jump $populate-mu-function-body:abort/disp8 +524 } # end line loop +525 $populate-mu-function-body:end: +526 # . reclaim locals +527 81 0/subop/add %esp 0x214/imm32 +528 # . restore registers +529 5b/pop-to-ebx +530 5a/pop-to-edx +531 59/pop-to-ecx +532 58/pop-to-eax +533 # . epilogue +534 89/<- %esp 5/r32/ebp +535 5d/pop-to-ebp +536 c3/return +537 +538 $populate-mu-function-body:abort: +539 # error("'{' or '}' should be on its own line, but got '") +540 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +541 (rewind-stream %ecx) +542 (write-stream 2 %ecx) +543 (write-buffered Stderr "'\n") +544 (flush Stderr) +545 # . syscall(exit, 1) +546 bb/copy-to-ebx 1/imm32 +547 b8/copy-to-eax 1/imm32/exit +548 cd/syscall 0x80/imm8 +549 # never gets here +550 +551 check-mu-types: +552 # . prologue +553 55/push-ebp +554 89/<- %ebp 4/r32/esp +555 # +556 $check-types:end: +557 # . epilogue +558 89/<- %esp 5/r32/ebp +559 5d/pop-to-ebp +560 c3/return +561 +562 emit-subx: # out : (address buffered-file) +563 # . prologue +564 55/push-ebp +565 89/<- %ebp 4/r32/esp +566 # . save registers +567 50/push-eax +568 51/push-ecx +569 57/push-edi +570 # edi = out +571 8b/-> *(ebp+8) 7/r32/edi +572 # var curr/ecx : (address function) = Program +573 8b/-> *Program 1/r32/ecx +574 { +575 # if (curr == NULL) break +576 81 7/subop/compare %ecx 0/imm32 +577 0f 84/jump-if-equal break/disp32 +578 (write-buffered %edi *ecx) +579 (write-buffered %edi ":\n") +580 (emit-subx-prologue %edi) +581 (emit-subx-epilogue %edi) +582 # curr = curr->next +583 8b/-> *(ecx+0x10) 1/r32/ecx +584 e9/jump loop/disp32 +585 } +586 $emit-subx:end: +587 # . restore registers +588 5f/pop-to-edi +589 59/pop-to-ecx +590 58/pop-to-eax +591 # . epilogue +592 89/<- %esp 5/r32/ebp +593 5d/pop-to-ebp +594 c3/return +595 +596 emit-subx-prologue: # out : (address buffered-file) +597 # . prologue +598 55/push-ebp +599 89/<- %ebp 4/r32/esp +600 # +601 (write-buffered *(ebp+8) "# . prologue\n") +602 (write-buffered *(ebp+8) "55/push-ebp\n") +603 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n") +604 # . epilogue +605 89/<- %esp 5/r32/ebp +606 5d/pop-to-ebp +607 c3/return +608 +609 emit-subx-epilogue: # out : (address buffered-file) +610 # . prologue +611 55/push-ebp +612 89/<- %ebp 4/r32/esp +613 # +614 (write-buffered *(ebp+8) "# . epilogue\n") +615 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n") +616 (write-buffered *(ebp+8) "5d/pop-to-ebp\n") +617 (write-buffered *(ebp+8) "c3/return\n") +618 # . epilogue +619 89/<- %esp 5/r32/ebp +620 5d/pop-to-ebp +621 c3/return diff --git a/linkify/linkify.cc b/linkify/linkify.cc index 9557f256..ece50748 100644 --- a/linkify/linkify.cc +++ b/linkify/linkify.cc @@ -203,6 +203,10 @@ void replace_tags_in_file(const string& filename, const map& in out << c; at_start_of_line = false; } + else if (c == ')') { + out << c; + at_start_of_line = false; + } else { //? cerr << "rest\n"; if (c == ',' || c == ':') { @@ -213,7 +217,7 @@ void replace_tags_in_file(const string& filename, const map& in ostringstream out2; out2 << c; while (in2 >> c) { - if (isspace(c) || c == '<' || c == '"' || c == '\'' || c == '/' || c == ',' || c == ':') { // keep sync'd with other clauses above + if (isspace(c) || c == '<' || c == '"' || c == '\'' || c == '/' || c == ',' || c == ':' || c == '(' || c == ')') { // keep sync'd with other clauses above in2.putback(c); break; } -- cgit 1.4.1-2-gfad0