1 /*
2  *  T5 - was created to reproduce a bug in the handling of dynamic arrays of structured types
3  */
4 #include "config.h"
5 #include "data_funcs.h"
6 #include "cod.h"
7 #include <stdlib.h>
8 #ifdef HAVE_MALLOC_H
9 #include "malloc.h"
10 #endif
11 #include "assert.h"
12 #include <stdio.h>
13 #include <string.h>
14 
15 struct order_header {
16     int order_id;
17     int advertiser_number;
18     int agency_number;
19     int contract_number;
20     int start_date;
21     int end_date;
22     int estimate_number;
23     char class;
24     char *product_name;
25     int conflict_code1;
26     int conflict_code2;
27 };
28 
29 struct spot_week {
30     unsigned char mo;
31     unsigned char tu;
32     unsigned char we;
33     unsigned char th;
34     unsigned char fr;
35     unsigned char sa;
36     unsigned char su;
37 };
38 
39 struct spot {
40     int order_item_id;
41     unsigned char broadcast_week;
42     char *program_id;
43     short rate_section;
44     short length;
45     unsigned char bookend;
46     int start_date;
47     int end_date;
48     int cost_per_spot;
49     int spots_per_week;
50     struct spot_week spots_per_day;
51 };
52 
53 struct station_order {
54     int station_id;
55     char *task_name;
56     char *salesperson_code;
57     int order_id;
58     int advertiser_number;
59     int agency_number;
60     int contract_number;
61     int start_date;
62     int end_date;
63     int estimate_number;
64     char class;
65     char *product_name;
66     int conflict_code1;
67     int conflict_code2;
68     int spot_count;
69     struct spot *spots;
70 };
71 
72 FMField order_header_fields[] = {
73     {NULL, NULL, 0, 0}
74 };
75 
76 FMField spot_week_fields[] = {
77     {"MO", "unsigned integer", sizeof(unsigned char),
78      FMOffset(struct spot_week *, mo)},
79     {"TU", "unsigned integer", sizeof(unsigned char),
80      FMOffset(struct spot_week *, tu)},
81     {"WE", "unsigned integer", sizeof(unsigned char),
82      FMOffset(struct spot_week *, we)},
83     {"TH", "unsigned integer", sizeof(unsigned char),
84      FMOffset(struct spot_week *, th)},
85     {"FR", "unsigned integer", sizeof(unsigned char),
86      FMOffset(struct spot_week *, fr)},
87     {"SA", "unsigned integer", sizeof(unsigned char),
88      FMOffset(struct spot_week *, sa)},
89     {"SU", "unsigned integer", sizeof(unsigned char),
90      FMOffset(struct spot_week *, su)},
91     {NULL, NULL, 0, 0}
92 };
93 
94 FMField spot_fields[] = {
95     {"ORDER_ITEM_ID", "integer", sizeof(int),
96      FMOffset(struct spot *, order_item_id)},
97     {"BROADCAST_WEEK", "integer", sizeof(unsigned char),
98      FMOffset(struct spot *, broadcast_week)},
99     {"PROGRAM_ID", "string", sizeof(char *),
100      FMOffset(struct spot *, program_id)},
101     {"RATE_SECTION", "integer", sizeof(short),
102      FMOffset(struct spot *, rate_section)},
103     {"LENGTH", "integer", sizeof(short),
104      FMOffset(struct spot *, length)},
105     {"BOOKEND", "integer", sizeof(char),
106      FMOffset(struct spot *, bookend)},
107     {"START_DATE", "integer", sizeof(int),
108      FMOffset(struct spot *, start_date)},
109     {"END_DATE", "integer", sizeof(int),
110      FMOffset(struct spot *, end_date)},
111     {"COST_PER_SPOT", "integer", sizeof(int),
112      FMOffset(struct spot *, cost_per_spot)},
113     {"SPOTS_PER_WEEK", "integer", sizeof(int),
114      FMOffset(struct spot *, spots_per_week)},
115     {"SPOTS_PER_DAY", "spot_week", sizeof(struct spot_week),
116      FMOffset(struct spot *, spots_per_day)},
117     {NULL, NULL, 0, 0}
118 };
119 
120 FMField station_order_fields[] = {
121     {"STATION_ID", "integer", sizeof(int),
122      FMOffset(struct station_order *, station_id)},
123     {"TASK_NAME", "string", sizeof(char *),
124      FMOffset(struct station_order *, task_name)},
125     {"SALESPERSON_CODE", "string", sizeof(char *),
126      FMOffset(struct station_order *, salesperson_code)},
127     {"MO_ORDER_ID", "integer", sizeof(int),
128      FMOffset(struct station_order *, order_id)},
129     {"ADVERTISER_NO", "integer", sizeof(int),
130      FMOffset(struct station_order *, advertiser_number)},
131     {"AGENCY_NO", "integer", sizeof(int),
132      FMOffset(struct station_order *, agency_number)},
133     {"CONTRACT_NO", "integer", sizeof(int),
134      FMOffset(struct station_order *, contract_number)},
135     {"FLIGHT_START_DATE", "integer", sizeof(int),
136      FMOffset(struct station_order *, start_date)},
137     {"FLIGHT_END_DATE", "integer", sizeof(int),
138      FMOffset(struct station_order *, end_date)},
139     {"ESTIMATE_NO", "integer", sizeof(int),
140      FMOffset(struct station_order *, estimate_number)},
141     {"CLASS", "char", sizeof(char),
142      FMOffset(struct station_order *, class)},
143     {"PRODUCT_NAME", "string", sizeof(char *),
144      FMOffset(struct station_order *, product_name)},
145     {"CONFLICT_CODE_1", "integer", sizeof(int),
146      FMOffset(struct station_order *, conflict_code1)},
147     {"CONFLICT_CODE_2", "integer", sizeof(int),
148      FMOffset(struct station_order *, conflict_code2)},
149     {"SPOT_COUNT", "integer", sizeof(int),
150      FMOffset(struct station_order *, spot_count)},
151     {"SPOTS", "spot[SPOT_COUNT]", sizeof(struct spot),
152      FMOffset(struct station_order *, spots)},
153     {NULL, NULL, 0, 0}
154 };
155 
156 int
main(int argc,char ** argv)157 main(int argc, char **argv)
158 {
159     int verbose = 0;
160     int test_num = 0;
161     int run_only = -1;
162     char *read_file = NULL;
163     char *write_file = NULL;
164     while (argc > 1) {
165 	if (strcmp(argv[1], "-v") == 0) {
166 	    verbose++;
167 	} else if (strcmp(argv[1], "-w") == 0) {
168 	    if (argc <= 1) {
169 		printf("Need argument to \"-w\"\n");
170 	    } else {
171 		write_file = strdup(argv[2]);
172 	    }
173 	    argc--; argv++;
174 	} else if (strcmp(argv[1], "-r") == 0) {
175 	    if (argc <= 1) {
176 		printf("Need argument to \"-r\"\n");
177 	    } else {
178 		read_file = strdup(argv[2]);
179 	    }
180 	    argc--; argv++;
181 	} else if (strcmp(argv[1], "-o") == 0) {
182 	    sscanf(argv[2], "%d", &run_only);
183 	    argc--; argv++;
184 	}
185 	argc--; argv++;
186     }
187     if ((run_only == -1) || (run_only == test_num)) {
188 	/* 0 */
189 	static char extern_string[] = "int printf(string format, ...);";
190 
191 	static cod_extern_entry externs[] =
192 	{
193 	    {"printf", (void*)(long)printf},
194 	    {(void*)0, (void*)0}
195 	};
196 	/* test external call */
197 	static char code[] = "{\n\
198 	order_out.STATION_ID = order.STATION_ID;\n\
199 	order_out.TASK_NAME = order.TASK_NAME;\n\
200 	order_out.SPOT_COUNT = order.SPOT_COUNT;\n\
201 	order_out.SPOTS[1].BROADCAST_WEEK = 5;\n\
202 	order_out.SPOT_COUNT = 4;\n\
203 	if (order.SPOTS[0].PROGRAM_ID == \"EM2\") {\n\
204 		order_out.SPOTS[0].PROGRAM_ID = \"My Favorite Martian\";\n\
205 	}\n\
206 	if (order.SPOTS[0].PROGRAM_ID == \"EM5\") {\n\
207 		order_out.SPOTS[1].PROGRAM_ID = \"Dance Fever\";\n\
208 	}\n\
209 	if (order.SPOTS[1].PROGRAM_ID == \"EM2\") {\n\
210 		order_out.SPOTS[2].PROGRAM_ID = \"Gilligan's Island\";\n\
211 	}\n\
212 	if (order.SPOTS[1].PROGRAM_ID == \"EM5\") {\n\
213 		order_out.SPOTS[3].PROGRAM_ID = \"I Dream of Genie\";\n\
214 	}\n\
215 		}";
216 
217 	struct station_order order, out_order;
218 	struct spot spots[2];
219 	struct station_order *param = &order;
220 
221 	cod_parse_context context = new_cod_parse_context();
222 
223 	cod_code gen_code;
224 	void (*func)(void*, void*);
225 
226 	order.station_id = 11514;
227 	order.task_name = "PollOrdersTask";
228 	order.salesperson_code = "2-30-3001";
229 	order.order_id = 1004;
230 	order.advertiser_number = 2701;
231 	order.agency_number = 1701;
232 	order.contract_number = 0;
233 	order.start_date = 61101;
234 	order.end_date = 61701;
235 	order.estimate_number = 0;
236 	order.class = 'L';
237 	order.product_name = "Fall Special";
238 	order.conflict_code1 = 275;
239 	order.conflict_code2 = 0;
240 	order.spot_count = 2;
241 
242 	spots[0].order_item_id = 999;
243 	spots[0].broadcast_week = 1;
244 	spots[0].program_id = "EM5";
245 	spots[0].rate_section = 2;
246 	spots[0].length = 30;
247 	spots[0].bookend = 1;
248 	spots[0].start_date = 61101;
249 	spots[0].end_date = 61701;
250 	spots[0].cost_per_spot = 120;
251 	spots[0].spots_per_week = 10;
252 	spots[0].spots_per_day.mo = 5;
253 	spots[0].spots_per_day.tu = 2;
254 	spots[0].spots_per_day.we = 1;
255 	spots[0].spots_per_day.th = 0;
256 	spots[0].spots_per_day.fr = 2;
257 	spots[0].spots_per_day.sa = 0;
258 	spots[0].spots_per_day.su = 0;
259 
260 
261 	spots[1].order_item_id = 999;
262 	spots[1].broadcast_week = 2;
263 	spots[1].program_id = "EM2";
264 	spots[1].rate_section = 2;
265 	spots[1].length = 30;
266 	spots[1].bookend = 1;
267 	spots[1].start_date = 61101;
268 	spots[1].end_date = 61701;
269 	spots[1].cost_per_spot = 120;
270 	spots[1].spots_per_week = 10;
271 	spots[1].spots_per_day.mo = 5;
272 	spots[1].spots_per_day.tu = 2;
273 	spots[1].spots_per_day.we = 1;
274 	spots[1].spots_per_day.th = 0;
275 	spots[1].spots_per_day.fr = 2;
276 	spots[1].spots_per_day.sa = 0;
277 	spots[1].spots_per_day.su = 0;
278 
279 	order.spots = (struct spot *)&spots;
280 
281 	if (write_file) {
282 	    FMStructDescRec formats[] = {
283 		{"spot_week", spot_week_fields, sizeof(struct spot_week), NULL},
284 		{"spot", spot_fields, sizeof(struct spot), NULL},
285 		{"station_order", station_order_fields, sizeof(struct station_order), NULL},
286 		{NULL, NULL, 0, NULL}};
287 	    write_buffer(write_file, &formats[0], &order, test_num);
288 	}
289 	cod_assoc_externs(context, externs);
290 	cod_parse_for_context(extern_string, context);
291 
292 	if (read_file) {
293 	    FMFieldList fields = NULL;
294 	    FMContext c = create_local_FMcontext();
295 	    char *buf = read_buffer(c, read_file, test_num);
296 	    param = (struct station_order *)buf;
297 	    cod_add_encoded_param("order", buf, 0, c, context);
298 	    cod_add_simple_struct_type("spot_week", spot_week_fields, context);
299 	    cod_add_simple_struct_type("spot", spot_fields, context);
300 	    cod_add_simple_struct_type("station_order2", station_order_fields, context);
301 	    cod_add_param("order_out", "station_order2", 1, context);
302 	} else {
303 	    cod_add_simple_struct_type("spot_week", spot_week_fields, context);
304 	    cod_add_simple_struct_type("spot", spot_fields, context);
305 	    cod_add_simple_struct_type("station_order", station_order_fields, context);
306 	    cod_subroutine_declaration("void proc(station_order *order, station_order *order_out)", context);
307 
308 	}
309 	gen_code = cod_code_gen(code, context);
310 	func = (void (*)(void*,void*))(long)gen_code->func;
311 	memset(&out_order, 0, sizeof(out_order));
312 	(func)((void*)param, (void*)&out_order);
313 	if (out_order.station_id != order.station_id) {
314 	    fprintf(stderr, "Missed station_id\n");
315 	    return 1;
316 	}
317 
318 	if (strcmp(out_order.task_name, order.task_name) != 0) {
319 	    fprintf(stderr, "Missed task_name\n");
320 	    return 1;
321 	}
322 
323 	if (out_order.spot_count != 4) {
324 	    fprintf(stderr, "Missed spot_count\n");
325 	    return 1;
326 	}
327 	if (out_order.spots[0].program_id != NULL) {
328 	    fprintf(stderr, "Spots[0] not NULL\n");
329 	    return 1;
330 	}
331 	if (strcmp(out_order.spots[1].program_id, "Dance Fever") != 0) {
332 	    fprintf(stderr, "Spots[1] not right\n");
333 	    return 1;
334 	}
335 	if (strcmp(out_order.spots[2].program_id, "Gilligan's Island") != 0) {
336 	    fprintf(stderr, "Spots[2] not right\n");
337 	    return 1;
338 	}
339 	if (out_order.spots[3].program_id != NULL) {
340 	    fprintf(stderr, "Spots[3] not NULL\n");
341 	    return 1;
342 	}
343 	free(out_order.spots[2].program_id);
344 	free(out_order.spots[1].program_id);
345 	free(out_order.spots[0].program_id);
346 	free(out_order.spots);
347 	free(out_order.task_name);
348 	cod_code_free(gen_code);
349 	cod_free_parse_context(context);
350     }
351     return 0;
352 }
353