1bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/*
2bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * Copyright 2008 Google Inc.
3bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson *
4bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * you may not use this file except in compliance with the License.
6bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * You may obtain a copy of the License at
7bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson *
8bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * http://www.apache.org/licenses/LICENSE-2.0
9bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson *
10bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * Unless required by applicable law or agreed to in writing, software
11bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * See the License for the specific language governing permissions and
14bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * limitations under the License.
15bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson */
16bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
17bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson// A calculator example used to demonstrate the cmockery testing library.
18bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
19bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#include <assert.h>
20bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#include <stdio.h>
21bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#include <stdlib.h>
22bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#include <string.h>
23bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
24bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson// If this is being built for a unit test.
25bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#if UNIT_TESTING
26bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
27bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/* Redirect printf to a function in the test application so it's possible to
28bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * test the standard output. */
29bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#ifdef printf
30bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#undef printf
31bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#endif // printf
32bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#define printf example_test_printf
33bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
34bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonextern void print_message(const char *format, ...);
35bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
36bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/* Redirect fprintf to a function in the test application so it's possible to
37bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * test error messages. */
38bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#ifdef fprintf
39bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#undef fprintf
40bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#endif // fprintf
41bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#define fprintf example_test_fprintf
42bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
43bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonextern int example_test_fprintf(FILE * const file, const char *format, ...);
44bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
45bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson// Redirect assert to mock_assert() so assertions can be caught by cmockery.
46bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#ifdef assert
47bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#undef assert
48bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#endif // assert
49bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#define assert(expression) \
50bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	mock_assert((int)(expression), #expression, __FILE__, __LINE__)
51bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonvoid mock_assert(const int result, const char* expression, const char *file,
52bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson                 const int line);
53bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
54bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/* Redirect calloc and free to test_calloc() and test_free() so cmockery can
55bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * check for memory leaks. */
56bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#ifdef calloc
57bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#undef calloc
58bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#endif // calloc
59bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
60bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#ifdef free
61bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#undef free
62bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#endif // free
63bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#define free(ptr) _test_free(ptr, __FILE__, __LINE__)
64bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonvoid* _test_calloc(const size_t number_of_elements, const size_t size,
65bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson                   const char* file, const int line);
66bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonvoid _test_free(void* const ptr, const char* file, const int line);
67bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
68bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/* main is defined in the unit test so redefine name of the the main function
69bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * here. */
70bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#define main example_main
71bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
72bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/* All functions in this object need to be exposed to the test application,
73bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * so redefine static to nothing. */
74bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#define static
75bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
76bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson#endif // UNIT_TESTING
77bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
78bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
79bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson// A binary arithmetic integer operation (add, subtract etc.)
80bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsontypedef int (*BinaryOperator)(int a, int b);
81bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
82bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson// Structure which maps operator strings to functions.
83bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsontypedef struct OperatorFunction {
84bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	const char* operator;
85bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	BinaryOperator function;
86bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson} OperatorFunction;
87bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
88bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
89bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int add(int a, int b);
90bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int subtract(int a, int b);
91bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int multiply(int a, int b);
92bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int divide(int a, int b);
93bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
94bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson// Associate operator strings to functions.
95bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic OperatorFunction operator_function_map[] = {
96bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	{"+", add},
97bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	{"-", subtract},
98bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	{"*", multiply},
99bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	{"/", divide},
100bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson};
101bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
102bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int add(int a, int b) {
103bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	return a + b;
104bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson}
105bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
106bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int subtract(int a, int b) {
107bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	return a - b;
108bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson}
109bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
110bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int multiply(int a, int b) {
111bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	return a * b;
112bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson}
113bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
114bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int divide(int a, int b) {
115bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(b);  // Check for divde by zero.
116bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	return a / b;
117bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson}
118bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
119bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/* Searches the specified array of operator_functions for the function
120bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * associated with the specified operator_string.  This function returns the
121bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * function associated with operator_string if successful, NULL otherwise.
122bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson */
123bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic BinaryOperator find_operator_function_by_string(
124bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        const size_t number_of_operator_functions,
125bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        const OperatorFunction * const operator_functions,
126bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        const char* const operator_string) {
127bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	size_t i;
128bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(!number_of_operator_functions || operator_functions);
129bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(operator_string);
130bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
131bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	for (i = 0; i < number_of_operator_functions; i++) {
132bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		const OperatorFunction *const operator_function =
133bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		    &operator_functions[i];
134bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		if (strcmp(operator_function->operator, operator_string) == 0) {
135bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			return operator_function->function;
136bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		}
137bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	}
138bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	return NULL;
139bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson}
140bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
141bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson/* Perform a series of binary arithmetic integer operations with no operator
142bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * precedence.
143bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson *
144bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * The input expression is specified by arguments which is an array of
145bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * containing number_of_arguments strings.  Operators invoked by the expression
146bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * are specified by the array operator_functions containing
147bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * number_of_operator_functions, OperatorFunction structures.  The value of
148bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * each binary operation is stored in a pointer returned to intermediate_values
149bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * which is allocated by malloc().
150bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson *
151bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * If successful, this function returns the integer result of the operations.
152bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * If an error occurs while performing the operation error_occurred is set to
153bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson * 1, the operation is aborted and 0 is returned.
154bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson */
155bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonstatic int perform_operation(
156bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        int number_of_arguments, char *arguments[],
157bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        const size_t number_of_operator_functions,
158bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        const OperatorFunction * const operator_functions,
159bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        int * const number_of_intermediate_values,
160bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson        int ** const intermediate_values, int * const error_occurred) {
161bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	char *end_of_integer;
162bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	int value;
163bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	unsigned int i;
164bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(!number_of_arguments || arguments);
165bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(!number_of_operator_functions || operator_functions);
166bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(error_occurred);
167bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(number_of_intermediate_values);
168bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	assert(intermediate_values);
169bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
170bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	*error_occurred = 0;
171bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	*number_of_intermediate_values = 0;
172bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	*intermediate_values = NULL;
173bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	if (!number_of_arguments)
174bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		return 0;
175bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
176bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	// Parse the first value.
177bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	value = (int)strtol(arguments[0], &end_of_integer, 10);
178bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	if (end_of_integer == arguments[0]) {
179bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		// If an error occurred while parsing the integer.
180bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		fprintf(stderr, "Unable to parse integer from argument %s\n",
181bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		        arguments[0]);
182bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		*error_occurred = 1;
183bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		return 0;
184bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	}
185bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
186bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	// Allocate an array for the output values.
187bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	*intermediate_values = calloc(((number_of_arguments - 1) / 2),
188bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	                              sizeof(**intermediate_values));
189bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
190bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	i = 1;
191bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	while (i < number_of_arguments) {
192bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		int other_value;
193bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		const char* const operator_string = arguments[i];
194bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		const BinaryOperator function = find_operator_function_by_string(
195bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		    number_of_operator_functions, operator_functions, operator_string);
196bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		int * const intermediate_value =
197bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		    &((*intermediate_values)[*number_of_intermediate_values]);
198bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		(*number_of_intermediate_values) ++;
199bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
200bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		if (!function) {
201bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			fprintf(stderr, "Unknown operator %s, argument %d\n",
202bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			        operator_string, i);
203bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			*error_occurred = 1;
204bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			break;
205bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		}
206bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		i ++;
207bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
208bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		if (i == number_of_arguments) {
209bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			fprintf(stderr, "Binary operator %s missing argument\n",
210bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			        operator_string);
211bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			*error_occurred = 1;
212bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			break;
213bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		}
214bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
215bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		other_value = (int)strtol(arguments[i], &end_of_integer, 10);
216bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		if (end_of_integer == arguments[i]) {
217bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			// If an error occurred while parsing the integer.
218bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			fprintf(stderr, "Unable to parse integer %s of argument %d\n",
219bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			        arguments[i], i);
220bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			*error_occurred = 1;
221bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			break;
222bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		}
223bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		i ++;
224bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
225bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		// Perform the operation and store the intermediate value.
226bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		*intermediate_value = function(value, other_value);
227bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		value = *intermediate_value;
228bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	}
229bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	if (*error_occurred) {
230bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		free(*intermediate_values);
231bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		*intermediate_values = NULL;
232bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		*number_of_intermediate_values = 0;
233bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		return 0;
234bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	}
235bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	return value;
236bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson}
237bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
238bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilsonint main(int argc, char *argv[]) {
239bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	int return_value;
240bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	int number_of_intermediate_values;
241bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	int *intermediate_values;
242bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	// Peform the operation.
243bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	const int result = perform_operation(
244bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	    argc - 1, &argv[1],
245bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	    sizeof(operator_function_map) / sizeof(operator_function_map[0]),
246bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	    operator_function_map, &number_of_intermediate_values,
247bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	    &intermediate_values, &return_value);
248bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
249bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	// If no errors occurred display the result.
250bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	if (!return_value && argc > 1) {
251bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		unsigned int i;
252bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		unsigned int intermediate_value_index = 0;
253bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		printf("%s\n", argv[1]);
254bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		for (i = 2; i < argc; i += 2) {
255bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			assert(intermediate_value_index < number_of_intermediate_values);
256bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			printf("  %s %s = %d\n", argv[i], argv[i + 1],
257bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson			       intermediate_values[intermediate_value_index++]);
258bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		}
259bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		printf("= %d\n", result);
260bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	}
261bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	if (intermediate_values) {
262bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson		free(intermediate_values);
263bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	}
264bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson
265bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson	return return_value;
266bdd62c531bbdea115a3a7e71bba91c19dd319cc4Heather Lee Wilson}
267