forked from mirrors/gecko-dev
		
	 0a80ad4a85
			
		
	
	
		0a80ad4a85
		
	
	
	
	
		
			
			This updates binjs_meta and thus weedle, bindgen and thus clang-sys transitively, and the mime / mime_guess crate and thus unicase and version-check. Differential Revision: https://phabricator.services.mozilla.com/D66282 --HG-- rename : third_party/rust/lmdb-rkv-sys/tests/fixtures/testdb/lock.mdb => third_party/rust/lmdb-rkv-sys/tests/fixtures/testdb-32/lock.mdb rename : third_party/rust/mime_guess/Cargo.lock => third_party/rust/nom/Cargo.lock rename : third_party/rust/nom/src/branch.rs => third_party/rust/nom/src/branch/macros.rs rename : third_party/rust/nom/src/sequence.rs => third_party/rust/nom/src/sequence/macros.rs rename : third_party/rust/rkv-0.10.2/.cargo-checksum.json => third_party/rust/rkv-0.10.4/.cargo-checksum.json rename : third_party/rust/rkv-0.10.2/CODE_OF_CONDUCT.md => third_party/rust/rkv-0.10.4/CODE_OF_CONDUCT.md rename : third_party/rust/rkv-0.10.2/Cargo.toml => third_party/rust/rkv-0.10.4/Cargo.toml rename : third_party/rust/rkv-0.10.2/LICENSE => third_party/rust/rkv-0.10.4/LICENSE rename : third_party/rust/rkv-0.10.2/examples/README.md => third_party/rust/rkv-0.10.4/examples/README.md rename : third_party/rust/rkv-0.10.2/examples/iterator.rs => third_party/rust/rkv-0.10.4/examples/iterator.rs rename : third_party/rust/rkv-0.10.2/examples/simple-store.rs => third_party/rust/rkv-0.10.4/examples/simple-store.rs rename : third_party/rust/rkv-0.10.2/run-all-examples.sh => third_party/rust/rkv-0.10.4/run-all-examples.sh rename : third_party/rust/rkv-0.10.2/src/bin/dump.rs => third_party/rust/rkv-0.10.4/src/bin/dump.rs rename : third_party/rust/rkv-0.10.2/src/bin/rand.rs => third_party/rust/rkv-0.10.4/src/bin/rand.rs rename : third_party/rust/rkv-0.10.2/src/env.rs => third_party/rust/rkv-0.10.4/src/env.rs rename : third_party/rust/rkv-0.10.2/src/error.rs => third_party/rust/rkv-0.10.4/src/error.rs rename : third_party/rust/rkv-0.10.2/src/lib.rs => third_party/rust/rkv-0.10.4/src/lib.rs rename : third_party/rust/rkv-0.10.2/src/manager.rs => third_party/rust/rkv-0.10.4/src/manager.rs rename : third_party/rust/rkv-0.10.2/src/migrate.rs => third_party/rust/rkv-0.10.4/src/migrate.rs rename : third_party/rust/rkv-0.10.2/src/readwrite.rs => third_party/rust/rkv-0.10.4/src/readwrite.rs rename : third_party/rust/rkv-0.10.2/src/store.rs => third_party/rust/rkv-0.10.4/src/store.rs rename : third_party/rust/rkv-0.10.2/src/store/integer.rs => third_party/rust/rkv-0.10.4/src/store/integer.rs rename : third_party/rust/rkv-0.10.2/src/store/integermulti.rs => third_party/rust/rkv-0.10.4/src/store/integermulti.rs rename : third_party/rust/rkv-0.10.2/src/store/multi.rs => third_party/rust/rkv-0.10.4/src/store/multi.rs rename : third_party/rust/rkv-0.10.2/src/store/single.rs => third_party/rust/rkv-0.10.4/src/store/single.rs rename : third_party/rust/rkv-0.10.2/src/value.rs => third_party/rust/rkv-0.10.4/src/value.rs rename : third_party/rust/rkv-0.10.2/tests/integer-store.rs => third_party/rust/rkv-0.10.4/tests/integer-store.rs rename : third_party/rust/rkv-0.10.2/tests/manager.rs => third_party/rust/rkv-0.10.4/tests/manager.rs rename : third_party/rust/rkv-0.10.2/tests/multi-integer-store.rs => third_party/rust/rkv-0.10.4/tests/multi-integer-store.rs rename : third_party/rust/rkv-0.10.2/tests/test_txn.rs => third_party/rust/rkv-0.10.4/tests/test_txn.rs extra : moz-landing-system : lando
		
			
				
	
	
		
			339 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			339 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| // (C) Copyright 2016 Jethro G. Beekman
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 | |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 | |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 | |
| // option. This file may not be copied, modified, or distributed
 | |
