Introduction

In this lesson, you will learn about how to use the SQL SELECT statement to retrieve rows from a single table.

The Role of SQL

SQL is the standard query language for retrieving data from relational databases. It is supported by virtually all relational databases in the same manner. Queries built for one database generally run without modification against another database. Many vendors provide extensions to SQL for analytics and special data types.

SQL is also often used to process tabular data outside of relational databases, e.g., spreadsheets and data frames. For example, Excel supports PowerQuery which allows SQL statements to be run against Excel worksheets; R and Python have packages for executing SQL queries against data frames.

The first query language based on relational algebra, the foundation of relational databases, was Alpha, developed by E. F. Codd (the creator of the relational model of data storage). After that, ISBL was created, and that language in turn was the basis for SQL. SQL is loosely based on relational algebra, though the operands in SQL do not quite map to relational algebra. One issues is that tables are not, in fact, relations and therefore several useful theorems about the relational algebra do not hold in the SQL counterpart. The reason is that the SQL table model is a bag (multiset), rather than a set. Note that SQL is no longer considered an acronym – although some believe it stands for Structured or Standard Query Language, but that is not true.

The tutorial below, in the form of a narrated slide deck (Slide Deck), summarizes the key points in this section. To download the slide deck, right click on the link and choose Save As or Save Link As – or whatever your browser uses to download a link.

Performing Queries

SQL queries require a connection to the database and a means to execute a query. This can be done through a program or via a query tool for ad hoc queries such as MySQL Workbench or the SQLite Console. Most common is embedded SQL for retrieving data into a programming language for analytics and further processing of the data.

Flow of a Query

The client running a program containing embedded SQL or running an ad hoc query tool sends a SQL query (SELECT) to the database management system (typically running on a remote server). The DBMS interprets the query, formulates a query plan, and then accesses the stored data. The result of the query is returned to the client program as a result set in the form of a table. The client program then processes the data further, stores it locally, visualizes the data, or generates a report containing the data.

Flow of SQL Query
Flow of SQL Query

Client/Server Model

Flow of SQL Query
Flow of SQL Query

While most database management systems are client/server databases, some are not. For example, SQLite and Microsoft Access are serverless, file-based databases where all database processing occurs within the application. MySQL, Oracle, SQL Server, Informix, etc are server-based databases and require a network connection and logging in with a user name and password.

Query Process Flow

  1. Client connects to a specific database on the database server by supplying connection parameters (IP address, username, password)
  2. Client stores connection information in a connection object
  3. Client issues a query by a sending SQL statement to the database server over the network connection using the connection object
  4. Server checks to ensure that connected user has permission to access data and that the SQL statement is syntactically correct
  5. Server optimizes query and formulates a query plan based on least cost for time and memory
  6. Server carries out the query by retrieving the data from the storage devices and packaging the result into a temporary table, the result set
  7. Server sends result set back to the client
  8. Client stores the result set in local memory and processes the data
  9. Client disconnects from the database by closing the connection to the server and releasing all resources

Relational Model

The relational data model is among the most used database structures:

  • physical data storage aspects are hidden
  • data records are logically stored in tables
  • each table contains related entries in rows
  • each row represents a data record
  • columns represents attributes
  • rows are unordered
  • columns are unordered
  • SQL is used to access the data records

Sample Database

The remainder of the lesson uses the AssetDB SQLite database to demonstrate the SQL SELECT statement.

AssetDB ER Diagram
AssetDB ER Diagram

The best way to learn a programming language is to follow along in your own program and to experiment with the statements.

To follow along, follow these steps:

  • download the sample database (AssetDB.db)
  • create your own R Notebook, Python Notebook, or Java program in your favorite IDE; or use SQLite Browser or the SQLite command line tools
  • connect to the database

Once you are connected, add code blocks, calls to the database, or ad hoc SQL, for each of the statements and experiment with them. The key is to type the SQL statements, play with them, and experiment; reading is not enough to learn – you need to actually execute the statements.

The quick tutorial below illustrates the different ways to connect to the SQLite database and issue SQL commands.

Tutorial Goes Here!

Tutorial I

The tutorial below, in the form of a narrated slide deck (Slide Deck: SQL Primer - SELECT), summarizes the basic use of SELECT to retrieve data from a single table. You might find if useful to watch before or after reading the lesson.

Tutorial II

In the tutorial below, Khoury Boston’s Prof. Schedlbauer demonstrates the use of the WHERE clause in a SQL SELECT to filter the rows that are retrieved. In addition, the tutorial covers UNIONs.

Covers: SELECT, WHERE, compound queries, LIKE, BETWEEN, IN, ANY, ALL, UNION

Tutorial III

In this tutorial, Khoury Boston’s Prof. Schedlbauer demonstrates how to aggregate data and perform simple computations directly in SQL. Particular attention is paid to how NULL values are handled during aggregation. The lessons finishes with a look at simple grouping with GROUP BY.

Covers: SELECT, WHERE, COUNT, SUM, AVG, MIN, MAX, NULL, IS NULL

SQL Style Recommendations

This section summarizes common style practices for writing and formatting SQL statements and creating SQL scripts1.

General Recommendations

  1. Use consistent and descriptive identifiers and names
  2. Make judicious use of white space and indentation to make code easier to read; keep indentation consistent.
  3. Store ISO 8601 compliant time and date information, i.e., YYYY-MM-DD HH:MM:SS.SSSSS
  4. As much as possible, use standard SQL functions instead of vendor-specific functions for reasons of portability
  5. Keep code succinct and devoid of redundant SQL, such as unnecessary quoting or parentheses or WHERE clauses that can otherwise be derived
  6. Include comments in SQL code where necessary; use C style opening /* and closing */ where possible, otherwise precede comments with – and finish them with a new line
  7. Be consistent with the use of semi-colon to terminate SQL statements, even when not required
  8. Use AS when introducing aliases despite not being required
  9. Disambiguate column names by prefixing with table name or table alias even when not necessary
  10. Avoid CamelCase for column and table names as it is difficult to scan quickly, but if you choose to use, be consistent
  11. Do not use descriptive prefixes or Hungarian notation such as sp_ or tbl.
  12. Avoid using plurals; instead use the more accepted collective term where possible instead, e.g., “staff” instead of “employees” or “people” instead of “individuals”
  13. Do not use periods or spaces in column or table names as it requires awkward escape mechanisms such as the use of backticks, i.e., name a table “foreign_clients” rather than “foreign.clients”
  14. Do not use reserved keywords for table or column names it is confusing and requires backticks to escape the meaning leading to unnecessary complexity
  15. Never give a table the same name as one of its columns and vice versa.
  16. Avoid, where possible, concatenating two table names together to create the name of a junction table, e.g., name the table “services” rather than “cars_mechanics”
  17. Always use the singular name for column.
  18. Where possible avoid simply using id as the primary identifier for the table, use cid or cust_id instead
  19. As much as possible, use lowercase letters for columns and tables
  20. Use upper case letters for all SQL keywords when writing queries
  21. Use the plural for tables names, e.g., “files” instead of “file”
  22. Stored procedure names must start with a verb and indicate an outcome or action, e.g., “InsertNewFlight”
  23. CamelCase is acceptable for stored procedure names
  24. The keywords in a SQL query should right align
  25. Use parenthesis rather than relying on implied order of precedence of operations

