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