library(tidyverse)
library(countrycode)
library(states)
library(WDI)
library(haven)
library(readxl)
library(naniar)
library(lubridate)
library(scales)
library(xml2)
library(httr)
library(rvest)
library(DT)
library(pander)
library(here)

Load raw data

# V-Dem
vdem_raw <- read_rds(here("data", "raw_data", "Country_Year_V-Dem_Full+others_R_v10",
                         "V-Dem-CY-Full+Others-v10.rds")) %>% as_tibble()

# World Bank World Development Indicators (WDI)
# http://data.worldbank.org/data-catalog/world-development-indicators
wdi_indicators <- c("NY.GDP.PCAP.PP.KD",  # GDP per capita, ppp (constant 2011 international $)
                    "NY.GDP.MKTP.PP.KD",  # GDP, ppp (constant 2010 international $)
                    "NE.TRD.GNFS.ZS",  # Trade (% of GDP)
                    "SP.POP.TOTL")     # Population, total

wdi_raw <- WDI(country = "all", wdi_indicators, extra = TRUE, start = 1980, end = 2018)

# Chaudhry restrictions
# In this data Sudan (625) splits into North Sudan (626) and South Sudan (525)
# in 2011, but in the other datasets regular Sudan stays 625 and South Sudan
# becomes 626, so adjust the numbers here
#
# Also, Chad is in the dataset, but all values are missing, so we drop it
chaudhry_raw <- read_dta(here("data", "raw_data", 
                              "Chaudhry restrictions", "SC_Expanded.dta")) %>% 
  filter(ccode != 483) %>%  # Remove Chad
  mutate(ccode = case_when(
    scode == "SSU" ~ 626,
    scode == "SDN" ~ 625,
    TRUE ~ ccode
  )) %>% 
  mutate(gwcode = countrycode(ccode, origin = "cown", destination = "gwn",
                              custom_match = c("679" = 678L, "818" = 816L,
                                               "342" = 345L, "341" = 347L,
                                               "348" = 341L, "315" = 316L)))

# UCDP/PRIO Armed Conflict
ucdp_prio_raw <- read_csv(here("data", "raw_data", "UCDP PRIO", 
                               "ucdp-prio-acd-191.csv"))

Create country-year skeleton

We use Gleditsch-Ward country codes to identify each country across the different datasets we merge. We omit microstates.

Importantly, when converting GW codes to COW codes, following Gleditsch and Ward, we treat post-2006 Serbia as 345 (a continuation of Serbia & Montenegro). And we also treat Serbia as a continuation of Yugoslavia with 345 (following V-Dem, which does that too).

In both COW and GW codes, modern Vietnam is 816, but countrycode() thinks the COW code is 817, which is old South Vietnam (see issue), so we use custom_match to force 816 to recode to 816.

Also, following Gleditsch and Ward, we treat Serbia after 2006 dissolution of Serbia & Montenegro as 345 in COW codes (see here)

Also, following V-Dem, we treat Czechoslovakia (GW/COW 315) and Czech Republic (GW/COW 316) as the same continuous country (V-Dem has both use ID 157).

Also, because the World Bank doesn’t include it in the WDI, we omit Taiwan (713). We also omit East Germany (265) and South Yemen (680).

microstates <- gwstates %>% 
  filter(microstate) %>% distinct(gwcode, iso3c)

panel_skeleton_all <- state_panel(1980, 2018, partial = "any") %>% 
  mutate(year = year(date)) %>% 
  filter(!(gwcode %in% microstates$gwcode)) %>% 
  filter(!(gwcode %in% c(265, 680, 713))) %>% 
  mutate(gwcode = recode(gwcode, `315` = 316L)) %>% 
  mutate(cowcode = countrycode(gwcode, origin = "gwn", destination = "cown",
                               custom_match = c("816" = 816L, "340" = 345L)),
         country = countrycode(cowcode, origin = "cown", destination = "country.name",
                               custom_match = c("678" = "Yemen")),
         iso2 = countrycode(cowcode, origin = "cown", destination = "iso2c",
                            custom_match = c("345" = "RS", "347" = "XK", "678" = "YE")),
         iso3 = countrycode(cowcode, origin = "cown", destination = "iso3c",
                            custom_match = c("345" = "SRB", "347" = "XKK", "678" = "YEM")),
         # Use 999 as the UN country code for Kosovo
         un = countrycode(cowcode, origin = "cown", destination = "un",
                          custom_match = c("345" = 688, "347" = 999, "678" = 887))) %>% 
  # There are two entries for "Yugoslavia" in 2006 after recoding 340 as 345;
  # get rid of one
  filter(!(gwcode == 340 & cowcode == 345 & year == 2006)) %>% 
  # Remove the Bahamas, Belize, and Brunei
  filter(!(gwcode %in% c(31, 80, 835))) %>% 
  # Make Serbia 345 in GW codes too, for joining with other datasets
  mutate(gwcode = recode(gwcode, `340` = 345L)) %>% 
  select(-date) %>% 
  arrange(gwcode, year)

But, we’re ultimately not using all 170 of those countries. There are 163 countries in Suparna’s anti-NGO law data, so we’re limiting the analysis to just those.

Additionally, we exclude long-term consolidated democracies from our analysis, following FinkelPerez-LinanSeligson:2007, 414. These are classified by the World Bank as high income; they score below 3 on Freedom House’s Scale, receive no aid from USAID, and are not newly independent states:

consolidated_democracies <- 
  tibble(country_name = c("Andorra", "Australia", "Austria", "Bahamas", 
                          "Barbados", "Belgium", "Canada", "Denmark", "Finland", 
                          "France", "Germany", "Greece", "Grenada", "Iceland", 
                          "Ireland", "Italy", "Japan", "Liechtenstein", "Luxembourg", 
                          "Malta", "Monaco", "Netherlands", "New Zealand", "Norway", 
                          "San Marino", "Spain", "Sweden", "Switzerland", 
                          "United Kingdom", "United States of America")) %>% 
  # Ignore these 5 microstates, since they're not in the panel skeleton
  filter(!(country_name %in% c("Andorra", "Grenada", "Liechtenstein", 
                               "Monaco", "San Marino"))) %>% 
  mutate(iso3 = countrycode(country_name, "country.name", "iso3c"),
         gwcode = countrycode(country_name, "country.name", "gwn"))

consolidated_democracies %>% knitr::kable()
country_name iso3 gwcode
Australia AUS 900
Austria AUT 305
Bahamas BHS 31
Barbados BRB 53
Belgium BEL 211
Canada CAN 20
Denmark DNK 390
Finland FIN 375
France FRA 220
Germany DEU 260
Greece GRC 350
Iceland ISL 395
Ireland IRL 205
Italy ITA 325
Japan JPN 740
Luxembourg LUX 212
Malta MLT 338
Netherlands NLD 210
New Zealand NZL 920
Norway NOR 385
Spain ESP 230
Sweden SWE 380
Switzerland CHE 225
United Kingdom GBR 200
United States of America USA 2

Thus, here’s our actual panel skeleton:

chaudhry_countries <- chaudhry_raw %>% distinct(gwcode)

panel_skeleton <- panel_skeleton_all %>% 
  filter(gwcode %in% chaudhry_countries$gwcode) %>% 
  filter(!(gwcode %in% consolidated_democracies$gwcode))

skeleton_lookup <- panel_skeleton %>% 
  group_by(gwcode, cowcode, country, iso2, iso3, un) %>% 
  summarize(years_included = n()) %>% 
  ungroup() %>% 
  arrange(country)

We have 142 countries in this data, spanning 39 possible years. Here’s a lookup table of all the countries included:

skeleton_lookup %>% 
  datatable()

Foreign aid

OECD and AidData

The OECD collects detailed data on all foreign aid flows (ODA) from OECD member countries (and some non-member countries), mulilateral organizations, and the Bill and Melinda Gates Foundation (for some reason they’re the only nonprofit donor) to all DAC-eligible countries (and some non non-DAC-eligible countries).

The OECD tracks all this in a centralized Creditor Reporting System database and provides a nice front end for it at OECD.Stat with an open (but inscrutable) API (raw CRS data is also available). There are a set of pre-built queries with information about ODA flows by donor, recipient, and sector (purpose), but the pre-built data sources do not include all dimensions of the data. For example, Table DAC2a includes columns for donor, recipient, year, and total ODA (e.g. the US gave $X to Nigeria in 2008) , but does not indicate the purpose/sector for the ODA. Table DAC5 includes columns for the donor, sector, year, and total ODA (e.g. the US gave $X for education in 2008), but does not include recipient information.

Instead of using these pre-built queries or attempting to manipulate their parameters, it’s possible to use the OECD’s QWIDS query builder to create a custom download of data. However, it is slow and clunky and requires significant munging and filtering after exporting.

The solution to all of this is to use data from AidData, which imports raw data from the OECD, cleans it, verifies it, and makes it freely available on GitHub.

AidData offers multiple versions of the data, including a full release, a thin release, aggregated donor/recipient/year data, and aggregated donor/recipient/year/purpose data. For the purposes of this study, all we care about are ODA flows by donor, recipient, year, and purpose, which is one of the ready-made datasets.

Notably, this aggregated data shows total aid commitments, not aid disbursements. Both types of ODA information are available from the OECD and it’s possible to get them using OECD’s raw data. However, AidData notes that disbursement data is sticky and slow—projects take a long time to fulfill and actual inflows of aid in a year can be tied to commitments made years before. Because we’re interested in donor reactions to restrictions on NGOs, any reaction would be visible in the decision to commit money to aid, not in the ultimate disbursement of aid, which is most likely already legally obligated and allocated to the country regardless of restrictions.

So, we look at ODA commitments.

aiddata_url <- "https://github.com/AidData-WM/public_datasets/releases/download/v3.1/AidDataCore_ResearchRelease_Level1_v3.1.zip"
aiddata_path <- here("data", "raw_data", "AidData")
aiddata_zip_name <- basename(aiddata_url)
aiddata_name <- tools::file_path_sans_ext(aiddata_zip_name)

aiddata_final_name <- "AidDataCoreDonorRecipientYearPurpose_ResearchRelease_Level1_v3.1.csv"

# Download AidData data if needed
if (!file.exists(file.path(aiddata_path, aiddata_final_name))) {
  aiddata_get <- GET(aiddata_url, 
                     write_disk(file.path(aiddata_path, aiddata_zip_name),
                                overwrite = TRUE), 
                     progress())
  unzip(file.path(aiddata_path, aiddata_zip_name), exdir = aiddata_path)
  
  # Clean up zip file and unnecessary CSV files
  file.remove(file.path(aiddata_path, aiddata_zip_name))
  list.files(aiddata_path, pattern = "csv", full.names = TRUE) %>%
    map(~ ifelse(str_detect(.x, "DonorRecipientYearPurpose"), 0,
                 file.remove(file.path(.x))))
}

# Clean up AidData data
aidraw_data <- read_csv(file.path(aiddata_path, aiddata_final_name))

aiddata_clean <- aidraw_data %>%
  # Get rid of non-country recipients
  filter(!str_detect(recipient,
                     regex("regional|unspecified|multi|value|global|commission", 
                           ignore_case = TRUE))) %>%
  filter(year < 9999) %>%
  mutate(purpose_code_short = as.integer(str_sub(coalesced_purpose_code, 1, 3)))

# Donor, recipient, and purpose details
# I pulled these country names out of the dropdown menu at OECD.Stat Table 2a
# online: https://stats.oecd.org/Index.aspx?DataSetCode=Table2A
dac_donors <- c("Australia", "Austria", "Belgium", "Canada", "Czech Republic",
                "Denmark", "Finland", "France", "Germany", "Greece", "Iceland",
                "Ireland", "Italy", "Japan", "Korea", "Luxembourg", "Netherlands",
                "New Zealand", "Norway", "Poland", "Portugal", "Slovak Republic",
                "Slovenia", "Spain", "Sweden", "Switzerland", "United Kingdom",
                "United States")

non_dac_donors <- c("Bulgaria", "Croatia", "Cyprus", "Estonia", "Hungary",
                    "Israel", "Kazakhstan", "Kuwait", "Latvia", "Liechtenstein",
                    "Lithuania", "Malta", "Romania", "Russia", "Saudi Arabia",
                    "Chinese Taipei", "Thailand", "Timor Leste", "Turkey",
                    "United Arab Emirates")

other_countries <- c("Brazil", "Chile", "Colombia", "India", "Monaco", "Qatar",
                     "South Africa", "Taiwan")

donors_all <- aiddata_clean %>%
  distinct(donor) %>%
  mutate(donor_type = case_when(
    donor %in% c(dac_donors, non_dac_donors, other_countries) ~ "Country",
    donor == "Bill & Melinda Gates Foundation" ~ "Private donor",
    TRUE ~ "Multilateral or IGO"
  ))

donor_countries <- donors_all %>% 
  filter(donor_type == "Country") %>% 
  mutate(donor_gwcode = countrycode(donor, "country.name", "gwn",
                                    custom_match = c("Liechtenstein" = 223,
                                                     "Monaco" = 221)),
         donor_iso3 = countrycode(donor, "country.name", "iso3c"))

donors <- bind_rows(filter(donors_all, donor_type != "Country"),
                    donor_countries)

recipients <- aiddata_clean %>%
  distinct(recipient) %>%
  mutate(iso3 = countrycode(recipient, "country.name", "iso3c",
                            custom_match = c(`Korea, Democratic Republic of` = NA,
                                             `Netherlands Antilles` = NA,
                                             Kosovo = "XKK",
                                             `Serbia and Montenegro` = "SCG",
                                             Yugoslavia = "YUG"
                                             ))) %>% 
  filter(iso3 %in% unique(panel_skeleton$iso3)) %>%
  mutate(gwcode = countrycode(iso3, "iso3c", "gwn",
                              custom_match = c(XKK = 347,
                                               YEM = 678)))

# Purposes
purposes <- aiddata_clean %>%
  count(coalesced_purpose_name, coalesced_purpose_code)

# Current list is at https://webfs.oecd.org/crs-iati-xml/Lookup/DAC-CRS-CODES.xml
# but the XML structure has changed and it's trickier to identify all the codes
# systematically now
# So instead we use a version from 2016
purposes_url <- "https://web.archive.org/web/20160819123535/https://www.oecd.org/dac/stats/documentupload/DAC_codeLists.xml"
purposes_path <- here("data", "raw_data", "DAC CRS codes")
purposes_name <- "DAC_codeLists.xml"

# Download DAC CRS codes if needed
if (!file.exists(file.path(purposes_path, purposes_name))) {
  purposes_get <- GET(purposes_url, 
                      write_disk(file.path(purposes_path, purposes_name),
                                 overwrite = TRUE), 
                      progress())
}

purpose_nodes <- read_xml(file.path(purposes_path, purposes_name)) %>%
  xml_find_all("//codelist-item")

purpose_codes <- tibble(
  code = purpose_nodes %>% xml_find_first(".//code") %>% xml_text(),
  category = purpose_nodes %>% xml_find_first(".//category") %>% xml_text(),
  # name = purpose_nodes %>% xml_find_first(".//name//narrative") %>% xml_text(),
  name = purpose_nodes %>% xml_find_first(".//name") %>% xml_text(),
  # description = purpose_nodes %>% xml_find_first(".//description//narrative") %>% xml_text()
  description = purpose_nodes %>% xml_find_first(".//description") %>% xml_text()
)

# Extract the general categories of aid purposes (i.e. the first three digits of the purpose codes)
general_codes <- purpose_codes %>%
  filter(code %in% as.character(100:1000) & str_detect(name, "^\\d")) %>%
  mutate(code = as.integer(code)) %>%
  select(purpose_code_short = code, purpose_category_name = name) %>%
  mutate(purpose_category_clean = str_replace(purpose_category_name,
                                              "\\d\\.\\d ", "")) %>%
  separate(purpose_category_clean,
           into = c("purpose_sector", "purpose_category"), 
           sep = ", ") %>%
  mutate(across(c(purpose_sector, purpose_category), ~str_to_title(.))) %>%
  select(-purpose_category_name)

# These 7 codes are weird and get filtered out inadvertently
codes_not_in_oecd_list <- tribble(
  ~purpose_code_short, ~purpose_sector, ~purpose_category,
  100,                 "Social",        "Social Infrastructure",
  200,                 "Eco",           "Economic Infrastructure",
  300,                 "Prod",          "Production",
  310,                 "Prod",          "Agriculture",
  320,                 "Prod",          "Industry",
  420,                 "Multisector",   "Women in development",
  # NB: This actually is split between 92010 (domestic NGOs), 92020
  # (international NGOs), and 92030 (local and regional NGOs)
  920,                 "Non Sector",    "Support to NGOs"
)

purpose_codes_clean <- general_codes %>%
  bind_rows(codes_not_in_oecd_list) %>%
  arrange(purpose_code_short) %>%
  mutate(purpose_contentiousness = "")

# Manually code contentiousness of purposes
write_csv(purpose_codes_clean,
          here("data", "manual_data",
               "purpose_codes_contention_WILL_BE_OVERWRITTEN.csv"))

purpose_codes_contentiousness <- read_csv(here("data", "manual_data",
                                               "purpose_codes_contention.csv"))

aiddata_final <- aiddata_clean %>%
  left_join(donors, by = "donor") %>%
  left_join(recipients, by = "recipient") %>%
  left_join(purpose_codes_contentiousness, by = "purpose_code_short") %>%
  mutate(donor_type_collapsed = ifelse(donor_type == "Country", "Country",
                                       "IGO, Multilateral, or Private")) %>%
  select(donor, donor_type, donor_type_collapsed,
         donor_gwcode, donor_iso3, year, gwcode, iso3,
         oda = commitment_amount_usd_constant_sum,
         purpose_code_short, purpose_sector, purpose_category,
         purpose_contentiousness,
         coalesced_purpose_code, coalesced_purpose_name) %>%
  arrange(gwcode, year)

ever_dac_eligible <- read_csv(here("data", "manual_data", 
                                   "oecd_dac_countries.csv")) %>%
  # Ignore High Income Countries and More Advanced Developing Countries
  filter(!(dac_abbr %in% c("HIC", "ADC"))) %>%
  # Ignore countries that aren't in our skeleton panel
  filter(iso3 %in% panel_skeleton$iso3) %>% 
  mutate(gwcode = countrycode(iso3, "iso3c", "gwn",
                              custom_match = c("YEM" = 678))) %>% 
  pull(gwcode) %>% unique()

List of donors

donors %>% datatable()

List of recipients

select(recipients, recipient) %>% datatable()

List of purposes

arrange(purposes, desc(n)) %>% datatable()

Summary of clean data

aiddata_final %>% glimpse()
## Rows: 624,258
## Columns: 15
## $ donor                   <chr> "Canada", "Italy", "Norway", "Sweden", "Sweden", "Swede…
## $ donor_type              <chr> "Country", "Country", "Country", "Country", "Country", …
## $ donor_type_collapsed    <chr> "Country", "Country", "Country", "Country", "Country", …
## $ donor_gwcode            <dbl> 20, 325, 385, 380, 380, 380, 305, 305, 20, 20, 20, 380,…
## $ donor_iso3              <chr> "CAN", "ITA", "NOR", "SWE", "SWE", "SWE", "AUT", "AUT",…
## $ year                    <dbl> 1973, 1973, 1973, 1973, 1973, 1973, 1974, 1974, 1974, 1…
## $ gwcode                  <dbl> 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,…
## $ iso3                    <chr> "CUB", "CUB", "CUB", "CUB", "CUB", "CUB", "CUB", "CUB",…
## $ oda                     <dbl> 868282, 65097, 3161808, 39976725, 6996366, 29982544, 19…
## $ purpose_code_short      <dbl> 998, 111, 321, 111, 321, 530, 311, 321, 311, 430, 998, …
## $ purpose_sector          <chr> "Non Sector", "Social", "Prod", "Social", "Prod", "Non …
## $ purpose_category        <chr> "Other", "Education", "Industry", "Education", "Industr…
## $ purpose_contentiousness <chr> "Low", "Low", "Low", "Low", "Low", "Low", "Low", "Low",…
## $ coalesced_purpose_code  <dbl> 99810, 11120, 32120, 11120, 32105, 53030, 31140, 32120,…
## $ coalesced_purpose_name  <chr> "Sectors not specified", "Education facilities and trai…

USAID

USAID provides the complete dataset for its Foreign Aid Explorer as a giant CSV file. The data includes both economic and military aid, but it’s easy to filter out the military aid. Here we only look at obligations, not disbursements, so that the data is comparable to the OECD data from AidData. The data we downloaded provides constant amounts in 2015 dollars; we rescale that to 2011 to match all other variables.

usaid_url <- "https://explorer.usaid.gov/prepared/us_foreign_aid_complete.csv"
usaid_path <- here("data", "raw_data", "USAID")
usaid_name <- basename(usaid_url)

# Download USAID data if needed
if (!file.exists(file.path(usaid_path, usaid_name))) {
  usaid_get <- GET(usaid_url, 
                   write_disk(file.path(usaid_path, usaid_name),
                              overwrite = TRUE), 
                   progress())
}

# Clean up USAID data
usaid_raw <- read_csv(file.path(usaid_path, usaid_name),
                      na = c("", "NA", "NULL"))

usaid_clean <- usaid_raw %>%
  filter(assistance_category_name == "Economic") %>%
  filter(transaction_type_name == "Obligations") %>%
  mutate(country_code = recode(country_code, `CS-KM` = "XKK")) %>%
  # Remove regions and World
  filter(!str_detect(country_name, "Region")) %>%
  filter(!(country_name %in% c("World"))) %>%
  # Ignore countries that aren't in our skeleton panel
  filter(country_code %in% panel_skeleton$iso3) %>% 
  mutate(gwcode = countrycode(country_code, "iso3c", "gwn",
                              custom_match = c("YEM" = 678, "XKK" = 347))) %>%
  select(gwcode, year = fiscal_year, 
         implementing_agency_name, subagency_name, activity_name,
         channel_category_name, channel_subcategory_name, dac_sector_code,
         oda_us_current = current_amount, oda_us_2015 = constant_amount) %>%
  mutate(aid_deflator = oda_us_current / oda_us_2015 * 100) %>%
  mutate(channel_ngo_us = channel_subcategory_name == "NGO - United States",
         channel_ngo_int = channel_subcategory_name == "NGO - International",
         channel_ngo_dom = channel_subcategory_name == "NGO - Non United States")

# Get rid of this because it's huge and taking up lots of memory
rm(usaid_raw)

Implementing agencies

Here are the US government agencies giving out money:

implementing_agencies <- usaid_clean %>%
  count(implementing_agency_name, subagency_name) %>%
  arrange(desc(n), implementing_agency_name)

implementing_agencies %>% datatable()

Activities

The activities listed don’t follow any standard coding guidelines. There are tens of thousands of them. Here are the first 100, just for reference:

activities <- usaid_clean %>%
  count(activity_name) %>%
  slice(1:100)

activities %>% datatable()

Channels

USAID distinguishes between domestic, foreign, and international NGOs, companies, multilateral organizations, etc. recipients (or channels) of money:

channels <- usaid_clean %>%
  count(channel_category_name, channel_subcategory_name) %>%
  filter(!is.na(channel_category_name))

channels %>% datatable(options = list(pageLength = 20))

Summary of clean data

usaid_clean %>% glimpse()
## Rows: 441,202
## Columns: 14
## $ gwcode                   <dbl> 666, 666, 666, 666, 666, 666, 645, 666, 666, 666, 666,…
## $ year                     <chr> "1985", "1985", "1986", "1986", "1991", "1991", "2004"…
## $ implementing_agency_name <chr> "U.S. Agency for International Development", "U.S. Age…
## $ subagency_name           <chr> "not applicable", "not applicable", "not applicable", …
## $ activity_name            <chr> "ESF", "USAID Grants", "ESF", "USAID Grants", "ESF", "…
## $ channel_category_name    <chr> "Government", "Government", "Government", "Government"…
## $ channel_subcategory_name <chr> "Government - United States", "Government - United Sta…
## $ dac_sector_code          <dbl> 430, 430, 430, 430, 430, 430, 210, 430, 430, 430, 430,…
## $ oda_us_current           <dbl> 1950050000, 1950050000, 1898400000, 1898400000, 185000…
## $ oda_us_2015              <dbl> 4026117551, 4026117551, 3833615802, 3833615802, 316861…
## $ aid_deflator             <dbl> 48.43500, 48.43500, 49.51983, 49.51983, 58.38520, 58.3…
## $ channel_ngo_us           <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
## $ channel_ngo_int          <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
## $ channel_ngo_dom          <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…

NGO regulations

Chaudhry laws

dcjw_questions_raw <- read_csv(here("data", "manual_data", "dcjw_questions.csv"))
## 
## ── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────
## cols(
##   question = col_character(),
##   question_cat = col_double(),
##   barrier = col_character(),
##   barrier_display = col_character(),
##   question_clean = col_character(),
##   question_display = col_character(),
##   ignore_in_index = col_logical()
## )
dcjw_barriers_clean <- dcjw_questions_raw %>%
  distinct(question_cat, barrier)

dcjw_barriers_ignore <- dcjw_questions_raw %>%
  select(question, ignore_in_index)
# Original DCJW data
dcjw_orig <- read_excel(here("data", "raw_data", 
                             "DCJW NGO laws", "DCJW_NGO_Laws.xlsx")) %>% 
  select(-c(contains("source"), contains("burden"), 
            contains("subset"), Coder, Date))
dcjw_orig_n <- nrow(dcjw_orig)

In 2013, Darin Christensen and Jeremy Weinstein collected detailed data on NGO regulations for their Journal of Democracy article, covering 98 countries.

Suparna Chaudhry expanded this data substantially (it now covers 163 countries and goes to 2013), so we use that.

Notes on year coverage

In our original paper from 2017, we used Suparna’s data and backfilled it to 1980, since going back in time is possible with the DCJW data—lots of the entries in DCJW include start dates of like 1950 or 1970. Accordingly, our analysis ranged from 1980-2013. However, not all of Suparna’s expanded countries when back in time that far, and she focused primarily on 1990+ changes. Additionally—and more importantly—the whole nature of foreign aid and civil society changed drastically after the Cold War. Civil society regulations weren’t really used as a political strategy until after 1990. We can confirm that by plotting V-Dem’s core civil society index:

vdem_raw %>% 
  filter(year >= 1980) %>% 
  select(year, v2xcs_ccsi) %>% 
  group_by(year) %>% 
  summarize(avg_ccsi = mean(v2xcs_ccsi)) %>% 
  ggplot(aes(x = year, y = avg_ccsi)) +
  geom_line() +
  geom_vline(xintercept = 1990, color = "red") +
  labs(x = "Year", y = "Average Core Civil Society Index", 
       caption = "Source: V-Dem's v2xcs_ccsi")

Something systematic happened to civil society regulations worldwide in 1990, and rather than try to model pre-Cold War regulations, which were connected to foreign aid in completely different ways than they were after the dissolution of the USSR, we limit our analysis to 1990+

We still collect as much pre-1990 data as possible for the sake of (1) lagging, so we can get lagged values from 1989 and 1988 when looking at lagged variables in 1990, and (2) robustness checks that we run using the 98 backfilled DCJW countries

Index creation

We create several indexes for each of the categories of regulation, following Christensen and Weinstein’s classification:

  • entry (Q2b, Q2c, Q2d; 3 points maximum, actual max = 3 points maximum): barriers to entry
    • Q2c is reversed, so not being allowed to appeal registration status earns 1 point.
    • Q2a is omitted because it’s benign
  • funding (Q3b, Q3c, Q3d, Q3e, Q3f; 5 points maximum, actual max = 4.5): barriers to funding
    • Q3a is omitted because it’s benign
    • Scores that range between 0–2 are rescaled to 0–1 (so 1 becomes 0.5)
  • advocacy (Q4a, Q4c; 2 points maximum, actual max = 2): barriers to advocacy
    • Q4b is omitted because it’s not a law
    • Scores that range between 0–2 are rescaled to 0–1 (so 1 becomes 0.5)
  • barriers_total (10 points maximum, actual max = 8.5): sum of all three indexes

These indexes are also standardized by dividing by the maximum, yielding the following variables:

  • entry_std: 1 point maximum, actual max = 1
  • funding_std: 1 point maximum, actual max = 1
  • advocacy_std: 1 point maximum, actual max = 1
  • barriers_total_std: 3 points maximum, actual max = 2.5

Chaudhry 2020 data

The most recent version of Suparna’s data is already in nice clean panel form, so it’s super easy to get cleaned up.

dcjw_questions <- read_csv(here("data", "manual_data", "dcjw_questions.csv")) %>% 
  select(question, barrier, question_clean, ignore_in_index)

regulation_categories <- tribble(
  ~question, ~col_name, ~category,
  "q2a", "ngo_register", "omit",
  "q2b", "ngo_register_burden", "entry",
  "q2c", "ngo_register_appeal", "entry",
  "q2d", "ngo_barrier_foreign_funds", "entry",
  "q3a", "ngo_disclose_funds", "omit",
  "q3b", "ngo_foreign_fund_approval", "funding",
  "q3c", "ngo_foreign_fund_channel", "funding", 
  "q3d", "ngo_foreign_fund_restrict", "funding",
  "q3e", "ngo_foreign_fund_prohibit", "funding",
  "q3f", "", "funding",
  "q4a", "", "advocacy",
  "q4c", "", "advocacy"
)

chaudhry_2014 <- expand_grid(gwcode = unique(chaudhry_raw$gwcode), 
                             year = 2014)

chaudhry_individual_laws <- chaudhry_raw %>% 
  bind_rows(chaudhry_2014) %>% 
  arrange(gwcode, year)

chaudhry_long <- chaudhry_raw %>% 
  # Bring in 2014 rows
  bind_rows(chaudhry_2014) %>% 
  # Ethiopia and Czech Republic have duplicate rows in 1993 and 1994 respectively, but 
  # the values are identical, so just keep the first of the two
  group_by(gwcode, year) %>% 
  slice(1) %>% 
  ungroup() %>% 
  arrange(gwcode, year) %>% 
  # Reverse values for q2c
  mutate(q2c = 1 - q2c) %>% 
  # Rescale 2-point questions to 0-1 scale
  mutate_at(vars(q3e, q3f, q4a), ~rescale(., to = c(0, 1), from = c(0, 2))) %>% 
  # q2d and q4c use -1 to indicate less restriction/burdensomeness. Since we're
  # concerned with an index of restriction, we make the negative values zero
  mutate_at(vars(q2d, q4c), ~ifelse(. == -1, 0, .)) %>% 
  pivot_longer(cols = starts_with("q"), names_to = "question") %>% 
  left_join(dcjw_questions, by = "question") %>% 
  group_by(gwcode) %>%
  mutate(all_missing = all(is.na(value))) %>%
  group_by(gwcode, question) %>% 
  # Bring most recent legislation forward in time
  fill(value) %>% 
  # For older NA legislation that can't be brought forward, set sensible
  # defaults. Leave countries that are 100% 0 as NA.
  mutate(value = ifelse(!all_missing & is.na(value), 0, value)) %>% 
  ungroup()

chaudhry_registration <- chaudhry_long %>% 
  select(gwcode, year, question_clean, value) %>% 
  pivot_wider(names_from = "question_clean", values_from = "value")

chaudhry_summed <- chaudhry_long %>%
  filter(!ignore_in_index) %>% 
  group_by(gwcode, year, barrier) %>% 
  summarize(total = sum(value)) %>% 
  ungroup()

chaudhry_clean <- chaudhry_summed %>% 
  pivot_wider(names_from = barrier, values_from = total) %>% 
  mutate_at(vars(entry, funding, advocacy), 
            list(std = ~. / max(., na.rm = TRUE))) %>% 
  mutate(barriers_total = advocacy + entry + funding,
         barriers_total_std = advocacy_std + entry_std + funding_std) %>% 
  left_join(chaudhry_registration, by = c("gwcode", "year"))

glimpse(chaudhry_clean)
## Rows: 3,965
## Columns: 22
## $ gwcode                         <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
## $ year                           <dbl> 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, …
## $ advocacy                       <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ entry                          <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ funding                        <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ entry_std                      <dbl> 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.33…
## $ funding_std                    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ advocacy_std                   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ barriers_total                 <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ barriers_total_std             <dbl> 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.33…
## $ ngo_register                   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_register_burden            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_register_appeal            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_barrier_foreign_funds      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ ngo_disclose_funds             <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ ngo_foreign_fund_approval      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_foreign_fund_channel       <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_foreign_fund_restrict      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_foreign_fund_prohibit      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_type_foreign_fund_prohibit <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_politics                   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ ngo_politics_foreign_fund      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …

DCJW data

For fun and robustness checks, we use DCJW’s non-panel data to generate a panel starting in 1980, since they have entries where laws start in the 1960s and 70s and other pre-1980 years.

dcjw_tidy <- dcjw_orig %>%
  mutate(across(everything(), as.character)) %>%
  pivot_longer(names_to = "key", values_to = "value", -Country) %>% 
  separate(key, c("question", "var_name"), 4) %>%
  mutate(var_name = ifelse(var_name == "", "value", gsub("_", "", var_name))) %>%
  pivot_wider(names_from = "var_name", values_from = "value") %>% 
  # Remove underscore to match Chaudhry's stuff
  mutate(question = str_remove(question, "_")) %>% 
  mutate(value = as.numeric(value)) %>% 
  # Reverse values for q2c
  mutate(value = ifelse(question == "q2c", 1 - value, value)) %>% 
  # Rescale 2-point questions to 0-1 scale
  mutate(value = ifelse(question %in% c("q3e", "q3f", "q4a"),
                        rescale(value, to = c(0, 1), from = c(0, 2)),
                        value)) %>% 
  # q2d and q4c use -1 to indicate less restriction/burdensomeness. Since we're
  # concerned with an index of restriction, we make the negative values zero
  mutate(value = ifelse(question %in% c("q2d", "q4c") & value == -1,
                        0, value)) %>% 
  # Get rid of rows where year is missing and regulation was not imposed
  filter(!(is.na(year) & value == 0)) %>%
  # Some entries have multiple years; for now just use the first year
  mutate(year = str_split(year, ",")) %>% unnest(year) %>% 
  group_by(Country, question) %>% slice(1) %>% ungroup() %>%
  mutate(value = as.integer(value), year = as.integer(year)) %>% 
  mutate(Country = countrycode(Country, "country.name", "country.name"),
         gwcode = countrycode(Country, "country.name", "gwn",
                              custom_match = c("Yemen" = 678))) %>% 
  # If year is missing but some regulation exists, assume it has always already
  # existed (since 1950, arbitrarily)
  mutate(year = ifelse(is.na(year), 1950, year))

