1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#![feature(asm)] #[macro_export] macro_rules! releasetag { // The argument of releasetag!() must be a byte-string (array) of 8bit elements, // instead of unicode string. The release-tag may be a byte-string of any size. In case the // the release-tag has byte-length of 126, the occupied stack-size would be 128 bytes, // adding leading and trailing null-characters. // // The feature is restricted to byte-strings as unicode strings might contain // non-printable characters causing 'strings' command line tool to print fragments of // tag only (causing loss of information) ($tag:expr) => {{ // CAPACITY incl leading and trailing \0 (+2) const CAPACITY : usize = byte_size_of!($tag) + 2; // const data will not be on stack, add leading and trailing null-char \0 const CONST_DATA : & 'static [u8; CAPACITY] = concat_bytes!([0u8],$tag,[0u8]); // local array on stack, must be declared as 'mut', otherwise would // be optimized out by compiler let mut stacktag : & mut [u8; CAPACITY] = & mut [0u8; CAPACITY]; // TODO: find a memcpy expression where compiler would verify matching array sizes. // Using clone_from_slice will check array-boundaries during runtime. stacktag[..CAPACITY].clone_from_slice(CONST_DATA); // nop to force linker to preserve the variable on stack unsafe { asm!("" : : "r"(&stacktag)) } }}; } #[cfg(test)] mod tests { // just testing syntax from within, please use test/run_test.sh which is // starting a small application. The script will cause the appl. to core-dump with // signal 6 and parse the core file for releasetag strings. If the tags can not be found // in the core file the feature did fail. #[test] fn valid_macro() { releasetag!(b"TAG1=123"); releasetag!(b"TAG2=ABC"); } }