Examples

SELECT f.uid, f.pwd  -- user ID and password
  FROM files AS f
 WHERE f.name = '.bashrc';
/* Updating the file record after writing to the file */
UPDATE file_system
   SET file_modified_date = '2023-01-01 00:00:00.00000',
       file_size = 209732
 WHERE file_name = '.vimrc';

Prefered Query Formalisms

  1. Use of BETWEEN where possible instead of combining multiple statements with AND
  2. Use set membership operators such as IN instead of multiple OR clause.
  3. Where a value needs to be interpreted before leaving the database use the CASE expression; CASE statements can be nested to form more complex logical structures
  4. Avoid the use of UNION clauses and temporary tables where possible. If the schema can be optimized to remove the reliance on these features then it most likely should be

Data Types and Defaults

  1. Whenever possible, do not use vendor-specific data types as these are not portable and may not be available in older versions of the same vendor’s software
  2. Only use REAL or FLOAT types where it is strictly necessary for floating point mathematics; otherwise prefer NUMERIC and DECIMAL at all times due to floating point rounding errors
  3. Specify default values whenever a reasonable value is available
  4. The default value must be the same type as the column, e.g., if a column is declared as DECIMAL do not provide an INTEGER default value
  5. Default values must follow the data type declaration and come before any NOT NULL statement

Conclusion

Files & Resources

All Files for Lesson 70.102

References

None.

Errata

Let us know.