potential_dcjw_panel <- dcjw_tidy %>%
  tidyr::expand(gwcode, question, 
                year = min(.$year, na.rm = TRUE):2015)

dcjw_clean <- dcjw_tidy %>%
  select(-Country) %>% 
  right_join(potential_dcjw_panel,
             by = c("gwcode", "question", "year")) %>% 
  arrange(gwcode, year) %>% 
  left_join(dcjw_questions, by = "question") %>% 
  filter(!ignore_in_index) %>% 
  group_by(gwcode) %>%
  mutate(all_missing = all(is.na(value))) %>%
  group_by(gwcode, question) %>% 
  # Bring most recent legislation forward in time
  fill(value) %>% 
  # For older NA legislation that can't be brought forward, set sensible
  # defaults. Leave countries that are 100% 0 as NA.
  mutate(value = ifelse(!all_missing & is.na(value), 0, value)) %>% 
  group_by(gwcode, year, barrier) %>%
  summarize(total = sum(value)) %>%
  ungroup() %>%
  pivot_wider(names_from = "barrier", values_from = "total") %>%
  filter(year > 1978) %>% 
  # Standardize barrier indexes by dividing by maximum number possible
  mutate(across(c(entry, funding, advocacy), list(std = ~ . / max(., na.rm = TRUE)))) %>% 
  mutate(barriers_total = advocacy + entry + funding,
         barriers_total_std = advocacy_std + entry_std + funding_std)

glimpse(dcjw_clean)
## Rows: 3,626
## Columns: 10
## $ gwcode             <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
## $ year               <dbl> 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, …
## $ advocacy           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ entry              <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ funding            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ entry_std          <dbl> 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.333…
## $ funding_std        <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ advocacy_std       <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ barriers_total     <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ barriers_total_std <dbl> 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.333…

All clean! Except not! NEVER MIND TO ALL THAT ↑

Suparna made updates to existing the DCJW countries too, like Honduras (gwcode 91), which has more correct values for q4a, for instance, which DCJW marks as 0, but is actually 1. So even though we can go back in time to 1980 with DCJW, it’s not comparable with Suparna’s expanded and more recent data.

# Look at Honduras in 1990 in both datasets:
dcjw_clean %>% filter(year == 1990, gwcode == 91)
## # A tibble: 1 x 10
##   gwcode  year advocacy entry funding entry_std funding_std advocacy_std barriers_total
##    <dbl> <dbl>    <dbl> <dbl>   <dbl>     <dbl>       <dbl>        <dbl>          <dbl>
## 1     91  1990        0     0       0         0           0            0              0
## # … with 1 more variable: barriers_total_std <dbl>
chaudhry_clean %>% filter(year == 1990, gwcode == 91)
## # A tibble: 1 x 22
##   gwcode  year advocacy entry funding entry_std funding_std advocacy_std barriers_total
##    <dbl> <dbl>    <dbl> <dbl>   <dbl>     <dbl>       <dbl>        <dbl>          <dbl>
## 1     91  1990      0.5     0       0         0           0         0.25            0.5
## # … with 13 more variables: barriers_total_std <dbl>, ngo_register <dbl>,
## #   ngo_register_burden <dbl>, ngo_register_appeal <dbl>,
## #   ngo_barrier_foreign_funds <dbl>, ngo_disclose_funds <dbl>,
## #   ngo_foreign_fund_approval <dbl>, ngo_foreign_fund_channel <dbl>,
## #   ngo_foreign_fund_restrict <dbl>, ngo_foreign_fund_prohibit <dbl>,
## #   ngo_type_foreign_fund_prohibit <dbl>, ngo_politics <dbl>,
## #   ngo_politics_foreign_fund <dbl>

So we live with just 1990+, even for the sake of lagging 🤷.

Except, we’re not quite done yet!

In Suparna’s clean data, due to post-Cold War chaos, Russia (365) is missing for 1990-1991 and Serbia/Serbia and Montenegro/Yugoslavia (345) is missing every thing pre-2006. DCJW don’t include any data for Serbia, so we’re out of luck there—we’re limited to Serbia itself and not past versions of it. DCJW do include data for Russia, though, so we use that in our clean final NGO laws data. Fortunately this is easy, since Russia’s values are all 0 for those two years:

dcjw_clean %>% 
  filter(gwcode == 365, year %in% c(1990, 1991))
## # A tibble: 2 x 10
##   gwcode  year advocacy entry funding entry_std funding_std advocacy_std barriers_total
##    <dbl> <dbl>    <dbl> <dbl>   <dbl>     <dbl>       <dbl>        <dbl>          <dbl>
## 1    365  1990        0     0       0         0           0            0              0
## 2    365  1991        0     0       0         0           0            0              0
## # … with 1 more variable: barriers_total_std <dbl>

So we just add two rows for Russia:

early_russia <- tibble(gwcode = 365, year = c(1990, 1991),
                       advocacy = 0, entry = 0, funding = 0, 
                       entry_std = 0, funding_std = 0, advocacy_std = 0, 
                       barriers_total = 0, barriers_total_std = 0)

chaudhry_clean <- chaudhry_clean %>% 
  bind_rows(early_russia) %>% 
  arrange(gwcode, year)

Regulatory environment

An alternative way of measuring civil society restrictions is to look at the overall civil society regulatory environment rather than specific laws, since de jure restrictions do not always map clearly into de facto restrictions (especially in dictatorships where the implementation of laws is more discretionary).

Andrew Heiss develops a new civil society regulatory environment index (CSRE) in his dissertation, which combines two civil society indexes from the Varieties of Democracy project (V-Dem): (1) civil society repression (v2csreprss) and (2) civil society entry and exit regulations (v2cseeorgs). The CSRE ranges from roughly −6 to 6 (though typically only from −4 to 4ish), and shows more variation over time since it ostensibly captures changes in the implementation of the regulatory environment rather than the presence or absence of legislation.

Additionally, since Andrew’s dissertation, the V-Dem project has created its own core civil society index (v2xcs_ccsi) (entry/exit (v2cseeorgs) + repression (v2csreprss) + participatory environment (v2csprtcpt)). We use that instead, since V-Dem rescales it to a 0-1 scale so it’s not weirdly distributed from like my additive two-factor CSRE index.

While the main focus of this paper is donor response to new legislation, we also look at donor response to changes in the overall civil society index as a robustness check. This also allows us to include data from 1980–2018 (Since Suparana’s law data ranges from 1990–2014)

We also use a bunch of other V-Dem variables as confounders:

Economics and development

   gdpcap_log + un_trade_pct_gdp + v2xeg_eqdr + v2peprisch + e_peinfmor +
   # Human rights and politics
   # Conflict and disasters
   internal_conflict_past_5 + natural_dis_count +
  • Civil society things
    • CSO entry and exit: v2cseeorgs
    • CSO repression: v2csreprss
    • CSO consultation: v2cscnsult
    • CSO participatory environment: v2csprtcpt
    • CSO women’s participation: v2csgender
    • CSO anti-system movements: v2csantimv
    • Core civil society index (entry/exit, repression, participatory env): v2xcs_ccsi
  • Human rights and politics
    • Polity scores: e_polity2 (only for reference with polyarchy; we don’t use these)
    • Electoral democracy index: v2x_polyarchy
    • Regimes of the world scores: v2x_regime_amb (only for determining average autocracy; we don’t use these)
    • Political corruption index: v2x_corr (less to more, 0-1) (public sector + executive + legislative + judicial corruption)
    • Rule of law index: v2x_rule
    • Civil liberties index: v2x_civlib
    • Physical violence index: v2x_clphy
    • Private civil liberties index: v2x_clpriv
    • Political civil liberties index: v2x_clpol (but not this because it includes v2cseeorgs and v2csreprss)
  • Economics and development
    • Educational equality: v2peedueq
    • Health equality: v2pehealth
    • Infant mortality rate: e_peinfmor
# 403: Sao Tome and Principe
# 591: Seychelles
# 679: Yemen (change to 678 for GW)
# 935: Vanuatu

vdem_clean <- vdem_raw %>% 
  filter(year >= 1980) %>% 
  mutate(COWcode = recode(COWcode, `315` = 316)) %>% 
  select(country_name, year, cowcode = COWcode, 
         # Civil society stuff
         v2cseeorgs,  # CSO entry and exit
         v2csreprss,  # CSO repression
         v2cscnsult,  # CSO consultation
         v2csprtcpt,  # CSO participatory environment
         v2csgender,  # CSO women's participation
         v2csantimv,  # CSO anti-system movements
         v2xcs_ccsi,  # Core civil society index (entry/exit, repression, participatory env)
         # Human rights and politics
         # Political corruption index (less to more, 0-1) (public sector +
         # executive + legislative + judicial corruption)
         v2x_corr,
         # Rule of law index
         v2x_rule,
         # Rights indexes
         v2x_civlib,  # Civil liberties index
         v2x_clphy,  # Physical violence index
         v2x_clpriv,  # Private civil liberties index
         v2x_clpol,  # Political civil liberties index
         # Democracy
         e_polity2, v2x_polyarchy, v2x_regime_amb,
         # Economics and development
         v2peedueq,  # Educational equality
         v2pehealth,  # Health equality
         e_peinfmor  # Infant mortality rate
  ) %>% 
  filter(cowcode != 265) %>%  # Omit East Germany
  # Convert West Germany (260) to Germany (255)
  mutate(gwcode = countrycode(cowcode, origin = "cown", destination = "gwn",
                              custom_match = c("403" = 403L, "591" = 591L,
                                               "679" = 678L, "935" = 935L, 
                                               "816" = 816L, "260" = 255L))) %>% 
  select(-country_name, -cowcode)

glimpse(vdem_clean)
## Rows: 6,747
## Columns: 21
## $ year           <dbl> 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990…
## $ v2cseeorgs     <dbl> 0.069, 0.069, 0.069, 0.069, 0.069, 0.069, 0.069, 0.069, 0.069, 0…
## $ v2csreprss     <dbl> -0.641, -0.641, -0.641, -0.641, -0.641, -0.641, -0.641, -0.641, …
## $ v2cscnsult     <dbl> 0.245, 0.245, 0.245, 0.245, 0.245, 0.245, 0.665, 0.665, 0.665, 0…
## $ v2csprtcpt     <dbl> -1.399, -1.399, -1.399, -1.399, -1.399, -0.693, -0.693, -0.693, …
## $ v2csgender     <dbl> -0.115, -0.115, -0.115, -0.115, -0.115, 0.453, 0.453, 0.453, 0.4…
## $ v2csantimv     <dbl> -0.560, -0.560, -0.560, -0.871, -0.871, -0.871, -0.871, -0.871, …
## $ v2xcs_ccsi     <dbl> 0.352, 0.352, 0.352, 0.352, 0.352, 0.386, 0.386, 0.386, 0.386, 0…
## $ v2x_corr       <dbl> 0.828, 0.828, 0.791, 0.783, 0.783, 0.783, 0.783, 0.783, 0.783, 0…
## $ v2x_rule       <dbl> 0.262, 0.243, 0.316, 0.298, 0.298, 0.298, 0.298, 0.298, 0.333, 0…
## $ v2x_civlib     <dbl> 0.588, 0.572, 0.606, 0.606, 0.606, 0.606, 0.606, 0.594, 0.602, 0…
## $ v2x_clphy      <dbl> 0.417, 0.417, 0.417, 0.417, 0.417, 0.417, 0.417, 0.422, 0.422, 0…
## $ v2x_clpriv     <dbl> 0.701, 0.701, 0.701, 0.701, 0.701, 0.701, 0.701, 0.701, 0.701, 0…
## $ v2x_clpol      <dbl> 0.624, 0.634, 0.669, 0.669, 0.669, 0.669, 0.669, 0.670, 0.678, 0…
## $ e_polity2      <dbl> -3, -3, -3, -3, -3, -3, -3, -3, 0, 0, 0, 0, 0, 0, 4, 4, 4, 6, 6,…
## $ v2x_polyarchy  <dbl> 0.293, 0.312, 0.317, 0.342, 0.342, 0.342, 0.348, 0.341, 0.354, 0…
## $ v2x_regime_amb <dbl> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 5, 5, 6, 6, 6, 6, 6…
## $ v2peedueq      <dbl> -1.026, -1.026, -1.026, -1.026, -1.026, -1.026, -1.026, -1.026, …
## $ v2pehealth     <dbl> -0.378, -0.378, -0.378, -0.378, -0.378, -0.378, -0.378, -0.378, …
## $ e_peinfmor     <dbl> 56.1, 53.7, 51.4, 49.2, 47.3, 45.5, 43.8, 42.1, 40.5, 38.8, 37.1…
## $ gwcode         <dbl> 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, …

Autocracies

We’re also interested in how these civil society dynamics work in autocracies in particular. We generate a crude list of autocracies based on average “Regimes of the World” scores from V-Dem. In that measure, 4 is the upper bound and 5 is the lower bound for electoral autocracy, so we use 4 as the cutoff. There are bound to be better ways, but this works for now.

autocracies <- vdem_clean %>% 
  group_by(gwcode) %>% 
  summarize(avg_row = mean(v2x_regime_amb, na.rm = TRUE)) %>% 
  ungroup() 

autocracies_final <- skeleton_lookup %>% 
  left_join(autocracies, by = "gwcode") %>% 
  mutate(autocracy = round(avg_row, 0) <= 4)

World Bank development indicators

We don’t really use anything from the World Bank’s data except for population data for Kosovo.

wdi_clean <- wdi_raw %>%
  filter(iso2c %in% unique(panel_skeleton$iso2)) %>%
  mutate_at(vars(income, region), as.character) %>%  # Don't use factors
  mutate(gwcode = countrycode(iso2c, origin = "iso2c", destination = "gwn",
                              custom_match = c("YE" = 678L, "XK" = 347L, 
                                               "VN" = 816L, "RS" = 345L))) %>% 
  mutate(region = ifelse(gwcode == 343, "Europe & Central Asia", region),
         income = ifelse(gwcode == 343, "Upper middle income", income)) %>% 
  select(country, gwcode, year, region, income, population = SP.POP.TOTL)

# The UN doesn't have population data for Kosovo, so we use WDI data for that
kosovo_population <- wdi_clean %>% 
  select(gwcode, year, population) %>% 
  filter(gwcode == 347, year >= 2008)

glimpse(wdi_clean)
## Rows: 5,538
## Columns: 6
## $ country    <chr> "United Arab Emirates", "United Arab Emirates", "United Arab Emirate…
## $ gwcode     <dbl> 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696…
## $ year       <int> 2007, 2002, 2003, 2004, 2005, 2006, 1980, 1981, 1982, 1983, 1984, 19…
## $ region     <chr> "Middle East & North Africa", "Middle East & North Africa", "Middle …
## $ income     <chr> "High income", "High income", "High income", "High income", "High in…
## $ population <dbl> 6168838, 3478777, 3711932, 4068570, 4588225, 5300174, 1019509, 10966…

UNData

The reason we don’t just use WDI data for GDP and % of GDP from trade is that the WDI data is incomplete, especially pre-1990. To get around that, we create our own GDP and trade measures using data directly from the UN (at UNData). They don’t have a neat API like the World Bank, so you have to go to their website and export the data manually.

We collect three variables: GDP at constant 2015 prices, GDP at current prices, and population.

# GDP by Type of Expenditure at constant (2015) prices - US dollars
# http://data.un.org/Data.aspx?q=gdp&d=SNAAMA&f=grID%3a102%3bcurrID%3aUSD%3bpcFlag%3a0
un_gdp_raw <- read_csv(here("data", "raw_data", "UN data",
                            "UNdata_Export_20210118_034054729.csv")) %>%
  rename(country = `Country or Area`) %>%
  mutate(value_type = "Constant")

# GDP by Type of Expenditure at current prices - US dollars
# http://data.un.org/Data.aspx?q=gdp&d=SNAAMA&f=grID%3a101%3bcurrID%3aUSD%3bpcFlag%3a0
un_gdp_current_raw <- read_csv(here("data", "raw_data", "UN data",
                                    "UNdata_Export_20210118_034311252.csv")) %>%
  rename(country = `Country or Area`) %>%
  mutate(value_type = "Current")

# Population
# Total Population - Both Sexes
# https://population.un.org/wpp/Download/Standard/Population/
un_pop_raw <- read_excel(here("data", "raw_data", "UN data",
                              "WPP2019_POP_F01_1_TOTAL_POPULATION_BOTH_SEXES.xlsx"),
                         skip = 16)
un_pop <- un_pop_raw %>%
  filter((`Country code` %in% unique(panel_skeleton_all$un))) %>%
  select(-c(Index, Variant, Notes, `Region, subregion, country or area *`, 
            `Parent code`, Type), 
         un_code = `Country code`) %>%
  pivot_longer(names_to = "year", values_to = "population", -un_code) %>%
  mutate(gwcode = countrycode(un_code, "un", "gwn",
                              custom_match = c("887" = 678, "704" = 816, "688" = 345))) %>% 
  mutate(year = as.integer(year),
         population = as.numeric(population) * 1000) %>%  # Values are in 1000s
  select(gwcode, year, population) %>% 
  bind_rows(kosovo_population)

glimpse(un_pop)
## Rows: 12,010
## Columns: 3
## $ gwcode     <dbl> 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516…
## $ year       <int> 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 19…
## $ population <dbl> 2308927, 2360442, 2406034, 2449089, 2492192, 2537150, 2584913, 26356…

Dealing with the GDP data is a little trickier because it’s in 2015 dollars, while AidData is in 2011 dollars. To fix this, we create a GDP deflator and rebase the 2015 values to 2011 values.

un_gdp <- bind_rows(un_gdp_raw, un_gdp_current_raw) %>%
  filter(Item %in% c("Gross Domestic Product (GDP)",
                     "Exports of goods and services",
                     "Imports of goods and services")) %>%
  filter(!(country %in% c("Former USSR", "Former Netherlands Antilles", 
                          "Yemen: Former Democratic Yemen", 
                          "United Republic of Tanzania: Zanzibar"))) %>% 
  filter(!(country == "Yemen: Former Yemen Arab Republic" & Year >= 1989)) %>% 
  filter(!(country == "Former Czechoslovakia" & Year >= 1990)) %>% 
  filter(!(country == "Former Yugoslavia" & Year >= 1990)) %>% 
  filter(!(country == "Former Ethiopia" & Year >= 1990)) %>% 
  mutate(country = recode(country, 
                          "Former Sudan" = "Sudan",
                          "Yemen: Former Yemen Arab Republic" = "Yemen",
                          "Former Czechoslovakia" = "Czechia",
                          "Former Yugoslavia" = "Serbia")) %>% 
  mutate(iso3 = countrycode(country, "country.name", "iso3c",
                            custom_match = c("Kosovo" = "XKK"))) %>% 
  left_join(select(skeleton_lookup, iso3, gwcode), by = "iso3") %>% 
  filter(!is.na(gwcode))

un_gdp_wide <- un_gdp %>% 
  select(gwcode, year = Year, Item, Value, value_type) %>% 
  pivot_wider(names_from = c(value_type, Item), values_from = Value) %>% 
  rename(exports_constant_2015 = `Constant_Exports of goods and services`,
         imports_constant_2015 = `Constant_Imports of goods and services`,
         gdp_constant_2015 = `Constant_Gross Domestic Product (GDP)`,
         exports_current = `Current_Exports of goods and services`,
         imports_current = `Current_Imports of goods and services`,
         gdp_current = `Current_Gross Domestic Product (GDP)`) %>%
  mutate(gdp_deflator = gdp_current / gdp_constant_2015 * 100)

# Rescale the 2015 data to 2011 to match AidData
#
# Deflator = current GDP / constant GDP * 100
# Current GDP in year_t * (deflator in year_target / deflator in year_t)
un_gdp_rescaled <- un_gdp_wide %>%
  left_join(select(filter(un_gdp_wide, year == 2011),
                   gwcode, deflator_target_year = gdp_deflator),
            by = "gwcode") %>%
  mutate(un_gdp_2011 = gdp_current * (deflator_target_year / gdp_deflator),
         un_trade_pct_gdp = (imports_current + exports_current) / gdp_current) 

un_gdp_final <- un_gdp_rescaled %>%
  select(gwcode, year, un_trade_pct_gdp, un_gdp = un_gdp_2011)

glimpse(un_gdp_final)
## Rows: 6,440
## Columns: 4
## $ gwcode           <int> 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 70…
## $ year             <dbl> 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009, 20…
## $ un_trade_pct_gdp <dbl> 0.5097236, 0.5840631, 0.5431432, 0.5534622, 0.5090126, 0.54423…
## $ un_gdp           <dbl> 25006241359, 25429194387, 23734473969, 22918774375, 2333676742…

UCDP/PRIO Armed Conflict

The UCDP/PRIO Armed Conflict Dataset tracks a ton of conflict-releated data, including reasons for the conflict, parties in the conflict, intensity of the conflict, and deaths in the conflict. We’re only interested in whether a conflict happened in a given year (or in the past 5 years), so here we simply create an indicator variable for whether there was internal conflict in a country-year (conflict type = 3).

ucdp_prio_clean <- ucdp_prio_raw %>% 
  filter(type_of_conflict == 3) %>%
  mutate(gwcode_raw = str_split(gwno_a, pattern = ", ")) %>% 
  unnest(gwcode_raw) %>% 
  mutate(gwcode = as.integer(gwcode_raw)) %>% 
  group_by(gwcode, year) %>% 
  summarize(internal_conflict = n() > 0) %>% 
  ungroup()

glimpse(ucdp_prio_clean)
## Rows: 1,283
## Columns: 3
## $ gwcode            <int> 40, 40, 40, 40, 41, 41, 41, 42, 52, 70, 70, 90, 90, 90, 90, 9…
## $ year              <dbl> 1953, 1956, 1957, 1958, 1989, 1991, 2004, 1965, 1990, 1994, 1…
## $ internal_conflict <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, T…

Natural disasters

Natural disaster data comes from the International Disaster Database (EM-DAT). The data includes the number of deaths, injuries, homeless displacements, and monetary losses (in 2000 dollars) for a huge number of natural and technological disasters (see EM-DAT’s full classification).

Natural disasters could matter for aid too, since donor countries might increase their aid to countries suffering more.

EM-DAT does not provide a single link to download their data. Instead, you have to create a query using their advanced search form. We downloaded data using the following query:

  • Select all countries from 1950–2021
  • Select all three disaster classification groups (natural, technological, complex)
  • Download Excel file and save in Data/raw_data/Disasters/
disasters_raw <- read_excel(here("data", "raw_data", "Disasters",
                                 "emdat_public_2021_01_16_query_uid-ufBbE2.xlsx"),
                            skip = 6)

disasters <- disasters_raw %>%
  # Only look at countries in the main panel
  filter(ISO %in% unique(panel_skeleton$iso3)) %>%
  filter(`Disaster Group` != "Complex Disasters") %>% 
  mutate(gwcode = countrycode(ISO, origin = "iso3c", destination = "gwn",
                              custom_match = c("YEM" = "678")),
         gwcode = as.numeric(gwcode)) %>% 
  select(country = Country, year = Year, iso3 = ISO, gwcode,
         type = `Disaster Type`, group = `Disaster Group`,
         subgroup = `Disaster Subgroup`,
         dis_deaths = `Total Deaths`, dis_injured = `No Injured`,
         dis_affected = `No Affected`, dis_homeless = `No Homeless`,
         dis_total_affected = `Total Affected`, dis_total_damage = `Total Damages ('000 US$)`)

disasters_summarized <- disasters %>% 
  group_by(gwcode, year, group) %>% 
  summarize(across(starts_with("dis_"), ~sum(., na.rm = TRUE)),
            dis_count = n()) %>% 
  ungroup() %>% 
  filter(group == "Natural") %>% 
  pivot_longer(names_to = "name", values_to = "value", starts_with("dis_")) %>% 
  mutate(group = str_to_lower(group)) %>% 
  unite(name, group, name) %>% 
  pivot_wider(names_from = "name", values_from = "value") %>% 
  mutate(year = as.numeric(year)) %>% 
  filter(year > 1980)

disasters_summarized %>% glimpse()
## Rows: 3,259
## Columns: 9
## $ gwcode                     <dbl> 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, …
## $ year                       <dbl> 1981, 1982, 1983, 1985, 1986, 1987, 1988, 1990, 1992…
## $ natural_dis_deaths         <dbl> 0, 24, 15, 4, 0, 0, 23, 4, 0, 51, 14, 2, 3, 3, 6, 4,…
## $ natural_dis_injured        <dbl> 0, 0, 39, 0, 0, 0, 12, 0, 40, 95, 0, 3, 0, 0, 0, 0, …
## $ natural_dis_affected       <dbl> 0, 105000, 164536, 479891, 7500, 0, 150000, 5000, 14…
## $ natural_dis_homeless       <dbl> 0, 75000, 0, 22000, 0, 0, 1500, 6000, 0, 32000, 4282…
## $ natural_dis_total_affected <dbl> 0, 180000, 164575, 501891, 7500, 0, 151512, 11000, 1…
## $ natural_dis_total_damage   <dbl> 0, 85000, 60000, 0, 0, 0, 0, 0, 2590, 1140000, 10196…
## $ natural_dis_count          <dbl> 1, 1, 1, 2, 2, 1, 3, 2, 2, 5, 2, 3, 3, 2, 2, 2, 2, 1…

Clean combined data

With both donor- and country-level data, we have lots of different options for analysis. Since our hypotheses deal with questions of donor responses, the data we use to model donor responses uses donor-years as the unit of observation. Not all donors give money to the same countries, so this final data is not a complete panel (i.e. it does not include every combination of donors and years), which will pose some interesting methodological issues when modeling if we use donor-level data.

donor_aidraw_data <- aiddata_final %>% 
  filter(gwcode %in% unique(panel_skeleton$gwcode)) %>%
  filter(year > 1980) %>%
  filter(oda > 0) %>%  # Only look at positive aid
  mutate(oda_log = log1p(oda))

# Create fake country codes for non-country donors
fake_codes <- donor_aidraw_data %>%
  distinct(donor, donor_type) %>%
  filter(donor_type != "Country") %>%
  arrange(donor_type) %>% select(-donor_type) %>%
  mutate(fake_donor_gwcode = 2001:(2000 + n()),
         fake_donor_iso3 = paste0("Z", str_sub(fake_donor_gwcode, 3)))

donor_level_data <- donor_aidraw_data %>%
  left_join(fake_codes, by = "donor") %>%
  mutate(donor_gwcode = ifelse(is.na(donor_gwcode), 
                               fake_donor_gwcode, 
                               donor_gwcode),
         donor_iso3 = ifelse(is.na(donor_iso3), 
                             fake_donor_iso3, 
                             donor_iso3)) %>%
  select(-starts_with("fake"))

USAID’s conversion to constant 2015 dollars doesn’t seem to take country differences into account—the deflator for each country in 2011 is essentially 96.65. When there are differences, it’s because of floating point issues (like, if there are tiny grants of $3, there aren’t enough decimal points to get the fraction to 96.65). So we just take the median value of the deflator for all countries and all grants and use that.

# Rescale the 2015 data to 2011 to match AidData
#
# Deflator = current aid / constant aid * 100
# Current aid in year_t * (deflator in year_target / deflator in year_t)
usaid_deflator_2011 <- usaid_clean %>%
  filter(year == 2011) %>%
  summarise(deflator_target_year = median(aid_deflator, na.rm = TRUE)) %>%
  as.numeric()

donor_level_data_usaid <- usaid_clean %>%
  filter(gwcode %in% unique(panel_skeleton$gwcode)) %>%
  filter(year > 1980) %>%
  filter(oda_us_current > 0) %>%
  mutate(oda_us_2011 = oda_us_current * (usaid_deflator_2011 / aid_deflator)) %>% 
  mutate(year = as.numeric(year))

usaid_by_country_total <- donor_level_data_usaid %>%
  group_by(gwcode, year) %>%
  summarise(oda_us = sum(oda_us_2011, na.rm = TRUE))

usaid_by_country_channel <- donor_level_data_usaid %>%
  pivot_longer(names_to = "key", values_to = "value", 
               c(channel_ngo_us, channel_ngo_int, channel_ngo_dom)) %>%
  group_by(gwcode, year, key, value) %>%
  summarise(total_oda_us = sum(oda_us_2011, na.rm = TRUE)) %>%
  ungroup() %>%
  unite(channel, key, value) %>%
  filter(str_detect(channel, "TRUE")) %>%
  mutate(channel = str_replace(channel, "channel", "oda_us"),
         channel = str_replace(channel, "_TRUE", "")) %>%
  spread(channel, total_oda_us, fill = 0)
# Country data
country_level_data <- panel_skeleton %>% 
  mutate(ever_dac_eligible = gwcode %in% ever_dac_eligible) %>% 
  filter(!(gwcode %in% consolidated_democracies$gwcode)) %>% 
  left_join(un_gdp_final, by = c("gwcode", "year")) %>% 
  left_join(un_pop, by = c("gwcode", "year")) %>% 
  mutate(gdpcap = un_gdp / population,
         gdpcap_log = log(gdpcap),
         population_log = log(population)) %>% 
  left_join(chaudhry_clean, by = c("gwcode", "year")) %>% 
  # Indicator for Chaudhry data coverage
  # Chaudhry's Serbia data starts with 2006 and doesn't include pre-2006 stuff,
  # so we mark those as false. Also, Chaudhry starts in 1992 for Russia and 1993
  # for Czechia, so we mark those as false too
  mutate(laws = year %in% 1990:2014) %>% 
  mutate(laws = case_when(
   # Serbia, Czechia, and Russia
   gwcode == 345 & year <= 2005 ~ FALSE,
   gwcode == 316 & year <= 1992 ~ FALSE,
   gwcode == 365 & year <= 1991 ~ FALSE,
   TRUE ~ laws  # Otherwise, use FALSE
  )) %>% 
  left_join(vdem_clean, by = c("gwcode", "year")) %>%
  left_join(ucdp_prio_clean, by = c("gwcode", "year")) %>% 
  # Treat NAs in conflicts as FALSE
  mutate(internal_conflict = ifelse(is.na(internal_conflict),
                                    FALSE, internal_conflict)) %>%
  left_join(disasters_summarized, 
            by = c("gwcode", "year")) %>% 
  # NAs in disasters are really 0, especially when occurrence is 0
  mutate_at(vars(starts_with("natural_")), ~ifelse(is.na(.), 0, .)) %>%
  # Add indicator for post-Cold War, since all the former Soviet republics have
  # no GDP data before 1990
  mutate(post_1989 = year >= 1990)
testthat::expect_equal(nrow(country_level_data), nrow(panel_skeleton))

# Combine country and donor data
donor_country_data <- donor_level_data %>%
  left_join(select(country_level_data, -country, -iso3),
            by = c("year", "gwcode")) %>% 
  arrange(donor, year)
testthat::expect_equal(nrow(donor_country_data), nrow(donor_level_data))

# Calculate different versions of aid variables
aid_by_country_total <- donor_country_data %>%
  group_by(gwcode, year) %>%
  summarise(total_oda = sum(oda, na.rm = TRUE)) %>% 
  ungroup()

aid_by_country_purpose <- donor_country_data %>%
  group_by(gwcode, year, purpose_contentiousness) %>%
  summarise(total_oda = sum(oda, na.rm = TRUE)) %>%
  pivot_wider(names_from = "purpose_contentiousness", 
              values_from = "total_oda", values_fill = 0) %>% 
  rename(oda_contentious_high = High, 
         oda_contentious_low = Low) %>% 
  ungroup()

country_aid <- country_level_data %>% 
  left_join(aid_by_country_total, by = c("year", "gwcode")) %>% 
  left_join(aid_by_country_purpose, by = c("year", "gwcode")) %>% 
  left_join(usaid_by_country_total, by = c("year", "gwcode")) %>% 
  left_join(usaid_by_country_channel, by = c("year", "gwcode")) %>% 
  mutate(across(contains("oda"), ~ifelse(is.na(.), 0, .)))

testthat::expect_equal(nrow(country_aid), nrow(panel_skeleton))

Missing data

The donor data is complete with no missing variables(!).

gg_miss_var(donor_level_data, show_pct = TRUE)

The country-level panel data is relatively complete, with only a few variables suffering from missing data, mostly from the World Bank and V-Dem. There are a lot of NGO-related missing variables, but that’s because we don’t have data from 1980–1989 and 2015+

gg_miss_var(country_aid, show_pct = TRUE)

country_aid %>% 
  select(-starts_with("funding"), -starts_with("entry"), 
         -starts_with("advocacy"), -starts_with("barriers")) %>% 
  gg_miss_var(., show_pct = TRUE)

