Loading

stringdata.macro

  1. ; ==============================================================================================================
  2. ;                                                                           __
  3. ;                      _   __        __ __ ______             __   __      / / ____  __ __
  4. ;                    */ | / /__  __ / // // ____/___   _____ / /_ / /_    / / / ___// // /
  5. ;                    /  |/ // / / // // // /_  / __ \ / ___// __// __ \  / / / __ \/ // /_
  6. ;                   / /|  // /_/ // // // __/ / /_/ // /   / /_ / / / / / / / /_/ /__  __/
  7. ;                  /_/ |_/ \__,_//_//_//_/    \____//_/    \__//_/ /_/ / /  \____/  /_/
  8. ;                                                                     /_/
  9. ; --------------------------------------------------------------------------------------------------------------
  10. ; =============================[    Software for the Machines, not for People.   ]==============================
  11. ; --------------------------------------------------------------------------------------------------------------
  12. ;    ___                     __   __       _____              __               __  _             __ ___ __
  13. ;   / _ | ___ ___ ___ __ _  / /  / /_ __  / ___/__  ___  ___ / /_______ ______/ /_(_)__  ___    / //_(_) /_
  14. ;  / __ |(_-<(_-</ -_)  ' \/ _ \/ / // / / /__/ _ \/ _ \(_-</ __/ __/ // / __/ __/ / _ \/ _ \  / ,< / / __/
  15. ; /_/ |_/___/___/\__/_/_/_/_.__/_/\_, /  \___/\___/_//_/___/\__/_/  \_,_/\__/\__/_/\___/_//_/ /_/|_/_/\__/
  16. ;                                /___/
  17. ; ----------------------------------------------------------------------------------------------------------
  18. ; NullForth/64 Subproject: x64 Assembly Construction Kit
  19. ; ----------------------------------------------------------------------------------------------------------
  20. ;   File:       stringdata.macro
  21. ;   Version:    1.0
  22. ;   Purpose:    A pure macro header for common string formats
  23. ;   Dependency: This file is shared between multiple projects
  24. ;   Author:     conscious@nullforth.org
  25. ;   License:    GPL3
  26. ; ---------------------------------------------------------------------------------------------------------------------------------
  27.  
  28. ; Note about produced warnings:
  29. ;   (informative) are benign, just a sign of a poor (or high hack :) coding practice of library user
  30. ;   (not critical) warns about suspect code with certain risk of failure at runtime
  31. ;   (critical) detects logic errors in code, assembly will probably fail later in compile with more cryptic
  32. ;     and strange derived errors
  33.  
  34. ;---{  Initiation  }-------------------------------------------------------------------------------------------
  35.  
  36. %ifdef  ENABLE_FULL_MACRO_LISTING
  37. %define .stringdata_nolist
  38. %else
  39. %define .stringdata_nolist .nolist
  40. %endif
  41.  
  42. %ifndef STRINGDATA_MACRO_INCLUDED
  43. %define STRINGDATA_MACRO_INCLUDED
  44.  
  45. %define PAD_BYTE    0x00
  46. %define FILLER_BYTE 0xFF
  47. %define PAD_WORD    0x0000
  48. %define FILLER_WORD 0xFFFF
  49. %define PAD_DWORD   0x0000_0000
  50. %define FILLER_DWORD    0xFFFF_FFFF
  51. %define PAD_QWORD   0x0000_0000_0000_0000
  52. %define FILLER_QWORD    0xFFFF_FFFF_FFFF_FFFF
  53.  
  54. ; initialized filler, just filling something with something
  55. %macro  STRINGADATA.FILLER  1-2.stringdata_nolist FILLER_BYTE
  56.     times %1 db %2
  57. %endmacro
  58.  
  59. ; pads storage with filler up to nearest quadword align
  60. %macro STRINGDATA.FILLER_UPTO_QUAD  0-1.stringdata_nolist FILLER_BYTE
  61.     align   8,db %1
  62. %endmacro
  63.  
  64. ; switch on/off automatic alignement of data declarations to quadword, a preffered alignment on AMD64 architecture for performance
  65. ; force %undefine in-code to switch off automatic alignment, rarely needed
  66. %define STRINGDATA.AutoAlign    8,db FILLER_BYTE
  67.  
  68. ;---{  Methodology  }------------------------------------------------------------------------------------------
  69.  
  70. ; At compile time, declarators provide some or all of following symbols with this common semantics independent of type,
  71. ; These symbols are intended and encouraged for use in user code for symbolic manipulation.
  72. ; Using this common generic symbolic provides some interchangeability of types during development cycle, without
  73. ;  necessity to change code details or sacrifice optimality, as well as to provide an opportunity for code optimizations.
  74. ; Thus, such string and buffer constants can be effectively handled by macro code generators,
  75. ;  with a special anticipation of automatic constant tables indexers. Welcome to metaprogramming in assembler!
  76. ;  Generally, our structures provide more type safety for programmer than clasic C language and we pursue to evolve this feature
  77. ;  into more advanced metaprogramming facilities implemented in assembler macro language.
  78.  
  79. ; <symbol>      address of a named structure
  80. ; <symbol>.type     an assembler string constant representing a declarator type (meta)
  81. ; <symbol>.class    an assembler string constant representing a declarator's class (meta)
  82. ; <symbol>.alignment    *** not yet *** a storage alignment of declarator, typically 8 for a quadword align
  83. ; <symbol>.length   symbol value of logical string length in BYTEs at compile time (meta)
  84. ; <symbol>.@length  address of a string/buffer length storage in BYTEs, bitsize and location may vary with types
  85. ;           (only if the type can support it in it's logical structure)
  86. ; <symbol>.text     symbolic address of a string data storage, bitsize and location varies
  87. ; <symbol>.data     symbolic address of a block data storage, in quadwords
  88. ; <symbol>.size     symbolic size of a block data storage, in quadwords
  89. ; <symbol>.sizeof   symbol value of a total structure size in storage at compile time, in bytes (meta)
  90. ; <symbol>.qsizeof  symbol value of a total structure size in storage at compile time, in quadwords (meta)
  91. ; <symbol>.Length   instance-defined accessor macro for length value, bound to symbol, for composition in metaprogramming
  92. ; <symbol>.Sizeof   instance-defined accessor macro for size value, bound to symbol, for composition in metaprogramming
  93. ; <symbol>.Qsizeof  instance-defined accessor macro for size value, bound to symbol, for composition in metaprogramming
  94.  
  95. ; While text/length mnemonic is more natural for strings, and data/size mnemonic for buffers, all relevant types
  96. ;  are compatible with each other with some little care. There is not a semantic difference between text and binary data, however
  97. ;  length is expressed in BYTEs, while size is expressed in QWORDs. For the sake of this compatibility, strings are padded with
  98. ;  FILLER to occupy a quad-sized storage to prevent content leak of the storage follower in block operations.
  99. ;  However, a filler is not considered to be part of data structure for byte-sized operations, in our code.
  100. ;  User shall pick a proper {LOD|MOV|STO}S{B|Q} instructions and/or increments pointers by 1 or 8 when handling strings and buffers.
  101. ; Classes should be seen as type class, like in Haskell, not object class, like in C++ (there is no inheritance)
  102. ; Metaprograming tools in macros generate excessive number of symbols in object files tables (just like c++ templates do), so
  103. ;  it is highly recommended to strip binaries after link in elf64 output format.
  104. ;  Of course, a user shall strip properly, if wants to keep debug information or special linkage (kernel, a grub module or so)
  105. ; As for any other NullForth binary data representation, <symbol> and <symbol>.[q]sizeof in source code always semantically
  106. ;  represent a binary fragment, but not it's content, and should not be used for access content directly in assembly,
  107. ;  only for manipulate a whole fragment. However, this mechanics is not enforced by macros.
  108. ; Buffers should be always zero-initialized or padded and this is considered a good practice. Fillers (unused storage padding and
  109. ;  reserved are initialized to hexadecimal FF, to make a distinguished difference for binary dumps and debuggers.
  110. ;  This is also considered a good practice. In block operations performed on quadwords, initial string fillers could be
  111. ;  overwritten or zeroed. This is by design and not considered a bad practice.
  112. ; Unicode: in literal strings, current assembler accepts escape sequence with u\4hexdigits and U\8hexdigits, converts them to UTF8.
  113. ; For UTF16/UCS2, which is a native string data type for NMX (NullForth currently uses ASCII/UTF8 only), we plan to provide
  114. ;  a separate string literal precompiler into binary format suitable for INCBIN assembler pseudoinstruction, as a workaround.
  115. ; Such precompiler will provide cryptographic signatures for static program data as well, that's why we do not pursue
  116. ;  to push more unicode features like better wide char support directly into assembler itself.
  117.  
  118. ;---{  common local macro helpers  }---------------------------------------------------------------------------
  119.  
  120. ; *** %defstr a %assign maji navzajem ruzne vyhody a nevyhody, upravit pozdeji podle zkusenosti se srozumitelnosti
  121. ; nasich kompilacnich chybovych hlaseni, zejmena rozdil kdyz nektery argument je povinne symbol a/nebo string literal
  122.  
  123. ; reports for zero length storage declarator
  124. %macro STRINGDATA.CheckZeroLength 3.stringdata_nolist
  125. %if %3 == 0
  126. ; a declaration with empty data is suspect for wrong declarator usage or possible generator error  
  127.   %defstr %%param1 %1
  128.   %defstr %%param2 %2
  129.   %defstr %%message STRINGDATA: %%param1 %%param2 declared with 0 length storage content (not critical)
  130.   %warning %%message
  131. %endif
  132. %endmacro
  133.  
  134. ; reports for too much literal data
  135. %macro STRINGDATA.CheckReserveLength 4.stringdata_nolist
  136. ; an insufficient buffer is suspicious and cannot receive a complete literal data
  137. %if %4 > %3
  138.   %defstr %%param1 %1
  139.   %defstr %%param2 %2
  140.   %defstr %%message STRINGDATA: %%param1 %%param2 string literal exceeds reserved storage (not critical)
  141.   %warning %%message
  142. %endif
  143. %endmacro
  144.  
  145. ; reports incorrect symbol class membership (possible usage error, wrong type class or so)
  146. %macro STRINGDATA.CheckClass 2.stringdata_nolist
  147. %ifidn %2 "STRINGDATA"
  148. %else
  149.   %defstr %%param1 %1
  150.   %defstr %%message STRINGDATA: %%param1 typed symbol does not belong to class "STRINGDATA" (critical)
  151.   %warning %%message
  152.   ; maybe we should even error here instead of a warning
  153. %endif
  154. %endmacro
  155.  
  156. ;---{  Metaprogramming Applicators }----------------------------------------------------------------------------------------------
  157.  
  158. ; these features are experimental. current implementation still requires a strings to be declared before accessors
  159. ; (string may be put in separate .~data section), otherwise symbolic accessor macros are still undefined at usage time
  160. ; this is a direct consequence of the fact "nasm is not a multipass assembler"
  161. ; slo by to zlepsit, pokud se mi podari odvodit akcesor od celeho typu, nejen od pouheho symbolu jak je to tedka, coz ovsem znamena
  162. ; do vystupniho formatu zavlect relativni relokace, coz zatim asi nechci. anebo rozdelit deklarator na relativni interface
  163. ; a implementaci storage coz uz zacina byt ponekud zbesile. druhe reseni je v budoucnu pravdepodobnejsi
  164.  
  165. ; Historical note: these tricks are modelled after workarounds in flakey ancient c++ templates implementations in late 90'
  166.  
  167. ; accessor LENGTH metaprogramming applicator
  168. %define LENGTH(x) x %+ .Length
  169.  
  170. ; tyhle uz nebudou po zjednoduseni symboliky zapotrebi, ale nechci to ted rozbit
  171. ; SIZEOF metaprogramming applicator
  172. %define SIZEOF(x) x %+ .Sizeof
  173.  
  174. ; QSIZEOF metaprogramming applicator
  175. %define QSIZEOF(x) x %+ .Qsizeof
  176.  
  177. ;---{  SString  }-----------------------------------------------------------------------------------------------------------------
  178.  
  179. ; SString: a static string. has length value as an embedded symbol only, not in storage. Good for constants.
  180. ; Does contain filler padding for the purpose of protection following data in storage from "content leaks" while
  181. ; used in block moves to elsewhere
  182. ; On elf64 binary format, SString shall be put typically in .rodata section, however this is not enforced
  183.  
  184. ; macro parameters:
  185. ; 1: new symbol for a string declaration
  186. ; 2: greedy literal assembly string data
  187.  
  188. %macro  SString 2+.stringdata_nolist
  189. %defstr %1.type "SString"
  190. %defstr %1.class "STRINGDATA"
  191.  
  192. %ifdef STRINGDATA.AutoAlign
  193.     align   STRINGDATA.AutoAlign
  194. %endif
  195.  
  196. %1:
  197. .text:
  198. .data:
  199.     db  %2
  200. .length equ $-%1
  201.     STRINGDATA.CheckZeroLength SString,%1,%1.length
  202. .sizeof equ $-%1        ; sizeof in bytes
  203.     STRINGDATA.FILLER_UPTO_QUAD
  204. .size   equ ($-%1)/8
  205. .qsizeof equ    ($-%1)/8    ; sizeof in quads
  206.  
  207. ; partial instruction producer, a LENGTH(<symbol>) -> value
  208. %assign %1.Length %1.length
  209. ; partial instruction producer, a SIZEOF(<symbol>) -> value
  210. %assign %1.Sizeof %1.sizeof
  211. ; partial instruction producer, a QSIZEOF(<symbol>) -> value
  212. %assign %1.Qsizeof %1.qsizeof
  213.  
  214. %endmacro
  215.  
  216. ; Example:
  217. ;   SString hello,"Hello, world",10
  218. ;   mov rax,QWORD LENGTH(hello) ; emits a mov rax,QWORD 13 instruction
  219.  
  220. ;---{  QString  }----------------------------------------------------------------------------------------------
  221.  
  222. ; Initialized data string with quadword-sized length prefix in storage and filler padding
  223. ; Most preferable dynamic string format in NullForth/64 on AMD64 platform
  224. ; on elf64 binary format, QString shall be put typically in .data or .rodata section, however this is not enforced
  225.  
  226. ; macro parameters:
  227. ; 1: new symbol for a string declaration
  228. ; 2: greedy literal string data
  229.  
  230. %macro QString  2+.stringdata_nolist
  231. %defstr %1.type "QString"
  232. %defstr %1.class "STRINGDATA"
  233.  
  234. %ifdef STRINGDATA.AutoAlign
  235.     align   STRINGDATA.AutoAlign
  236. %endif
  237.  
  238. ; jeste vycistit
  239. %strlen %%length %2
  240.  
  241. %1:
  242. .length equ %%length
  243. .length:
  244.     dq  strict %%length
  245. .text:
  246. .data:
  247.     db  %2
  248. .length.value equ $-%1      ; length of string in bytes
  249.     ;STRINGDATA.CheckZeroLength QString,%1,%%length
  250. .sizeof equ $-%1        ; sizeof in bytes
  251.     ;STRINGDATA.FILLER_UPTO_QUAD
  252. .size   equ ($-%1.data)/8   ; size of data in quads
  253. .qsizeof equ    ($-%1)/8    ; sizeof in quads
  254.  
  255. ; partial instruction producer, a LENGTH(symbol) produces [<symbol>.@lenght] indirect reference
  256. %define %1.Length [%1.length]
  257. ; partial instruction producer, a SIZEOF(<symbol>) -> value
  258. %assign %1.Sizeof %1.sizeof
  259. ; partial instruction producer, a QSIZEOF(<symbol>) -> value
  260. %assign %1.Qsizeof %1.qsizeof
  261.  
  262. %endmacro
  263.  
  264. ; example:
  265. ;   QString another_string,"What's the buzz?",10
  266. ;   ... LENGTH(another_string)  ; produces a [another_string] instruction part (indirect reference), so
  267. ;   mov rax, QWORD LENGTH(another_string) emits a mov rax, QWORD [another_string.@length] instruction
  268.  
  269. ;---{  QStringBuffer  }----------------------------------------------------------------------------------------------
  270.  
  271. ; Zero-initialized buffer with
  272. ;   Q-sized total size prefix (maximum length)
  273. ;   Q-sized current string length prefix, complementary to Qstring
  274. ; on elf64 binary format, QStringBuffer shall be put typically in .data section, this is not _currently_ enforced but may be in
  275. ; future
  276.  
  277. ; macro parameters:
  278. ; 1: new symbol for a string buffer declaration
  279. ; 2: size of the required storage reservation, in bytes. padded up to quadword alignment
  280.  
  281. %macro QStringBuffer    2.stringdata_nolist
  282. %defstr %1.type "QStringBuffer"
  283. %defstr %1.class "STRINGDATA"
  284.  
  285. %ifdef STRINGDATA.AutoAlign
  286.     align   STRINGDATA.AutoAlign
  287. %endif
  288.  
  289. %warning %2
  290. ; compute length, if passed as expression
  291. %assign %%size (%2)/8
  292.  
  293. %warning %%size
  294.  
  295. %1:
  296. .size:
  297.     dq  strict %%length
  298. .QString:   ; symbolic address of an embedded QString-like
  299. .length:
  300.     dq  0
  301. .text:
  302. .data:
  303.     times %%size db 0
  304.     STRINGDATA.CheckZeroLength QStringBuffer,%1,%%size
  305. .sizeof     equ $-%1        ; sizeof in bytes
  306.     ;STRINGDATA.FILLER_UPTO_QUAD
  307. .qsizeof    equ ($-%1)/8    ; sizeof in quads
  308.  
  309. %define %1.Length [%1.length]
  310. %assign %1.Sizeof %1.sizeof
  311. %assign %1.Qsizeof %1.qsizeof
  312.  
  313. %endmacro
  314.  
  315. ; example:
  316. ;   QStringBuffer   target_buffer,1024
  317.  
  318. ;---{  QBlock  }----------------------------------------------------------------------------------------------
  319.  
  320. ; Zero initialized data block with quadword-sized length prefix in storage and filler padding
  321. ; on elf64 binary format, QBlock shall be put typically in .data or .rodata section, however this is not enforced
  322. ; quadword blocks knowing their own sizes can be manipulated efficiently in memory
  323.  
  324. ; macro parameters:
  325. ; 1: new symbol for a block declaration
  326. ; 2: size in quadwords
  327.  
  328. %macro QBlock   2+.stringdata_nolist
  329. %defstr %1.type "QBlock"
  330. %defstr %1.class "STRINGDATA"
  331.  
  332. %ifdef STRINGDATA.AutoAlign
  333.     align   STRINGDATA.AutoAlign
  334. %endif
  335.  
  336. ; compute size, if passed as expression
  337. %assign %%size %2
  338.  
  339. %1:
  340. .size   equ %%size
  341. .@size:
  342.     dq  strict %%size
  343. .data:
  344.     times %2 dq 0
  345.     STRINGDATA.CheckZeroLength QBlock,%1,%%size
  346. .sizeof equ $-%1        ; sizeof in bytes  
  347. .qsizeof equ    ($-%1)/8    ; sizeof in quads
  348.  
  349. ; partial instruction producer, a SIZE(symbol) produces [<symbol>.@size] indirect reference
  350. %define %1.Size [%1.@size]
  351. ; partial instruction producer, a SIZEOF(<symbol>) -> value
  352. %assign %1.Sizeof %1.sizeof
  353. ; partial instruction producer, a QSIZEOF(<symbol>) -> value
  354. %assign %1.Qsizeof %1.qsizeof
  355.  
  356. %endmacro
  357.  
  358. ;---{  SList  }---------------------------------------------------------------------------------------------------------
  359. ; Static List declarator accepts a list of symbols and assembles them into list of respective critical values of those symbols
  360. ; puts null pointer at end, making list suitable for walking with FORALL flow control macro
  361. ; declarator also measures the list items count for metaprogramming
  362. ; list also has a symbolic end, so it can be walked backwards, by it's count
  363.  
  364. ; macro parameters:
  365. ; 1: new symbol for a list declaration
  366. ; 2-*: variable list of symbols
  367.  
  368. %macro SList    2-*.stringdata_nolist
  369.  
  370. %defstr %1.type "SList"
  371. %defstr %1.class "LISTDATA"
  372.  
  373. %ifdef STRINGDATA.AutoAlign
  374.     align   STRINGDATA.AutoAlign
  375. %endif
  376.  
  377. %1:
  378. %assign %%count 0
  379. %rep %0-1
  380.     ; if passed as expression, compute (and force critical)
  381.     %assign %%symbol_value %1
  382.     dq  %%symbol_value
  383.     %assign %%count %%count + 1
  384. %rotate 1
  385. %endrep
  386. .end:   ; end marker as a symbol
  387.     dq  0
  388. .count  equ %%count
  389. %endmacro
  390.  
  391. ;---{  RList  }---------------------------------------------------------------------------------------------------------
  392. ; Relocatable List declarator accepts a list of symbols and assembles them into list of respective reloc values of those symbols
  393. ; puts null pointer at end, making list suitable for walking with FORALL flow control macro
  394. ; declarator also measures the list items count for metaprogramming
  395. ; list also has a symbolic end, so it can be walked backwards, by it's count
  396.  
  397. ; macro parameters:
  398. ; 1: new symbol for a list declaration
  399. ; 2-*: variable list of symbols
  400.  
  401. %macro RList    2-*.stringdata_nolist
  402.  
  403. %defstr %1.type "RList"
  404. %defstr %1.class "LISTDATA"
  405.  
  406. %ifdef STRINGDATA.AutoAlign
  407.     align   STRINGDATA.AutoAlign
  408. %endif
  409.  
  410. %1:
  411. %assign %%count 0
  412. %rep %0-1
  413.     dq  %1
  414.     %assign %%count %%count + 1
  415. %rotate 1
  416. %endrep
  417. .end:   ; list end marker as a symbol
  418.     dq  0
  419. .count  equ %%count
  420. %endmacro
  421.  
  422. ;---{  QPair  }---------------------------------------------------------------------------------------------------------
  423. ; Declares a pair of quadword values. use whenever two quadword values are strongly related. should happen often
  424. ; 1:    symbol
  425. ; 2:    first value
  426. ; 3:    second value
  427. ; 4:    (optional) .subsymbol name of the first pair member synonym
  428. ; 5:    (optional) .subsymbol name of the second pair member synonym
  429.  
  430. %macro  QPair   3-5.stringdata_nolist first second
  431.  
  432. %1:
  433. .first:
  434. %ifnidn %4 first
  435. .%4:
  436. %endif
  437.     dq  %2
  438. .second:
  439. %ifnidn %5 second
  440. .%5:
  441. %endif
  442.     dq  %3
  443.  
  444. .sizeof equ $-%1        ; sizeof in bytes (16)
  445. .qsizeof equ    ($-%1)/8    ; sizeof in quads (2)
  446.  
  447. %endmacro
  448.  
  449. ; value accessors. shall we use some qualifier prefix or not?
  450. %define FIRST(x)    [x]
  451. %define SECOND(x)   [x+8]
  452.  
  453. ;---{  QTriplet  }---------------------------------------------------------------------------------------------------------
  454. ; Declares a triplet of quadword values. use whenever three quadword values are strongly related. should happen sometimes
  455. ; 1:    symbol
  456. ; 2:    first value
  457. ; 3:    second value
  458. ; 4:    third value
  459. ; 4:    (optional) .subsymbol name of the first pair member synonym
  460. ; 5:    (optional) .subsymbol name of the second pair member synonym
  461. ; 6:    (optional) .subsymbol name of the third pair member synonym
  462.  
  463. %macro  QTriplet    3-6.stringdata_nolist first second third
  464.  
  465. %1:
  466. .first:
  467. %ifnidn %4 first
  468. .%4:
  469. %endif
  470.     dq  %2
  471. .second:
  472. %ifnidn %5 second
  473. .%5:
  474. %endif
  475.     dq  %3
  476. .third:
  477. %ifnidn %6 third
  478. .%6:
  479. %endif
  480.     dq  %4
  481.  
  482. .sizeof equ $-%1        ; sizeof in bytes (24)
  483. .qsizeof equ    ($-%1)/8    ; sizeof in quads (3)
  484.  
  485. %endmacro
  486.  
  487. ; yet another value accessor
  488. %define THIRD(x)    [x+16]
  489.  
  490. ;---{  CString  }------------------------------------------------------------------------------------------------------------------
  491.  
  492. ; A deprecated, POSIX C-compatible string, 0 terminated byte characters
  493. ; Using this proofed-unsafe-by-history type is not recommended for using in robust programming, it is only provided
  494. ; for interfacing with ancient foreign code and static usage only is recommended
  495.  
  496. ; macro parameters:
  497. ; 1: symbol for a string declaration
  498. ; 2: greedy string data
  499.  
  500. ; an exception from methodology: a static c-string has no runtime length/size field, but it's value is known at compile time
  501.  
  502. %macro CString  2+.stringdata_nolist
  503.  
  504. %defstr %1.type "CString"
  505. ; Note CString type is not a STRINGDATA class, so cannot by used directly by stringdata operations macros. That's by design.
  506. ; Of course, a user can force that by indirect usage but she express her own will by doing that and takes full responsibility
  507. %defstr %1.class "POSIX"
  508.  
  509. %defstr %1.string   %2
  510. %strlen %1.length   %2
  511.     STRINGDATA.CheckZeroLength Cstring,%1,%1.length
  512.  
  513. %ifdef STRINGDATA.AutoAlign
  514.     align   STRINGDATA.AutoAlign
  515. %endif
  516.  
  517. %1:
  518. .length.value equ %1.length ; a forced terminating 0 is not considered to be part of string in our assembly code
  519. .size.value equ %1.length+1 ; but it IS considered to be part of the structure!!!
  520. .text:
  521. .data:
  522.     db  %2,0    ; always force a terminating 0, even if user provides one
  523. .sizeof equ $-%1
  524.  
  525. %endmacro
  526.  
  527. ; example:
  528. ;   Cstring hello_world,'Hello, world!'
  529.  
  530. ; dirty code fragment:
  531. ; we put it here, for at least printing passed in argv and envp strings via write syscall, we allways need to measure them
  532. ; here is an inline strlen of a posix-compatible CString, a zero terminated byte string
  533. ; input: rdi (string address)
  534. ; returns: rsi (original rdi value), rdx (character count up to 0 byte including), rdi points to after terminal zero
  535. ; scratch: al
  536.  
  537. %macro  cstrlen 0
  538.  
  539.     mov rsi,rdi
  540.     xor al,al
  541.     or  rdi,rdi ; on "normal" valid address, unsets ZF, and also checks for null automagically forcing skip scan
  542.     repnz   scasb
  543.     mov rdx,rdi
  544.     sub rdx,rsi ; null pointer has zero length, while "\0x00" has length 1
  545.     inc rdi ; consider remove that waste, no more purpose for it in examples code
  546.  
  547. %endmacro
  548.  
  549. ; ---------------------------------------------------------------------------------------------------------------------------------
  550.  
  551. %endif  ; STRINGDATA_MACRO_INCLUDED
  552.  
  553. ; end stringdata.macro