| // except according to those terms.
 | |
| extern crate cexpr;
 | |
| extern crate clang_sys;
 | |
| 
 | |
| use std::collections::HashMap;
 | |
| use std::io::Write;
 | |
| use std::str::{self, FromStr};
 | |
| use std::{char, ffi, mem, ptr, slice};
 | |
| 
 | |
| use cexpr::assert_full_parse;
 | |
| use cexpr::expr::{fn_macro_declaration, EvalResult, IdentifierParser};
 | |
| use cexpr::literal::CChar;
 | |
| use cexpr::token::Token;
 | |
| use clang_sys::*;
 | |
| 
 | |
| // main testing routine
 | |
| fn test_definition(
 | |
|     ident: Vec<u8>,
 | |
|     tokens: &[Token],
 | |
|     idents: &mut HashMap<Vec<u8>, EvalResult>,
 | |
| ) -> bool {
 | |
|     fn bytes_to_int(value: &[u8]) -> Option<EvalResult> {
 | |
|         str::from_utf8(value)
 | |
|             .ok()
 | |
|             .map(|s| s.replace("n", "-"))
 | |
|             .map(|s| s.replace("_", ""))
 | |
|             .and_then(|v| i64::from_str(&v).ok())
 | |
|             .map(::std::num::Wrapping)
 | |
|             .map(Int)
 | |
|     }
 | |
| 
 | |
|     use cexpr::expr::EvalResult::*;
 | |
| 
 | |
|     let display_name = String::from_utf8_lossy(&ident).into_owned();
 | |
| 
 | |
|     let functional;
 | |
|     let test = {
 | |
|         // Split name such as Str_test_string into (Str,test_string)
 | |
|         let pos = ident
 | |
|             .iter()
 | |
|             .position(|c| *c == b'_')
 | |
|             .expect(&format!("Invalid definition in testcase: {}", display_name));
 | |
|         let mut expected = &ident[..pos];
 | |
|         let mut value = &ident[(pos + 1)..];
 | |
| 
 | |
|         functional = expected == b"Fn";
 | |
| 
 | |
|         if functional {
 | |
|             let ident = value;
 | |
|             let pos = ident
 | |
|                 .iter()
 | |
|                 .position(|c| *c == b'_')
 | |
|                 .expect(&format!("Invalid definition in testcase: {}", display_name));
 | |
|             expected = &ident[..pos];
 | |
|             value = &ident[(pos + 1)..];
 | |
|         }
 | |
| 
 | |
|         if expected == b"Str" {
 | |
|             let mut splits = value.split(|c| *c == b'U');
 | |
|             let mut s = Vec::with_capacity(value.len());
 | |
|             s.extend_from_slice(splits.next().unwrap());
 | |
|             for split in splits {
 | |
|                 let (chr, rest) = split.split_at(6);
 | |
|                 let chr = u32::from_str_radix(str::from_utf8(chr).unwrap(), 16).unwrap();
 | |
|                 write!(s, "{}", char::from_u32(chr).unwrap()).unwrap();
 | |
|                 s.extend_from_slice(rest);
 | |
|             }
 | |
|             Some(Str(s))
 | |
|         } else if expected == b"Int" {
 | |
|             bytes_to_int(value)
 | |
|         } else if expected == b"Float" {
 | |
|             str::from_utf8(value)
 | |
|                 .ok()
 | |
|                 .map(|s| s.replace("n", "-").replace("p", "."))
 | |
|                 .and_then(|v| f64::from_str(&v).ok())
 | |
|                 .map(Float)
 | |
|         } else if expected == b"CharRaw" {
 | |
|             str::from_utf8(value)
 | |
|                 .ok()
 | |
|                 .and_then(|v| u64::from_str(v).ok())
 | |
|                 .map(CChar::Raw)
 | |
|                 .map(Char)
 | |
|         } else if expected == b"CharChar" {
 | |
|             str::from_utf8(value)
 | |
|                 .ok()
 | |
|                 .and_then(|v| u32::from_str(v).ok())
 | |
|                 .and_then(char::from_u32)
 | |
|                 .map(CChar::Char)
 | |
|                 .map(Char)
 | |
|         } else {
 | |
|             Some(Invalid)
 | |
|         }
 | |
|         .expect(&format!("Invalid definition in testcase: {}", display_name))
 | |
|     };
 | |
| 
 | |
|     let result = if functional {
 | |
|         let mut fnidents;
 | |
|         let expr_tokens;
 | |
|         match fn_macro_declaration(&tokens) {
 | |
|             Ok((rest, (_, args))) => {
 | |
|                 fnidents = idents.clone();
 | |
|                 expr_tokens = rest;
 | |
|                 for arg in args {
 | |
|                     let val = match test {
 | |
|                         Int(_) => bytes_to_int(&arg),
 | |
|                         Str(_) => Some(Str(arg.to_owned())),
 | |
|                         _ => unimplemented!(),
 | |
|                     }
 | |
|                     .expect(&format!(
 | |
|                         "Invalid argument in functional macro testcase: {}",
 | |
|                         display_name
 | |
|                     ));
 | |
|                     fnidents.insert(arg.to_owned(), val);
 | |
|                 }
 | |
|             }
 | |
|             e => {
 | |
|                 println!(
 | |
|                     "Failed test for {}, unable to parse functional macro declaration: {:?}",
 | |
|                     display_name, e
 | |
|                 );
 | |
|                 return false;
 | |
|             }
 | |
|         }
 | |
|         assert_full_parse(IdentifierParser::new(&fnidents).expr(&expr_tokens))
 | |
|     } else {
 | |
|         IdentifierParser::new(idents)
 | |
|             .macro_definition(&tokens)
 | |
|             .map(|(i, (_, val))| (i, val))
 | |
|     };
 | |
| 
 | |
|     match result {
 | |
|         Ok((_, val)) => {
 | |
|             if val == test {
 | |
|                 if let Some(_) = idents.insert(ident, val) {
 | |
|                     panic!("Duplicate definition for testcase: {}", display_name);
 | |
|                 }
 | |
|                 true
 | |
|             } else {
 | |
|                 println!(
 | |
|                     "Failed test for {}, expected {:?}, got {:?}",
 | |
|                     display_name, test, val
 | |
|                 );
 | |
|                 false
 | |
|             }
 | |
|         }
 | |
|         e => {
 | |
|             if test == Invalid {
 | |
|                 true
 | |
|             } else {
 | |
|                 println!(
 | |
|                     "Failed test for {}, expected {:?}, got {:?}",
 | |
|                     display_name, test, e
 | |
|                 );
 | |
|                 false
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| // support code for the clang lexer
 | |
| unsafe fn clang_str_to_vec(s: CXString) -> Vec<u8> {
 | |
|     let vec = ffi::CStr::from_ptr(clang_getCString(s))
 | |
|         .to_bytes()
 | |
|         .to_owned();
 | |
|     clang_disposeString(s);
 | |
|     vec
 | |
| }
 | |
| 
 | |
| #[allow(non_upper_case_globals)]
 | |
| unsafe fn token_clang_to_cexpr(tu: CXTranslationUnit, orig: &CXToken) -> Token {
 | |
|     Token {
 | |
|         kind: match clang_getTokenKind(*orig) {
 | |
|             CXToken_Comment => cexpr::token::Kind::Comment,
 | |
|             CXToken_Identifier => cexpr::token::Kind::Identifier,
 | |
|             CXToken_Keyword => cexpr::token::Kind::Keyword,
 | |
|             CXToken_Literal => cexpr::token::Kind::Literal,
 | |
|             CXToken_Punctuation => cexpr::token::Kind::Punctuation,
 | |
|             _ => panic!("invalid token kind: {:?}", *orig),
 | |
|         },
 | |
|         raw: clang_str_to_vec(clang_getTokenSpelling(tu, *orig)).into_boxed_slice(),
 | |
|     }
 | |
| }
 | |
| 
 | |
| extern "C" fn visit_children_thunk<F>(
 | |
|     cur: CXCursor,
 | |
|     parent: CXCursor,
 | |
|     closure: CXClientData,
 | |
| ) -> CXChildVisitResult
 | |
| where
 | |
|     F: FnMut(CXCursor, CXCursor) -> CXChildVisitResult,
 | |
| {
 | |
|     unsafe { (&mut *(closure as *mut F))(cur, parent) }
 | |
| }
 | |
| 
 | |
| unsafe fn visit_children<F>(cursor: CXCursor, mut f: F)
 | |
| where
 | |
|     F: FnMut(CXCursor, CXCursor) -> CXChildVisitResult,
 | |
| {
 | |
|     clang_visitChildren(
 | |
|         cursor,
 | |
|         visit_children_thunk::<F> as _,
 | |
|         &mut f as *mut F as CXClientData,
 | |
|     );
 | |
| }
 | |
| 
 | |
| unsafe fn location_in_scope(r: CXSourceRange) -> bool {
 | |
|     let start = clang_getRangeStart(r);
 | |
|     let mut file = ptr::null_mut();
 | |
|     clang_getSpellingLocation(
 | |
|         start,
 | |
|         &mut file,
 | |
|         ptr::null_mut(),
 | |
|         ptr::null_mut(),
 | |
|         ptr::null_mut(),
 | |
|     );
 | |
|     clang_Location_isFromMainFile(start) != 0
 | |
|         && clang_Location_isInSystemHeader(start) == 0
 | |
|         && file != ptr::null_mut()
 | |
| }
 | |
| 
 | |
| /// tokenize_range_adjust can be used to work around LLVM bug 9069
 | |
| /// https://bugs.llvm.org//show_bug.cgi?id=9069
 | |
| fn file_visit_macros<F: FnMut(Vec<u8>, Vec<Token>)>(
 | |
|     file: &str,
 | |
|     tokenize_range_adjust: bool,
 | |
|     mut visitor: F,
 | |
| ) {
 | |
|     unsafe {
 | |
|         let tu = {
 | |
|             let index = clang_createIndex(true as _, false as _);
 | |
|             let cfile = ffi::CString::new(file).unwrap();
 | |
|             let mut tu = mem::MaybeUninit::uninit();
 | |
|             assert!(
 | |
|                 clang_parseTranslationUnit2(
 | |
|                     index,
 | |
|                     cfile.as_ptr(),
 | |
|                     [b"-std=c11\0".as_ptr() as *const ::std::os::raw::c_char].as_ptr(),
 | |
|                     1,
 | |
|                     ptr::null_mut(),
 | |
|                     0,
 | |
|                     CXTranslationUnit_DetailedPreprocessingRecord,
 | |
|                     &mut *tu.as_mut_ptr()
 | |
|                 ) == CXError_Success,
 | |
|                 "Failure reading test case {}",
 | |
|                 file
 | |
|             );
 | |
|             tu.assume_init()
 | |
|         };
 | |
|         visit_children(clang_getTranslationUnitCursor(tu), |cur, _parent| {
 | |
|             if cur.kind == CXCursor_MacroDefinition {
 | |
|                 let mut range = clang_getCursorExtent(cur);
 | |
|                 if !location_in_scope(range) {
 | |
|                     return CXChildVisit_Continue;
 | |
|                 }
 | |
|                 range.end_int_data -= if tokenize_range_adjust { 1 } else { 0 };
 | |
|                 let mut token_ptr = ptr::null_mut();
 | |
|                 let mut num = 0;
 | |
|                 clang_tokenize(tu, range, &mut token_ptr, &mut num);
 | |
|                 if token_ptr != ptr::null_mut() {
 | |
|                     let tokens = slice::from_raw_parts(token_ptr, num as usize);
 | |
|                     let tokens: Vec<_> = tokens
 | |
|                         .iter()
 | |
|                         .filter_map(|t| {
 | |
|                             if clang_getTokenKind(*t) != CXToken_Comment {
 | |
|                                 Some(token_clang_to_cexpr(tu, t))
 | |
|                             } else {
 | |
|                                 None
 | |
|                             }
 | |
|                         })
 | |
|                         .collect();
 | |
|                     clang_disposeTokens(tu, token_ptr, num);
 | |
|                     visitor(clang_str_to_vec(clang_getCursorSpelling(cur)), tokens)
 | |
|                 }
 | |
|             }
 | |
|             CXChildVisit_Continue
 | |
|         });
 | |
|         clang_disposeTranslationUnit(tu);
 | |
|     };
 | |
| }
 | |
| 
 | |
| fn test_file(file: &str) -> bool {
 | |
|     let mut idents = HashMap::new();
 | |
|     let mut all_succeeded = true;
 | |
|     file_visit_macros(file, fix_bug_9069(), |ident, tokens| {
 | |
|         all_succeeded &= test_definition(ident, &tokens, &mut idents)
 | |
|     });
 | |
|     all_succeeded
 | |
| }
 | |
| 
 | |
| fn fix_bug_9069() -> bool {
 | |
|     fn check_bug_9069() -> bool {
 | |
|         let mut token_sets = vec![];
 | |
|         file_visit_macros(
 | |
|             "tests/input/test_llvm_bug_9069.h",
 | |
|             false,
 | |
|             |ident, tokens| {
 | |
|                 assert_eq!(&ident, b"A");
 | |
|                 token_sets.push(tokens);
 | |
|             },
 | |
|         );
 | |
|         assert_eq!(token_sets.len(), 2);
 | |
|         token_sets[0] != token_sets[1]
 | |
|     }
 | |
| 
 | |
|     use std::sync::atomic::{AtomicBool, Ordering};
 | |
|     use std::sync::Once;
 | |
| 
 | |
|     static CHECK_FIX: Once = Once::new();
 | |
|     static FIX: AtomicBool = AtomicBool::new(false);
 | |
| 
 | |
|     CHECK_FIX.call_once(|| FIX.store(check_bug_9069(), Ordering::SeqCst));
 | |
| 
 | |
|     FIX.load(Ordering::SeqCst)
 | |
| }
 | |
| 
 | |
| macro_rules! test_file {
 | |
|     ($f:ident) => {
 | |
|         #[test]
 | |
|         fn $f() {
 | |
|             assert!(
 | |
|                 test_file(concat!("tests/input/", stringify!($f), ".h")),
 | |
|                 "test_file"
 | |
|             )
 | |
|         }
 | |
|     };
 | |
| }
 | |
| 
 | |
| test_file!(floats);
 | |
| test_file!(chars);
 | |
| test_file!(strings);
 | |
| test_file!(int_signed);
 | |
| test_file!(int_unsigned);
 | |
| test_file!(fail);
 |