Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ; $$$$$$$$$$$$$$ ABA-KIS EVOLUTION $$$$$$$$$$$$$$$
  2. ; *************** STAR^2 SOFTWARE ****************
  3. ; ???????????????? LANGUAGE.INC ??????????????????
  4.  
  5. ;;;;;;;;;;;;;;;;;;; REGISTERS ;;;;;;;;;;;;;;;;;;;;
  6.  
  7. r0 fix eax
  8. r1 fix ecx
  9. r2 fix edx
  10. r3 fix ebx
  11. r4 fix esp
  12. r5 fix ebp
  13. r6 fix esi
  14. r7 fix edi
  15.  
  16. is.i? fix eqtype 0
  17.  
  18. is.m? fix eqtype [0]
  19.  
  20. is.r? fix in \
  21.  <eax,ecx,edx,ebx,esp,ebp,esi,edi,\
  22.  ax,cx,dx,bx,al,ah,cl,ch,dl,dh,bl,bh>
  23.  
  24. is.r32? fix in \
  25.  <eax,ecx,edx,ebx,esp,ebp,esi,edi>
  26.  
  27. is.r16? fix in <ax,cx,dx,bx>
  28. is.r16x? fix in <ax,cx,dx,bx,sp,bp,si,di>
  29.  
  30. is.r8l? fix in <al,cl,dl,bl>
  31. is.r8h? fix in <ah,ch,dh,bh>
  32. is.r8? fix in <al,ah,cl,ch,dl,dh,bl,bh>
  33.  
  34. ;;;;;;;;;;;;;;;;; SYNTAX, VERIFY ;;;;;;;;;;;;;;;;;
  35.  
  36. ?not fix ~
  37. ?empty fix eq
  38.  
  39. macro syntax v {
  40.  IF v eq
  41.   define ?s 1
  42.  ELSE
  43.   define ?s v
  44.  END IF
  45. }
  46.  
  47. macro verify e {
  48.  IF ?s eq 0
  49.   display `e
  50.   'Error: ' e
  51.  END IF
  52. }
  53.  
  54. if.syntax fix IF ?s eq
  55. if.not.syntax fix IF ?s eq 0
  56.  
  57. macro verify.r [r] {
  58.  IF ~r is.r?
  59.   'Register expected:' r
  60.  END IF
  61. }
  62.  
  63. macro verify.r32 [r] {
  64.  IF ~r is.r32?
  65.   'Register expected:' r
  66.  END IF
  67. }
  68.  
  69. macro verify.i i {
  70.  IF ~i is.i?
  71.   'Number expected:' i
  72.  END IF
  73. }
  74.  
  75. macro verify.n n, min, max {
  76.  IF n<min | n>max
  77.   'Number exceeds range:' min-max
  78.  END IF
  79. }
  80.  
  81. macro verify.u3 n  { verify.n n, 0, 7 }
  82. macro verify.u4 n  { verify.n n, 0, 15 }
  83. macro verify.u5 n  { verify.n n, 0, 31 }
  84. macro verify.u6 n  { verify.n n, 0, 63 }
  85. macro verify.u7 n  { verify.n n, 0, 127 }
  86. macro verify.8 n   { verify.n n, -255, 255 }
  87. macro verify.u8 n  { verify.n n, 0, 255 }
  88. macro verify.i8 n  { verify.n n, -128, 127 }
  89. macro verify.12 n  { verify.n n, -4095, 4095 }
  90. macro verify.u12 n { verify.n n, 0, 4095 }
  91. macro verify.i12 n { verify.n n, -2048, 2047 }
  92. macro verify.16 n  { verify.n n, -65535, 65535 }
  93. macro verify.u16 n { verify.n n, 0, 65535 }
  94. macro verify.i16 n { verify.n n, -32768, 32767 }
  95.  
  96. ; verify size of block/text/array
  97.  
  98. macro verify.size n {
  99.  IF n eq
  100.   'Size must be specified'
  101.  ELSE IF ~ n eqtype 0
  102.   'Size must be numeric'
  103.  ELSE IF n eq 0
  104.   'Size cannot be zero'
  105.  END IF
  106. }
  107.  
  108. ;;;;;;;;;;;;;;;;;;; ALIGNMENT ;;;;;;;;;;;;;;;;;;;;
  109.  
  110. macro align n {
  111.  IF n eq        ; by address size
  112.   align 4
  113.  ELSE
  114.   IF n is.i?    ; align n (standard)
  115.    align n
  116.   ELSE          ; align integer i=123
  117.    align 4
  118.    n            ; line after
  119.   END IF
  120.  END IF
  121. }
  122.  
  123. macro IF.align n, by { IF n mod by=0 }
  124.  
  125. macro IF.not.align n, by { IF n mod by<>0 }
  126.  
  127. macro verify.a n, by {
  128.  display.h n
  129.  IF.not.align n, by
  130.   'Number' n 'must be aligned by:' by
  131.  END IF
  132. }
  133.  
  134. ;;;;;;;;;;;;;;;;;;;; DISPLAY ;;;;;;;;;;;;;;;;;;;;;
  135.  
  136. ; display numbers at assembly time
  137.  
  138. macro display.b n {
  139.  REPEAT 32
  140.   display '0'+((n shr (32-%)) and 1)
  141.  END REPEAT
  142. }    
  143.  
  144. macro display.h n {
  145.  local c
  146.  REPEAT 8
  147.   c=(n and (0Fh shl ((8-%) shl 2))) \
  148.    shr ((8-%) shl 2) + '0'
  149.   IF c>'9'
  150.    c=c+7
  151.   END IF
  152.   display c
  153.   IF %=8
  154.    display 'h'
  155.   END IF
  156.   IF (((%*4) and 31)=0)
  157.    display ' '
  158.   END IF
  159.  END REPEAT
  160. }
  161.  
  162. ;;;;;;;;;;;;;;;;;; EQUATE LIST ;;;;;;;;;;;;;;;;;;;
  163.  
  164. macro ?list.attach list, item {
  165.  match any, list \{ list equ list, item \}
  166.  match , list \{ list equ item \}
  167. }
  168.  
  169. macro ?display.list [p] {
  170.  common
  171.   match q, p \{
  172.    ?p equ q
  173.    irps s, q \\{
  174.     display \\`s, ' '
  175.     match a b, ?p \\\{
  176.      restore ?p
  177.      ?p equ b
  178.     \\\}
  179.    \\}
  180.    restore ?p
  181.   \}
  182. }
  183.  
  184. ;;;;;;;;;;;;;;;;;;;; SETTINGS ;;;;;;;;;;;;;;;;;;;;
  185.  
  186. ; example: ?enable align
  187.  
  188. ?setting.align equ
  189. ?setting.debug equ
  190.  
  191. IF.align fix match =1, ?setting.align
  192. IF.debug fix match =1, ?setting.debug
  193.  
  194. macro ?enable s, v {
  195.  restore ?setting.#s
  196.  match , v
  197.   \{ ?setting.#s equ 1 \}
  198.  match any, v
  199.   \{ ?setting.#s equ v \}
  200. }
  201.  
  202. macro ?disable s {
  203.  restore ?setting.#s
  204.  ?setting.#s equ 0
  205. }
  206.  
  207. ;;;;;;;;;;;;;;;;;;;; VARIABLE ;;;;;;;;;;;;;;;;;;;;
  208.  
  209. _strict_ equ 0 ; strict type safety?
  210. _scope_ equ 0  ; 0=global, 1=local
  211.  
  212. _object_ equ 0
  213.  
  214. ; create variable: name (a), type, value,
  215. ; size (n), sign (s)
  216.  
  217. macro ?V a, t, v, n, s {
  218.  
  219.  IF.align \{ align \}
  220.  
  221.  IF n=8
  222.   !#a dq v
  223.  ELSE IF n=4
  224.   !#a dd v
  225.  ELSE IF n=2
  226.   !#a dw v
  227.  ELSE IF n=1
  228.   !#a db v
  229.  ELSE
  230.   'Invalid size'
  231.  END IF
  232.  
  233.  name$#a equ a
  234.  type$#a=t
  235.  size$#a=n
  236.  sign$#a=s
  237.  scope$#a=_scope_
  238.  strict$#a=_strict_
  239.  
  240.  a equ [!#a]
  241. }
  242.  
  243. ; define X. syntax: type then any a/a=b
  244. ; sequence/s separated with ,s.
  245. ; variables=0 if there is no initial value
  246.  
  247. macro ?D type, [p] {
  248.  forward
  249.   define ?s 0
  250.   match =0 \
  251.    a==b, ?s p \{ ; a=b
  252.    type a, b
  253.    define ?s 1
  254.   \}
  255.   match =0 \
  256.    a=,, ?s p \{  ; a, (next)
  257.    type a, 0
  258.    define ?s 1
  259.   \}
  260.   match =0 \
  261.    a, ?s p \{    ; a (end)
  262.    type a, 0
  263.    define ?s 1
  264.   \}
  265.   verify variable
  266. }
  267.  
  268. ; real variable names...
  269.  
  270. macro i8 a, v  { ?V a, 'i', v, 1, 1 }
  271. macro u8 a, v  { ?V a, 'i', v, 1, 0 }
  272. macro i16 a, v { ?V a, 'i', v, 2, 1 }
  273. macro u16 a, v { ?V a, 'i', v, 2, 0 }
  274. macro i32 a, v { ?V a, 'i', v, 4, 1 }
  275. macro u32 a, v { ?V a, 'i', v, 4, 0 }
  276. macro i64 a, v { ?V a, 'i', v, 8, 1 }
  277. macro u64 a, v { ?V a, 'i', v, 8, 0 }
  278.  
  279. ; aliases...
  280.  
  281. macro void [a]   { ?D u32, a }
  282.  
  283. macro char [a]   { ?D i8, a }
  284. macro uchar [a]  { ?D u8, a }
  285. macro wchar [a]  { ?D u16, a }
  286. macro short [a]  { ?D i16, a }
  287. macro ushort [a] { ?D u16, a }
  288. macro int [a]    { ?D i32, a }
  289. macro uint [a]   { ?D u32, a }
  290. macro long [a]   { ?D i64, a }
  291. macro ulong [a]  { ?D u64, a }
  292. macro float [a]  { ?D u32, a }
  293. macro double [a] { ?D u64, a }
  294.  
  295. macro byte [a]     { ?D i8, a }
  296. macro ubyte [a]    { ?D u8, a }
  297. macro integer [a]  { ?D i32, a }
  298. macro uinteger [a] { ?D u32, a }
  299. macro boolean [a]  { ?D i32, a }
  300.  
  301. ;;;;;;;;;;;;;;;;; LITERAL TABLE ;;;;;;;;;;;;;;;;
  302.  
  303. ?literals.i=0 ; offset
  304.  
  305. ?literals equ align 4,\
  306.  ?LITERALS:, ?literals.i=0
  307.  
  308. ; store literal 'text'. attach line
  309.  
  310. macro ?literal t {
  311.  local n
  312.  virtual at 0
  313.    db t, 0
  314.    n=$
  315.  END virtual
  316.  ?literals equ ?literals,\
  317.   db t, db 0
  318.  ?literals.i=?literals.i+n
  319. }
  320.  
  321. ; store table. expand line/s
  322.  
  323. macro @literals {
  324.  IF ?literals.i
  325.   match j, ?literals \{
  326.    irp i, j \\{ i \\}
  327.   \}
  328.  END IF
  329. }
  330.  
  331. ;;;;;;;;;;;;;;;;; TEXT VARIABLES ;;;;;;;;;;;;;;;;;
  332.  
  333. ; create HL 'text' variable/s. text t='X'.
  334. ; note: (n) is the size
  335.  
  336. macro text [p] {
  337.  forward
  338.   local l
  339.   define ?s 0
  340.   match =0 \           ; text t(n)='abc'
  341.    name(n)==t, ?s p \{
  342.    l=$
  343.    verify.size n
  344.    name: db t, 0
  345.    times \
  346.     (n-($-l)) db 0
  347.    name\#.$=n
  348.    define ?s 1
  349.   \}
  350.   match =0 name(n),\   ; text t(n)
  351.    ?s p \{
  352.    verify.size n
  353.    name: db n dup(0)
  354.    name\#.$=n
  355.    define ?s 1
  356.   \}
  357.   match =0 name==t,\   ; text t='abc'
  358.    ?s p \{
  359.    l=$
  360.    name: db t, 0
  361.    name\#.$=($-l)
  362.    define ?s 1
  363.   \}
  364.   match =0 name, ?s p \{
  365.    'Size not specified:' name
  366.    define ?s 1
  367.   \}
  368.   verify name
  369. }
  370.  
  371. ; helper macros: text/x/a/i/p
  372.  
  373. ; text extended to 2+ lines:
  374.  
  375. ; text name=+'Hi, how ',\
  376. ;  'are ', 'you?'
  377.  
  378. macro textx name, [p] {
  379.  common
  380.   name: db p, 0
  381. }
  382.  
  383. ; create array of pointers and literal
  384. ; 'text'. optional a/lign each to size
  385. ; or 0=none:
  386.  
  387. ; text names[]='ann', 'kim', 'sue'
  388.  
  389. macro texta a, name, [t] {
  390.  common
  391.   local n
  392.   n=0
  393.   label name dword
  394.  forward
  395.   local l
  396.   dd l
  397.   n=n+1
  398.  forward
  399.   l db t, 0
  400.   IF a
  401.    times (a-($-l)) db 0
  402.   END IF
  403.  common
  404.   name#.$=n
  405. }
  406.  
  407. ; like texta with ids (0-n):
  408.  
  409. ; textai 0, names.ta, 'ann', 'kim', 'sue'
  410.  
  411. macro textai a, name, [p] {
  412.  common
  413.   local n
  414.   n=0
  415.   label name dword
  416.  forward
  417.   local l
  418.   dd l
  419.  forward
  420.   define ?s 0
  421.   match id==t, p \{
  422.    l db t, 0
  423.    id=n
  424.    n=n+1
  425.    define ?s 1
  426.   \}
  427.   verify textai
  428.   IF a
  429.    times (a-($-l)) db 0
  430.   END IF
  431.  common
  432.   name#.$=n
  433. }
  434.  
  435. ; same with prefix
  436.  
  437. macro textaip a, name, x, [p] {
  438.  common
  439.   local n
  440.   n=0
  441.   label name dword
  442.  forward
  443.   local l
  444.   dd l
  445.  forward
  446.   define ?s 0
  447.   match id==t, p \{
  448.    l db t, 0
  449.    x\#id=n
  450.    n=n+1
  451.    define ?s 1
  452.   \}
  453.   verify textaip
  454.   IF a
  455.    times (a-($-l)) db 0
  456.   END IF
  457.  common
  458.   name#.$=n
  459. }
  460.  
  461. ; upgrade text to support ()/textx/a/i/p
  462.  
  463. macro text [p] {
  464.  common
  465.   define ?s 0
  466.   match =0 (n), ?s p \{
  467.    db n dup(0)
  468.    define ?s 1
  469.   \}
  470.   match =0 a==+b, ?s p \{
  471.    textx a, b
  472.    define ?s 1
  473.   \}
  474.   match =0 \
  475.    a[]==name* t, ?s p \{
  476.    match x==y, t \\{
  477.     textaip 0, a, name, t
  478.     define ?s 1
  479.    \\}
  480.    IF ?s eq 0
  481.     texta 0, a, t
  482.    END IF
  483.    define ?s 1
  484.   \}
  485.   match =0 \
  486.    a[]==t, ?s p \{
  487.    match x==y, t \\{
  488.     textai 0, a, t
  489.     define ?s 1
  490.    \\}
  491.    IF ?s eq 0
  492.     texta 0, a, t
  493.    END IF
  494.    define ?s 1
  495.   \}
  496.   match =0 \
  497.    a[](n)==t, ?s p \{
  498.    texta n, a, t
  499.    define ?s 1
  500.   \}
  501.   IF ?s eq 0
  502.    text p
  503.   END IF
  504. }
  505.  
  506. ; create 'text' in code. r/egister='t/ext'
  507. ; WARNING: all commands that accept a literal
  508. ; 'text' parameter (.t suffix) will alter eax.
  509. ; only intended for testing and utilities
  510.  
  511. macro make.txt r, t {
  512.  IF t eqtype ""
  513.   local ..t, ..e
  514.   jmp ..e
  515.   ..t db t, 0
  516.   ..e:
  517.   mov r, ..t
  518.  ELSE
  519.   mov r, t
  520.  END IF
  521. }
  522.  
  523. ;;;;;;;;;;;;;;; VARIABLE EXAMPLES ;;;;;;;;;;;;;;
  524.  
  525. ; variables: void, int, float, x
  526.  
  527. ; int i, n=123
  528.  
  529. ; void p
  530.  
  531. ; float f=1.0, g=0.5
  532. ; double d, e=7.25
  533.  
  534. ; text t='ABC', name(64) ; byte[]
  535.  
  536. ; extended 2+ lines:
  537.  
  538. ; text name=+'Hi, how ',\
  539. ;  'are ', 'you?'
  540.  
  541. ; void[]+'text'...
  542.  
  543. ; text ta[]='A', '123'
  544.  
  545. ; with alignment:
  546.  
  547. ; text names[](8)='ann', 'kim', 'sue'
  548.  
  549. ; with numeric ID #s (0-n):
  550.  
  551. ; text xyz[]= \
  552. ;  ID.A='A', ID.B='B', ID.C='C'
  553.  
  554. ; with prefix + ID #s (ERROR.NAME):
  555.  
  556. ; text errors[]= ERROR.* \
  557. ;  NONE    = 'No error',\
  558. ;  SYNTAX  = 'Syntax',\
  559. ;  ADDRESS = 'Invalid address',\
  560. ;  MEMORY  = 'Memory allocation',\
  561. ;  SETUP   = 'Initiation'
  562.  
  563. ; access text from pointer array:
  564.  
  565. ; mov eax, [ta+3*4]
  566. ; say [errors+ERROR.MEMORY*4]
  567.  
  568. ;;;;;;;;;;;;;; NUMERIC CONSTANTS ;;;;;;;;;;;;;;;;;
  569.  
  570. ; create incremental (0-n) list of numeric
  571. ; constants with optional prefix. each token
  572. ; can be assigned or it equals previous+1.
  573. ; if first token ends with *, it becomes the
  574. ; prefix for subsequent tokens. example:
  575.  
  576. ; numeric COLOR.*,\
  577. ; BLACK, WHITE, RED, GREEN, BLUE
  578.  
  579. ; COLOR.BLACK=0 ; output...
  580. ; COLOR.WHITE=1
  581. ; COLOR.RED=2
  582. ; COLOR.GREEN=3
  583. ; COLOR.BLUE=4
  584.  
  585. macro numeric ?p, [p] {
  586.  common
  587.   local n
  588.   n=0                ; n=0
  589.   syntax 0
  590.   match z$*, ?p \{   ; extract prefix
  591.    syntax 1
  592.   \}
  593.   match a==b, ?p \{  ; first item
  594.    a=b
  595.    n=b+1
  596.    syntax 1
  597.   \}
  598.   match =0, ?s \{    ; else, first=0
  599.    ?p=0
  600.    n=1
  601.   \}
  602.  forward
  603.   syntax 0
  604.   match a==b, p \{   ; assigment?
  605.    n=b               ; set n
  606.    match z$*, ?p \\{ ; extract prefix
  607.     z$\\#a=b
  608.     syntax 1
  609.    \\}
  610.    if.syntax 0       ; no prefix
  611.     a=b
  612.    END IF
  613.    syntax 1          ; yes, specified
  614.   \}
  615.   match =0, ?s \{    ; else=n (previous+1)
  616.    match z$*, ?p \\{ ; extract prefix
  617.     z$\\#p=n
  618.     syntax 1
  619.    \\}
  620.    if.syntax 0       ; no prefix
  621.     p=n
  622.    END IF
  623.   \}
  624.   n=n+1              ; n++
  625. }
  626.  
  627. KB=1024             ; 1<<10
  628. MB=1048576          ; 1<<20
  629. GB=1073741824       ; 1<<30
  630.  
  631. numeric YES=1, NO=0, TRUE=1, FALSE=0,\
  632.  NULL=0, DEFAULT=0, NONE=-1, INVALID=-1,\
  633.  DETECT=-1, INFINITE=-1, NOTHING=-1
  634.  
  635. ; note: -1 means "not zero and not maximum"
  636. ; (FFFF/FF/FFh) for indices, sizes, handles
  637. ; (index or pointer), etc, where >=0 is
  638. ; valid/finite/something...
  639.  
  640. ; if n=INFINITE     ; if -1
  641. ; if handle=INVALID ; if -1
  642. ; if n not INVALID  ; if <>-1
  643. ; if win>NOTHING    ; if >=0
  644.  
  645. ;;;;;;;;;;;;;;;;;;;;; POWERS ;;;;;;;;;;;;;;;;;;;;;
  646.  
  647. ; create successive powers of 2 starting
  648. ; at BIT0, from right to left. example:
  649.  
  650. ; powers IS.*, ACTIVE, VISIBLE,\
  651. ;  DRAWABLE, MOVEABLE, SIZABLE
  652.  
  653. macro _powers [id] {
  654.  common local n
  655.  n=0
  656.  forward id=1 shl n
  657.  n=n+1
  658. }
  659.  
  660. macro powers ?p, [p] {
  661.  common
  662.   local n
  663.   n=0                ; n=1
  664.   syntax 0
  665.   match z$*, ?p \{   ; extract prefix
  666.    syntax 1
  667.   \}
  668.   match =0, ?s \{    ; else, first item
  669.    ?p=0
  670.    n=1
  671.   \}
  672.  forward
  673.   syntax 0
  674.   match a==b, p \{   ; assigment?
  675.    n=b               ; set n
  676.    match z$*, ?p \\{ ; extract prefix
  677.     z$\\#a=1 shl n
  678.     syntax 1
  679.    \\}
  680.    if.syntax 0       ; no prefix
  681.     a=1 shl n
  682.    END IF
  683.    syntax 1          ; yes, specified
  684.   \}
  685.   match =0, ?s \{    ; else=n (previous+1)
  686.    match z$*, ?p \\{ ; extract prefix
  687.     z$\\#p=1 shl n
  688.     syntax 1
  689.    \\}
  690.    if.syntax 0       ; no prefix
  691.     p=1 shl n
  692.    END IF
  693.   \}
  694.   n=n+1              ; next bit
  695. }
  696.  
  697. ; create readable bit structure from
  698. ; left to right. example: 0000ABCDb.
  699. ; powerz A, B, C, D ; A=8, B=4, C=2, D=1
  700.  
  701. macro powerz [id] {
  702.  common local n
  703.  n=1
  704.  forward n=n+1
  705.  common n=n-2
  706.  forward id=1 shl n
  707.  n=n-1
  708. }
  709.  
  710. ; get power of 2. n-1 then search from left
  711. ; to right for 1st 0 BIT. rv=return value
  712.  
  713. ; n=0
  714. ; ?power.2 256, n
  715. ; say.n n
  716.  
  717. macro ?power.2 n, rv {
  718.  local i, x
  719.  i=0
  720.  IF (n and (n-1))=0
  721.   i=1
  722.   x=n-1
  723.   WHILE 1
  724.    IF x and (1 shl i)=0
  725.     ?break
  726.    END IF
  727.    i=i+1
  728.   END WHILE
  729.  END IF
  730.  rv=i
  731. }
  732.  
  733. ;;;;;;;;;;;;;;;;;;;; IF BIT/S ;;;;;;;;;;;;;;;;;;;;
  734.  
  735. ; compare BITs in r or eax. alters edx
  736.  
  737. ; if.bit 20
  738. ; if.bits 4-7=1001b
  739. ; if.bit 20, eax
  740. ; if.bits 31-24=11110011b, eax
  741.  
  742. macro if.bit n, r {
  743.  IF ~r eq
  744.   mov edx, r
  745.  ELSE
  746.   mov edx, eax
  747.  END IF
  748.  local ..start, ..else, ..end
  749.  ?IF equ
  750.  ?START equ ..start
  751.  ?ELSE equ ..else
  752.  ?END equ ..end
  753.  ?START:
  754.  test edx, (1 shl n)
  755.  jz ?ELSE
  756. }
  757.  
  758. macro if.not.bit n, r {
  759.  IF ~r eq
  760.   mov edx, r
  761.  ELSE
  762.   mov edx, eax
  763.  END IF
  764.  local ..start, ..else, ..end
  765.  ?IF equ
  766.  ?START equ ..start
  767.  ?ELSE equ ..else
  768.  ?END equ ..end
  769.  ?START:
  770.  test edx, (1 shl n)
  771.  jnz ?ELSE
  772. }
  773.  
  774. ; alters edx
  775.  
  776. macro if.bits n, r {
  777.  local i, b,\
  778.   lo, hi, mask
  779.  syntax 0
  780.  match l-h==v, n \{     ; BITs = value
  781.   IF l<h                ; low to high
  782.    lo=l
  783.    hi=h
  784.   ELSE                  ; high to low
  785.    lo=h
  786.    hi=l
  787.   END IF
  788.   i=0                   ; search value from
  789.   REPEAT 32             ; left to right (31-0)
  790.    IF v and \           ; for 1st BIT set...
  791.     (1 shl (31-i))<>0
  792.     ?break
  793.    END IF
  794.    i=i+1
  795.   END REPEAT
  796.   b=0                   ; # BITs required
  797.   REPEAT 32-i           ; for v/alue
  798.    b=b+1
  799.   END REPEAT
  800.   IF b>(hi-lo+1)        ; example: 4-5=111b
  801.    'Value exceeds size' ; 4-5 is only 2BITs,
  802.   END IF                ; not enough for 111b.
  803.   i=0
  804.   mask=0                ; create mask: 111xb
  805.   REPEAT (hi-lo+1)      ; # 1 BITs
  806.    mask=\
  807.     (mask or (1 shl i))
  808.    i=i+1
  809.   END REPEAT
  810.   local ..start, ..else, ..end
  811.   ?IF equ
  812.   ?START equ ..start
  813.   ?ELSE equ ..else
  814.   ?END equ ..end
  815.   IF ~r eq
  816.    mov edx, r
  817.   ELSE
  818.    mov edx, eax
  819.   END IF
  820.   shr edx, lo           ; extract BITs
  821.   and edx, mask
  822.   ?START:
  823.   cmp edx, v
  824.   jne ?ELSE
  825.   syntax 1
  826.  \}
  827.  verify
  828. }
  829.  
  830. ;;;;;;;;;;;;;;;;;;;;; CLASS ;;;;;;;;;;;;;;;;;;;;;;
  831.  
  832. ; unfinished
  833.  
  834. ; macro class name {
  835. ;   name:
  836. ;   macro u8 a, v \{ u8 name\#.\#a, v \}
  837. ;   macro i8 a, v \{ i8 name\#.\#a, v \}
  838. ;   macro u16 a, v \{ u16 name\#.\#a, v \}
  839. ;   macro i16 a, v \{ i16 name\#.\#a, v \}
  840. ;   macro u32 a, v \{ u32 name\#.\#a, v \}
  841. ;   macro i32 a, v \{ i32 name\#.\#a, v \}
  842. ;   macro u64 a, v \{ u64 name\#.\#a, v \}
  843. ;   macro i64 a, v \{ i64 name\#.\#a, v \}
  844. ;   ...
  845. ; }
  846. ;
  847. ; macro endc [p] {
  848. ;  common
  849. ;   restore u8, i8, u16, i16,\
  850. ;    u32, i32, u64, i64
  851. ; }
  852.  
  853. ; 2-DO: single-line classes:
  854.  
  855. ; class RGB     = byte a, r, g, b
  856. ; class POINT   = integer x, y
  857. ; class LINE    = POINT a, b
  858. ; class BOX     = integer x, y, w, h
  859. ; class POINT3D = integer x, y, z
  860. ; class POLYGON = ARRAY POINT3D points[]
  861.  
  862. macro assume [p] {
  863.  common
  864.   match name==type, p \{
  865.    virtual at 0
  866.     type name
  867.    END virtual
  868.   \}
  869. }
  870.  
  871. ;;;;;;;;;;;;;;;;; LET ARITHMETIC ;;;;;;;;;;;;;;;;;
  872.  
  873. ; perform assignment/s, operation/s and
  874. ; low-level "expressions".
  875.  
  876. ; signed is the default for numbers that can
  877. ; be negative (ex, coordinates). some symbols
  878. ; are for unsigned operations (>>> is shr)
  879.  
  880. ; = is a standard copy, move, assignment
  881.  
  882. ; =& gets the address of integers/void/x
  883.  
  884. ; WARNING: both ++/--/+-/-+ cannot used.
  885. ; replace let eax+[?image.x+edx] (has 2 ++)
  886. ; with: let ecx=[?image.x+edx], eax+ecx
  887.  
  888. macro let [p] {
  889. forward
  890.  define ?s 0
  891.  
  892.  ; a=&b, lea r, [b]
  893.  
  894.  match =0 a==&(b), ?s p \{
  895.   lea a, [b]
  896.   define ?s 1
  897.  \}
  898.  
  899.  match =0 a==&b, ?s p \{
  900.   lea a, b
  901.   define ?s 1
  902.  \}
  903.  
  904.  match =0 a><b, ?s p \{
  905.   xor a, b
  906.   define ?s 1
  907.  \}
  908.  
  909.  ; a=b, mov or push/pop or xor
  910.  
  911.  match =0 a==b, ?s p \{
  912.   IF a eqtype [] & b eqtype [] ; m=m
  913.    push dword b
  914.    pop dword a
  915.   ELSE
  916.    IF b eq 0 & \
  917.     a in <eax,ecx,edx,ebx,esi,edi>
  918.      xor a, a
  919.    ELSE
  920.     mov a, b
  921.    END IF
  922.   END IF
  923.   define ?s 1
  924.  \}
  925.  
  926.  ; binary and/or
  927.  
  928.  match =0 a&b, ?s p \{ and a, b
  929.   define ?s 1 \}
  930.  match =0 a|b, ?s p \{ or a, b
  931.   define ?s 1 \}
  932.  
  933.  ; shifts. note: >>> must be matched
  934.  ; before >> or there will be a partial match
  935.  
  936.  match =0 a>>>b, ?s p \{ shr a, b
  937.   define ?s 1 \}
  938.  match =0 a<<b, ?s p \{ sal a, b
  939.   define ?s 1 \}
  940.  match =0 a>>b, ?s p \{ sar a, b
  941.   define ?s 1 \}
  942.  match =0 a<>>b, ?s p \{ ror a, b
  943.   define ?s 1 \}
  944.  
  945.  ; increment/decrement. must be matched
  946.  ; before a-b, a+b
  947.  
  948.  match =0 a--, ?s p \{
  949.   dec a
  950.   define ?s 1
  951.  \}
  952.  
  953.  match =0 a++, ?s p \{
  954.   inc a
  955.   define ?s 1
  956.  \}
  957.  
  958.  ; add/subtract
  959.  
  960.  match =0 a-b, ?s p \{
  961.   IF b eq 1
  962.    dec a
  963.   ELSE
  964.    sub a, b
  965.   END IF
  966.   define ?s 1
  967.  \}
  968.  
  969.  match =0 a+b, ?s p \{
  970.   IF b eq 1
  971.    inc a
  972.   ELSE
  973.    add a, b
  974.   END IF
  975.   define ?s 1
  976.  \}
  977.  
  978.  ; multiply. 2/4/8/16 will be optimized
  979.  ; and replaced with shift left 1/2/3/4
  980.  
  981.  match =0 a*b, ?s p \{
  982.   IF b eq 2
  983.    sal a, 1
  984.   ELSE IF b eq 4
  985.    sal a, 2
  986.   ELSE IF b eq 8
  987.    sal a, 3
  988.   ELSE IF b eq 16
  989.    sal a, 4
  990.   ELSE
  991.    imul a, b
  992.   END IF
  993.   define ?s 1
  994.  \}
  995.  
  996.  ; divide. a: must be eax or m/2/4/8/16.
  997.  ; b: must be m, ecx or 2/4/8/16.
  998.  ; example: eax=n/123 may be written as:
  999.  
  1000.  ; let eax=n, ecx=123, eax/ecx
  1001.  
  1002.  ; ... instead of 4 separate lines
  1003.  
  1004.  match =0 a/b, ?s p \{
  1005.   IF b eq 2
  1006.    sar a, 1
  1007.   ELSE IF b eq 4
  1008.    sar a, 2
  1009.   ELSE IF b eq 8
  1010.    sar a, 3
  1011.   ELSE IF b eq 16
  1012.    sar a, 4
  1013.   ELSE
  1014.    IF a eq eax
  1015.     cdq
  1016.     idiv b
  1017.    ELSE
  1018.     'Unsupported'
  1019.    END IF
  1020.   END IF
  1021.    define ?s 1
  1022.  \}
  1023.  
  1024.  ; jmp/jz/jnz. only support the most
  1025.  ; common ones for fast assembly speed...
  1026.  
  1027.  match =0 =jmp l, ?s p \{
  1028.   jmp l
  1029.   define ?s 1
  1030.  \}
  1031.  
  1032.  match =0 =jz l, ?s p \{
  1033.   jz l
  1034.   define ?s 1
  1035.  \}
  1036.  
  1037.  match =0 =jnz l, ?s p \{
  1038.   jnz l
  1039.   define ?s 1
  1040.  \}
  1041.  
  1042.  ; unary prefixes
  1043.  
  1044.  match =0 -a, ?s p \{
  1045.   neg a
  1046.   define ?s 1
  1047.  \}
  1048.  
  1049.  match =0 =neg a, ?s p \{
  1050.   neg a
  1051.   define ?s 1
  1052.  \}
  1053.  
  1054.  match =0 =not a, ?s p \{
  1055.   not a
  1056.   define ?s 1
  1057.  \}
  1058.  
  1059.  match =0 =bswap a, ?s p \{
  1060.   bswap a
  1061.   define ?s 1
  1062.  \}
  1063.  
  1064.  match =0 xchg(a=,b), ?s p \{
  1065.   xchg a, b
  1066.   define ?s 1
  1067.  \}
  1068.  
  1069.  match =0 =mul a, ?s p \{
  1070.   mul a
  1071.   define ?s 1
  1072.  \}
  1073.  
  1074.  match =0 =div a, ?s p \{
  1075.   div a
  1076.   define ?s 1
  1077.  \}
  1078.  
  1079.  verify let
  1080. }
  1081.  
  1082. ;;;;;;;;;;;;;;;;; GET SIZE/SIGN ;;;;;;;;;;;;;;;;;;
  1083.  
  1084. ; from t=type name, return s=size and
  1085. ; i=sign in numeric constants. example:
  1086.  
  1087. ; size=0
  1088. ; sign=0
  1089. ; @gets i32, size, sign ; s=32, i=1
  1090.  
  1091. macro @gets t, s, i {
  1092.  s=0
  1093.  i=0
  1094.  IF t eq u32 | t eq i32 | t eq dword
  1095.   s=32
  1096.  ELSE IF t eq u16 | t eq i16 | t eq word
  1097.   s=16
  1098.  ELSE IF t eq u8 | t eq i8 | t eq byte
  1099.   s=8
  1100.  ELSE
  1101.   'Unknown type'
  1102.  END IF
  1103.  IF t eq i32 | t eq i16 | t eq i8
  1104.   i=1
  1105.  END IF
  1106. }
  1107.  
  1108. ;;;;;;;;;;;;;;; POINTER ARITHMETIC ;;;;;;;;;;;;;;;
  1109.  
  1110. ;;;;;;;;;;;;;;;;;; GET/SET VALUE ;;;;;;;;;;;;;;;;;
  1111.  
  1112. ; helper load/store...
  1113.  
  1114. ; t=type, r=register, v=value,
  1115. ; s=size, i=sign
  1116.  
  1117. macro @gv t, r, v, s, i {
  1118.  IF s=32
  1119.   mov r, v
  1120.  ELSE IF s=8
  1121.   IF i=1
  1122.    movsx r, byte v
  1123.   ELSE
  1124.    movzx r, byte v
  1125.   END IF
  1126.  ELSE IF s=16
  1127.   IF i=1
  1128.    movsx r, word v
  1129.   ELSE
  1130.    movzx r, word v
  1131.   END IF
  1132.  END IF
  1133. }
  1134.  
  1135. macro @get t, r, [v] {
  1136.  common
  1137.   local s, i              ; get size
  1138.   @gets t, s, i           ; and sign
  1139.   define ?s 0
  1140.   match *a, v \{          ; *p
  1141.    match x++, a \\{       ; *p++
  1142.     ?a equ x
  1143.     ?o equ add
  1144.     define ?s 1
  1145.    \\}
  1146.    match =0 \
  1147.     x--, ?s a \\{         ; *p--
  1148.     ?a equ x
  1149.     ?o equ sub
  1150.     define ?s 1
  1151.    \\}
  1152.    match =0 x, ?s a \\{   ; else, *p
  1153.     ?a equ x
  1154.     ?o equ                ; no advance
  1155.     define ?s 1
  1156.    \\}
  1157.    IF ~ ?a is.r?
  1158.     'Error'
  1159.    END IF
  1160.    @gv t, r, [?a], s, i   ; get value
  1161.    IF ~ ?o eq             ; advance?
  1162.      ?o ?a, s/8           ; add/sub n
  1163.    END IF
  1164.    verify
  1165.   \}
  1166.   match =0 a, ?s v \{     ; r
  1167.    @gv t, r, a, s, i
  1168.    define ?s 1
  1169.   \}
  1170.   verify
  1171.   restore ?a, ?o
  1172. }
  1173.  
  1174. ; t=type, r=register, v=value
  1175.  
  1176. macro @sv t, r, v {
  1177.  IF t eq u32 | t eq i32 | t eq dword
  1178.   mov dword v, r
  1179.  ELSE IF t eq u16 \
  1180.   | t eq i16 | t eq word
  1181.   IF r eq eax
  1182.    mov v, ax
  1183.   ELSE IF r eq ecx
  1184.    mov v, cx
  1185.   ELSE IF r eq edx
  1186.    mov v, dx
  1187.   ELSE IF r eq ebx
  1188.    mov v, bx
  1189.   ELSE                  ; assume i
  1190.    mov dword v, r
  1191.   END IF
  1192.  ELSE IF t eq u8 \
  1193.   | t eq i8 | t eq byte
  1194.   IF r eq eax
  1195.    mov v, al
  1196.   ELSE IF r eq ecx
  1197.    mov v, cl
  1198.   ELSE IF r eq edx
  1199.    mov v, dl
  1200.   ELSE IF r eq ebx
  1201.    mov v, bl
  1202.   ELSE                  ; assume i
  1203.    mov dword v, r
  1204.   END IF
  1205.  ELSE
  1206.   'Unknown type/size'
  1207.  END IF
  1208. }
  1209.  
  1210. macro @set t, r, [v] {
  1211.  common
  1212.   local s, i              ; get size
  1213.   @gets t, s, i           ; and sign
  1214.   define ?s 0
  1215.   match *a, v \{          ; *p
  1216.    match x++, a \\{       ; *p++
  1217.     ?a equ x
  1218.     ?o equ add
  1219.     define ?s 1
  1220.    \\}
  1221.    match =0 \
  1222.     x--, ?s a \\{         ; *p--
  1223.     ?a equ x
  1224.     ?o equ sub
  1225.     define ?s 1
  1226.    \\}
  1227.    match =0 x, ?s a \\{   ; else, *p
  1228.     ?a equ x
  1229.     ?o equ                ; no advance
  1230.     define ?s 1
  1231.    \\}
  1232.    IF ~ ?a is.r?
  1233.     'Error'
  1234.    END IF
  1235.    @sv t, r, [?a]         ; set value
  1236.    IF ~ ?o eq             ; advance
  1237.     ?o ?a, s/8            ; add/sub n
  1238.    END IF
  1239.    verify
  1240.   \}
  1241.   match =0 a, ?s v \{     ; r
  1242.    @sv t, r, a            ; set value
  1243.    define ?s 1
  1244.   \}
  1245.   verify
  1246.   restore ?a, ?o
  1247. }
  1248.  
  1249. ;;;;;;;;;;;;;;;; POINTER OPERATION ;;;;;;;;;;;;;;;
  1250.  
  1251. macro let [p] {
  1252.  forward
  1253.   define ?s 0
  1254.   match =0 (t) \     ; (t) a=*(b)
  1255.    a==*(b), ?s p \{
  1256.     @get t, a, [b]
  1257.     define ?s 1
  1258.   \}
  1259.   match =0 \         ; a=*(b)
  1260.    a==*(b), ?s p \{  ; (u8) default
  1261.     @get u8, a, [b]
  1262.     define ?s 1
  1263.   \}
  1264.   match =0 (t) \     ; (t) *(a)=b
  1265.    *(a)==b, ?s p \{
  1266.     @set t, b, [a]
  1267.     define ?s 1
  1268.   \}
  1269.   match =0 \         ; *(a)=b
  1270.    *(a)==b, ?s p \{  ; (u8) default
  1271.     @set u8, b, [a]
  1272.     define ?s 1
  1273.   \}
  1274.   match \
  1275.    (t) a==b, p \{    ; (t) a=b
  1276.    match *x, a \\{   ; m,m
  1277.     match *y, b \\\{
  1278.      @get t, ebx, b  ; use ebx
  1279.      @set t, ebx, a
  1280.      define ?s 1
  1281.     \\\}
  1282.    \\}
  1283.    IF ?s eq 0
  1284.     match *y, b \\{  ; source=*p
  1285.      @get t, a, b
  1286.      define ?s 1
  1287.     \\}
  1288.     IF ?s eq 0
  1289.      match *x, a \\{ ; destiny=*p
  1290.       @set t, b, a
  1291.       define ?s 1
  1292.      \\}
  1293.     END IF
  1294.    END IF
  1295.   \}
  1296.   match =0 \
  1297.    a==b, ?s p \{     ; a=b
  1298.    match *x, a \\{   ; m,m
  1299.     match *y, b \\\{
  1300.      @get u8, ebx, b ; use ebx
  1301.      @set u8, ebx, a
  1302.      define ?s 1
  1303.     \\\}
  1304.    \\}
  1305.    IF ?s eq 0
  1306.     match *y, b \\{  ; source=*
  1307.      @get u8, a, b
  1308.      define ?s 1
  1309.     \\}
  1310.     IF ?s eq 0
  1311.      match *x, a \\{ ; destiny=*p
  1312.       @set u8, b, a
  1313.       define ?s 1
  1314.      \\}
  1315.     END IF
  1316.    END IF
  1317.   \}
  1318.  
  1319.   ; 2-DO: insert improved let
  1320.  
  1321.   IF ?s eq 0         ; default
  1322.     let p
  1323.   END IF
  1324. }
  1325.  
  1326. ;;;;;;;;;;;;;;;;;;; FUNCTION ;;;;;;;;;;;;;;;;;;;;;
  1327.  
  1328. macro pushr [p] { ; push parameters backwards
  1329.  common           ; to access forwards
  1330.   IF ~p eq
  1331.    reverse
  1332.    pushd p
  1333.   common
  1334.   END IF
  1335. }
  1336.  
  1337. ; call a/ddress direct or p/ointer indirect
  1338.  
  1339. macro call a, [p] {
  1340.  common pushr p
  1341.  call a
  1342. }
  1343.  
  1344. macro callp f, [p] { common call [f], p }
  1345.  
  1346. ; call "function" forward reference that
  1347. ; has not been defined yet
  1348.  
  1349. macro callf f, [p] { common call !#f, p }
  1350.  
  1351. ; call "variadic" procedure with "variable
  1352. ; arguments" (...). push invisible # arguments
  1353. ; last, call, then adjust esp after
  1354.  
  1355. macro callv f, [p] {
  1356.  common ?n=0
  1357.  reverse pushd p
  1358.  ?n=?n+1
  1359.  common push ?n
  1360.  call f
  1361.  add esp, (?n+1)*4
  1362. }
  1363.  
  1364. ; call "interface"
  1365.  
  1366. macro callx c, x, [p] {
  1367.  common
  1368.  pushr p            ; push parameters
  1369.  mov eax, c
  1370.  push eax           ; push class address
  1371.  mov eax, [eax]
  1372.  call dword [eax+x] ; call method offset
  1373. }
  1374.  
  1375. ; call function pointer IF non-zero
  1376.  
  1377. macro callfp f {
  1378.  cmp dword [f], 0
  1379.  jz @f
  1380.  call dword [f]
  1381.  @@:
  1382. }
  1383.  
  1384. ; call function IF defined
  1385.  
  1386. macro ?call name, [p] {
  1387.  common
  1388.  IF defined name
  1389.   call name, p
  1390.  END IF
  1391. }
  1392.  
  1393. ; call function then get return. example:
  1394.  
  1395. ; get n=text.n t
  1396. ; get c=rgb 128, 0, 64
  1397.  
  1398. macro get [p] {
  1399.  common
  1400.   define ?s 0
  1401.   match v==f ps, p \{
  1402.    f ps
  1403.    mov v, eax
  1404.    define ?s 1
  1405.   \}
  1406.   match =0 v==f, ?s p \{
  1407.    f
  1408.    mov v, eax
  1409.    define ?s 1
  1410.   \}
  1411.   verify get
  1412. }
  1413.  
  1414. ; set label for try/fail
  1415.  
  1416. define ?ef .! ; end function
  1417.  
  1418. macro fault l { define ?ef l }
  1419. macro catch l { define ?ef l }
  1420.  
  1421. ; call function then jmp to return
  1422. ; if it returns 0. example:
  1423.  
  1424. ; try open filename
  1425. ; try p=allocate 4*KB
  1426.  
  1427. macro try [p] {
  1428.  common
  1429.   define ?s 0
  1430.   match a==b, p \{
  1431.    b
  1432.    mov a, eax
  1433.    define ?s 1
  1434.   \}
  1435.   IF ?s eq 0
  1436.    common p
  1437.   END IF
  1438.   fail ?ef ; endf
  1439. }
  1440.  
  1441. ;;;;;;;;;;;;;; FUNCTION/PROCEDURE ;;;;;;;;;;;;;;;
  1442.  
  1443. ; create "function/proc/edure"...
  1444.  
  1445. macro function name, [p] {
  1446.  common
  1447.   local i, n
  1448.   n=0
  1449.  forward
  1450.   n=n+1
  1451.  common
  1452.  !#name#$type='f'
  1453.  
  1454.  ; only insert this inside of the executable
  1455.  ; if it was accessed somewhere
  1456.  
  1457.  IF used !#name ; real function !name
  1458.   !#name:
  1459.  
  1460.  ; macro to call with no prefix.
  1461.  ; example: f a, b, c
  1462.  
  1463.  macro name p \{
  1464.   pushr p
  1465.   call !\#name
  1466.  \}
  1467.  
  1468.  ?begin equ !#name
  1469.  ?parameters equ p
  1470.  ?alias equ
  1471.  
  1472.  ..n.parameters=0
  1473.  ..n.locals=0
  1474.  ..locals.size=0
  1475.  
  1476.  ; create parameter names and offsets
  1477.  
  1478.  IF ~ p eq           ; if parameters
  1479.   virtual at ebp+8
  1480.   forward
  1481.   local ..p
  1482.   ..p dd ?           ; (ebp+8)+i*4
  1483.   p equ [..p]
  1484.   ..n.parameters=\   ; i++
  1485.   ..n.parameters+1
  1486.   common
  1487.   END virtual
  1488.   push ebp           ; create stack frame
  1489.   mov ebp, esp
  1490.  END IF
  1491.  ; ...
  1492. }
  1493.  
  1494. ; HL return statement. use this instead of
  1495. ; ret/n in functions. no ret/urn before endf.
  1496. ; it inserts one automatically
  1497.  
  1498. macro return v {
  1499.  IF ~v eq               ; value?
  1500.   mov eax, v
  1501.  END IF
  1502.  IF ..n.parameters<>0   ; if parameters
  1503.   mov esp, ebp
  1504.   pop ebp
  1505.   ret ..n.parameters*4  ; ret n
  1506.  ELSE IF ..n.locals<>0  ; if locals
  1507.   mov esp, ebp
  1508.   pop ebp
  1509.   ret
  1510.  ELSE
  1511.   ret
  1512.  END IF
  1513. }
  1514.  
  1515. ; end function
  1516.  
  1517. macro endf v {
  1518.  IF ~v eq
  1519.   mov eax, v
  1520.  END IF
  1521.  .!:
  1522.  return
  1523.  .$=$-?begin              ; total size
  1524.  IF ..n.parameters<>0     ; if parameters
  1525.   match p, ?parameters
  1526.   \{ restore p, ?begin \}
  1527.   END IF
  1528.  IF ..n.locals<>0         ; if locals
  1529.   match l, local.names
  1530.   \{ restore l \}
  1531.  match a, ?alias \
  1532.   \{ restore a \}
  1533.   fault .!                ; reset try label
  1534.  END IF
  1535.  
  1536.  ; end "if used name" at very beginning
  1537.  ; of function
  1538.  
  1539.  END IF
  1540. }
  1541.  
  1542. ; aliases for register names inside functions.
  1543. ; endf will restore names. example:
  1544.  
  1545. ; alias x=r0, y=r1, w=r2, h=r3, c=v1
  1546.  
  1547. macro alias [x] {
  1548.  forward
  1549.   syntax 0
  1550.   match name==r, x \{
  1551.    ?list.attach ?alias, name
  1552.    name equ r
  1553.    syntax 1
  1554.   \}
  1555.   verify
  1556. }
  1557.  
  1558. ; end alias outside function
  1559.  
  1560. macro endal
  1561.  { match a, ?alias \{ restore a \} }
  1562.  
  1563. ;;;;;;;;;;;;;;;;;;;;; LOCALS ;;;;;;;;;;;;;;;;;;;;;
  1564.  
  1565. ; locals ... - create local 32BIT variables.
  1566. ; example: locals x, y, n, c
  1567.  
  1568. macro locals [p] {
  1569.  common local.names equ p
  1570.  forward ..n.locals=..n.locals+1
  1571.  common ..locals.size=..n.locals*4
  1572.  virtual at ebp-..locals.size
  1573.  forward
  1574.  local ..l
  1575.  ..l dd ?
  1576.  p equ [..l]
  1577.  common
  1578.  END virtual
  1579.  IF ..n.parameters=0   ; create stack frame?
  1580.   push ebp
  1581.   mov ebp, esp
  1582.  END IF
  1583.  sub esp, ..locals.size ; allocate locals
  1584. }
  1585.  
  1586. ; create locals of specified sizes or 32BIT.
  1587. ; example:
  1588.  
  1589. ; locale x, y, username(32), filename(256),\
  1590. ; image(IMAGE.$), my.font(FONT.$), etc
  1591.  
  1592. macro locale [p] {
  1593.  common
  1594.   ..locals.size=0
  1595.  forward                 ; get names and sizes
  1596.   define ?s 0
  1597.   match name(size), p \{ ; size specified
  1598.    ?list.attach \
  1599.     local.names, name
  1600.    verify.size size
  1601.    ..locals.size=..locals.size+size
  1602.    define ?s 1
  1603.   \}
  1604.   match =0 name, ?s p \{ ; default 32BIT
  1605.    ?list.attach \
  1606.     local.names, name
  1607.    ..locals.size=..locals.size+4
  1608.    define ?s 1
  1609.   \}
  1610.   ..n.locals=..n.locals+1
  1611.  common
  1612.   virtual at ebp-..locals.size ; get offsets
  1613.  forward
  1614.   local ..l
  1615.   define ?s 0
  1616.   match name(size), p \{
  1617.    ..l dd (size/4) dup(?)
  1618.    name equ [..l]
  1619.    define ?s 1
  1620.   \}
  1621.   match =0 name, ?s p \{   ; default 32BIT
  1622.    ..l dd ?
  1623.    name equ [..l]
  1624.    define ?s 1
  1625.   \}
  1626.  common
  1627.   END virtual
  1628.   IF ..n.parameters=0    ; create stack frame?
  1629.    push ebp
  1630.    mov ebp, esp
  1631.   END IF
  1632.   sub esp, ..locals.size  ; allocate locals
  1633. }
  1634.  
  1635. ;;;;;;;;;;;;;;;;;; IF EXPRESSION ;;;;;;;;;;;;;;;;;
  1636.  
  1637. ?NOT equ 0
  1638. ?use.r equ 0
  1639.  
  1640. ; jump if condition to l (or ?NOT IF 1)
  1641.  
  1642. macro jif l, [c] {
  1643. common
  1644.  local f
  1645.  define ?s 0
  1646.  
  1647.  match =0 =true, ?s c \{
  1648.   test eax, eax
  1649.   jz l
  1650.   define ?s 1
  1651.  \}
  1652.  match =0 =false, ?s c \{
  1653.   test eax, eax
  1654.   jnz l
  1655.   define ?s 1
  1656.  \}
  1657.  match =0 =valid, ?s c \{
  1658.   cmp eax, -1
  1659.   je l
  1660.   define ?s 1
  1661.  \}
  1662.  match =0 =invalid, ?s c \{
  1663.   cmp eax, -1
  1664.   jne l
  1665.   define ?s 1
  1666.  \}
  1667.  
  1668.  macro ?J O,A,C,B, [X] \{
  1669.  match =0 X, ?s c \\{
  1670.   IF ?use.r eq 0
  1671.    O A, B         ; opcode o1, o2
  1672.   ELSE
  1673.    mov ?use.r, A
  1674.    O ?use.r, B
  1675.   END IF
  1676.   IF ?NOT eq 0
  1677.    j\#C l
  1678.   ELSE
  1679.    jN\#C l
  1680.   END IF
  1681.   define ?s 1
  1682.  \\}
  1683.  \}
  1684.  
  1685.  ; standard expressions...
  1686.  
  1687.  ?J cmp,a,NE,b,  a<>b     ; a not b (a<>b)
  1688.  
  1689.  ?J cmp,a,BE,b,  a<<==b   ; a<<=b
  1690.  ?J cmp,a,AE,b,  a>>==b   ; a>>=b
  1691.  ?J cmp,a,B,b,   a<<b     ; a<<b
  1692.  ?J cmp,a,A,b,   a>>b     ; a>>b
  1693.  
  1694.  ?J cmp,a,LE,b,  a<==b    ; a<=b
  1695.  ?J cmp,a,GE,b,  a>==b    ; a>=b
  1696.  ?J cmp,a,L,b,   a<b      ; a<b
  1697.  ?J cmp,a,G,b,   a>b      ; a>b
  1698.  ?J cmp,a,E,b,   a==b     ; a=b
  1699.  ?J cmp,a,NE,b,  a =not b ; a not b (a<>b)
  1700.  ?J test,a,NE,b, a&b      ; a&b
  1701.  ?J or,a,NE,b,   a|b      ; a|b
  1702.  ?J cmp,a,E,0,  =not a    ; not a (=0)
  1703.  
  1704.  ; 2-DO: support pointer arithmetic
  1705.  ; and functions: if p=allocate 4*KB
  1706.  
  1707.  ; else, default: a (not 0, by itself)
  1708.  
  1709.  ?J cmp,a,NE,0,a
  1710.  
  1711.  verify 'Invalid expression' c
  1712.  ?use.r equ 0
  1713. }
  1714.  
  1715. ; jump to l IF NOT condition
  1716.  
  1717. macro jifn l, [c] {
  1718.  common
  1719.  ?NOT equ 1
  1720.  jif l, c
  1721.  ?NOT equ 0 ; restore default
  1722. }
  1723.  
  1724. ; HL IF/ELSE
  1725.  
  1726. macro if.begin {
  1727.  local ..start, ..else, ..end
  1728.  ?IF equ
  1729.  ?START equ ..start
  1730.  ?ELSE equ ..else
  1731.  ?END equ ..end
  1732.  ?START:
  1733. }
  1734.  
  1735. macro if.n [c] {
  1736.  common
  1737.   if.begin
  1738.   jif ?ELSE, c
  1739. }
  1740.  
  1741. macro if [p] {
  1742.  common
  1743.   if.begin
  1744.   define ?s 0
  1745.   match a=,b, p \{
  1746.    jifn ?ELSE, a
  1747.    let b
  1748.    define ?s 1
  1749.   \}
  1750.   match =0, ?s \{
  1751.    jifn ?ELSE, p
  1752.   \}
  1753.   verify if
  1754. }
  1755.  
  1756. macro else [p] {
  1757.  common
  1758.   jmp ?END
  1759.   ?ELSE:
  1760.   restore ?IF
  1761.   ?IF equ ,
  1762.   match =,x, p \{ let x \}
  1763. }
  1764.  
  1765. macro else.if [p] {
  1766.  common
  1767.   local ..else
  1768.   jmp ?END
  1769.   ?ELSE:
  1770.   restore ?ELSE
  1771.   ?ELSE equ ..else
  1772.   define ?s 0
  1773.   match a=,b, p \{
  1774.    jifn ?ELSE, a
  1775.    . b
  1776.    define ?s 1
  1777.   \}
  1778.   match =0 a, ?s p \{
  1779.    jifn ?ELSE, a
  1780.   \}
  1781.   verify else.if
  1782. }
  1783.  
  1784. macro end [p] {
  1785.  common
  1786.   IF ?IF eq
  1787.    ?ELSE:
  1788.   END IF
  1789.   ?END:
  1790.   restore ?IF, ?START, ?ELSE, ?END
  1791.   match =,x, p \{ let x \}
  1792. }
  1793.  
  1794. ; call function with parameters then
  1795. ; if non/zero
  1796.  
  1797. macro !if f, [p] {
  1798.  common f p
  1799.  if eax
  1800. }
  1801.  
  1802. macro !if.n f, [p] {
  1803.  common f p
  1804.  if eax=0
  1805. }
  1806.  
  1807. jNE equ jne
  1808. jNNE equ je
  1809. jNA equ jna
  1810. jNB equ jnb
  1811. jNG equ jng
  1812. jNL equ jnl
  1813.  
  1814. macro jifc r, c, l {
  1815.  test r, r
  1816.  j#c l
  1817. }
  1818.  
  1819. macro fail l {
  1820.  IF l eq
  1821.   jifc eax, z, ?ef
  1822.  ELSE
  1823.   jifc eax, z, l
  1824.  END IF
  1825. }
  1826.  
  1827. macro failn l {
  1828.  IF l eq
  1829.   cmp eax, -1
  1830.   je ?ef
  1831.  ELSE
  1832.   cmp eax, -1
  1833.   je l
  1834.  END IF
  1835. }
  1836.  
  1837. macro success l { jifc eax, nz, l }
  1838.  
  1839. failnz fix success
  1840.  
  1841. ; fail? or escape? on condition
  1842. ; example: escape? eax=-1
  1843.  
  1844. macro fail? [c] {
  1845.  common
  1846.  IF c eq
  1847.   test eax, eax
  1848.   jz ?ef
  1849.  ELSE
  1850.   if c
  1851.    jmp ?ef
  1852.   end
  1853.  END IF
  1854. }
  1855.  
  1856. ;;;;;;;;;;;;;;;;;;;;;; LOOP ;;;;;;;;;;;;;;;;;;;;;;
  1857.  
  1858. ; loop variations. unfinished...
  1859.  
  1860. macro forever [p] {
  1861.  common
  1862.   local ..start, ..next, ..end
  1863.   ?STARTFV equ ..start
  1864.   ?NEXTFV equ ..next
  1865.   ?ENDFV equ ..end
  1866.   ?STARTFV:
  1867.   ?HL.BLOCK='fv'
  1868.   match =,x, p \{ let x \}
  1869. }
  1870.  
  1871. macro endfv [p] {
  1872.  common
  1873.   ?NEXTFV:
  1874.    jmp ?STARTFV
  1875.   ?ENDFV:
  1876.   restore ?STARTFV, ?NEXTFV, ?ENDFV
  1877.   match a=,b, p \{ let b \}
  1878. }
  1879.  
  1880. macro repeat n {
  1881.  local ..start, ..end
  1882.  ?STARTR equ ..start
  1883.  ?ENDR equ ..end
  1884.  ?NR equ n
  1885.  ?HL.BLOCK='r'
  1886.  ?STARTR:
  1887.   cmp ?NR, 0
  1888.   jle ?ENDR
  1889. }
  1890.  
  1891. macro endr {
  1892.   dec ?NR
  1893.  jmp ?STARTR
  1894.  ?ENDR:
  1895.  restore ?STARTR, ?ENDR, ?NR
  1896. }
  1897.  
  1898. macro while [c] {
  1899.  common
  1900.   local ..a, ..b, ..c
  1901.   ?STARTW equ ..a
  1902.   ?NEXTW equ ..b
  1903.   ?ENDW equ ..c
  1904.   ?HL.BLOCK='w'
  1905.   ?STARTW:
  1906.   define ?s 0
  1907.   match a=,b, c \{
  1908.    jifn ?ENDW, a
  1909.    let b
  1910.    define ?s 1
  1911.   \}
  1912.   match =0 a, ?s c \{
  1913.    jifn ?ENDW, a
  1914.   \}
  1915. }
  1916.  
  1917. macro endw [p] {
  1918.  common
  1919.   ?NEXTW:
  1920.    jmp ?STARTW
  1921.   ?ENDW:
  1922.   restore ?STARTW, ?NEXTW, ?ENDW
  1923.   match =,x, p \{ let x \}
  1924. }
  1925.  
  1926. ; unfinished, exhausted, can't keep
  1927. ; eyes open... 2-DO: improve all
  1928. ; blocks/if/loops
  1929.  
  1930. ; loop          ; infinite
  1931. ; loop n        ; # times
  1932. ; loop i=0 to n ; iterate (2-DO)
  1933. ; loop X, ...   ; optional arithmetic
  1934.  
  1935. ?LOOP.N fix 1   ; repeat # times
  1936. ?LOOP.I fix 2   ; index, i=0 to n
  1937. ?LOOP.F fix 3   ; forever, infinite
  1938.  
  1939. macro loop [c] {
  1940.  common
  1941.   local ..a, ..b, ..c
  1942.   ?STARTL equ ..a
  1943.   ?NEXTL equ ..b
  1944.   ?ENDL equ ..c
  1945.   ?STARTL:
  1946.   define ?s 0
  1947.   match =0 n=,x, ?s c \{  ; loop n, ...
  1948.    ?HL.BLOCK=?LOOP.N
  1949.    ?N equ n
  1950.    cmp n, 0
  1951.    jle ?ENDL
  1952.    let x
  1953.    define ?s 1
  1954.   \}
  1955.   match =0 =,x, ?s c \{   ; loop, ...
  1956.    ?HL.BLOCK=?LOOP.F
  1957.    let x
  1958.    define ?s 1
  1959.   \}
  1960.   match =0 n, ?s c \{     ; loop n
  1961.    ?HL.BLOCK=?LOOP.N
  1962.    ?N equ n
  1963.    cmp n, 0
  1964.    jle ?ENDL
  1965.    define ?s 1
  1966.   \}
  1967.   verify loop
  1968. }
  1969.  
  1970. macro endl [p] {
  1971.  common
  1972.   IF ?HL.BLOCK=?LOOP.N
  1973.     dec ?N
  1974.     restore ?N
  1975.   END IF
  1976.   ?NEXTL:
  1977.   jmp ?STARTL
  1978.   ?ENDL:
  1979.   restore ?STARTL, ?NEXTL, ?ENDL
  1980.   match =,x, p \{ let x \}
  1981. }
  1982.  
  1983. macro break [p] {
  1984.  common
  1985.   IF ?HL.BLOCK='fv'
  1986.     jmp ?ENDFV
  1987.   ELSE IF ?HL.BLOCK='r'
  1988.     jmp ?ENDR
  1989.   ELSE IF ?HL.BLOCK='w'
  1990.     jmp ?ENDW
  1991.   ELSE IF ?HL.BLOCK='l'
  1992.     jmp ?ENDL
  1993.   END IF
  1994.  match =,x, p \{ let x \}
  1995. }
  1996.  
  1997. macro next [p] {
  1998.  common
  1999.   IF ?HL.BLOCK='fv'
  2000.     jmp ?STARTFV
  2001.   ELSE IF ?HL.BLOCK='r'
  2002.     jmp ?STARTR
  2003.   ELSE IF ?HL.BLOCK='w'
  2004.     jmp ?STARTW
  2005.   ELSE IF ?HL.BLOCK='l'
  2006.     jmp ?STARTL
  2007.   END IF
  2008.  match =,x, p \{ let x \}
  2009. }
  2010.  
  2011. macro continue [p] { common next p }
  2012.  
  2013. ; 2-DO: create one "end" for all HL blocks
  2014.  
  2015. ;;;;;;;;;;;;;;;;;; NEW LANGUAGE ;;;;;;;;;;;;;;;;;;
  2016.  
  2017. ; upgrade let with multi-statements.
  2018. ; unfinished. 2-DO: create one good "let"
  2019. ; with helper macros
  2020.  
  2021. macro let [p] {
  2022.  forward
  2023.   define ?s 0
  2024.   match =0 \
  2025.    l:, ?s p \{
  2026.    l:
  2027.    define ?s 1
  2028.   \}
  2029.   match =0 \
  2030.    =go x, ?s p \{
  2031.    jmp x
  2032.    define ?s 1
  2033.   \}
  2034.   match =0 \
  2035.    =if x, ?s p \{
  2036.    if x
  2037.    define ?s 1
  2038.   \}
  2039.   match =0 \
  2040.    =return x, ?s p \{
  2041.    return x
  2042.    define ?s 1
  2043.   \}
  2044.   match =0 \
  2045.    =return, ?s p \{
  2046.    return
  2047.    define ?s 1
  2048.   \}
  2049.   match =0 \
  2050.    =while x, ?s p \{
  2051.    while x
  2052.    define ?s 1
  2053.   \}
  2054.   match =0 \
  2055.    =forever x, ?s p \{
  2056.    forever x
  2057.    define ?s 1
  2058.   \}
  2059.   match =0 \
  2060.    =loop x, ?s p \{
  2061.    loop x
  2062.    define ?s 1
  2063.   \}
  2064.   match =0 \
  2065.    =end, ?s p \{
  2066.    end
  2067.    define ?s 1
  2068.   \}
  2069.   match =0 \
  2070.    =endw, ?s p \{
  2071.    endw
  2072.    define ?s 1
  2073.   \}
  2074.   match =0 \
  2075.    =endl, ?s p \{
  2076.    endl
  2077.    define ?s 1
  2078.   \}
  2079.   match =0 \
  2080.    =endfv x, ?s p \{
  2081.    endfv
  2082.    define ?s 1
  2083.   \}
  2084.   match =0 \
  2085.    =break, ?s p \{
  2086.    break
  2087.    define ?s 1
  2088.   \}
  2089.   match =0 \
  2090.    =next, ?s p \{
  2091.    next
  2092.    define ?s 1
  2093.   \}
  2094.   IF ?s eq 0
  2095.    let p
  2096.   END IF
  2097. }
  2098.  
  2099. macro . [p] { common let p }
  2100.  
  2101. macro go [p] {
  2102.  common
  2103.   define ?s 0
  2104.   match a=,b, p \{
  2105.    jmp a
  2106.    let b
  2107.    define ?s 1
  2108.   \}
  2109.   match =0, ?s \{ jmp p \}
  2110. }