LS0tCnRpdGxlOiAiRGF0YSBSZXRyaWV2YWwgd2l0aCBTUUwgU0VMRUNUIgpwYXJhbXM6CiAgY2F0ZWdvcnk6IDcwCiAgbnVtYmVyOiAxMDIKICB0aW1lOiAzMAogIGxldmVsOiBiZWdpbm5lcgogIHRhZ3M6ICJzcWwsU0VMRUNULEFTLExJTUlULE9SREVSIEJZLERJU1RJTkNUIgogIGRlc2NyaXB0aW9uOiAiRXhwbGFpbnMgaG93IHRvIHJldHJpZXZlIGRhdGEgdXNpbmcgdGhlIFNRTCBTRUxFQ1Qgc3RhdGVtZW50LgogICAgICAgICAgICAgICAgQ292ZXJzIHNlbGVjdGlvbiwgYWdncmVnYXRpb24sIGFsaWFzaW5nLCBsaW1pdHMsIG9yZGVyaW5nLCAKICAgICAgICAgICAgICAgIGRpc3RpbmN0IHJvd3MsIGJ1aWx0LWluIGZ1bmN0aW9ucywgYW5kIGxpdGVyYWxzLiBQcm92aWRlcwogICAgICAgICAgICAgICAgZXhwbGFuYXRpb24gb2Ygb3JkZXIgb2YgZXhlY3V0aW9uLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCi0tLQoKLS0tCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iCi0tLQoKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAoKIyMgSW50cm9kdWN0aW9uCgpJbiB0aGlzIGxlc3NvbiwgeW91IHdpbGwgbGVhcm4gYWJvdXQgaG93IHRvIHVzZSB0aGUgU1FMIFNFTEVDVCBzdGF0ZW1lbnQgdG8gcmV0cmlldmUgcm93cyBmcm9tIGEgc2luZ2xlIHRhYmxlLgoKIyMgVGhlIFJvbGUgb2YgU1FMCgpTUUwgaXMgdGhlIHN0YW5kYXJkIHF1ZXJ5IGxhbmd1YWdlIGZvciByZXRyaWV2aW5nIGRhdGEgZnJvbSByZWxhdGlvbmFsIGRhdGFiYXNlcy4gSXQgaXMgc3VwcG9ydGVkIGJ5IHZpcnR1YWxseSBhbGwgcmVsYXRpb25hbCBkYXRhYmFzZXMgaW4gdGhlIHNhbWUgbWFubmVyLiBRdWVyaWVzIGJ1aWx0IGZvciBvbmUgZGF0YWJhc2UgZ2VuZXJhbGx5IHJ1biB3aXRob3V0IG1vZGlmaWNhdGlvbiBhZ2FpbnN0IGFub3RoZXIgZGF0YWJhc2UuIE1hbnkgdmVuZG9ycyBwcm92aWRlIGV4dGVuc2lvbnMgdG8gU1FMIGZvciBhbmFseXRpY3MgYW5kIHNwZWNpYWwgZGF0YSB0eXBlcy4KClNRTCBpcyBhbHNvIG9mdGVuIHVzZWQgdG8gcHJvY2VzcyB0YWJ1bGFyIGRhdGEgb3V0c2lkZSBvZiByZWxhdGlvbmFsIGRhdGFiYXNlcywgKmUuZy4qLCBzcHJlYWRzaGVldHMgYW5kIGRhdGEgZnJhbWVzLiBGb3IgZXhhbXBsZSwgRXhjZWwgc3VwcG9ydHMgUG93ZXJRdWVyeSB3aGljaCBhbGxvd3MgU1FMIHN0YXRlbWVudHMgdG8gYmUgcnVuIGFnYWluc3QgRXhjZWwgd29ya3NoZWV0czsgUiBhbmQgUHl0aG9uIGhhdmUgcGFja2FnZXMgZm9yIGV4ZWN1dGluZyBTUUwgcXVlcmllcyBhZ2FpbnN0IGRhdGEgZnJhbWVzLgoKVGhlIGZpcnN0IHF1ZXJ5IGxhbmd1YWdlIGJhc2VkIG9uIHJlbGF0aW9uYWwgYWxnZWJyYSwgdGhlIGZvdW5kYXRpb24gb2YgcmVsYXRpb25hbCBkYXRhYmFzZXMsIHdhcyBBbHBoYSwgZGV2ZWxvcGVkIGJ5IEUuIEYuIENvZGQgKHRoZSBjcmVhdG9yIG9mIHRoZSByZWxhdGlvbmFsIG1vZGVsIG9mIGRhdGEgc3RvcmFnZSkuIEFmdGVyIHRoYXQsIElTQkwgd2FzIGNyZWF0ZWQsIGFuZCB0aGF0IGxhbmd1YWdlIGluIHR1cm4gd2FzIHRoZSBiYXNpcyBmb3IgU1FMLiBTUUwgaXMgbG9vc2VseSBiYXNlZCBvbiByZWxhdGlvbmFsIGFsZ2VicmEsIHRob3VnaCB0aGUgb3BlcmFuZHMgaW4gU1FMIGRvIG5vdCBxdWl0ZSBtYXAgdG8gcmVsYXRpb25hbCBhbGdlYnJhLiBPbmUgaXNzdWVzIGlzIHRoYXQgdGFibGVzIGFyZSBub3QsIGluIGZhY3QsIHJlbGF0aW9ucyBhbmQgdGhlcmVmb3JlIHNldmVyYWwgdXNlZnVsIHRoZW9yZW1zIGFib3V0IHRoZSByZWxhdGlvbmFsIGFsZ2VicmEgZG8gbm90IGhvbGQgaW4gdGhlIFNRTCBjb3VudGVycGFydC4gVGhlIHJlYXNvbiBpcyB0aGF0IHRoZSBTUUwgdGFibGUgbW9kZWwgaXMgYSBiYWcgKG11bHRpc2V0KSwgcmF0aGVyIHRoYW4gYSBzZXQuIE5vdGUgdGhhdCBTUUwgaXMgbm8gbG9uZ2VyIGNvbnNpZGVyZWQgYW4gYWNyb255bSAtLSBhbHRob3VnaCBzb21lIGJlbGlldmUgaXQgc3RhbmRzIGZvciBTdHJ1Y3R1cmVkIG9yIFN0YW5kYXJkIFF1ZXJ5IExhbmd1YWdlLCBidXQgdGhhdCBpcyBub3QgdHJ1ZS4KClRoZSB0dXRvcmlhbCBiZWxvdywgaW4gdGhlIGZvcm0gb2YgYSBuYXJyYXRlZCBzbGlkZSBkZWNrIChbU2xpZGUgRGVja10ocy03MC0xMDItc3FsLXNlbGVjdC5wcHR4KSksIHN1bW1hcml6ZXMgdGhlIGtleSBwb2ludHMgaW4gdGhpcyBzZWN0aW9uLiBUbyBkb3dubG9hZCB0aGUgc2xpZGUgZGVjaywgcmlnaHQgY2xpY2sgb24gdGhlIGxpbmsgYW5kIGNob29zZSAqU2F2ZSBBcyogb3IgKlNhdmUgTGluayBBcyogLS0gb3Igd2hhdGV2ZXIgeW91ciBicm93c2VyIHVzZXMgdG8gZG93bmxvYWQgYSBsaW5rLgoKYGBgez1odG1sfQo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9ub3J0aGVhc3Rlcm4uaG9zdGVkLnBhbm9wdG8uY29tL1Bhbm9wdG8vUGFnZXMvRW1iZWQuYXNweD9pZD03Zjc3MjVlZi1iN2NiLTRjNzMtYTU0YS1hYzUyMDE0YTE5NDYmYW1wO2F1dG9wbGF5PWZhbHNlJmFtcDtvZmZlcnZpZXdlcj10cnVlJmFtcDtzaG93dGl0bGU9ZmFsc2UmYW1wO3Nob3dicmFuZD1mYWxzZSZhbXA7c3RhcnQ9MCZhbXA7aW50ZXJhY3Rpdml0eT1hbGwiIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBhbGxvd2Z1bGxzY3JlZW49ImFsbG93ZnVsbHNjcmVlbiIgYWxsb3c9ImF1dG9wbGF5IiBkYXRhLWV4dGVybmFsPSIxIj48L2lmcmFtZT4KYGBgCiMjIFBlcmZvcm1pbmcgUXVlcmllcwoKU1FMIHF1ZXJpZXMgcmVxdWlyZSBhIGNvbm5lY3Rpb24gdG8gdGhlIGRhdGFiYXNlIGFuZCBhIG1lYW5zIHRvIGV4ZWN1dGUgYSBxdWVyeS4gVGhpcyBjYW4gYmUgZG9uZSB0aHJvdWdoIGEgcHJvZ3JhbSBvciB2aWEgYSBxdWVyeSB0b29sIGZvciAqYWQgaG9jKiBxdWVyaWVzIHN1Y2ggYXMgTXlTUUwgV29ya2JlbmNoIG9yIHRoZSBTUUxpdGUgQ29uc29sZS4gTW9zdCBjb21tb24gaXMgZW1iZWRkZWQgU1FMIGZvciByZXRyaWV2aW5nIGRhdGEgaW50byBhIHByb2dyYW1taW5nIGxhbmd1YWdlIGZvciBhbmFseXRpY3MgYW5kIGZ1cnRoZXIgcHJvY2Vzc2luZyBvZiB0aGUgZGF0YS4KCiMjIEZsb3cgb2YgYSBRdWVyeQoKVGhlIGNsaWVudCBydW5uaW5nIGEgcHJvZ3JhbSBjb250YWluaW5nIGVtYmVkZGVkIFNRTCBvciBydW5uaW5nIGFuICphZCBob2MqIHF1ZXJ5IHRvb2wgc2VuZHMgYSBTUUwgcXVlcnkgKFNFTEVDVCkgdG8gdGhlIGRhdGFiYXNlIG1hbmFnZW1lbnQgc3lzdGVtICh0eXBpY2FsbHkgcnVubmluZyBvbiBhIHJlbW90ZSBzZXJ2ZXIpLiBUaGUgREJNUyBpbnRlcnByZXRzIHRoZSBxdWVyeSwgZm9ybXVsYXRlcyBhIHF1ZXJ5IHBsYW4sIGFuZCB0aGVuIGFjY2Vzc2VzIHRoZSBzdG9yZWQgZGF0YS4gVGhlIHJlc3VsdCBvZiB0aGUgcXVlcnkgaXMgcmV0dXJuZWQgdG8gdGhlIGNsaWVudCBwcm9ncmFtIGFzIGEgcmVzdWx0IHNldCBpbiB0aGUgZm9ybSBvZiBhIHRhYmxlLiBUaGUgY2xpZW50IHByb2dyYW0gdGhlbiBwcm9jZXNzZXMgdGhlIGRhdGEgZnVydGhlciwgc3RvcmVzIGl0IGxvY2FsbHksIHZpc3VhbGl6ZXMgdGhlIGRhdGEsIG9yIGdlbmVyYXRlcyBhIHJlcG9ydCBjb250YWluaW5nIHRoZSBkYXRhLgoKIVtGbG93IG9mIFNRTCBRdWVyeV0oaW1hZ2VzL2Zsb3ctb2Ytc3FsLXF1ZXJ5LWNsaWVudC1zZXJ2ZXIuanBnKXt3aWR0aD0iNTAlIn0KCiMjIENsaWVudC9TZXJ2ZXIgTW9kZWwKCiFbRmxvdyBvZiBTUUwgUXVlcnldKGltYWdlcy9jbGllbnQtc2VydmVyLW1vZGVsLWZhdC12cy10aGluLWNsaWVudC5qcGcpe3dpZHRoPSI1MCUifQoKV2hpbGUgbW9zdCBkYXRhYmFzZSBtYW5hZ2VtZW50IHN5c3RlbXMgYXJlIGNsaWVudC9zZXJ2ZXIgZGF0YWJhc2VzLCBzb21lIGFyZSBub3QuIEZvciBleGFtcGxlLCBTUUxpdGUgYW5kIE1pY3Jvc29mdCBBY2Nlc3MgYXJlIHNlcnZlcmxlc3MsIGZpbGUtYmFzZWQgZGF0YWJhc2VzIHdoZXJlIGFsbCBkYXRhYmFzZSBwcm9jZXNzaW5nIG9jY3VycyB3aXRoaW4gdGhlIGFwcGxpY2F0aW9uLiBNeVNRTCwgT3JhY2xlLCBTUUwgU2VydmVyLCBJbmZvcm1peCwgKmV0YyogYXJlIHNlcnZlci1iYXNlZCBkYXRhYmFzZXMgYW5kIHJlcXVpcmUgYSBuZXR3b3JrIGNvbm5lY3Rpb24gYW5kIGxvZ2dpbmcgaW4gd2l0aCBhIHVzZXIgbmFtZSBhbmQgcGFzc3dvcmQuCgojIyMgUXVlcnkgUHJvY2VzcyBGbG93CgoxLiAgQ2xpZW50IGNvbm5lY3RzIHRvIGEgc3BlY2lmaWMgZGF0YWJhc2Ugb24gdGhlIGRhdGFiYXNlIHNlcnZlciBieSBzdXBwbHlpbmcgY29ubmVjdGlvbiBwYXJhbWV0ZXJzIChJUCBhZGRyZXNzLCB1c2VybmFtZSwgcGFzc3dvcmQpCjIuICBDbGllbnQgc3RvcmVzIGNvbm5lY3Rpb24gaW5mb3JtYXRpb24gaW4gYSBjb25uZWN0aW9uIG9iamVjdAozLiAgQ2xpZW50IGlzc3VlcyBhIHF1ZXJ5IGJ5IGEgc2VuZGluZyBTUUwgc3RhdGVtZW50IHRvIHRoZSBkYXRhYmFzZSBzZXJ2ZXIgb3ZlciB0aGUgbmV0d29yayBjb25uZWN0aW9uIHVzaW5nIHRoZSBjb25uZWN0aW9uIG9iamVjdAo0LiAgU2VydmVyIGNoZWNrcyB0byBlbnN1cmUgdGhhdCBjb25uZWN0ZWQgdXNlciBoYXMgcGVybWlzc2lvbiB0byBhY2Nlc3MgZGF0YSBhbmQgdGhhdCB0aGUgU1FMIHN0YXRlbWVudCBpcyBzeW50YWN0aWNhbGx5IGNvcnJlY3QKNS4gIFNlcnZlciBvcHRpbWl6ZXMgcXVlcnkgYW5kIGZvcm11bGF0ZXMgYSBxdWVyeSBwbGFuIGJhc2VkIG9uIGxlYXN0IGNvc3QgZm9yIHRpbWUgYW5kIG1lbW9yeQo2LiAgU2VydmVyIGNhcnJpZXMgb3V0IHRoZSBxdWVyeSBieSByZXRyaWV2aW5nIHRoZSBkYXRhIGZyb20gdGhlIHN0b3JhZ2UgZGV2aWNlcyBhbmQgcGFja2FnaW5nIHRoZSByZXN1bHQgaW50byBhIHRlbXBvcmFyeSB0YWJsZSwgdGhlIHJlc3VsdCBzZXQKNy4gIFNlcnZlciBzZW5kcyByZXN1bHQgc2V0IGJhY2sgdG8gdGhlIGNsaWVudAo4LiAgQ2xpZW50IHN0b3JlcyB0aGUgcmVzdWx0IHNldCBpbiBsb2NhbCBtZW1vcnkgYW5kIHByb2Nlc3NlcyB0aGUgZGF0YQo5LiAgQ2xpZW50IGRpc2Nvbm5lY3RzIGZyb20gdGhlIGRhdGFiYXNlIGJ5IGNsb3NpbmcgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIHNlcnZlciBhbmQgcmVsZWFzaW5nIGFsbCByZXNvdXJjZXMKCiMjIFJlbGF0aW9uYWwgTW9kZWwKClRoZSByZWxhdGlvbmFsIGRhdGEgbW9kZWwgaXMgYW1vbmcgdGhlIG1vc3QgdXNlZCBkYXRhYmFzZSBzdHJ1Y3R1cmVzOgoKLSAgIHBoeXNpY2FsIGRhdGEgc3RvcmFnZSBhc3BlY3RzIGFyZSBoaWRkZW4KLSAgIGRhdGEgcmVjb3JkcyBhcmUgbG9naWNhbGx5IHN0b3JlZCBpbiB0YWJsZXMKLSAgIGVhY2ggdGFibGUgY29udGFpbnMgcmVsYXRlZCBlbnRyaWVzIGluIHJvd3MKLSAgIGVhY2ggcm93IHJlcHJlc2VudHMgYSBkYXRhIHJlY29yZAotICAgY29sdW1ucyByZXByZXNlbnRzIGF0dHJpYnV0ZXMKLSAgIHJvd3MgYXJlIHVub3JkZXJlZAotICAgY29sdW1ucyBhcmUgdW5vcmRlcmVkCi0gICBTUUwgaXMgdXNlZCB0byBhY2Nlc3MgdGhlIGRhdGEgcmVjb3JkcwoKIyMgU2FtcGxlIERhdGFiYXNlCgpUaGUgcmVtYWluZGVyIG9mIHRoZSBsZXNzb24gdXNlcyB0aGUgKkFzc2V0REIqIFNRTGl0ZSBkYXRhYmFzZSB0byBkZW1vbnN0cmF0ZSB0aGUgU1FMIFNFTEVDVCBzdGF0ZW1lbnQuCgohW0Fzc2V0REIgRVIgRGlhZ3JhbV0oaW1hZ2VzL2Fzc2V0ZGItZXJkLmpwZyl7d2lkdGg9IjcwJSJ9CgpUaGUgYmVzdCB3YXkgdG8gbGVhcm4gYSBwcm9ncmFtbWluZyBsYW5ndWFnZSBpcyB0byBmb2xsb3cgYWxvbmcgaW4geW91ciBvd24gcHJvZ3JhbSBhbmQgdG8gZXhwZXJpbWVudCB3aXRoIHRoZSBzdGF0ZW1lbnRzLgoKVG8gZm9sbG93IGFsb25nLCBmb2xsb3cgdGhlc2Ugc3RlcHM6CgotICAgZG93bmxvYWQgdGhlIHNhbXBsZSBkYXRhYmFzZSAoW0Fzc2V0REIuZGJdKEFzc2V0REIuZGIpKQotICAgY3JlYXRlIHlvdXIgb3duIFIgTm90ZWJvb2ssIFB5dGhvbiBOb3RlYm9vaywgb3IgSmF2YSBwcm9ncmFtIGluIHlvdXIgZmF2b3JpdGUgSURFOyBvciB1c2UgW1NRTGl0ZSBCcm93c2VyXShodHRwczovL3NxbGl0ZWJyb3dzZXIub3JnL2RsLykgb3IgdGhlIFNRTGl0ZSBjb21tYW5kIGxpbmUgdG9vbHMKLSAgIGNvbm5lY3QgdG8gdGhlIGRhdGFiYXNlCgpPbmNlIHlvdSBhcmUgY29ubmVjdGVkLCBhZGQgY29kZSBibG9ja3MsIGNhbGxzIHRvIHRoZSBkYXRhYmFzZSwgb3IgKmFkIGhvYyogU1FMLCBmb3IgZWFjaCBvZiB0aGUgc3RhdGVtZW50cyBhbmQgZXhwZXJpbWVudCB3aXRoIHRoZW0uIFRoZSBrZXkgaXMgdG8gdHlwZSB0aGUgU1FMIHN0YXRlbWVudHMsIHBsYXkgd2l0aCB0aGVtLCBhbmQgZXhwZXJpbWVudDsgcmVhZGluZyBpcyBub3QgZW5vdWdoIHRvIGxlYXJuIC0tIHlvdSBuZWVkIHRvIGFjdHVhbGx5IGV4ZWN1dGUgdGhlIHN0YXRlbWVudHMuCgpUaGUgcXVpY2sgdHV0b3JpYWwgYmVsb3cgaWxsdXN0cmF0ZXMgdGhlIGRpZmZlcmVudCB3YXlzIHRvIGNvbm5lY3QgdG8gdGhlIFNRTGl0ZSBkYXRhYmFzZSBhbmQgaXNzdWUgU1FMIGNvbW1hbmRzLgoKPiBUdXRvcmlhbCBHb2VzIEhlcmUhCgojIyBUdXRvcmlhbCBJCgpUaGUgdHV0b3JpYWwgYmVsb3csIGluIHRoZSBmb3JtIG9mIGEgbmFycmF0ZWQgc2xpZGUgZGVjayAoW1NsaWRlIERlY2s6IFNRTCBQcmltZXIgLSBTRUxFQ1RdKHMtNzAtMTAyLXNxbC1zZWxlY3QucHB0eCkpLCBzdW1tYXJpemVzIHRoZSBiYXNpYyB1c2Ugb2YgU0VMRUNUIHRvIHJldHJpZXZlIGRhdGEgZnJvbSBhIHNpbmdsZSB0YWJsZS4gWW91IG1pZ2h0IGZpbmQgaWYgdXNlZnVsIHRvIHdhdGNoIGJlZm9yZSBvciBhZnRlciByZWFkaW5nIHRoZSBsZXNzb24uCgpgYGB7PWh0bWx9CjxpZnJhbWUgc3JjPSJodHRwczovL25vcnRoZWFzdGVybi5ob3N0ZWQucGFub3B0by5jb20vUGFub3B0by9QYWdlcy9FbWJlZC5hc3B4P2lkPWI0M2Y3OTM4LWYwZDUtNGU4Ny1iZDg2LWFjNTQwMDI5MmJmZCZhbXA7YXV0b3BsYXk9ZmFsc2UmYW1wO29mZmVydmlld2VyPXRydWUmYW1wO3Nob3d0aXRsZT1mYWxzZSZhbXA7c2hvd2JyYW5kPWZhbHNlJmFtcDtzdGFydD0wJmFtcDtpbnRlcmFjdGl2aXR5PWFsbCIgd2lkdGg9IjQ4MCIgaGVpZ2h0PSIyNzAiIGFsbG93ZnVsbHNjcmVlbj0iYWxsb3dmdWxsc2NyZWVuIiBhbGxvdz0iYXV0b3BsYXkiIGRhdGEtZXh0ZXJuYWw9IjEiPjwvaWZyYW1lPgpgYGAKIyMgVHV0b3JpYWwgSUkKCkluIHRoZSB0dXRvcmlhbCBiZWxvdywgS2hvdXJ5IEJvc3RvbidzIFByb2YuIFNjaGVkbGJhdWVyIGRlbW9uc3RyYXRlcyB0aGUgdXNlIG9mIHRoZSBXSEVSRSBjbGF1c2UgaW4gYSBTUUwgU0VMRUNUIHRvIGZpbHRlciB0aGUgcm93cyB0aGF0IGFyZSByZXRyaWV2ZWQuIEluIGFkZGl0aW9uLCB0aGUgdHV0b3JpYWwgY292ZXJzIFVOSU9Ocy4KCjxpZnJhbWUgc3R5bGU9ImJvcmRlcjogMXB4IHNvbGlkICM0NjQ2NDY7IiBzcmM9Imh0dHBzOi8vbm9ydGhlYXN0ZXJuLmhvc3RlZC5wYW5vcHRvLmNvbS9QYW5vcHRvL1BhZ2VzL0VtYmVkLmFzcHg/aWQ9ZTA2NDc0NWMtNzFhNy00M2QwLThjMDktYWNjZDAxN2FkMjJkJmFtcDthdXRvcGxheT1mYWxzZSZhbXA7b2ZmZXJ2aWV3ZXI9dHJ1ZSZhbXA7c2hvd3RpdGxlPWZhbHNlJmFtcDtzaG93YnJhbmQ9ZmFsc2UmYW1wO3N0YXJ0PTAmYW1wO2ludGVyYWN0aXZpdHk9YWxsIiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjI3MCIgYWxsb3dmdWxsc2NyZWVuPSJhbGxvd2Z1bGxzY3JlZW4iIGFsbG93PSJhdXRvcGxheSIgZGF0YS1leHRlcm5hbD0iMSI+Cgo8L2lmcmFtZT4KCioqQ292ZXJzKio6IFNFTEVDVCwgV0hFUkUsIGNvbXBvdW5kIHF1ZXJpZXMsIExJS0UsIEJFVFdFRU4sIElOLCBBTlksIEFMTCwgVU5JT04KCiMjIFR1dG9yaWFsIElJSQoKSW4gdGhpcyB0dXRvcmlhbCwgS2hvdXJ5IEJvc3RvbidzIFByb2YuIFNjaGVkbGJhdWVyIGRlbW9uc3RyYXRlcyBob3cgdG8gYWdncmVnYXRlIGRhdGEgYW5kIHBlcmZvcm0gc2ltcGxlIGNvbXB1dGF0aW9ucyBkaXJlY3RseSBpbiBTUUwuIFBhcnRpY3VsYXIgYXR0ZW50aW9uIGlzIHBhaWQgdG8gaG93IE5VTEwgdmFsdWVzIGFyZSBoYW5kbGVkIGR1cmluZyBhZ2dyZWdhdGlvbi4gVGhlIGxlc3NvbnMgZmluaXNoZXMgd2l0aCBhIGxvb2sgYXQgc2ltcGxlIGdyb3VwaW5nIHdpdGggR1JPVVAgQlkuCgo8aWZyYW1lIHN0eWxlPSJib3JkZXI6IDFweCBzb2xpZCAjNDY0NjQ2OyIgc3JjPSJodHRwczovL25vcnRoZWFzdGVybi5ob3N0ZWQucGFub3B0by5jb20vUGFub3B0by9QYWdlcy9FbWJlZC5hc3B4P2lkPTlkZDVjN2EwLTY0YWEtNGE2Ni1iODg0LWFjOTkwMGVjNmQ2ZSZhbXA7YXV0b3BsYXk9ZmFsc2UmYW1wO29mZmVydmlld2VyPXRydWUmYW1wO3Nob3d0aXRsZT1mYWxzZSZhbXA7c2hvd2JyYW5kPWZhbHNlJmFtcDtzdGFydD0wJmFtcDtpbnRlcmFjdGl2aXR5PWFsbCIgd2lkdGg9IjQ4MCIgaGVpZ2h0PSIyNzAiIGFsbG93ZnVsbHNjcmVlbj0iYWxsb3dmdWxsc2NyZWVuIiBhbGxvdz0iYXV0b3BsYXkiIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgoqKkNvdmVycyoqOiBTRUxFQ1QsIFdIRVJFLCBDT1VOVCwgU1VNLCBBVkcsIE1JTiwgTUFYLCBOVUxMLCBJUyBOVUxMCgojIyBTUUwgU3R5bGUgUmVjb21tZW5kYXRpb25zCgpUaGlzIHNlY3Rpb24gc3VtbWFyaXplcyBjb21tb24gc3R5bGUgcHJhY3RpY2VzIGZvciB3cml0aW5nIGFuZCBmb3JtYXR0aW5nIFNRTCBzdGF0ZW1lbnRzIGFuZCBjcmVhdGluZyBTUUwgc2NyaXB0c1teMV0uCgpbXjFdOiBQb3J0aW9ucyBkZXJpdmVkIGZyb20gU1FMIFN0eWxlIEd1aWRlIDxodHRwczovL3d3dy5zcWxzdHlsZS5ndWlkZS8+LiBieSBbU2ltb24gSG9seXdlbGxdKDxodHRwczovL3d3dy5zaW1vbmhvbHl3ZWxsLmNvbS8/dXRtX3NvdXJjZT1zcWxzdHlsZS5ndWlkZSZ1dG1fbWVkaXVtPWxpbmsmdXRtX2NhbXBhaWduPW1kLWRvY3VtZW50Pi4gd2hpY2ggaXMgbGljZW5zZWQgdW5kZXIgYSBbQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2VdKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS80LjAvKS4KCiMjIyBHZW5lcmFsIFJlY29tbWVuZGF0aW9ucwoKMS4gIFVzZSBjb25zaXN0ZW50IGFuZCBkZXNjcmlwdGl2ZSBpZGVudGlmaWVycyBhbmQgbmFtZXMKMi4gIE1ha2UganVkaWNpb3VzIHVzZSBvZiB3aGl0ZSBzcGFjZSBhbmQgaW5kZW50YXRpb24gdG8gbWFrZSBjb2RlIGVhc2llciB0byByZWFkOyBrZWVwIGluZGVudGF0aW9uIGNvbnNpc3RlbnQuCjMuICBTdG9yZSBbSVNPIDg2MDFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT184NjAxKSBjb21wbGlhbnQgdGltZSBhbmQgZGF0ZSBpbmZvcm1hdGlvbiwgKmkuZS4qLCBZWVlZLU1NLUREIEhIOk1NOlNTLlNTU1NTCjQuICBBcyBtdWNoIGFzIHBvc3NpYmxlLCB1c2Ugc3RhbmRhcmQgU1FMIGZ1bmN0aW9ucyBpbnN0ZWFkIG9mIHZlbmRvci1zcGVjaWZpYyBmdW5jdGlvbnMgZm9yIHJlYXNvbnMgb2YgcG9ydGFiaWxpdHkKNS4gIEtlZXAgY29kZSBzdWNjaW5jdCBhbmQgZGV2b2lkIG9mIHJlZHVuZGFudCBTUUwsIHN1Y2ggYXMgdW5uZWNlc3NhcnkgcXVvdGluZyBvciBwYXJlbnRoZXNlcyBvciBXSEVSRSBjbGF1c2VzIHRoYXQgY2FuIG90aGVyd2lzZSBiZSBkZXJpdmVkCjYuICBJbmNsdWRlIGNvbW1lbnRzIGluIFNRTCBjb2RlIHdoZXJlIG5lY2Vzc2FyeTsgdXNlIEMgc3R5bGUgb3BlbmluZyAvXCogYW5kIGNsb3NpbmcgXCovIHdoZXJlIHBvc3NpYmxlLCBvdGhlcndpc2UgcHJlY2VkZSBjb21tZW50cyB3aXRoIC0tIGFuZCBmaW5pc2ggdGhlbSB3aXRoIGEgbmV3IGxpbmUKNy4gIEJlIGNvbnNpc3RlbnQgd2l0aCB0aGUgdXNlIG9mIHNlbWktY29sb24gdG8gdGVybWluYXRlIFNRTCBzdGF0ZW1lbnRzLCBldmVuIHdoZW4gbm90IHJlcXVpcmVkCjguICBVc2UgKkFTKiB3aGVuIGludHJvZHVjaW5nIGFsaWFzZXMgZGVzcGl0ZSBub3QgYmVpbmcgcmVxdWlyZWQKOS4gIERpc2FtYmlndWF0ZSBjb2x1bW4gbmFtZXMgYnkgcHJlZml4aW5nIHdpdGggdGFibGUgbmFtZSBvciB0YWJsZSBhbGlhcyBldmVuIHdoZW4gbm90IG5lY2Vzc2FyeQoxMC4gQXZvaWQgQ2FtZWxDYXNlIGZvciBjb2x1bW4gYW5kIHRhYmxlIG5hbWVzIGFzIGl0IGlzIGRpZmZpY3VsdCB0byBzY2FuIHF1aWNrbHksIGJ1dCBpZiB5b3UgY2hvb3NlIHRvIHVzZSwgYmUgY29uc2lzdGVudAoxMS4gRG8gbm90IHVzZSBkZXNjcmlwdGl2ZSBwcmVmaXhlcyBvciBIdW5nYXJpYW4gbm90YXRpb24gc3VjaCBhcyAqc3BcXyogb3IgKnRibCouCjEyLiBBdm9pZCB1c2luZyBwbHVyYWxzOyBpbnN0ZWFkIHVzZSB0aGUgbW9yZSBhY2NlcHRlZCBjb2xsZWN0aXZlIHRlcm0gd2hlcmUgcG9zc2libGUgaW5zdGVhZCwgKmUuZy4qLCAic3RhZmYiIGluc3RlYWQgb2YgImVtcGxveWVlcyIgb3IgInBlb3BsZSIgaW5zdGVhZCBvZiAiaW5kaXZpZHVhbHMiCjEzLiBEbyBub3QgdXNlIHBlcmlvZHMgb3Igc3BhY2VzIGluIGNvbHVtbiBvciB0YWJsZSBuYW1lcyBhcyBpdCByZXF1aXJlcyBhd2t3YXJkIGVzY2FwZSBtZWNoYW5pc21zIHN1Y2ggYXMgdGhlIHVzZSBvZiBiYWNrdGlja3MsICppLmUuKiwgbmFtZSBhIHRhYmxlICJmb3JlaWduX2NsaWVudHMiIHJhdGhlciB0aGFuICJmb3JlaWduLmNsaWVudHMiCjE0LiBEbyBub3QgdXNlIHJlc2VydmVkIGtleXdvcmRzIGZvciB0YWJsZSBvciBjb2x1bW4gbmFtZXMgaXQgaXMgY29uZnVzaW5nIGFuZCByZXF1aXJlcyBiYWNrdGlja3MgdG8gZXNjYXBlIHRoZSBtZWFuaW5nIGxlYWRpbmcgdG8gdW5uZWNlc3NhcnkgY29tcGxleGl0eQoxNS4gTmV2ZXIgZ2l2ZSBhIHRhYmxlIHRoZSBzYW1lIG5hbWUgYXMgb25lIG9mIGl0cyBjb2x1bW5zIGFuZCAqdmljZSB2ZXJzYSouCjE2LiBBdm9pZCwgd2hlcmUgcG9zc2libGUsIGNvbmNhdGVuYXRpbmcgdHdvIHRhYmxlIG5hbWVzIHRvZ2V0aGVyIHRvIGNyZWF0ZSB0aGUgbmFtZSBvZiBhIGp1bmN0aW9uIHRhYmxlLCAqZS5nLiosIG5hbWUgdGhlIHRhYmxlICJzZXJ2aWNlcyIgcmF0aGVyIHRoYW4gImNhcnNfbWVjaGFuaWNzIgoxNy4gQWx3YXlzIHVzZSB0aGUgc2luZ3VsYXIgbmFtZSBmb3IgY29sdW1uLgoxOC4gV2hlcmUgcG9zc2libGUgYXZvaWQgc2ltcGx5IHVzaW5nICppZCogYXMgdGhlIHByaW1hcnkgaWRlbnRpZmllciBmb3IgdGhlIHRhYmxlLCB1c2UgKmNpZCogb3IgKmN1c3RfaWQqIGluc3RlYWQKMTkuIEFzIG11Y2ggYXMgcG9zc2libGUsIHVzZSBsb3dlcmNhc2UgbGV0dGVycyBmb3IgY29sdW1ucyBhbmQgdGFibGVzCjIwLiBVc2UgdXBwZXIgY2FzZSBsZXR0ZXJzIGZvciBhbGwgU1FMIGtleXdvcmRzIHdoZW4gd3JpdGluZyBxdWVyaWVzCjIxLiBVc2UgdGhlIHBsdXJhbCBmb3IgdGFibGVzIG5hbWVzLCAqZS5nLiosICJmaWxlcyIgaW5zdGVhZCBvZiAiZmlsZSIKMjIuIFN0b3JlZCBwcm9jZWR1cmUgbmFtZXMgbXVzdCBzdGFydCB3aXRoIGEgdmVyYiBhbmQgaW5kaWNhdGUgYW4gb3V0Y29tZSBvciBhY3Rpb24sICplLmcuKiwgIkluc2VydE5ld0ZsaWdodCIKMjMuIENhbWVsQ2FzZSBpcyBhY2NlcHRhYmxlIGZvciBzdG9yZWQgcHJvY2VkdXJlIG5hbWVzCjI0LiBUaGUga2V5d29yZHMgaW4gYSBTUUwgcXVlcnkgc2hvdWxkIHJpZ2h0IGFsaWduCjI1LiBVc2UgcGFyZW50aGVzaXMgcmF0aGVyIHRoYW4gcmVseWluZyBvbiBpbXBsaWVkIG9yZGVyIG9mIHByZWNlZGVuY2Ugb2Ygb3BlcmF0aW9ucwoKIyMjIEV4YW1wbGVzCgpgYGAgc3FsClNFTEVDVCBmLnVpZCwgZi5wd2QgIC0tIHVzZXIgSUQgYW5kIHBhc3N3b3JkCiAgRlJPTSBmaWxlcyBBUyBmCiBXSEVSRSBmLm5hbWUgPSAnLmJhc2hyYyc7CmBgYAoKYGBgIHNxbAovKiBVcGRhdGluZyB0aGUgZmlsZSByZWNvcmQgYWZ0ZXIgd3JpdGluZyB0byB0aGUgZmlsZSAqLwpVUERBVEUgZmlsZV9zeXN0ZW0KICAgU0VUIGZpbGVfbW9kaWZpZWRfZGF0ZSA9ICcyMDIzLTAxLTAxIDAwOjAwOjAwLjAwMDAwJywKICAgICAgIGZpbGVfc2l6ZSA9IDIwOTczMgogV0hFUkUgZmlsZV9uYW1lID0gJy52aW1yYyc7CmBgYAoKIyMjIFByZWZlcmVkIFF1ZXJ5IEZvcm1hbGlzbXMKCjEuICBVc2Ugb2YgYEJFVFdFRU5gIHdoZXJlIHBvc3NpYmxlIGluc3RlYWQgb2YgY29tYmluaW5nIG11bHRpcGxlIHN0YXRlbWVudHMgd2l0aCBgQU5EYAoyLiAgVXNlIHNldCBtZW1iZXJzaGlwIG9wZXJhdG9ycyBzdWNoIGFzIGBJTmAgaW5zdGVhZCBvZiBtdWx0aXBsZSBgT1JgIGNsYXVzZS4KMy4gIFdoZXJlIGEgdmFsdWUgbmVlZHMgdG8gYmUgaW50ZXJwcmV0ZWQgYmVmb3JlIGxlYXZpbmcgdGhlIGRhdGFiYXNlIHVzZSB0aGUgYENBU0VgIGV4cHJlc3Npb247IGBDQVNFYCBzdGF0ZW1lbnRzIGNhbiBiZSBuZXN0ZWQgdG8gZm9ybSBtb3JlIGNvbXBsZXggbG9naWNhbCBzdHJ1Y3R1cmVzCjQuICBBdm9pZCB0aGUgdXNlIG9mIGBVTklPTmAgY2xhdXNlcyBhbmQgdGVtcG9yYXJ5IHRhYmxlcyB3aGVyZSBwb3NzaWJsZS4gSWYgdGhlIHNjaGVtYSBjYW4gYmUgb3B0aW1pemVkIHRvIHJlbW92ZSB0aGUgcmVsaWFuY2Ugb24gdGhlc2UgZmVhdHVyZXMgdGhlbiBpdCBtb3N0IGxpa2VseSBzaG91bGQgYmUKCiMjIyBEYXRhIFR5cGVzIGFuZCBEZWZhdWx0cwoKMS4gIFdoZW5ldmVyIHBvc3NpYmxlLCBkbyBub3QgdXNlIHZlbmRvci1zcGVjaWZpYyBkYXRhIHR5cGVzIGFzIHRoZXNlIGFyZSBub3QgcG9ydGFibGUgYW5kIG1heSBub3QgYmUgYXZhaWxhYmxlIGluIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBzYW1lIHZlbmRvcidzIHNvZnR3YXJlCjIuICBPbmx5IHVzZSAqUkVBTCogb3IgKkZMT0FUKiB0eXBlcyB3aGVyZSBpdCBpcyBzdHJpY3RseSBuZWNlc3NhcnkgZm9yIGZsb2F0aW5nIHBvaW50IG1hdGhlbWF0aWNzOyBvdGhlcndpc2UgcHJlZmVyICpOVU1FUklDKiBhbmQgKkRFQ0lNQUwqIGF0IGFsbCB0aW1lcyBkdWUgdG8gZmxvYXRpbmcgcG9pbnQgcm91bmRpbmcgZXJyb3JzCjMuICBTcGVjaWZ5IGRlZmF1bHQgdmFsdWVzIHdoZW5ldmVyIGEgcmVhc29uYWJsZSB2YWx1ZSBpcyBhdmFpbGFibGUKNC4gIFRoZSBkZWZhdWx0IHZhbHVlIG11c3QgYmUgdGhlIHNhbWUgdHlwZSBhcyB0aGUgY29sdW1uLCAqZS5nLiosIGlmIGEgY29sdW1uIGlzIGRlY2xhcmVkIGFzICpERUNJTUFMKiBkbyBub3QgcHJvdmlkZSBhbiAqSU5URUdFUiogZGVmYXVsdCB2YWx1ZQo1LiAgRGVmYXVsdCB2YWx1ZXMgbXVzdCBmb2xsb3cgdGhlIGRhdGEgdHlwZSBkZWNsYXJhdGlvbiBhbmQgY29tZSBiZWZvcmUgYW55IGBOT1QgTlVMTGAgc3RhdGVtZW50CgojIyBDb25jbHVzaW9uCgojIyBTZWUgQWxzbwoKLSAgIFs3MC44MDEgVGhlIFNRTGl0ZSBEYXRhYmFzZV0oaHR0cDovL2FydGlmaWNpdW0udXMvbGVzc29ucy83MC5zcWwvbC03MC04MDEtaW50cm8tc3FsaXRlL2wtNzAtODAxLmh0bWwpCi0gICBbNi4zMDEgV29ya2luZyB3aXRoIERhdGFiYXNlcyBpbiBSXShodHRwOi8vYXJ0aWZpY2l1bS51cy9sZXNzb25zLzA2LnIvbC02LTMwMS1zcWxpdGUtZnJvbS1yL2wtNi0zMDEuaHRtbCkKLSAgIFs5LjYwMiBXb3JraW5nIHdpdGggRGF0YWJhc2VzIGluIEphdmFdKGh0dHA6Ly9hcnRpZmljaXVtLnVzL2xlc3NvbnMvMDkuamF2YS9sLTktNjAyLXNxbGl0ZS1mcm9tLWphdmEvbC05LTYwMi5odG1sKQoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBGaWxlcyAmIFJlc291cmNlcwoKYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9CnppcE5hbWUgPSBzcHJpbnRmKCJMZXNzb25GaWxlcy0lcy0lcy56aXAiLCAKICAgICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikKCnRleHRBTGluayA9IHBhc3RlMCgiQWxsIEZpbGVzIGZvciBMZXNzb24gIiwgCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikKCiMgZG93bmxvYWRGaWxlc0xpbmsoKSBpcyBpbmNsdWRlZCBmcm9tIF9pbnNlcnQyREIuUgprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgUmVmZXJlbmNlcwoKTm9uZS4KCiMjIEVycmF0YQoKW0xldCB1cyBrbm93XShodHRwczovL2Zvcm0uam90Zm9ybS5jb20vMjEyMTg3MDcyNzg0MTU3KXt0YXJnZXQ9Il9ibGFuayJ9Lgo=