Here’s how we address that:

  • We remove everything from Yugoslavia/Serbia and Montenegro (345) prior to 2006

  • Infant mortality e_peinfmor is missing from Kosovo (2008–2014), and the World Bank doesn’t have data for it, but Eurostat does in their demo_minfind indicator. Their data, however, is missing a couple years

    kosovo_infant_mort <- tibble(year = 2007:2019,
                                 e_peinfmor = c(11.1, 9.7, 9.9, 8.8, 13.1, 11.4, 
                                                NA, NA, 9.7, 8.5, 9.7, 10.6, 8.7))
    kosovo_infant_mort
    ## # A tibble: 13 x 2
    ##     year e_peinfmor
    ##    <int>      <dbl>
    ##  1  2007       11.1
    ##  2  2008        9.7
    ##  3  2009        9.9
    ##  4  2010        8.8
    ##  5  2011       13.1
    ##  6  2012       11.4
    ##  7  2013       NA  
    ##  8  2014       NA  
    ##  9  2015        9.7
    ## 10  2016        8.5
    ## 11  2017        9.7
    ## 12  2018       10.6
    ## 13  2019        8.7

    To fix this, we use linear interpolation to fill in 2013 and 2014:

    kosovo_infant_mort <- zoo::na.approx(kosovo_infant_mort) %>% 
      as_tibble() %>% rename(e_peinfmor_interp = e_peinfmor) %>% 
      mutate(gwcode = 347)
    kosovo_infant_mort
    ## # A tibble: 13 x 3
    ##     year e_peinfmor_interp gwcode
    ##    <dbl>             <dbl>  <dbl>
    ##  1  2007              11.1    347
    ##  2  2008               9.7    347
    ##  3  2009               9.9    347
    ##  4  2010               8.8    347
    ##  5  2011              13.1    347
    ##  6  2012              11.4    347
    ##  7  2013              10.8    347
    ##  8  2014              10.3    347
    ##  9  2015               9.7    347
    ## 10  2016               8.5    347
    ## 11  2017               9.7    347
    ## 12  2018              10.6    347
    ## 13  2019               8.7    347
  • v2x_corr is only missing data from Bahrain, which oddly has no data from 1980–2004. Because corruption levels do not really change after 2005, we impute the average corruption for the country in all previous years.

  • v2x_polyarchy is only missing in Mozambique from 1980–1993. To address this, we calculate the average value of V-Dem’s polyarchy index (v2x_polyarchy) for each level of Polity (−8, −7, and −6 in the case of Mozambique), and then use that corresponding average polyarchy

  • We also create an imputed column for those rows in Bahrain and Mozambique to see if imputation does anything weird in the models

# Find Bahrain's average corruption
avg_corruption_bhr <- country_aid %>% 
  filter(iso3 == "BHR") %>% 
  summarize(avg_corr = mean(v2x_corr, na.rm = TRUE)) %>% 
  pull(avg_corr)

# Find average polyarchy scores across different pre-1994 polity scores
avg_polyarchy_polity <- country_aid %>% 
  filter(year < 1994) %>% 
  group_by(e_polity2) %>% 
  summarize(avg_polyarchy = mean(v2x_polyarchy, na.rm = TRUE),
            n = n())

country_aid_complete <- country_aid %>% 
  # Get rid of pre-2006 Serbia stuff
  filter(!(gwcode == 345 & year < 2006)) %>% 
  # Fix Serbia name
  mutate(country = ifelse(gwcode == 345, "Serbia", country)) %>% 
  mutate(v2x_corr = ifelse(is.na(v2x_corr) & iso3 == "BHR", 
         avg_corruption_bhr, v2x_corr)) %>% 
  mutate(imputed_corr = is.na(v2x_corr) & iso3 == "BHR") %>% 
  mutate(v2x_polyarchy = case_when(
    iso3 == "MOZ" & is.na(v2x_polyarchy) & e_polity2 == -6 ~ 
      filter(avg_polyarchy_polity, e_polity2 == -6)$avg_polyarchy,
    iso3 == "MOZ" & is.na(v2x_polyarchy) & e_polity2 == -7 ~ 
      filter(avg_polyarchy_polity, e_polity2 == -7)$avg_polyarchy,
    iso3 == "MOZ" & is.na(v2x_polyarchy) & e_polity2 == -8 ~ 
      filter(avg_polyarchy_polity, e_polity2 == -8)$avg_polyarchy,
    TRUE ~ v2x_polyarchy
  )) %>% 
  mutate(imputed_polyarchy = is.na(v2x_polyarchy) & iso3 == "MOZ") %>% 
  # Add Kosovo infant mortality
  left_join(kosovo_infant_mort, by = c("gwcode", "year")) %>% 
  mutate(e_peinfmor = coalesce(e_peinfmor, e_peinfmor_interp)) %>% 
  # Get rid of polity and RoW---we don't actually need them
  select(-e_polity2, -v2x_regime_amb, -e_peinfmor_interp)

country_aid_complete %>% glimpse()
## Rows: 5,168
## Columns: 70
## $ gwcode                         <dbl> 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, …
## $ year                           <dbl> 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, …
## $ cowcode                        <dbl> 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, …
## $ country                        <chr> "Cuba", "Cuba", "Cuba", "Cuba", "Cuba", "Cuba", …
## $ iso2                           <chr> "CU", "CU", "CU", "CU", "CU", "CU", "CU", "CU", …
## $ iso3                           <chr> "CUB", "CUB", "CUB", "CUB", "CUB", "CUB", "CUB",…
## $ un                             <dbl> 192, 192, 192, 192, 192, 192, 192, 192, 192, 192…
## $ ever_dac_eligible              <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, …
## $ un_trade_pct_gdp               <dbl> 0.7703379, 0.7678009, 0.7678627, 0.7651135, 0.76…
## $ un_gdp                         <dbl> 31513499922, 37717983194, 41081761480, 433048889…
## $ population                     <dbl> 9849457, 9898891, 9940314, 9981303, 10031651, 10…
## $ gdpcap                         <dbl> 3199.516, 3810.324, 4132.843, 4338.601, 4659.138…
## $ gdpcap_log                     <dbl> 8.070755, 8.245470, 8.326721, 8.375307, 8.446586…
## $ population_log                 <dbl> 16.10293, 16.10793, 16.11211, 16.11622, 16.12126…
## $ advocacy                       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, 1, 1,…
## $ entry                          <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ funding                        <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.0, 0.0…
## $ entry_std                      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ funding_std                    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ advocacy_std                   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.5, 0.5…
## $ barriers_total                 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1.0, 1.0…
## $ barriers_total_std             <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.5, 0.5…
## $ ngo_register                   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_register_burden            <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_register_appeal            <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_barrier_foreign_funds      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_disclose_funds             <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_foreign_fund_approval      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_foreign_fund_channel       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_foreign_fund_restrict      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_foreign_fund_prohibit      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.0, 0.0…
## $ ngo_type_foreign_fund_prohibit <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ ngo_politics                   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, 1, 1,…
## $ ngo_politics_foreign_fund      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 0, 0,…
## $ laws                           <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,…
## $ v2cseeorgs                     <dbl> -2.425, -2.425, -2.425, -2.425, -2.425, -2.425, …
## $ v2csreprss                     <dbl> -2.022, -2.022, -2.022, -2.022, -2.022, -2.022, …
## $ v2cscnsult                     <dbl> -1.038, -1.038, -1.038, -1.038, -1.038, -1.038, …
## $ v2csprtcpt                     <dbl> -2.305, -2.305, -2.305, -2.305, -2.305, -2.305, …
## $ v2csgender                     <dbl> 1.48, 1.48, 1.48, 1.48, 1.48, 1.48, 1.48, 1.48, …
## $ v2csantimv                     <dbl> -0.577, -0.577, -0.577, -0.577, -0.600, -0.591, …
## $ v2xcs_ccsi                     <dbl> 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050,…
## $ v2x_corr                       <dbl> 0.375, 0.375, 0.375, 0.375, 0.375, 0.375, 0.375,…
## $ v2x_rule                       <dbl> 0.301, 0.301, 0.301, 0.301, 0.301, 0.301, 0.301,…
## $ v2x_civlib                     <dbl> 0.311, 0.311, 0.311, 0.311, 0.311, 0.311, 0.298,…
## $ v2x_clphy                      <dbl> 0.799, 0.799, 0.799, 0.799, 0.799, 0.799, 0.799,…
## $ v2x_clpriv                     <dbl> 0.077, 0.077, 0.077, 0.077, 0.077, 0.077, 0.060,…
## $ v2x_clpol                      <dbl> 0.041, 0.041, 0.041, 0.041, 0.041, 0.041, 0.041,…
## $ v2x_polyarchy                  <dbl> 0.074, 0.074, 0.074, 0.074, 0.074, 0.074, 0.074,…
## $ v2peedueq                      <dbl> 2.341, 2.341, 2.341, 2.341, 2.341, 2.341, 2.341,…
## $ v2pehealth                     <dbl> 2.715, 2.715, 2.715, 2.715, 2.715, 2.715, 2.715,…
## $ e_peinfmor                     <dbl> 16.7, 16.5, 16.3, 16.1, 15.7, 15.0, 14.1, 13.3, …
## $ internal_conflict              <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,…
## $ natural_dis_deaths             <dbl> 0, 0, 24, 15, 0, 4, 0, 0, 23, 0, 4, 0, 0, 51, 14…
## $ natural_dis_injured            <dbl> 0, 0, 0, 39, 0, 0, 0, 0, 12, 0, 0, 0, 40, 95, 0,…
## $ natural_dis_affected           <dbl> 0, 0, 105000, 164536, 0, 479891, 7500, 0, 150000…
## $ natural_dis_homeless           <dbl> 0, 0, 75000, 0, 0, 22000, 0, 0, 1500, 0, 6000, 0…
## $ natural_dis_total_affected     <dbl> 0, 0, 180000, 164575, 0, 501891, 7500, 0, 151512…
## $ natural_dis_total_damage       <dbl> 0, 0, 85000, 60000, 0, 0, 0, 0, 0, 0, 0, 0, 2590…
## $ natural_dis_count              <dbl> 0, 1, 1, 1, 0, 2, 2, 1, 3, 0, 2, 0, 2, 5, 2, 3, …
## $ post_1989                      <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,…
## $ total_oda                      <dbl> 0, 1159924, 981820, 28253724, 10967245, 17376910…
## $ oda_contentious_low            <dbl> 0, 1159924, 981820, 28253724, 10967245, 17376910…
## $ oda_contentious_high           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18032,…
## $ oda_us                         <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0…
## $ oda_us_ngo_dom                 <dbl> 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0…
## $ oda_us_ngo_int                 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ oda_us_ngo_us                  <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, …
## $ imputed_corr                   <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,…
## $ imputed_polyarchy              <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,…

Much better!

country_aid_complete %>% 
  select(-starts_with("funding"), -starts_with("entry"),
         -starts_with("advocacy"), -starts_with("barriers")) %>%
  gg_miss_var(., show_pct = TRUE)

There are only three countries now that have any missing data:

  • Kosovo is missing pre-existence infant mortality, which is fine becuase it didn’t exist yet.

  • Russia is missing GDP, GDP per capita, and percent of GDP from trade from 1980–1989. There’s no easy way around this. V-Dem has GDP per capita data from the long-running Maddison Project Database, and it includes 1980s Soviet Russia, but the values aren’t really comparable to the stuff we calculated using UN GDP data. At first glance it seems that this is a difference in real years, since the Maddison Project uses 2011 dollars and the UN uses 2015 dollars, and there’s not an easy way to shift the Maddison Project’s values up to 2015 (i.e. there’s no deflator). But even if they were in the same dollar-years, the values from the Maddison Project seem really really low compared to what we made with the UN GDP data, so they don’t seem to be comparable.

  • Czechoslovakia is missing percent of GDP from trade from 1980–1989. This is because it is missing imports data in the UN GDP data. It has exports data and overall GDP data, but for whatever reason, imports are missing. Boo.

country_aid_complete %>% 
  select(gwcode, country, year, un_trade_pct_gdp, un_gdp, gdpcap, gdpcap_log) %>% 
  filter(is.na(un_trade_pct_gdp))
##    gwcode country year un_trade_pct_gdp       un_gdp   gdpcap gdpcap_log
## 1     316 Czechia 1980               NA 183919110258 17771.54   9.785353
## 2     316 Czechia 1981               NA 183743647861 17726.42   9.782812
## 3     316 Czechia 1982               NA 183984035455 17750.06   9.784144
## 4     316 Czechia 1983               NA 188240745011 18180.31   9.808094
## 5     316 Czechia 1984               NA 194289061254 18788.90   9.841022
## 6     316 Czechia 1985               NA 199875093661 19346.85   9.870285
## 7     316 Czechia 1986               NA 205065586592 19856.67   9.896295
## 8     316 Czechia 1987               NA 209182118795 20254.92   9.916153
## 9     316 Czechia 1988               NA 214531745219 20765.98   9.941071
## 10    316 Czechia 1989               NA 215359391664 20836.11   9.944443
## 11    365  Russia 1980               NA           NA       NA         NA
## 12    365  Russia 1981               NA           NA       NA         NA
## 13    365  Russia 1982               NA           NA       NA         NA
## 14    365  Russia 1983               NA           NA       NA         NA
## 15    365  Russia 1984               NA           NA       NA         NA
## 16    365  Russia 1985               NA           NA       NA         NA
## 17    365  Russia 1986               NA           NA       NA         NA
## 18    365  Russia 1987               NA           NA       NA         NA
## 19    365  Russia 1988               NA           NA       NA         NA
## 20    365  Russia 1989               NA           NA       NA         NA

Since those issues are all pre-1990, our data is perfect post-1990 in cases with Suparna’s law coverage:

country_aid_complete %>% 
  filter(laws) %>% 
  gg_miss_var(., show_pct = TRUE)

Final data

Now that we know all the data is clean and pretty much nothing is missing, we can do a few final windowed operations that will add missing values (e.g. lagging). We also add an indicator marking if a disaster happened in the past 5 years.

In H3 we hypothesize that more aid will be allocated to international or US-based NGOs than domestic NGOs in response to harsher anti-NGO restrictions. While AidData unfortunately does not categorize aid by channel (i.e. aid given to international vs. US vs. domestic NGOs), USAID does. For this hypothesis, then we only look at aid given by USAID, not the rest of the OECD. As with the proportion of contentious aid, we create similar variables to measure the proportion of aid given to international NGOs, US-based NGOs, and both international and US-based NGOs.

# Determine if any of the values in the last k rows are TRUE
check_last_k <- function(x, k) {
  # This creates a matrix with a column for each lag value (e.g. column 1 = lag
  # 0, column 2 = lag 1, etc.)
  all_lags <- sapply(0:k, FUN = function(k) lag(x, k))
  
  # Mark TRUE if any of the columns have TRUE in them
  any_true_in_window <- apply(all_lags, MARGIN = 1, FUN = any, na.rm = TRUE)
  return(any_true_in_window)
}

country_aid_final <- country_aid_complete %>% 
  # Proportion of contentious aid
  mutate(prop_contentious = oda_contentious_high / 
           (oda_contentious_low + oda_contentious_high),
         prop_contentious = 
           ifelse(oda_contentious_high == 0 & oda_contentious_low == 0, 
                  0, prop_contentious)) %>% 
  mutate(prop_contentious_logit = car::logit(prop_contentious, adjust = 0.001)) %>% 
  # Proportion of aid to NGOs
  mutate(prop_ngo_int = oda_us_ngo_int / oda_us,
         prop_ngo_us = oda_us_ngo_us / oda_us,
         prop_ngo_dom = oda_us_ngo_dom / oda_us,
         prop_ngo_foreign = (oda_us_ngo_int + oda_us_ngo_us) / oda_us) %>% 
  mutate(across(starts_with("prop_ngo"), ~ifelse(is.nan(.), 0, .))) %>% 
  mutate(across(starts_with("prop_ngo"), list(logit = ~car::logit(., adjust = 0.001)))) %>% 
  mutate(across(c(total_oda, oda_contentious_high, oda_contentious_low, oda_us),
         list(log = ~log1p(.)))) %>% 
  # Lag/lead/diff things within countries
  group_by(gwcode) %>% 
  # Determine if there was conflict in the past 5 years
  mutate(internal_conflict_past_5 = check_last_k(internal_conflict, 5),
         natural_dis_past_5 = check_last_k(natural_dis_count >= 1, 5)) %>% 
  # Indicate changes in laws
  mutate(across(c(advocacy, entry, funding, barriers_total),
                list(new = ~. - lag(.),
                     worse = ~(. - lag(.)) > 0,
                     cat = ~cut(. - lag(.),
                                breaks = c(-Inf, -1, 0, Inf),
                                labels = c("New better law", "No new laws",
                                           "New worse law"),
                                ordered_result = TRUE)))) %>%
  # Lag and lead stuff
  mutate(across(c(barriers_total, advocacy, entry, funding, v2xcs_ccsi,
                  total_oda, total_oda_log, prop_contentious,
                  prop_ngo_dom, prop_ngo_foreign),
                list(lag1 = ~lag(., n = 1)))) %>% 
  mutate(across(c(total_oda, total_oda_log, prop_contentious,
                  prop_ngo_dom, prop_ngo_foreign),
                list(lead1 = ~lead(., n = 1)))) %>% 
  ungroup()

Save data

Phew. Everything checks out. Save this stuff for use in actual analyses in /data/derived_data/

