//********************************************************
//
// Assignment 7 - Structures and Strings
//
// Name: Rose Samedi
//
// Class: C Programming, Fall 2025
//
// Date: 11/16/2025
//
// Description: Program which determines overtime and
// gross pay for a set of employees with outputs sent
// to standard output (the screen).
//
// This assignment also adds the employee name, their tax state,
// and calculates the state tax, federal tax, and net pay. It
// also calculates totals, averages, minimum, and maximum values.
//
// Call by Reference design
//
//********************************************************
// necessary header files
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// define constants
#define SIZE 5
#define STD_HOURS 40.0
#define OT_RATE 1.5
#define MA_TAX_RATE 0.05
#define NH_TAX_RATE 0.0
#define VT_TAX_RATE 0.06
#define CA_TAX_RATE 0.07
#define DEFAULT_TAX_RATE 0.08
#define NAME_SIZE 20
#define TAX_STATE_SIZE 3
#define FED_TAX_RATE 0.25
#define FIRST_NAME_SIZE 10
#define LAST_NAME_SIZE 10
// Define a structure type to store an employee name
struct name
{
char firstName[FIRST_NAME_SIZE];
char lastName [LAST_NAME_SIZE];
};
// Define a structure type to pass employee data between functions
struct employee
{
struct name empName;
char taxState [TAX_STATE_SIZE];
long int clockNumber;
float wageRate;
float hours;
float overtimeHrs;
float grossPay;
float stateTax;
float fedTax;
float netPay;
};
// this structure type defines the totals of all floating point items
// so they can be totaled and used also to calculate averages
struct totals
{
float total_wageRate;
float total_hours;
float total_overtimeHrs;
float total_grossPay;
float total_stateTax;
float total_fedTax;
float total_netPay;
};
// Function prototypes
void calculatePay(struct employee *emp);
void calculateTaxes(struct employee *emp);
void updateTotals(struct totals *tots, const struct employee *emp);
void findMinMax(const struct employee emps[], int size, struct employee *minGrossPayEmp, struct employee *maxGrossPayEmp);
void displayOutput(const struct employee emps[], int size, const struct totals *tots, const struct employee *minGrossPayEmp, const struct employee *maxGrossPayEmp);
void convertToUpper(char *str);
int main(void)
{
// Initialize employee data for SIZE employees
struct employee employees[SIZE] = {
{{"Pat", "Curry"}, "MA", 980124L, 10.60, 51.5, 0.0, 0.0, 0.0, 0.0, 0.0},
{{"Leo", "Demers"}, "NH", 980221L, 10.60, 40.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{{"Kim", "Wong"}, "VT", 980345L, 10.60, 41.2, 0.0, 0.0, 0.0, 0.0, 0.0},
{{"Jack", "Gourdeau"}, "MA", 980400L, 10.60, 60.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{{"Phil", "Lacourse"}, "CA", 980512L, 10.60, 38.5, 0.0, 0.0, 0.0, 0.0, 0.0}
};
struct totals allTotals = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
struct employee minGrossPayEmp;
struct employee maxGrossPayEmp;
int i;
// Process each employee
for (i = 0; i < SIZE; i++)
{
calculatePay(&employees[i]);
calculateTaxes(&employees[i]);
updateTotals(&allTotals, &employees[i]);
}
// Find min/max after all calculations are done
findMinMax(employees, SIZE, &minGrossPayEmp, &maxGrossPayEmp);
// Display the results
displayOutput(employees, SIZE, &allTotals, &minGrossPayEmp, &maxGrossPayEmp);
return 0;
}
// Function to calculate overtime hours and gross pay for a single employee
void calculatePay(struct employee *emp)
{
if (emp->hours > STD_HOURS)
{
emp->overtimeHrs = emp->hours - STD_HOURS;
emp->grossPay = (STD_HOURS * emp->wageRate) + (emp->overtimeHrs * emp->wageRate * OT_RATE);
}
else
{
emp->overtimeHrs = 0.0;
emp->grossPay = emp->hours * emp->wageRate;
}
}
// Function to calculate state tax, federal tax, and net pay for a single employee
void calculateTaxes(struct employee *emp)
{
float stateTaxRate;
// Convert state code to uppercase for consistent comparison
convertToUpper(emp->taxState);
if (strcmp(emp
->taxState
, "MA") == 0) {
stateTaxRate = MA_TAX_RATE;
}
else if (strcmp(emp
->taxState
, "NH") == 0) {
stateTaxRate = NH_TAX_RATE;
}
else if (strcmp(emp
->taxState
, "VT") == 0) {
stateTaxRate = VT_TAX_RATE;
}
else if (strcmp(emp
->taxState
, "CA") == 0) {
stateTaxRate = CA_TAX_RATE;
}
else
{
stateTaxRate = DEFAULT_TAX_RATE;
}
emp->stateTax = emp->grossPay * stateTaxRate;
emp->fedTax = emp->grossPay * FED_TAX_RATE;
emp->netPay = emp->grossPay - emp->stateTax - emp->fedTax;
}
// Function to update the running totals structure
void updateTotals(struct totals *tots, const struct employee *emp)
{
tots->total_wageRate += emp->wageRate;
tots->total_hours += emp->hours;
tots->total_overtimeHrs += emp->overtimeHrs;
tots->total_grossPay += emp->grossPay;
tots->total_stateTax += emp->stateTax;
tots->total_fedTax += emp->fedTax;
tots->total_netPay += emp->netPay;
}
// Function to find the employees with minimum and maximum gross pay
void findMinMax(const struct employee emps[], int size, struct employee *minGrossPayEmp, struct employee *maxGrossPayEmp)
{
int i;
// Initialize min/max to the first employee's data
*minGrossPayEmp = emps[0];
*maxGrossPayEmp = emps[0];
for (i = 1; i < size; i++)
{
if (emps[i].grossPay < minGrossPayEmp->grossPay)
{
*minGrossPayEmp = emps[i];
}
if (emps[i].grossPay > maxGrossPayEmp->grossPay)
{
*maxGrossPayEmp = emps[i];
}
}
}
// Function to display all employee details, totals, averages, and min/max
void displayOutput(const struct employee emps[], int size, const struct totals *tots, const struct employee *minGrossPayEmp, const struct employee *maxGrossPayEmp)
{
int i;
printf("\n\n-------------------------------------------------------------------------------------------------------------------\n"); printf("Name\t\tState\tClock #\t Wage\t Hours\t OT Hrs\t Gross Pay\t State Tax\t Fed Tax\t Net Pay\n"); printf("-------------------------------------------------------------------------------------------------------------------\n");
for (i = 0; i < size; i++)
{
printf("%s %s\t%s\t%ld\t%.2f\t%.1f\t%.1f\t$%.2f\t$%.2f\t$%.2f\t$%.2f\n", emps[i].empName.firstName, emps[i].empName.lastName,
emps[i].taxState, emps[i].clockNumber, emps[i].wageRate,
emps[i].hours, emps[i].overtimeHrs, emps[i].grossPay,
emps[i].stateTax, emps[i].fedTax, emps[i].netPay);
}
printf("-------------------------------------------------------------------------------------------------------------------\n");
// Display Totals
printf("Totals:\t\t\t\t\t%.1f\t%.1f\t$%.2f\t$%.2f\t$%.2f\t$%.2f\n", tots->total_hours, tots->total_overtimeHrs, tots->total_grossPay,
tots->total_stateTax, tots->total_fedTax, tots->total_netPay);
// Display Averages (calculated on the fly)
printf("Averages:\t\t\t\t%.1f\t%.1f\t$%.2f\t$%.2f\t$%.2f\t$%.2f\n", tots->total_hours / size, tots->total_overtimeHrs / size, tots->total_grossPay / size,
tots->total_stateTax / size, tots->total_fedTax / size, tots->total_netPay / size);
printf("-------------------------------------------------------------------------------------------------------------------\n");
// Display Min/Max Gross Pay employees
printf("\nMinimum Gross Pay Employee: %s %s (Clock #%ld) - $%.2f\n", minGrossPayEmp->empName.firstName, minGrossPayEmp->empName.lastName,
minGrossPayEmp->clockNumber, minGrossPayEmp->grossPay);
printf("Maximum Gross Pay Employee: %s %s (Clock #%ld) - $%.2f\n\n", maxGrossPayEmp->empName.firstName, maxGrossPayEmp->empName.lastName,
maxGrossPayEmp->clockNumber, maxGrossPayEmp->grossPay);
}
// Function to convert a string to uppercase
void convertToUpper(char *str) {
for (int i = 0; str[i] != '\0'; i++) {
str
[i
] = toupper((unsigned char)str
[i
]); }
}
Ly8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgovLwovLyBBc3NpZ25tZW50IDcgLSBTdHJ1Y3R1cmVzIGFuZCBTdHJpbmdzCi8vCi8vIE5hbWU6IFJvc2UgU2FtZWRpCi8vCi8vIENsYXNzOiBDIFByb2dyYW1taW5nLCBGYWxsIDIwMjUKLy8KLy8gRGF0ZTogMTEvMTYvMjAyNQovLwovLyBEZXNjcmlwdGlvbjogUHJvZ3JhbSB3aGljaCBkZXRlcm1pbmVzIG92ZXJ0aW1lIGFuZAovLyBncm9zcyBwYXkgZm9yIGEgc2V0IG9mIGVtcGxveWVlcyB3aXRoIG91dHB1dHMgc2VudAovLyB0byBzdGFuZGFyZCBvdXRwdXQgKHRoZSBzY3JlZW4pLgovLwovLyBUaGlzIGFzc2lnbm1lbnQgYWxzbyBhZGRzIHRoZSBlbXBsb3llZSBuYW1lLCB0aGVpciB0YXggc3RhdGUsCi8vIGFuZCBjYWxjdWxhdGVzIHRoZSBzdGF0ZSB0YXgsIGZlZGVyYWwgdGF4LCBhbmQgbmV0IHBheS4gICBJdAovLyBhbHNvIGNhbGN1bGF0ZXMgdG90YWxzLCBhdmVyYWdlcywgbWluaW11bSwgYW5kIG1heGltdW0gdmFsdWVzLgovLwovLyBDYWxsIGJ5IFJlZmVyZW5jZSBkZXNpZ24KLy8KLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogCi8vIG5lY2Vzc2FyeSBoZWFkZXIgZmlsZXMKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGN0eXBlLmg+CiAKLy8gZGVmaW5lIGNvbnN0YW50cwojZGVmaW5lIFNJWkUgNQojZGVmaW5lIFNURF9IT1VSUyA0MC4wCiNkZWZpbmUgT1RfUkFURSAxLjUKI2RlZmluZSBNQV9UQVhfUkFURSAwLjA1CiNkZWZpbmUgTkhfVEFYX1JBVEUgMC4wCiNkZWZpbmUgVlRfVEFYX1JBVEUgMC4wNgojZGVmaW5lIENBX1RBWF9SQVRFIDAuMDcKI2RlZmluZSBERUZBVUxUX1RBWF9SQVRFIDAuMDgKI2RlZmluZSBOQU1FX1NJWkUgMjAKI2RlZmluZSBUQVhfU1RBVEVfU0laRSAzCiNkZWZpbmUgRkVEX1RBWF9SQVRFIDAuMjUKI2RlZmluZSBGSVJTVF9OQU1FX1NJWkUgMTAKI2RlZmluZSBMQVNUX05BTUVfU0laRSAxMAogCi8vIERlZmluZSBhIHN0cnVjdHVyZSB0eXBlIHRvIHN0b3JlIGFuIGVtcGxveWVlIG5hbWUKc3RydWN0IG5hbWUKewogICAgY2hhciBmaXJzdE5hbWVbRklSU1RfTkFNRV9TSVpFXTsKICAgIGNoYXIgbGFzdE5hbWUgW0xBU1RfTkFNRV9TSVpFXTsKfTsKIAovLyBEZWZpbmUgYSBzdHJ1Y3R1cmUgdHlwZSB0byBwYXNzIGVtcGxveWVlIGRhdGEgYmV0d2VlbiBmdW5jdGlvbnMKc3RydWN0IGVtcGxveWVlCnsKICAgIHN0cnVjdCBuYW1lIGVtcE5hbWU7CiAgICBjaGFyIHRheFN0YXRlIFtUQVhfU1RBVEVfU0laRV07CiAgICBsb25nIGludCBjbG9ja051bWJlcjsKICAgIGZsb2F0IHdhZ2VSYXRlOwogICAgZmxvYXQgaG91cnM7CiAgICBmbG9hdCBvdmVydGltZUhyczsKICAgIGZsb2F0IGdyb3NzUGF5OwogICAgZmxvYXQgc3RhdGVUYXg7CiAgICBmbG9hdCBmZWRUYXg7CiAgICBmbG9hdCBuZXRQYXk7Cn07CiAKLy8gdGhpcyBzdHJ1Y3R1cmUgdHlwZSBkZWZpbmVzIHRoZSB0b3RhbHMgb2YgYWxsIGZsb2F0aW5nIHBvaW50IGl0ZW1zCi8vIHNvIHRoZXkgY2FuIGJlIHRvdGFsZWQgYW5kIHVzZWQgYWxzbyB0byBjYWxjdWxhdGUgYXZlcmFnZXMKc3RydWN0IHRvdGFscwp7CiAgICBmbG9hdCB0b3RhbF93YWdlUmF0ZTsKICAgIGZsb2F0IHRvdGFsX2hvdXJzOwogICAgZmxvYXQgdG90YWxfb3ZlcnRpbWVIcnM7CiAgICBmbG9hdCB0b3RhbF9ncm9zc1BheTsKICAgIGZsb2F0IHRvdGFsX3N0YXRlVGF4OwogICAgZmxvYXQgdG90YWxfZmVkVGF4OwogICAgZmxvYXQgdG90YWxfbmV0UGF5Owp9OwoKLy8gRnVuY3Rpb24gcHJvdG90eXBlcwp2b2lkIGNhbGN1bGF0ZVBheShzdHJ1Y3QgZW1wbG95ZWUgKmVtcCk7CnZvaWQgY2FsY3VsYXRlVGF4ZXMoc3RydWN0IGVtcGxveWVlICplbXApOwp2b2lkIHVwZGF0ZVRvdGFscyhzdHJ1Y3QgdG90YWxzICp0b3RzLCBjb25zdCBzdHJ1Y3QgZW1wbG95ZWUgKmVtcCk7CnZvaWQgZmluZE1pbk1heChjb25zdCBzdHJ1Y3QgZW1wbG95ZWUgZW1wc1tdLCBpbnQgc2l6ZSwgc3RydWN0IGVtcGxveWVlICptaW5Hcm9zc1BheUVtcCwgc3RydWN0IGVtcGxveWVlICptYXhHcm9zc1BheUVtcCk7CnZvaWQgZGlzcGxheU91dHB1dChjb25zdCBzdHJ1Y3QgZW1wbG95ZWUgZW1wc1tdLCBpbnQgc2l6ZSwgY29uc3Qgc3RydWN0IHRvdGFscyAqdG90cywgY29uc3Qgc3RydWN0IGVtcGxveWVlICptaW5Hcm9zc1BheUVtcCwgY29uc3Qgc3RydWN0IGVtcGxveWVlICptYXhHcm9zc1BheUVtcCk7CnZvaWQgY29udmVydFRvVXBwZXIoY2hhciAqc3RyKTsKCmludCBtYWluKHZvaWQpCnsKICAgIC8vIEluaXRpYWxpemUgZW1wbG95ZWUgZGF0YSBmb3IgU0laRSBlbXBsb3llZXMKICAgIHN0cnVjdCBlbXBsb3llZSBlbXBsb3llZXNbU0laRV0gPSB7CiAgICAgICAge3siUGF0IiwgIkN1cnJ5In0sICJNQSIsIDk4MDEyNEwsIDEwLjYwLCA1MS41LCAwLjAsIDAuMCwgMC4wLCAwLjAsIDAuMH0sCiAgICAgICAge3siTGVvIiwgIkRlbWVycyJ9LCAiTkgiLCA5ODAyMjFMLCAxMC42MCwgNDAuMCwgMC4wLCAwLjAsIDAuMCwgMC4wLCAwLjB9LAogICAgICAgIHt7IktpbSIsICJXb25nIn0sICJWVCIsIDk4MDM0NUwsIDEwLjYwLCA0MS4yLCAwLjAsIDAuMCwgMC4wLCAwLjAsIDAuMH0sCiAgICAgICAge3siSmFjayIsICJHb3VyZGVhdSJ9LCAiTUEiLCA5ODA0MDBMLCAxMC42MCwgNjAuMCwgMC4wLCAwLjAsIDAuMCwgMC4wLCAwLjB9LAogICAgICAgIHt7IlBoaWwiLCAiTGFjb3Vyc2UifSwgIkNBIiwgOTgwNTEyTCwgMTAuNjAsIDM4LjUsIDAuMCwgMC4wLCAwLjAsIDAuMCwgMC4wfQogICAgfTsKCiAgICBzdHJ1Y3QgdG90YWxzIGFsbFRvdGFscyA9IHswLjAsIDAuMCwgMC4wLCAwLjAsIDAuMCwgMC4wLCAwLjB9OwogICAgc3RydWN0IGVtcGxveWVlIG1pbkdyb3NzUGF5RW1wOwogICAgc3RydWN0IGVtcGxveWVlIG1heEdyb3NzUGF5RW1wOwogICAgaW50IGk7CgogICAgLy8gUHJvY2VzcyBlYWNoIGVtcGxveWVlCiAgICBmb3IgKGkgPSAwOyBpIDwgU0laRTsgaSsrKQogICAgewogICAgICAgIGNhbGN1bGF0ZVBheSgmZW1wbG95ZWVzW2ldKTsKICAgICAgICBjYWxjdWxhdGVUYXhlcygmZW1wbG95ZWVzW2ldKTsKICAgICAgICB1cGRhdGVUb3RhbHMoJmFsbFRvdGFscywgJmVtcGxveWVlc1tpXSk7CiAgICB9CgogICAgLy8gRmluZCBtaW4vbWF4IGFmdGVyIGFsbCBjYWxjdWxhdGlvbnMgYXJlIGRvbmUKICAgIGZpbmRNaW5NYXgoZW1wbG95ZWVzLCBTSVpFLCAmbWluR3Jvc3NQYXlFbXAsICZtYXhHcm9zc1BheUVtcCk7CgogICAgLy8gRGlzcGxheSB0aGUgcmVzdWx0cwogICAgZGlzcGxheU91dHB1dChlbXBsb3llZXMsIFNJWkUsICZhbGxUb3RhbHMsICZtaW5Hcm9zc1BheUVtcCwgJm1heEdyb3NzUGF5RW1wKTsKCiAgICByZXR1cm4gMDsKfQoKLy8gRnVuY3Rpb24gdG8gY2FsY3VsYXRlIG92ZXJ0aW1lIGhvdXJzIGFuZCBncm9zcyBwYXkgZm9yIGEgc2luZ2xlIGVtcGxveWVlCnZvaWQgY2FsY3VsYXRlUGF5KHN0cnVjdCBlbXBsb3llZSAqZW1wKQp7CiAgICBpZiAoZW1wLT5ob3VycyA+IFNURF9IT1VSUykKICAgIHsKICAgICAgICBlbXAtPm92ZXJ0aW1lSHJzID0gZW1wLT5ob3VycyAtIFNURF9IT1VSUzsKICAgICAgICBlbXAtPmdyb3NzUGF5ID0gKFNURF9IT1VSUyAqIGVtcC0+d2FnZVJhdGUpICsgKGVtcC0+b3ZlcnRpbWVIcnMgKiBlbXAtPndhZ2VSYXRlICogT1RfUkFURSk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgZW1wLT5vdmVydGltZUhycyA9IDAuMDsKICAgICAgICBlbXAtPmdyb3NzUGF5ID0gZW1wLT5ob3VycyAqIGVtcC0+d2FnZVJhdGU7CiAgICB9Cn0KCi8vIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBzdGF0ZSB0YXgsIGZlZGVyYWwgdGF4LCBhbmQgbmV0IHBheSBmb3IgYSBzaW5nbGUgZW1wbG95ZWUKdm9pZCBjYWxjdWxhdGVUYXhlcyhzdHJ1Y3QgZW1wbG95ZWUgKmVtcCkKewogICAgZmxvYXQgc3RhdGVUYXhSYXRlOwogICAgCiAgICAvLyBDb252ZXJ0IHN0YXRlIGNvZGUgdG8gdXBwZXJjYXNlIGZvciBjb25zaXN0ZW50IGNvbXBhcmlzb24KICAgIGNvbnZlcnRUb1VwcGVyKGVtcC0+dGF4U3RhdGUpOwoKICAgIGlmIChzdHJjbXAoZW1wLT50YXhTdGF0ZSwgIk1BIikgPT0gMCkKICAgIHsKICAgICAgICBzdGF0ZVRheFJhdGUgPSBNQV9UQVhfUkFURTsKICAgIH0KICAgIGVsc2UgaWYgKHN0cmNtcChlbXAtPnRheFN0YXRlLCAiTkgiKSA9PSAwKQogICAgewogICAgICAgIHN0YXRlVGF4UmF0ZSA9IE5IX1RBWF9SQVRFOwogICAgfQogICAgZWxzZSBpZiAoc3RyY21wKGVtcC0+dGF4U3RhdGUsICJWVCIpID09IDApCiAgICB7CiAgICAgICAgc3RhdGVUYXhSYXRlID0gVlRfVEFYX1JBVEU7CiAgICB9CiAgICBlbHNlIGlmIChzdHJjbXAoZW1wLT50YXhTdGF0ZSwgIkNBIikgPT0gMCkKICAgIHsKICAgICAgICBzdGF0ZVRheFJhdGUgPSBDQV9UQVhfUkFURTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBzdGF0ZVRheFJhdGUgPSBERUZBVUxUX1RBWF9SQVRFOwogICAgfQoKICAgIGVtcC0+c3RhdGVUYXggPSBlbXAtPmdyb3NzUGF5ICogc3RhdGVUYXhSYXRlOwogICAgZW1wLT5mZWRUYXggPSBlbXAtPmdyb3NzUGF5ICogRkVEX1RBWF9SQVRFOwogICAgZW1wLT5uZXRQYXkgPSBlbXAtPmdyb3NzUGF5IC0gZW1wLT5zdGF0ZVRheCAtIGVtcC0+ZmVkVGF4Owp9CgovLyBGdW5jdGlvbiB0byB1cGRhdGUgdGhlIHJ1bm5pbmcgdG90YWxzIHN0cnVjdHVyZQp2b2lkIHVwZGF0ZVRvdGFscyhzdHJ1Y3QgdG90YWxzICp0b3RzLCBjb25zdCBzdHJ1Y3QgZW1wbG95ZWUgKmVtcCkKewogICAgdG90cy0+dG90YWxfd2FnZVJhdGUgKz0gZW1wLT53YWdlUmF0ZTsKICAgIHRvdHMtPnRvdGFsX2hvdXJzICs9IGVtcC0+aG91cnM7CiAgICB0b3RzLT50b3RhbF9vdmVydGltZUhycyArPSBlbXAtPm92ZXJ0aW1lSHJzOwogICAgdG90cy0+dG90YWxfZ3Jvc3NQYXkgKz0gZW1wLT5ncm9zc1BheTsKICAgIHRvdHMtPnRvdGFsX3N0YXRlVGF4ICs9IGVtcC0+c3RhdGVUYXg7CiAgICB0b3RzLT50b3RhbF9mZWRUYXggKz0gZW1wLT5mZWRUYXg7CiAgICB0b3RzLT50b3RhbF9uZXRQYXkgKz0gZW1wLT5uZXRQYXk7Cn0KCi8vIEZ1bmN0aW9uIHRvIGZpbmQgdGhlIGVtcGxveWVlcyB3aXRoIG1pbmltdW0gYW5kIG1heGltdW0gZ3Jvc3MgcGF5CnZvaWQgZmluZE1pbk1heChjb25zdCBzdHJ1Y3QgZW1wbG95ZWUgZW1wc1tdLCBpbnQgc2l6ZSwgc3RydWN0IGVtcGxveWVlICptaW5Hcm9zc1BheUVtcCwgc3RydWN0IGVtcGxveWVlICptYXhHcm9zc1BheUVtcCkKewogICAgaW50IGk7CiAgICAvLyBJbml0aWFsaXplIG1pbi9tYXggdG8gdGhlIGZpcnN0IGVtcGxveWVlJ3MgZGF0YQogICAgKm1pbkdyb3NzUGF5RW1wID0gZW1wc1swXTsKICAgICptYXhHcm9zc1BheUVtcCA9IGVtcHNbMF07CgogICAgZm9yIChpID0gMTsgaSA8IHNpemU7IGkrKykKICAgIHsKICAgICAgICBpZiAoZW1wc1tpXS5ncm9zc1BheSA8IG1pbkdyb3NzUGF5RW1wLT5ncm9zc1BheSkKICAgICAgICB7CiAgICAgICAgICAgICptaW5Hcm9zc1BheUVtcCA9IGVtcHNbaV07CiAgICAgICAgfQogICAgICAgIGlmIChlbXBzW2ldLmdyb3NzUGF5ID4gbWF4R3Jvc3NQYXlFbXAtPmdyb3NzUGF5KQogICAgICAgIHsKICAgICAgICAgICAgKm1heEdyb3NzUGF5RW1wID0gZW1wc1tpXTsKICAgICAgICB9CiAgICB9Cn0KCi8vIEZ1bmN0aW9uIHRvIGRpc3BsYXkgYWxsIGVtcGxveWVlIGRldGFpbHMsIHRvdGFscywgYXZlcmFnZXMsIGFuZCBtaW4vbWF4CnZvaWQgZGlzcGxheU91dHB1dChjb25zdCBzdHJ1Y3QgZW1wbG95ZWUgZW1wc1tdLCBpbnQgc2l6ZSwgY29uc3Qgc3RydWN0IHRvdGFscyAqdG90cywgY29uc3Qgc3RydWN0IGVtcGxveWVlICptaW5Hcm9zc1BheUVtcCwgY29uc3Qgc3RydWN0IGVtcGxveWVlICptYXhHcm9zc1BheUVtcCkKewogICAgaW50IGk7CgogICAgcHJpbnRmKCJcblxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIik7CiAgICBwcmludGYoIk5hbWVcdFx0U3RhdGVcdENsb2NrICNcdCBXYWdlXHQgSG91cnNcdCBPVCBIcnNcdCBHcm9zcyBQYXlcdCBTdGF0ZSBUYXhcdCBGZWQgVGF4XHQgTmV0IFBheVxuIik7CiAgICBwcmludGYoIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiIpOwoKICAgIGZvciAoaSA9IDA7IGkgPCBzaXplOyBpKyspCiAgICB7CiAgICAgICAgcHJpbnRmKCIlcyAlc1x0JXNcdCVsZFx0JS4yZlx0JS4xZlx0JS4xZlx0JCUuMmZcdCQlLjJmXHQkJS4yZlx0JCUuMmZcbiIsCiAgICAgICAgICAgICAgIGVtcHNbaV0uZW1wTmFtZS5maXJzdE5hbWUsIGVtcHNbaV0uZW1wTmFtZS5sYXN0TmFtZSwKICAgICAgICAgICAgICAgZW1wc1tpXS50YXhTdGF0ZSwgZW1wc1tpXS5jbG9ja051bWJlciwgZW1wc1tpXS53YWdlUmF0ZSwKICAgICAgICAgICAgICAgZW1wc1tpXS5ob3VycywgZW1wc1tpXS5vdmVydGltZUhycywgZW1wc1tpXS5ncm9zc1BheSwKICAgICAgICAgICAgICAgZW1wc1tpXS5zdGF0ZVRheCwgZW1wc1tpXS5mZWRUYXgsIGVtcHNbaV0ubmV0UGF5KTsKICAgIH0KCiAgICBwcmludGYoIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiIpOwoKICAgIC8vIERpc3BsYXkgVG90YWxzCiAgICBwcmludGYoIlRvdGFsczpcdFx0XHRcdFx0JS4xZlx0JS4xZlx0JCUuMmZcdCQlLjJmXHQkJS4yZlx0JCUuMmZcbiIsCiAgICAgICAgICAgdG90cy0+dG90YWxfaG91cnMsIHRvdHMtPnRvdGFsX292ZXJ0aW1lSHJzLCB0b3RzLT50b3RhbF9ncm9zc1BheSwKICAgICAgICAgICB0b3RzLT50b3RhbF9zdGF0ZVRheCwgdG90cy0+dG90YWxfZmVkVGF4LCB0b3RzLT50b3RhbF9uZXRQYXkpOwoKICAgIC8vIERpc3BsYXkgQXZlcmFnZXMgKGNhbGN1bGF0ZWQgb24gdGhlIGZseSkKICAgIHByaW50ZigiQXZlcmFnZXM6XHRcdFx0XHQlLjFmXHQlLjFmXHQkJS4yZlx0JCUuMmZcdCQlLjJmXHQkJS4yZlxuIiwKICAgICAgICAgICB0b3RzLT50b3RhbF9ob3VycyAvIHNpemUsIHRvdHMtPnRvdGFsX292ZXJ0aW1lSHJzIC8gc2l6ZSwgdG90cy0+dG90YWxfZ3Jvc3NQYXkgLyBzaXplLAogICAgICAgICAgIHRvdHMtPnRvdGFsX3N0YXRlVGF4IC8gc2l6ZSwgdG90cy0+dG90YWxfZmVkVGF4IC8gc2l6ZSwgdG90cy0+dG90YWxfbmV0UGF5IC8gc2l6ZSk7CiAgICAKICAgIHByaW50ZigiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIik7CgogICAgLy8gRGlzcGxheSBNaW4vTWF4IEdyb3NzIFBheSBlbXBsb3llZXMKICAgIHByaW50ZigiXG5NaW5pbXVtIEdyb3NzIFBheSBFbXBsb3llZTogJXMgJXMgKENsb2NrICMlbGQpIC0gJCUuMmZcbiIsCiAgICAgICAgICAgbWluR3Jvc3NQYXlFbXAtPmVtcE5hbWUuZmlyc3ROYW1lLCBtaW5Hcm9zc1BheUVtcC0+ZW1wTmFtZS5sYXN0TmFtZSwKICAgICAgICAgICBtaW5Hcm9zc1BheUVtcC0+Y2xvY2tOdW1iZXIsIG1pbkdyb3NzUGF5RW1wLT5ncm9zc1BheSk7CgogICAgcHJpbnRmKCJNYXhpbXVtIEdyb3NzIFBheSBFbXBsb3llZTogJXMgJXMgKENsb2NrICMlbGQpIC0gJCUuMmZcblxuIiwKICAgICAgICAgICBtYXhHcm9zc1BheUVtcC0+ZW1wTmFtZS5maXJzdE5hbWUsIG1heEdyb3NzUGF5RW1wLT5lbXBOYW1lLmxhc3ROYW1lLAogICAgICAgICAgIG1heEdyb3NzUGF5RW1wLT5jbG9ja051bWJlciwgbWF4R3Jvc3NQYXlFbXAtPmdyb3NzUGF5KTsKfQoKLy8gRnVuY3Rpb24gdG8gY29udmVydCBhIHN0cmluZyB0byB1cHBlcmNhc2UKdm9pZCBjb252ZXJ0VG9VcHBlcihjaGFyICpzdHIpIHsKICAgIGZvciAoaW50IGkgPSAwOyBzdHJbaV0gIT0gJ1wwJzsgaSsrKSB7CiAgICAgICAgc3RyW2ldID0gdG91cHBlcigodW5zaWduZWQgY2hhcilzdHJbaV0pOwogICAgfQp9