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
46
47
48
49
#[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 120, the occupied stack-size would be 125 bytes on
    // 32bit arch (or 129 bytes on 64bit architecture) adding leading and trailing null-characters.
    //   
    // The feature is restricted to byte-strings as unicode strings might contain 
    // non-printable characters causing the command line tool 'strings'  to print fragments of
    // tag only (causing loss of information)
    // 
    // Thanks to Japaric's help, this crate no longer depends on nightly features.
    ($tag:expr) => {
        let _tag = {
            // Prevent reordering of struct-members
            #[repr(C)]
            struct EmbeddedOctetBuf<T> {
                pad0 : usize, // Leading '\0' using default integer alignment
                data : T,     // User defined array or static string
                pad1 : u8,    // Trailing '\0' consecutive to array
            }

            // Define stacktag, with leading (and aligned) 0 and trailing \0, fencing the string.
            let stacktag = EmbeddedOctetBuf{pad0: 0, data : *$tag, pad1: 0x0u8};

            stacktag
        };
        // "Volatile" will prevent compiler from
        // * optimizing the unused value out
        // * turning the stack value into a static value
        let _myref = unsafe { std::ptr::read_volatile(&&_tag); };
    }
}

#[cfg(test)]
mod tests {
    // just testing syntax from within lib, 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() {
        #[allow(dead_code)]
        releasetag!(b"TAG1=123");
        releasetag!(b"TAG2=ABC");
        releasetag!(&[0x42u8, 0x55u8, 0x49u8, 0x4cu8, 0x44u8, 0x5fu8]); // "BUILD_"
    }
}