text: #include "config.h"
  #include <assert.h>
  #include <fcntl.h>
  #ifdef STDC_HEADERS
  #include <stdlib.h>
  #endif
  #ifdef HAVE_MEMORY_H
  #include <memory.h>
  #endif
  #ifdef HAVE_MALLOC_H
  #include <malloc.h>
  #endif
  #include <stdio.h>
  #include <string.h>
  #include "ffs.h"
  
  #include "test_funcs.h"
  
  static int verbose = 0;
  static char *test_only = NULL;
  
  int
  size_func_sizeof(iofile, size)
  FFSFile iofile;
  int size;
  {
      return size;
  }
  
  int
  size_func_next_size(iofile, size)
  FFSFile iofile;
  int size;
  {
      return FFSfile_next_decode_length(iofile);
  }
  
  attr_list last_attrs = NULL;
  
  int
  read_func_no_buffer(iofile, data, size)
  FFSFile iofile;
  void *data;
  int size;
  {
      return FFSread_attr(iofile, data, &last_attrs);
  }
  
  int
  read_func_buffer(iofile, data, size)
  FFSFile iofile;
  void *data;
  int size;
  {
      FFSBuffer b = create_fixed_FFSBuffer(data, size);
      int ret = FFSread_to_buffer(iofile, b, NULL);
      free(b);
      last_attrs = FFSattrs_from_last_read(iofile);
      return ret;
  }
  
  
  static FFSTypeHandle first_rec_ioformat, second_rec_ioformat, third_rec_ioformat;
  static FFSTypeHandle fourth_rec_ioformat, later_rec_ioformat, nested_rec_ioformat;
  static FFSTypeHandle fifth_rec_ioformat, sixth_rec_ioformat;
  static FFSTypeHandle ninth_rec_ioformat, string_array_ioformat, derive_ioformat;
  static FFSTypeHandle multi_array_ioformat, triangle_ioformat, add_action_ioformat;
  static FFSTypeHandle node_ioformat, embedded_rec_ioformat;
  
  static void
  set_targets(context)
  FFSContext context;
  {
      if ((test_only == NULL) || (strcmp(test_only, "first_rec") == 0))
  	first_rec_ioformat = FFSset_fixed_target(context, first_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "second_rec") == 0))
  	second_rec_ioformat = FFSset_fixed_target(context, string_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "third_rec") == 0))
  	third_rec_ioformat = FFSset_fixed_target(context, two_string_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "fourth_rec") == 0))
  	fourth_rec_ioformat = FFSset_fixed_target(context, fourth_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "fifth_rec") == 0))
  	fifth_rec_ioformat = FFSset_fixed_target(context, structured_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "sixth_rec") == 0))
  	sixth_rec_ioformat = FFSset_fixed_target(context, variant_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "later_rec") == 0))
  	later_rec_ioformat = FFSset_fixed_target(context, later_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "nested_rec") == 0))
  	nested_rec_ioformat = FFSset_fixed_target(context, nested_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "ninth_rec") == 0))
  	ninth_rec_ioformat = FFSset_fixed_target(context, ninth_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "string_array") == 0))
  	string_array_ioformat = FFSset_fixed_target(context, string_array_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "derive") == 0))
  	derive_ioformat = FFSset_fixed_target(context, derive_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "multi_array") == 0))
  	multi_array_ioformat = FFSset_fixed_target(context, multi_array_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "triangle_param") == 0))
  	triangle_ioformat = FFSset_fixed_target(context, triangle_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "add_action") == 0))
  	add_action_ioformat = FFSset_fixed_target(context, add_action_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "node") == 0))
  	node_ioformat = FFSset_fixed_target(context, node_format_list);
      if ((test_only == NULL) || (strcmp(test_only, "embedded") == 0))
  	embedded_rec_ioformat = FFSset_fixed_target(context, embedded_format_list);
  }
  
  void
  do_test(input_file, size_func, read_func)
  char *input_file;
  int (*size_func) (FFSFile, int);
  int (*read_func) ();
  {
      FFSFile iofile;
      int item_count = 0;
      int data_count = 0;
      int finished = 0;
      int first_rec_count = 0;
      int second_rec_count = 0;
      int third_rec_count = 0;
      int fourth_rec_count = 0;
      int fifth_rec_count = 0;
      int sixth_rec_count = 0;
      int nested_rec_count = 0;
      int later_rec_count = 0;
      int ninth_rec_count = 0;
      int string_array_rec_count = 0;
  
      int unknown_rec_count = 0;
      atom_t iteration_atom = attr_atom_from_string("iteration");
      iofile = open_FFSfile(input_file, "rR");
  
      if (!iofile) {
  	printf("Open of file \"%s\" failed.  Exitting.\n", input_file);
  	exit(1);
      }
  
      init_written_data();
  
      set_targets(FFSContext_of_file(iofile));
      
  
      while (!finished) {
  	char *comment;
  	FFSRecordType next;
  
  	if (data_count == 5) {
  	    FFSseek(iofile, 0);  /* seek backwards to first data item */
  	    first_rec_count = 0;
  	    second_rec_count = 0;
  	    fifth_rec_count = 0;
  	}
  
  	next = FFSnext_record_type(iofile);
  	switch (next) {
  	case FFSindex:
  	    assert(0);
  	case FFScomment:
  	    comment = FFSread_comment(iofile);
  	    if (verbose)  printf("Got a comment %s\n", comment);
  	    break;
  	case FFSformat:
  	    /* ignore format, get to the next data record */
  	    if (verbose)  printf("Got a Format\n");
  	    (void) FFSnext_type_handle(iofile);
  	    break;
  	case FFSdata:
  	    if (verbose) 
  		printf("Record of format %s\n",
  		       FFSTypeHandle_name(FFSnext_type_handle(iofile)));
  	    if (FFSnext_type_handle(iofile) == first_rec_ioformat) {
  		first_rec read_data[10];
  		attr_list attr;
  		int iter_attr = -1;
  		memset(&read_data[0], 0, sizeof(first_rec));
  		if (!FFSread_attr(iofile, &read_data[0], &attr))
  		    printf("read first data");
  		if (verbose && attr) dump_attr_list(attr);
  		get_int_attr(attr, iteration_atom, &iter_attr);
  		if ((memcmp(&read_data[0], &rec1_array[first_rec_count++],
  			    sizeof(first_rec)) != 0) || (iter_attr != rec1_attr_val[first_rec_count-1])) {
  		    if (read_data[0].integer_field != 
  			rec1_array[first_rec_count-1].integer_field) {
  			printf("read integer = %d (0x%x), exp integer = %d"
                                 " (0x%x)\n",
  			       read_data[0].integer_field, 
  			       read_data[0].integer_field, 
  			       rec1_array[first_rec_count-1].integer_field,
  			       rec1_array[first_rec_count-1].integer_field);
  		    }
  		    if (read_data[0].double_field != 
  			rec1_array[first_rec_count-1].double_field) {
  			printf("read double = %g, exp double = %g\n",
  			       read_data[0].double_field, 
  			       rec1_array[first_rec_count-1].double_field);
  		    }
  		    if (read_data[0].char_field != 
  			rec1_array[first_rec_count-1].char_field) {
  			printf("read char = %c, exp char = %c\n",
  			       read_data[0].char_field, 
  			       rec1_array[first_rec_count-1].char_field);
  		    }
  		    if (iter_attr != rec1_attr_val[first_rec_count-1]) {
  			printf("iteration attribute = %d, exp %d\n", iter_attr, rec1_attr_val[first_rec_count-1]);
  		    }
  		    printf("Rec1 failure at count %d\n", first_rec_count-1);
  		    exit(1);
  		}
  	    } else if (FFSnext_type_handle(iofile) == second_rec_ioformat) {
  		int size = size_func(iofile, sizeof(second_rec));
  		second_rec *read_data = malloc(size);
  		int iter_attr = -1;
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read second data failed\n");
  		get_int_attr(FFSattrs_from_last_read(iofile), iteration_atom, &iter_attr);
  		if (!second_rec_eq(read_data, &rec2_array[second_rec_count]) || 
  		    (iter_attr != rec2_attr_val[second_rec_count])) {
  		    if (iter_attr != rec2_attr_val[second_rec_count]) {
  			printf("iteration attribute = %d, exp %d\n", iter_attr, rec1_attr_val[second_rec_count]);
  		    }
  		    printf("Rec2 failure at index %d\n", second_rec_count);
  		    exit(1);
  		}
  		second_rec_count++;
  		free(read_data);
  	    } else if (FFSnext_type_handle(iofile) == third_rec_ioformat) {
  		int size = size_func(iofile, sizeof(third_rec));
  		third_rec *read_data = malloc(size);
  		int iter_attr = -1;
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read third data failed\n");
  		get_int_attr(FFSattrs_from_last_read(iofile), iteration_atom, &iter_attr);
  		if (!third_rec_eq(read_data, &rec3_array[third_rec_count]) ||
  		    (iter_attr != rec3_attr_val[third_rec_count])) {
  		    printf("Rec3 failure\n");
  		    exit(1);
  		}
  		free(read_data);
  		third_rec_count++;
  	    } else if (FFSnext_type_handle(iofile) == fourth_rec_ioformat) {
  		int size = size_func(iofile, sizeof(fourth_rec));
  		fourth_rec *read_data = malloc(size);
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read fourth data failed\n");
  		if (!fourth_rec_eq(read_data, &rec4)) {
  		    printf("Rec4 failure\n");
  		    exit(1);
  		}
  		free(read_data);
  		fourth_rec_count++;
  	    } else if (FFSnext_type_handle(iofile) == embedded_rec_ioformat) {
  
  		printf("Emb Rec failure\n");
  		FFSread(iofile, NULL);
  	    } else if (FFSnext_type_handle(iofile) == fifth_rec_ioformat) {
  		int size = size_func(iofile, sizeof(fifth_rec));
  		fifth_rec *read_data = malloc(size);
  		int iter_attr = -1;
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read fifth data failed\n");
  		get_int_attr(last_attrs, iteration_atom, &iter_attr);
  		if (!fifth_rec_eq(read_data, &rec5) || (iter_attr != rec5_attr_val)) {
  		    printf("Rec5 failure\n");
  		    exit(1);
  		}
  		free(read_data);
  		fifth_rec_count++;
  	    } else if (FFSnext_type_handle(iofile) == sixth_rec_ioformat) {
  		int size = size_func(iofile, sizeof(sixth_rec));
  		sixth_rec *read_data = malloc(size);
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read variant format failed\n");
  		if (!sixth_rec_eq(read_data, &rec6_array[sixth_rec_count++])) {
  		    printf("Rec6 failure\n");
  		    exit(1);
  		}
  		free(read_data);
  	    } else if (FFSnext_type_handle(iofile) == nested_rec_ioformat) {
  		int size = size_func(iofile, sizeof(nested_rec));
  		nested_rec *read_data = malloc(size);
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read variant format");
  		if (!nested_rec_eq(read_data,
                                     &rec7_array[nested_rec_count++])) {
  		    printf("Rec7 failure\n");
  		    exit(1);
  		}
  		free(read_data);
  	    } else if (FFSnext_type_handle(iofile) == later_rec_ioformat) {
  		int size = size_func(iofile, sizeof(later_rec));
  		later_rec *read_data = malloc(size);
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read variant format");
  		if (!later_rec_eq(read_data, &rec8_array[later_rec_count++])) {
  		    printf("Rec8 failure\n");
  		    exit(1);
  		}
  		free(read_data);
  	    } else if (FFSnext_type_handle(iofile) == ninth_rec_ioformat) {
  		int size = size_func(iofile, sizeof(ninth_rec));
  		ninth_rec *read_data = malloc(size);
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read variant format");
  		if (!ninth_rec_eq(read_data, &rec9_array[ninth_rec_count++])) {
  		    printf("Rec9 failure\n");
  		    exit(1);
  		}
  		free(read_data);
  	    } else if (FFSnext_type_handle(iofile) == string_array_ioformat) {
  		int size = size_func(iofile, sizeof(string_array_rec));
  		string_array_rec *read_data = malloc(size);
  		memset(read_data, 0, size);
  		if (!read_func(iofile, read_data, size))
  		    printf("read variant format");
  		if (!string_array_eq(read_data, &string_array_array
                                       [string_array_rec_count++])) {
  		    printf("string_array failure\n");
  		    exit(1);
  		}
  		free(read_data);
  
  	    } else {
  		if (test_only == NULL) {
  		    printf("discarding a record\n");
  		}
  		FFSread(iofile, NULL);
  		unknown_rec_count++;
  	    }
  	    data_count++;
  	    break;
  	case FFSerror:
  	case FFSend:
  	    finished++;
  	    break;
  	}
  	item_count++;
      }
  
      close_FFSfile(iofile);
      free_FFSfile(iofile);
      free_written_data();
      if (first_rec_count != 3) {
  	printf("Missed first, expected 3, got %d\n", first_rec_count);
  	exit(1);
      }
      if (second_rec_count != sizeof(rec2_array) / sizeof(rec2_array[0])) {
  	printf("Missed second\n");
  	exit(1);
      }
      if (third_rec_count != sizeof(rec3_array) / sizeof(rec3_array[0])) {
  	printf("Missed third\n");
  	exit(1);
      }
      if (fourth_rec_count != 1) {
  	printf("Missed fourth\n");
  	exit(1);
      }
      if (fifth_rec_count != 1) {
  	printf("Missed fifth, expected 1, got %d\n", fifth_rec_count);
  	exit(1);
      }
      if (sixth_rec_count != sizeof(rec6_array) / sizeof(rec6_array[0])) {
  	printf("Missed sixth\n");
  	exit(1);
      }
      if (nested_rec_count != sizeof(rec7_array) / sizeof(rec7_array[0])) {
  	printf("Missed sixth\n");
  	exit(1);
      }
      if (later_rec_count != 3) {
  	printf("Missed later\n");
  	exit(1);
      }
      if (unknown_rec_count != 0) {
  	printf("Got unknown\n");
  	exit(1);
      }
      if (ninth_rec_count != 5) {
  	printf("missed rec9\n");
  	exit(1);
      }
      if ((string_array_rec_count != 5) && (string_array_rec_count != 0)){
  	printf("missed string_array\n");
  	exit(1);
      }
  }
  
  
  int
  main(argc, argv)
  int argc;
  char **argv;
  {
      int i;
      char *input_file = "test_output";
  
      for (i = 1; i < argc; i++) {
  	if (argv[i][0] == '-') {
  	    /* argument */
  	    if (argv[i][1] == 'v') {
  		verbose++;
  	    } else if (argv[i][1] == 't') {
  		test_only = argv[++i];
  	    } else {
  		printf("Unknown argument \"%s\"\n", argv[i]);
  	    }
  	} else {
  	    input_file = argv[i];
  	}
      }
      do_test(input_file, size_func_sizeof, read_func_no_buffer);
      do_test(input_file, size_func_next_size, read_func_buffer);
      return 0;
  }
  