saveRDS(country_aid_final, here("data", "derived_data", "df_country_aid.rds"))
saveRDS(donor_level_data, here("data", "derived_data", "df_donor.rds"))
saveRDS(donor_level_data_usaid, here("data", "derived_data", "df_donor_usaid.rds"))
saveRDS(autocracies_final, here("data", "derived_data", "df_autocracies.rds"))
LS0tCnRpdGxlOiAiUHJvY2VzcyBhbmQgbWVyZ2UgZGF0YSIKYXV0aG9yOiAiU3VwYXJuYSBDaGF1ZGhyeSBhbmQgQW5kcmV3IEhlaXNzIgpkYXRlOiAiTGFzdCBydW46IGByIGZvcm1hdChTeXMudGltZSgpLCAnJUYnKWAiCm91dHB1dDogaHRtbF9kb2N1bWVudAplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5yZXRpbmEgPSAzLCBmaWcud2lkdGggPSA2LCBmaWcuYXNwID0gMC42MTgsCiAgICAgICAgICAgICAgICAgICAgICB0aWR5Lm9wdHMgPSBsaXN0KHdpZHRoLmN1dG9mZiA9IDEyMCksICAjIEZvciBjb2RlCiAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zKHdpZHRoID0gOTApKSAgIyBGb3Igb3V0cHV0CgpvcHRpb25zKGRwbHlyLnN1bW1hcmlzZS5pbmZvcm0gPSBGQUxTRSkKYGBgCgpgYGB7ciBsb2FkLWxpYnJhcmllcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY291bnRyeWNvZGUpCmxpYnJhcnkoc3RhdGVzKQpsaWJyYXJ5KFdESSkKbGlicmFyeShoYXZlbikKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkobmFuaWFyKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoeG1sMikKbGlicmFyeShodHRyKQpsaWJyYXJ5KHJ2ZXN0KQpsaWJyYXJ5KERUKQpsaWJyYXJ5KHBhbmRlcikKbGlicmFyeShoZXJlKQpgYGAKCiMgTG9hZCByYXcgZGF0YQoKYGBge3IgbG9hZC1yYXctZGF0YSwgY2FjaGU9VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBWLURlbQp2ZGVtX3JhdyA8LSByZWFkX3JkcyhoZXJlKCJkYXRhIiwgInJhd19kYXRhIiwgIkNvdW50cnlfWWVhcl9WLURlbV9GdWxsK290aGVyc19SX3YxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVi1EZW0tQ1ktRnVsbCtPdGhlcnMtdjEwLnJkcyIpKSAlPiUgYXNfdGliYmxlKCkKCiMgV29ybGQgQmFuayBXb3JsZCBEZXZlbG9wbWVudCBJbmRpY2F0b3JzIChXREkpCiMgaHR0cDovL2RhdGEud29ybGRiYW5rLm9yZy9kYXRhLWNhdGFsb2cvd29ybGQtZGV2ZWxvcG1lbnQtaW5kaWNhdG9ycwp3ZGlfaW5kaWNhdG9ycyA8LSBjKCJOWS5HRFAuUENBUC5QUC5LRCIsICAjIEdEUCBwZXIgY2FwaXRhLCBwcHAgKGNvbnN0YW50IDIwMTEgaW50ZXJuYXRpb25hbCAkKQogICAgICAgICAgICAgICAgICAgICJOWS5HRFAuTUtUUC5QUC5LRCIsICAjIEdEUCwgcHBwIChjb25zdGFudCAyMDEwIGludGVybmF0aW9uYWwgJCkKICAgICAgICAgICAgICAgICAgICAiTkUuVFJELkdORlMuWlMiLCAgIyBUcmFkZSAoJSBvZiBHRFApCiAgICAgICAgICAgICAgICAgICAgIlNQLlBPUC5UT1RMIikgICAgICMgUG9wdWxhdGlvbiwgdG90YWwKCndkaV9yYXcgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgd2RpX2luZGljYXRvcnMsIGV4dHJhID0gVFJVRSwgc3RhcnQgPSAxOTgwLCBlbmQgPSAyMDE4KQoKIyBDaGF1ZGhyeSByZXN0cmljdGlvbnMKIyBJbiB0aGlzIGRhdGEgU3VkYW4gKDYyNSkgc3BsaXRzIGludG8gTm9ydGggU3VkYW4gKDYyNikgYW5kIFNvdXRoIFN1ZGFuICg1MjUpCiMgaW4gMjAxMSwgYnV0IGluIHRoZSBvdGhlciBkYXRhc2V0cyByZWd1bGFyIFN1ZGFuIHN0YXlzIDYyNSBhbmQgU291dGggU3VkYW4KIyBiZWNvbWVzIDYyNiwgc28gYWRqdXN0IHRoZSBudW1iZXJzIGhlcmUKIwojIEFsc28sIENoYWQgaXMgaW4gdGhlIGRhdGFzZXQsIGJ1dCBhbGwgdmFsdWVzIGFyZSBtaXNzaW5nLCBzbyB3ZSBkcm9wIGl0CmNoYXVkaHJ5X3JhdyA8LSByZWFkX2R0YShoZXJlKCJkYXRhIiwgInJhd19kYXRhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGF1ZGhyeSByZXN0cmljdGlvbnMiLCAiU0NfRXhwYW5kZWQuZHRhIikpICU+JSAKICBmaWx0ZXIoY2NvZGUgIT0gNDgzKSAlPiUgICMgUmVtb3ZlIENoYWQKICBtdXRhdGUoY2NvZGUgPSBjYXNlX3doZW4oCiAgICBzY29kZSA9PSAiU1NVIiB+IDYyNiwKICAgIHNjb2RlID09ICJTRE4iIH4gNjI1LAogICAgVFJVRSB+IGNjb2RlCiAgKSkgJT4lIAogIG11dGF0ZShnd2NvZGUgPSBjb3VudHJ5Y29kZShjY29kZSwgb3JpZ2luID0gImNvd24iLCBkZXN0aW5hdGlvbiA9ICJnd24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCI2NzkiID0gNjc4TCwgIjgxOCIgPSA4MTZMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIzNDIiID0gMzQ1TCwgIjM0MSIgPSAzNDdMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIzNDgiID0gMzQxTCwgIjMxNSIgPSAzMTZMKSkpCgojIFVDRFAvUFJJTyBBcm1lZCBDb25mbGljdAp1Y2RwX3ByaW9fcmF3IDwtIHJlYWRfY3N2KGhlcmUoImRhdGEiLCAicmF3X2RhdGEiLCAiVUNEUCBQUklPIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidWNkcC1wcmlvLWFjZC0xOTEuY3N2IikpCmBgYAoKIyBDcmVhdGUgY291bnRyeS15ZWFyIHNrZWxldG9uCgpXZSB1c2UgW0dsZWRpdHNjaC1XYXJkIGNvdW50cnkgY29kZXNdKGh0dHA6Ly9rc2dsZWRpdHNjaC5jb20vZGF0YS00Lmh0bWwpIHRvIGlkZW50aWZ5IGVhY2ggY291bnRyeSBhY3Jvc3MgdGhlIGRpZmZlcmVudCBkYXRhc2V0cyB3ZSBtZXJnZS4gV2Ugb21pdCBtaWNyb3N0YXRlcy4gCgpJbXBvcnRhbnRseSwgd2hlbiBjb252ZXJ0aW5nIEdXIGNvZGVzIHRvIENPVyBjb2RlcywgW2ZvbGxvd2luZyBHbGVkaXRzY2ggYW5kIFdhcmRdKGh0dHBzOi8vd3d3LmFuZHliZWdlci5jb20vc3RhdGVzL2FydGljbGVzL2RpZmZlcmVuY2VzLWd3LWNvdy5odG1sKSwgd2UgdHJlYXQgcG9zdC0yMDA2IFNlcmJpYSBhcyAzNDUgKGEgY29udGludWF0aW9uIG9mIFNlcmJpYSAmIE1vbnRlbmVncm8pLiBBbmQgd2UgYWxzbyB0cmVhdCBTZXJiaWEgYXMgYSBjb250aW51YXRpb24gb2YgWXVnb3NsYXZpYSB3aXRoIDM0NSAoZm9sbG93aW5nIFYtRGVtLCB3aGljaCBkb2VzIHRoYXQgdG9vKS4KCkluIGJvdGggQ09XIGFuZCBHVyBjb2RlcywgbW9kZXJuIFZpZXRuYW0gaXMgODE2LCBidXQgYGNvdW50cnljb2RlKClgIHRoaW5rcyB0aGUgQ09XIGNvZGUgaXMgODE3LCB3aGljaCBpcyBvbGQgU291dGggVmlldG5hbSAoc2VlIFtpc3N1ZV0oaHR0cHM6Ly9naXRodWIuY29tL3ZpbmNlbnRhcmVsYnVuZG9jay9jb3VudHJ5Y29kZS9pc3N1ZXMvMTYpKSwgc28gd2UgdXNlIGBjdXN0b21fbWF0Y2hgIHRvIGZvcmNlIDgxNiB0byByZWNvZGUgdG8gODE2LgoKQWxzbywgZm9sbG93aW5nIEdsZWRpdHNjaCBhbmQgV2FyZCwgd2UgdHJlYXQgU2VyYmlhIGFmdGVyIDIwMDYgZGlzc29sdXRpb24gb2YgU2VyYmlhICYgTW9udGVuZWdybyBhcyAzNDUgaW4gQ09XIGNvZGVzIChzZWUgW2hlcmVdKGh0dHBzOi8vd3d3LmFuZHliZWdlci5jb20vc3RhdGVzL2FydGljbGVzL2RpZmZlcmVuY2VzLWd3LWNvdy5odG1sKSkgCgpBbHNvLCBmb2xsb3dpbmcgVi1EZW0sIHdlIHRyZWF0IEN6ZWNob3Nsb3Zha2lhIChHVy9DT1cgMzE1KSBhbmQgQ3plY2ggUmVwdWJsaWMgKEdXL0NPVyAzMTYpIGFzIHRoZSBzYW1lIGNvbnRpbnVvdXMgY291bnRyeSAoVi1EZW0gaGFzIGJvdGggdXNlIElEIDE1NykuCgpBbHNvLCBiZWNhdXNlIHRoZSBXb3JsZCBCYW5rIGRvZXNuJ3QgaW5jbHVkZSBpdCBpbiB0aGUgV0RJLCB3ZSBvbWl0IFRhaXdhbiAoNzEzKS4gV2UgYWxzbyBvbWl0IEVhc3QgR2VybWFueSAoMjY1KSBhbmQgU291dGggWWVtZW4gKDY4MCkuCgpgYGB7ciBidWlsZC1za2VsZXRvbn0KbWljcm9zdGF0ZXMgPC0gZ3dzdGF0ZXMgJT4lIAogIGZpbHRlcihtaWNyb3N0YXRlKSAlPiUgZGlzdGluY3QoZ3djb2RlLCBpc28zYykKCnBhbmVsX3NrZWxldG9uX2FsbCA8LSBzdGF0ZV9wYW5lbCgxOTgwLCAyMDE4LCBwYXJ0aWFsID0gImFueSIpICU+JSAKICBtdXRhdGUoeWVhciA9IHllYXIoZGF0ZSkpICU+JSAKICBmaWx0ZXIoIShnd2NvZGUgJWluJSBtaWNyb3N0YXRlcyRnd2NvZGUpKSAlPiUgCiAgZmlsdGVyKCEoZ3djb2RlICVpbiUgYygyNjUsIDY4MCwgNzEzKSkpICU+JSAKICBtdXRhdGUoZ3djb2RlID0gcmVjb2RlKGd3Y29kZSwgYDMxNWAgPSAzMTZMKSkgJT4lIAogIG11dGF0ZShjb3djb2RlID0gY291bnRyeWNvZGUoZ3djb2RlLCBvcmlnaW4gPSAiZ3duIiwgZGVzdGluYXRpb24gPSAiY293biIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCI4MTYiID0gODE2TCwgIjM0MCIgPSAzNDVMKSksCiAgICAgICAgIGNvdW50cnkgPSBjb3VudHJ5Y29kZShjb3djb2RlLCBvcmlnaW4gPSAiY293biIsIGRlc3RpbmF0aW9uID0gImNvdW50cnkubmFtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCI2NzgiID0gIlllbWVuIikpLAogICAgICAgICBpc28yID0gY291bnRyeWNvZGUoY293Y29kZSwgb3JpZ2luID0gImNvd24iLCBkZXN0aW5hdGlvbiA9ICJpc28yYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCIzNDUiID0gIlJTIiwgIjM0NyIgPSAiWEsiLCAiNjc4IiA9ICJZRSIpKSwKICAgICAgICAgaXNvMyA9IGNvdW50cnljb2RlKGNvd2NvZGUsIG9yaWdpbiA9ICJjb3duIiwgZGVzdGluYXRpb24gPSAiaXNvM2MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYygiMzQ1IiA9ICJTUkIiLCAiMzQ3IiA9ICJYS0siLCAiNjc4IiA9ICJZRU0iKSksCiAgICAgICAgICMgVXNlIDk5OSBhcyB0aGUgVU4gY291bnRyeSBjb2RlIGZvciBLb3Nvdm8KICAgICAgICAgdW4gPSBjb3VudHJ5Y29kZShjb3djb2RlLCBvcmlnaW4gPSAiY293biIsIGRlc3RpbmF0aW9uID0gInVuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCIzNDUiID0gNjg4LCAiMzQ3IiA9IDk5OSwgIjY3OCIgPSA4ODcpKSkgJT4lIAogICMgVGhlcmUgYXJlIHR3byBlbnRyaWVzIGZvciAiWXVnb3NsYXZpYSIgaW4gMjAwNiBhZnRlciByZWNvZGluZyAzNDAgYXMgMzQ1OwogICMgZ2V0IHJpZCBvZiBvbmUKICBmaWx0ZXIoIShnd2NvZGUgPT0gMzQwICYgY293Y29kZSA9PSAzNDUgJiB5ZWFyID09IDIwMDYpKSAlPiUgCiAgIyBSZW1vdmUgdGhlIEJhaGFtYXMsIEJlbGl6ZSwgYW5kIEJydW5laQogIGZpbHRlcighKGd3Y29kZSAlaW4lIGMoMzEsIDgwLCA4MzUpKSkgJT4lIAogICMgTWFrZSBTZXJiaWEgMzQ1IGluIEdXIGNvZGVzIHRvbywgZm9yIGpvaW5pbmcgd2l0aCBvdGhlciBkYXRhc2V0cwogIG11dGF0ZShnd2NvZGUgPSByZWNvZGUoZ3djb2RlLCBgMzQwYCA9IDM0NUwpKSAlPiUgCiAgc2VsZWN0KC1kYXRlKSAlPiUgCiAgYXJyYW5nZShnd2NvZGUsIHllYXIpCmBgYAoKQnV0LCB3ZSdyZSB1bHRpbWF0ZWx5IG5vdCB1c2luZyBhbGwgYHIgcGFuZWxfc2tlbGV0b25fYWxsICU+JSBkaXN0aW5jdChnd2NvZGUpICU+JSBucm93KClgIG9mIHRob3NlIGNvdW50cmllcy4gVGhlcmUgYXJlIGByIGNoYXVkaHJ5X3JhdyAlPiUgZGlzdGluY3QoZ3djb2RlKSAlPiUgbnJvdygpYCBjb3VudHJpZXMgaW4gU3VwYXJuYSdzIGFudGktTkdPIGxhdyBkYXRhLCBzbyB3ZSdyZSBsaW1pdGluZyB0aGUgYW5hbHlzaXMgdG8ganVzdCB0aG9zZS4KCkFkZGl0aW9uYWxseSwgd2UgZXhjbHVkZSBsb25nLXRlcm0gY29uc29saWRhdGVkIGRlbW9jcmFjaWVzIGZyb20gb3VyIGFuYWx5c2lzLCBmb2xsb3dpbmcgRmlua2VsUGVyZXotTGluYW5TZWxpZ3NvbjoyMDA3LCA0MTQuIFRoZXNlIGFyZSBjbGFzc2lmaWVkIGJ5IHRoZSBXb3JsZCBCYW5rIGFzIGhpZ2ggaW5jb21lOyB0aGV5IHNjb3JlIGJlbG93IDMgb24gRnJlZWRvbSBIb3VzZSdzIFNjYWxlLCByZWNlaXZlIG5vIGFpZCBmcm9tIFVTQUlELCBhbmQgYXJlIG5vdCBuZXdseSBpbmRlcGVuZGVudCBzdGF0ZXM6CgpgYGB7ciBjcmVhdGUtY29uc29saWRhdGVkLWRlbW9jcmFjaWVzfQpjb25zb2xpZGF0ZWRfZGVtb2NyYWNpZXMgPC0gCiAgdGliYmxlKGNvdW50cnlfbmFtZSA9IGMoIkFuZG9ycmEiLCAiQXVzdHJhbGlhIiwgIkF1c3RyaWEiLCAiQmFoYW1hcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJCYXJiYWRvcyIsICJCZWxnaXVtIiwgIkNhbmFkYSIsICJEZW5tYXJrIiwgIkZpbmxhbmQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAiRnJhbmNlIiwgIkdlcm1hbnkiLCAiR3JlZWNlIiwgIkdyZW5hZGEiLCAiSWNlbGFuZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJJcmVsYW5kIiwgIkl0YWx5IiwgIkphcGFuIiwgIkxpZWNodGVuc3RlaW4iLCAiTHV4ZW1ib3VyZyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJNYWx0YSIsICJNb25hY28iLCAiTmV0aGVybGFuZHMiLCAiTmV3IFplYWxhbmQiLCAiTm9yd2F5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlNhbiBNYXJpbm8iLCAiU3BhaW4iLCAiU3dlZGVuIiwgIlN3aXR6ZXJsYW5kIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXRlZCBLaW5nZG9tIiwgIlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSIpKSAlPiUgCiAgIyBJZ25vcmUgdGhlc2UgNSBtaWNyb3N0YXRlcywgc2luY2UgdGhleSdyZSBub3QgaW4gdGhlIHBhbmVsIHNrZWxldG9uCiAgZmlsdGVyKCEoY291bnRyeV9uYW1lICVpbiUgYygiQW5kb3JyYSIsICJHcmVuYWRhIiwgIkxpZWNodGVuc3RlaW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNb25hY28iLCAiU2FuIE1hcmlubyIpKSkgJT4lIAogIG11dGF0ZShpc28zID0gY291bnRyeWNvZGUoY291bnRyeV9uYW1lLCAiY291bnRyeS5uYW1lIiwgImlzbzNjIiksCiAgICAgICAgIGd3Y29kZSA9IGNvdW50cnljb2RlKGNvdW50cnlfbmFtZSwgImNvdW50cnkubmFtZSIsICJnd24iKSkKCmNvbnNvbGlkYXRlZF9kZW1vY3JhY2llcyAlPiUga25pdHI6OmthYmxlKCkKYGBgCgpUaHVzLCBoZXJlJ3Mgb3VyIGFjdHVhbCBwYW5lbCBza2VsZXRvbjoKCmBgYHtyIGJ1aWxkLXJlYWwtc2tlbGV0b259CmNoYXVkaHJ5X2NvdW50cmllcyA8LSBjaGF1ZGhyeV9yYXcgJT4lIGRpc3RpbmN0KGd3Y29kZSkKCnBhbmVsX3NrZWxldG9uIDwtIHBhbmVsX3NrZWxldG9uX2FsbCAlPiUgCiAgZmlsdGVyKGd3Y29kZSAlaW4lIGNoYXVkaHJ5X2NvdW50cmllcyRnd2NvZGUpICU+JSAKICBmaWx0ZXIoIShnd2NvZGUgJWluJSBjb25zb2xpZGF0ZWRfZGVtb2NyYWNpZXMkZ3djb2RlKSkKCnNrZWxldG9uX2xvb2t1cCA8LSBwYW5lbF9za2VsZXRvbiAlPiUgCiAgZ3JvdXBfYnkoZ3djb2RlLCBjb3djb2RlLCBjb3VudHJ5LCBpc28yLCBpc28zLCB1bikgJT4lIAogIHN1bW1hcml6ZSh5ZWFyc19pbmNsdWRlZCA9IG4oKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgYXJyYW5nZShjb3VudHJ5KQpgYGAKCldlIGhhdmUgYHIgcGFuZWxfc2tlbGV0b24gJT4lIGRpc3RpbmN0KGd3Y29kZSkgJT4lIG5yb3coKWAgY291bnRyaWVzIGluIHRoaXMgZGF0YSwgc3Bhbm5pbmcgYHIgcGFuZWxfc2tlbGV0b24gJT4lIGRpc3RpbmN0KHllYXIpICU+JSBucm93KClgIHBvc3NpYmxlIHllYXJzLiBIZXJlJ3MgYSBsb29rdXAgdGFibGUgb2YgYWxsIHRoZSBjb3VudHJpZXMgaW5jbHVkZWQ6CgpgYGB7ciBzaG93LWZpbmFsLWNvdW50cmllc30Kc2tlbGV0b25fbG9va3VwICU+JSAKICBkYXRhdGFibGUoKQpgYGAKCgojIEZvcmVpZ24gYWlkCgojIyBPRUNEIGFuZCBBaWREYXRhIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKVGhlIE9FQ0QgY29sbGVjdHMgZGV0YWlsZWQgZGF0YSBvbiBhbGwgZm9yZWlnbiBhaWQgZmxvd3MgKE9EQSkgZnJvbSBPRUNEIG1lbWJlciBjb3VudHJpZXMgKGFuZCBzb21lIG5vbi1tZW1iZXIgY291bnRyaWVzKSwgbXVsaWxhdGVyYWwgb3JnYW5pemF0aW9ucywgYW5kIHRoZSBCaWxsIGFuZCBNZWxpbmRhIEdhdGVzIEZvdW5kYXRpb24gKGZvciBzb21lIHJlYXNvbiB0aGV5J3JlIHRoZSBvbmx5IG5vbnByb2ZpdCBkb25vcikgdG8gYWxsIERBQy1lbGlnaWJsZSBjb3VudHJpZXMgKGFuZCBzb21lIG5vbiBub24tREFDLWVsaWdpYmxlIGNvdW50cmllcykuIAoKVGhlIE9FQ0QgdHJhY2tzIGFsbCB0aGlzIGluIGEgY2VudHJhbGl6ZWQgQ3JlZGl0b3IgUmVwb3J0aW5nIFN5c3RlbSBkYXRhYmFzZSBhbmQgcHJvdmlkZXMgYSBuaWNlIGZyb250IGVuZCBmb3IgaXQgYXQgW09FQ0QuU3RhdF0oaHR0cDovL3N0YXRzLm9lY2Qub3JnLykgd2l0aCBhbiBvcGVuIChidXQgaW5zY3J1dGFibGUpIEFQSSAoW3JhdyBDUlMgZGF0YV0oaHR0cDovL3N0YXRzLm9lY2Qub3JnL0Rvd25sb2FkRmlsZXMuYXNweD9IaWRlVG9wTWVudT15ZXMmRGF0YXNldENvZGU9Q1JTMSkgaXMgYWxzbyBhdmFpbGFibGUpLiBUaGVyZSBhcmUgYSBzZXQgb2YgcHJlLWJ1aWx0IHF1ZXJpZXMgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBPREEgZmxvd3MgYnkgZG9ub3IsIHJlY2lwaWVudCwgYW5kIHNlY3RvciAocHVycG9zZSksIGJ1dCB0aGUgcHJlLWJ1aWx0IGRhdGEgc291cmNlcyBkbyBub3QgaW5jbHVkZSBhbGwgZGltZW5zaW9ucyBvZiB0aGUgZGF0YS4gRm9yIGV4YW1wbGUsIFtUYWJsZSBEQUMyYV0oaHR0cDovL3N0YXRzLm9lY2Qub3JnL0luZGV4LmFzcHg/RGF0YVNldENvZGU9VEFCTEUyQSkgaW5jbHVkZXMgY29sdW1ucyBmb3IgZG9ub3IsIHJlY2lwaWVudCwgeWVhciwgYW5kIHRvdGFsIE9EQSAoZS5nLiB0aGUgVVMgZ2F2ZSBcJFggdG8gTmlnZXJpYSBpbiAyMDA4KSAsIGJ1dCBkb2VzIG5vdCBpbmRpY2F0ZSB0aGUgcHVycG9zZS9zZWN0b3IgZm9yIHRoZSBPREEuIFtUYWJsZSBEQUM1XShodHRwOi8vc3RhdHMub2VjZC5vcmcvSW5kZXguYXNweD9EYXRhU2V0Q29kZT1UQUJMRTUpIGluY2x1ZGVzIGNvbHVtbnMgZm9yIHRoZSBkb25vciwgc2VjdG9yLCB5ZWFyLCBhbmQgdG90YWwgT0RBIChlLmcuIHRoZSBVUyBnYXZlIFwkWCBmb3IgZWR1Y2F0aW9uIGluIDIwMDgpLCBidXQgZG9lcyBub3QgaW5jbHVkZSByZWNpcGllbnQgaW5mb3JtYXRpb24uIAoKSW5zdGVhZCBvZiB1c2luZyB0aGVzZSBwcmUtYnVpbHQgcXVlcmllcyBvciBhdHRlbXB0aW5nIHRvIG1hbmlwdWxhdGUgdGhlaXIgcGFyYW1ldGVycywgaXQncyBwb3NzaWJsZSB0byB1c2UgdGhlIFtPRUNEJ3MgUVdJRFMgcXVlcnkgYnVpbGRlcl0oaHR0cHM6Ly9zdGF0cy5vZWNkLm9yZy9xd2lkcy8pIHRvIGNyZWF0ZSBhIGN1c3RvbSBkb3dubG9hZCBvZiBkYXRhLiBIb3dldmVyLCBpdCBpcyBzbG93IGFuZCBjbHVua3kgYW5kIHJlcXVpcmVzIHNpZ25pZmljYW50IG11bmdpbmcgYW5kIGZpbHRlcmluZyBhZnRlciBleHBvcnRpbmcuIAoKVGhlIHNvbHV0aW9uIHRvIGFsbCBvZiB0aGlzIGlzIHRvIHVzZSBbZGF0YSBmcm9tIEFpZERhdGFdKGh0dHA6Ly9haWRkYXRhLm9yZy9haWRkYXRhLXJlc2VhcmNoLXJlbGVhc2VzKSwgd2hpY2ggaW1wb3J0cyByYXcgZGF0YSBmcm9tIHRoZSBPRUNELCBjbGVhbnMgaXQsIHZlcmlmaWVzIGl0LCBhbmQgbWFrZXMgaXQgZnJlZWx5IGF2YWlsYWJsZSBvbiBHaXRIdWIuCgpBaWREYXRhIG9mZmVycyBtdWx0aXBsZSB2ZXJzaW9ucyBvZiB0aGUgZGF0YSwgaW5jbHVkaW5nIGEgZnVsbCByZWxlYXNlLCBhIHRoaW4gcmVsZWFzZSwgYWdncmVnYXRlZCBkb25vci9yZWNpcGllbnQveWVhciBkYXRhLCBhbmQgYWdncmVnYXRlZCBkb25vci9yZWNpcGllbnQveWVhci9wdXJwb3NlIGRhdGEuIEZvciB0aGUgcHVycG9zZXMgb2YgdGhpcyBzdHVkeSwgYWxsIHdlIGNhcmUgYWJvdXQgYXJlIE9EQSBmbG93cyBieSBkb25vciwgcmVjaXBpZW50LCB5ZWFyLCBhbmQgcHVycG9zZSwgd2hpY2ggaXMgb25lIG9mIHRoZSByZWFkeS1tYWRlIGRhdGFzZXRzLiAKCk5vdGFibHksIHRoaXMgYWdncmVnYXRlZCBkYXRhIHNob3dzIHRvdGFsIGFpZCAqY29tbWl0bWVudHMqLCBub3QgYWlkICpkaXNidXJzZW1lbnRzKi4gQm90aCB0eXBlcyBvZiBPREEgaW5mb3JtYXRpb24gYXJlIGF2YWlsYWJsZSBmcm9tIHRoZSBPRUNEIGFuZCBpdCdzIHBvc3NpYmxlIHRvIGdldCB0aGVtIHVzaW5nIE9FQ0QncyByYXcgZGF0YS4gSG93ZXZlciwgW0FpZERhdGEgbm90ZXNdKGh0dHA6Ly9haWRkYXRhLm9yZy9mYXFzLWFib3V0LW91ci1kYXRhKSB0aGF0IGRpc2J1cnNlbWVudCBkYXRhIGlzIHN0aWNreSBhbmQgc2xvd+KAlHByb2plY3RzIHRha2UgYSBsb25nIHRpbWUgdG8gZnVsZmlsbCBhbmQgYWN0dWFsIGluZmxvd3Mgb2YgYWlkIGluIGEgeWVhciBjYW4gYmUgdGllZCB0byBjb21taXRtZW50cyBtYWRlIHllYXJzIGJlZm9yZS4gQmVjYXVzZSB3ZSdyZSBpbnRlcmVzdGVkIGluIGRvbm9yIHJlYWN0aW9ucyB0byByZXN0cmljdGlvbnMgb24gTkdPcywgYW55IHJlYWN0aW9uIHdvdWxkIGJlIHZpc2libGUgaW4gdGhlIGRlY2lzaW9uIHRvIGNvbW1pdCBtb25leSB0byBhaWQsIG5vdCBpbiB0aGUgdWx0aW1hdGUgZGlzYnVyc2VtZW50IG9mIGFpZCwgd2hpY2ggaXMgbW9zdCBsaWtlbHkgYWxyZWFkeSBsZWdhbGx5IG9ibGlnYXRlZCBhbmQgYWxsb2NhdGVkIHRvIHRoZSBjb3VudHJ5IHJlZ2FyZGxlc3Mgb2YgcmVzdHJpY3Rpb25zLgoKU28sIHdlIGxvb2sgYXQgT0RBICpjb21taXRtZW50cyouCgpgYGB7ciBsb2FkLWFpZGRhdGEsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUV9CmFpZGRhdGFfdXJsIDwtICJodHRwczovL2dpdGh1Yi5jb20vQWlkRGF0YS1XTS9wdWJsaWNfZGF0YXNldHMvcmVsZWFzZXMvZG93bmxvYWQvdjMuMS9BaWREYXRhQ29yZV9SZXNlYXJjaFJlbGVhc2VfTGV2ZWwxX3YzLjEuemlwIgphaWRkYXRhX3BhdGggPC0gaGVyZSgiZGF0YSIsICJyYXdfZGF0YSIsICJBaWREYXRhIikKYWlkZGF0YV96aXBfbmFtZSA8LSBiYXNlbmFtZShhaWRkYXRhX3VybCkKYWlkZGF0YV9uYW1lIDwtIHRvb2xzOjpmaWxlX3BhdGhfc2Fuc19leHQoYWlkZGF0YV96aXBfbmFtZSkKCmFpZGRhdGFfZmluYWxfbmFtZSA8LSAiQWlkRGF0YUNvcmVEb25vclJlY2lwaWVudFllYXJQdXJwb3NlX1Jlc2VhcmNoUmVsZWFzZV9MZXZlbDFfdjMuMS5jc3YiCgojIERvd25sb2FkIEFpZERhdGEgZGF0YSBpZiBuZWVkZWQKaWYgKCFmaWxlLmV4aXN0cyhmaWxlLnBhdGgoYWlkZGF0YV9wYXRoLCBhaWRkYXRhX2ZpbmFsX25hbWUpKSkgewogIGFpZGRhdGFfZ2V0IDwtIEdFVChhaWRkYXRhX3VybCwgCiAgICAgICAgICAgICAgICAgICAgIHdyaXRlX2Rpc2soZmlsZS5wYXRoKGFpZGRhdGFfcGF0aCwgYWlkZGF0YV96aXBfbmFtZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcndyaXRlID0gVFJVRSksIAogICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcygpKQogIHVuemlwKGZpbGUucGF0aChhaWRkYXRhX3BhdGgsIGFpZGRhdGFfemlwX25hbWUpLCBleGRpciA9IGFpZGRhdGFfcGF0aCkKICAKICAjIENsZWFuIHVwIHppcCBmaWxlIGFuZCB1bm5lY2Vzc2FyeSBDU1YgZmlsZXMKICBmaWxlLnJlbW92ZShmaWxlLnBhdGgoYWlkZGF0YV9wYXRoLCBhaWRkYXRhX3ppcF9uYW1lKSkKICBsaXN0LmZpbGVzKGFpZGRhdGFfcGF0aCwgcGF0dGVybiA9ICJjc3YiLCBmdWxsLm5hbWVzID0gVFJVRSkgJT4lCiAgICBtYXAofiBpZmVsc2Uoc3RyX2RldGVjdCgueCwgIkRvbm9yUmVjaXBpZW50WWVhclB1cnBvc2UiKSwgMCwKICAgICAgICAgICAgICAgICBmaWxlLnJlbW92ZShmaWxlLnBhdGgoLngpKSkpCn0KCiMgQ2xlYW4gdXAgQWlkRGF0YSBkYXRhCmFpZHJhd19kYXRhIDwtIHJlYWRfY3N2KGZpbGUucGF0aChhaWRkYXRhX3BhdGgsIGFpZGRhdGFfZmluYWxfbmFtZSkpCgphaWRkYXRhX2NsZWFuIDwtIGFpZHJhd19kYXRhICU+JQogICMgR2V0IHJpZCBvZiBub24tY291bnRyeSByZWNpcGllbnRzCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KHJlY2lwaWVudCwKICAgICAgICAgICAgICAgICAgICAgcmVnZXgoInJlZ2lvbmFsfHVuc3BlY2lmaWVkfG11bHRpfHZhbHVlfGdsb2JhbHxjb21taXNzaW9uIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZV9jYXNlID0gVFJVRSkpKSAlPiUKICBmaWx0ZXIoeWVhciA8IDk5OTkpICU+JQogIG11dGF0ZShwdXJwb3NlX2NvZGVfc2hvcnQgPSBhcy5pbnRlZ2VyKHN0cl9zdWIoY29hbGVzY2VkX3B1cnBvc2VfY29kZSwgMSwgMykpKQoKIyBEb25vciwgcmVjaXBpZW50LCBhbmQgcHVycG9zZSBkZXRhaWxzCiMgSSBwdWxsZWQgdGhlc2UgY291bnRyeSBuYW1lcyBvdXQgb2YgdGhlIGRyb3Bkb3duIG1lbnUgYXQgT0VDRC5TdGF0IFRhYmxlIDJhCiMgb25saW5lOiBodHRwczovL3N0YXRzLm9lY2Qub3JnL0luZGV4LmFzcHg/RGF0YVNldENvZGU9VGFibGUyQQpkYWNfZG9ub3JzIDwtIGMoIkF1c3RyYWxpYSIsICJBdXN0cmlhIiwgIkJlbGdpdW0iLCAiQ2FuYWRhIiwgIkN6ZWNoIFJlcHVibGljIiwKICAgICAgICAgICAgICAgICJEZW5tYXJrIiwgIkZpbmxhbmQiLCAiRnJhbmNlIiwgIkdlcm1hbnkiLCAiR3JlZWNlIiwgIkljZWxhbmQiLAogICAgICAgICAgICAgICAgIklyZWxhbmQiLCAiSXRhbHkiLCAiSmFwYW4iLCAiS29yZWEiLCAiTHV4ZW1ib3VyZyIsICJOZXRoZXJsYW5kcyIsCiAgICAgICAgICAgICAgICAiTmV3IFplYWxhbmQiLCAiTm9yd2F5IiwgIlBvbGFuZCIsICJQb3J0dWdhbCIsICJTbG92YWsgUmVwdWJsaWMiLAogICAgICAgICAgICAgICAgIlNsb3ZlbmlhIiwgIlNwYWluIiwgIlN3ZWRlbiIsICJTd2l0emVybGFuZCIsICJVbml0ZWQgS2luZ2RvbSIsCiAgICAgICAgICAgICAgICAiVW5pdGVkIFN0YXRlcyIpCgpub25fZGFjX2Rvbm9ycyA8LSBjKCJCdWxnYXJpYSIsICJDcm9hdGlhIiwgIkN5cHJ1cyIsICJFc3RvbmlhIiwgIkh1bmdhcnkiLAogICAgICAgICAgICAgICAgICAgICJJc3JhZWwiLCAiS2F6YWtoc3RhbiIsICJLdXdhaXQiLCAiTGF0dmlhIiwgIkxpZWNodGVuc3RlaW4iLAogICAgICAgICAgICAgICAgICAgICJMaXRodWFuaWEiLCAiTWFsdGEiLCAiUm9tYW5pYSIsICJSdXNzaWEiLCAiU2F1ZGkgQXJhYmlhIiwKICAgICAgICAgICAgICAgICAgICAiQ2hpbmVzZSBUYWlwZWkiLCAiVGhhaWxhbmQiLCAiVGltb3IgTGVzdGUiLCAiVHVya2V5IiwKICAgICAgICAgICAgICAgICAgICAiVW5pdGVkIEFyYWIgRW1pcmF0ZXMiKQoKb3RoZXJfY291bnRyaWVzIDwtIGMoIkJyYXppbCIsICJDaGlsZSIsICJDb2xvbWJpYSIsICJJbmRpYSIsICJNb25hY28iLCAiUWF0YXIiLAogICAgICAgICAgICAgICAgICAgICAiU291dGggQWZyaWNhIiwgIlRhaXdhbiIpCgpkb25vcnNfYWxsIDwtIGFpZGRhdGFfY2xlYW4gJT4lCiAgZGlzdGluY3QoZG9ub3IpICU+JQogIG11dGF0ZShkb25vcl90eXBlID0gY2FzZV93aGVuKAogICAgZG9ub3IgJWluJSBjKGRhY19kb25vcnMsIG5vbl9kYWNfZG9ub3JzLCBvdGhlcl9jb3VudHJpZXMpIH4gIkNvdW50cnkiLAogICAgZG9ub3IgPT0gIkJpbGwgJiBNZWxpbmRhIEdhdGVzIEZvdW5kYXRpb24iIH4gIlByaXZhdGUgZG9ub3IiLAogICAgVFJVRSB+ICJNdWx0aWxhdGVyYWwgb3IgSUdPIgogICkpCgpkb25vcl9jb3VudHJpZXMgPC0gZG9ub3JzX2FsbCAlPiUgCiAgZmlsdGVyKGRvbm9yX3R5cGUgPT0gIkNvdW50cnkiKSAlPiUgCiAgbXV0YXRlKGRvbm9yX2d3Y29kZSA9IGNvdW50cnljb2RlKGRvbm9yLCAiY291bnRyeS5uYW1lIiwgImd3biIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoIkxpZWNodGVuc3RlaW4iID0gMjIzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNb25hY28iID0gMjIxKSksCiAgICAgICAgIGRvbm9yX2lzbzMgPSBjb3VudHJ5Y29kZShkb25vciwgImNvdW50cnkubmFtZSIsICJpc28zYyIpKQoKZG9ub3JzIDwtIGJpbmRfcm93cyhmaWx0ZXIoZG9ub3JzX2FsbCwgZG9ub3JfdHlwZSAhPSAiQ291bnRyeSIpLAogICAgICAgICAgICAgICAgICAgIGRvbm9yX2NvdW50cmllcykKCnJlY2lwaWVudHMgPC0gYWlkZGF0YV9jbGVhbiAlPiUKICBkaXN0aW5jdChyZWNpcGllbnQpICU+JQogIG11dGF0ZShpc28zID0gY291bnRyeWNvZGUocmVjaXBpZW50LCAiY291bnRyeS5uYW1lIiwgImlzbzNjIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoYEtvcmVhLCBEZW1vY3JhdGljIFJlcHVibGljIG9mYCA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTmV0aGVybGFuZHMgQW50aWxsZXNgID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEtvc292byA9ICJYS0siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgU2VyYmlhIGFuZCBNb250ZW5lZ3JvYCA9ICJTQ0ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZdWdvc2xhdmlhID0gIllVRyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkpICU+JSAKICBmaWx0ZXIoaXNvMyAlaW4lIHVuaXF1ZShwYW5lbF9za2VsZXRvbiRpc28zKSkgJT4lCiAgbXV0YXRlKGd3Y29kZSA9IGNvdW50cnljb2RlKGlzbzMsICJpc28zYyIsICJnd24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKFhLSyA9IDM0NywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZRU0gPSA2NzgpKSkKCiMgUHVycG9zZXMKcHVycG9zZXMgPC0gYWlkZGF0YV9jbGVhbiAlPiUKICBjb3VudChjb2FsZXNjZWRfcHVycG9zZV9uYW1lLCBjb2FsZXNjZWRfcHVycG9zZV9jb2RlKQoKIyBDdXJyZW50IGxpc3QgaXMgYXQgaHR0cHM6Ly93ZWJmcy5vZWNkLm9yZy9jcnMtaWF0aS14bWwvTG9va3VwL0RBQy1DUlMtQ09ERVMueG1sCiMgYnV0IHRoZSBYTUwgc3RydWN0dXJlIGhhcyBjaGFuZ2VkIGFuZCBpdCdzIHRyaWNraWVyIHRvIGlkZW50aWZ5IGFsbCB0aGUgY29kZXMKIyBzeXN0ZW1hdGljYWxseSBub3cKIyBTbyBpbnN0ZWFkIHdlIHVzZSBhIHZlcnNpb24gZnJvbSAyMDE2CnB1cnBvc2VzX3VybCA8LSAiaHR0cHM6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMTYwODE5MTIzNTM1L2h0dHBzOi8vd3d3Lm9lY2Qub3JnL2RhYy9zdGF0cy9kb2N1bWVudHVwbG9hZC9EQUNfY29kZUxpc3RzLnhtbCIKcHVycG9zZXNfcGF0aCA8LSBoZXJlKCJkYXRhIiwgInJhd19kYXRhIiwgIkRBQyBDUlMgY29kZXMiKQpwdXJwb3Nlc19uYW1lIDwtICJEQUNfY29kZUxpc3RzLnhtbCIKCiMgRG93bmxvYWQgREFDIENSUyBjb2RlcyBpZiBuZWVkZWQKaWYgKCFmaWxlLmV4aXN0cyhmaWxlLnBhdGgocHVycG9zZXNfcGF0aCwgcHVycG9zZXNfbmFtZSkpKSB7CiAgcHVycG9zZXNfZ2V0IDwtIEdFVChwdXJwb3Nlc191cmwsIAogICAgICAgICAgICAgICAgICAgICAgd3JpdGVfZGlzayhmaWxlLnBhdGgocHVycG9zZXNfcGF0aCwgcHVycG9zZXNfbmFtZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpLCAKICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzKCkpCn0KCnB1cnBvc2Vfbm9kZXMgPC0gcmVhZF94bWwoZmlsZS5wYXRoKHB1cnBvc2VzX3BhdGgsIHB1cnBvc2VzX25hbWUpKSAlPiUKICB4bWxfZmluZF9hbGwoIi8vY29kZWxpc3QtaXRlbSIpCgpwdXJwb3NlX2NvZGVzIDwtIHRpYmJsZSgKICBjb2RlID0gcHVycG9zZV9ub2RlcyAlPiUgeG1sX2ZpbmRfZmlyc3QoIi4vL2NvZGUiKSAlPiUgeG1sX3RleHQoKSwKICBjYXRlZ29yeSA9IHB1cnBvc2Vfbm9kZXMgJT4lIHhtbF9maW5kX2ZpcnN0KCIuLy9jYXRlZ29yeSIpICU+JSB4bWxfdGV4dCgpLAogICMgbmFtZSA9IHB1cnBvc2Vfbm9kZXMgJT4lIHhtbF9maW5kX2ZpcnN0KCIuLy9uYW1lLy9uYXJyYXRpdmUiKSAlPiUgeG1sX3RleHQoKSwKICBuYW1lID0gcHVycG9zZV9ub2RlcyAlPiUgeG1sX2ZpbmRfZmlyc3QoIi4vL25hbWUiKSAlPiUgeG1sX3RleHQoKSwKICAjIGRlc2NyaXB0aW9uID0gcHVycG9zZV9ub2RlcyAlPiUgeG1sX2ZpbmRfZmlyc3QoIi4vL2Rlc2NyaXB0aW9uLy9uYXJyYXRpdmUiKSAlPiUgeG1sX3RleHQoKQogIGRlc2NyaXB0aW9uID0gcHVycG9zZV9ub2RlcyAlPiUgeG1sX2ZpbmRfZmlyc3QoIi4vL2Rlc2NyaXB0aW9uIikgJT4lIHhtbF90ZXh0KCkKKQoKIyBFeHRyYWN0IHRoZSBnZW5lcmFsIGNhdGVnb3JpZXMgb2YgYWlkIHB1cnBvc2VzIChpLmUuIHRoZSBmaXJzdCB0aHJlZSBkaWdpdHMgb2YgdGhlIHB1cnBvc2UgY29kZXMpCmdlbmVyYWxfY29kZXMgPC0gcHVycG9zZV9jb2RlcyAlPiUKICBmaWx0ZXIoY29kZSAlaW4lIGFzLmNoYXJhY3RlcigxMDA6MTAwMCkgJiBzdHJfZGV0ZWN0KG5hbWUsICJeXFxkIikpICU+JQogIG11dGF0ZShjb2RlID0gYXMuaW50ZWdlcihjb2RlKSkgJT4lCiAgc2VsZWN0KHB1cnBvc2VfY29kZV9zaG9ydCA9IGNvZGUsIHB1cnBvc2VfY2F0ZWdvcnlfbmFtZSA9IG5hbWUpICU+JQogIG11dGF0ZShwdXJwb3NlX2NhdGVnb3J5X2NsZWFuID0gc3RyX3JlcGxhY2UocHVycG9zZV9jYXRlZ29yeV9uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxcZFxcLlxcZCAiLCAiIikpICU+JQogIHNlcGFyYXRlKHB1cnBvc2VfY2F0ZWdvcnlfY2xlYW4sCiAgICAgICAgICAgaW50byA9IGMoInB1cnBvc2Vfc2VjdG9yIiwgInB1cnBvc2VfY2F0ZWdvcnkiKSwgCiAgICAgICAgICAgc2VwID0gIiwgIikgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKHB1cnBvc2Vfc2VjdG9yLCBwdXJwb3NlX2NhdGVnb3J5KSwgfnN0cl90b190aXRsZSguKSkpICU+JQogIHNlbGVjdCgtcHVycG9zZV9jYXRlZ29yeV9uYW1lKQoKIyBUaGVzZSA3IGNvZGVzIGFyZSB3ZWlyZCBhbmQgZ2V0IGZpbHRlcmVkIG91dCBpbmFkdmVydGVudGx5CmNvZGVzX25vdF9pbl9vZWNkX2xpc3QgPC0gdHJpYmJsZSgKICB+cHVycG9zZV9jb2RlX3Nob3J0LCB+cHVycG9zZV9zZWN0b3IsIH5wdXJwb3NlX2NhdGVnb3J5LAogIDEwMCwgICAgICAgICAgICAgICAgICJTb2NpYWwiLCAgICAgICAgIlNvY2lhbCBJbmZyYXN0cnVjdHVyZSIsCiAgMjAwLCAgICAgICAgICAgICAgICAgIkVjbyIsICAgICAgICAgICAiRWNvbm9taWMgSW5mcmFzdHJ1Y3R1cmUiLAogIDMwMCwgICAgICAgICAgICAgICAgICJQcm9kIiwgICAgICAgICAgIlByb2R1Y3Rpb24iLAogIDMxMCwgICAgICAgICAgICAgICAgICJQcm9kIiwgICAgICAgICAgIkFncmljdWx0dXJlIiwKICAzMjAsICAgICAgICAgICAgICAgICAiUHJvZCIsICAgICAgICAgICJJbmR1c3RyeSIsCiAgNDIwLCAgICAgICAgICAgICAgICAgIk11bHRpc2VjdG9yIiwgICAiV29tZW4gaW4gZGV2ZWxvcG1lbnQiLAogICMgTkI6IFRoaXMgYWN0dWFsbHkgaXMgc3BsaXQgYmV0d2VlbiA5MjAxMCAoZG9tZXN0aWMgTkdPcyksIDkyMDIwCiAgIyAoaW50ZXJuYXRpb25hbCBOR09zKSwgYW5kIDkyMDMwIChsb2NhbCBhbmQgcmVnaW9uYWwgTkdPcykKICA5MjAsICAgICAgICAgICAgICAgICAiTm9uIFNlY3RvciIsICAgICJTdXBwb3J0IHRvIE5HT3MiCikKCnB1cnBvc2VfY29kZXNfY2xlYW4gPC0gZ2VuZXJhbF9jb2RlcyAlPiUKICBiaW5kX3Jvd3MoY29kZXNfbm90X2luX29lY2RfbGlzdCkgJT4lCiAgYXJyYW5nZShwdXJwb3NlX2NvZGVfc2hvcnQpICU+JQogIG11dGF0ZShwdXJwb3NlX2NvbnRlbnRpb3VzbmVzcyA9ICIiKQoKIyBNYW51YWxseSBjb2RlIGNvbnRlbnRpb3VzbmVzcyBvZiBwdXJwb3Nlcwp3cml0ZV9jc3YocHVycG9zZV9jb2Rlc19jbGVhbiwKICAgICAgICAgIGhlcmUoImRhdGEiLCAibWFudWFsX2RhdGEiLAogICAgICAgICAgICAgICAicHVycG9zZV9jb2Rlc19jb250ZW50aW9uX1dJTExfQkVfT1ZFUldSSVRURU4uY3N2IikpCgpwdXJwb3NlX2NvZGVzX2NvbnRlbnRpb3VzbmVzcyA8LSByZWFkX2NzdihoZXJlKCJkYXRhIiwgIm1hbnVhbF9kYXRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicHVycG9zZV9jb2Rlc19jb250ZW50aW9uLmNzdiIpKQoKYWlkZGF0YV9maW5hbCA8LSBhaWRkYXRhX2NsZWFuICU+JQogIGxlZnRfam9pbihkb25vcnMsIGJ5ID0gImRvbm9yIikgJT4lCiAgbGVmdF9qb2luKHJlY2lwaWVudHMsIGJ5ID0gInJlY2lwaWVudCIpICU+JQogIGxlZnRfam9pbihwdXJwb3NlX2NvZGVzX2NvbnRlbnRpb3VzbmVzcywgYnkgPSAicHVycG9zZV9jb2RlX3Nob3J0IikgJT4lCiAgbXV0YXRlKGRvbm9yX3R5cGVfY29sbGFwc2VkID0gaWZlbHNlKGRvbm9yX3R5cGUgPT0gIkNvdW50cnkiLCAiQ291bnRyeSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJR08sIE11bHRpbGF0ZXJhbCwgb3IgUHJpdmF0ZSIpKSAlPiUKICBzZWxlY3QoZG9ub3IsIGRvbm9yX3R5cGUsIGRvbm9yX3R5cGVfY29sbGFwc2VkLAogICAgICAgICBkb25vcl9nd2NvZGUsIGRvbm9yX2lzbzMsIHllYXIsIGd3Y29kZSwgaXNvMywKICAgICAgICAgb2RhID0gY29tbWl0bWVudF9hbW91bnRfdXNkX2NvbnN0YW50X3N1bSwKICAgICAgICAgcHVycG9zZV9jb2RlX3Nob3J0LCBwdXJwb3NlX3NlY3RvciwgcHVycG9zZV9jYXRlZ29yeSwKICAgICAgICAgcHVycG9zZV9jb250ZW50aW91c25lc3MsCiAgICAgICAgIGNvYWxlc2NlZF9wdXJwb3NlX2NvZGUsIGNvYWxlc2NlZF9wdXJwb3NlX25hbWUpICU+JQogIGFycmFuZ2UoZ3djb2RlLCB5ZWFyKQoKZXZlcl9kYWNfZWxpZ2libGUgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsICJtYW51YWxfZGF0YSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvZWNkX2RhY19jb3VudHJpZXMuY3N2IikpICU+JQogICMgSWdub3JlIEhpZ2ggSW5jb21lIENvdW50cmllcyBhbmQgTW9yZSBBZHZhbmNlZCBEZXZlbG9waW5nIENvdW50cmllcwogIGZpbHRlcighKGRhY19hYmJyICVpbiUgYygiSElDIiwgIkFEQyIpKSkgJT4lCiAgIyBJZ25vcmUgY291bnRyaWVzIHRoYXQgYXJlbid0IGluIG91ciBza2VsZXRvbiBwYW5lbAogIGZpbHRlcihpc28zICVpbiUgcGFuZWxfc2tlbGV0b24kaXNvMykgJT4lIAogIG11dGF0ZShnd2NvZGUgPSBjb3VudHJ5Y29kZShpc28zLCAiaXNvM2MiLCAiZ3duIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYygiWUVNIiA9IDY3OCkpKSAlPiUgCiAgcHVsbChnd2NvZGUpICU+JSB1bmlxdWUoKQpgYGAKCiMjIyBMaXN0IG9mIGRvbm9ycwoKYGBge3Igc2hvdy1kb25vcnN9CmRvbm9ycyAlPiUgZGF0YXRhYmxlKCkKYGBgCgojIyMgTGlzdCBvZiByZWNpcGllbnRzCgpgYGB7ciBzaG93LXJlY2lwaWVudHN9CnNlbGVjdChyZWNpcGllbnRzLCByZWNpcGllbnQpICU+JSBkYXRhdGFibGUoKQpgYGAKCiMjIyBMaXN0IG9mIHB1cnBvc2VzCgpgYGB7ciBzaG93LXB1cnBvc2VzfQphcnJhbmdlKHB1cnBvc2VzLCBkZXNjKG4pKSAlPiUgZGF0YXRhYmxlKCkKYGBgCgojIyMgU3VtbWFyeSBvZiBjbGVhbiBkYXRhCgpgYGB7ciBhaWRkYXRhLXN1bW1hcnl9CmFpZGRhdGFfZmluYWwgJT4lIGdsaW1wc2UoKQpgYGAKCgojIyBVU0FJRCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KClVTQUlEIHByb3ZpZGVzIHRoZSBjb21wbGV0ZSBkYXRhc2V0IGZvciBpdHMgW0ZvcmVpZ24gQWlkIEV4cGxvcmVyXShodHRwczovL2V4cGxvcmVyLnVzYWlkLmdvdi9haWQtZGFzaGJvYXJkLmh0bWwpIGFzIGEgW2dpYW50IENTViBmaWxlXShodHRwczovL2V4cGxvcmVyLnVzYWlkLmdvdi9kYXRhLmh0bWwpLiBUaGUgZGF0YSBpbmNsdWRlcyBib3RoIGVjb25vbWljIGFuZCBtaWxpdGFyeSBhaWQsIGJ1dCBpdCdzIGVhc3kgdG8gZmlsdGVyIG91dCB0aGUgbWlsaXRhcnkgYWlkLiBIZXJlIHdlIG9ubHkgbG9vayBhdCBvYmxpZ2F0aW9ucywgbm90IGRpc2J1cnNlbWVudHMsIHNvIHRoYXQgdGhlIGRhdGEgaXMgY29tcGFyYWJsZSB0byB0aGUgT0VDRCBkYXRhIGZyb20gQWlkRGF0YS4gVGhlIGRhdGEgd2UgZG93bmxvYWRlZCBwcm92aWRlcyBjb25zdGFudCBhbW91bnRzIGluIDIwMTUgZG9sbGFyczsgd2UgcmVzY2FsZSB0aGF0IHRvIDIwMTEgdG8gbWF0Y2ggYWxsIG90aGVyIHZhcmlhYmxlcy4gCgpgYGB7ciBsb2FkLXVzYWlkLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQp1c2FpZF91cmwgPC0gImh0dHBzOi8vZXhwbG9yZXIudXNhaWQuZ292L3ByZXBhcmVkL3VzX2ZvcmVpZ25fYWlkX2NvbXBsZXRlLmNzdiIKdXNhaWRfcGF0aCA8LSBoZXJlKCJkYXRhIiwgInJhd19kYXRhIiwgIlVTQUlEIikKdXNhaWRfbmFtZSA8LSBiYXNlbmFtZSh1c2FpZF91cmwpCgojIERvd25sb2FkIFVTQUlEIGRhdGEgaWYgbmVlZGVkCmlmICghZmlsZS5leGlzdHMoZmlsZS5wYXRoKHVzYWlkX3BhdGgsIHVzYWlkX25hbWUpKSkgewogIHVzYWlkX2dldCA8LSBHRVQodXNhaWRfdXJsLCAKICAgICAgICAgICAgICAgICAgIHdyaXRlX2Rpc2soZmlsZS5wYXRoKHVzYWlkX3BhdGgsIHVzYWlkX25hbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFKSwgCiAgICAgICAgICAgICAgICAgICBwcm9ncmVzcygpKQp9CgojIENsZWFuIHVwIFVTQUlEIGRhdGEKdXNhaWRfcmF3IDwtIHJlYWRfY3N2KGZpbGUucGF0aCh1c2FpZF9wYXRoLCB1c2FpZF9uYW1lKSwKICAgICAgICAgICAgICAgICAgICAgIG5hID0gYygiIiwgIk5BIiwgIk5VTEwiKSkKCnVzYWlkX2NsZWFuIDwtIHVzYWlkX3JhdyAlPiUKICBmaWx0ZXIoYXNzaXN0YW5jZV9jYXRlZ29yeV9uYW1lID09ICJFY29ub21pYyIpICU+JQogIGZpbHRlcih0cmFuc2FjdGlvbl90eXBlX25hbWUgPT0gIk9ibGlnYXRpb25zIikgJT4lCiAgbXV0YXRlKGNvdW50cnlfY29kZSA9IHJlY29kZShjb3VudHJ5X2NvZGUsIGBDUy1LTWAgPSAiWEtLIikpICU+JQogICMgUmVtb3ZlIHJlZ2lvbnMgYW5kIFdvcmxkCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KGNvdW50cnlfbmFtZSwgIlJlZ2lvbiIpKSAlPiUKICBmaWx0ZXIoIShjb3VudHJ5X25hbWUgJWluJSBjKCJXb3JsZCIpKSkgJT4lCiAgIyBJZ25vcmUgY291bnRyaWVzIHRoYXQgYXJlbid0IGluIG91ciBza2VsZXRvbiBwYW5lbAogIGZpbHRlcihjb3VudHJ5X2NvZGUgJWluJSBwYW5lbF9za2VsZXRvbiRpc28zKSAlPiUgCiAgbXV0YXRlKGd3Y29kZSA9IGNvdW50cnljb2RlKGNvdW50cnlfY29kZSwgImlzbzNjIiwgImd3biIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoIllFTSIgPSA2NzgsICJYS0siID0gMzQ3KSkpICU+JQogIHNlbGVjdChnd2NvZGUsIHllYXIgPSBmaXNjYWxfeWVhciwgCiAgICAgICAgIGltcGxlbWVudGluZ19hZ2VuY3lfbmFtZSwgc3ViYWdlbmN5X25hbWUsIGFjdGl2aXR5X25hbWUsCiAgICAgICAgIGNoYW5uZWxfY2F0ZWdvcnlfbmFtZSwgY2hhbm5lbF9zdWJjYXRlZ29yeV9uYW1lLCBkYWNfc2VjdG9yX2NvZGUsCiAgICAgICAgIG9kYV91c19jdXJyZW50ID0gY3VycmVudF9hbW91bnQsIG9kYV91c18yMDE1ID0gY29uc3RhbnRfYW1vdW50KSAlPiUKICBtdXRhdGUoYWlkX2RlZmxhdG9yID0gb2RhX3VzX2N1cnJlbnQgLyBvZGFfdXNfMjAxNSAqIDEwMCkgJT4lCiAgbXV0YXRlKGNoYW5uZWxfbmdvX3VzID0gY2hhbm5lbF9zdWJjYXRlZ29yeV9uYW1lID09ICJOR08gLSBVbml0ZWQgU3RhdGVzIiwKICAgICAgICAgY2hhbm5lbF9uZ29faW50ID0gY2hhbm5lbF9zdWJjYXRlZ29yeV9uYW1lID09ICJOR08gLSBJbnRlcm5hdGlvbmFsIiwKICAgICAgICAgY2hhbm5lbF9uZ29fZG9tID0gY2hhbm5lbF9zdWJjYXRlZ29yeV9uYW1lID09ICJOR08gLSBOb24gVW5pdGVkIFN0YXRlcyIpCgojIEdldCByaWQgb2YgdGhpcyBiZWNhdXNlIGl0J3MgaHVnZSBhbmQgdGFraW5nIHVwIGxvdHMgb2YgbWVtb3J5CnJtKHVzYWlkX3JhdykKYGBgCgojIyMgSW1wbGVtZW50aW5nIGFnZW5jaWVzCgpIZXJlIGFyZSB0aGUgVVMgZ292ZXJubWVudCBhZ2VuY2llcyBnaXZpbmcgb3V0IG1vbmV5OgoKYGBge3Igc2hvdy1hZ2VuY2llc30KaW1wbGVtZW50aW5nX2FnZW5jaWVzIDwtIHVzYWlkX2NsZWFuICU+JQogIGNvdW50KGltcGxlbWVudGluZ19hZ2VuY3lfbmFtZSwgc3ViYWdlbmN5X25hbWUpICU+JQogIGFycmFuZ2UoZGVzYyhuKSwgaW1wbGVtZW50aW5nX2FnZW5jeV9uYW1lKQoKaW1wbGVtZW50aW5nX2FnZW5jaWVzICU+JSBkYXRhdGFibGUoKQpgYGAKCiMjIyBBY3Rpdml0aWVzCgpUaGUgYWN0aXZpdGllcyBsaXN0ZWQgZG9uJ3QgZm9sbG93IGFueSBzdGFuZGFyZCBjb2RpbmcgZ3VpZGVsaW5lcy4gVGhlcmUgYXJlIHRlbnMgb2YgdGhvdXNhbmRzIG9mIHRoZW0uIEhlcmUgYXJlIHRoZSBmaXJzdCAxMDAsIGp1c3QgZm9yIHJlZmVyZW5jZToKCmBgYHtyIHNob3ctYWN0aXZpdGllc30KYWN0aXZpdGllcyA8LSB1c2FpZF9jbGVhbiAlPiUKICBjb3VudChhY3Rpdml0eV9uYW1lKSAlPiUKICBzbGljZSgxOjEwMCkKCmFjdGl2aXRpZXMgJT4lIGRhdGF0YWJsZSgpCmBgYAoKIyMjIENoYW5uZWxzCgpVU0FJRCBkaXN0aW5ndWlzaGVzIGJldHdlZW4gZG9tZXN0aWMsIGZvcmVpZ24sIGFuZCBpbnRlcm5hdGlvbmFsIE5HT3MsIGNvbXBhbmllcywgbXVsdGlsYXRlcmFsIG9yZ2FuaXphdGlvbnMsIGV0Yy4gcmVjaXBpZW50cyAob3IgY2hhbm5lbHMpIG9mIG1vbmV5OgoKYGBge3Igc2hvdy1jaGFubmVsc30KY2hhbm5lbHMgPC0gdXNhaWRfY2xlYW4gJT4lCiAgY291bnQoY2hhbm5lbF9jYXRlZ29yeV9uYW1lLCBjaGFubmVsX3N1YmNhdGVnb3J5X25hbWUpICU+JQogIGZpbHRlcighaXMubmEoY2hhbm5lbF9jYXRlZ29yeV9uYW1lKSkKCmNoYW5uZWxzICU+JSBkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDIwKSkKYGBgCgojIyMgU3VtbWFyeSBvZiBjbGVhbiBkYXRhCgpgYGB7ciB1c2FpZC1zdW1tYXJ5fQp1c2FpZF9jbGVhbiAlPiUgZ2xpbXBzZSgpCmBgYAoKCiMgTkdPIHJlZ3VsYXRpb25zCgojIyBDaGF1ZGhyeSBsYXdzCgpgYGB7ciBjbGVhbi1kY2p3LW5hbWVzfQpkY2p3X3F1ZXN0aW9uc19yYXcgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsICJtYW51YWxfZGF0YSIsICJkY2p3X3F1ZXN0aW9ucy5jc3YiKSkKCmRjandfYmFycmllcnNfY2xlYW4gPC0gZGNqd19xdWVzdGlvbnNfcmF3ICU+JQogIGRpc3RpbmN0KHF1ZXN0aW9uX2NhdCwgYmFycmllcikKCmRjandfYmFycmllcnNfaWdub3JlIDwtIGRjandfcXVlc3Rpb25zX3JhdyAlPiUKICBzZWxlY3QocXVlc3Rpb24sIGlnbm9yZV9pbl9pbmRleCkKYGBgCgpgYGB7ciBsb2FkLW9yaWdpbmFsLWRjancsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgT3JpZ2luYWwgRENKVyBkYXRhCmRjandfb3JpZyA8LSByZWFkX2V4Y2VsKGhlcmUoImRhdGEiLCAicmF3X2RhdGEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRENKVyBOR08gbGF3cyIsICJEQ0pXX05HT19MYXdzLnhsc3giKSkgJT4lIAogIHNlbGVjdCgtYyhjb250YWlucygic291cmNlIiksIGNvbnRhaW5zKCJidXJkZW4iKSwgCiAgICAgICAgICAgIGNvbnRhaW5zKCJzdWJzZXQiKSwgQ29kZXIsIERhdGUpKQpkY2p3X29yaWdfbiA8LSBucm93KGRjandfb3JpZykKYGBgCgpJbiAyMDEzLCBEYXJpbiBDaHJpc3RlbnNlbiBhbmQgSmVyZW15IFdlaW5zdGVpbiBjb2xsZWN0ZWQgW2RldGFpbGVkIGRhdGFdKGh0dHBzOi8vZGFyaW5jaHJpc3RlbnNlbi5jb20vcHVibGljYXRpb24vZGVmdW5kaW5nLWRpc3NlbnQvKSBvbiBOR08gcmVndWxhdGlvbnMgZm9yIFt0aGVpciAqSm91cm5hbCBvZiBEZW1vY3JhY3kqIGFydGljbGVdKGh0dHA6Ly93d3cuam91cm5hbG9mZGVtb2NyYWN5Lm9yZy9hcnRpY2xlL2RlZnVuZGluZy1kaXNzZW50LXJlc3RyaWN0aW9ucy1haWQtbmdvcyksIGNvdmVyaW5nIGByIGRjandfb3JpZ19uYCBjb3VudHJpZXMuCgpTdXBhcm5hIENoYXVkaHJ5IGV4cGFuZGVkIHRoaXMgZGF0YSBzdWJzdGFudGlhbGx5IChpdCBub3cgY292ZXJzIGByIGNoYXVkaHJ5X3JhdyAlPiUgZGlzdGluY3QoZ3djb2RlKSAlPiUgbnJvdygpYCBjb3VudHJpZXMgYW5kIGdvZXMgdG8gMjAxMyksIHNvIHdlIHVzZSB0aGF0LgoKIyMjIE5vdGVzIG9uIHllYXIgY292ZXJhZ2UKCkluIG91ciBvcmlnaW5hbCBwYXBlciBmcm9tIDIwMTcsIHdlIHVzZWQgU3VwYXJuYSdzIGRhdGEgYW5kIGJhY2tmaWxsZWQgaXQgdG8gMTk4MCwgc2luY2UgZ29pbmcgYmFjayBpbiB0aW1lIGlzIHBvc3NpYmxlIHdpdGggdGhlIERDSlcgZGF0YeKAlGxvdHMgb2YgdGhlIGVudHJpZXMgaW4gRENKVyBpbmNsdWRlIHN0YXJ0IGRhdGVzIG9mIGxpa2UgMTk1MCBvciAxOTcwLiBBY2NvcmRpbmdseSwgb3VyIGFuYWx5c2lzIHJhbmdlZCBmcm9tIDE5ODAtMjAxMy4gSG93ZXZlciwgbm90IGFsbCBvZiBTdXBhcm5hJ3MgZXhwYW5kZWQgY291bnRyaWVzIHdoZW4gYmFjayBpbiB0aW1lIHRoYXQgZmFyLCBhbmQgc2hlIGZvY3VzZWQgcHJpbWFyaWx5IG9uIDE5OTArIGNoYW5nZXMuIEFkZGl0aW9uYWxseeKAlGFuZCBtb3JlIGltcG9ydGFudGx54oCUdGhlIHdob2xlIG5hdHVyZSBvZiBmb3JlaWduIGFpZCBhbmQgY2l2aWwgc29jaWV0eSBjaGFuZ2VkIGRyYXN0aWNhbGx5IGFmdGVyIHRoZSBDb2xkIFdhci4gQ2l2aWwgc29jaWV0eSByZWd1bGF0aW9ucyB3ZXJlbid0IHJlYWxseSB1c2VkIGFzIGEgcG9saXRpY2FsIHN0cmF0ZWd5IHVudGlsIGFmdGVyIDE5OTAuIFdlIGNhbiBjb25maXJtIHRoYXQgYnkgcGxvdHRpbmcgVi1EZW0ncyBjb3JlIGNpdmlsIHNvY2lldHkgaW5kZXg6CgpgYGB7ciB2ZGVtLWNpdmlsLXNvY2lldHktaW5kZXh9CnZkZW1fcmF3ICU+JSAKICBmaWx0ZXIoeWVhciA+PSAxOTgwKSAlPiUgCiAgc2VsZWN0KHllYXIsIHYyeGNzX2Njc2kpICU+JSAKICBncm91cF9ieSh5ZWFyKSAlPiUgCiAgc3VtbWFyaXplKGF2Z19jY3NpID0gbWVhbih2Mnhjc19jY3NpKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBhdmdfY2NzaSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMTk5MCwgY29sb3IgPSAicmVkIikgKwogIGxhYnMoeCA9ICJZZWFyIiwgeSA9ICJBdmVyYWdlIENvcmUgQ2l2aWwgU29jaWV0eSBJbmRleCIsIAogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IFYtRGVtJ3MgdjJ4Y3NfY2NzaSIpCmBgYAoKU29tZXRoaW5nIHN5c3RlbWF0aWMgaGFwcGVuZWQgdG8gY2l2aWwgc29jaWV0eSByZWd1bGF0aW9ucyB3b3JsZHdpZGUgaW4gMTk5MCwgYW5kIHJhdGhlciB0aGFuIHRyeSB0byBtb2RlbCBwcmUtQ29sZCBXYXIgcmVndWxhdGlvbnMsIHdoaWNoIHdlcmUgY29ubmVjdGVkIHRvIGZvcmVpZ24gYWlkIGluIGNvbXBsZXRlbHkgZGlmZmVyZW50IHdheXMgdGhhbiB0aGV5IHdlcmUgYWZ0ZXIgdGhlIGRpc3NvbHV0aW9uIG9mIHRoZSBVU1NSLCB3ZSBsaW1pdCBvdXIgYW5hbHlzaXMgdG8gMTk5MCsKCldlIHN0aWxsIGNvbGxlY3QgYXMgbXVjaCBwcmUtMTk5MCBkYXRhIGFzIHBvc3NpYmxlIGZvciB0aGUgc2FrZSBvZiAoMSkgbGFnZ2luZywgc28gd2UgY2FuIGdldCBsYWdnZWQgdmFsdWVzIGZyb20gMTk4OSBhbmQgMTk4OCB3aGVuIGxvb2tpbmcgYXQgbGFnZ2VkIHZhcmlhYmxlcyBpbiAxOTkwLCBhbmQgKDIpIHJvYnVzdG5lc3MgY2hlY2tzIHRoYXQgd2UgcnVuIHVzaW5nIHRoZSA5OCBiYWNrZmlsbGVkIERDSlcgY291bnRyaWVzCgojIyMgSW5kZXggY3JlYXRpb24KCldlIGNyZWF0ZSBzZXZlcmFsIGluZGV4ZXMgZm9yIGVhY2ggb2YgdGhlIGNhdGVnb3JpZXMgb2YgcmVndWxhdGlvbiwgZm9sbG93aW5nIENocmlzdGVuc2VuIGFuZCBXZWluc3RlaW4ncyBjbGFzc2lmaWNhdGlvbjoKCi0gYGVudHJ5YCAoUTJiLCBRMmMsIFEyZDsgMyBwb2ludHMgbWF4aW11bSwgYWN0dWFsIG1heCA9IDMgcG9pbnRzIG1heGltdW0pOiBiYXJyaWVycyB0byBlbnRyeQogIC0gUTJjIGlzIHJldmVyc2VkLCBzbyBub3QgYmVpbmcgYWxsb3dlZCB0byBhcHBlYWwgcmVnaXN0cmF0aW9uIHN0YXR1cyBlYXJucyAxIHBvaW50LgogIC0gUTJhIGlzIG9taXR0ZWQgYmVjYXVzZSBpdCdzIGJlbmlnbgotIGBmdW5kaW5nYCAoUTNiLCBRM2MsIFEzZCwgUTNlLCBRM2Y7IDUgcG9pbnRzIG1heGltdW0sIGFjdHVhbCBtYXggPSA0LjUpOiBiYXJyaWVycyB0byBmdW5kaW5nCiAgLSBRM2EgaXMgb21pdHRlZCBiZWNhdXNlIGl0J3MgYmVuaWduCiAgLSBTY29yZXMgdGhhdCByYW5nZSBiZXR3ZWVuIDDigJMyIGFyZSByZXNjYWxlZCB0byAw4oCTMSAoc28gMSBiZWNvbWVzIDAuNSkKLSBgYWR2b2NhY3lgIChRNGEsIFE0YzsgMiBwb2ludHMgbWF4aW11bSwgYWN0dWFsIG1heCA9IDIpOiBiYXJyaWVycyB0byBhZHZvY2FjeQogIC0gUTRiIGlzIG9taXR0ZWQgYmVjYXVzZSBpdCdzIG5vdCBhIGxhdwogIC0gU2NvcmVzIHRoYXQgcmFuZ2UgYmV0d2VlbiAw4oCTMiBhcmUgcmVzY2FsZWQgdG8gMOKAkzEgKHNvIDEgYmVjb21lcyAwLjUpCi0gYGJhcnJpZXJzX3RvdGFsYCAoMTAgcG9pbnRzIG1heGltdW0sIGFjdHVhbCBtYXggPSA4LjUpOiBzdW0gb2YgYWxsIHRocmVlIGluZGV4ZXMKClRoZXNlIGluZGV4ZXMgYXJlIGFsc28gc3RhbmRhcmRpemVkIGJ5IGRpdmlkaW5nIGJ5IHRoZSBtYXhpbXVtLCB5aWVsZGluZyB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczoKCi0gYGVudHJ5X3N0ZGA6IDEgcG9pbnQgbWF4aW11bSwgYWN0dWFsIG1heCA9IDEKLSBgZnVuZGluZ19zdGRgOiAxIHBvaW50IG1heGltdW0sIGFjdHVhbCBtYXggPSAxCi0gYGFkdm9jYWN5X3N0ZGA6IDEgcG9pbnQgbWF4aW11bSwgYWN0dWFsIG1heCA9IDEKLSBgYmFycmllcnNfdG90YWxfc3RkYDogMyBwb2ludHMgbWF4aW11bSwgYWN0dWFsIG1heCA9IDIuNQoKIyMjIENoYXVkaHJ5IDIwMjAgZGF0YQoKVGhlIG1vc3QgcmVjZW50IHZlcnNpb24gb2YgU3VwYXJuYSdzIGRhdGEgaXMgYWxyZWFkeSBpbiBuaWNlIGNsZWFuIHBhbmVsIGZvcm0sIHNvIGl0J3Mgc3VwZXIgZWFzeSB0byBnZXQgY2xlYW5lZCB1cC4KCmBgYHtyIGNsZWFuLWNoYXVkaHJ5LW5nb3MsIG1lc3NhZ2U9RkFMU0V9CmRjandfcXVlc3Rpb25zIDwtIHJlYWRfY3N2KGhlcmUoImRhdGEiLCAibWFudWFsX2RhdGEiLCAiZGNqd19xdWVzdGlvbnMuY3N2IikpICU+JSAKICBzZWxlY3QocXVlc3Rpb24sIGJhcnJpZXIsIHF1ZXN0aW9uX2NsZWFuLCBpZ25vcmVfaW5faW5kZXgpCgpyZWd1bGF0aW9uX2NhdGVnb3JpZXMgPC0gdHJpYmJsZSgKICB+cXVlc3Rpb24sIH5jb2xfbmFtZSwgfmNhdGVnb3J5LAogICJxMmEiLCAibmdvX3JlZ2lzdGVyIiwgIm9taXQiLAogICJxMmIiLCAibmdvX3JlZ2lzdGVyX2J1cmRlbiIsICJlbnRyeSIsCiAgInEyYyIsICJuZ29fcmVnaXN0ZXJfYXBwZWFsIiwgImVudHJ5IiwKICAicTJkIiwgIm5nb19iYXJyaWVyX2ZvcmVpZ25fZnVuZHMiLCAiZW50cnkiLAogICJxM2EiLCAibmdvX2Rpc2Nsb3NlX2Z1bmRzIiwgIm9taXQiLAogICJxM2IiLCAibmdvX2ZvcmVpZ25fZnVuZF9hcHByb3ZhbCIsICJmdW5kaW5nIiwKICAicTNjIiwgIm5nb19mb3JlaWduX2Z1bmRfY2hhbm5lbCIsICJmdW5kaW5nIiwgCiAgInEzZCIsICJuZ29fZm9yZWlnbl9mdW5kX3Jlc3RyaWN0IiwgImZ1bmRpbmciLAogICJxM2UiLCAibmdvX2ZvcmVpZ25fZnVuZF9wcm9oaWJpdCIsICJmdW5kaW5nIiwKICAicTNmIiwgIiIsICJmdW5kaW5nIiwKICAicTRhIiwgIiIsICJhZHZvY2FjeSIsCiAgInE0YyIsICIiLCAiYWR2b2NhY3kiCikKCmNoYXVkaHJ5XzIwMTQgPC0gZXhwYW5kX2dyaWQoZ3djb2RlID0gdW5pcXVlKGNoYXVkaHJ5X3JhdyRnd2NvZGUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ZWFyID0gMjAxNCkKCmNoYXVkaHJ5X2luZGl2aWR1YWxfbGF3cyA8LSBjaGF1ZGhyeV9yYXcgJT4lIAogIGJpbmRfcm93cyhjaGF1ZGhyeV8yMDE0KSAlPiUgCiAgYXJyYW5nZShnd2NvZGUsIHllYXIpCgpjaGF1ZGhyeV9sb25nIDwtIGNoYXVkaHJ5X3JhdyAlPiUgCiAgIyBCcmluZyBpbiAyMDE0IHJvd3MKICBiaW5kX3Jvd3MoY2hhdWRocnlfMjAxNCkgJT4lIAogICMgRXRoaW9waWEgYW5kIEN6ZWNoIFJlcHVibGljIGhhdmUgZHVwbGljYXRlIHJvd3MgaW4gMTk5MyBhbmQgMTk5NCByZXNwZWN0aXZlbHksIGJ1dCAKICAjIHRoZSB2YWx1ZXMgYXJlIGlkZW50aWNhbCwgc28ganVzdCBrZWVwIHRoZSBmaXJzdCBvZiB0aGUgdHdvCiAgZ3JvdXBfYnkoZ3djb2RlLCB5ZWFyKSAlPiUgCiAgc2xpY2UoMSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgYXJyYW5nZShnd2NvZGUsIHllYXIpICU+JSAKICAjIFJldmVyc2UgdmFsdWVzIGZvciBxMmMKICBtdXRhdGUocTJjID0gMSAtIHEyYykgJT4lIAogICMgUmVzY2FsZSAyLXBvaW50IHF1ZXN0aW9ucyB0byAwLTEgc2NhbGUKICBtdXRhdGVfYXQodmFycyhxM2UsIHEzZiwgcTRhKSwgfnJlc2NhbGUoLiwgdG8gPSBjKDAsIDEpLCBmcm9tID0gYygwLCAyKSkpICU+JSAKICAjIHEyZCBhbmQgcTRjIHVzZSAtMSB0byBpbmRpY2F0ZSBsZXNzIHJlc3RyaWN0aW9uL2J1cmRlbnNvbWVuZXNzLiBTaW5jZSB3ZSdyZQogICMgY29uY2VybmVkIHdpdGggYW4gaW5kZXggb2YgcmVzdHJpY3Rpb24sIHdlIG1ha2UgdGhlIG5lZ2F0aXZlIHZhbHVlcyB6ZXJvCiAgbXV0YXRlX2F0KHZhcnMocTJkLCBxNGMpLCB+aWZlbHNlKC4gPT0gLTEsIDAsIC4pKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgicSIpLCBuYW1lc190byA9ICJxdWVzdGlvbiIpICU+JSAKICBsZWZ0X2pvaW4oZGNqd19xdWVzdGlvbnMsIGJ5ID0gInF1ZXN0aW9uIikgJT4lIAogIGdyb3VwX2J5KGd3Y29kZSkgJT4lCiAgbXV0YXRlKGFsbF9taXNzaW5nID0gYWxsKGlzLm5hKHZhbHVlKSkpICU+JQogIGdyb3VwX2J5KGd3Y29kZSwgcXVlc3Rpb24pICU+JSAKICAjIEJyaW5nIG1vc3QgcmVjZW50IGxlZ2lzbGF0aW9uIGZvcndhcmQgaW4gdGltZQogIGZpbGwodmFsdWUpICU+JSAKICAjIEZvciBvbGRlciBOQSBsZWdpc2xhdGlvbiB0aGF0IGNhbid0IGJlIGJyb3VnaHQgZm9yd2FyZCwgc2V0IHNlbnNpYmxlCiAgIyBkZWZhdWx0cy4gTGVhdmUgY291bnRyaWVzIHRoYXQgYXJlIDEwMCUgMCBhcyBOQS4KICBtdXRhdGUodmFsdWUgPSBpZmVsc2UoIWFsbF9taXNzaW5nICYgaXMubmEodmFsdWUpLCAwLCB2YWx1ZSkpICU+JSAKICB1bmdyb3VwKCkKCmNoYXVkaHJ5X3JlZ2lzdHJhdGlvbiA8LSBjaGF1ZGhyeV9sb25nICU+JSAKICBzZWxlY3QoZ3djb2RlLCB5ZWFyLCBxdWVzdGlvbl9jbGVhbiwgdmFsdWUpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gInF1ZXN0aW9uX2NsZWFuIiwgdmFsdWVzX2Zyb20gPSAidmFsdWUiKQoKY2hhdWRocnlfc3VtbWVkIDwtIGNoYXVkaHJ5X2xvbmcgJT4lCiAgZmlsdGVyKCFpZ25vcmVfaW5faW5kZXgpICU+JSAKICBncm91cF9ieShnd2NvZGUsIHllYXIsIGJhcnJpZXIpICU+JSAKICBzdW1tYXJpemUodG90YWwgPSBzdW0odmFsdWUpKSAlPiUgCiAgdW5ncm91cCgpCgpjaGF1ZGhyeV9jbGVhbiA8LSBjaGF1ZGhyeV9zdW1tZWQgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBiYXJyaWVyLCB2YWx1ZXNfZnJvbSA9IHRvdGFsKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoZW50cnksIGZ1bmRpbmcsIGFkdm9jYWN5KSwgCiAgICAgICAgICAgIGxpc3Qoc3RkID0gfi4gLyBtYXgoLiwgbmEucm0gPSBUUlVFKSkpICU+JSAKICBtdXRhdGUoYmFycmllcnNfdG90YWwgPSBhZHZvY2FjeSArIGVudHJ5ICsgZnVuZGluZywKICAgICAgICAgYmFycmllcnNfdG90YWxfc3RkID0gYWR2b2NhY3lfc3RkICsgZW50cnlfc3RkICsgZnVuZGluZ19zdGQpICU+JSAKICBsZWZ0X2pvaW4oY2hhdWRocnlfcmVnaXN0cmF0aW9uLCBieSA9IGMoImd3Y29kZSIsICJ5ZWFyIikpCgpnbGltcHNlKGNoYXVkaHJ5X2NsZWFuKQpgYGAKCiMjIyBEQ0pXIGRhdGEKCkZvciBmdW4gYW5kIHJvYnVzdG5lc3MgY2hlY2tzLCB3ZSB1c2UgRENKVydzIG5vbi1wYW5lbCBkYXRhIHRvIGdlbmVyYXRlIGEgcGFuZWwgc3RhcnRpbmcgaW4gMTk4MCwgc2luY2UgdGhleSBoYXZlIGVudHJpZXMgd2hlcmUgbGF3cyBzdGFydCBpbiB0aGUgMTk2MHMgYW5kIDcwcyBhbmQgb3RoZXIgcHJlLTE5ODAgeWVhcnMuIAoKYGBge3IgY2xlYW4tZGNqdy1uZ29zfQpkY2p3X3RpZHkgPC0gZGNqd19vcmlnICU+JQogIG11dGF0ZShhY3Jvc3MoZXZlcnl0aGluZygpLCBhcy5jaGFyYWN0ZXIpKSAlPiUKICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAia2V5IiwgdmFsdWVzX3RvID0gInZhbHVlIiwgLUNvdW50cnkpICU+JSAKICBzZXBhcmF0ZShrZXksIGMoInF1ZXN0aW9uIiwgInZhcl9uYW1lIiksIDQpICU+JQogIG11dGF0ZSh2YXJfbmFtZSA9IGlmZWxzZSh2YXJfbmFtZSA9PSAiIiwgInZhbHVlIiwgZ3N1YigiXyIsICIiLCB2YXJfbmFtZSkpKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gInZhcl9uYW1lIiwgdmFsdWVzX2Zyb20gPSAidmFsdWUiKSAlPiUgCiAgIyBSZW1vdmUgdW5kZXJzY29yZSB0byBtYXRjaCBDaGF1ZGhyeSdzIHN0dWZmCiAgbXV0YXRlKHF1ZXN0aW9uID0gc3RyX3JlbW92ZShxdWVzdGlvbiwgIl8iKSkgJT4lIAogIG11dGF0ZSh2YWx1ZSA9IGFzLm51bWVyaWModmFsdWUpKSAlPiUgCiAgIyBSZXZlcnNlIHZhbHVlcyBmb3IgcTJjCiAgbXV0YXRlKHZhbHVlID0gaWZlbHNlKHF1ZXN0aW9uID09ICJxMmMiLCAxIC0gdmFsdWUsIHZhbHVlKSkgJT4lIAogICMgUmVzY2FsZSAyLXBvaW50IHF1ZXN0aW9ucyB0byAwLTEgc2NhbGUKICBtdXRhdGUodmFsdWUgPSBpZmVsc2UocXVlc3Rpb24gJWluJSBjKCJxM2UiLCAicTNmIiwgInE0YSIpLAogICAgICAgICAgICAgICAgICAgICAgICByZXNjYWxlKHZhbHVlLCB0byA9IGMoMCwgMSksIGZyb20gPSBjKDAsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUpKSAlPiUgCiAgIyBxMmQgYW5kIHE0YyB1c2UgLTEgdG8gaW5kaWNhdGUgbGVzcyByZXN0cmljdGlvbi9idXJkZW5zb21lbmVzcy4gU2luY2Ugd2UncmUKICAjIGNvbmNlcm5lZCB3aXRoIGFuIGluZGV4IG9mIHJlc3RyaWN0aW9uLCB3ZSBtYWtlIHRoZSBuZWdhdGl2ZSB2YWx1ZXMgemVybwogIG11dGF0ZSh2YWx1ZSA9IGlmZWxzZShxdWVzdGlvbiAlaW4lIGMoInEyZCIsICJxNGMiKSAmIHZhbHVlID09IC0xLAogICAgICAgICAgICAgICAgICAgICAgICAwLCB2YWx1ZSkpICU+JSAKICAjIEdldCByaWQgb2Ygcm93cyB3aGVyZSB5ZWFyIGlzIG1pc3NpbmcgYW5kIHJlZ3VsYXRpb24gd2FzIG5vdCBpbXBvc2VkCiAgZmlsdGVyKCEoaXMubmEoeWVhcikgJiB2YWx1ZSA9PSAwKSkgJT4lCiAgIyBTb21lIGVudHJpZXMgaGF2ZSBtdWx0aXBsZSB5ZWFyczsgZm9yIG5vdyBqdXN0IHVzZSB0aGUgZmlyc3QgeWVhcgogIG11dGF0ZSh5ZWFyID0gc3RyX3NwbGl0KHllYXIsICIsIikpICU+JSB1bm5lc3QoeWVhcikgJT4lIAogIGdyb3VwX2J5KENvdW50cnksIHF1ZXN0aW9uKSAlPiUgc2xpY2UoMSkgJT4lIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUodmFsdWUgPSBhcy5pbnRlZ2VyKHZhbHVlKSwgeWVhciA9IGFzLmludGVnZXIoeWVhcikpICU+JSAKICBtdXRhdGUoQ291bnRyeSA9IGNvdW50cnljb2RlKENvdW50cnksICJjb3VudHJ5Lm5hbWUiLCAiY291bnRyeS5uYW1lIiksCiAgICAgICAgIGd3Y29kZSA9IGNvdW50cnljb2RlKENvdW50cnksICJjb3VudHJ5Lm5hbWUiLCAiZ3duIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYygiWWVtZW4iID0gNjc4KSkpICU+JSAKICAjIElmIHllYXIgaXMgbWlzc2luZyBidXQgc29tZSByZWd1bGF0aW9uIGV4aXN0cywgYXNzdW1lIGl0IGhhcyBhbHdheXMgYWxyZWFkeQogICMgZXhpc3RlZCAoc2luY2UgMTk1MCwgYXJiaXRyYXJpbHkpCiAgbXV0YXRlKHllYXIgPSBpZmVsc2UoaXMubmEoeWVhciksIDE5NTAsIHllYXIpKQoKcG90ZW50aWFsX2RjandfcGFuZWwgPC0gZGNqd190aWR5ICU+JQogIHRpZHlyOjpleHBhbmQoZ3djb2RlLCBxdWVzdGlvbiwgCiAgICAgICAgICAgICAgICB5ZWFyID0gbWluKC4keWVhciwgbmEucm0gPSBUUlVFKToyMDE1KQoKZGNqd19jbGVhbiA8LSBkY2p3X3RpZHkgJT4lCiAgc2VsZWN0KC1Db3VudHJ5KSAlPiUgCiAgcmlnaHRfam9pbihwb3RlbnRpYWxfZGNqd19wYW5lbCwKICAgICAgICAgICAgIGJ5ID0gYygiZ3djb2RlIiwgInF1ZXN0aW9uIiwgInllYXIiKSkgJT4lIAogIGFycmFuZ2UoZ3djb2RlLCB5ZWFyKSAlPiUgCiAgbGVmdF9qb2luKGRjandfcXVlc3Rpb25zLCBieSA9ICJxdWVzdGlvbiIpICU+JSAKICBmaWx0ZXIoIWlnbm9yZV9pbl9pbmRleCkgJT4lIAogIGdyb3VwX2J5KGd3Y29kZSkgJT4lCiAgbXV0YXRlKGFsbF9taXNzaW5nID0gYWxsKGlzLm5hKHZhbHVlKSkpICU+JQogIGdyb3VwX2J5KGd3Y29kZSwgcXVlc3Rpb24pICU+JSAKICAjIEJyaW5nIG1vc3QgcmVjZW50IGxlZ2lzbGF0aW9uIGZvcndhcmQgaW4gdGltZQogIGZpbGwodmFsdWUpICU+JSAKICAjIEZvciBvbGRlciBOQSBsZWdpc2xhdGlvbiB0aGF0IGNhbid0IGJlIGJyb3VnaHQgZm9yd2FyZCwgc2V0IHNlbnNpYmxlCiAgIyBkZWZhdWx0cy4gTGVhdmUgY291bnRyaWVzIHRoYXQgYXJlIDEwMCUgMCBhcyBOQS4KICBtdXRhdGUodmFsdWUgPSBpZmVsc2UoIWFsbF9taXNzaW5nICYgaXMubmEodmFsdWUpLCAwLCB2YWx1ZSkpICU+JSAKICBncm91cF9ieShnd2NvZGUsIHllYXIsIGJhcnJpZXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbCA9IHN1bSh2YWx1ZSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gImJhcnJpZXIiLCB2YWx1ZXNfZnJvbSA9ICJ0b3RhbCIpICU+JQogIGZpbHRlcih5ZWFyID4gMTk3OCkgJT4lIAogICMgU3RhbmRhcmRpemUgYmFycmllciBpbmRleGVzIGJ5IGRpdmlkaW5nIGJ5IG1heGltdW0gbnVtYmVyIHBvc3NpYmxlCiAgbXV0YXRlKGFjcm9zcyhjKGVudHJ5LCBmdW5kaW5nLCBhZHZvY2FjeSksIGxpc3Qoc3RkID0gfiAuIC8gbWF4KC4sIG5hLnJtID0gVFJVRSkpKSkgJT4lIAogIG11dGF0ZShiYXJyaWVyc190b3RhbCA9IGFkdm9jYWN5ICsgZW50cnkgKyBmdW5kaW5nLAogICAgICAgICBiYXJyaWVyc190b3RhbF9zdGQgPSBhZHZvY2FjeV9zdGQgKyBlbnRyeV9zdGQgKyBmdW5kaW5nX3N0ZCkKCmdsaW1wc2UoZGNqd19jbGVhbikKYGBgCgpBbGwgY2xlYW4hIEV4Y2VwdCBub3QhIE5FVkVSIE1JTkQgVE8gQUxMIFRIQVQg4oaRCgpTdXBhcm5hIG1hZGUgdXBkYXRlcyB0byBleGlzdGluZyB0aGUgRENKVyBjb3VudHJpZXMgdG9vLCBsaWtlIEhvbmR1cmFzIChnd2NvZGUgOTEpLCB3aGljaCBoYXMgbW9yZSBjb3JyZWN0IHZhbHVlcyBmb3IgYHE0YWAsIGZvciBpbnN0YW5jZSwgd2hpY2ggRENKVyBtYXJrcyBhcyAwLCBidXQgaXMgYWN0dWFsbHkgMS4gU28gZXZlbiB0aG91Z2ggd2UgY2FuIGdvIGJhY2sgaW4gdGltZSB0byAxOTgwIHdpdGggRENKVywgaXQncyBub3QgY29tcGFyYWJsZSB3aXRoIFN1cGFybmEncyBleHBhbmRlZCBhbmQgbW9yZSByZWNlbnQgZGF0YS4gCgpgYGB7ciBjaGVjay1ob25kdXJhc30KIyBMb29rIGF0IEhvbmR1cmFzIGluIDE5OTAgaW4gYm90aCBkYXRhc2V0czoKZGNqd19jbGVhbiAlPiUgZmlsdGVyKHllYXIgPT0gMTk5MCwgZ3djb2RlID09IDkxKQoKY2hhdWRocnlfY2xlYW4gJT4lIGZpbHRlcih5ZWFyID09IDE5OTAsIGd3Y29kZSA9PSA5MSkKYGBgCgpTbyB3ZSBsaXZlIHdpdGggKmp1c3QqIDE5OTArLCBldmVuIGZvciB0aGUgc2FrZSBvZiBsYWdnaW5nIGByIGVtbzo6amkoInNocnVnIilgLgoKRXhjZXB0LCB3ZSdyZSBub3QgcXVpdGUgZG9uZSB5ZXQhCgpJbiBTdXBhcm5hJ3MgY2xlYW4gZGF0YSwgZHVlIHRvIHBvc3QtQ29sZCBXYXIgY2hhb3MsIFJ1c3NpYSAoMzY1KSBpcyBtaXNzaW5nIGZvciAxOTkwLTE5OTEgYW5kIFNlcmJpYS9TZXJiaWEgYW5kIE1vbnRlbmVncm8vWXVnb3NsYXZpYSAoMzQ1KSBpcyBtaXNzaW5nIGV2ZXJ5IHRoaW5nIHByZS0yMDA2LiBEQ0pXIGRvbid0IGluY2x1ZGUgYW55IGRhdGEgZm9yIFNlcmJpYSwgc28gd2UncmUgb3V0IG9mIGx1Y2sgdGhlcmXigJR3ZSdyZSBsaW1pdGVkIHRvIFNlcmJpYSBpdHNlbGYgYW5kIG5vdCBwYXN0IHZlcnNpb25zIG9mIGl0LiBEQ0pXICpkbyogaW5jbHVkZSBkYXRhIGZvciBSdXNzaWEsIHRob3VnaCwgc28gd2UgdXNlIHRoYXQgaW4gb3VyIGNsZWFuIGZpbmFsIE5HTyBsYXdzIGRhdGEuIEZvcnR1bmF0ZWx5IHRoaXMgaXMgZWFzeSwgc2luY2UgUnVzc2lhJ3MgdmFsdWVzIGFyZSBhbGwgMCBmb3IgdGhvc2UgdHdvIHllYXJzOgoKYGBge3Igc2hvdy1ydXNzaWF9CmRjandfY2xlYW4gJT4lIAogIGZpbHRlcihnd2NvZGUgPT0gMzY1LCB5ZWFyICVpbiUgYygxOTkwLCAxOTkxKSkKYGBgCgpTbyB3ZSBqdXN0IGFkZCB0d28gcm93cyBmb3IgUnVzc2lhOgoKYGBge3IgYWRkLXJ1c3NpYX0KZWFybHlfcnVzc2lhIDwtIHRpYmJsZShnd2NvZGUgPSAzNjUsIHllYXIgPSBjKDE5OTAsIDE5OTEpLAogICAgICAgICAgICAgICAgICAgICAgIGFkdm9jYWN5ID0gMCwgZW50cnkgPSAwLCBmdW5kaW5nID0gMCwgCiAgICAgICAgICAgICAgICAgICAgICAgZW50cnlfc3RkID0gMCwgZnVuZGluZ19zdGQgPSAwLCBhZHZvY2FjeV9zdGQgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICBiYXJyaWVyc190b3RhbCA9IDAsIGJhcnJpZXJzX3RvdGFsX3N0ZCA9IDApCgpjaGF1ZGhyeV9jbGVhbiA8LSBjaGF1ZGhyeV9jbGVhbiAlPiUgCiAgYmluZF9yb3dzKGVhcmx5X3J1c3NpYSkgJT4lIAogIGFycmFuZ2UoZ3djb2RlLCB5ZWFyKQpgYGAKCgojIyBSZWd1bGF0b3J5IGVudmlyb25tZW50CgpBbiBhbHRlcm5hdGl2ZSB3YXkgb2YgbWVhc3VyaW5nIGNpdmlsIHNvY2lldHkgcmVzdHJpY3Rpb25zIGlzIHRvIGxvb2sgYXQgdGhlIG92ZXJhbGwgY2l2aWwgc29jaWV0eSByZWd1bGF0b3J5IGVudmlyb25tZW50IHJhdGhlciB0aGFuIHNwZWNpZmljIGxhd3MsIHNpbmNlIGRlIGp1cmUgcmVzdHJpY3Rpb25zIGRvIG5vdCBhbHdheXMgbWFwIGNsZWFybHkgaW50byBkZSBmYWN0byByZXN0cmljdGlvbnMgKGVzcGVjaWFsbHkgaW4gZGljdGF0b3JzaGlwcyB3aGVyZSB0aGUgaW1wbGVtZW50YXRpb24gb2YgbGF3cyBpcyBtb3JlIGRpc2NyZXRpb25hcnkpLiAKCkFuZHJldyBIZWlzcyBkZXZlbG9wcyBhIG5ldyBjaXZpbCBzb2NpZXR5IHJlZ3VsYXRvcnkgZW52aXJvbm1lbnQgaW5kZXggKENTUkUpIGluIGhpcyBkaXNzZXJ0YXRpb24sIHdoaWNoIGNvbWJpbmVzIHR3byBjaXZpbCBzb2NpZXR5IGluZGV4ZXMgZnJvbSB0aGUgW1ZhcmlldGllcyBvZiBEZW1vY3JhY3kgcHJvamVjdCAoVi1EZW0pXShodHRwczovL3d3dy52LWRlbS5uZXQvZW4vKTogKDEpIGNpdmlsIHNvY2lldHkgcmVwcmVzc2lvbiAoYHYyY3NyZXByc3NgKSBhbmQgKDIpIGNpdmlsIHNvY2lldHkgZW50cnkgYW5kIGV4aXQgcmVndWxhdGlvbnMgKGB2MmNzZWVvcmdzYCkuIFRoZSBDU1JFIHJhbmdlcyBmcm9tIHJvdWdobHkg4oiSNiB0byA2ICh0aG91Z2ggdHlwaWNhbGx5IG9ubHkgZnJvbSDiiJI0IHRvIDRpc2gpLCBhbmQgc2hvd3MgbW9yZSB2YXJpYXRpb24gb3ZlciB0aW1lIHNpbmNlIGl0IG9zdGVuc2libHkgY2FwdHVyZXMgY2hhbmdlcyBpbiB0aGUgaW1wbGVtZW50YXRpb24gb2YgdGhlIHJlZ3VsYXRvcnkgZW52aXJvbm1lbnQgcmF0aGVyIHRoYW4gdGhlIHByZXNlbmNlIG9yIGFic2VuY2Ugb2YgbGVnaXNsYXRpb24uCgpBZGRpdGlvbmFsbHksIHNpbmNlIEFuZHJldydzIGRpc3NlcnRhdGlvbiwgdGhlIFYtRGVtIHByb2plY3QgaGFzIGNyZWF0ZWQgaXRzIG93biBjb3JlIGNpdmlsIHNvY2lldHkgaW5kZXggKGB2Mnhjc19jY3NpYCkgKGVudHJ5L2V4aXQgKGB2MmNzZWVvcmdzYCkgKyByZXByZXNzaW9uIChgdjJjc3JlcHJzc2ApICsgcGFydGljaXBhdG9yeSBlbnZpcm9ubWVudCAoYHYyY3NwcnRjcHRgKSkuIFdlIHVzZSB0aGF0IGluc3RlYWQsIHNpbmNlIFYtRGVtIHJlc2NhbGVzIGl0IHRvIGEgMC0xIHNjYWxlIHNvIGl0J3Mgbm90IHdlaXJkbHkgZGlzdHJpYnV0ZWQgZnJvbSBsaWtlIG15IGFkZGl0aXZlIHR3by1mYWN0b3IgQ1NSRSBpbmRleC4KCldoaWxlIHRoZSBtYWluIGZvY3VzIG9mIHRoaXMgcGFwZXIgaXMgZG9ub3IgcmVzcG9uc2UgdG8gbmV3ICpsZWdpc2xhdGlvbiosIHdlIGFsc28gbG9vayBhdCBkb25vciByZXNwb25zZSB0byBjaGFuZ2VzIGluIHRoZSBvdmVyYWxsIGNpdmlsIHNvY2lldHkgaW5kZXggYXMgYSByb2J1c3RuZXNzIGNoZWNrLiBUaGlzIGFsc28gYWxsb3dzIHVzIHRvIGluY2x1ZGUgZGF0YSBmcm9tIDE5ODDigJMyMDE4IChTaW5jZSBTdXBhcmFuYSdzIGxhdyBkYXRhIHJhbmdlcyBmcm9tIDE5OTDigJMyMDE0KQoKV2UgYWxzbyB1c2UgYSBidW5jaCBvZiBvdGhlciBWLURlbSB2YXJpYWJsZXMgYXMgY29uZm91bmRlcnM6CgojIEVjb25vbWljcyBhbmQgZGV2ZWxvcG1lbnQKICAgICAgIGdkcGNhcF9sb2cgKyB1bl90cmFkZV9wY3RfZ2RwICsgdjJ4ZWdfZXFkciArIHYycGVwcmlzY2ggKyBlX3BlaW5mbW9yICsKICAgICAgICMgSHVtYW4gcmlnaHRzIGFuZCBwb2xpdGljcwogICAgICAgIyBDb25mbGljdCBhbmQgZGlzYXN0ZXJzCiAgICAgICBpbnRlcm5hbF9jb25mbGljdF9wYXN0XzUgKyBuYXR1cmFsX2Rpc19jb3VudCArCgotICoqQ2l2aWwgc29jaWV0eSB0aGluZ3MqKgogIC0gQ1NPIGVudHJ5IGFuZCBleGl0OiBgdjJjc2Vlb3Jnc2AKICAtIENTTyByZXByZXNzaW9uOiBgdjJjc3JlcHJzc2AKICAtIENTTyBjb25zdWx0YXRpb246IGB2MmNzY25zdWx0YAogIC0gQ1NPIHBhcnRpY2lwYXRvcnkgZW52aXJvbm1lbnQ6IGB2MmNzcHJ0Y3B0YAogIC0gQ1NPIHdvbWVuJ3MgcGFydGljaXBhdGlvbjogYHYyY3NnZW5kZXJgCiAgLSBDU08gYW50aS1zeXN0ZW0gbW92ZW1lbnRzOiBgdjJjc2FudGltdmAKICAtIENvcmUgY2l2aWwgc29jaWV0eSBpbmRleCAoZW50cnkvZXhpdCwgcmVwcmVzc2lvbiwgcGFydGljaXBhdG9yeSBlbnYpOiBgdjJ4Y3NfY2NzaWAKLSAqKkh1bWFuIHJpZ2h0cyBhbmQgcG9saXRpY3MqKgogIC0gUG9saXR5IHNjb3JlczogYGVfcG9saXR5MmAgKG9ubHkgZm9yIHJlZmVyZW5jZSB3aXRoIHBvbHlhcmNoeTsgd2UgZG9uJ3QgdXNlIHRoZXNlKQogIC0gRWxlY3RvcmFsIGRlbW9jcmFjeSBpbmRleDogYHYyeF9wb2x5YXJjaHlgCiAgLSBSZWdpbWVzIG9mIHRoZSB3b3JsZCBzY29yZXM6IGB2MnhfcmVnaW1lX2FtYmAgKG9ubHkgZm9yIGRldGVybWluaW5nIGF2ZXJhZ2UgYXV0b2NyYWN5OyB3ZSBkb24ndCB1c2UgdGhlc2UpCiAgLSBQb2xpdGljYWwgY29ycnVwdGlvbiBpbmRleDogYHYyeF9jb3JyYCAobGVzcyB0byBtb3JlLCAwLTEpIChwdWJsaWMgc2VjdG9yICsgZXhlY3V0aXZlICsgbGVnaXNsYXRpdmUgKyBqdWRpY2lhbCBjb3JydXB0aW9uKQogIC0gUnVsZSBvZiBsYXcgaW5kZXg6IGB2MnhfcnVsZWAKICAtIENpdmlsIGxpYmVydGllcyBpbmRleDogYHYyeF9jaXZsaWJgCiAgLSBQaHlzaWNhbCB2aW9sZW5jZSBpbmRleDogYHYyeF9jbHBoeWAKICAtIFByaXZhdGUgY2l2aWwgbGliZXJ0aWVzIGluZGV4OiBgdjJ4X2NscHJpdmAKICAtIFBvbGl0aWNhbCBjaXZpbCBsaWJlcnRpZXMgaW5kZXg6IGB2MnhfY2xwb2xgIChidXQgbm90IHRoaXMgYmVjYXVzZSBpdCBpbmNsdWRlcyBgdjJjc2Vlb3Jnc2AgYW5kIGB2MmNzcmVwcnNzYCkKLSAqKkVjb25vbWljcyBhbmQgZGV2ZWxvcG1lbnQqKgogIC0gRWR1Y2F0aW9uYWwgZXF1YWxpdHk6IGB2MnBlZWR1ZXFgCiAgLSBIZWFsdGggZXF1YWxpdHk6IGB2MnBlaGVhbHRoYAogIC0gSW5mYW50IG1vcnRhbGl0eSByYXRlOiBgZV9wZWluZm1vcmAKCmBgYHtyIGNsZWFuLXZkZW19CiMgNDAzOiBTYW8gVG9tZSBhbmQgUHJpbmNpcGUKIyA1OTE6IFNleWNoZWxsZXMKIyA2Nzk6IFllbWVuIChjaGFuZ2UgdG8gNjc4IGZvciBHVykKIyA5MzU6IFZhbnVhdHUKCnZkZW1fY2xlYW4gPC0gdmRlbV9yYXcgJT4lIAogIGZpbHRlcih5ZWFyID49IDE5ODApICU+JSAKICBtdXRhdGUoQ09XY29kZSA9IHJlY29kZShDT1djb2RlLCBgMzE1YCA9IDMxNikpICU+JSAKICBzZWxlY3QoY291bnRyeV9uYW1lLCB5ZWFyLCBjb3djb2RlID0gQ09XY29kZSwgCiAgICAgICAgICMgQ2l2aWwgc29jaWV0eSBzdHVmZgogICAgICAgICB2MmNzZWVvcmdzLCAgIyBDU08gZW50cnkgYW5kIGV4aXQKICAgICAgICAgdjJjc3JlcHJzcywgICMgQ1NPIHJlcHJlc3Npb24KICAgICAgICAgdjJjc2Nuc3VsdCwgICMgQ1NPIGNvbnN1bHRhdGlvbgogICAgICAgICB2MmNzcHJ0Y3B0LCAgIyBDU08gcGFydGljaXBhdG9yeSBlbnZpcm9ubWVudAogICAgICAgICB2MmNzZ2VuZGVyLCAgIyBDU08gd29tZW4ncyBwYXJ0aWNpcGF0aW9uCiAgICAgICAgIHYyY3NhbnRpbXYsICAjIENTTyBhbnRpLXN5c3RlbSBtb3ZlbWVudHMKICAgICAgICAgdjJ4Y3NfY2NzaSwgICMgQ29yZSBjaXZpbCBzb2NpZXR5IGluZGV4IChlbnRyeS9leGl0LCByZXByZXNzaW9uLCBwYXJ0aWNpcGF0b3J5IGVudikKICAgICAgICAgIyBIdW1hbiByaWdodHMgYW5kIHBvbGl0aWNzCiAgICAgICAgICMgUG9saXRpY2FsIGNvcnJ1cHRpb24gaW5kZXggKGxlc3MgdG8gbW9yZSwgMC0xKSAocHVibGljIHNlY3RvciArCiAgICAgICAgICMgZXhlY3V0aXZlICsgbGVnaXNsYXRpdmUgKyBqdWRpY2lhbCBjb3JydXB0aW9uKQogICAgICAgICB2MnhfY29yciwKICAgICAgICAgIyBSdWxlIG9mIGxhdyBpbmRleAogICAgICAgICB2MnhfcnVsZSwKICAgICAgICAgIyBSaWdodHMgaW5kZXhlcwogICAgICAgICB2MnhfY2l2bGliLCAgIyBDaXZpbCBsaWJlcnRpZXMgaW5kZXgKICAgICAgICAgdjJ4X2NscGh5LCAgIyBQaHlzaWNhbCB2aW9sZW5jZSBpbmRleAogICAgICAgICB2MnhfY2xwcml2LCAgIyBQcml2YXRlIGNpdmlsIGxpYmVydGllcyBpbmRleAogICAgICAgICB2MnhfY2xwb2wsICAjIFBvbGl0aWNhbCBjaXZpbCBsaWJlcnRpZXMgaW5kZXgKICAgICAgICAgIyBEZW1vY3JhY3kKICAgICAgICAgZV9wb2xpdHkyLCB2MnhfcG9seWFyY2h5LCB2MnhfcmVnaW1lX2FtYiwKICAgICAgICAgIyBFY29ub21pY3MgYW5kIGRldmVsb3BtZW50CiAgICAgICAgIHYycGVlZHVlcSwgICMgRWR1Y2F0aW9uYWwgZXF1YWxpdHkKICAgICAgICAgdjJwZWhlYWx0aCwgICMgSGVhbHRoIGVxdWFsaXR5CiAgICAgICAgIGVfcGVpbmZtb3IgICMgSW5mYW50IG1vcnRhbGl0eSByYXRlCiAgKSAlPiUgCiAgZmlsdGVyKGNvd2NvZGUgIT0gMjY1KSAlPiUgICMgT21pdCBFYXN0IEdlcm1hbnkKICAjIENvbnZlcnQgV2VzdCBHZXJtYW55ICgyNjApIHRvIEdlcm1hbnkgKDI1NSkKICBtdXRhdGUoZ3djb2RlID0gY291bnRyeWNvZGUoY293Y29kZSwgb3JpZ2luID0gImNvd24iLCBkZXN0aW5hdGlvbiA9ICJnd24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCI0MDMiID0gNDAzTCwgIjU5MSIgPSA1OTFMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI2NzkiID0gNjc4TCwgIjkzNSIgPSA5MzVMLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODE2IiA9IDgxNkwsICIyNjAiID0gMjU1TCkpKSAlPiUgCiAgc2VsZWN0KC1jb3VudHJ5X25hbWUsIC1jb3djb2RlKQoKZ2xpbXBzZSh2ZGVtX2NsZWFuKQpgYGAKCiMjIEF1dG9jcmFjaWVzCgpXZSdyZSBhbHNvIGludGVyZXN0ZWQgaW4gaG93IHRoZXNlIGNpdmlsIHNvY2lldHkgZHluYW1pY3Mgd29yayBpbiBhdXRvY3JhY2llcyBpbiBwYXJ0aWN1bGFyLiBXZSBnZW5lcmF0ZSBhIGNydWRlIGxpc3Qgb2YgYXV0b2NyYWNpZXMgYmFzZWQgb24gYXZlcmFnZSAiUmVnaW1lcyBvZiB0aGUgV29ybGQiIHNjb3JlcyBmcm9tIFYtRGVtLiBJbiB0aGF0IG1lYXN1cmUsIDQgaXMgdGhlIHVwcGVyIGJvdW5kIGFuZCA1IGlzIHRoZSBsb3dlciBib3VuZCBmb3IgZWxlY3RvcmFsIGF1dG9jcmFjeSwgc28gd2UgdXNlIDQgYXMgdGhlIGN1dG9mZi4gVGhlcmUgYXJlIGJvdW5kIHRvIGJlIGJldHRlciB3YXlzLCBidXQgdGhpcyB3b3JrcyBmb3Igbm93LgoKYGBge3IgbWFrZS1hdXRvY3JhY2llc30KYXV0b2NyYWNpZXMgPC0gdmRlbV9jbGVhbiAlPiUgCiAgZ3JvdXBfYnkoZ3djb2RlKSAlPiUgCiAgc3VtbWFyaXplKGF2Z19yb3cgPSBtZWFuKHYyeF9yZWdpbWVfYW1iLCBuYS5ybSA9IFRSVUUpKSAlPiUgCiAgdW5ncm91cCgpIAoKYXV0b2NyYWNpZXNfZmluYWwgPC0gc2tlbGV0b25fbG9va3VwICU+JSAKICBsZWZ0X2pvaW4oYXV0b2NyYWNpZXMsIGJ5ID0gImd3Y29kZSIpICU+JSAKICBtdXRhdGUoYXV0b2NyYWN5ID0gcm91bmQoYXZnX3JvdywgMCkgPD0gNCkKYGBgCgoKIyBXb3JsZCBCYW5rIGRldmVsb3BtZW50IGluZGljYXRvcnMKCldlIGRvbid0IHJlYWxseSB1c2UgYW55dGhpbmcgZnJvbSB0aGUgV29ybGQgQmFuaydzIGRhdGEgZXhjZXB0IGZvciBwb3B1bGF0aW9uIGRhdGEgZm9yIEtvc292by4KCmBgYHtyIGxvYWQtd2RpfQp3ZGlfY2xlYW4gPC0gd2RpX3JhdyAlPiUKICBmaWx0ZXIoaXNvMmMgJWluJSB1bmlxdWUocGFuZWxfc2tlbGV0b24kaXNvMikpICU+JQogIG11dGF0ZV9hdCh2YXJzKGluY29tZSwgcmVnaW9uKSwgYXMuY2hhcmFjdGVyKSAlPiUgICMgRG9uJ3QgdXNlIGZhY3RvcnMKICBtdXRhdGUoZ3djb2RlID0gY291bnRyeWNvZGUoaXNvMmMsIG9yaWdpbiA9ICJpc28yYyIsIGRlc3RpbmF0aW9uID0gImd3biIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoIllFIiA9IDY3OEwsICJYSyIgPSAzNDdMLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVk4iID0gODE2TCwgIlJTIiA9IDM0NUwpKSkgJT4lIAogIG11dGF0ZShyZWdpb24gPSBpZmVsc2UoZ3djb2RlID09IDM0MywgIkV1cm9wZSAmIENlbnRyYWwgQXNpYSIsIHJlZ2lvbiksCiAgICAgICAgIGluY29tZSA9IGlmZWxzZShnd2NvZGUgPT0gMzQzLCAiVXBwZXIgbWlkZGxlIGluY29tZSIsIGluY29tZSkpICU+JSAKICBzZWxlY3QoY291bnRyeSwgZ3djb2RlLCB5ZWFyLCByZWdpb24sIGluY29tZSwgcG9wdWxhdGlvbiA9IFNQLlBPUC5UT1RMKQoKIyBUaGUgVU4gZG9lc24ndCBoYXZlIHBvcHVsYXRpb24gZGF0YSBmb3IgS29zb3ZvLCBzbyB3ZSB1c2UgV0RJIGRhdGEgZm9yIHRoYXQKa29zb3ZvX3BvcHVsYXRpb24gPC0gd2RpX2NsZWFuICU+JSAKICBzZWxlY3QoZ3djb2RlLCB5ZWFyLCBwb3B1bGF0aW9uKSAlPiUgCiAgZmlsdGVyKGd3Y29kZSA9PSAzNDcsIHllYXIgPj0gMjAwOCkKCmdsaW1wc2Uod2RpX2NsZWFuKQpgYGAKCgojIFVORGF0YQoKVGhlIHJlYXNvbiB3ZSBkb24ndCBqdXN0IHVzZSBXREkgZGF0YSBmb3IgR0RQIGFuZCAlIG9mIEdEUCBmcm9tIHRyYWRlIGlzIHRoYXQgdGhlIFdESSBkYXRhIGlzIGluY29tcGxldGUsIGVzcGVjaWFsbHkgcHJlLTE5OTAuIFRvIGdldCBhcm91bmQgdGhhdCwgd2UgY3JlYXRlIG91ciBvd24gR0RQIGFuZCB0cmFkZSBtZWFzdXJlcyB1c2luZyBkYXRhIGRpcmVjdGx5IGZyb20gdGhlIFVOIChhdCBbVU5EYXRhXShodHRwczovL2RhdGEudW4ub3JnLykpLiBUaGV5IGRvbid0IGhhdmUgYSBuZWF0IEFQSSBsaWtlIHRoZSBXb3JsZCBCYW5rLCBzbyB5b3UgaGF2ZSB0byBnbyB0byB0aGVpciB3ZWJzaXRlIGFuZCBleHBvcnQgdGhlIGRhdGEgbWFudWFsbHkuCgpXZSBjb2xsZWN0IHRocmVlIHZhcmlhYmxlczogW0dEUCBhdCBjb25zdGFudCAyMDE1IHByaWNlc10oaHR0cDovL2RhdGEudW4ub3JnL0RhdGEuYXNweD9xPWdkcCZkPVNOQUFNQSZmPWdySUQlM2ExMDIlM2JjdXJySUQlM2FVU0QlM2JwY0ZsYWclM2EwKSwgW0dEUCBhdCBjdXJyZW50IHByaWNlc10oaHR0cDovL2RhdGEudW4ub3JnL0RhdGEuYXNweD9xPWdkcCZkPVNOQUFNQSZmPWdySUQlM2ExMDElM2JjdXJySUQlM2FVU0QlM2JwY0ZsYWclM2EwKSwgYW5kIFtwb3B1bGF0aW9uXShodHRwczovL3BvcHVsYXRpb24udW4ub3JnL3dwcC9Eb3dubG9hZC9TdGFuZGFyZC9Qb3B1bGF0aW9uLykuCgpgYGB7ciBnZXQtY2xlYW4tdW4tZGF0YSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBHRFAgYnkgVHlwZSBvZiBFeHBlbmRpdHVyZSBhdCBjb25zdGFudCAoMjAxNSkgcHJpY2VzIC0gVVMgZG9sbGFycwojIGh0dHA6Ly9kYXRhLnVuLm9yZy9EYXRhLmFzcHg/cT1nZHAmZD1TTkFBTUEmZj1ncklEJTNhMTAyJTNiY3VycklEJTNhVVNEJTNicGNGbGFnJTNhMAp1bl9nZHBfcmF3IDwtIHJlYWRfY3N2KGhlcmUoImRhdGEiLCAicmF3X2RhdGEiLCAiVU4gZGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVU5kYXRhX0V4cG9ydF8yMDIxMDExOF8wMzQwNTQ3MjkuY3N2IikpICU+JQogIHJlbmFtZShjb3VudHJ5ID0gYENvdW50cnkgb3IgQXJlYWApICU+JQogIG11dGF0ZSh2YWx1ZV90eXBlID0gIkNvbnN0YW50IikKCiMgR0RQIGJ5IFR5cGUgb2YgRXhwZW5kaXR1cmUgYXQgY3VycmVudCBwcmljZXMgLSBVUyBkb2xsYXJzCiMgaHR0cDovL2RhdGEudW4ub3JnL0RhdGEuYXNweD9xPWdkcCZkPVNOQUFNQSZmPWdySUQlM2ExMDElM2JjdXJySUQlM2FVU0QlM2JwY0ZsYWclM2EwCnVuX2dkcF9jdXJyZW50X3JhdyA8LSByZWFkX2NzdihoZXJlKCJkYXRhIiwgInJhd19kYXRhIiwgIlVOIGRhdGEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVU5kYXRhX0V4cG9ydF8yMDIxMDExOF8wMzQzMTEyNTIuY3N2IikpICU+JQogIHJlbmFtZShjb3VudHJ5ID0gYENvdW50cnkgb3IgQXJlYWApICU+JQogIG11dGF0ZSh2YWx1ZV90eXBlID0gIkN1cnJlbnQiKQoKIyBQb3B1bGF0aW9uCiMgVG90YWwgUG9wdWxhdGlvbiAtIEJvdGggU2V4ZXMKIyBodHRwczovL3BvcHVsYXRpb24udW4ub3JnL3dwcC9Eb3dubG9hZC9TdGFuZGFyZC9Qb3B1bGF0aW9uLwp1bl9wb3BfcmF3IDwtIHJlYWRfZXhjZWwoaGVyZSgiZGF0YSIsICJyYXdfZGF0YSIsICJVTiBkYXRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldQUDIwMTlfUE9QX0YwMV8xX1RPVEFMX1BPUFVMQVRJT05fQk9USF9TRVhFUy54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICBza2lwID0gMTYpCmBgYAoKYGBge3IgY2xlYW4tdW4tcG9wfQp1bl9wb3AgPC0gdW5fcG9wX3JhdyAlPiUKICBmaWx0ZXIoKGBDb3VudHJ5IGNvZGVgICVpbiUgdW5pcXVlKHBhbmVsX3NrZWxldG9uX2FsbCR1bikpKSAlPiUKICBzZWxlY3QoLWMoSW5kZXgsIFZhcmlhbnQsIE5vdGVzLCBgUmVnaW9uLCBzdWJyZWdpb24sIGNvdW50cnkgb3IgYXJlYSAqYCwgCiAgICAgICAgICAgIGBQYXJlbnQgY29kZWAsIFR5cGUpLCAKICAgICAgICAgdW5fY29kZSA9IGBDb3VudHJ5IGNvZGVgKSAlPiUKICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAieWVhciIsIHZhbHVlc190byA9ICJwb3B1bGF0aW9uIiwgLXVuX2NvZGUpICU+JQogIG11dGF0ZShnd2NvZGUgPSBjb3VudHJ5Y29kZSh1bl9jb2RlLCAidW4iLCAiZ3duIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYygiODg3IiA9IDY3OCwgIjcwNCIgPSA4MTYsICI2ODgiID0gMzQ1KSkpICU+JSAKICBtdXRhdGUoeWVhciA9IGFzLmludGVnZXIoeWVhciksCiAgICAgICAgIHBvcHVsYXRpb24gPSBhcy5udW1lcmljKHBvcHVsYXRpb24pICogMTAwMCkgJT4lICAjIFZhbHVlcyBhcmUgaW4gMTAwMHMKICBzZWxlY3QoZ3djb2RlLCB5ZWFyLCBwb3B1bGF0aW9uKSAlPiUgCiAgYmluZF9yb3dzKGtvc292b19wb3B1bGF0aW9uKQoKZ2xpbXBzZSh1bl9wb3ApCmBgYAoKRGVhbGluZyB3aXRoIHRoZSBHRFAgZGF0YSBpcyBhIGxpdHRsZSB0cmlja2llciBiZWNhdXNlIGl0J3MgaW4gMjAxNSBkb2xsYXJzLCB3aGlsZSBBaWREYXRhIGlzIGluIDIwMTEgZG9sbGFycy4gVG8gZml4IHRoaXMsIHdlIGNyZWF0ZSBhIEdEUCBkZWZsYXRvciBhbmQgcmViYXNlIHRoZSAyMDE1IHZhbHVlcyB0byAyMDExIHZhbHVlcy4KCmBgYHtyIGNsZWFuLXVuLWdkcH0KdW5fZ2RwIDwtIGJpbmRfcm93cyh1bl9nZHBfcmF3LCB1bl9nZHBfY3VycmVudF9yYXcpICU+JQogIGZpbHRlcihJdGVtICVpbiUgYygiR3Jvc3MgRG9tZXN0aWMgUHJvZHVjdCAoR0RQKSIsCiAgICAgICAgICAgICAgICAgICAgICJFeHBvcnRzIG9mIGdvb2RzIGFuZCBzZXJ2aWNlcyIsCiAgICAgICAgICAgICAgICAgICAgICJJbXBvcnRzIG9mIGdvb2RzIGFuZCBzZXJ2aWNlcyIpKSAlPiUKICBmaWx0ZXIoIShjb3VudHJ5ICVpbiUgYygiRm9ybWVyIFVTU1IiLCAiRm9ybWVyIE5ldGhlcmxhbmRzIEFudGlsbGVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlllbWVuOiBGb3JtZXIgRGVtb2NyYXRpYyBZZW1lbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJVbml0ZWQgUmVwdWJsaWMgb2YgVGFuemFuaWE6IFphbnppYmFyIikpKSAlPiUgCiAgZmlsdGVyKCEoY291bnRyeSA9PSAiWWVtZW46IEZvcm1lciBZZW1lbiBBcmFiIFJlcHVibGljIiAmIFllYXIgPj0gMTk4OSkpICU+JSAKICBmaWx0ZXIoIShjb3VudHJ5ID09ICJGb3JtZXIgQ3plY2hvc2xvdmFraWEiICYgWWVhciA+PSAxOTkwKSkgJT4lIAogIGZpbHRlcighKGNvdW50cnkgPT0gIkZvcm1lciBZdWdvc2xhdmlhIiAmIFllYXIgPj0gMTk5MCkpICU+JSAKICBmaWx0ZXIoIShjb3VudHJ5ID09ICJGb3JtZXIgRXRoaW9waWEiICYgWWVhciA+PSAxOTkwKSkgJT4lIAogIG11dGF0ZShjb3VudHJ5ID0gcmVjb2RlKGNvdW50cnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICJGb3JtZXIgU3VkYW4iID0gIlN1ZGFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAiWWVtZW46IEZvcm1lciBZZW1lbiBBcmFiIFJlcHVibGljIiA9ICJZZW1lbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkZvcm1lciBDemVjaG9zbG92YWtpYSIgPSAiQ3plY2hpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkZvcm1lciBZdWdvc2xhdmlhIiA9ICJTZXJiaWEiKSkgJT4lIAogIG11dGF0ZShpc28zID0gY291bnRyeWNvZGUoY291bnRyeSwgImNvdW50cnkubmFtZSIsICJpc28zYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCJLb3Nvdm8iID0gIlhLSyIpKSkgJT4lIAogIGxlZnRfam9pbihzZWxlY3Qoc2tlbGV0b25fbG9va3VwLCBpc28zLCBnd2NvZGUpLCBieSA9ICJpc28zIikgJT4lIAogIGZpbHRlcighaXMubmEoZ3djb2RlKSkKCnVuX2dkcF93aWRlIDwtIHVuX2dkcCAlPiUgCiAgc2VsZWN0KGd3Y29kZSwgeWVhciA9IFllYXIsIEl0ZW0sIFZhbHVlLCB2YWx1ZV90eXBlKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGModmFsdWVfdHlwZSwgSXRlbSksIHZhbHVlc19mcm9tID0gVmFsdWUpICU+JSAKICByZW5hbWUoZXhwb3J0c19jb25zdGFudF8yMDE1ID0gYENvbnN0YW50X0V4cG9ydHMgb2YgZ29vZHMgYW5kIHNlcnZpY2VzYCwKICAgICAgICAgaW1wb3J0c19jb25zdGFudF8yMDE1ID0gYENvbnN0YW50X0ltcG9ydHMgb2YgZ29vZHMgYW5kIHNlcnZpY2VzYCwKICAgICAgICAgZ2RwX2NvbnN0YW50XzIwMTUgPSBgQ29uc3RhbnRfR3Jvc3MgRG9tZXN0aWMgUHJvZHVjdCAoR0RQKWAsCiAgICAgICAgIGV4cG9ydHNfY3VycmVudCA9IGBDdXJyZW50X0V4cG9ydHMgb2YgZ29vZHMgYW5kIHNlcnZpY2VzYCwKICAgICAgICAgaW1wb3J0c19jdXJyZW50ID0gYEN1cnJlbnRfSW1wb3J0cyBvZiBnb29kcyBhbmQgc2VydmljZXNgLAogICAgICAgICBnZHBfY3VycmVudCA9IGBDdXJyZW50X0dyb3NzIERvbWVzdGljIFByb2R1Y3QgKEdEUClgKSAlPiUKICBtdXRhdGUoZ2RwX2RlZmxhdG9yID0gZ2RwX2N1cnJlbnQgLyBnZHBfY29uc3RhbnRfMjAxNSAqIDEwMCkKCiMgUmVzY2FsZSB0aGUgMjAxNSBkYXRhIHRvIDIwMTEgdG8gbWF0Y2ggQWlkRGF0YQojCiMgRGVmbGF0b3IgPSBjdXJyZW50IEdEUCAvIGNvbnN0YW50IEdEUCAqIDEwMAojIEN1cnJlbnQgR0RQIGluIHllYXJfdCAqIChkZWZsYXRvciBpbiB5ZWFyX3RhcmdldCAvIGRlZmxhdG9yIGluIHllYXJfdCkKdW5fZ2RwX3Jlc2NhbGVkIDwtIHVuX2dkcF93aWRlICU+JQogIGxlZnRfam9pbihzZWxlY3QoZmlsdGVyKHVuX2dkcF93aWRlLCB5ZWFyID09IDIwMTEpLAogICAgICAgICAgICAgICAgICAgZ3djb2RlLCBkZWZsYXRvcl90YXJnZXRfeWVhciA9IGdkcF9kZWZsYXRvciksCiAgICAgICAgICAgIGJ5ID0gImd3Y29kZSIpICU+JQogIG11dGF0ZSh1bl9nZHBfMjAxMSA9IGdkcF9jdXJyZW50ICogKGRlZmxhdG9yX3RhcmdldF95ZWFyIC8gZ2RwX2RlZmxhdG9yKSwKICAgICAgICAgdW5fdHJhZGVfcGN0X2dkcCA9IChpbXBvcnRzX2N1cnJlbnQgKyBleHBvcnRzX2N1cnJlbnQpIC8gZ2RwX2N1cnJlbnQpIAoKdW5fZ2RwX2ZpbmFsIDwtIHVuX2dkcF9yZXNjYWxlZCAlPiUKICBzZWxlY3QoZ3djb2RlLCB5ZWFyLCB1bl90cmFkZV9wY3RfZ2RwLCB1bl9nZHAgPSB1bl9nZHBfMjAxMSkKCmdsaW1wc2UodW5fZ2RwX2ZpbmFsKQpgYGAKCgojIFVDRFAvUFJJTyBBcm1lZCBDb25mbGljdAoKVGhlIFtVQ0RQL1BSSU8gQXJtZWQgQ29uZmxpY3QgRGF0YXNldF0oaHR0cDovL3VjZHAudXUuc2UvZG93bmxvYWRzLykgdHJhY2tzIGEgdG9uIG9mIGNvbmZsaWN0LXJlbGVhdGVkIGRhdGEsIGluY2x1ZGluZyByZWFzb25zIGZvciB0aGUgY29uZmxpY3QsIHBhcnRpZXMgaW4gdGhlIGNvbmZsaWN0LCBpbnRlbnNpdHkgb2YgdGhlIGNvbmZsaWN0LCBhbmQgZGVhdGhzIGluIHRoZSBjb25mbGljdC4gV2UncmUgb25seSBpbnRlcmVzdGVkIGluIHdoZXRoZXIgYSBjb25mbGljdCBoYXBwZW5lZCBpbiBhIGdpdmVuIHllYXIgKG9yIGluIHRoZSBwYXN0IDUgeWVhcnMpLCBzbyBoZXJlIHdlIHNpbXBseSBjcmVhdGUgYW4gaW5kaWNhdG9yIHZhcmlhYmxlIGZvciB3aGV0aGVyIHRoZXJlIHdhcyBpbnRlcm5hbCBjb25mbGljdCBpbiBhIGNvdW50cnkteWVhciAoY29uZmxpY3QgdHlwZSA9IDMpLiAgCgpgYGB7ciBjbGVhbi11Y2RwLXByaW99CnVjZHBfcHJpb19jbGVhbiA8LSB1Y2RwX3ByaW9fcmF3ICU+JSAKICBmaWx0ZXIodHlwZV9vZl9jb25mbGljdCA9PSAzKSAlPiUKICBtdXRhdGUoZ3djb2RlX3JhdyA9IHN0cl9zcGxpdChnd25vX2EsIHBhdHRlcm4gPSAiLCAiKSkgJT4lIAogIHVubmVzdChnd2NvZGVfcmF3KSAlPiUgCiAgbXV0YXRlKGd3Y29kZSA9IGFzLmludGVnZXIoZ3djb2RlX3JhdykpICU+JSAKICBncm91cF9ieShnd2NvZGUsIHllYXIpICU+JSAKICBzdW1tYXJpemUoaW50ZXJuYWxfY29uZmxpY3QgPSBuKCkgPiAwKSAlPiUgCiAgdW5ncm91cCgpCgpnbGltcHNlKHVjZHBfcHJpb19jbGVhbikKYGBgCgoKIyBOYXR1cmFsIGRpc2FzdGVycwoKTmF0dXJhbCBkaXNhc3RlciBkYXRhIGNvbWVzIGZyb20gdGhlIFtJbnRlcm5hdGlvbmFsIERpc2FzdGVyIERhdGFiYXNlIChFTS1EQVQpXShodHRwOi8vd3d3LmVtZGF0LmJlL2RhdGFiYXNlKS4gVGhlIGRhdGEgaW5jbHVkZXMgdGhlIG51bWJlciBvZiBkZWF0aHMsIGluanVyaWVzLCBob21lbGVzcyBkaXNwbGFjZW1lbnRzLCBhbmQgbW9uZXRhcnkgbG9zc2VzIChpbiAyMDAwIGRvbGxhcnMpIGZvciBhIGh1Z2UgbnVtYmVyIG9mIG5hdHVyYWwgYW5kIHRlY2hub2xvZ2ljYWwgZGlzYXN0ZXJzIChzZWUgW0VNLURBVCdzIGZ1bGwgY2xhc3NpZmljYXRpb25dKGh0dHA6Ly93d3cuZW1kYXQuYmUvY2xhc3NpZmljYXRpb24pKS4KCk5hdHVyYWwgZGlzYXN0ZXJzIGNvdWxkIG1hdHRlciBmb3IgYWlkIHRvbywgc2luY2UgZG9ub3IgY291bnRyaWVzIG1pZ2h0IGluY3JlYXNlIHRoZWlyIGFpZCB0byBjb3VudHJpZXMgc3VmZmVyaW5nIG1vcmUuIAoKRU0tREFUIGRvZXMgbm90IHByb3ZpZGUgYSBzaW5nbGUgbGluayB0byBkb3dubG9hZCB0aGVpciBkYXRhLiBJbnN0ZWFkLCB5b3UgaGF2ZSB0byBjcmVhdGUgYSBxdWVyeSB1c2luZyBbdGhlaXIgYWR2YW5jZWQgc2VhcmNoIGZvcm1dKGh0dHA6Ly93d3cuZW1kYXQuYmUvYWR2YW5jZWRfc2VhcmNoL2luZGV4Lmh0bWwpLiBXZSBkb3dubG9hZGVkIGRhdGEgdXNpbmcgdGhlIGZvbGxvd2luZyBxdWVyeToKCi0gU2VsZWN0IGFsbCBjb3VudHJpZXMgZnJvbSAxOTUw4oCTMjAyMQotIFNlbGVjdCBhbGwgdGhyZWUgZGlzYXN0ZXIgY2xhc3NpZmljYXRpb24gZ3JvdXBzIChuYXR1cmFsLCB0ZWNobm9sb2dpY2FsLCBjb21wbGV4KQotIERvd25sb2FkIEV4Y2VsIGZpbGUgYW5kIHNhdmUgaW4gYERhdGEvcmF3X2RhdGEvRGlzYXN0ZXJzL2AKCmBgYHtyIGxvYWQtZGlzYXN0ZXJzLCBtZXNzYWdlPUZBTFNFfQpkaXNhc3RlcnNfcmF3IDwtIHJlYWRfZXhjZWwoaGVyZSgiZGF0YSIsICJyYXdfZGF0YSIsICJEaXNhc3RlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZW1kYXRfcHVibGljXzIwMjFfMDFfMTZfcXVlcnlfdWlkLXVmQmJFMi54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwID0gNikKCmRpc2FzdGVycyA8LSBkaXNhc3RlcnNfcmF3ICU+JQogICMgT25seSBsb29rIGF0IGNvdW50cmllcyBpbiB0aGUgbWFpbiBwYW5lbAogIGZpbHRlcihJU08gJWluJSB1bmlxdWUocGFuZWxfc2tlbGV0b24kaXNvMykpICU+JQogIGZpbHRlcihgRGlzYXN0ZXIgR3JvdXBgICE9ICJDb21wbGV4IERpc2FzdGVycyIpICU+JSAKICBtdXRhdGUoZ3djb2RlID0gY291bnRyeWNvZGUoSVNPLCBvcmlnaW4gPSAiaXNvM2MiLCBkZXN0aW5hdGlvbiA9ICJnd24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKCJZRU0iID0gIjY3OCIpKSwKICAgICAgICAgZ3djb2RlID0gYXMubnVtZXJpYyhnd2NvZGUpKSAlPiUgCiAgc2VsZWN0KGNvdW50cnkgPSBDb3VudHJ5LCB5ZWFyID0gWWVhciwgaXNvMyA9IElTTywgZ3djb2RlLAogICAgICAgICB0eXBlID0gYERpc2FzdGVyIFR5cGVgLCBncm91cCA9IGBEaXNhc3RlciBHcm91cGAsCiAgICAgICAgIHN1Ymdyb3VwID0gYERpc2FzdGVyIFN1Ymdyb3VwYCwKICAgICAgICAgZGlzX2RlYXRocyA9IGBUb3RhbCBEZWF0aHNgLCBkaXNfaW5qdXJlZCA9IGBObyBJbmp1cmVkYCwKICAgICAgICAgZGlzX2FmZmVjdGVkID0gYE5vIEFmZmVjdGVkYCwgZGlzX2hvbWVsZXNzID0gYE5vIEhvbWVsZXNzYCwKICAgICAgICAgZGlzX3RvdGFsX2FmZmVjdGVkID0gYFRvdGFsIEFmZmVjdGVkYCwgZGlzX3RvdGFsX2RhbWFnZSA9IGBUb3RhbCBEYW1hZ2VzICgnMDAwIFVTJClgKQoKZGlzYXN0ZXJzX3N1bW1hcml6ZWQgPC0gZGlzYXN0ZXJzICU+JSAKICBncm91cF9ieShnd2NvZGUsIHllYXIsIGdyb3VwKSAlPiUgCiAgc3VtbWFyaXplKGFjcm9zcyhzdGFydHNfd2l0aCgiZGlzXyIpLCB+c3VtKC4sIG5hLnJtID0gVFJVRSkpLAogICAgICAgICAgICBkaXNfY291bnQgPSBuKCkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihncm91cCA9PSAiTmF0dXJhbCIpICU+JSAKICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAibmFtZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIsIHN0YXJ0c193aXRoKCJkaXNfIikpICU+JSAKICBtdXRhdGUoZ3JvdXAgPSBzdHJfdG9fbG93ZXIoZ3JvdXApKSAlPiUgCiAgdW5pdGUobmFtZSwgZ3JvdXAsIG5hbWUpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gIm5hbWUiLCB2YWx1ZXNfZnJvbSA9ICJ2YWx1ZSIpICU+JSAKICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoeWVhcikpICU+JSAKICBmaWx0ZXIoeWVhciA+IDE5ODApCgpkaXNhc3RlcnNfc3VtbWFyaXplZCAlPiUgZ2xpbXBzZSgpCmBgYAoKCiMgQ2xlYW4gY29tYmluZWQgZGF0YQoKV2l0aCBib3RoIGRvbm9yLSBhbmQgY291bnRyeS1sZXZlbCBkYXRhLCB3ZSBoYXZlIGxvdHMgb2YgZGlmZmVyZW50IG9wdGlvbnMgZm9yIGFuYWx5c2lzLiBTaW5jZSBvdXIgaHlwb3RoZXNlcyBkZWFsIHdpdGggcXVlc3Rpb25zIG9mICpkb25vciogcmVzcG9uc2VzLCB0aGUgZGF0YSB3ZSB1c2UgdG8gbW9kZWwgZG9ub3IgcmVzcG9uc2VzIHVzZXMgZG9ub3IteWVhcnMgYXMgdGhlIHVuaXQgb2Ygb2JzZXJ2YXRpb24uIE5vdCBhbGwgZG9ub3JzIGdpdmUgbW9uZXkgdG8gdGhlIHNhbWUgY291bnRyaWVzLCBzbyB0aGlzIGZpbmFsIGRhdGEgaXMgbm90IGEgY29tcGxldGUgcGFuZWwgKGkuZS4gaXQgZG9lcyBub3QgaW5jbHVkZSBldmVyeSBjb21iaW5hdGlvbiBvZiBkb25vcnMgYW5kIHllYXJzKSwgd2hpY2ggd2lsbCBwb3NlIHNvbWUgaW50ZXJlc3RpbmcgbWV0aG9kb2xvZ2ljYWwgaXNzdWVzIHdoZW4gbW9kZWxpbmcgaWYgd2UgdXNlIGRvbm9yLWxldmVsIGRhdGEuCgpgYGB7ciBjcmVhdGUtZG9ub3ItZGF0YX0KZG9ub3JfYWlkcmF3X2RhdGEgPC0gYWlkZGF0YV9maW5hbCAlPiUgCiAgZmlsdGVyKGd3Y29kZSAlaW4lIHVuaXF1ZShwYW5lbF9za2VsZXRvbiRnd2NvZGUpKSAlPiUKICBmaWx0ZXIoeWVhciA+IDE5ODApICU+JQogIGZpbHRlcihvZGEgPiAwKSAlPiUgICMgT25seSBsb29rIGF0IHBvc2l0aXZlIGFpZAogIG11dGF0ZShvZGFfbG9nID0gbG9nMXAob2RhKSkKCiMgQ3JlYXRlIGZha2UgY291bnRyeSBjb2RlcyBmb3Igbm9uLWNvdW50cnkgZG9ub3JzCmZha2VfY29kZXMgPC0gZG9ub3JfYWlkcmF3X2RhdGEgJT4lCiAgZGlzdGluY3QoZG9ub3IsIGRvbm9yX3R5cGUpICU+JQogIGZpbHRlcihkb25vcl90eXBlICE9ICJDb3VudHJ5IikgJT4lCiAgYXJyYW5nZShkb25vcl90eXBlKSAlPiUgc2VsZWN0KC1kb25vcl90eXBlKSAlPiUKICBtdXRhdGUoZmFrZV9kb25vcl9nd2NvZGUgPSAyMDAxOigyMDAwICsgbigpKSwKICAgICAgICAgZmFrZV9kb25vcl9pc28zID0gcGFzdGUwKCJaIiwgc3RyX3N1YihmYWtlX2Rvbm9yX2d3Y29kZSwgMykpKQoKZG9ub3JfbGV2ZWxfZGF0YSA8LSBkb25vcl9haWRyYXdfZGF0YSAlPiUKICBsZWZ0X2pvaW4oZmFrZV9jb2RlcywgYnkgPSAiZG9ub3IiKSAlPiUKICBtdXRhdGUoZG9ub3JfZ3djb2RlID0gaWZlbHNlKGlzLm5hKGRvbm9yX2d3Y29kZSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFrZV9kb25vcl9nd2NvZGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9ub3JfZ3djb2RlKSwKICAgICAgICAgZG9ub3JfaXNvMyA9IGlmZWxzZShpcy5uYShkb25vcl9pc28zKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFrZV9kb25vcl9pc28zLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25vcl9pc28zKSkgJT4lCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgiZmFrZSIpKQpgYGAKClVTQUlEJ3MgY29udmVyc2lvbiB0byBjb25zdGFudCAyMDE1IGRvbGxhcnMgZG9lc24ndCBzZWVtIHRvIHRha2UgY291bnRyeSBkaWZmZXJlbmNlcyBpbnRvIGFjY291bnTigJR0aGUgZGVmbGF0b3IgZm9yIGVhY2ggY291bnRyeSBpbiAyMDExIGlzIGVzc2VudGlhbGx5IDk2LjY1LiBXaGVuIHRoZXJlIGFyZSBkaWZmZXJlbmNlcywgaXQncyBiZWNhdXNlIG9mIGZsb2F0aW5nIHBvaW50IGlzc3VlcyAobGlrZSwgaWYgdGhlcmUgYXJlIHRpbnkgZ3JhbnRzIG9mICQzLCB0aGVyZSBhcmVuJ3QgZW5vdWdoIGRlY2ltYWwgcG9pbnRzIHRvIGdldCB0aGUgZnJhY3Rpb24gdG8gOTYuNjUpLiBTbyB3ZSBqdXN0IHRha2UgdGhlIG1lZGlhbiB2YWx1ZSBvZiB0aGUgZGVmbGF0b3IgZm9yIGFsbCBjb3VudHJpZXMgYW5kIGFsbCBncmFudHMgYW5kIHVzZSB0aGF0LgoKYGBge3IgZml4LXVzYWlkLWRhdGF9CiMgUmVzY2FsZSB0aGUgMjAxNSBkYXRhIHRvIDIwMTEgdG8gbWF0Y2ggQWlkRGF0YQojCiMgRGVmbGF0b3IgPSBjdXJyZW50IGFpZCAvIGNvbnN0YW50IGFpZCAqIDEwMAojIEN1cnJlbnQgYWlkIGluIHllYXJfdCAqIChkZWZsYXRvciBpbiB5ZWFyX3RhcmdldCAvIGRlZmxhdG9yIGluIHllYXJfdCkKdXNhaWRfZGVmbGF0b3JfMjAxMSA8LSB1c2FpZF9jbGVhbiAlPiUKICBmaWx0ZXIoeWVhciA9PSAyMDExKSAlPiUKICBzdW1tYXJpc2UoZGVmbGF0b3JfdGFyZ2V0X3llYXIgPSBtZWRpYW4oYWlkX2RlZmxhdG9yLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBhcy5udW1lcmljKCkKCmRvbm9yX2xldmVsX2RhdGFfdXNhaWQgPC0gdXNhaWRfY2xlYW4gJT4lCiAgZmlsdGVyKGd3Y29kZSAlaW4lIHVuaXF1ZShwYW5lbF9za2VsZXRvbiRnd2NvZGUpKSAlPiUKICBmaWx0ZXIoeWVhciA+IDE5ODApICU+JQogIGZpbHRlcihvZGFfdXNfY3VycmVudCA+IDApICU+JQogIG11dGF0ZShvZGFfdXNfMjAxMSA9IG9kYV91c19jdXJyZW50ICogKHVzYWlkX2RlZmxhdG9yXzIwMTEgLyBhaWRfZGVmbGF0b3IpKSAlPiUgCiAgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKQoKdXNhaWRfYnlfY291bnRyeV90b3RhbCA8LSBkb25vcl9sZXZlbF9kYXRhX3VzYWlkICU+JQogIGdyb3VwX2J5KGd3Y29kZSwgeWVhcikgJT4lCiAgc3VtbWFyaXNlKG9kYV91cyA9IHN1bShvZGFfdXNfMjAxMSwgbmEucm0gPSBUUlVFKSkKCnVzYWlkX2J5X2NvdW50cnlfY2hhbm5lbCA8LSBkb25vcl9sZXZlbF9kYXRhX3VzYWlkICU+JQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJrZXkiLCB2YWx1ZXNfdG8gPSAidmFsdWUiLCAKICAgICAgICAgICAgICAgYyhjaGFubmVsX25nb191cywgY2hhbm5lbF9uZ29faW50LCBjaGFubmVsX25nb19kb20pKSAlPiUKICBncm91cF9ieShnd2NvZGUsIHllYXIsIGtleSwgdmFsdWUpICU+JQogIHN1bW1hcmlzZSh0b3RhbF9vZGFfdXMgPSBzdW0ob2RhX3VzXzIwMTEsIG5hLnJtID0gVFJVRSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICB1bml0ZShjaGFubmVsLCBrZXksIHZhbHVlKSAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdChjaGFubmVsLCAiVFJVRSIpKSAlPiUKICBtdXRhdGUoY2hhbm5lbCA9IHN0cl9yZXBsYWNlKGNoYW5uZWwsICJjaGFubmVsIiwgIm9kYV91cyIpLAogICAgICAgICBjaGFubmVsID0gc3RyX3JlcGxhY2UoY2hhbm5lbCwgIl9UUlVFIiwgIiIpKSAlPiUKICBzcHJlYWQoY2hhbm5lbCwgdG90YWxfb2RhX3VzLCBmaWxsID0gMCkKYGBgCgpgYGB7ciBjcmVhdGUtY291bnRyeS1kYXRhfQojIENvdW50cnkgZGF0YQpjb3VudHJ5X2xldmVsX2RhdGEgPC0gcGFuZWxfc2tlbGV0b24gJT4lIAogIG11dGF0ZShldmVyX2RhY19lbGlnaWJsZSA9IGd3Y29kZSAlaW4lIGV2ZXJfZGFjX2VsaWdpYmxlKSAlPiUgCiAgZmlsdGVyKCEoZ3djb2RlICVpbiUgY29uc29saWRhdGVkX2RlbW9jcmFjaWVzJGd3Y29kZSkpICU+JSAKICBsZWZ0X2pvaW4odW5fZ2RwX2ZpbmFsLCBieSA9IGMoImd3Y29kZSIsICJ5ZWFyIikpICU+JSAKICBsZWZ0X2pvaW4odW5fcG9wLCBieSA9IGMoImd3Y29kZSIsICJ5ZWFyIikpICU+JSAKICBtdXRhdGUoZ2RwY2FwID0gdW5fZ2RwIC8gcG9wdWxhdGlvbiwKICAgICAgICAgZ2RwY2FwX2xvZyA9IGxvZyhnZHBjYXApLAogICAgICAgICBwb3B1bGF0aW9uX2xvZyA9IGxvZyhwb3B1bGF0aW9uKSkgJT4lIAogIGxlZnRfam9pbihjaGF1ZGhyeV9jbGVhbiwgYnkgPSBjKCJnd2NvZGUiLCAieWVhciIpKSAlPiUgCiAgIyBJbmRpY2F0b3IgZm9yIENoYXVkaHJ5IGRhdGEgY292ZXJhZ2UKICAjIENoYXVkaHJ5J3MgU2VyYmlhIGRhdGEgc3RhcnRzIHdpdGggMjAwNiBhbmQgZG9lc24ndCBpbmNsdWRlIHByZS0yMDA2IHN0dWZmLAogICMgc28gd2UgbWFyayB0aG9zZSBhcyBmYWxzZS4gQWxzbywgQ2hhdWRocnkgc3RhcnRzIGluIDE5OTIgZm9yIFJ1c3NpYSBhbmQgMTk5MwogICMgZm9yIEN6ZWNoaWEsIHNvIHdlIG1hcmsgdGhvc2UgYXMgZmFsc2UgdG9vCiAgbXV0YXRlKGxhd3MgPSB5ZWFyICVpbiUgMTk5MDoyMDE0KSAlPiUgCiAgbXV0YXRlKGxhd3MgPSBjYXNlX3doZW4oCiAgICMgU2VyYmlhLCBDemVjaGlhLCBhbmQgUnVzc2lhCiAgIGd3Y29kZSA9PSAzNDUgJiB5ZWFyIDw9IDIwMDUgfiBGQUxTRSwKICAgZ3djb2RlID09IDMxNiAmIHllYXIgPD0gMTk5MiB+IEZBTFNFLAogICBnd2NvZGUgPT0gMzY1ICYgeWVhciA8PSAxOTkxIH4gRkFMU0UsCiAgIFRSVUUgfiBsYXdzICAjIE90aGVyd2lzZSwgdXNlIEZBTFNFCiAgKSkgJT4lIAogIGxlZnRfam9pbih2ZGVtX2NsZWFuLCBieSA9IGMoImd3Y29kZSIsICJ5ZWFyIikpICU+JQogIGxlZnRfam9pbih1Y2RwX3ByaW9fY2xlYW4sIGJ5ID0gYygiZ3djb2RlIiwgInllYXIiKSkgJT4lIAogICMgVHJlYXQgTkFzIGluIGNvbmZsaWN0cyBhcyBGQUxTRQogIG11dGF0ZShpbnRlcm5hbF9jb25mbGljdCA9IGlmZWxzZShpcy5uYShpbnRlcm5hbF9jb25mbGljdCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZBTFNFLCBpbnRlcm5hbF9jb25mbGljdCkpICU+JQogIGxlZnRfam9pbihkaXNhc3RlcnNfc3VtbWFyaXplZCwgCiAgICAgICAgICAgIGJ5ID0gYygiZ3djb2RlIiwgInllYXIiKSkgJT4lIAogICMgTkFzIGluIGRpc2FzdGVycyBhcmUgcmVhbGx5IDAsIGVzcGVjaWFsbHkgd2hlbiBvY2N1cnJlbmNlIGlzIDAKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgibmF0dXJhbF8iKSksIH5pZmVsc2UoaXMubmEoLiksIDAsIC4pKSAlPiUKICAjIEFkZCBpbmRpY2F0b3IgZm9yIHBvc3QtQ29sZCBXYXIsIHNpbmNlIGFsbCB0aGUgZm9ybWVyIFNvdmlldCByZXB1YmxpY3MgaGF2ZQogICMgbm8gR0RQIGRhdGEgYmVmb3JlIDE5OTAKICBtdXRhdGUocG9zdF8xOTg5ID0geWVhciA+PSAxOTkwKQp0ZXN0dGhhdDo6ZXhwZWN0X2VxdWFsKG5yb3coY291bnRyeV9sZXZlbF9kYXRhKSwgbnJvdyhwYW5lbF9za2VsZXRvbikpCgojIENvbWJpbmUgY291bnRyeSBhbmQgZG9ub3IgZGF0YQpkb25vcl9jb3VudHJ5X2RhdGEgPC0gZG9ub3JfbGV2ZWxfZGF0YSAlPiUKICBsZWZ0X2pvaW4oc2VsZWN0KGNvdW50cnlfbGV2ZWxfZGF0YSwgLWNvdW50cnksIC1pc28zKSwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwgImd3Y29kZSIpKSAlPiUgCiAgYXJyYW5nZShkb25vciwgeWVhcikKdGVzdHRoYXQ6OmV4cGVjdF9lcXVhbChucm93KGRvbm9yX2NvdW50cnlfZGF0YSksIG5yb3coZG9ub3JfbGV2ZWxfZGF0YSkpCgojIENhbGN1bGF0ZSBkaWZmZXJlbnQgdmVyc2lvbnMgb2YgYWlkIHZhcmlhYmxlcwphaWRfYnlfY291bnRyeV90b3RhbCA8LSBkb25vcl9jb3VudHJ5X2RhdGEgJT4lCiAgZ3JvdXBfYnkoZ3djb2RlLCB5ZWFyKSAlPiUKICBzdW1tYXJpc2UodG90YWxfb2RhID0gc3VtKG9kYSwgbmEucm0gPSBUUlVFKSkgJT4lIAogIHVuZ3JvdXAoKQoKYWlkX2J5X2NvdW50cnlfcHVycG9zZSA8LSBkb25vcl9jb3VudHJ5X2RhdGEgJT4lCiAgZ3JvdXBfYnkoZ3djb2RlLCB5ZWFyLCBwdXJwb3NlX2NvbnRlbnRpb3VzbmVzcykgJT4lCiAgc3VtbWFyaXNlKHRvdGFsX29kYSA9IHN1bShvZGEsIG5hLnJtID0gVFJVRSkpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAicHVycG9zZV9jb250ZW50aW91c25lc3MiLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9ICJ0b3RhbF9vZGEiLCB2YWx1ZXNfZmlsbCA9IDApICU+JSAKICByZW5hbWUob2RhX2NvbnRlbnRpb3VzX2hpZ2ggPSBIaWdoLCAKICAgICAgICAgb2RhX2NvbnRlbnRpb3VzX2xvdyA9IExvdykgJT4lIAogIHVuZ3JvdXAoKQoKY291bnRyeV9haWQgPC0gY291bnRyeV9sZXZlbF9kYXRhICU+JSAKICBsZWZ0X2pvaW4oYWlkX2J5X2NvdW50cnlfdG90YWwsIGJ5ID0gYygieWVhciIsICJnd2NvZGUiKSkgJT4lIAogIGxlZnRfam9pbihhaWRfYnlfY291bnRyeV9wdXJwb3NlLCBieSA9IGMoInllYXIiLCAiZ3djb2RlIikpICU+JSAKICBsZWZ0X2pvaW4odXNhaWRfYnlfY291bnRyeV90b3RhbCwgYnkgPSBjKCJ5ZWFyIiwgImd3Y29kZSIpKSAlPiUgCiAgbGVmdF9qb2luKHVzYWlkX2J5X2NvdW50cnlfY2hhbm5lbCwgYnkgPSBjKCJ5ZWFyIiwgImd3Y29kZSIpKSAlPiUgCiAgbXV0YXRlKGFjcm9zcyhjb250YWlucygib2RhIiksIH5pZmVsc2UoaXMubmEoLiksIDAsIC4pKSkKCnRlc3R0aGF0OjpleHBlY3RfZXF1YWwobnJvdyhjb3VudHJ5X2FpZCksIG5yb3cocGFuZWxfc2tlbGV0b24pKQpgYGAKCiMgTWlzc2luZyBkYXRhCgpUaGUgZG9ub3IgZGF0YSBpcyBjb21wbGV0ZSB3aXRoIG5vIG1pc3NpbmcgdmFyaWFibGVzKCEpLgoKYGBge3IgZmluYWwtZGF0YS1taXNzaW5nLWRvbm9ycywgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9M30KZ2dfbWlzc192YXIoZG9ub3JfbGV2ZWxfZGF0YSwgc2hvd19wY3QgPSBUUlVFKQpgYGAKClRoZSBjb3VudHJ5LWxldmVsIHBhbmVsIGRhdGEgaXMgcmVsYXRpdmVseSBjb21wbGV0ZSwgd2l0aCBvbmx5IGEgZmV3IHZhcmlhYmxlcyBzdWZmZXJpbmcgZnJvbSBtaXNzaW5nIGRhdGEsIG1vc3RseSBmcm9tIHRoZSBXb3JsZCBCYW5rIGFuZCBWLURlbS4gVGhlcmUgYXJlIGEgbG90IG9mIE5HTy1yZWxhdGVkIG1pc3NpbmcgdmFyaWFibGVzLCBidXQgdGhhdCdzIGJlY2F1c2Ugd2UgZG9uJ3QgaGF2ZSBkYXRhIGZyb20gMTk4MOKAkzE5ODkgYW5kIDIwMTUrCgpgYGB7ciBkYXRhLW1pc3NpbmctY291bnRyaWVzLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD03fQpnZ19taXNzX3Zhcihjb3VudHJ5X2FpZCwgc2hvd19wY3QgPSBUUlVFKQpgYGAKCmBgYHtyIGRhdGEtbWlzc2luZy1jb3VudHJpZXMtc2Fucy1sYXdzLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD03fQpjb3VudHJ5X2FpZCAlPiUgCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgiZnVuZGluZyIpLCAtc3RhcnRzX3dpdGgoImVudHJ5IiksIAogICAgICAgICAtc3RhcnRzX3dpdGgoImFkdm9jYWN5IiksIC1zdGFydHNfd2l0aCgiYmFycmllcnMiKSkgJT4lIAogIGdnX21pc3NfdmFyKC4sIHNob3dfcGN0ID0gVFJVRSkKYGBgCgpIZXJlJ3MgaG93IHdlIGFkZHJlc3MgdGhhdDoKCi0gV2UgcmVtb3ZlIGV2ZXJ5dGhpbmcgZnJvbSBZdWdvc2xhdmlhL1NlcmJpYSBhbmQgTW9udGVuZWdybyAoMzQ1KSBwcmlvciB0byAyMDA2CgotIEluZmFudCBtb3J0YWxpdHkgYGVfcGVpbmZtb3JgIGlzIG1pc3NpbmcgZnJvbSBLb3Nvdm8gKDIwMDjigJMyMDE0KSwgYW5kIHRoZSBXb3JsZCBCYW5rIGRvZXNuJ3QgaGF2ZSBkYXRhIGZvciBpdCwgYnV0IEV1cm9zdGF0IGRvZXMgaW4gW3RoZWlyIGBkZW1vX21pbmZpbmRgIGluZGljYXRvcl0oaHR0cHM6Ly9lYy5ldXJvcGEuZXUvZXVyb3N0YXQvZGF0YWJyb3dzZXIvdmlldy9ERU1PX01JTkZJTkRfX2N1c3RvbV82NjA2NjQvZGVmYXVsdC90YWJsZT9sYW5nPWVuKS4gVGhlaXIgZGF0YSwgaG93ZXZlciwgaXMgbWlzc2luZyBhIGNvdXBsZSB5ZWFycwoKYGBge3Igc2hvdy1rb3Nvdm8taW5mYW50LW1vcnQsIGluZGVudD0iICAgICJ9Cmtvc292b19pbmZhbnRfbW9ydCA8LSB0aWJibGUoeWVhciA9IDIwMDc6MjAxOSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlX3BlaW5mbW9yID0gYygxMS4xLCA5LjcsIDkuOSwgOC44LCAxMy4xLCAxMS40LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwgTkEsIDkuNywgOC41LCA5LjcsIDEwLjYsIDguNykpCmtvc292b19pbmZhbnRfbW9ydApgYGAKCiAgICBUbyBmaXggdGhpcywgd2UgdXNlIGxpbmVhciBpbnRlcnBvbGF0aW9uIHRvIGZpbGwgaW4gMjAxMyBhbmQgMjAxNDoKCmBgYHtyIGZpeC1rb3Nvdm8taW5mYW50LW1vcnQsIGluZGVudD0iICAgICJ9Cmtvc292b19pbmZhbnRfbW9ydCA8LSB6b286Om5hLmFwcHJveChrb3Nvdm9faW5mYW50X21vcnQpICU+JSAKICBhc190aWJibGUoKSAlPiUgcmVuYW1lKGVfcGVpbmZtb3JfaW50ZXJwID0gZV9wZWluZm1vcikgJT4lIAogIG11dGF0ZShnd2NvZGUgPSAzNDcpCmtvc292b19pbmZhbnRfbW9ydApgYGAKCi0gYHYyeF9jb3JyYCBpcyBvbmx5IG1pc3NpbmcgZGF0YSBmcm9tIEJhaHJhaW4sIHdoaWNoIG9kZGx5IGhhcyBubyBkYXRhIGZyb20gMTk4MOKAkzIwMDQuIEJlY2F1c2UgY29ycnVwdGlvbiBsZXZlbHMgZG8gbm90IHJlYWxseSBjaGFuZ2UgYWZ0ZXIgMjAwNSwgd2UgaW1wdXRlIHRoZSBhdmVyYWdlIGNvcnJ1cHRpb24gZm9yIHRoZSBjb3VudHJ5IGluIGFsbCBwcmV2aW91cyB5ZWFycy4KCi0gYHYyeF9wb2x5YXJjaHlgIGlzIG9ubHkgbWlzc2luZyBpbiBNb3phbWJpcXVlIGZyb20gMTk4MOKAkzE5OTMuIFRvIGFkZHJlc3MgdGhpcywgd2UgY2FsY3VsYXRlIHRoZSBhdmVyYWdlIHZhbHVlIG9mIFYtRGVtJ3MgcG9seWFyY2h5IGluZGV4IChgdjJ4X3BvbHlhcmNoeWApIGZvciBlYWNoIGxldmVsIG9mIFBvbGl0eSAo4oiSOCwg4oiSNywgYW5kIOKIkjYgaW4gdGhlIGNhc2Ugb2YgTW96YW1iaXF1ZSksIGFuZCB0aGVuIHVzZSB0aGF0IGNvcnJlc3BvbmRpbmcgYXZlcmFnZSBwb2x5YXJjaHkKCi0gV2UgYWxzbyBjcmVhdGUgYW4gYGltcHV0ZWRgIGNvbHVtbiBmb3IgdGhvc2Ugcm93cyBpbiBCYWhyYWluIGFuZCBNb3phbWJpcXVlIHRvIHNlZSBpZiBpbXB1dGF0aW9uIGRvZXMgYW55dGhpbmcgd2VpcmQgaW4gdGhlIG1vZGVscwoKYGBge3IgZmluYWwtdHdlYWtzfQojIEZpbmQgQmFocmFpbidzIGF2ZXJhZ2UgY29ycnVwdGlvbgphdmdfY29ycnVwdGlvbl9iaHIgPC0gY291bnRyeV9haWQgJT4lIAogIGZpbHRlcihpc28zID09ICJCSFIiKSAlPiUgCiAgc3VtbWFyaXplKGF2Z19jb3JyID0gbWVhbih2MnhfY29yciwgbmEucm0gPSBUUlVFKSkgJT4lIAogIHB1bGwoYXZnX2NvcnIpCgojIEZpbmQgYXZlcmFnZSBwb2x5YXJjaHkgc2NvcmVzIGFjcm9zcyBkaWZmZXJlbnQgcHJlLTE5OTQgcG9saXR5IHNjb3JlcwphdmdfcG9seWFyY2h5X3BvbGl0eSA8LSBjb3VudHJ5X2FpZCAlPiUgCiAgZmlsdGVyKHllYXIgPCAxOTk0KSAlPiUgCiAgZ3JvdXBfYnkoZV9wb2xpdHkyKSAlPiUgCiAgc3VtbWFyaXplKGF2Z19wb2x5YXJjaHkgPSBtZWFuKHYyeF9wb2x5YXJjaHksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIG4gPSBuKCkpCgpjb3VudHJ5X2FpZF9jb21wbGV0ZSA8LSBjb3VudHJ5X2FpZCAlPiUgCiAgIyBHZXQgcmlkIG9mIHByZS0yMDA2IFNlcmJpYSBzdHVmZgogIGZpbHRlcighKGd3Y29kZSA9PSAzNDUgJiB5ZWFyIDwgMjAwNikpICU+JSAKICAjIEZpeCBTZXJiaWEgbmFtZQogIG11dGF0ZShjb3VudHJ5ID0gaWZlbHNlKGd3Y29kZSA9PSAzNDUsICJTZXJiaWEiLCBjb3VudHJ5KSkgJT4lIAogIG11dGF0ZSh2MnhfY29yciA9IGlmZWxzZShpcy5uYSh2MnhfY29ycikgJiBpc28zID09ICJCSFIiLCAKICAgICAgICAgYXZnX2NvcnJ1cHRpb25fYmhyLCB2MnhfY29ycikpICU+JSAKICBtdXRhdGUoaW1wdXRlZF9jb3JyID0gaXMubmEodjJ4X2NvcnIpICYgaXNvMyA9PSAiQkhSIikgJT4lIAogIG11dGF0ZSh2MnhfcG9seWFyY2h5ID0gY2FzZV93aGVuKAogICAgaXNvMyA9PSAiTU9aIiAmIGlzLm5hKHYyeF9wb2x5YXJjaHkpICYgZV9wb2xpdHkyID09IC02IH4gCiAgICAgIGZpbHRlcihhdmdfcG9seWFyY2h5X3BvbGl0eSwgZV9wb2xpdHkyID09IC02KSRhdmdfcG9seWFyY2h5LAogICAgaXNvMyA9PSAiTU9aIiAmIGlzLm5hKHYyeF9wb2x5YXJjaHkpICYgZV9wb2xpdHkyID09IC03IH4gCiAgICAgIGZpbHRlcihhdmdfcG9seWFyY2h5X3BvbGl0eSwgZV9wb2xpdHkyID09IC03KSRhdmdfcG9seWFyY2h5LAogICAgaXNvMyA9PSAiTU9aIiAmIGlzLm5hKHYyeF9wb2x5YXJjaHkpICYgZV9wb2xpdHkyID09IC04IH4gCiAgICAgIGZpbHRlcihhdmdfcG9seWFyY2h5X3BvbGl0eSwgZV9wb2xpdHkyID09IC04KSRhdmdfcG9seWFyY2h5LAogICAgVFJVRSB+IHYyeF9wb2x5YXJjaHkKICApKSAlPiUgCiAgbXV0YXRlKGltcHV0ZWRfcG9seWFyY2h5ID0gaXMubmEodjJ4X3BvbHlhcmNoeSkgJiBpc28zID09ICJNT1oiKSAlPiUgCiAgIyBBZGQgS29zb3ZvIGluZmFudCBtb3J0YWxpdHkKICBsZWZ0X2pvaW4oa29zb3ZvX2luZmFudF9tb3J0LCBieSA9IGMoImd3Y29kZSIsICJ5ZWFyIikpICU+JSAKICBtdXRhdGUoZV9wZWluZm1vciA9IGNvYWxlc2NlKGVfcGVpbmZtb3IsIGVfcGVpbmZtb3JfaW50ZXJwKSkgJT4lIAogICMgR2V0IHJpZCBvZiBwb2xpdHkgYW5kIFJvVy0tLXdlIGRvbid0IGFjdHVhbGx5IG5lZWQgdGhlbQogIHNlbGVjdCgtZV9wb2xpdHkyLCAtdjJ4X3JlZ2ltZV9hbWIsIC1lX3BlaW5mbW9yX2ludGVycCkKCmNvdW50cnlfYWlkX2NvbXBsZXRlICU+JSBnbGltcHNlKCkKYGBgCgpNdWNoIGJldHRlciEKCmBgYHtyIGZpbmFsLWRhdGEtbWlzc2luZy1jb3VudHJpZXMtc2Fucy1sYXdzLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD03fQpjb3VudHJ5X2FpZF9jb21wbGV0ZSAlPiUgCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgiZnVuZGluZyIpLCAtc3RhcnRzX3dpdGgoImVudHJ5IiksCiAgICAgICAgIC1zdGFydHNfd2l0aCgiYWR2b2NhY3kiKSwgLXN0YXJ0c193aXRoKCJiYXJyaWVycyIpKSAlPiUKICBnZ19taXNzX3ZhciguLCBzaG93X3BjdCA9IFRSVUUpCmBgYAoKVGhlcmUgYXJlIG9ubHkgdGhyZWUgY291bnRyaWVzIG5vdyB0aGF0IGhhdmUgYW55IG1pc3NpbmcgZGF0YTogCgotICoqS29zb3ZvIGlzIG1pc3NpbmcgcHJlLWV4aXN0ZW5jZSBpbmZhbnQgbW9ydGFsaXR5LCB3aGljaCBpcyBmaW5lIGJlY3Vhc2UgaXQgZGlkbid0IGV4aXN0IHlldC4qKgoKLSAqKlJ1c3NpYSBpcyBtaXNzaW5nIEdEUCwgR0RQIHBlciBjYXBpdGEsIGFuZCBwZXJjZW50IG9mIEdEUCBmcm9tIHRyYWRlIGZyb20gMTk4MOKAkzE5ODkuKiogVGhlcmUncyBubyBlYXN5IHdheSBhcm91bmQgdGhpcy4gVi1EZW0gaGFzIEdEUCBwZXIgY2FwaXRhIGRhdGEgZnJvbSB0aGUgbG9uZy1ydW5uaW5nIFtNYWRkaXNvbiBQcm9qZWN0IERhdGFiYXNlXShodHRwczovL3d3dy5ydWcubmwvZ2dkYy9oaXN0b3JpY2FsZGV2ZWxvcG1lbnQvbWFkZGlzb24vcmVsZWFzZXMvbWFkZGlzb24tcHJvamVjdC1kYXRhYmFzZS0yMDE4KSwgYW5kIGl0IGluY2x1ZGVzIDE5ODBzIFNvdmlldCBSdXNzaWEsIGJ1dCB0aGUgdmFsdWVzIGFyZW4ndCByZWFsbHkgY29tcGFyYWJsZSB0byB0aGUgc3R1ZmYgd2UgY2FsY3VsYXRlZCB1c2luZyBVTiBHRFAgZGF0YS4gQXQgZmlyc3QgZ2xhbmNlIGl0IHNlZW1zIHRoYXQgdGhpcyBpcyBhIGRpZmZlcmVuY2UgaW4gcmVhbCB5ZWFycywgc2luY2UgdGhlIE1hZGRpc29uIFByb2plY3QgdXNlcyAyMDExIGRvbGxhcnMgYW5kIHRoZSBVTiB1c2VzIDIwMTUgZG9sbGFycywgYW5kIHRoZXJlJ3Mgbm90IGFuIGVhc3kgd2F5IHRvIHNoaWZ0IHRoZSBNYWRkaXNvbiBQcm9qZWN0J3MgdmFsdWVzIHVwIHRvIDIwMTUgKGkuZS4gdGhlcmUncyBubyBkZWZsYXRvcikuIEJ1dCBldmVuIGlmIHRoZXkgd2VyZSBpbiB0aGUgc2FtZSBkb2xsYXIteWVhcnMsIHRoZSB2YWx1ZXMgZnJvbSB0aGUgTWFkZGlzb24gUHJvamVjdCBzZWVtIHJlYWxseSByZWFsbHkgbG93IGNvbXBhcmVkIHRvIHdoYXQgd2UgbWFkZSB3aXRoIHRoZSBVTiBHRFAgZGF0YSwgc28gdGhleSBkb24ndCBzZWVtIHRvIGJlIGNvbXBhcmFibGUuCgotICoqQ3plY2hvc2xvdmFraWEgaXMgbWlzc2luZyBwZXJjZW50IG9mIEdEUCBmcm9tIHRyYWRlIGZyb20gMTk4MOKAkzE5ODkuKiogVGhpcyBpcyBiZWNhdXNlIGl0IGlzIG1pc3NpbmcgaW1wb3J0cyBkYXRhIGluIHRoZSBVTiBHRFAgZGF0YS4gSXQgaGFzIGV4cG9ydHMgZGF0YSBhbmQgb3ZlcmFsbCBHRFAgZGF0YSwgYnV0IGZvciB3aGF0ZXZlciByZWFzb24sIGltcG9ydHMgYXJlIG1pc3NpbmcuIEJvby4KCmBgYHtyIG1pc3Npbmctc292aWV0LXRoaW5nc30KY291bnRyeV9haWRfY29tcGxldGUgJT4lIAogIHNlbGVjdChnd2NvZGUsIGNvdW50cnksIHllYXIsIHVuX3RyYWRlX3BjdF9nZHAsIHVuX2dkcCwgZ2RwY2FwLCBnZHBjYXBfbG9nKSAlPiUgCiAgZmlsdGVyKGlzLm5hKHVuX3RyYWRlX3BjdF9nZHApKQpgYGAKClNpbmNlIHRob3NlIGlzc3VlcyBhcmUgYWxsIHByZS0xOTkwLCBvdXIgZGF0YSBpcyBwZXJmZWN0IHBvc3QtMTk5MCBpbiBjYXNlcyB3aXRoIFN1cGFybmEncyBsYXcgY292ZXJhZ2U6CgpgYGB7ciBmaW5hbC1kYXRhLW1pc3NpbmctY291bnRyaWVzLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD03fQpjb3VudHJ5X2FpZF9jb21wbGV0ZSAlPiUgCiAgZmlsdGVyKGxhd3MpICU+JSAKICBnZ19taXNzX3ZhciguLCBzaG93X3BjdCA9IFRSVUUpCmBgYAoKIyBGaW5hbCBkYXRhCgpOb3cgdGhhdCB3ZSBrbm93IGFsbCB0aGUgZGF0YSBpcyBjbGVhbiBhbmQgcHJldHR5IG11Y2ggbm90aGluZyBpcyBtaXNzaW5nLCB3ZSBjYW4gZG8gYSBmZXcgZmluYWwgd2luZG93ZWQgb3BlcmF0aW9ucyB0aGF0IHdpbGwgYWRkIG1pc3NpbmcgdmFsdWVzIChlLmcuIGxhZ2dpbmcpLiBXZSBhbHNvIGFkZCBhbiBpbmRpY2F0b3IgbWFya2luZyBpZiBhIGRpc2FzdGVyIGhhcHBlbmVkIGluIHRoZSBwYXN0IDUgeWVhcnMuCgpJbiBIfjN+IHdlIGh5cG90aGVzaXplIHRoYXQgbW9yZSBhaWQgd2lsbCBiZSBhbGxvY2F0ZWQgdG8gaW50ZXJuYXRpb25hbCBvciBVUy1iYXNlZCBOR09zIHRoYW4gZG9tZXN0aWMgTkdPcyBpbiByZXNwb25zZSB0byBoYXJzaGVyIGFudGktTkdPIHJlc3RyaWN0aW9ucy4gV2hpbGUgQWlkRGF0YSB1bmZvcnR1bmF0ZWx5IGRvZXMgbm90IGNhdGVnb3JpemUgYWlkIGJ5IGNoYW5uZWwgKGkuZS4gYWlkIGdpdmVuIHRvIGludGVybmF0aW9uYWwgdnMuIFVTIHZzLiBkb21lc3RpYyBOR09zKSwgVVNBSUQgZG9lcy4gRm9yIHRoaXMgaHlwb3RoZXNpcywgdGhlbiB3ZSBvbmx5IGxvb2sgYXQgYWlkIGdpdmVuIGJ5IFVTQUlELCBub3QgdGhlIHJlc3Qgb2YgdGhlIE9FQ0QuIEFzIHdpdGggdGhlIHByb3BvcnRpb24gb2YgY29udGVudGlvdXMgYWlkLCB3ZSBjcmVhdGUgc2ltaWxhciB2YXJpYWJsZXMgdG8gbWVhc3VyZSB0aGUgcHJvcG9ydGlvbiBvZiBhaWQgZ2l2ZW4gdG8gaW50ZXJuYXRpb25hbCBOR09zLCBVUy1iYXNlZCBOR09zLCBhbmQgYm90aCBpbnRlcm5hdGlvbmFsIGFuZCBVUy1iYXNlZCBOR09zLgoKYGBge3IgbWFrZS1maW5hbC1kYXRhfQojIERldGVybWluZSBpZiBhbnkgb2YgdGhlIHZhbHVlcyBpbiB0aGUgbGFzdCBrIHJvd3MgYXJlIFRSVUUKY2hlY2tfbGFzdF9rIDwtIGZ1bmN0aW9uKHgsIGspIHsKICAjIFRoaXMgY3JlYXRlcyBhIG1hdHJpeCB3aXRoIGEgY29sdW1uIGZvciBlYWNoIGxhZyB2YWx1ZSAoZS5nLiBjb2x1bW4gMSA9IGxhZwogICMgMCwgY29sdW1uIDIgPSBsYWcgMSwgZXRjLikKICBhbGxfbGFncyA8LSBzYXBwbHkoMDprLCBGVU4gPSBmdW5jdGlvbihrKSBsYWcoeCwgaykpCiAgCiAgIyBNYXJrIFRSVUUgaWYgYW55IG9mIHRoZSBjb2x1bW5zIGhhdmUgVFJVRSBpbiB0aGVtCiAgYW55X3RydWVfaW5fd2luZG93IDwtIGFwcGx5KGFsbF9sYWdzLCBNQVJHSU4gPSAxLCBGVU4gPSBhbnksIG5hLnJtID0gVFJVRSkKICByZXR1cm4oYW55X3RydWVfaW5fd2luZG93KQp9Cgpjb3VudHJ5X2FpZF9maW5hbCA8LSBjb3VudHJ5X2FpZF9jb21wbGV0ZSAlPiUgCiAgIyBQcm9wb3J0aW9uIG9mIGNvbnRlbnRpb3VzIGFpZAogIG11dGF0ZShwcm9wX2NvbnRlbnRpb3VzID0gb2RhX2NvbnRlbnRpb3VzX2hpZ2ggLyAKICAgICAgICAgICAob2RhX2NvbnRlbnRpb3VzX2xvdyArIG9kYV9jb250ZW50aW91c19oaWdoKSwKICAgICAgICAgcHJvcF9jb250ZW50aW91cyA9IAogICAgICAgICAgIGlmZWxzZShvZGFfY29udGVudGlvdXNfaGlnaCA9PSAwICYgb2RhX2NvbnRlbnRpb3VzX2xvdyA9PSAwLCAKICAgICAgICAgICAgICAgICAgMCwgcHJvcF9jb250ZW50aW91cykpICU+JSAKICBtdXRhdGUocHJvcF9jb250ZW50aW91c19sb2dpdCA9IGNhcjo6bG9naXQocHJvcF9jb250ZW50aW91cywgYWRqdXN0ID0gMC4wMDEpKSAlPiUgCiAgIyBQcm9wb3J0aW9uIG9mIGFpZCB0byBOR09zCiAgbXV0YXRlKHByb3BfbmdvX2ludCA9IG9kYV91c19uZ29faW50IC8gb2RhX3VzLAogICAgICAgICBwcm9wX25nb191cyA9IG9kYV91c19uZ29fdXMgLyBvZGFfdXMsCiAgICAgICAgIHByb3BfbmdvX2RvbSA9IG9kYV91c19uZ29fZG9tIC8gb2RhX3VzLAogICAgICAgICBwcm9wX25nb19mb3JlaWduID0gKG9kYV91c19uZ29faW50ICsgb2RhX3VzX25nb191cykgLyBvZGFfdXMpICU+JSAKICBtdXRhdGUoYWNyb3NzKHN0YXJ0c193aXRoKCJwcm9wX25nbyIpLCB+aWZlbHNlKGlzLm5hbiguKSwgMCwgLikpKSAlPiUgCiAgbXV0YXRlKGFjcm9zcyhzdGFydHNfd2l0aCgicHJvcF9uZ28iKSwgbGlzdChsb2dpdCA9IH5jYXI6OmxvZ2l0KC4sIGFkanVzdCA9IDAuMDAxKSkpKSAlPiUgCiAgbXV0YXRlKGFjcm9zcyhjKHRvdGFsX29kYSwgb2RhX2NvbnRlbnRpb3VzX2hpZ2gsIG9kYV9jb250ZW50aW91c19sb3csIG9kYV91cyksCiAgICAgICAgIGxpc3QobG9nID0gfmxvZzFwKC4pKSkpICU+JSAKICAjIExhZy9sZWFkL2RpZmYgdGhpbmdzIHdpdGhpbiBjb3VudHJpZXMKICBncm91cF9ieShnd2NvZGUpICU+JSAKICAjIERldGVybWluZSBpZiB0aGVyZSB3YXMgY29uZmxpY3QgaW4gdGhlIHBhc3QgNSB5ZWFycwogIG11dGF0ZShpbnRlcm5hbF9jb25mbGljdF9wYXN0XzUgPSBjaGVja19sYXN0X2soaW50ZXJuYWxfY29uZmxpY3QsIDUpLAogICAgICAgICBuYXR1cmFsX2Rpc19wYXN0XzUgPSBjaGVja19sYXN0X2sobmF0dXJhbF9kaXNfY291bnQgPj0gMSwgNSkpICU+JSAKICAjIEluZGljYXRlIGNoYW5nZXMgaW4gbGF3cwogIG11dGF0ZShhY3Jvc3MoYyhhZHZvY2FjeSwgZW50cnksIGZ1bmRpbmcsIGJhcnJpZXJzX3RvdGFsKSwKICAgICAgICAgICAgICAgIGxpc3QobmV3ID0gfi4gLSBsYWcoLiksCiAgICAgICAgICAgICAgICAgICAgIHdvcnNlID0gfiguIC0gbGFnKC4pKSA+IDAsCiAgICAgICAgICAgICAgICAgICAgIGNhdCA9IH5jdXQoLiAtIGxhZyguKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC1JbmYsIC0xLCAwLCBJbmYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk5ldyBiZXR0ZXIgbGF3IiwgIk5vIG5ldyBsYXdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZXcgd29yc2UgbGF3IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZF9yZXN1bHQgPSBUUlVFKSkpKSAlPiUKICAjIExhZyBhbmQgbGVhZCBzdHVmZgogIG11dGF0ZShhY3Jvc3MoYyhiYXJyaWVyc190b3RhbCwgYWR2b2NhY3ksIGVudHJ5LCBmdW5kaW5nLCB2Mnhjc19jY3NpLAogICAgICAgICAgICAgICAgICB0b3RhbF9vZGEsIHRvdGFsX29kYV9sb2csIHByb3BfY29udGVudGlvdXMsCiAgICAgICAgICAgICAgICAgIHByb3BfbmdvX2RvbSwgcHJvcF9uZ29fZm9yZWlnbiksCiAgICAgICAgICAgICAgICBsaXN0KGxhZzEgPSB+bGFnKC4sIG4gPSAxKSkpKSAlPiUgCiAgbXV0YXRlKGFjcm9zcyhjKHRvdGFsX29kYSwgdG90YWxfb2RhX2xvZywgcHJvcF9jb250ZW50aW91cywKICAgICAgICAgICAgICAgICAgcHJvcF9uZ29fZG9tLCBwcm9wX25nb19mb3JlaWduKSwKICAgICAgICAgICAgICAgIGxpc3QobGVhZDEgPSB+bGVhZCguLCBuID0gMSkpKSkgJT4lIAogIHVuZ3JvdXAoKQpgYGAKCgojIFNhdmUgZGF0YQoKUGhldy4gRXZlcnl0aGluZyBjaGVja3Mgb3V0LiBTYXZlIHRoaXMgc3R1ZmYgZm9yIHVzZSBpbiBhY3R1YWwgYW5hbHlzZXMgaW4gYC9kYXRhL2Rlcml2ZWRfZGF0YS9gCgpgYGB7ciBzYXZlLWZpbmFsLWRhdGF9CnNhdmVSRFMoY291bnRyeV9haWRfZmluYWwsIGhlcmUoImRhdGEiLCAiZGVyaXZlZF9kYXRhIiwgImRmX2NvdW50cnlfYWlkLnJkcyIpKQpzYXZlUkRTKGRvbm9yX2xldmVsX2RhdGEsIGhlcmUoImRhdGEiLCAiZGVyaXZlZF9kYXRhIiwgImRmX2Rvbm9yLnJkcyIpKQpzYXZlUkRTKGRvbm9yX2xldmVsX2RhdGFfdXNhaWQsIGhlcmUoImRhdGEiLCAiZGVyaXZlZF9kYXRhIiwgImRmX2Rvbm9yX3VzYWlkLnJkcyIpKQpzYXZlUkRTKGF1dG9jcmFjaWVzX2ZpbmFsLCBoZXJlKCJkYXRhIiwgImRlcml2ZWRfZGF0YSIsICJkZl9hdXRvY3JhY2llcy5yZHMiKSkKYGBgCg==