Exploratory Analyses

Similar to Fig 1 & 6 - Land Area

This figure matches with the values presented in original Figures 1 and 2.

Breaking pasture area down by region, it’s apparent that the decline in global pasture is driven by a turn-around in pasture area in Asia, as well as a continued decline in area in Oceania, with the more recent declines in pasture area perhaps being an artefact of reporting methods in Africa or Oceania.

The decreases in Asia and later step drop in Africa warrant further investigation.

You can see that the big drop-off from 2008-2009 in Africa is largely driven by a drop in Sudan (former). This could be an actual drop in pastureland due to warfare, or a decline in reporting standards. Sudan (former) reported its own pasture values until 2009, when FAO had to manually estimate it, likely based on the values that Sudan (former) reported later after the independence of South Sudan. Note, the pasture values for Sudan and South Sudan add up to a similar value (~74,000) as the last reported value for former Sudan (80,000).

Overall there was a drop in pasture in Sudan (former) of 34950 between 2008 and 2009. This accounts for ~75% of the global drop in pasture of 45725 between 2008 and 2009.

Most countries in Southern and Easter Asia are estimated to have had a steady decline in pasture area.

The sharp decline in 2002 in Eastern Asia is in Mongolia. The decline in 2004 in Southern Asia is in Iran. For both MOngolia and Iran, there is no clear indication why the values jumped. These data were reported by the countries to FAO and there was no concurrent decline in cropland. THis suggests it could be an issue of how they classify pasture. FAO doesnt indicate there was a concurrent rise in pasture elsewhere - they just say that the area under “Other Land Uses” increased when pasture declined.

However, focusing on East Asia raises a red flag: China. Enjoy the pun, because this raises a major data issue. The 1.5483310^{5} thousand hectare rise in pasture area in China from 1961 to 1994, when China’s pasture area suddenly stops being updated in FAO accounts for 58.3110351 of the 2.65529510^{5} thousand hectare global change in pasture in this time period. The worry is that if their pasture area has indeed kept increasing at the same pace as it was earlier, it would likely reverse the decline in global pasture area we seem to see.

Also, China didn’t update FAO with their pasture data between 1978 and 2010. I believe FAO had to impute the values, but would need to verify this.

Estimates of grassland area in Chian based on remote-sensed data indicate taht grassland area hasn’t changed since reporting of this dataset began in 1992. This provides some evidence that the FAO data may be reasonable since grassland land cover estimates and pasture land use estimates should overlap and somewhat mirror each other. Nevertheless, we ought to ask others about the China data if we want to be really sure about the global trend (which I actually think doesnt matter much).

Australia also distorts the trend in pasture area. The 39,505 drop for 2014-15 pasture in Australia accounted for over 100% of the 39454 drop in global pasture area in this time period. This is worrying because of what we’ve been told about the Australia data - that it may just represent a reclassification of the land even though the land use has remained in pasture. FAO calculated these pasture values, but based off of values Australia reported on “Agricultural Land” area, which saw the same decline.

Holding all else constant, if 2015 Australia pasture area was the same as 2014 area, global pasture would have negligibly increased that year.

When omitting all Sudan data, and using the same Australia pasture value as for 2013 for 2015 and 2016, global pasture area sill peaked in 2000 and declined afterward, but less quickly. I use 2013 instead of 2014 because it seems more representative of recent trends than 2014, when pasture area temporarily spiked upward.

197 codes from your data successfully matched countries in the map
11 codes from your data failed to match with a country code in the map
46 codes from the map weren't represented in your data
3 colours specified and 6 required, using interpolation to calculate colours

Recently, for instance, from 2010 to 2016, pasture has grown in some countries, while shrinking in others. Pasture has notably shrunk from earlier high levels almost across the world, including in Brazil and dramatically in Australia. However, it has expanded in the U.S., and Peru, Columbia, and China, as well as parts of Western and Northern Europe.

Similar to Fig. 2 - Global Ruminant Meat and Milk Production

Global meat production has generally risen for all grazing animals, but dramatically more so for cattle than other animals. This supports the idea that cattle production is the main global driver of pasture expansion.

The same is true for milk - production from cattle rose most dramatically. Buffalo produce the second most milk compared to cattle. Nevertheless, they too produce a fraction of what cattle do, ~1/7 in 2016.

There has been a slight leveling off in combined meat production from all animals, similar to previous trends in meat production, and forecasts, there is little reason to think this levelling off will persist.

Combined global milk production form all animals has seen a similar, but slightly more dramatic leveling off.

Similar to Fig 3 - Consumption

Total consumption of ruminant meat and milk has increased by 128 and 174, respectively, since 1961.

Consumption per capita is greatest for milk whether measured in calories, grams protein, or weight. Milk consumption per capita has increased more than that for any ruminant meats. However, as James’ graphs showed, pork and poultry consumption has dramatically increased over time.

The relatively flat trend in bovine meat consumption indicates that growth in cattle production has been driven by a combinatio of increasing dairy demand s well as increased global population, moreso than any change in beef demand.

Note: There are only total consumption values in tonnes for cheese since the calorie, protein and fat content varies so widely and apparently FAO does not calculate this. The cream values are also negligible. I have omitted these from the graphs.

The steep rise in poultry and pork is more apparent when you look at change in consumption (in kcal/capita) relative to the first year in the data.

Similar to Fig. 7 - Cattle Meat and Milk Consumption by Region

167 codes from your data successfully matched countries in the map
13 codes from your data failed to match with a country code in the map
76 codes from the map weren't represented in your data
3 colours specified and 8 required, using interpolation to calculate colours

The global trend in beef meat consumption appears to mostly be driven by the rapid rise in Eastern Asia (China), as well as the steady increase in South America (Especially Brazil)

Similar to Figure 4 & 8 - Change in Yields

Cattle yields have increased the most compared to other top grazing animals, with yields nearly 34% higher in 2013 than in 1961. As the report describes, this improvement is emblematic of the “livestock revolution” that has improved land productivity of animal production and reduced pasture expansion pressure.

THis is apparent when looking at cattle and buffalo as well. Cattle milk yields in 2016 were 36% higher than in 1961. Although goat and sheep yields have decreased over time, this has put little additional pressure on pasture expansion since these animals comprise a fraction of overall milk and meat production.

However, the global trends mask regional differences in yields and changes in yields.

Regional Meat Yields

Although meat yields have grown globally, they have grown much less in Africa than elsewhere. Despite growing in Asia over 50%, they are still substantially below yield levels in Europe, the Americas and Oceania.

Ignoring 1 observationsIgnoring 1 observations

Digging deeper, it becomes apparent that yields in Africa have grown mostly in Northern and Southern Africa, while they have stagnated in Middle, Eastern and Western Africa. In Asia, a lot of the growth in yields was in Western Asia, while yields in East Asia, where a lot of the growth in demand is, have not grown much.

Regional Milk Yields

Similar trends are visible for cattle milk yields, although the differences between Oceania, Europe, and the Americas vs. Asia and Africa are starker.

Ignoring 1 observationsIgnoring 1 observations

Milk yields have stalled in many of the same places as meat yields, though Southern and Northern Afrca didn’t see the same gains in milk yields as they saw in meat yields.

Similar to Figure 5 - Pasture per production/ Decoupling

Joining, by = c("country", "year", "minor_group", "major_group")
Joining, by = c("country", "year", "minor_group", "major_group")

The top left shows dairy + meat production from ruminants divided by total pasture area, the top right shows just dairy production from ruminants divided by total pasture area, and the bottom left shows just meat production from ruminants divided by total pasture area.

I think that showing the top right graph in the report, but omitting the FOrmer Soviet Union, would be useful. This demonstrates that the rat of improvement in meat and dairy production/unit pasture has been steadily improving, particularly in the areas where consumption is growing most - Asia and Africa, though less so in the Americas where pasture expansion is a problem.

LS0tCnRpdGxlOiAiRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyBmb3IgUGFzdHVyZSIKb3V0cHV0OiBodG1sX25vdGVib29rCmRhdGU6ICJOb3YuIDEzIgotLS0KCmBgYHtyIGdsb2JhbF9vcHRpb25zLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojc2V0IGtuaXRyIGRpc3BsYXkgb3B0aW9ucwprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEwLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSkKYGBgCgpgYGB7ciBTZXR1cH0KI0NPTU1FTlQgQkFDSyBJTiBBUyBORUVERUQgVE8gbmF2aWdhdGUgdG8gUGVhayBQYXN0dXJlIEZvbGRlciBiZWZvcmUgc3RhcnRpbmcKI3NldHdkKCJ+L0dvb2dsZSBEcml2ZSBGaWxlIFN0cmVhbS9NeSBEcml2ZS9CVEkgUmVzZWFyY2gvRm9vZCAmIEZhcm1pbmcvUGVhayBQYXN0dXJlIikKCiNsb2FkIHBhY2thZ2VzIApsaWJyYXJ5KCd0aWR5dmVyc2UnKQpsaWJyYXJ5KCdzY2FsZXMnKQpsaWJyYXJ5KCdwbG90bHknKQpsaWJyYXJ5KCdyd29ybGRtYXAnKQoKI3NldCBydWxlcyBmb3IgZm9ybWF0dGluZyBncmFwaHMKcG9pbnQgPC0gZm9ybWF0X2Zvcm1hdChiaWcubWFyayA9ICIsIiwgZGVjaW1hbC5tYXJrID0gIi4iLCBzY2llbnRpZmljID0gRkFMU0UpCmBgYAoKIyBFeHBsb3JhdG9yeSBBbmFseXNlcwojIyBTaW1pbGFyIHRvIEZpZyAxICYgNiAtICBMYW5kIEFyZWEKYGBge3IgR2xvYmFsIExhbmQgVW5kZXIgUGVybSBQYXN0dXJlIGFuZCBPdGhlciBQYXN0dXJlfQp2aXogPC0gbGFuZF9hcmVhICU+JQogIGZpbHRlcihpdGVtID09ICJwYXN0dXJlIikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KGl0ZW0sIHllYXIpICU+JQogIGRwbHlyOjpzdW1tYXJpemUoYXJlYT1zdW0oYXJlYSkpICU+JQogIGdncGxvdCgpICsKICAgIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSBhcmVhKSkgKyAKICBsYWJzKHRpdGxlID0gIkdsb2JhbCBQYXN0dXJlIEFyZWEgU3RlZXBseSBEZWNsaW5lZCBzaW5jZSAyMDAwIiwgIAogICAgICAgeSA9ICJHbG9iYWwgUGFzdHVyZSBBcmVhICh0aG91c2FuZCBoYSkiKSAKCmdncGxvdGx5KHZpeikKYGBgClRoaXMgZmlndXJlIG1hdGNoZXMgd2l0aCB0aGUgdmFsdWVzIHByZXNlbnRlZCBpbiBvcmlnaW5hbCBGaWd1cmVzIDEgYW5kIDIuCgpgYGB7ciBGaWd1cmUgMSAtIFBlcm1hbmVudCBQYXN0dXJlIGJ5IFJlZ2lvbn0Kdml6IDwtICBsYW5kX2FyZWEgJT4lCiAgZHBseXI6OiBmaWx0ZXIoaXRlbSA9PSAicGFzdHVyZSIpICU+JQogIGdyb3VwX2J5KHllYXIsIG1ham9yX2dyb3VwKSAlPiUKICBkcGx5cjo6c3VtbWFyaXplKGFyZWE9c3VtKGFyZWEsIG5hLnJtPVQpKSAlPiUKICBnZ3Bsb3QoKSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gYXJlYSwgY29sb3IgPSBtYWpvcl9ncm91cCkpICsKICBsYWJzKHRpdGxlID0gIlBhc3R1cmUgQXJlYSB0cmVuZHMgRGlmZmVyIGJ5IFJlZ2lvbiIsIHkgPSAiQXJlYSAodGhvdXNhbmQgaGEpIikKCmdncGxvdGx5KHZpeikKYGBgCkJyZWFraW5nIHBhc3R1cmUgYXJlYSBkb3duIGJ5IHJlZ2lvbiwgaXQncyBhcHBhcmVudCB0aGF0IHRoZSBkZWNsaW5lIGluIGdsb2JhbCBwYXN0dXJlIGlzIGRyaXZlbiBieSBhIHR1cm4tYXJvdW5kIGluIHBhc3R1cmUgYXJlYSBpbiBBc2lhLCBhcyB3ZWxsIGFzIGEgY29udGludWVkIGRlY2xpbmUgaW4gYXJlYSBpbiBPY2VhbmlhLCB3aXRoIHRoZSBtb3JlIHJlY2VudCBkZWNsaW5lcyBpbiBwYXN0dXJlIGFyZWEgcGVyaGFwcyBiZWluZyBhbiBhcnRlZmFjdCBvZiByZXBvcnRpbmcgbWV0aG9kcyBpbiBBZnJpY2Egb3IgIE9jZWFuaWEuCgpUaGUgZGVjcmVhc2VzIGluIEFzaWEgYW5kIGxhdGVyIHN0ZXAgZHJvcCBpbiBBZnJpY2Egd2FycmFudCBmdXJ0aGVyIGludmVzdGlnYXRpb24uIAoKYGBge3IgUGFzdHVyZSBBcmVhIHRyZW5kcyBpbiBBc2lhIGFuZCBBZnJpY2F9CnZpeiA8LSAgbGFuZF9hcmVhICU+JQogIGZpbHRlcihpdGVtID09ICJwYXN0dXJlIiwgbWFqb3JfZ3JvdXAgJWluJSBjKCJBc2lhIiwgIkFmcmljYSIpKSAlPiUKICBncm91cF9ieSh5ZWFyLCBtaW5vcl9ncm91cCkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhcmVhPXN1bShhcmVhLCBuYS5ybT1UKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IGFyZWEsIGNvbG9yID0gbWlub3JfZ3JvdXApKSArCiAgbGFicyh0aXRsZSA9ICJQYXN0dXJlIFRyZW5kcyBpbiBBZnJpY2EgYW5kIEFzaWEiLCB5ID0gIkFyZWEgKHRob3VzYW5kIGhhKSIpCgpnZ3Bsb3RseSh2aXopCmBgYAoKYGBge3IgUGFzdHVyZSBpbiBOb3J0aGVybiBBZnJpY2F9CnZpeiA8LSAgbGFuZF9hcmVhICU+JQogIGZpbHRlcihpdGVtID09ICJwYXN0dXJlIiwgbWlub3JfZ3JvdXAgJWluJSBjKCJOb3J0aGVybiBBZnJpY2EiKSkgJT4lCiAgZ3JvdXBfYnkoeWVhciwgY291bnRyeSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhcmVhPXN1bShhcmVhLCBuYS5ybT1UKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IGFyZWEsIGNvbG9yID0gY291bnRyeSkpICsKICBsYWJzKHRpdGxlID0gIlBhc3R1cmUgVHJlbmRzIGluIE5vcnRoZXJuIEFmcmljYSIsIHkgPSAiQXJlYSAodGhvdXNhbmQgaGEpIikKCmdncGxvdGx5KHZpeikKYGBgCllvdSBjYW4gc2VlIHRoYXQgdGhlIGJpZyBkcm9wLW9mZiBmcm9tIDIwMDgtMjAwOSBpbiBBZnJpY2EgaXMgbGFyZ2VseSBkcml2ZW4gYnkgYSBkcm9wIGluIFN1ZGFuIChmb3JtZXIpLiBUaGlzIGNvdWxkIGJlIGFuIGFjdHVhbCBkcm9wIGluIHBhc3R1cmVsYW5kIGR1ZSB0byB3YXJmYXJlLCBvciBhIGRlY2xpbmUgaW4gcmVwb3J0aW5nIHN0YW5kYXJkcy4gU3VkYW4gKGZvcm1lcikgcmVwb3J0ZWQgaXRzIG93biBwYXN0dXJlIHZhbHVlcyB1bnRpbCAyMDA5LCB3aGVuIEZBTyBoYWQgdG8gbWFudWFsbHkgZXN0aW1hdGUgaXQsIGxpa2VseSBiYXNlZCBvbiB0aGUgdmFsdWVzIHRoYXQgU3VkYW4gKGZvcm1lcikgcmVwb3J0ZWQgbGF0ZXIgYWZ0ZXIgdGhlIGluZGVwZW5kZW5jZSBvZiBTb3V0aCBTdWRhbi4gTm90ZSwgdGhlIHBhc3R1cmUgdmFsdWVzIGZvciBTdWRhbiBhbmQgU291dGggU3VkYW4gYWRkIHVwIHRvIGEgc2ltaWxhciB2YWx1ZSAofjc0LDAwMCkgYXMgdGhlIGxhc3QgcmVwb3J0ZWQgdmFsdWUgZm9yIGZvcm1lciBTdWRhbiAoODAsMDAwKS4gCgpPdmVyYWxsIHRoZXJlIHdhcyBhIGRyb3AgaW4gcGFzdHVyZSBpbiBTdWRhbiAoZm9ybWVyKSBvZiAzNDk1MCBiZXR3ZWVuIDIwMDggYW5kIDIwMDkuIFRoaXMgYWNjb3VudHMgZm9yIH43NSUgb2YgdGhlIGdsb2JhbCBkcm9wIGluIHBhc3R1cmUgb2YgNDU3MjUgYmV0d2VlbiAyMDA4IGFuZCAyMDA5LgoKYGBge3IgUGFzdHVyZSBpbiBTb3V0aGVybiBhbmQgRWFzdGVybiBBc2lhfQp2aXogPC0gIGxhbmRfYXJlYSAlPiUKICBmaWx0ZXIoaXRlbSA9PSAicGFzdHVyZSIsIG1pbm9yX2dyb3VwICVpbiUgYygiRWFzdGVybiBBc2lhIiwgIlNvdXRoZXJuIEFzaWEiKSkgJT4lCiAgZ3JvdXBfYnkoeWVhciwgY291bnRyeSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhcmVhPXN1bShhcmVhLCBuYS5ybT1UKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IGFyZWEsIGNvbG9yID0gY291bnRyeSkpICsKICBsYWJzKHRpdGxlID0gIlBhc3R1cmUgVHJlbmRzIGluIFNvdXRoZXJuIGFuZCBFYXN0ZXJuIiwgeSA9ICJBcmVhICh0aG91c2FuZCBoYSkiKQoKZ2dwbG90bHkodml6KQoKI2NhbGN1bGF0ZSBwZXJjZW50IG9mIGdsb2JhbCBjaGFuZ2UgaW4gcGFzdHVyZSBhcmVhIHRoYXQgY2hpbmVzZSBjaGFuZ2UgaW4gcGFzdHVyZSBhY2NvdW50ZWQgZm9yCmNoaW5hXzE5NjEgPC0gbGFuZF9hcmVhICU+JSBmaWx0ZXIoeWVhcj09MTk2MSwgY291bnRyeT09IkNoaW5hIiwgaXRlbT09InBhc3R1cmUiKSAlPiUgc2VsZWN0KGFyZWEpCmNoaW5hXzE5OTQgPC0gbGFuZF9hcmVhICU+JSBmaWx0ZXIoeWVhcj09MTk5NCwgY291bnRyeT09IkNoaW5hIiwgaXRlbT09InBhc3R1cmUiKSAlPiUgc2VsZWN0KGFyZWEpCmNoaW5hXzE5NjFfMTk5NF9kaWZmIDwtIGNoaW5hXzE5OTQtY2hpbmFfMTk2MQoKZ2xvYmFsXzE5NjEgPC0gZ2xvYmFsX2FyZWEgJT4lIHVuZ3JvdXAoKSAlPiUgZmlsdGVyKHllYXI9PTE5NjEpICU+JSBzZWxlY3QoYXJlYSkKZ2xvYmFsXzE5OTQgPC0gZ2xvYmFsX2FyZWEgJT4lIHVuZ3JvdXAoKSAlPiUgZmlsdGVyKHllYXI9PTE5OTQpICU+JSBzZWxlY3QoYXJlYSkKCmdsb2JhbF8xOTYxXzE5OTRfZGlmZiA8LSBnbG9iYWxfMTk5NCAtIGdsb2JhbF8xOTYxCgpjaGluYV9wY3RfMTk2MV8xOTk0X3dvcmxkIDwtIGNoaW5hXzE5NjFfMTk5NF9kaWZmL2dsb2JhbF8xOTYxXzE5OTRfZGlmZiAqMTAwCmBgYApNb3N0IGNvdW50cmllcyBpbiBTb3V0aGVybiBhbmQgRWFzdGVyIEFzaWEgYXJlIGVzdGltYXRlZCB0byBoYXZlIGhhZCBhIHN0ZWFkeSBkZWNsaW5lIGluIHBhc3R1cmUgYXJlYS4KClRoZSBzaGFycCBkZWNsaW5lIGluIDIwMDIgaW4gRWFzdGVybiBBc2lhIGlzIGluIE1vbmdvbGlhLiBUaGUgZGVjbGluZSBpbiAyMDA0IGluIFNvdXRoZXJuIEFzaWEgaXMgaW4gSXJhbi4gRm9yIGJvdGggTU9uZ29saWEgYW5kIElyYW4sIHRoZXJlIGlzIG5vIGNsZWFyIGluZGljYXRpb24gd2h5IHRoZSB2YWx1ZXMganVtcGVkLiBUaGVzZSBkYXRhIHdlcmUgcmVwb3J0ZWQgYnkgdGhlIGNvdW50cmllcyB0byBGQU8gYW5kIHRoZXJlIHdhcyBubyBjb25jdXJyZW50IGRlY2xpbmUgaW4gY3JvcGxhbmQuIFRIaXMgc3VnZ2VzdHMgaXQgY291bGQgYmUgYW4gaXNzdWUgb2YgaG93IHRoZXkgY2xhc3NpZnkgcGFzdHVyZS4gRkFPIGRvZXNudCBpbmRpY2F0ZSB0aGVyZSB3YXMgYSBjb25jdXJyZW50IHJpc2UgaW4gcGFzdHVyZSBlbHNld2hlcmUgLSB0aGV5IGp1c3Qgc2F5IHRoYXQgdGhlIGFyZWEgdW5kZXIgIk90aGVyIExhbmQgVXNlcyIgaW5jcmVhc2VkIHdoZW4gcGFzdHVyZSBkZWNsaW5lZC4KCkhvd2V2ZXIsIGZvY3VzaW5nIG9uIEVhc3QgQXNpYSByYWlzZXMgYSByZWQgZmxhZzogQ2hpbmEuIEVuam95IHRoZSBwdW4sIGJlY2F1c2UgdGhpcyByYWlzZXMgYSBtYWpvciBkYXRhIGlzc3VlLiBUaGUgYHIgYXMubnVtZXJpYyhjaGluYV8xOTYxXzE5OTRfZGlmZilgIHRob3VzYW5kIGhlY3RhcmUgcmlzZSBpbiBwYXN0dXJlIGFyZWEgaW4gQ2hpbmEgZnJvbSAxOTYxIHRvIDE5OTQsIHdoZW4gQ2hpbmEncyBwYXN0dXJlIGFyZWEgc3VkZGVubHkgc3RvcHMgYmVpbmcgdXBkYXRlZCBpbiBGQU8gYWNjb3VudHMgZm9yIGByIGFzLm51bWVyaWMoY2hpbmFfcGN0XzE5NjFfMTk5NF93b3JsZClgIG9mIHRoZSBgciBhcy5udW1lcmljKGdsb2JhbF8xOTYxXzE5OTRfZGlmZilgIHRob3VzYW5kIGhlY3RhcmUgZ2xvYmFsIGNoYW5nZSBpbiBwYXN0dXJlIGluIHRoaXMgdGltZSBwZXJpb2QuIFRoZSB3b3JyeSBpcyB0aGF0IGlmIHRoZWlyIHBhc3R1cmUgYXJlYSBoYXMgaW5kZWVkIGtlcHQgaW5jcmVhc2luZyBhdCB0aGUgc2FtZSBwYWNlIGFzIGl0IHdhcyBlYXJsaWVyLCBpdCB3b3VsZCBsaWtlbHkgcmV2ZXJzZSB0aGUgZGVjbGluZSBpbiBnbG9iYWwgcGFzdHVyZSBhcmVhIHdlIHNlZW0gdG8gc2VlLgoKQWxzbywgQ2hpbmEgZGlkbid0IHVwZGF0ZSBGQU8gd2l0aCB0aGVpciBwYXN0dXJlIGRhdGEgYmV0d2VlbiAxOTc4IGFuZCAyMDEwLiBJIGJlbGlldmUgRkFPIGhhZCB0byBpbXB1dGUgdGhlIHZhbHVlcywgYnV0IHdvdWxkIG5lZWQgdG8gdmVyaWZ5IHRoaXMuCgpgYGB7ciBDaGluYSBsYW5kIGNvdmVyfQpsYW5kX2NvdmVyICU+JSBmaWx0ZXIoaXRlbT09IkdyYXNzbGFuZCIsIGNvdW50cnk9PSJDaGluYSwgbWFpbmxhbmQiKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4PXllYXIsIHk9Y2NpKSkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBvaW50LCBsaW1pdHMgPSBjKDAsIDI5ODAwMCkpICsKICBsYWJzKHRpdGxlID0gIkNoaW5hIEdyYXNzbGFuZCBUcmVuZCAoUmVtb3RlIFNlbnNlZCkiLCB5ID0gIkFyZWEgKHRob3VzYW5kIGhhKSIpCmBgYApFc3RpbWF0ZXMgb2YgZ3Jhc3NsYW5kIGFyZWEgaW4gQ2hpYW4gYmFzZWQgb24gcmVtb3RlLXNlbnNlZCBkYXRhIGluZGljYXRlIHRhaHQgZ3Jhc3NsYW5kIGFyZWEgaGFzbid0IGNoYW5nZWQgc2luY2UgcmVwb3J0aW5nIG9mIHRoaXMgZGF0YXNldCBiZWdhbiBpbiAxOTkyLiBUaGlzIHByb3ZpZGVzIHNvbWUgZXZpZGVuY2UgdGhhdCB0aGUgRkFPIGRhdGEgbWF5IGJlIHJlYXNvbmFibGUgc2luY2UgZ3Jhc3NsYW5kIGxhbmQgY292ZXIgZXN0aW1hdGVzIGFuZCBwYXN0dXJlIGxhbmQgdXNlIGVzdGltYXRlcyBzaG91bGQgb3ZlcmxhcCBhbmQgc29tZXdoYXQgbWlycm9yIGVhY2ggb3RoZXIuIE5ldmVydGhlbGVzcywgd2Ugb3VnaHQgdG8gYXNrIG90aGVycyBhYm91dCB0aGUgQ2hpbmEgZGF0YSBpZiB3ZSB3YW50IHRvIGJlIHJlYWxseSBzdXJlIGFib3V0IHRoZSBnbG9iYWwgdHJlbmQgKHdoaWNoIEkgYWN0dWFsbHkgdGhpbmsgZG9lc250IG1hdHRlciBtdWNoKS4KCgpgYGB7ciBBdXN0cmFsaWEgUGFzdHVyZSBBcmVhfQp2aXogPC0gIGxhbmRfYXJlYSAlPiUKICBmaWx0ZXIoaXRlbSA9PSAicGFzdHVyZSIsIGNvdW50cnkgPT0gIkF1c3RyYWxpYSIpICU+JQogIGdyb3VwX2J5KHllYXIsIGNvdW50cnkpICU+JQogIGRwbHlyOjpzdW1tYXJpemUoYXJlYT1zdW0oYXJlYSwgbmEucm09VCkpICU+JQogIGdncGxvdCgpICsKICAgIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSBhcmVhKSkgKwogIGxhYnModGl0bGUgPSAiUGFzdHVyZSBUcmVuZHMgaW4gQXVzdHJhbGlhIiwgeSA9ICJBcmVhICh0aG91c2FuZCBoYSkiKQoKZ2dwbG90bHkodml6KQpgYGAKQXVzdHJhbGlhIGFsc28gZGlzdG9ydHMgdGhlIHRyZW5kIGluIHBhc3R1cmUgYXJlYS4gVGhlIDM5LDUwNSBkcm9wIGZvciAyMDE0LTE1IHBhc3R1cmUgaW4gQXVzdHJhbGlhIGFjY291bnRlZCBmb3Igb3ZlciAxMDAlIG9mIHRoZSAzOTQ1NCBkcm9wIGluIGdsb2JhbCBwYXN0dXJlIGFyZWEgaW4gdGhpcyB0aW1lIHBlcmlvZC4gVGhpcyBpcyB3b3JyeWluZyBiZWNhdXNlIG9mIHdoYXQgd2UndmUgYmVlbiB0b2xkIGFib3V0IHRoZSBBdXN0cmFsaWEgZGF0YSAtIHRoYXQgaXQgbWF5IGp1c3QgcmVwcmVzZW50IGEgcmVjbGFzc2lmaWNhdGlvbiBvZiB0aGUgbGFuZCBldmVuIHRob3VnaCB0aGUgbGFuZCB1c2UgaGFzIHJlbWFpbmVkIGluIHBhc3R1cmUuIEZBTyBjYWxjdWxhdGVkIHRoZXNlIHBhc3R1cmUgdmFsdWVzLCBidXQgYmFzZWQgb2ZmIG9mIHZhbHVlcyBBdXN0cmFsaWEgcmVwb3J0ZWQgb24gIkFncmljdWx0dXJhbCBMYW5kIiBhcmVhLCB3aGljaCBzYXcgdGhlIHNhbWUgZGVjbGluZS4gCgpIb2xkaW5nIGFsbCBlbHNlIGNvbnN0YW50LCBpZiAyMDE1IEF1c3RyYWxpYSBwYXN0dXJlIGFyZWEgd2FzIHRoZSBzYW1lIGFzIDIwMTQgYXJlYSwgZ2xvYmFsIHBhc3R1cmUgd291bGQgaGF2ZSBuZWdsaWdpYmx5IGluY3JlYXNlZCB0aGF0IHllYXIuIAoKCmBgYHtyIEdsb2JhbCBQYXN0dXJlIHdpdGhvdXQgU3VkYW4gYW5kIEF1c3RyYWxpYSBuZXcgdmFsdWVzfQoKI2NyZWF0ZSB0ZW1wb3JhcnkgZGF0YS5mcmFtZSB3aXRoIEF1c3RyYWxpYSdzIDIwMTUgYW5kIDIwMTYgcGFzdHVyZSB2YWx1ZXMgZXF1YWwgdG8gMjAxMyB2YWx1ZQp0ZW1wIDwtIGZpbHRlcihsYW5kX2FyZWEsIGl0ZW0gPT0icGFzdHVyZSIpCnRlbXAkYXJlYVt0ZW1wJGNvdW50cnk9PSJBdXN0cmFsaWEiICYgdGVtcCR5ZWFyICVpbiUgYygyMDE1LDIwMTYpXSA8LSAgZmlsdGVyKGxhbmRfYXJlYSwgY291bnRyeT09IkF1c3RyYWxpYSIsIHllYXI9PTIwMTMsIGl0ZW09PSJwYXN0dXJlIikkYXJlYQoKdGVtcCAlPiUKICBmaWx0ZXIoaXRlbSA9PSAicGFzdHVyZSIsICFzdHJfZGV0ZWN0KGNvdW50cnksICJTdWRhbiIpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoaXRlbSwgeWVhcikgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhcmVhPXN1bShhcmVhKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IGFyZWEpKSArCiAgbGFicyh0aXRsZSA9ICJHbG9iYWwgUGFzdHVyZSBBcmVhIFN0aWxsIFN0ZWVwbHkgRGVjbGluZWQgc2luY2UgMjAwMCIsIHN1YnRpdGxlPSJPbWl0dGluZyBTdWRhbiBhbmQgSG9sZGluZyBBdXN0cmFsaWEncyBSZWNlbnQgUGFzdHVyZSBWYWx1ZXMgQ29uc3RhbnQiLCAKICAgICAgIHkgPSAiR2xvYmFsIFBhc3R1cmUgQXJlYSAodGhvdXNhbmQgaGEpIikKYGBgCldoZW4gb21pdHRpbmcgYWxsIFN1ZGFuIGRhdGEsIGFuZCB1c2luZyB0aGUgc2FtZSBBdXN0cmFsaWEgcGFzdHVyZSB2YWx1ZSBhcyBmb3IgMjAxMyBmb3IgMjAxNSBhbmQgMjAxNiwgZ2xvYmFsIHBhc3R1cmUgYXJlYSBzaWxsIHBlYWtlZCBpbiAyMDAwIGFuZCBkZWNsaW5lZCBhZnRlcndhcmQsIGJ1dCBsZXNzIHF1aWNrbHkuIEkgdXNlIDIwMTMgaW5zdGVhZCBvZiAyMDE0IGJlY2F1c2UgaXQgc2VlbXMgbW9yZSByZXByZXNlbnRhdGl2ZSBvZiByZWNlbnQgdHJlbmRzIHRoYW4gMjAxNCwgd2hlbiBwYXN0dXJlIGFyZWEgdGVtcG9yYXJpbHkgc3Bpa2VkIHVwd2FyZC4KCmBgYHtyIFJlY2VudCBQYXN0dXJlIENoYW5nZSBIb3RzcG90c30KI21hcCBjaGFuZ2UgaW4gcGFzdHVyZSBhcmVhIGJldHdlZW4gdHdvIHllYXJzIGJ5IGNvdW50cnkgdG8gaWRlbnRpZnkgaG90c3BvdHMgb2YgZXhwYW5zaW9uCiNSRVRVUk4gICNtb3ZlIHRvIGNsZWFuaW5nIGZpbGUKbGFuZF9hcmVhJGNvdW50cnkgPC0gcmVjb2RlKGxhbmRfYXJlYSRjb3VudHJ5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJ1c3NpYW4gRmVkZXJhdGlvbiI9IlJ1c3NpYSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoaW5hLCBtYWlubGFuZCIgPSAiQ2hpbmEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVU1NSIj0iUnVzc2lhIikKI0VORAoKdml6IDwtIGxhbmRfYXJlYSAlPiUKICBmaWx0ZXIoaXRlbT09InBhc3R1cmUiLCB5ZWFyICVpbiUgYygyMDEwLCAyMDE2KSkgJT4lCiAgc2VsZWN0KGNvdW50cnksIHllYXIsIGFyZWEpICU+JQogIHNwcmVhZChrZXkgPSB5ZWFyLCB2YWx1ZSA9IGFyZWEpICU+JQogIGdyb3VwX2J5KGNvdW50cnkpICU+JSBzdW1tYXJpemUodmFsdWUgPSBgMjAxNmAtYDIwMTBgKSAlPiUKICBqb2luQ291bnRyeURhdGEyTWFwKGpvaW5Db2RlPSJOQU1FIiwgbmFtZUpvaW5Db2x1bW49ImNvdW50cnkiKQoKbWFwUGFyYW1zIDwtIG1hcENvdW50cnlEYXRhKHZpeiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lQ29sdW1uVG9QbG90PSJ2YWx1ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwVGl0bGU9IkNoYW5nZSBpbiBQYXN0dXJlIEFyZWEgMjAxMC0yMDE2ICgxMDAwIGhhKSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0TWV0aG9kID0gYygtNDUwMDAsLTUwMDAsLTUwMCwwLDUwMCw1MDAwLDEwMDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXJQYWxldHRlID0gYygiZGFyayBncmVlbiIsICJ3aGl0ZSIsICJyZWQiKSwgYWRkTGVnZW5kID0gRkFMU0UpIAoKZG8uY2FsbChhZGRNYXBMZWdlbmQsIGMobWFwUGFyYW1zLCBsZWdlbmRMYWJlbHM9ImFsbCIsIGxlZ2VuZFdpZHRoPTAuNSkpCgpgYGAKUmVjZW50bHksIGZvciBpbnN0YW5jZSwgZnJvbSAyMDEwIHRvIDIwMTYsIHBhc3R1cmUgaGFzIGdyb3duIGluIHNvbWUgY291bnRyaWVzLCB3aGlsZSBzaHJpbmtpbmcgaW4gb3RoZXJzLiBQYXN0dXJlIGhhcyBub3RhYmx5IHNocnVuayBmcm9tIGVhcmxpZXIgaGlnaCBsZXZlbHMgYWxtb3N0IGFjcm9zcyB0aGUgd29ybGQsIGluY2x1ZGluZyBpbiBCcmF6aWwgYW5kIGRyYW1hdGljYWxseSBpbiBBdXN0cmFsaWEuIEhvd2V2ZXIsIGl0IGhhcyBleHBhbmRlZCBpbiB0aGUgVS5TLiwgYW5kIFBlcnUsIENvbHVtYmlhLCBhbmQgQ2hpbmEsIGFzIHdlbGwgYXMgcGFydHMgb2YgV2VzdGVybiBhbmQgTm9ydGhlcm4gRXVyb3BlLiAgIAoKCgojIyBTaW1pbGFyIHRvIEZpZy4gMiAtIEdsb2JhbCBSdW1pbmFudCBNZWF0IGFuZCBNaWxrIFByb2R1Y3Rpb24KYGBge3IgR2xvYmFsIE1lYXQgUHJvZHVjdGlvbiBieSBBbmltYWx9CnZpeiA8LSBtZWF0X3Byb2R1Y3Rpb24gJT4lCiAgZ3JvdXBfYnkoeWVhciwgaXRlbSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhbGwgPSBzdW0obV9wcm9kLCBuYS5ybSA9IFQpKSAlPiUKICBnZ3Bsb3QoKSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gYWxsLCBjb2xvcj1pdGVtKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBvaW50KSArCiAgICBsYWJzKHRpdGxlID0gIk1lYXQgUHJvZHVjdGlvbiBmcm9tIEdyYXppbmcgQW5pbWFscyBSb3NlIE1vc3QgZm9yIENhdHRsZSIsIHkgPSAiUHJvZHVjdGlvbiAodG9ubmVzKSIpCmdncGxvdGx5KHZpeikKYGBgCkdsb2JhbCBtZWF0IHByb2R1Y3Rpb24gaGFzIGdlbmVyYWxseSByaXNlbiBmb3IgYWxsIGdyYXppbmcgYW5pbWFscywgYnV0IGRyYW1hdGljYWxseSBtb3JlIHNvIGZvciBjYXR0bGUgdGhhbiBvdGhlciBhbmltYWxzLiBUaGlzIHN1cHBvcnRzIHRoZSBpZGVhIHRoYXQgY2F0dGxlIHByb2R1Y3Rpb24gaXMgdGhlIG1haW4gZ2xvYmFsIGRyaXZlciBvZiBwYXN0dXJlIGV4cGFuc2lvbi4gCgoKCmBgYHtyIEdsb2JhbCBNaWxrIFByb2R1Y3Rpb24gYnkgQW5pbWFsfQp2aXogPC1taWxrX3Byb2R1Y3Rpb24gJT4lCiAgZ3JvdXBfYnkoeWVhciwgaXRlbSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhbGwgPSBzdW0oZF9wcm9kLCBuYS5ybSA9IFQpKSAlPiUKICBnZ3Bsb3QoKSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gYWxsLCBjb2xvcj1pdGVtKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBvaW50KSArCiAgICBsYWJzKHRpdGxlID0gIk1pbGsgUHJvZHVjdGlvbiBmcm9tIEdyYXppbmcgQW5pbWFscyBSb3NlIE1vc3QgZm9yIENhdHRsZSIsIHkgPSAiUHJvZHVjdGlvbiAodG9ubmVzKSIpCmdncGxvdGx5KHZpeikKYGBgClRoZSBzYW1lIGlzIHRydWUgZm9yIG1pbGsgLSBwcm9kdWN0aW9uIGZyb20gY2F0dGxlIHJvc2UgbW9zdCBkcmFtYXRpY2FsbHkuIEJ1ZmZhbG8gcHJvZHVjZSB0aGUgc2Vjb25kIG1vc3QgbWlsayBjb21wYXJlZCB0byBjYXR0bGUuIE5ldmVydGhlbGVzcywgdGhleSB0b28gcHJvZHVjZSBhIGZyYWN0aW9uIG9mIHdoYXQgY2F0dGxlIGRvLCB+MS83IGluIDIwMTYuCgoKYGBge3IgRmlnLiAyYSBDb21iaW5lZCBNZWF0IFByb2R1Y3Rpb259Cm1lYXRfcHJvZHVjdGlvbiAlPiUKICBncm91cF9ieSh5ZWFyKSAlPiUKICBkcGx5cjo6c3VtbWFyaXplKGFsbCA9IHN1bShtX3Byb2QsIG5hLnJtID0gVCkpICU+JQogIGdncGxvdCgpICsKICAgIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSBhbGwpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcG9pbnQpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygxOTYxLDE5NzAsMTk4MCwxOTkwLDIwMDAsMjAxMCkpICsKICAgIGxhYnModGl0bGUgPSAiVG90YWwgR2xvYmFsIE1lYXQgUHJvZHVjdGlvbiIsIHkgPSAiUHJvZHVjdGlvbiAodG9ubmVzKSIpCmBgYApUaGVyZSBoYXMgYmVlbiBhIHNsaWdodCBsZXZlbGluZyBvZmYgaW4gY29tYmluZWQgbWVhdCBwcm9kdWN0aW9uIGZyb20gYWxsIGFuaW1hbHMsIHNpbWlsYXIgdG8gcHJldmlvdXMgdHJlbmRzIGluIG1lYXQgcHJvZHVjdGlvbiwgYW5kIGZvcmVjYXN0cywgdGhlcmUgaXMgbGl0dGxlIHJlYXNvbiB0byB0aGluayB0aGlzIGxldmVsbGluZyBvZmYgd2lsbCBwZXJzaXN0LgoKCmBgYHtyIEZpZy4gMmIgLSBDb21iaW5lZCBNaWxrIFByb2R1Y3Rpb259Cm1pbGtfcHJvZHVjdGlvbiAlPiUKICBncm91cF9ieSh5ZWFyKSAlPiUKICBkcGx5cjo6c3VtbWFyaXplKGFsbCA9IHN1bShkX3Byb2QsIG5hLnJtID0gVCkpICU+JQogIGdncGxvdCgpICsKICAgIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSBhbGwpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcG9pbnQpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygxOTYxLDE5NzAsMTk4MCwxOTkwLDIwMDAsMjAxMCkpICsKICAgIGxhYnModGl0bGUgPSAiVG90YWwgR2xvYmFsIE1pbGsgUHJvZHVjdGlvbiIsIHkgPSAiUHJvZHVjdGlvbiAodG9ubmVzKSIpCmBgYApDb21iaW5lZCBnbG9iYWwgbWlsayBwcm9kdWN0aW9uIGZvcm0gYWxsIGFuaW1hbHMgaGFzIHNlZW4gYSBzaW1pbGFyLCBidXQgc2xpZ2h0bHkgbW9yZSBkcmFtYXRpYyBsZXZlbGluZyBvZmYuIAoKCgojIyBTaW1pbGFyIHRvIEZpZyAzIC0gQ29uc3VtcHRpb24KYGBge3IgVG90YWwgQ29uc3VtcHRpb24gR2xvYmFsbHkgYW5kIGJ5IFJlZ2lvbn0KIyBjb25zdW1wdGlvbl9nbG9iYWwkY29uc190b3RhbF9ub3JtIDwtIHdpdGgoY29uc3VtcHRpb25fZ2xvYmFsLCBhdmUoY29uc190b3RhbCwgaXRlbSwgRlVOID0gZnVuY3Rpb24oeCkgeC94WzFdKSkgI2NyZWF0ZSBjb2x1bW4gZm9yIGNoYW5nZSBjb21wYXJlZCB0byAxc3Qgb2JzZXJ2YXRpb24gCgpjb25zdW1wdGlvbl9nbG9iYWwgJT4lCiAgZmlsdGVyKGl0ZW0gIT0iQ2hlZXNlIiAmIGl0ZW0gIT0iQ3JlYW0iKSAlPiUKICBnZ3Bsb3QoKSArCiAgICBnZW9tX2FyZWEoYWVzKHggPSB5ZWFyLCB5ID0gY29uc190b3RhbCwgZmlsbCA9IGl0ZW0pKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcG9pbnQpICsKICAgIGxhYnModGl0bGUgPSAiR2xvYmFsIE1lYXQgYW5kIE1pbGsgQ29uc3VtcHRpb24iLCB5ID0gIkNvbnN1bXB0aW9uIGluIDEwMDAgdG9ubmVzIikKCm1lYXRfY29uc19jaGFuZ2UgPC0gY29uc3VtcHRpb25fZ2xvYmFsICU+JSAKICBmaWx0ZXIoaXRlbSAlaW4lIGMoIkJvdmluZSBNZWF0IiwgIk11dHRvbiAmIEdvYXQgTWVhdCIpLCB5ZWFyICVpbiUgYygxOTYxLDIwMTMpKSAlPiUKICBzZWxlY3QoaXRlbSwgeWVhciwgY29uc190b3RhbCkgJT4lCiAgZ3JvdXBfYnkoeWVhcikgJT4lIHN1bW1hcml6ZSh0b3RhbD1zdW0oY29uc190b3RhbCwgbmEucm09VCkpICU+JQogIHNwcmVhZChrZXkgPSB5ZWFyLCB2YWx1ZSA9IHRvdGFsKSAlPiUKICBtdXRhdGUoZGlmZl9hYnM9IGAyMDEzYC1gMTk2MWAsIGRpZmZfcGN0PSAoKGAyMDEzYC9gMTk2MWApLTEpKjEwMCkKCm1pbGtfY29uc19jaGFuZ2UgPC0gY29uc3VtcHRpb25fZ2xvYmFsICU+JSAKICBmaWx0ZXIoaXRlbSAlaW4lIGMoIkJ1dHRlciwgR2hlZSIsICJDaGVlc2UiLCAiQ3JlYW0iLCAiTWlsayAtIEV4Y2x1ZGluZyBCdXR0ZXIiKSwgeWVhciAlaW4lIGMoMTk2MSwyMDEzKSkgJT4lCiAgc2VsZWN0KGl0ZW0sIHllYXIsIGNvbnNfdG90YWwpICU+JQogIGdyb3VwX2J5KHllYXIpICU+JSBzdW1tYXJpemUodG90YWw9c3VtKGNvbnNfdG90YWwsIG5hLnJtPVQpKSAlPiUKICBzcHJlYWQoa2V5ID0geWVhciwgdmFsdWUgPSB0b3RhbCkgJT4lCiAgbXV0YXRlKGRpZmZfYWJzPSBgMjAxM2AtYDE5NjFgLCBkaWZmX3BjdD0gKChgMjAxM2AvYDE5NjFgKS0xKSoxMDApCmBgYApUb3RhbCBjb25zdW1wdGlvbiBvZiBydW1pbmFudCBtZWF0IGFuZCBtaWxrIGhhcyBpbmNyZWFzZWQgYnkgYHIgcm91bmQobWVhdF9jb25zX2NoYW5nZSRkaWZmX3BjdCwwKWAgYW5kIGByIHJvdW5kKG1pbGtfY29uc19jaGFuZ2UkZGlmZl9wY3QsIDApYCwgcmVzcGVjdGl2ZWx5LCBzaW5jZSAxOTYxLgoKCmBgYHtyIENvbnN1bXB0aW9uIHBlciBjYXBpdGF9CiMgY29uc3VtcHRpb25fZ2xvYmFsICU+JQojICAgZmlsdGVyKGl0ZW0gIT0iQ2hlZXNlIikgJT4lCiMgICBncm91cF9ieSh5ZWFyLCBpdGVtKSAlPiUKIyAgIGRwbHlyOjpzdW1tYXJpemUoYWxsID0gc3VtKGNvbnNfcGNfa2csIG5hLnJtID0gVCkpICU+JQojICAgZ2dwbG90KCkgKwojICAgICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gYWxsLCBjb2xvciA9IGl0ZW0pKSArCiMgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwb2ludCkgKwojICAgICBsYWJzKHRpdGxlID0gIk1lYXQgYW5kIE1pbGsgQ29uc3VtcHRpb24gcGVyIENhcGl0YSIsIHN1YnRpdGxlID0gIk9yaWdpbmFsIEZpZ3VyZSAzIiwgeSA9ICJDb25zdW1wdGlvbiBpbiBrZy9jYXBpdGEveXIiKQoKY29uc3VtcHRpb25fZ2xvYmFsICU+JQogIGZpbHRlcihpdGVtICE9IkNoZWVzZSIgJiBpdGVtICE9IkNyZWFtIikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgaXRlbSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhbGwgPSBzdW0oY29uc19wY19jYWwsIG5hLnJtID0gVCkpICU+JQogIGdncGxvdCgpICsKICAgIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSBhbGwsIGNvbG9yID0gaXRlbSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwb2ludCkgKwogICAgbGFicyh0aXRsZSA9ICJNZWF0IGFuZCBNaWxrIENvbnN1bXB0aW9uIHBlciBDYXBpdGEiLCB5ID0gIkNvbnN1bXB0aW9uIGluIGtjYWwvY2FwaXRhL2RheSIpCgojIGNvbnN1bXB0aW9uX2dsb2JhbCAlPiUKIyAgIGZpbHRlcihpdGVtICE9IkNoZWVzZSIpICU+JQojICAgZ3JvdXBfYnkoeWVhciwgaXRlbSkgJT4lCiMgICBkcGx5cjo6c3VtbWFyaXplKGFsbCA9IHN1bShwcm90ZWluX3BjLCBuYS5ybSA9IFQpKSAlPiUKIyAgIGdncGxvdCgpICsKIyAgICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IGFsbCwgY29sb3IgPSBpdGVtKSkgKwojICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcG9pbnQpICsKIyAgICAgbGFicyh0aXRsZSA9ICJNZWF0IGFuZCBNaWxrIENvbnN1bXB0aW9uIHBlciBDYXBpdGEiLCB5ID0gIkNvbnN1bXB0aW9uIGluIHByb3RlaW4vY2FwaXRhL2RheSIpCmBgYApDb25zdW1wdGlvbiBwZXIgY2FwaXRhIGlzIGdyZWF0ZXN0IGZvciBtaWxrIHdoZXRoZXIgbWVhc3VyZWQgaW4gY2Fsb3JpZXMsIGdyYW1zIHByb3RlaW4sIG9yIHdlaWdodC4gTWlsayBjb25zdW1wdGlvbiBwZXIgY2FwaXRhIGhhcyBpbmNyZWFzZWQgbW9yZSB0aGFuIHRoYXQgZm9yIGFueSBydW1pbmFudCBtZWF0cy4gSG93ZXZlciwgYXMgSmFtZXMnIGdyYXBocyBzaG93ZWQsIHBvcmsgYW5kIHBvdWx0cnkgY29uc3VtcHRpb24gaGFzIGRyYW1hdGljYWxseSBpbmNyZWFzZWQgb3ZlciB0aW1lLiAKClRoZSByZWxhdGl2ZWx5IGZsYXQgdHJlbmQgaW4gYm92aW5lIG1lYXQgY29uc3VtcHRpb24gaW5kaWNhdGVzIHRoYXQgZ3Jvd3RoIGluIGNhdHRsZSBwcm9kdWN0aW9uIGhhcyBiZWVuIGRyaXZlbiBieSBhIGNvbWJpbmF0aW8gb2YgaW5jcmVhc2luZyBkYWlyeSBkZW1hbmQgcyB3ZWxsIGFzIGluY3JlYXNlZCBnbG9iYWwgcG9wdWxhdGlvbiwgbW9yZXNvIHRoYW4gYW55IGNoYW5nZSBpbiBiZWVmIGRlbWFuZC4KCk5vdGU6IFRoZXJlIGFyZSBvbmx5IHRvdGFsIGNvbnN1bXB0aW9uIHZhbHVlcyBpbiB0b25uZXMgZm9yIGNoZWVzZSBzaW5jZSB0aGUgY2Fsb3JpZSwgcHJvdGVpbiBhbmQgZmF0IGNvbnRlbnQgdmFyaWVzIHNvIHdpZGVseSBhbmQgYXBwYXJlbnRseSBGQU8gZG9lcyBub3QgY2FsY3VsYXRlIHRoaXMuIFRoZSBjcmVhbSB2YWx1ZXMgYXJlIGFsc28gbmVnbGlnaWJsZS4gSSBoYXZlIG9taXR0ZWQgdGhlc2UgZnJvbSB0aGUgZ3JhcGhzLiAKCgpgYGB7ciBUb3RhbCBDb25zdW1wdGlvbiBkaWZmZXJlbmNlIGZyb20gZmlyc3QgeWVhcn0KY29uc3VtcHRpb25fZ2xvYmFsJGNvbnNfcGNfY2FsX25vcm0gPC0gd2l0aChjb25zdW1wdGlvbl9nbG9iYWwsIGF2ZShjb25zX3BjX2NhbCwgaXRlbSwgRlVOID0gZnVuY3Rpb24oeCkgeC94WzFdKSkgI2NyZWF0ZSBjb2x1bW4gZm9yIGNoYW5nZSBjb21wYXJlZCB0byAxc3Qgb2JzZXJ2YXRpb24gCgp2aXogPC0gY29uc3VtcHRpb25fZ2xvYmFsICU+JQogIGZpbHRlcihpdGVtICE9IkNoZWVzZSIgJiBpdGVtICE9IkNyZWFtIikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgaXRlbSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShhbGwgPSBzdW0oY29uc19wY19jYWxfbm9ybSwgbmEucm0gPSBUKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IGFsbCwgY29sb3IgPSBpdGVtKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBvaW50KSArCiAgICBsYWJzKHRpdGxlID0gIk1lYXQgYW5kIE1pbGsgQ29uc3VtcHRpb24iLCB5ID0gIkNvbnN1bXB0aW9uIHBlciBjYXBpdGEgaW4ga2NhbCByZWxhdGl2ZSB0byBmaXJzdCB5ZWFyIikKCmdncGxvdGx5KHZpeikKYGBgClRoZSBzdGVlcCByaXNlIGluIHBvdWx0cnkgYW5kIHBvcmsgaXMgbW9yZSBhcHBhcmVudCB3aGVuIHlvdSBsb29rIGF0IGNoYW5nZSBpbiBjb25zdW1wdGlvbiAoaW4ga2NhbC9jYXBpdGEpIHJlbGF0aXZlIHRvIHRoZSBmaXJzdCB5ZWFyIGluIHRoZSBkYXRhLgoKIyMgU2ltaWxhciB0byBGaWcuIDcgLSBDYXR0bGUgTWVhdCBhbmQgTWlsayBDb25zdW1wdGlvbiBieSBSZWdpb24gCmBgYHtyfQpjb25zdW1wdGlvbiAlPiUKICBmaWx0ZXIoaXRlbT09IkJvdmluZSBNZWF0IikgJT4lCiAgZ3JvdXBfYnkobWFqb3JfZ3JvdXAsIG1pbm9yX2dyb3VwLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWwgPSBzdW0oY29uc190b3RhbCkpICU+JQogIGdncGxvdCgpICsKICAgIGdlb21fYXJlYShhZXMoeCA9IHllYXIsIHkgPSB0b3RhbCwgZ3JvdXA9bWlub3JfZ3JvdXAsIGZpbGw9bWlub3JfZ3JvdXApKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcG9pbnQpICsKICAgIGxhYnModGl0bGUgPSAiUmVnaW9uYWwgTWVhdCBDb25zdW1wdGlvbiIsIHkgPSAiQ29uc3VtcHRpb24gaW4gMTAwMCB0b25uZXMiKSArCiAgZmFjZXRfd3JhcCgufm1ham9yX2dyb3VwLCBuY29sPTIpCgoKY29uc3VtcHRpb25fbWFwIDwtIGNvbnN1bXB0aW9uCmNvbnN1bXB0aW9uX21hcCRjb3VudHJ5IDwtIGFzLmZhY3Rvcihjb25zdW1wdGlvbl9tYXAkY291bnRyeSkKY29uc3VtcHRpb25fbWFwJGNvdW50cnkgPC0gcmVjb2RlKGNvbnN1bXB0aW9uX21hcCRjb3VudHJ5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJ1c3NpYW4gRmVkZXJhdGlvbiI9IlJ1c3NpYSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoaW5hLCBtYWlubGFuZCIgPSAiQ2hpbmEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVU1NSIj0iUnVzc2lhIikKCnZpeiA8LSBjb25zdW1wdGlvbl9tYXAgJT4lCiAgZmlsdGVyKGl0ZW09PSJCb3ZpbmUgTWVhdCIsIHllYXIgJWluJSBjKDE5NjEsMjAxMykpICU+JQogIHNlbGVjdChjb3VudHJ5LCB5ZWFyLCBjb25zX3RvdGFsKSAlPiUKICBzcHJlYWQoa2V5ID0geWVhciwgdmFsdWUgPSBjb25zX3RvdGFsKSAlPiUKICBncm91cF9ieShjb3VudHJ5KSAlPiUgc3VtbWFyaXplKHZhbHVlID0gYDIwMTNgLWAxOTYxYCkgJT4lCiAgam9pbkNvdW50cnlEYXRhMk1hcChqb2luQ29kZT0iTkFNRSIsIG5hbWVKb2luQ29sdW1uPSJjb3VudHJ5IikKICAKCm1hcFBhcmFtcyA8LSBtYXBDb3VudHJ5RGF0YSh2aXosIG5hbWVDb2x1bW5Ub1Bsb3Q9InZhbHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXBUaXRsZT0iQ2hhbmdlIGluIEJlZWYgQ29uc3VtcHRpb24gMTk2MS0yMDEzICgxMDAwIHRvbm5lcykiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0TWV0aG9kID0gYygwLDEwMDAsMjAwMCwzMDAwLDQwMDAsNTAwMCw2MDAwLDcwMDAsODAwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXJQYWxldHRlID0gYygibGlnaHQgeWVsbG93IiwgIm9yYW5nZSIsICJyZWQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZExlZ2VuZCA9IEZBTFNFKQoKZG8uY2FsbChhZGRNYXBMZWdlbmQsIGMobWFwUGFyYW1zLCBsZWdlbmRMYWJlbHM9ImFsbCIsIGxlZ2VuZFdpZHRoPTAuNSkpCgpgYGAKVGhlIGdsb2JhbCB0cmVuZCBpbiBiZWVmIG1lYXQgY29uc3VtcHRpb24gYXBwZWFycyB0byBtb3N0bHkgYmUgZHJpdmVuIGJ5IHRoZSByYXBpZCByaXNlIGluIEVhc3Rlcm4gQXNpYSAoQ2hpbmEpLCBhcyB3ZWxsIGFzIHRoZSBzdGVhZHkgaW5jcmVhc2UgaW4gU291dGggQW1lcmljYSAoRXNwZWNpYWxseSBCcmF6aWwpCgoKIyMgU2ltaWxhciB0byBGaWd1cmUgNCAmIDggLSBDaGFuZ2UgaW4gWWllbGRzCmBgYHtyIEdsb2JhbCBNZWF0IFlpZWxkc30KI25vdCBpbnRlcmVzdGluZwojIG1lYXRfeWllbGRzX2dsb2JhbCAlPiUKIyAgIGdncGxvdCgpICsKIyAgICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IHlpZWxkLCBjb2xvcj1pdGVtKSkgKwojICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcG9pbnQpICsKIyAgICAgbGFicyh0aXRsZSA9ICJHbG9iYWwgTWVhdCBZaWVsZHMgZm9yIFRvcCBHcmF6aW5nIEFuaW1hbHMiLCB5ID0gIkhlY3RvZ3JhbXMvQW5pbWFsIikKCm1lYXRfeWllbGRzX2dsb2JhbCR5aWVsZF9ub3JtIDwtIHdpdGgobWVhdF95aWVsZHNfZ2xvYmFsLCBhdmUoeWllbGQsIGl0ZW0sIEZVTiA9IGZ1bmN0aW9uKHgpIHgveFsxXSkpICNjcmVhdGUgY29sdW1uIGZvciBjaGFuZ2UgY29tcGFyZWQgdG8gMXN0IG9ic2VydmF0aW9uCgp2aXogPC0gIG1lYXRfeWllbGRzX2dsb2JhbCAlPiUKICBnZ3Bsb3QoKSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0geWllbGRfbm9ybSwgY29sb3I9aXRlbSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwb2ludCkgKwogICBsYWJzKHRpdGxlID0gIkdsb2JhbCBNZWF0IFlpZWxkcyBmb3IgVG9wIEdyYXppbmcgQW5pbWFscyAtICUgQ2hhbmdlIGZyb20gMTk2MSIsIHkgPSAiS2cvQW5pbWFsIFJlbGF0aXZlIHRvIEZpcnN0IFllYXIiKQoKZ2dwbG90bHkodml6KQpgYGAKQ2F0dGxlIHlpZWxkcyBoYXZlIGluY3JlYXNlZCB0aGUgbW9zdCBjb21wYXJlZCB0byBvdGhlciB0b3AgZ3JhemluZyBhbmltYWxzLCB3aXRoIHlpZWxkcyBuZWFybHkgMzQlIGhpZ2hlciBpbiAyMDEzIHRoYW4gaW4gMTk2MS4gIEFzIHRoZSByZXBvcnQgZGVzY3JpYmVzLCB0aGlzIGltcHJvdmVtZW50IGlzIGVtYmxlbWF0aWMgb2YgdGhlICJsaXZlc3RvY2sgcmV2b2x1dGlvbiIgdGhhdCBoYXMgaW1wcm92ZWQgbGFuZCBwcm9kdWN0aXZpdHkgb2YgYW5pbWFsIHByb2R1Y3Rpb24gYW5kIHJlZHVjZWQgcGFzdHVyZSBleHBhbnNpb24gcHJlc3N1cmUuCgpgYGB7ciBHbG9iYWwgTWlsayBZaWVsZHN9CiNub3QgaW50ZXJlc3RpbmcKIyBtaWxrX3lpZWxkc19nbG9iYWwgJT4lCiMgICBnZ3Bsb3QoKSArCiMgICAgIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSB5aWVsZCwgY29sb3I9aXRlbSkpICsKIyAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBvaW50KSArCiMgICAgIGxhYnModGl0bGUgPSAiR2xvYmFsIE1pbGsgWWllbGRzIGZvciBUb3AgR3JhemluZyBBbmltYWxzIiwgeSA9ICJIZWN0b2dyYW1zL0FuaW1hbCIpCgptaWxrX3lpZWxkc19nbG9iYWwkeWllbGRfbm9ybSA8LSB3aXRoKG1pbGtfeWllbGRzX2dsb2JhbCwgYXZlKHlpZWxkLCBpdGVtLCBGVU4gPSBmdW5jdGlvbih4KSB4L3hbMV0pKSAjY3JlYXRlIGNvbHVtbiBmb3IgY2hhbmdlIGNvbXBhcmVkIHRvIDFzdCBvYnNlcnZhdGlvbgoKdml6IDwtICBtaWxrX3lpZWxkc19nbG9iYWwgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IHlpZWxkX25vcm0sIGNvbG9yPWl0ZW0pKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcG9pbnQpICsKICAgbGFicyh0aXRsZSA9ICJHbG9iYWwgTWlsayBZaWVsZHMgZm9yIFRvcCBHcmF6aW5nIEFuaW1hbHMgLSAlIENoYW5nZSBmcm9tIDE5NjEiLCB5ID0gIktnL0FuaW1hbCBSZWxhdGl2ZSB0byBGaXJzdCBZZWFyIikKCmdncGxvdGx5KHZpeikKYGBgClRIaXMgaXMgYXBwYXJlbnQgd2hlbiBsb29raW5nIGF0IGNhdHRsZSBhbmQgYnVmZmFsbyBhcyB3ZWxsLiBDYXR0bGUgbWlsayB5aWVsZHMgaW4gMjAxNiB3ZXJlIDM2JSBoaWdoZXIgdGhhbiBpbiAxOTYxLiBBbHRob3VnaCBnb2F0IGFuZCBzaGVlcCB5aWVsZHMgaGF2ZSBkZWNyZWFzZWQgb3ZlciB0aW1lLCB0aGlzIGhhcyBwdXQgbGl0dGxlIGFkZGl0aW9uYWwgcHJlc3N1cmUgb24gcGFzdHVyZSBleHBhbnNpb24gc2luY2UgdGhlc2UgYW5pbWFscyBjb21wcmlzZSBhIGZyYWN0aW9uIG9mIG92ZXJhbGwgbWlsayBhbmQgbWVhdCBwcm9kdWN0aW9uLiAKCkhvd2V2ZXIsIHRoZSBnbG9iYWwgdHJlbmRzIG1hc2sgcmVnaW9uYWwgZGlmZmVyZW5jZXMgaW4geWllbGRzIGFuZCBjaGFuZ2VzIGluIHlpZWxkcy4KCiMjIFJlZ2lvbmFsIE1lYXQgWWllbGRzCmBgYHtyIE1ham9yIFJlZ2lvbmFsIE1lYXQgWWllbGRzfQojd2hpbGUgd2UgY291bGQgYWdncmVnYXRlIHVwIHRoZSBjb3VudHJ5IGxldmVsIHZhbHVlcyB0byB0aGUgcmVnaW9uYWwgbGV2ZWwsIHRoZXNlIGRvIG5vdCBhbGlnbiB3aXRoIEZBTyByZWdpb25hbCB2YWx1ZXMgZnJvbSB0aGVpciB3ZWJzaXRlLiBUaGVyZWZvcmUgSSB1c2UgIHJlZ2lvbmFsIGRhdGEgZG93bmxvYWRlZCBmcm9tIEZBTyBpbnN0ZWFkIGFzIGRldGFpbGVkIGluIHRoZSBjbGVhbl9hbmRfcHJlcF9maWxlLiAgCgp5aWVsZF9kdW1iZWxsIDwtZnVuY3Rpb24oeCwgYW5pbWFsLCBmaXJzdF95ciwgbGFzdF95cikgewogIHRlbXAgPC0geCAlPiUgZmlsdGVyKGl0ZW09PWFzLmNoYXJhY3RlcihhbmltYWwpLCB5ZWFyICVpbiUgYyhmaXJzdF95cixsYXN0X3lyKSkgJT4lCiAgc3ByZWFkKGtleSA9IHllYXIsIHZhbHVlPXlpZWxkKQogIAogIGNvbG5hbWVzKHRlbXApWzM6NF0gPC0gYygiZmlyc3RfeXIiLCAibGFzdF95ciIpCiAgCiAgdml6IDwtIHBsb3RfbHkodGVtcCwgY29sb3IgPSBJKCJncmF5ODAiKSkgJT4lCiAgYWRkX3NlZ21lbnRzKHggPSB+Zmlyc3RfeXIsIHhlbmQgPSB+YGxhc3RfeXJgLCB5ID0gfmNvdW50cnksIHllbmQgPSB+Y291bnRyeSwgc2hvd2xlZ2VuZCA9IEZBTFNFKSAlPiUKICBhZGRfbWFya2Vycyh4ID0gfmZpcnN0X3lyLCB5ID0gfmNvdW50cnksIG5hbWUgPSBkZXBhcnNlKGZpcnN0X3lyKSwgY29sb3IgPSBJKCJyZWQiKSkgJT4lCiAgYWRkX21hcmtlcnMoeCA9IH5sYXN0X3lyLCB5ID0gfmNvdW50cnksIG5hbWUgPSBkZXBhcnNlKGxhc3RfeXIpLCBjb2xvciA9IEkoImdyZWVuIikpICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gcGFzdGUwKCJDaGFuZ2UgaW4gIiwgc3RyX3RvX3RpdGxlKGFzLmNoYXJhY3RlcihhbmltYWwpKSwgIiBZaWVsZHMiKSwKICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJZaWVsZHMgKGhnL2FuaW1hbCkiKSwKICAgIG1hcmdpbiA9IGxpc3QobCA9IDY1KSkgCiAgICByZXR1cm4odml6KQp9CiAgCnlpZWxkX2R1bWJlbGwobWVhdF95aWVsZHNfcmVnaW9uYWxfbWFqb3IsICJjYXR0bGUiLCAxOTYxLCAyMDEzKSAgI2NhbiBjaG9vc2UgYW55IGFuaW1hbCBvciAyIHllYXJzLgpgYGAKQWx0aG91Z2ggbWVhdCB5aWVsZHMgaGF2ZSBncm93biBnbG9iYWxseSwgdGhleSBoYXZlIGdyb3duIG11Y2ggbGVzcyBpbiBBZnJpY2EgdGhhbiBlbHNld2hlcmUuIERlc3BpdGUgZ3Jvd2luZyBpbiBBc2lhIG92ZXIgNTAlLCB0aGV5IGFyZSBzdGlsbCBzdWJzdGFudGlhbGx5IGJlbG93IHlpZWxkIGxldmVscyBpbiBFdXJvcGUsIHRoZSBBbWVyaWNhcyBhbmQgT2NlYW5pYS4gCgpgYGB7ciBSZWdpb25hbCBNaW5vciBNZWF0IFlpZWxkc30KeWllbGRfZHVtYmVsbChtZWF0X3lpZWxkc19yZWdpb25hbF9taW5vciwgImNhdHRsZSIsIDE5NjEsIDIwMTMpICAjY2FuIGNob29zZSBhbnkgYW5pbWFsIG9yIDIgeWVhcnMuCmBgYApEaWdnaW5nIGRlZXBlciwgaXQgYmVjb21lcyBhcHBhcmVudCB0aGF0IHlpZWxkcyBpbiBBZnJpY2EgaGF2ZSBncm93biBtb3N0bHkgaW4gTm9ydGhlcm4gYW5kIFNvdXRoZXJuIEFmcmljYSwgd2hpbGUgdGhleSBoYXZlIHN0YWduYXRlZCBpbiBNaWRkbGUsIEVhc3Rlcm4gYW5kIFdlc3Rlcm4gQWZyaWNhLiBJbiBBc2lhLCBhIGxvdCBvZiB0aGUgZ3Jvd3RoIGluIHlpZWxkcyB3YXMgaW4gV2VzdGVybiBBc2lhLCB3aGlsZSB5aWVsZHMgaW4gRWFzdCBBc2lhLCB3aGVyZSBhIGxvdCBvZiB0aGUgZ3Jvd3RoIGluIGRlbWFuZCBpcywgaGF2ZSBub3QgZ3Jvd24gbXVjaC4gCgojIyBSZWdpb25hbCBNaWxrIFlpZWxkcwpgYGB7ciBSZWdpb25hbCBNaWxrIE1ham9yIFlpZWxkc30KeWllbGRfZHVtYmVsbChtaWxrX3lpZWxkc19yZWdpb25hbF9tYWpvciwgImNhdHRsZSIsIDE5NjEsIDIwMTMpICAjY2FuIGNob29zZSBhbnkgYW5pbWFsIG9yIDIgeWVhcnMuCmBgYApTaW1pbGFyIHRyZW5kcyBhcmUgdmlzaWJsZSBmb3IgY2F0dGxlIG1pbGsgeWllbGRzLCBhbHRob3VnaCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBPY2VhbmlhLCBFdXJvcGUsIGFuZCB0aGUgQW1lcmljYXMgdnMuIEFzaWEgYW5kIEFmcmljYSBhcmUgc3Rhcmtlci4gCgoKYGBge3IgfQp5aWVsZF9kdW1iZWxsKG1pbGtfeWllbGRzX3JlZ2lvbmFsX21pbm9yLCAiY2F0dGxlIiwgMTk2MSwgMjAxMykgICNjYW4gY2hvb3NlIGFueSBhbmltYWwgb3IgMiB5ZWFycy4KYGBgCk1pbGsgeWllbGRzIGhhdmUgc3RhbGxlZCBpbiBtYW55IG9mIHRoZSBzYW1lIHBsYWNlcyBhcyBtZWF0IHlpZWxkcywgdGhvdWdoIFNvdXRoZXJuIGFuZCBOb3J0aGVybiBBZnJjYSBkaWRuJ3Qgc2VlIHRoZSBzYW1lIGdhaW5zIGluIG1pbGsgeWllbGRzIGFzIHRoZXkgc2F3IGluIG1lYXQgeWllbGRzLiAKCgojIyBTaW1pbGFyIHRvIEZpZ3VyZSA1IC0gUGFzdHVyZSBwZXIgcHJvZHVjdGlvbi8gRGVjb3VwbGluZyAKYGBge3IgR2xvYmFsIE1lYXQgYW5kIE1pbGsgQW5pbWFscyBwZXIgUGFzdHVyZX0KIyNNT1ZFIFRPIFBSRVAgRklMRQojbWVyZ2UgbWlsayBhbmQgbWVhdCBnbG9iYWwgcHJvZHVjdGlvbiAKCiNDT01NRU5URUQgT1VUIEJFQ0FVU0UgSU4gUFJJT1JJVFkgU0VDVElPTiBBTFJFQURZCiMgbWVhdF9wcm9kdWN0aW9uX2dsb2JhbCA8LSByZW5hbWUobWVhdF9wcm9kdWN0aW9uX2dsb2JhbCwgbWVhdF9wcm9kID0gcHJvZHVjdGlvbikKIyBtaWxrX3Byb2R1Y3Rpb25fZ2xvYmFsIDwtIHJlbmFtZShtaWxrX3Byb2R1Y3Rpb25fZ2xvYmFsLCBtaWxrX3Byb2QgPSBwcm9kdWN0aW9uKQojIG1lYXRfbWlsa19nbG9iYWwgPC0gbGVmdF9qb2luKG1lYXRfcHJvZHVjdGlvbl9nbG9iYWwsIG1pbGtfcHJvZHVjdGlvbl9nbG9iYWwpIAojIAojICNzdW0gdXAgbWVhdCBhbmQgbWlsayBwcm9kCiMgbWVhdF9taWxrX2dsb2JhbCRhbGxfcHJvZCA8LSBtZWF0X21pbGtfZ2xvYmFsJG1lYXRfcHJvZCArIG1lYXRfbWlsa19nbG9iYWwkbWlsa19wcm9kCiMgCiMgI2NyZWF0ZSBkYXRhZnJhbWUgb2YgZ2xvYmFsIHBhc3R1cmUgYXJlYQojIHBhc3R1cmVfZ2xvYmFsIDwtIGxhbmRfYXJlYSAlPiUgZmlsdGVyKGl0ZW0gPT0gYygicGFzdHVyZSIpKSAlPiUgc2VsZWN0KC1pdGVtKSAlPiUgZ3JvdXBfYnkoeWVhcikgJT4lIGRwbHlyOjpzdW1tYXJpc2UoYXJlYSA9IHN1bShhcmVhLCBuYS5ybT1UKSkgCiMgCiMgbWVhdF9taWxrX2dsb2JhbCA8LSBsZWZ0X2pvaW4obWVhdF9taWxrX2dsb2JhbCwgcGFzdHVyZV9nbG9iYWwpCiMgCiMgbWVhdF9taWxrX2dsb2JhbF9jb21iaW5lZCA8LSBzdW1tYXJpemUoZ3JvdXBfYnkobWVhdF9taWxrX2dsb2JhbCwgeWVhciksIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbF9wcm9kID0gbWVhbihhcmVhKS9zdW0oYWxsX3Byb2QsIG5hLnJtPVQpLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWF0X3Byb2QgPSBtZWFuKGFyZWEpL3N1bShtZWF0X3Byb2QsIG5hLnJtPVQpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbGtfcHJvZCA9IG1lYW4oYXJlYSkvc3VtKG1pbGtfcHJvZCwgbmEucm09VCkpICU+JQojICAgZ2F0aGVyKGtleSA9IHByb2R1Y3Rpb25fdHlwZSwgdmFsdWUgPSB2YWx1ZSwgYWxsX3Byb2QsIG1lYXRfcHJvZCwgbWlsa19wcm9kKQojICNFTkQKIyAKIyBtZWF0X21pbGtfZ2xvYmFsX2NvbWJpbmVkJHZhbHVlX25vcm0gPC0gd2l0aChtZWF0X21pbGtfZ2xvYmFsX2NvbWJpbmVkLCBhdmUodmFsdWUsIHByb2R1Y3Rpb25fdHlwZSwgRlVOID0gZnVuY3Rpb24oeCkgeC94WzFdKSkgI2NyZWF0ZSBjb2x1bW4gZm9yIGNoYW5nZSBjb21wYXJlZCB0byAxc3Qgb2JzZXJ2YXRpb24gCiMgCiMgI3Zpc3VhbGl6ZQojIG1lYXRfbWlsa19nbG9iYWxfY29tYmluZWQgJT4lCiMgICBnZ3Bsb3QoKSArCiMgICAgIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZV9ub3JtLCBncm91cD1wcm9kdWN0aW9uX3R5cGUsIGNvbG9yPXByb2R1Y3Rpb25fdHlwZSkpICsKIyAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBvaW50LCBicmVha3MgPSBzZXEoZnJvbSA9IDEuMCx0byA9IDAuNCxieSA9IC0wLjEpKSArCiMgICAgbGFicyh0aXRsZSA9ICJQYXN0dXJlIEFyZWEgcGVyIFJ1bWluYW50IFByb2R1Y3Rpb24gRGVjbGluZWQiLCB5ID0gIkhlY3RhcmVzIHBlciBLZyBNaWxrIG9yIE1lYXQgUHJvZHVjdGlvbiBmcm9tIEFsbCBSdW1pbmFudHMiKQojIGdncGxvdGx5KHZpeikKIyAKIyAgQXMgSmFtZXMgc2hvd2VkIGluIGhpcyBncmFwaHMgYXMgd2VsbCwgdGhlIGFtb3VudCBvZiBwYXN0dXJlIGxhbmQgcGVyIHVuaXQgb2YgbWVhdCBhbmQgbWlsayBwcm9kdWN0aW9uLCB3aGV0aGVyIG1lYXN1cmVkIHNlcGFyYXRlbHkgb3IgY29tYmluZWQgZGVjcmVhc2VkIG92ZXIgNTAlIHNpbmNlIDE5NjEgKG9yIGludmVyc2VseSAgcHJvZHVjdGlvbiBwZXIgaGVjdGFyZSBvZiBwYXN0dXJlIG1vcmUgdGhhbiBkb3VibGVkKS4gIApgYGAKCiAKIApgYGB7ciBSZWdpb25hbCBNZWF0IGFuZCBNaWxrIFByb2R1Y3Rpb24gcGVyIFBhc3R1cmUgQXJlYX0KIyNNT1ZFIFRPIFBSRVAgRklMRT8KI3N1bW1hcml6ZSBhbGwgcnVtaW5hbnQgbWVhdAptZWF0X3N1bSA8LSBzdW1tYXJpemUoZ3JvdXBfYnkobWVhdF9wcm9kdWN0aW9uLGNvdW50cnkseWVhcixtaW5vcl9ncm91cCwgbWFqb3JfZ3JvdXApLCAKICAgICAgICAgICAgICAgICAgICAgIG1faGVhZD1zdW0obV9oZWFkLCBuYS5ybT1UKSwgbV9wcm9kPXN1bShtX3Byb2QsIG5hLnJtPVQpKQoKI3N1bW1hcml6ZSBhbGwgcnVtaW5hbnQgbWlsawptaWxrX3N1bSA8LSBzdW1tYXJpemUoZ3JvdXBfYnkobWlsa19wcm9kdWN0aW9uLGNvdW50cnkseWVhcixtaW5vcl9ncm91cCwgbWFqb3JfZ3JvdXApLCAKICAgICAgICAgICAgICAgICAgICAgIGRfaGVhZD1zdW0oZF9oZWFkLCBuYS5ybT1UKSwgZF9wcm9kPXN1bShkX3Byb2QsIG5hLnJtPVQpKQojbWVyZ2UKbWVhdF9taWxrIDwtIGxlZnRfam9pbihtZWF0X3N1bSwgbWlsa19zdW0pIAoKI3N1bSB1cCBtZWF0IGFuZCBtaWxrIHByb2QKbWVhdF9taWxrJGFsbF9wcm9kIDwtIG1lYXRfbWlsayRtX3Byb2QgKyBtZWF0X21pbGskZF9wcm9kCgojbWVyZ2UgaW4gcGFzdHVyZSBhcmVhCm1lYXRfbWlsayA8LSBsZWZ0X2pvaW4obWVhdF9taWxrLCBmaWx0ZXIobGFuZF9hcmVhLGl0ZW0gPT0gInBhc3R1cmUiKSkKCgptZWF0X21pbGtfbWFqb3JfZ3JvdXAgPC0gc3VtbWFyaXplKAogIGdyb3VwX2J5KG1lYXRfbWlsaywgeWVhciwgbWFqb3JfZ3JvdXApLCAKICBhbGxfcHJvZCA9IHN1bShhcmVhLCBuYS5ybT1UKS9zdW0oYWxsX3Byb2QsIG5hLnJtPVQpLCAKICBtX3Byb2QgPSBzdW0oYXJlYSwgbmEucm09VCkvc3VtKG1fcHJvZCwgbmEucm09VCksCiAgZF9wcm9kID0gc3VtKGFyZWEsIG5hLnJtPVQpL3N1bShkX3Byb2QsIG5hLnJtPVQpKSAlPiUKICAgIGdhdGhlcihrZXkgPSBwcm9kdWN0aW9uX3R5cGUsIHZhbHVlID0gdmFsdWUsIGFsbF9wcm9kLCBtX3Byb2QsIGRfcHJvZCkKCm1lYXRfbWlsa19tYWpvcl9ncm91cCR2YWx1ZV9ub3JtIDwtIHdpdGgobWVhdF9taWxrX21ham9yX2dyb3VwLCBhdmUodmFsdWUsIHByb2R1Y3Rpb25fdHlwZSwgbWFqb3JfZ3JvdXAsIEZVTiA9IGZ1bmN0aW9uKHgpIHgveFsxXSkpICNjcmVhdGUgY29sdW1uIGZvciBjaGFuZ2UgY29tcGFyZWQgdG8gMXN0IG9ic2VydmF0aW9uIAoKI0VORD8KCiN2aXN1YWxpemUKbWVhdF9taWxrX21ham9yX2dyb3VwICU+JQogICNmaWx0ZXIocHJvZHVjdGlvbl90eXBlPT0ibV9wcm9kIikgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IHZhbHVlX25vcm0sIGdyb3VwPW1ham9yX2dyb3VwLCBjb2xvcj1tYWpvcl9ncm91cCkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwb2ludCwgYnJlYWtzID0gc2VxKGZyb20gPSAxLjAsdG8gPSAwLjQsYnkgPSAtMC4xKSkgKwogICBsYWJzKHRpdGxlID0gIlBhc3R1cmUgQXJlYSBwZXIgUnVtaW5hbnQgTWVhdCBQcm9kdWN0aW9uIERlY2xpbmVkIGluIGFsbCBSZWdpb25zIiwgc3VidGl0bGUgPSAiRXhjZXB0IGZvciB0aGUgRm9ybWVyIFNvdmlldCBVbmlvbiIsICJDaGFuZ2UgaW4gSGVjdGFyZXMgcGVyIEtnIE1lYXQgUHJvZHVjdGlvbiBmcm9tIEFsbCBSdW1pbmFudHMgZnJvbSAxOTYxIikgKwogIGZhY2V0X3dyYXAocHJvZHVjdGlvbl90eXBlfi4sIG5jb2w9MikKI2dncGxvdGx5KHZpeikKYGBgCiBUaGUgdG9wIGxlZnQgc2hvd3MgZGFpcnkgKyBtZWF0IHByb2R1Y3Rpb24gZnJvbSBydW1pbmFudHMgZGl2aWRlZCBieSB0b3RhbCBwYXN0dXJlIGFyZWEsIHRoZSB0b3AgcmlnaHQgc2hvd3MganVzdCBkYWlyeSBwcm9kdWN0aW9uIGZyb20gcnVtaW5hbnRzIGRpdmlkZWQgYnkgdG90YWwgcGFzdHVyZSBhcmVhLCBhbmQgdGhlIGJvdHRvbSBsZWZ0IHNob3dzIGp1c3QgbWVhdCBwcm9kdWN0aW9uIGZyb20gcnVtaW5hbnRzIGRpdmlkZWQgYnkgdG90YWwgcGFzdHVyZSBhcmVhLgogCkkgdGhpbmsgdGhhdCBzaG93aW5nIHRoZSB0b3AgcmlnaHQgZ3JhcGggaW4gdGhlIHJlcG9ydCwgYnV0IG9taXR0aW5nIHRoZSBGT3JtZXIgU292aWV0IFVuaW9uLCB3b3VsZCBiZSB1c2VmdWwuIFRoaXMgZGVtb25zdHJhdGVzIHRoYXQgdGhlIHJhdCBvZiBpbXByb3ZlbWVudCBpbiBtZWF0IGFuZCBkYWlyeSBwcm9kdWN0aW9uL3VuaXQgcGFzdHVyZSBoYXMgYmVlbiBzdGVhZGlseSBpbXByb3ZpbmcsIHBhcnRpY3VsYXJseSBpbiB0aGUgYXJlYXMgd2hlcmUgY29uc3VtcHRpb24gaXMgZ3Jvd2luZyBtb3N0IC0gQXNpYSBhbmQgQWZyaWNhLCB0aG91Z2ggbGVzcyBzbyBpbiB0aGUgQW1lcmljYXMgd2hlcmUgcGFzdHVyZSBleHBhbnNpb24gaXMgYSBwcm9ibGVtLiA=