167c3a3e4Sopenharmony_ci// (C) Copyright 2016 Jethro G. Beekman
267c3a3e4Sopenharmony_ci//
367c3a3e4Sopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
467c3a3e4Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
567c3a3e4Sopenharmony_ci// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
667c3a3e4Sopenharmony_ci// option. This file may not be copied, modified, or distributed
767c3a3e4Sopenharmony_ci// except according to those terms.
867c3a3e4Sopenharmony_ciextern crate cexpr;
967c3a3e4Sopenharmony_ciextern crate clang_sys;
1067c3a3e4Sopenharmony_ci
1167c3a3e4Sopenharmony_ciuse std::collections::HashMap;
1267c3a3e4Sopenharmony_ciuse std::io::Write;
1367c3a3e4Sopenharmony_ciuse std::str::{self, FromStr};
1467c3a3e4Sopenharmony_ciuse std::{char, ffi, mem, ptr, slice};
1567c3a3e4Sopenharmony_ci
1667c3a3e4Sopenharmony_ciuse cexpr::assert_full_parse;
1767c3a3e4Sopenharmony_ciuse cexpr::expr::{fn_macro_declaration, EvalResult, IdentifierParser};
1867c3a3e4Sopenharmony_ciuse cexpr::literal::CChar;
1967c3a3e4Sopenharmony_ciuse cexpr::token::Token;
2067c3a3e4Sopenharmony_ciuse clang_sys::*;
2167c3a3e4Sopenharmony_ci
2267c3a3e4Sopenharmony_ci// main testing routine
2367c3a3e4Sopenharmony_cifn test_definition(
2467c3a3e4Sopenharmony_ci    ident: Vec<u8>,
2567c3a3e4Sopenharmony_ci    tokens: &[Token],
2667c3a3e4Sopenharmony_ci    idents: &mut HashMap<Vec<u8>, EvalResult>,
2767c3a3e4Sopenharmony_ci) -> bool {
2867c3a3e4Sopenharmony_ci    fn bytes_to_int(value: &[u8]) -> Option<EvalResult> {
2967c3a3e4Sopenharmony_ci        str::from_utf8(value)
3067c3a3e4Sopenharmony_ci            .ok()
3167c3a3e4Sopenharmony_ci            .map(|s| s.replace("n", "-"))
3267c3a3e4Sopenharmony_ci            .map(|s| s.replace("_", ""))
3367c3a3e4Sopenharmony_ci            .and_then(|v| i64::from_str(&v).ok())
3467c3a3e4Sopenharmony_ci            .map(::std::num::Wrapping)
3567c3a3e4Sopenharmony_ci            .map(Int)
3667c3a3e4Sopenharmony_ci    }
3767c3a3e4Sopenharmony_ci
3867c3a3e4Sopenharmony_ci    use cexpr::expr::EvalResult::*;
3967c3a3e4Sopenharmony_ci
4067c3a3e4Sopenharmony_ci    let display_name = String::from_utf8_lossy(&ident).into_owned();
4167c3a3e4Sopenharmony_ci
4267c3a3e4Sopenharmony_ci    let functional;
4367c3a3e4Sopenharmony_ci    let test = {
4467c3a3e4Sopenharmony_ci        // Split name such as Str_test_string into (Str,test_string)
4567c3a3e4Sopenharmony_ci        let pos = ident
4667c3a3e4Sopenharmony_ci            .iter()
4767c3a3e4Sopenharmony_ci            .position(|c| *c == b'_')
4867c3a3e4Sopenharmony_ci            .expect(&format!("Invalid definition in testcase: {}", display_name));
4967c3a3e4Sopenharmony_ci        let mut expected = &ident[..pos];
5067c3a3e4Sopenharmony_ci        let mut value = &ident[(pos + 1)..];
5167c3a3e4Sopenharmony_ci
5267c3a3e4Sopenharmony_ci        functional = expected == b"Fn";
5367c3a3e4Sopenharmony_ci
5467c3a3e4Sopenharmony_ci        if functional {
5567c3a3e4Sopenharmony_ci            let ident = value;
5667c3a3e4Sopenharmony_ci            let pos = ident
5767c3a3e4Sopenharmony_ci                .iter()
5867c3a3e4Sopenharmony_ci                .position(|c| *c == b'_')
5967c3a3e4Sopenharmony_ci                .expect(&format!("Invalid definition in testcase: {}", display_name));
6067c3a3e4Sopenharmony_ci            expected = &ident[..pos];
6167c3a3e4Sopenharmony_ci            value = &ident[(pos + 1)..];
6267c3a3e4Sopenharmony_ci        }
6367c3a3e4Sopenharmony_ci
6467c3a3e4Sopenharmony_ci        if expected == b"Str" {
6567c3a3e4Sopenharmony_ci            let mut splits = value.split(|c| *c == b'U');
6667c3a3e4Sopenharmony_ci            let mut s = Vec::with_capacity(value.len());
6767c3a3e4Sopenharmony_ci            s.extend_from_slice(splits.next().unwrap());
6867c3a3e4Sopenharmony_ci            for split in splits {
6967c3a3e4Sopenharmony_ci                let (chr, rest) = split.split_at(6);
7067c3a3e4Sopenharmony_ci                let chr = u32::from_str_radix(str::from_utf8(chr).unwrap(), 16).unwrap();
7167c3a3e4Sopenharmony_ci                write!(s, "{}", char::from_u32(chr).unwrap()).unwrap();
7267c3a3e4Sopenharmony_ci                s.extend_from_slice(rest);
7367c3a3e4Sopenharmony_ci            }
7467c3a3e4Sopenharmony_ci            Some(Str(s))
7567c3a3e4Sopenharmony_ci        } else if expected == b"Int" {
7667c3a3e4Sopenharmony_ci            bytes_to_int(value)
7767c3a3e4Sopenharmony_ci        } else if expected == b"Float" {
7867c3a3e4Sopenharmony_ci            str::from_utf8(value)
7967c3a3e4Sopenharmony_ci                .ok()
8067c3a3e4Sopenharmony_ci                .map(|s| s.replace("n", "-").replace("p", "."))
8167c3a3e4Sopenharmony_ci                .and_then(|v| f64::from_str(&v).ok())
8267c3a3e4Sopenharmony_ci                .map(Float)
8367c3a3e4Sopenharmony_ci        } else if expected == b"CharRaw" {
8467c3a3e4Sopenharmony_ci            str::from_utf8(value)
8567c3a3e4Sopenharmony_ci                .ok()
8667c3a3e4Sopenharmony_ci                .and_then(|v| u64::from_str(v).ok())
8767c3a3e4Sopenharmony_ci                .map(CChar::Raw)
8867c3a3e4Sopenharmony_ci                .map(Char)
8967c3a3e4Sopenharmony_ci        } else if expected == b"CharChar" {
9067c3a3e4Sopenharmony_ci            str::from_utf8(value)
9167c3a3e4Sopenharmony_ci                .ok()
9267c3a3e4Sopenharmony_ci                .and_then(|v| u32::from_str(v).ok())
9367c3a3e4Sopenharmony_ci                .and_then(char::from_u32)
9467c3a3e4Sopenharmony_ci                .map(CChar::Char)
9567c3a3e4Sopenharmony_ci                .map(Char)
9667c3a3e4Sopenharmony_ci        } else {
9767c3a3e4Sopenharmony_ci            Some(Invalid)
9867c3a3e4Sopenharmony_ci        }
9967c3a3e4Sopenharmony_ci        .expect(&format!("Invalid definition in testcase: {}", display_name))
10067c3a3e4Sopenharmony_ci    };
10167c3a3e4Sopenharmony_ci
10267c3a3e4Sopenharmony_ci    let result = if functional {
10367c3a3e4Sopenharmony_ci        let mut fnidents;
10467c3a3e4Sopenharmony_ci        let expr_tokens;
10567c3a3e4Sopenharmony_ci        match fn_macro_declaration(&tokens) {
10667c3a3e4Sopenharmony_ci            Ok((rest, (_, args))) => {
10767c3a3e4Sopenharmony_ci                fnidents = idents.clone();
10867c3a3e4Sopenharmony_ci                expr_tokens = rest;
10967c3a3e4Sopenharmony_ci                for arg in args {
11067c3a3e4Sopenharmony_ci                    let val = match test {
11167c3a3e4Sopenharmony_ci                        Int(_) => bytes_to_int(&arg),
11267c3a3e4Sopenharmony_ci                        Str(_) => Some(Str(arg.to_owned())),
11367c3a3e4Sopenharmony_ci                        _ => unimplemented!(),
11467c3a3e4Sopenharmony_ci                    }
11567c3a3e4Sopenharmony_ci                    .expect(&format!(
11667c3a3e4Sopenharmony_ci                        "Invalid argument in functional macro testcase: {}",
11767c3a3e4Sopenharmony_ci                        display_name
11867c3a3e4Sopenharmony_ci                    ));
11967c3a3e4Sopenharmony_ci                    fnidents.insert(arg.to_owned(), val);
12067c3a3e4Sopenharmony_ci                }
12167c3a3e4Sopenharmony_ci            }
12267c3a3e4Sopenharmony_ci            e => {
12367c3a3e4Sopenharmony_ci                println!(
12467c3a3e4Sopenharmony_ci                    "Failed test for {}, unable to parse functional macro declaration: {:?}",
12567c3a3e4Sopenharmony_ci                    display_name, e
12667c3a3e4Sopenharmony_ci                );
12767c3a3e4Sopenharmony_ci                return false;
12867c3a3e4Sopenharmony_ci            }
12967c3a3e4Sopenharmony_ci        }
13067c3a3e4Sopenharmony_ci        assert_full_parse(IdentifierParser::new(&fnidents).expr(&expr_tokens))
13167c3a3e4Sopenharmony_ci    } else {
13267c3a3e4Sopenharmony_ci        IdentifierParser::new(idents)
13367c3a3e4Sopenharmony_ci            .macro_definition(&tokens)
13467c3a3e4Sopenharmony_ci            .map(|(i, (_, val))| (i, val))
13567c3a3e4Sopenharmony_ci    };
13667c3a3e4Sopenharmony_ci
13767c3a3e4Sopenharmony_ci    match result {
13867c3a3e4Sopenharmony_ci        Ok((_, val)) => {
13967c3a3e4Sopenharmony_ci            if val == test {
14067c3a3e4Sopenharmony_ci                if let Some(_) = idents.insert(ident, val) {
14167c3a3e4Sopenharmony_ci                    panic!("Duplicate definition for testcase: {}", display_name);
14267c3a3e4Sopenharmony_ci                }
14367c3a3e4Sopenharmony_ci                true
14467c3a3e4Sopenharmony_ci            } else {
14567c3a3e4Sopenharmony_ci                println!(
14667c3a3e4Sopenharmony_ci                    "Failed test for {}, expected {:?}, got {:?}",
14767c3a3e4Sopenharmony_ci                    display_name, test, val
14867c3a3e4Sopenharmony_ci                );
14967c3a3e4Sopenharmony_ci                false
15067c3a3e4Sopenharmony_ci            }
15167c3a3e4Sopenharmony_ci        }
15267c3a3e4Sopenharmony_ci        e => {
15367c3a3e4Sopenharmony_ci            if test == Invalid {
15467c3a3e4Sopenharmony_ci                true
15567c3a3e4Sopenharmony_ci            } else {
15667c3a3e4Sopenharmony_ci                println!(
15767c3a3e4Sopenharmony_ci                    "Failed test for {}, expected {:?}, got {:?}",
15867c3a3e4Sopenharmony_ci                    display_name, test, e
15967c3a3e4Sopenharmony_ci                );
16067c3a3e4Sopenharmony_ci                false
16167c3a3e4Sopenharmony_ci            }
16267c3a3e4Sopenharmony_ci        }
16367c3a3e4Sopenharmony_ci    }
16467c3a3e4Sopenharmony_ci}
16567c3a3e4Sopenharmony_ci
16667c3a3e4Sopenharmony_ci// support code for the clang lexer
16767c3a3e4Sopenharmony_ciunsafe fn clang_str_to_vec(s: CXString) -> Vec<u8> {
16867c3a3e4Sopenharmony_ci    let vec = ffi::CStr::from_ptr(clang_getCString(s))
16967c3a3e4Sopenharmony_ci        .to_bytes()
17067c3a3e4Sopenharmony_ci        .to_owned();
17167c3a3e4Sopenharmony_ci    clang_disposeString(s);
17267c3a3e4Sopenharmony_ci    vec
17367c3a3e4Sopenharmony_ci}
17467c3a3e4Sopenharmony_ci
17567c3a3e4Sopenharmony_ci#[allow(non_upper_case_globals)]
17667c3a3e4Sopenharmony_ciunsafe fn token_clang_to_cexpr(tu: CXTranslationUnit, orig: &CXToken) -> Token {
17767c3a3e4Sopenharmony_ci    Token {
17867c3a3e4Sopenharmony_ci        kind: match clang_getTokenKind(*orig) {
17967c3a3e4Sopenharmony_ci            CXToken_Comment => cexpr::token::Kind::Comment,
18067c3a3e4Sopenharmony_ci            CXToken_Identifier => cexpr::token::Kind::Identifier,
18167c3a3e4Sopenharmony_ci            CXToken_Keyword => cexpr::token::Kind::Keyword,
18267c3a3e4Sopenharmony_ci            CXToken_Literal => cexpr::token::Kind::Literal,
18367c3a3e4Sopenharmony_ci            CXToken_Punctuation => cexpr::token::Kind::Punctuation,
18467c3a3e4Sopenharmony_ci            _ => panic!("invalid token kind: {:?}", *orig),
18567c3a3e4Sopenharmony_ci        },
18667c3a3e4Sopenharmony_ci        raw: clang_str_to_vec(clang_getTokenSpelling(tu, *orig)).into_boxed_slice(),
18767c3a3e4Sopenharmony_ci    }
18867c3a3e4Sopenharmony_ci}
18967c3a3e4Sopenharmony_ci
19067c3a3e4Sopenharmony_ciextern "C" fn visit_children_thunk<F>(
19167c3a3e4Sopenharmony_ci    cur: CXCursor,
19267c3a3e4Sopenharmony_ci    parent: CXCursor,
19367c3a3e4Sopenharmony_ci    closure: CXClientData,
19467c3a3e4Sopenharmony_ci) -> CXChildVisitResult
19567c3a3e4Sopenharmony_ciwhere
19667c3a3e4Sopenharmony_ci    F: FnMut(CXCursor, CXCursor) -> CXChildVisitResult,
19767c3a3e4Sopenharmony_ci{
19867c3a3e4Sopenharmony_ci    unsafe { (&mut *(closure as *mut F))(cur, parent) }
19967c3a3e4Sopenharmony_ci}
20067c3a3e4Sopenharmony_ci
20167c3a3e4Sopenharmony_ciunsafe fn visit_children<F>(cursor: CXCursor, mut f: F)
20267c3a3e4Sopenharmony_ciwhere
20367c3a3e4Sopenharmony_ci    F: FnMut(CXCursor, CXCursor) -> CXChildVisitResult,
20467c3a3e4Sopenharmony_ci{
20567c3a3e4Sopenharmony_ci    clang_visitChildren(
20667c3a3e4Sopenharmony_ci        cursor,
20767c3a3e4Sopenharmony_ci        visit_children_thunk::<F> as _,
20867c3a3e4Sopenharmony_ci        &mut f as *mut F as CXClientData,
20967c3a3e4Sopenharmony_ci    );
21067c3a3e4Sopenharmony_ci}
21167c3a3e4Sopenharmony_ci
21267c3a3e4Sopenharmony_ciunsafe fn location_in_scope(r: CXSourceRange) -> bool {
21367c3a3e4Sopenharmony_ci    let start = clang_getRangeStart(r);
21467c3a3e4Sopenharmony_ci    let mut file = ptr::null_mut();
21567c3a3e4Sopenharmony_ci    clang_getSpellingLocation(
21667c3a3e4Sopenharmony_ci        start,
21767c3a3e4Sopenharmony_ci        &mut file,
21867c3a3e4Sopenharmony_ci        ptr::null_mut(),
21967c3a3e4Sopenharmony_ci        ptr::null_mut(),
22067c3a3e4Sopenharmony_ci        ptr::null_mut(),
22167c3a3e4Sopenharmony_ci    );
22267c3a3e4Sopenharmony_ci    clang_Location_isFromMainFile(start) != 0
22367c3a3e4Sopenharmony_ci        && clang_Location_isInSystemHeader(start) == 0
22467c3a3e4Sopenharmony_ci        && file != ptr::null_mut()
22567c3a3e4Sopenharmony_ci}
22667c3a3e4Sopenharmony_ci
22767c3a3e4Sopenharmony_ci/// tokenize_range_adjust can be used to work around LLVM bug 9069
22867c3a3e4Sopenharmony_ci/// https://bugs.llvm.org//show_bug.cgi?id=9069
22967c3a3e4Sopenharmony_cifn file_visit_macros<F: FnMut(Vec<u8>, Vec<Token>)>(
23067c3a3e4Sopenharmony_ci    file: &str,
23167c3a3e4Sopenharmony_ci    tokenize_range_adjust: bool,
23267c3a3e4Sopenharmony_ci    mut visitor: F,
23367c3a3e4Sopenharmony_ci) {
23467c3a3e4Sopenharmony_ci    unsafe {
23567c3a3e4Sopenharmony_ci        let tu = {
23667c3a3e4Sopenharmony_ci            let index = clang_createIndex(true as _, false as _);
23767c3a3e4Sopenharmony_ci            let cfile = ffi::CString::new(file).unwrap();
23867c3a3e4Sopenharmony_ci            let mut tu = mem::MaybeUninit::uninit();
23967c3a3e4Sopenharmony_ci            assert!(
24067c3a3e4Sopenharmony_ci                clang_parseTranslationUnit2(
24167c3a3e4Sopenharmony_ci                    index,
24267c3a3e4Sopenharmony_ci                    cfile.as_ptr(),
24367c3a3e4Sopenharmony_ci                    [b"-std=c11\0".as_ptr() as *const ::std::os::raw::c_char].as_ptr(),
24467c3a3e4Sopenharmony_ci                    1,
24567c3a3e4Sopenharmony_ci                    ptr::null_mut(),
24667c3a3e4Sopenharmony_ci                    0,
24767c3a3e4Sopenharmony_ci                    CXTranslationUnit_DetailedPreprocessingRecord,
24867c3a3e4Sopenharmony_ci                    &mut *tu.as_mut_ptr()
24967c3a3e4Sopenharmony_ci                ) == CXError_Success,
25067c3a3e4Sopenharmony_ci                "Failure reading test case {}",
25167c3a3e4Sopenharmony_ci                file
25267c3a3e4Sopenharmony_ci            );
25367c3a3e4Sopenharmony_ci            tu.assume_init()
25467c3a3e4Sopenharmony_ci        };
25567c3a3e4Sopenharmony_ci        visit_children(clang_getTranslationUnitCursor(tu), |cur, _parent| {
25667c3a3e4Sopenharmony_ci            if cur.kind == CXCursor_MacroDefinition {
25767c3a3e4Sopenharmony_ci                let mut range = clang_getCursorExtent(cur);
25867c3a3e4Sopenharmony_ci                if !location_in_scope(range) {
25967c3a3e4Sopenharmony_ci                    return CXChildVisit_Continue;
26067c3a3e4Sopenharmony_ci                }
26167c3a3e4Sopenharmony_ci                range.end_int_data -= if tokenize_range_adjust { 1 } else { 0 };
26267c3a3e4Sopenharmony_ci                let mut token_ptr = ptr::null_mut();
26367c3a3e4Sopenharmony_ci                let mut num = 0;
26467c3a3e4Sopenharmony_ci                clang_tokenize(tu, range, &mut token_ptr, &mut num);
26567c3a3e4Sopenharmony_ci                if token_ptr != ptr::null_mut() {
26667c3a3e4Sopenharmony_ci                    let tokens = slice::from_raw_parts(token_ptr, num as usize);
26767c3a3e4Sopenharmony_ci                    let tokens: Vec<_> = tokens
26867c3a3e4Sopenharmony_ci                        .iter()
26967c3a3e4Sopenharmony_ci                        .filter_map(|t| {
27067c3a3e4Sopenharmony_ci                            if clang_getTokenKind(*t) != CXToken_Comment {
27167c3a3e4Sopenharmony_ci                                Some(token_clang_to_cexpr(tu, t))
27267c3a3e4Sopenharmony_ci                            } else {
27367c3a3e4Sopenharmony_ci                                None
27467c3a3e4Sopenharmony_ci                            }
27567c3a3e4Sopenharmony_ci                        })
27667c3a3e4Sopenharmony_ci                        .collect();
27767c3a3e4Sopenharmony_ci                    clang_disposeTokens(tu, token_ptr, num);
27867c3a3e4Sopenharmony_ci                    visitor(clang_str_to_vec(clang_getCursorSpelling(cur)), tokens)
27967c3a3e4Sopenharmony_ci                }
28067c3a3e4Sopenharmony_ci            }
28167c3a3e4Sopenharmony_ci            CXChildVisit_Continue
28267c3a3e4Sopenharmony_ci        });
28367c3a3e4Sopenharmony_ci        clang_disposeTranslationUnit(tu);
28467c3a3e4Sopenharmony_ci    };
28567c3a3e4Sopenharmony_ci}
28667c3a3e4Sopenharmony_ci
28767c3a3e4Sopenharmony_cifn test_file(file: &str) -> bool {
28867c3a3e4Sopenharmony_ci    let mut idents = HashMap::new();
28967c3a3e4Sopenharmony_ci    let mut all_succeeded = true;
29067c3a3e4Sopenharmony_ci    file_visit_macros(file, fix_bug_9069(), |ident, tokens| {
29167c3a3e4Sopenharmony_ci        all_succeeded &= test_definition(ident, &tokens, &mut idents)
29267c3a3e4Sopenharmony_ci    });
29367c3a3e4Sopenharmony_ci    all_succeeded
29467c3a3e4Sopenharmony_ci}
29567c3a3e4Sopenharmony_ci
29667c3a3e4Sopenharmony_cifn fix_bug_9069() -> bool {
29767c3a3e4Sopenharmony_ci    fn check_bug_9069() -> bool {
29867c3a3e4Sopenharmony_ci        let mut token_sets = vec![];
29967c3a3e4Sopenharmony_ci        file_visit_macros(
30067c3a3e4Sopenharmony_ci            "tests/input/test_llvm_bug_9069.h",
30167c3a3e4Sopenharmony_ci            false,
30267c3a3e4Sopenharmony_ci            |ident, tokens| {
30367c3a3e4Sopenharmony_ci                assert_eq!(&ident, b"A");
30467c3a3e4Sopenharmony_ci                token_sets.push(tokens);
30567c3a3e4Sopenharmony_ci            },
30667c3a3e4Sopenharmony_ci        );
30767c3a3e4Sopenharmony_ci        assert_eq!(token_sets.len(), 2);
30867c3a3e4Sopenharmony_ci        token_sets[0] != token_sets[1]
30967c3a3e4Sopenharmony_ci    }
31067c3a3e4Sopenharmony_ci
31167c3a3e4Sopenharmony_ci    use std::sync::atomic::{AtomicBool, Ordering};
31267c3a3e4Sopenharmony_ci    use std::sync::Once;
31367c3a3e4Sopenharmony_ci
31467c3a3e4Sopenharmony_ci    static CHECK_FIX: Once = Once::new();
31567c3a3e4Sopenharmony_ci    static FIX: AtomicBool = AtomicBool::new(false);
31667c3a3e4Sopenharmony_ci
31767c3a3e4Sopenharmony_ci    CHECK_FIX.call_once(|| FIX.store(check_bug_9069(), Ordering::SeqCst));
31867c3a3e4Sopenharmony_ci
31967c3a3e4Sopenharmony_ci    FIX.load(Ordering::SeqCst)
32067c3a3e4Sopenharmony_ci}
32167c3a3e4Sopenharmony_ci
32267c3a3e4Sopenharmony_cimacro_rules! test_file {
32367c3a3e4Sopenharmony_ci    ($f:ident) => {
32467c3a3e4Sopenharmony_ci        #[test]
32567c3a3e4Sopenharmony_ci        fn $f() {
32667c3a3e4Sopenharmony_ci            assert!(
32767c3a3e4Sopenharmony_ci                test_file(concat!("tests/input/", stringify!($f), ".h")),
32867c3a3e4Sopenharmony_ci                "test_file"
32967c3a3e4Sopenharmony_ci            )
33067c3a3e4Sopenharmony_ci        }
33167c3a3e4Sopenharmony_ci    };
33267c3a3e4Sopenharmony_ci}
33367c3a3e4Sopenharmony_ci
33467c3a3e4Sopenharmony_citest_file!(floats);
33567c3a3e4Sopenharmony_citest_file!(chars);
33667c3a3e4Sopenharmony_citest_file!(strings);
33767c3a3e4Sopenharmony_citest_file!(int_signed);
33867c3a3e4Sopenharmony_citest_file!(int_unsigned);
33967c3a3e4Sopenharmony_citest_file!(fail);
340