# NAME: convstruct.pl
# AIM: Convert a GCC structure declaration to one compatible with MSVC
#
# 20090827 - some improvements - seems to be working well. One idea would be
# to have more than 1 structure definition hash, and thus be able to 'decode'
# different instance declarations. And then combine instance declaration, and handle
# each separatel... and finally, simply read the C/H files directly ;=))
#
# 8/21/2009 - geoff mclane - http://geoffair.net/mperl/
use strict;
use warnings;
# use Data::Dumper;
unshift(@INC, 'C:/GTools/perl');
require 'logfile.pl' or die "Unable to load logfile.pl ...\n";
# log file stuff
my ($LF);
my $pgmname = $0;
if ($pgmname =~ /\w{1}:\\.*/) {
	my @tmpsp = split(/\\/,$pgmname);
	$pgmname = $tmpsp[-1];
}
my $outfile = "temp.$pgmname.txt";
open_log($outfile);

my $out_file = 'tempstruct.txt';
my $in_file = "convstruct.txt";   # instance text
my $done_file = 'convstruct-done.txt';

# features
my $twinvq_spl = -1;
my $do_test_num = $twinvq_spl; # test 1 to 18... or $twinvq_spl
my $load_out = 1;	# load the file written
my $load_log = 1;	# load the LOG file contents
my $do_multi_sets = 0;  # load of MULTIPLE structure, keeping each in a hash HoH
my $strip_comments = 1; # strip comments from instance string

my $twinvq_str = 'twinvq_str.txt';
my $twinvq_inst = 'twinvq_inst.txt';


# some debug groups
my $dbg_str_parse   = 0; # like set_debug_on_str_parse() if ($dbg_str_parse);	# MAKE building structure VERY NOISY
my $dbg_fill_action = 0; # like set_debug_on_fill_str() if ($dbg_fill_action);	# make the filling of values VERY NOISY
# and to gen a NULL/0 set
my $gen_null_set = 0;  # load all defineds structures, and generate a NULL for each
my @gen_null_for = qw( DVprofile );
#my @gen_null_for = qw( AVInputFormat AVOutputFormat );
#my @gen_null_for = qw( AVCodec );
#my @gen_null_for = qw( URLProtocol );

my $inst_indent = "   ";
my $memb_indent = "   ";
my $max_spacing_out = 60;
my $max_spacing_out2 = 48;

# FEATURE (BIT) FLAGS
my $FF_COMM = 1;	# add comment after member - default as '//...' comment type
my $FF_COM1 = 2;	# add comment after member using '/*...*/' comment type
my $FF_COMA = 4;	# if add comments using '/*...*/, fill to align end
my $FF_SORG = 8;	# add show of ORIGINAL line
my $FF_MSCV = 16; # add #ifdef _MSC_VER to output string
my $FF_MSC2 = 32; # extract .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0},
my $FF_MSC3 = 64;  # fix (enum PixelFormat[]) {PIX_FMT_YUV411P, PIX_FMT_YUV422P, PIX_FMT_YUV420P, PIX_FMT_NONE},
my $FF_MSC4 = 128; # fix .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
my $FF_MSC5 = 256; # fix like .channel_layouts = (int64_t[]){CH_LAYOUT_MONO,CH_LAYOUT_STEREO,...},
my $FF_BLLN = 512; # fix - try to break LONG lines
my $max_long = 100; # if it contains ',' and is longer than this

my $FF_NIND = 2048; # no indenting
my $FF_NHED = 4096;  # no heading
my $FF_INLN = 6192; # no newline in stream

# these are only added under certain program conditions
my $FF_WPOS = 16384;	# this member has a specific position
my $FF_BLAN = 32768;	# generate a BLANK instance block
my $FF_WNUM = 65536;	# we have an instance with set number of blocks in head

my $FF_MSVC_SET = ($FF_MSCV | $FF_MSC2 | $FF_MSC3 | $FF_MSC4 | $FF_MSC5 | $FF_BLLN);

# bit flags to modify member construction = 1 = put member name 2 = use /* ... */
my $features = ($FF_COMM | $FF_COM1 | $FF_COMA | $FF_MSVC_SET );	

my $use_copy_hash = 1;
my $bad_posn = -200;

# MEMBER ARRAY
my $str_tag = 'TAG';
my $mem_bgn = 'member'; # plus a number
my $str_nam = 'NAME';	# name of 'structure'
my $mem_cnt = "MEMBER_COUNT";	# count of members in structure
my $mem_nxt = "NEXT_MEMEBR";	# and NEXT member

# DECLARATION - like
# Master - Note a 'master' ONLY contains ONE filled instance, but that 'instance' can consist of more
# than ONE block, inst_name[NUMBER], in which case $mast_len contains this number
# BUT the 'master' can also contain lots of NON-filled other structure definitions
# ====================================================================================================
my $mast_inst = 'INSTANCE';	# name of 'instance' as a FULL LINE like 'str_name inst_name [] = {'...
my $mast_iname = 'INAME';     # specific NAME of instance, like 'wav_muxer'...
my $mast_len = 'LENGTH';      # block count of instances, if any, like inst_name[NUMBER] = {
my $mast_copied = 'COPIED';   # count of FILLED members COPIED to master

# Blocks
my $str_off = 'OFFSET';	# to place the block member at a specific OFFSET, in a group of BLOCK
my $str_done = 'DONE';
# Enumeration of values, like [AAA]
my $str_enum = 'ENUMERATION';

# offsets into members array
my $O_TYP = 0;	# member type - int, uint8_t, enum AVCod *, ...etc
my $O_NAM = 1;	# member name - if a function pointer '(*func)(int a,...)'
my $O_ORG = 2;	# original structure line
my $O_VAL = 3;	# value found
my $O_DEC = 4;  # declaration line
my $O_FNM = 5;	# if a function pointer, like (*foo)(int a, char *p, ...), then 'foo' - it simple name here
my $O_BIT = 6; # if a member is 'name : number' bits, then this contains the BITS number, else -1

# decode BIT fsflags used in sub add_line_2_hash
my $F_HADID  = 1;
my $F_HADEND = 2;
my $F_HADDOT = 4;
my $F_HADMEM = 8; # added at least ONE member to the HASH

# level dependant things kept
my $L_EQU = 0;	# equal sign
my $L_CMA = 1;	# comma
my $L_DOT = 2;	# dot
my $L_QOT = 3;	# double quotes
my $L_QT1 = 4;  # single quotes
my $L_BRA = 5;  # inc on '(' dec on ')'
my $L_BRC = 6;  # inc on '{' dec on '}'
my $L_SQU = 7;  # inc on '[' dec on ']'

my ($act_href);
my ($mast_ref_hoh);

# DEBUG
# a test and exit
my $test_only = 0;
# keyed to the structure name

# individual debug actions
my $dbg_spl = 1;  # to show something special
my $dbgext = 0; # show lots of stages in decode of structure - 
my $dbg00 = 0;	# show prt("$lnn: deal with member [$line], split=$ac, type=$typ, next=$nxt\n" ) if ($dbg00);
my $dbg01 = 0;	# show each line of structure 
my $dbg02 = 0;	# show structure collected...
my $dbg03 = 0;	# show def re-lining
my $dbg04 = 0;	# show discarded comments in building structure members
my $dbg05 = 0;	# show discarded comments 1 /*...*/ in filling structure
my $dbg06 = 0;	# show discarded comments 2 // to EOL in filling structure
my $dbg07 = 0;  # show prt( "Added [$equ] to key [$key], for off[$off]\n" )
my $dbg08 = 0;  # show each line in structure filling
my $dbg09 = 0;	# show level information
my $dbg10 = 0;	# call show_full_hash_of_hashes( $rfullhash ) if ($dbg10);
my $dbg11 = 0;	# show discarded comments in enum parsing
my $dbg12 = 0;	# show brace stack levels
my $dbg13 = 0;	# show prt( "$msg:$lvl: [$ln]\n" ) if ($dbg13); in sub deal_with_enum_line($$$$$) {
my $dbg14 = 0;	# show the resultant HASH after enumeration parse - prt("***************\n".show_enum_hash(0,$rpf)....
my $dbg15 = 0;	# show prt("WARNING: [$k]=[$v], NOT [$wd]!\n"); for missed 'NAME' in hash
my $dbg16 = 0;	# show $msg = "Checking [$word] ";
my $dbg17 = 0;	# for $msg .= "$key => Enumeration HASH - $c2 items\n"; show each enumeration
my $dbg18 = 0;  # show block messages - open and close BLOCK - like prt( "$lnn:$lvl: Open new BLOCK... on [$ln]\n")...
my $dbg19 = 0;	# show prt( "$lnn:$lvl: [$ln] as offset [$off]\n");
my $dbg20 = 0;	# show 	prt("Add [$ln] to hash...\n")...
my $dbg21 = 0;	# show prt("[dbg21] Got length [$snum](".length($snum).") - decode or lookup in enum...\n")...
my $dbg22 = 0; # show prt("Doing is id - split $al...\n");
my $dbg23 = 0; # show prt("[dbg23] $lnn:deal_with_member: got BITS split name=[$sec], bits=[$bit]\n") if ($dbg23);
my $dbg24 = 0; # show prt( "\n[dbg24] Display of $c structures loaded...\n" ); and each structure
my $dbg25 = 0; # show prt( "[dbg25] Bulding structure hash... $len chars...\n" ) if ($dbg25);
my $dbg26 = 0; # show prt("[dbg26] Start of structure: [$msg]\n") if ($dbg26);
my $dbg27 = 0; # show prt("[dbg27] Closing: $msg\n") if ($dbg27); + line number, and word found = structure NAME
my $dbg28 = 0; # show prt("[dbg28] get_total_block: key=[$k] has value [$t]\n") if ($dbg28);
my $dbg29 = 0; # show prt( "[dbg29] Get struct instance string - total=$len, not-unique=$nuniq, blk/pos=$pcnt copied=$imax\n" );
my $dbg30 = 0; # show prt( "[dbg30] Keys:[$msg]\n");
my $dbg31 = 1; # show prt( "[dbg31] Returning potential name [$tg], from [$tx]\n" ) if ($dbg31);

my @res_words = qw( static typedef struct unsigned int enum const char uint8_t short uint16_t long uint32_t int64_t );
my @warnings = ();

sub get_dbg_str() {
	my $str = '';
	if ($dbgext) { $str .= "ext "; } # show lots of stages in decode of structure - 
	if ($dbg00) { $str .= "00 "; }	# show prt("$lnn: deal with member [$line], split=$ac, type=$typ, next=$nxt\n" ) if ($dbg00);
	if ($dbg01) { $str .= "01 "; }	# show each line of structure 
	if ($dbg02) { $str .= "02 "; }	# show structure collected...
	if ($dbg03) { $str .= "03 "; }	# show def re-lining
	if ($dbg04) { $str .= "04 "; }	# show discarded comments in building structure members
	if ($dbg05) { $str .= "05 "; }	# show discarded comments 1 /*...*/ in filling structure
	if ($dbg06) { $str .= "06 "; }	# show discarded comments 2 // to EOL in filling structure
	if ($dbg07) { $str .= "07 "; }  # show prt( "Added [$equ] to key [$key], for off[$off]\n" )
	if ($dbg08) { $str .= "08 "; }  # show each line in structure filling
	if ($dbg09) { $str .= "09 "; }	# show level information
	if ($dbg10) { $str .= "10 "; }	# call show_full_hash_of_hashes( $rfullhash ) if ($dbg10);
	if ($dbg11) { $str .= "11 "; }	# show discarded comments in enum parsing
	if ($dbg12) { $str .= "12 "; }	# show brace stack levels
	if ($dbg13) { $str .= "13 "; }	# show prt( "$msg:$lvl: [$ln]\n" ) if ($dbg13); in sub deal_with_enum_line
	if ($dbg14) { $str .= "14 "; }	# show the resultant HASH after enumeration parse - prt("***************\n".show_enum_hash(0,$rpf)....
	if ($dbg15) { $str .= "15 "; }	# show prt("WARNING: [$k]=[$v], NOT [$wd]!\n"); for missed 'NAME' in hash
	if ($dbg16) { $str .= "16 "; }	# show $msg = "Checking [$word] ";
	if ($dbg17) { $str .= "17 "; }	# for $msg .= "$key => Enumeration HASH - $c2 items\n"; show each enumeration
	if ($dbg18) { $str .= "18 "; }  # show block messages - open and close BLOCK - like prt( "$lnn:$lvl: Open new BLOCK... on [$ln]\n") if ($dbg18);
	if ($dbg19) { $str .= "19 "; }	# show prt( "$lnn:$lvl: [$ln] as offset [$off]\n");
	if ($dbg20) { $str .= "20 "; }	# show 	prt("Add [$ln] to hash...\n") if ($dbg20);
	if ($dbg21) { $str .= "21 "; }	# show prt("[dbg21] Got length [$snum](".length($snum).") - decode or lookup in enum...\n") if ($dbg21);
   if ($dbg22) { $str .= "22 "; } # show prt("Doing is id - split $al...\n");
   if ($dbg23) { $str .= "23 "; } # show prt("[dbg23] $lnn:deal_with_member: got BITS split name=[$sec], bits=[$bit]\n") if ($dbg23);
   if ($dbg24) { $str .= "24 "; } # show prt( "\n[dbg24] Display of $c structures loaded...\n" ); and each structure
   if ($dbg25) { $str .= "24 "; } # show prt( "[dbg25] Bulding structure hash... $len chars...\n" ) if ($dbg25);
   if ($dbg26) { $str .= "26 "; } # show prt("[dbg26] Start of structure: [$msg]\n") if ($dbg26);
   if ($dbg27) { $str .= "27 "; } # show prt("[dbg27] Closing: $msg\n") if ($dbg27); + line number, and word found = structure NAME
   if ($dbg28) { $str .= "28 "; } # show prt("[dbg28] get_total_block: key=[$k] has value [$t]\n") if ($dbg28);
   if ($dbg29) { $str .= "29 "; } # show prt( "[dbg29] Get struct instance string - total=$len, not-unique=$nuniq, blk/pos=$pcnt copied=$imax\n" );
   if ($dbg30) { $str .= "30 "; } # show prt( "[dbg30] Keys:[$msg]\n");
   if ($dbg31) { $str .= "31 "; } # show prt( "[dbg31] Returning potential name [$tg], from [$tx]\n" ) if ($dbg31);
	return $str;
}

sub prtw($) {
	my ($txt) = shift;
	prt($txt);
	$txt =~ s/\n$//;
	push(@warnings,$txt);
}

sub show_warnings() {
    if (@warnings) {
        prt( "\nGot ".scalar @warnings." WARNINGS ...\n" );
        foreach my $line (@warnings) {
            prt("$line\n" );
        }
    } else {
        prt("\nNo warnings issued.\n");
    }
	my $s = get_dbg_str();
	prt( "WARNING: DEBUG ON [$s]\n" ) if length($s);
    prt("\n");
}

sub my_exit($$) {
   my ($ret,$msg) = @_;
   prt($msg) if (length($msg));
   show_warnings();
   close_log($outfile,$load_log);
   exit($ret);
}

sub word_in_array($$) {
	my ($wd,$rar) = @_;
	foreach my $w (@{$rar}) {
		if ($w eq $wd) {
			return 1;
		}
	}
	return 0;
}

sub word_in_res_words($) {
	my ($wd) = shift;
	return word_in_array($wd, \@res_words);
}

sub get_unique_key($) { # ($str_tag) # something like "\@_".$str_tag."_\@", or...
	my ($k) = shift;
	return "!_".$k."_!";
}

sub key_is_unique_type($) { # like say $k =~ /^\@_/, or ...
	my ($k) = shift;
	if ($k =~ /^!_(.+)_!$/) {
		return 1;
	}
	return 0;
}

sub show_struc_defines($$$) {
   my ($call, $rh, $wd) = @_;
   my $msg = "";
   my $caller = (($call == 1) ? "word_is_rh_name: " : "word_is_rh_name_2: ");
   foreach my $k (keys %{$rh}) {
      if ($k =~ /^$mem_bgn/) {
         # $msg .= "{$k}";
      } else {
         $msg .= "\n[$k = ".${$rh}{$k}."]";
      }
   }
   prt( "$caller seeks [$wd], list is == $msg ==\n" );
}

sub get_total_blocks($) {
	my ($rmh) = shift;
	my $k = get_unique_key($mast_len);
	my $t = $bad_posn;
	if (defined ${$rmh}{$k}) {
		$t = ${$rmh}{$k};
      prt("[dbg28] get_total_block: key=[$k] has value [$t]\n") if ($dbg28);
	} else {
      prt("[dbg28] get_total_block: key=[$k] NOT DEFINED\n") if ($dbg28);
   }
	return $t;
}

sub get_copied_count($) {
	my ($rmh) = shift;
	my $k = get_unique_key($mast_copied);
	my $t = $bad_posn;
	if (defined ${$rmh}{$k}) {
		$t = ${$rmh}{$k};
      prt("[dbg28] get_copied_count: key=[$k] has value [$t]\n") if ($dbg28);
	} else {
      prt("[dbg28] get_copied_count: key=[$k] NOT DEFINED\n") if ($dbg28);
   }
	return $t;
}

sub trim_ends($) {
   my ($t) = shift;
   $t = substr($t,1) while ($t =~ /^\s/);	# clear leading
   $t = substr($t,0,length($t)-1) while ($t =~ /\s$/);	# and trailing
   return $t;
}

################################################
# My particular time 'translation'
# 20090904 - added format to add hh:mm:ss (bit 1)
sub YYYYMMDD($$) {
	#  0    1    2     3     4    5     6     7     8
	my ($fm,$tm) = @_;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($tm);
	$year += 1900;
	$mon += 1;
	my $ymd = "$year/";
	if ($mon < 10) {
		$ymd .= '0'.$mon.'/';
	} else {
		$ymd .= "$mon/";
	}
	if ($mday < 10) {
		$ymd .= '0'.$mday;
	} else {
		$ymd .= "$mday";
	}
   if ($fm & 1) {
      $ymd .= " ";
      if ($hour < 10) {
         $ymd .= '0'.$hour;
      } else {
         $ymd .= $hour;
      }
      $ymd .= ':';
      if ($min < 10) {
         $ymd .= '0'.$min;
      } else {
         $ymd .= $min;
      }
      $ymd .= ':';
      if ($sec < 10) {
         $ymd .= '0'.$sec;
      } else {
         $ymd .= $sec;
      }
   }
	return $ymd;
}

sub add_to_done_file($) {
   my ($gcc) = shift;
   my $s = get_dbg_str();
   if (length($s)) {
      prtw( "WARNING: This action NOT added to file [$done_file] due some DEBUG ON!\n" );
      return 0;
   }
   my $tm = YYYYMMDD(1,time());
   $gcc = "// =========================================================\n// $tm\n$gcc";
   $gcc .= "\n" if !($gcc =~ /\n$/);
   $gcc .= "// =========================================================\n";
   if (-f $done_file) {
      append2file($gcc,$done_file);
   } else {
      write2file($gcc,$done_file);
   }
   return 1;
}

######################################################################################################
# ====================================================================================================
# EXAMPLE DATA
# ====================================================================================================

# test 1

my $enum_pixfmt = <<EOF;
enum PixelFormat {
    PIX_FMT_NONE= -1,
    PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
    PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
    PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
    PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
    PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
    PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
    PIX_FMT_YUV410P,   ///< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
    PIX_FMT_YUV411P,   ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
    PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
    PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black
    PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white
    PIX_FMT_PAL8,      ///< 8 bit with PIX_FMT_RGB32 palette
    PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG)
    PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG)
    PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG)
    PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing
    PIX_FMT_XVMC_MPEG2_IDCT,
    PIX_FMT_UYVY422,   ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
    PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
    PIX_FMT_BGR8,      ///< packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)
    PIX_FMT_BGR4,      ///< packed RGB 1:2:1,  4bpp, (msb)1B 2G 1R(lsb)
    PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
    PIX_FMT_RGB8,      ///< packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)
    PIX_FMT_RGB4,      ///< packed RGB 1:2:1,  4bpp, (msb)1R 2G 1B(lsb)
    PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1R 2G 1B(lsb)
    PIX_FMT_NV12,      ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
    PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped

    PIX_FMT_ARGB,      ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
    PIX_FMT_RGBA,      ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
    PIX_FMT_ABGR,      ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
    PIX_FMT_BGRA,      ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...

    PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
    PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
    PIX_FMT_YUV440P,   ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
    PIX_FMT_YUVJ440P,  ///< planar YUV 4:4:0 full scale (JPEG)
    PIX_FMT_YUVA420P,  ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
    PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
    PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
    PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
    PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
    PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
    PIX_FMT_RGB48BE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, big-endian
    PIX_FMT_RGB48LE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, little-endian

    PIX_FMT_RGB565BE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), big-endian
    PIX_FMT_RGB565LE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), little-endian
    PIX_FMT_RGB555BE,  ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0
    PIX_FMT_RGB555LE,  ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0

    PIX_FMT_BGR565BE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), big-endian
    PIX_FMT_BGR565LE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), little-endian
    PIX_FMT_BGR555BE,  ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1
    PIX_FMT_BGR555LE,  ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1

    PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
    PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
    PIX_FMT_VAAPI_VLD,  ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers

    PIX_FMT_YUV420PLE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
    PIX_FMT_YUV420PBE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
    PIX_FMT_YUV422PLE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
    PIX_FMT_YUV422PBE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
    PIX_FMT_YUV444PLE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
    PIX_FMT_YUV444PBE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
    PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
};

EOF

my $struct_details1 = <<EOF;
typedef struct PixFmtInfo {
    const char *name;
    uint8_t nb_channels;     /**< number of channels (including alpha) */
    uint8_t color_type;      /**< color type (see FF_COLOR_xxx constants) */
    uint8_t pixel_type;      /**< pixel storage type (see FF_PIXEL_xxx constants) */
    uint8_t is_alpha : 1;    /**< true if alpha can be specified */
    uint8_t is_hwaccel : 1;  /**< true if this is an HW accelerated format */
    uint8_t x_chroma_shift;  /**< X chroma subsampling factor is 2 ^ shift */
    uint8_t y_chroma_shift;  /**< Y chroma subsampling factor is 2 ^ shift */
    uint8_t depth;           /**< bit depth of the color components */
} PixFmtInfo;

EOF

my $gcc_struct1_short_test = <<EOF;
static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
    /* YUV formats */
    [PIX_FMT_YUV420P] = {
        .name = "yuv420p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_YUV422P] = {
        .name = "yuv422p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 0,
    },
};

EOF

my $gcc_struct1 = <<EOF;
static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
    /* YUV formats */
    [PIX_FMT_YUV420P] = {
        .name = "yuv420p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_YUV422P] = {
        .name = "yuv422p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUV444P] = {
        .name = "yuv444p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUYV422] = {
        .name = "yuyv422",
        .nb_channels = 1,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 0,
    },
    [PIX_FMT_UYVY422] = {
        .name = "uyvy422",
        .nb_channels = 1,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUV410P] = {
        .name = "yuv410p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 2, .y_chroma_shift = 2,
    },
    [PIX_FMT_YUV411P] = {
        .name = "yuv411p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 2, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUV440P] = {
        .name = "yuv440p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 1,
    },
    [PIX_FMT_YUV420PLE] = {
        .name = "yuv420ple",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_YUV422PLE] = {
        .name = "yuv422ple",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
        .x_chroma_shift = 1, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUV444PLE] = {
        .name = "yuv444ple",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUV420PBE] = {
        .name = "yuv420pbe",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_YUV422PBE] = {
        .name = "yuv422pbe",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
        .x_chroma_shift = 1, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUV444PBE] = {
        .name = "yuv444pbe",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },


    /* YUV formats with alpha plane */
    [PIX_FMT_YUVA420P] = {
        .name = "yuva420p",
        .nb_channels = 4,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },

    /* JPEG YUV */
    [PIX_FMT_YUVJ420P] = {
        .name = "yuvj420p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV_JPEG,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_YUVJ422P] = {
        .name = "yuvj422p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV_JPEG,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUVJ444P] = {
        .name = "yuvj444p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV_JPEG,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_YUVJ440P] = {
        .name = "yuvj440p",
        .nb_channels = 3,
        .color_type = FF_COLOR_YUV_JPEG,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 1,
    },

    /* RGB formats */
    [PIX_FMT_RGB24] = {
        .name = "rgb24",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR24] = {
        .name = "bgr24",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_ARGB] = {
        .name = "argb",
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB48BE] = {
        .name = "rgb48be",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 16,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB48LE] = {
        .name = "rgb48le",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 16,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB565BE] = {
        .name = "rgb565be",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB565LE] = {
        .name = "rgb565le",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB555BE] = {
        .name = "rgb555be",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB555LE] = {
        .name = "rgb555le",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },

    /* gray / mono formats */
    [PIX_FMT_GRAY16BE] = {
        .name = "gray16be",
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
    [PIX_FMT_GRAY16LE] = {
        .name = "gray16le",
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 16,
    },
    [PIX_FMT_GRAY8] = {
        .name = "gray",
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
    },
    [PIX_FMT_MONOWHITE] = {
        .name = "monow",
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 1,
    },
    [PIX_FMT_MONOBLACK] = {
        .name = "monob",
        .nb_channels = 1,
        .color_type = FF_COLOR_GRAY,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 1,
    },

    /* paletted formats */
    [PIX_FMT_PAL8] = {
        .name = "pal8",
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PALETTE,
        .depth = 8,
    },
    [PIX_FMT_XVMC_MPEG2_MC] = {
        .name = "xvmcmc",
        .is_hwaccel = 1,
    },
    [PIX_FMT_XVMC_MPEG2_IDCT] = {
        .name = "xvmcidct",
        .is_hwaccel = 1,
    },
    [PIX_FMT_VDPAU_MPEG1] = {
        .name = "vdpau_mpeg1",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_VDPAU_MPEG2] = {
        .name = "vdpau_mpeg2",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_VDPAU_H264] = {
        .name = "vdpau_h264",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_VDPAU_WMV3] = {
        .name = "vdpau_wmv3",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_VDPAU_VC1] = {
        .name = "vdpau_vc1",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_UYYVYY411] = {
        .name = "uyyvyy411",
        .nb_channels = 1,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 2, .y_chroma_shift = 0,
    },
    [PIX_FMT_ABGR] = {
        .name = "abgr",
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR565BE] = {
        .name = "bgr565be",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR565LE] = {
        .name = "bgr565le",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR555BE] = {
        .name = "bgr555be",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR555LE] = {
        .name = "bgr555le",
        .nb_channels = 3,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 5,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB8] = {
        .name = "rgb8",
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB4] = {
        .name = "rgb4",
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGB4_BYTE] = {
        .name = "rgb4_byte",
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR8] = {
        .name = "bgr8",
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR4] = {
        .name = "bgr4",
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 4,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_BGR4_BYTE] = {
        .name = "bgr4_byte",
        .nb_channels = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_NV12] = {
        .name = "nv12",
        .nb_channels = 2,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_NV21] = {
        .name = "nv12",
        .nb_channels = 2,
        .color_type = FF_COLOR_YUV,
        .pixel_type = FF_PIXEL_PLANAR,
        .depth = 8,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },

    [PIX_FMT_BGRA] = {
        .name = "bgra",
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },
    [PIX_FMT_RGBA] = {
        .name = "rgba",
        .nb_channels = 4, .is_alpha = 1,
        .color_type = FF_COLOR_RGB,
        .pixel_type = FF_PIXEL_PACKED,
        .depth = 8,
        .x_chroma_shift = 0, .y_chroma_shift = 0,
    },

    /* VA API formats */
    [PIX_FMT_VAAPI_MOCO] = {
        .name = "vaapi_moco",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_VAAPI_IDCT] = {
        .name = "vaapi_idct",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
    [PIX_FMT_VAAPI_VLD] = {
        .name = "vaapi_vld",
        .is_hwaccel = 1,
        .x_chroma_shift = 1, .y_chroma_shift = 1,
    },
};

EOF

# ====================================================================================================
# test 2

my $struct_details2 = <<EOF;
typedef struct DVprofile {
    int              dsf;                   /* value of the dsf in the DV header */
    int              video_stype;           /* stype for VAUX source pack */
    int              frame_size;            /* total size of one frame in bytes */
    int              difseg_size;           /* number of DIF segments per DIF channel */
    int              n_difchan;             /* number of DIF channels per frame */
    AVRational       time_base;             /* 1/framerate */
    int              ltc_divisor;           /* FPS from the LTS standpoint */
    int              height;                /* picture height in pixels */
    int              width;                 /* picture width in pixels */
    AVRational       sar[2];                /* sample aspect ratios for 4:3 and 16:9 */
    DVwork_chunk    *work_chunks;           /* each thread gets its own chunk of frame to work on */
    uint32_t        *idct_factor;           /* set of iDCT factor tables */
    enum PixelFormat pix_fmt;               /* picture pixel format */
    int              bpm;                   /* blocks per macroblock */
    const uint8_t   *block_sizes;           /* AC block sizes, in bits */
    int              audio_stride;          /* size of audio_shuffle table */
    int              audio_min_samples[3];  /* min amount of audio samples */
                                            /* for 48kHz, 44.1kHz and 32kHz */
    int              audio_samples_dist[5]; /* how many samples are supposed to be */
                                            /* in each frame in a 5 frames window */
    const uint8_t  (*audio_shuffle)[9];     /* PCM shuffling table */
} DVprofile;
EOF

my $gcc_struct2 = <<EOF;
static 
const 
DVprofile dv_profiles[] = {
    { .dsf = 0, // DISCARD THIS TYPE
      .video_stype = 0x0,
      .frame_size = 120000,        /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */
      .difseg_size = 10,
      .n_difchan = 1,
      .time_base = { 1001, 30000 },
      .ltc_divisor = 30,
      .height = 480,
      .width = 720,
      .sar = {{10, 11}, {40, 33}},
      .work_chunks = &work_chunks_dv25ntsc[0],
      .idct_factor = &dv_idct_factor_sd[0],
      .pix_fmt = PIX_FMT_YUV411P,
      .bpm = 6,
      .block_sizes = block_sizes_dv2550,
      .audio_stride = 90,
      .audio_min_samples  = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */
      .audio_shuffle = dv_audio_shuffle525,
    },
    { .dsf = 1,
      .video_stype = 0x0,
      .frame_size = 144000,        /* IEC 61834 - 625/50 (PAL) */
      .difseg_size = 12,
      .n_difchan = 1,
      .time_base = { 1, 25 },
      .ltc_divisor = 25,
      .height = 576,
      .width = 720,
      .sar = {{59, 54}, {118, 81}},
      .work_chunks = &work_chunks_dv25pal[0],
      .idct_factor = &dv_idct_factor_sd[0],
      .pix_fmt = PIX_FMT_YUV420P,
      .bpm = 6,
      .block_sizes = block_sizes_dv2550,
      .audio_stride = 108,
      .audio_min_samples  = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 },
      .audio_shuffle = dv_audio_shuffle625,
    },
    { .dsf = 1,
      .video_stype = 0x0,
      .frame_size = 144000,        /* SMPTE-314M - 625/50 (PAL) */
      .difseg_size = 12,
      .n_difchan = 1,
      .time_base = { 1, 25 },
      .ltc_divisor = 25,
      .height = 576,
      .width = 720,
      .sar = {{59, 54}, {118, 81}},
      .work_chunks = &work_chunks_dv25pal411[0],
      .idct_factor = &dv_idct_factor_sd[0],
      .pix_fmt = PIX_FMT_YUV411P,
      .bpm = 6,
      .block_sizes = block_sizes_dv2550,
      .audio_stride = 108,
      .audio_min_samples  = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 },
      .audio_shuffle = dv_audio_shuffle625,
    },
    { .dsf = 0,
      .video_stype = 0x4,
      .frame_size = 240000,        /* SMPTE-314M - 525/60 (NTSC) 50 Mbps */
      .difseg_size = 10,           /* also known as "DVCPRO50" */
      .n_difchan = 2,
      .time_base = { 1001, 30000 },
      .ltc_divisor = 30,
      .height = 480,
      .width = 720,
      .sar = {{10, 11}, {40, 33}},
      .work_chunks = &work_chunks_dv50ntsc[0],
      .idct_factor = &dv_idct_factor_sd[0],
      .pix_fmt = PIX_FMT_YUV422P,
      .bpm = 6,
      .block_sizes = block_sizes_dv2550,
      .audio_stride = 90,
      .audio_min_samples  = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */
      .audio_shuffle = dv_audio_shuffle525,
    },
    { .dsf = 1,
      .video_stype = 0x4,
      .frame_size = 288000,        /* SMPTE-314M - 625/50 (PAL) 50 Mbps */
      .difseg_size = 12,           /* also known as "DVCPRO50" */
      .n_difchan = 2,
      .time_base = { 1, 25 },
      .ltc_divisor = 25,
      .height = 576,
      .width = 720,
      .sar = {{59, 54}, {118, 81}},
      .work_chunks = &work_chunks_dv50pal[0],
      .idct_factor = &dv_idct_factor_sd[0],
      .pix_fmt = PIX_FMT_YUV422P,
      .bpm = 6,
      .block_sizes = block_sizes_dv2550,
      .audio_stride = 108,
      .audio_min_samples  = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 },
      .audio_shuffle = dv_audio_shuffle625,
    },
    { .dsf = 0,
      .video_stype = 0x14,
      .frame_size = 480000,        /* SMPTE-370M - 1080i60 100 Mbps */
      .difseg_size = 10,           /* also known as "DVCPRO HD" */
      .n_difchan = 4,
      .time_base = { 1001, 30000 },
      .ltc_divisor = 30,
      .height = 1080,
      .width = 1280,
      .sar = {{1, 1}, {1, 1}},
      .work_chunks = &work_chunks_dv100ntsci[0],
      .idct_factor = &dv_idct_factor_hd1080[0],
      .pix_fmt = PIX_FMT_YUV422P,
      .bpm = 8,
      .block_sizes = block_sizes_dv100,
      .audio_stride = 90,
      .audio_min_samples  = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */
      .audio_shuffle = dv_audio_shuffle525,
    },
    { .dsf = 1,
      .video_stype = 0x14,
      .frame_size = 576000,        /* SMPTE-370M - 1080i50 100 Mbps */
      .difseg_size = 12,           /* also known as "DVCPRO HD" */
      .n_difchan = 4,
      .time_base = { 1, 25 },
      .ltc_divisor = 25,
      .height = 1080,
      .width = 1440,
      .sar = {{1, 1}, {1, 1}},
      .work_chunks = &work_chunks_dv100pali[0],
      .idct_factor = &dv_idct_factor_hd1080[0],
      .pix_fmt = PIX_FMT_YUV422P,
      .bpm = 8,
      .block_sizes = block_sizes_dv100,
      .audio_stride = 108,
      .audio_min_samples  = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 },
      .audio_shuffle = dv_audio_shuffle625,
    },
    { .dsf = 0,
      .video_stype = 0x18,
      .frame_size = 240000,        /* SMPTE-370M - 720p60 100 Mbps */
      .difseg_size = 10,           /* also known as "DVCPRO HD" */
      .n_difchan = 2,
      .time_base = { 1001, 60000 },
      .ltc_divisor = 60,
      .height = 720,
      .width = 960,
      .sar = {{1, 1}, {1, 1}},
      .work_chunks = &work_chunks_dv100ntscp[0],
      .idct_factor = &dv_idct_factor_hd720[0],
      .pix_fmt = PIX_FMT_YUV422P,
      .bpm = 8,
      .block_sizes = block_sizes_dv100,
      .audio_stride = 90,
      .audio_min_samples  = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */
      .audio_shuffle = dv_audio_shuffle525,
    },
    { .dsf = 1,
      .video_stype = 0x18,
      .frame_size = 288000,        /* SMPTE-370M - 720p50 100 Mbps */
      .difseg_size = 12,           /* also known as "DVCPRO HD" */
      .n_difchan = 2,
      .time_base = { 1, 50 },
      .ltc_divisor = 50,
      .height = 720,
      .width = 960,
      .sar = {{1, 1}, {1, 1}},
      .work_chunks = &work_chunks_dv100palp[0],
      .idct_factor = &dv_idct_factor_hd720[0],
      .pix_fmt = PIX_FMT_YUV422P,
      .bpm = 8,
      .block_sizes = block_sizes_dv100,
      .audio_stride = 90,
      .audio_min_samples  = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */
      .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 },
      .audio_shuffle = dv_audio_shuffle625,
    }
};

EOF

# ====================================================================================================
# test 3

my $struct_details3 = <<EOF;
/**
 * AVCodec.
 */
typedef struct AVCodec {
    /**
     * Name of the codec implementation.
     * The name is globally unique among encoders and among decoders (but an
     * encoder and a decoder can share the same name).
     * This is the primary way to find a codec from the user perspective.
     */
    const char *name;
    enum CodecType type;
    enum CodecID id;
    int priv_data_size;
    int (*init)(AVCodecContext *);
    int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data);
    int (*close)(AVCodecContext *);
    int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt);
    /**
     * Codec capabilities.
     * see CODEC_CAP_*
     */
    int capabilities;
    struct AVCodec *next;
    /**
     * Flush buffers.
     * Will be called when seeking
     */
    void (*flush)(AVCodecContext *);
    const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}
    const enum PixelFormat *pix_fmts;       ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1
    /**
     * Descriptive name for the codec, meant to be more human readable than name.
     * You should use the NULL_IF_CONFIG_SMALL() macro to define it.
     */
    const char *long_name;
    const int *supported_samplerates;       ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
    const enum SampleFormat *sample_fmts;   ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
    const int64_t *channel_layouts;         ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
} AVCodec;

EOF

my $gcc_struct3_1 = <<EOF;
AVCodec libfaac_encoder = {
    "libfaac",
    CODEC_TYPE_AUDIO,
    CODEC_ID_AAC,
    sizeof(FaacAudioContext),
    Faac_encode_init,
    Faac_encode_frame,
    Faac_encode_close,
    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
    .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Codec)"),
};

EOF

my $gcc_struct3_2 = <<EOF;
AVCodec libfaad2_decoder = {
    .name = "AAC_LATM",
    .type = CODEC_TYPE_AUDIO,
    .id = CODEC_ID_AAC_LATM,
    .priv_data_size = sizeof (FAACContext),
    .init = faac_decode_init,
    .close = faac_decode_end,
    .decode = faac_decode_frame,
    .long_name = "AAC over LATM",
};

EOF

my $gcc_struct3 = <<EOF;
AVCodec ac3_encoder = {
    "ac3",
    CODEC_TYPE_AUDIO,
    CODEC_ID_AC3,
    sizeof(AC3EncodeContext),
    AC3_encode_init,
    AC3_encode_frame,
    AC3_encode_close,
    NULL,
    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
    .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
    .channel_layouts = (int64_t[]){
        CH_LAYOUT_MONO,
        CH_LAYOUT_STEREO,
        CH_LAYOUT_2_1,
        CH_LAYOUT_SURROUND,
        CH_LAYOUT_2_2,
        CH_LAYOUT_QUAD,
        CH_LAYOUT_4POINT0,
        CH_LAYOUT_5POINT0,
        CH_LAYOUT_5POINT0_BACK,
       (CH_LAYOUT_MONO     | CH_LOW_FREQUENCY),
       (CH_LAYOUT_STEREO   | CH_LOW_FREQUENCY),
       (CH_LAYOUT_2_1      | CH_LOW_FREQUENCY),
       (CH_LAYOUT_SURROUND | CH_LOW_FREQUENCY),
       (CH_LAYOUT_2_2      | CH_LOW_FREQUENCY),
       (CH_LAYOUT_QUAD     | CH_LOW_FREQUENCY),
       (CH_LAYOUT_4POINT0  | CH_LOW_FREQUENCY),
        CH_LAYOUT_5POINT1,
        CH_LAYOUT_5POINT1_BACK,
        0 },
};
EOF

# ====================================================================================================
# test 4

my $struct_details4 = <<EOF;
/**
 * Descriptor that unambiguously describes how the bits of a pixel are
 * stored in the up to 4 data planes of an image. It also stores the
 * subsampling factors and number of components.
 *
 * \@note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV
 *       and all the YUV variants) AVPixFmtDescriptor just stores how values
 *       are stored not what these values represent.
 */
typedef struct AVPixFmtDescriptor{
    const char *name;
    uint8_t nb_channels;        ///< The number of components each pixel has, (1-4)

    /**
     * Amount to shift the luma width right to find the chroma width.
     * For YV12 this is 1 for example.
     * chroma_width = -((-luma_width) >> log2_chroma_w)
     * The note above is needed to ensure rounding up.
     */
    uint8_t log2_chroma_w;      ///< chroma_width = -((-luma_width )>>log2_chroma_w)

    /**
     * Amount to shift the luma height right to find the chroma height.
     * For YV12 this is 1 for example.
     * chroma_height= -((-luma_height) >> log2_chroma_h)
     * The note above is needed to ensure rounding up.
     */
    uint8_t log2_chroma_h;
    uint8_t flags;
    AVComponentDescriptor comp[4]; ///< parameters that describe how pixels are packed
}AVPixFmtDescriptor;

// #define PIX_FMT_BE        1 ///< big-endian
// #define PIX_FMT_PAL       2 ///< Pixel format has a palette in data[1], values are indexes in this palette.
// #define PIX_FMT_BITSTREAM 4 ///< All values of a component are bit-wise packed end to end.

EOF



# and of AVCOmponentDecriptor
my $struct_details4a = <<EOF;
typedef struct AVComponentDescriptor{
    uint16_t plane        :2;            ///< which of the 4 planes contains the component

    /**
     * Number of elements between 2 horizontally consecutive pixels minus 1.
     * Elements are bits for bitstream formats, bytes otherwise.
     */
    uint16_t step_minus1  :3;

    /**
     * Number of elements before the component of the first pixel plus 1.
     * Elements are bits for bitstream formats, bytes otherwise.
     */
    uint16_t offset_plus1 :3;
    uint16_t shift        :3;            ///< number of least significant bits that must be shifted away to get the value
    uint16_t depth_minus1 :4;            ///< number of bits in the component minus 1
}AVComponentDescriptor;

EOF

my $gcc_struct4 = <<EOF;
const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = {
    [PIX_FMT_YUV420P] = {
        .name = "yuv420p",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 1,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUYV422] = {
        .name = "yuyv422",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,1,0,7},        /* Y */
            {0,3,2,0,7},        /* U */
            {0,3,4,0,7},        /* V */
        },
    },
    [PIX_FMT_RGB24] = {
        .name = "rgb24",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,2,1,0,7},        /* R */
            {0,2,2,0,7},        /* G */
            {0,2,3,0,7},        /* B */
        },
    },
    [PIX_FMT_BGR24] = {
        .name = "bgr24",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,2,1,0,7},        /* B */
            {0,2,2,0,7},        /* G */
            {0,2,3,0,7},        /* R */
        },
    },
    [PIX_FMT_YUV422P] = {
        .name = "yuv422p",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUV444P] = {
        .name = "yuv444p",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUV410P] = {
        .name = "yuv410p",
        .nb_channels  = 3,
        .log2_chroma_w= 2,
        .log2_chroma_h= 2,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUV411P] = {
        .name = "yuv411p",
        .nb_channels  = 3,
        .log2_chroma_w= 2,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_GRAY8] = {
        .name = "gray8",
        .nb_channels  = 1,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,7},        /* Y */
        },
    },
    [PIX_FMT_MONOWHITE] = {
        .name = "monowhite",
        .nb_channels  = 1,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,0},        /* Y */
        },
        .flags = PIX_FMT_BITSTREAM,
    },
    [PIX_FMT_MONOBLACK] = {
        .name = "monoblack",
        .nb_channels  = 1,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,7,0},        /* Y */
        },
        .flags = PIX_FMT_BITSTREAM,
    },
    [PIX_FMT_PAL8] = {
        .name = "pal8",
        .nb_channels  = 1,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,7},
        },
        .flags = PIX_FMT_PAL,
    },
    [PIX_FMT_YUVJ420P] = {
        .name = "yuvj420p",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 1,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUVJ422P] = {
        .name = "yuvj422p",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUVJ444P] = {
        .name = "yuvj444p",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_UYVY422] = {
        .name = "uyvy422",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,2,0,7},        /* Y */
            {0,3,1,0,7},        /* U */
            {0,3,3,0,7},        /* V */
        },
    },
    [PIX_FMT_UYYVYY411] = {
        .name = "uyyvyy411",
        .nb_channels  = 3,
        .log2_chroma_w= 2,
        .log2_chroma_h= 0,
        .comp = {
            {0,3,2,0,7},        /* Y */
            {0,5,1,0,7},        /* U */
            {0,5,4,0,7},        /* V */
        },
    },
    [PIX_FMT_BGR8] = {
        .name = "bgr8",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,6,1},        /* B */
            {0,0,1,3,2},        /* G */
            {0,0,1,0,2},        /* R */
        },
    },
    [PIX_FMT_BGR4] = {
        .name = "bgr4",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,3,1,0,0},        /* B */
            {0,3,2,0,1},        /* G */
            {0,3,4,0,0},        /* R */
        },
        .flags = PIX_FMT_BITSTREAM,
    },
    [PIX_FMT_BGR4_BYTE] = {
        .name = "bgr4_byte",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,3,0},        /* B */
            {0,0,1,1,1},        /* G */
            {0,0,1,0,0},        /* R */
        },
    },
    [PIX_FMT_RGB8] = {
        .name = "rgb8",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,6,1},        /* R */
            {0,0,1,3,2},        /* G */
            {0,0,1,0,2},        /* B */
        },
    },
    [PIX_FMT_RGB4] = {
        .name = "rgb4",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,3,1,0,0},       /* R */
            {0,3,2,0,1},       /* G */
            {0,3,4,0,0},       /* B */
        },
        .flags = PIX_FMT_BITSTREAM,
    },
    [PIX_FMT_RGB4_BYTE] = {
        .name = "rgb4_byte",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,0,1,3,0},        /* R */
            {0,0,1,1,1},        /* G */
            {0,0,1,0,0},        /* B */
        },
    },
    [PIX_FMT_NV12] = {
        .name = "nv12",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 1,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,1,1,0,7},        /* U */
            {1,1,2,0,7},        /* V */
        },
    },
    [PIX_FMT_NV21] = {
        .name = "nv21",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 1,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,1,1,0,7},        /* V */
            {1,1,2,0,7},        /* U */
        },
    },
    [PIX_FMT_ARGB] = {
        .name = "argb",
        .nb_channels  = 4,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,3,1,0,7},        /* A */
            {0,3,2,0,7},        /* R */
            {0,3,3,0,7},        /* G */
            {0,3,4,0,7},        /* B */
        },
    },
    [PIX_FMT_RGBA] = {
        .name = "rgba",
        .nb_channels  = 4,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,3,1,0,7},        /* R */
            {0,3,2,0,7},        /* G */
            {0,3,3,0,7},        /* B */
            {0,3,4,0,7},        /* A */
        },
    },
    [PIX_FMT_ABGR] = {
        .name = "abgr",
        .nb_channels  = 4,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,3,1,0,7},        /* A */
            {0,3,2,0,7},        /* B */
            {0,3,3,0,7},        /* G */
            {0,3,4,0,7},        /* R */
        },
    },
    [PIX_FMT_BGRA] = {
        .name = "bgra",
        .nb_channels  = 4,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,3,1,0,7},        /* B */
            {0,3,2,0,7},        /* G */
            {0,3,3,0,7},        /* R */
            {0,3,4,0,7},        /* A */
        },
    },
    [PIX_FMT_GRAY16BE] = {
        .name = "gray16be",
        .nb_channels  = 1,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,1,0,15},       /* Y */
        },
        .flags = PIX_FMT_BE,
    },
    [PIX_FMT_GRAY16LE] = {
        .name = "gray16le",
        .nb_channels  = 1,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,1,0,15},       /* Y */
        },
    },
    [PIX_FMT_YUV440P] = {
        .name = "yuv440p",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 1,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUVJ440P] = {
        .name = "yuvj440p",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 1,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
        },
    },
    [PIX_FMT_YUVA420P] = {
        .name = "yuva420p",
        .nb_channels  = 4,
        .log2_chroma_w= 1,
        .log2_chroma_h= 1,
        .comp = {
            {0,0,1,0,7},        /* Y */
            {1,0,1,0,7},        /* U */
            {2,0,1,0,7},        /* V */
            {3,0,1,0,7},        /* A */
        },
    },
    [PIX_FMT_RGB48BE] = {
        .name = "rgb48be",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,5,1,0,15},       /* R */
            {0,5,3,0,15},       /* G */
            {0,5,5,0,15},       /* B */
        },
        .flags = PIX_FMT_BE,
    },
    [PIX_FMT_RGB48LE] = {
        .name = "rgb48le",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,5,1,0,15},       /* R */
            {0,5,3,0,15},       /* G */
            {0,5,5,0,15},       /* B */
        },
    },
    [PIX_FMT_RGB565BE] = {
        .name = "rgb565be",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,0,3,4},        /* R */
            {0,1,1,5,5},        /* G */
            {0,1,1,0,4},        /* B */
        },
        .flags = PIX_FMT_BE,
    },
    [PIX_FMT_RGB565LE] = {
        .name = "rgb565le",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,2,3,4},        /* R */
            {0,1,1,5,5},        /* G */
            {0,1,1,0,4},        /* B */
        },
    },
    [PIX_FMT_RGB555BE] = {
        .name = "rgb555be",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,0,2,4},        /* R */
            {0,1,1,5,4},        /* G */
            {0,1,1,0,4},        /* B */
        },
        .flags = PIX_FMT_BE,
    },
    [PIX_FMT_RGB555LE] = {
        .name = "rgb555le",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,2,2,4},        /* R */
            {0,1,1,5,4},        /* G */
            {0,1,1,0,4},        /* B */
        },
    },
    [PIX_FMT_BGR565BE] = {
        .name = "bgr565be",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,0,3,4},        /* B */
            {0,1,1,5,5},        /* G */
            {0,1,1,0,4},        /* R */
        },
        .flags = PIX_FMT_BE,
    },
    [PIX_FMT_BGR565LE] = {
        .name = "bgr565le",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,2,3,4},        /* B */
            {0,1,1,5,5},        /* G */
            {0,1,1,0,4},        /* R */
        },
    },
    [PIX_FMT_BGR555BE] = {
        .name = "bgr555be",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,0,2,4},       /* B */
            {0,1,1,5,4},       /* G */
            {0,1,1,0,4},       /* R */
        },
        .flags = PIX_FMT_BE,
     },
    [PIX_FMT_BGR555LE] = {
        .name = "bgr555le",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,2,2,4},        /* B */
            {0,1,1,5,4},        /* G */
            {0,1,1,0,4},        /* R */
        },
    },
    [PIX_FMT_YUV420PLE] = {
        .name = "yuv420ple",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 1,
        .comp = {
            {0,1,1,0,15},        /* Y */
            {1,1,1,0,15},        /* U */
            {2,1,1,0,15},        /* V */
        },
    },
    [PIX_FMT_YUV420PBE] = {
        .name = "yuv420pbe",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 1,
        .comp = {
            {0,1,1,0,15},        /* Y */
            {1,1,1,0,15},        /* U */
            {2,1,1,0,15},        /* V */
        },
        .flags = PIX_FMT_BE,
    },
    [PIX_FMT_YUV422PLE] = {
        .name = "yuv422ple",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,1,0,15},        /* Y */
            {1,1,1,0,15},        /* U */
            {2,1,1,0,15},        /* V */
        },
    },
    [PIX_FMT_YUV422PBE] = {
        .name = "yuv422pbe",
        .nb_channels  = 3,
        .log2_chroma_w= 1,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,1,0,15},        /* Y */
            {1,1,1,0,15},        /* U */
            {2,1,1,0,15},        /* V */
        },
        .flags = PIX_FMT_BE,
    },
    [PIX_FMT_YUV444PLE] = {
        .name = "yuv444ple",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,1,0,15},        /* Y */
            {1,1,1,0,15},        /* U */
            {2,1,1,0,15},        /* V */
        },
    },
    [PIX_FMT_YUV444PBE] = {
        .name = "yuv444pbe",
        .nb_channels  = 3,
        .log2_chroma_w= 0,
        .log2_chroma_h= 0,
        .comp = {
            {0,1,1,0,15},        /* Y */
            {1,1,1,0,15},        /* U */
            {2,1,1,0,15},        /* V */
        },
        .flags = PIX_FMT_BE,
    },
};

EOF

# ====================================================================================================
# test 5

my $struct_details5 = <<EOF;
typedef struct BlockNode{
    int16_t mx;
    int16_t my;
    uint8_t ref;
    uint8_t color[3];
    uint8_t type;
/* //#define TYPE_SPLIT    1
#define BLOCK_INTRA   1
#define BLOCK_OPT     2
//#define TYPE_NOCOLOR  4 */
    uint8_t level; //FIXME merge into type?
}BlockNode;

EOF

my $gcc_struct5 = <<EOF;
static const BlockNode null_block= { //FIXME add border maybe
    .color= {128,128,128},
    .mx= 0,
    .my= 0,
    .ref= 0,
    .type= 0,
    .level= 0,
};

EOF

# ====================================================================================================
# test 6

my $struct_details6 = <<EOF;
/**
 * AVHWAccel.
 */
typedef struct AVHWAccel {
    /**
     * Name of the hardware accelerated codec.
     * The name is globally unique among encoders and among decoders (but an
     * encoder and a decoder can share the same name).
     */
    const char *name;

    /**
     * Type of codec implemented by the hardware accelerator.
     *
     * See CODEC_TYPE_xxx
     */
    enum CodecType type;

    /**
     * Codec implemented by the hardware accelerator.
     *
     * See CODEC_ID_xxx
     */
    enum CodecID id;

    /**
     * Supported pixel format.
     *
     * Only hardware accelerated formats are supported here.
     */
    enum PixelFormat pix_fmt;

    /**
     * Hardware accelerated codec capabilities.
     * see FF_HWACCEL_CODEC_CAP_*
     */
    int capabilities;

    struct AVHWAccel *next;

    /**
     * Called at the beginning of each frame or field picture.
     *
     * Meaningful frame information (codec specific) is guaranteed to
     * be parsed at this point. This function is mandatory.
     *
     * Note that buf can be NULL along with buf_size set to 0.
     * Otherwise, this means the whole frame is available at this point.
     *
     * \@param avctx the codec context
     * \@param buf the frame data buffer base
     * \@param buf_size the size of the frame in bytes
     * \@return zero if successful, a negative value otherwise
     */
    int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);

    /**
     * Callback for each slice.
     *
     * Meaningful slice information (codec specific) is guaranteed to
     * be parsed at this point. This function is mandatory.
     *
     * \@param avctx the codec context
     * \@param buf the slice data buffer base
     * \@param buf_size the size of the slice in bytes
     * \@return zero if successful, a negative value otherwise
     */
    int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);

    /**
     * Called at the end of each frame or field picture.
     *
     * The whole picture is parsed at this point and can now be sent
     * to the hardware accelerator. This function is mandatory.
     *
     * \@param avctx the codec context
     * \@return zero if successful, a negative value otherwise
     */
    int (*end_frame)(AVCodecContext *avctx);

    /**
     * Size of HW accelerator private data.
     *
     * Private data is allocated with av_mallocz() before
     * AVCodecContext.get_buffer() and deallocated after
     * AVCodecContext.release_buffer().
     */
    int priv_data_size;
} AVHWAccel;

EOF

my $gcc_struct6_1 = <<EOF;
AVHWAccel mpeg2_vaapi_hwaccel = {
    .name           = "mpeg2_vaapi",
    .type           = CODEC_TYPE_VIDEO,
    .id             = CODEC_ID_MPEG2VIDEO,
    .pix_fmt        = PIX_FMT_VAAPI_VLD,
    .capabilities   = 0,
    .start_frame    = vaapi_mpeg2_start_frame,
    .end_frame      = vaapi_mpeg2_end_frame,
    .decode_slice   = vaapi_mpeg2_decode_slice,
    .priv_data_size = 0,
};

EOF

#if CONFIG_MPEG4_VAAPI_HWACCEL
my $gcc_struct6_2 = <<EOF;
AVHWAccel mpeg4_vaapi_hwaccel = {
    .name           = "mpeg4_vaapi",
    .type           = CODEC_TYPE_VIDEO,
    .id             = CODEC_ID_MPEG4,
    .pix_fmt        = PIX_FMT_VAAPI_VLD,
    .capabilities   = 0,
    .start_frame    = vaapi_mpeg4_start_frame,
    .end_frame      = vaapi_mpeg4_end_frame,
    .decode_slice   = vaapi_mpeg4_decode_slice,
    .priv_data_size = 0,
};

EOF

#if CONFIG_H263_VAAPI_HWACCEL
my $gcc_struct6_3 = <<EOF;
AVHWAccel h263_vaapi_hwaccel = {
    .name           = "h263_vaapi",
    .type           = CODEC_TYPE_VIDEO,
    .id             = CODEC_ID_H263,
    .pix_fmt        = PIX_FMT_VAAPI_VLD,
    .capabilities   = 0,
    .start_frame    = vaapi_mpeg4_start_frame,
    .end_frame      = vaapi_mpeg4_end_frame,
    .decode_slice   = vaapi_mpeg4_decode_slice,
    .priv_data_size = 0,
};

EOF

#if CONFIG_WMV3_VAAPI_HWACCEL
my $gcc_struct6_4 = <<EOF;
AVHWAccel wmv3_vaapi_hwaccel = {
    .name           = "wmv3_vaapi",
    .type           = CODEC_TYPE_VIDEO,
    .id             = CODEC_ID_WMV3,
    .pix_fmt        = PIX_FMT_VAAPI_VLD,
    .capabilities   = 0,
    .start_frame    = vaapi_vc1_start_frame,
    .end_frame      = vaapi_vc1_end_frame,
    .decode_slice   = vaapi_vc1_decode_slice,
    .priv_data_size = 0,
};

EOF

my $gcc_struct6 = <<EOF;
AVHWAccel vc1_vaapi_hwaccel = {
    .name           = "vc1_vaapi",
    .type           = CODEC_TYPE_VIDEO,
    .id             = CODEC_ID_VC1,
    .pix_fmt        = PIX_FMT_VAAPI_VLD,
    .capabilities   = 0,
    .start_frame    = vaapi_vc1_start_frame,
    .end_frame      = vaapi_vc1_end_frame,
    .decode_slice   = vaapi_vc1_decode_slice,
    .priv_data_size = 0,
};

EOF

# ====================================================================================================
# test 7

my $struct_detailst_53 = <<EOF;
typedef struct AVInputFormat {
    const char *name;
    const char *long_name;
    int priv_data_size;
    int (*read_probe)(AVProbeData *);
    int (*read_header)(struct AVFormatContext *,AVFormatParameters *ap);
    int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
    int (*read_close)(struct AVFormatContext *);
#if LIBAVFORMAT_VERSION_MAJOR < 53
    int (*read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags);
    int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit);
    int flags;
    const char *extensions;
    int value;
    int (*read_play)(struct AVFormatContext *);
    int (*read_pause)(struct AVFormatContext *);
    const struct AVCodecTag * const *codec_tag;
    int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
    const AVMetadataConv *metadata_conv;
    struct AVInputFormat *next;
} AVInputFormat;

EOF

my $struct_instance_blank_53 = <<EOF;
AVInputFormat sinput_form_blank = {
   NULL, // const char *name;
   NULL, // const char *long_name;
   0,    // int priv_data_size;
   NULL, // int (*read_probe)(AVProbeData *);
   NULL, // int (*read_header)(struct AVFormatContext *,AVFormatParameters *ap);
   NULL, // int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
   NULL, // int (*read_close)(struct AVFormatContext *);
// #if LIBAVFORMAT_VERSION_MAJOR < 53
   NULL, // int (*read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags);
   NULL, // int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit);
   0,    // int flags;
   NULL, // const char *extensions;
   0,    // int value;
   NULL, // int (*read_play)(struct AVFormatContext *);
   NULL, // int (*read_pause)(struct AVFormatContext *);
   NULL, // const struct AVCodecTag * const *codec_tag;
   NULL, // int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
   NULL, // const AVMetadataConv *metadata_conv;
   NULL // struct AVInputFormat *next;
};

AVInputFormat aiff_demuxer = {
    "aiff",                                           /* const char * name                                                                                                     */
    NULL_IF_CONFIG_SMALL("Audio IFF"),                /* const char * long_name                                                                                                */
    0,                                                /* int priv_data_size                                                                                                    */
    aiff_probe,                                       /* int (*read_probe)(AVProbeData *)                                                                                      */
    aiff_read_header,                                 /* int (*read_header)(struct AVFormatContext *, AVFormatParameters *ap)                                                  */
    aiff_read_packet,                                 /* int (*read_packet)(struct AVFormatContext *, AVPacket *pkt)                                                           */
    NULL,                                             /* int (*read_close)(struct AVFormatContext *)                                                                           */
    pcm_read_seek,                                    /* int flags                                                                                                             */
    NULL,                                             /* const char * extensions                                                                                               */
    0,                                                /* int value                                                                                                             */
    NULL,                                             /* int (*read_play)(struct AVFormatContext *)                                                                            */
    NULL,                                             /* int (*read_pause)(struct AVFormatContext *)                                                                           */
    (const AVCodecTag* const []){codec_aiff_tags, 0}, /* const struct AVCodecTag * const * codec_tag                                                                           */
    NULL,                                             /* int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) */
    NULL,                                             /* const AVMetadataConv * metadata_conv                                                                                  */
    NULL                                              /* struct AVInputFormat * next                                                                                           */
};

EOF


my $struct_details7 = <<EOF;

typedef struct AVInputFormat {
    const char *name;
    /**
     * Descriptive name for the format, meant to be more human-readable
     * than name. You should use the NULL_IF_CONFIG_SMALL() macro
     * to define it.
     */
    const char *long_name;
    /** Size of private data so that it can be allocated in the wrapper. */
    int priv_data_size;
    /**
     * Tell if a given file has a chance of being parsed as this format.
     * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes
     * big so you do not have to check for that unless you need more.
     */
    int (*read_probe)(AVProbeData *);
    /** Read the format header and initialize the AVFormatContext
       structure. Return 0 if OK. 'ap' if non-NULL contains
       additional parameters. Only used in raw format right
       now. 'av_new_stream' should be called to create new streams.  */
    int (*read_header)(struct AVFormatContext *,
                       AVFormatParameters *ap);
    /** Read one packet and put it in 'pkt'. pts and flags are also
       set. 'av_new_stream' can be called only if the flag
       AVFMTCTX_NOHEADER is used.
       \@return 0 on success, < 0 on error.
               When returning an error, pkt must not have been allocated
               or must be freed before returning */
    int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
    /** Close the stream. The AVFormatContext and AVStreams are not
       freed by this function */
    int (*read_close)(struct AVFormatContext *);

//#if LIBAVFORMAT_VERSION_MAJOR < 53 - pesently compiling 52!

    /**
     * Seek to a given timestamp relative to the frames in
     * stream component stream_index.
     * \@param stream_index Must not be -1.
     * \@param flags Selects which direction should be preferred if no exact
     *              match is available.
     * \@return >= 0 on success (but not necessarily the new offset)
     */
    int (*read_seek)(struct AVFormatContext *,
                     int stream_index, int64_t timestamp, int flags);
//#endif
    /**
     * Gets the next timestamp in stream[stream_index].time_base units.
     * \@return the timestamp or AV_NOPTS_VALUE if an error occurred
     */
    int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
                              int64_t *pos, int64_t pos_limit);
    /** Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER. */
    int flags;
    /** If extensions are defined, then no probe is done. You should
       usually not use extension format guessing because it is not
       reliable enough */
    const char *extensions;
    /** General purpose read-only value that the format can use. */
    int value;

    /** Starts/resumes playing - only meaningful if using a network-based format
       (RTSP). */
    int (*read_play)(struct AVFormatContext *);

    /** Pauses playing - only meaningful if using a network-based format
       (RTSP). */
    int (*read_pause)(struct AVFormatContext *);

    const struct AVCodecTag * const *codec_tag;

    /**
     * Seeks to timestamp ts.
     * Seeking will be done so that the point from which all active streams
     * can be presented successfully will be closest to ts and within min/max_ts.
     * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
     */
    int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);

    const AVMetadataConv *metadata_conv;

    /* private fields */
    struct AVInputFormat *next;
} AVInputFormat;

EOF


my $gcc_struct7_1 = <<EOF;
AVInputFormat aiff_demuxer = {
    "aiff",
    NULL_IF_CONFIG_SMALL("Audio IFF"),
    0,
    aiff_probe,
    aiff_read_header,
    aiff_read_packet,
    NULL,
    pcm_read_seek,
    .codec_tag= (const AVCodecTag* const []){codec_aiff_tags, 0},
};

EOF

my $gcc_struct7_2 = <<EOF;
AVInputFormat ape_demuxer = {
    "ape",
    NULL_IF_CONFIG_SMALL("Monkey's Audio"),
    sizeof(APEContext),
    ape_probe,
    ape_read_header,
    ape_read_packet,
    ape_read_close,
    ape_read_seek,
    .extensions = "ape,apl,mac"
};

EOF

my $gcc_struct7_3 = <<EOF;
AVInputFormat asf_demuxer = {
    "asf",
    NULL_IF_CONFIG_SMALL("ASF format"),
    sizeof(ASFContext),
    asf_probe,
    asf_read_header,
    asf_read_packet,
    asf_read_close,
    asf_read_seek,
    asf_read_pts,
    .metadata_conv = ff_asf_metadata_conv,
};

EOF

my $gcc_struct7 = <<EOF;
AVInputFormat daud_demuxer = {
    "daud",
    NULL_IF_CONFIG_SMALL("D-Cinema audio format"),
    0,
    NULL,
    daud_header,
    daud_packet,
    NULL,
    NULL,
    .extensions = "302",
};
EOF

# ====================================================================================================
# test 8

my $struct_details8 = <<EOF;
typedef struct AVOutputFormat {
    const char *name;
    /**
     * Descriptive name for the format, meant to be more human-readable
     * than name. You should use the NULL_IF_CONFIG_SMALL() macro
     * to define it.
     */
    const char *long_name;
    const char *mime_type;
    const char *extensions; /**< comma-separated filename extensions */
    /** size of private data so that it can be allocated in the wrapper */
    int priv_data_size;
    /* output support */
    enum CodecID audio_codec; /**< default audio codec */
    enum CodecID video_codec; /**< default video codec */
    int (*write_header)(struct AVFormatContext *);
    int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
    int (*write_trailer)(struct AVFormatContext *);
    /** can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER */
    int flags;
    /** Currently only used to set pixel format if not YUV420P. */
    int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *);
    int (*interleave_packet)(struct AVFormatContext *, AVPacket *out,
                             AVPacket *in, int flush);

    /**
     * List of supported codec_id-codec_tag pairs, ordered by "better
     * choice first". The arrays are all terminated by CODEC_ID_NONE.
     */
    const struct AVCodecTag * const *codec_tag;

    enum CodecID subtitle_codec; /**< default subtitle codec */

    const AVMetadataConv *metadata_conv;

    /* private fields */
    struct AVOutputFormat *next;
} AVOutputFormat;

EOF

my $gcc_struct8_1 = <<EOF;
AVOutputFormat aiff_muxer = {
    "aiff",
    NULL_IF_CONFIG_SMALL("Audio IFF"),
    "audio/aiff",
    "aif,aiff,afc,aifc",
    sizeof(AIFFOutputContext),
    CODEC_ID_PCM_S16BE,
    CODEC_ID_NONE,
    aiff_write_header,
    aiff_write_packet,
    aiff_write_trailer,
    .codec_tag= (const AVCodecTag* const []){codec_aiff_tags, 0},
};

EOF

my $gcc_struct8_2 = <<EOF;
AVOutputFormat daud_muxer = {
    "daud",
    NULL_IF_CONFIG_SMALL("D-Cinema audio format"),
    NULL,
    "302",
    0,
    CODEC_ID_PCM_S24DAUD,
    CODEC_ID_NONE,
    daud_write_header,
    daud_write_packet,
    .flags= AVFMT_NOTIMESTAMPS,
};
EOF

my $gcc_struct8_w_comm = <<EOF;
// #if CONFIG_ASF_MUXER

AVOutputFormat asf_muxer = {
    "asf",
    NULL_IF_CONFIG_SMALL("ASF format"),
    "video/x-ms-asf",
    "asf,wmv,wma",
    sizeof(ASFContext),
// #if CONFIG_LIBMP3LAME
    CODEC_ID_MP3,
// #else
//    CODEC_ID_MP2,
// #endif
    CODEC_ID_MSMPEG4V3,
    asf_write_header,
    asf_write_packet,
    asf_write_trailer,
    .flags = AVFMT_GLOBALHEADER,
    .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0},
    .metadata_conv = ff_asf_metadata_conv,
};

// #endif

EOF

my $gcc_struct8_3 = <<EOF;
AVOutputFormat asf_muxer = {
    "asf",
    NULL_IF_CONFIG_SMALL("ASF format"),
    "video/x-ms-asf",
    "asf,wmv,wma",
    sizeof(ASFContext),
    CODEC_ID_MP3,
    CODEC_ID_MSMPEG4V3,
    asf_write_header,
    asf_write_packet,
    asf_write_trailer,
    .flags = AVFMT_GLOBALHEADER,
    .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0},
    .metadata_conv = ff_asf_metadata_conv,
};

EOF

my $gcc_struct8_wcomm = <<EOF;
AVOutputFormat asf_stream_muxer = {
    "asf_stream",
    NULL_IF_CONFIG_SMALL("ASF format"),
    "video/x-ms-asf",
    "asf,wmv,wma",
    sizeof(ASFContext),
#if CONFIG_LIBMP3LAME
    CODEC_ID_MP3,
#else
    CODEC_ID_MP2,
#endif
    CODEC_ID_MSMPEG4V3,
    asf_write_stream_header,
    asf_write_packet,
    asf_write_trailer,
    .flags = AVFMT_GLOBALHEADER,
    .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0},
    .metadata_conv = ff_asf_metadata_conv,
};
EOF

my $gcc_struct8 = <<EOF;
AVOutputFormat asf_stream_muxer = {
    "asf_stream",
    NULL_IF_CONFIG_SMALL("ASF format"),
    "video/x-ms-asf",
    "asf,wmv,wma",
    sizeof(ASFContext),
    CODEC_ID_MP3,
    CODEC_ID_MSMPEG4V3,
    asf_write_stream_header,
    asf_write_packet,
    asf_write_trailer,
    .flags = AVFMT_GLOBALHEADER,
    .codec_tag= (const AVCodecTag* const []){codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0},
    .metadata_conv = ff_asf_metadata_conv,
};
EOF


# ====================================================================================================
# test 9

my $struct_details9 = <<EOF;
struct RTPDynamicProtocolHandler {
    // fields from AVRtpDynamicPayloadType_s
    const char enc_name[50];    /* XXX: still why 50 ? ;-) */
    enum CodecType codec_type;
    enum CodecID codec_id;

    // may be null
    int (*parse_sdp_a_line) (AVFormatContext *s,
                             int st_index,
                             PayloadContext *priv_data,
                             const char *line); ///< Parse the a= line from the sdp field
    PayloadContext *(*open) (); ///< allocate any data needed by the rtp parsing for this dynamic data.
    void (*close)(PayloadContext *protocol_data); ///< free any data needed by the rtp parsing for this dynamic data.
    DynamicPayloadPacketHandlerProc parse_packet; ///< parse handler for this dynamic packet.

    struct RTPDynamicProtocolHandler_s *next;
};
EOF

my $gcc_struct9_1 = <<EOF;
RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
    .enc_name         = "vorbis",
    .codec_type       = CODEC_TYPE_AUDIO,
    .codec_id         = CODEC_ID_VORBIS,
    .parse_sdp_a_line = NULL,
    .open             = vorbis_new_context,
    .close            = vorbis_free_context,
    .parse_packet     = vorbis_handle_packet
};
EOF

# RTP_ASF_HANDLER(asf_pfv, "x-asf-pf",  CODEC_TYPE_VIDEO);
my $gcc_struct9 = <<EOF;
RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler = {
    .enc_name         = "x-asf-pf",
    .codec_type       = CODEC_TYPE_VIDEO,
    .codec_id         = CODEC_ID_NONE,
    .parse_sdp_a_line = asfrtp_parse_sdp_line,
    .open             = asfrtp_new_context,
    .close            = asfrtp_free_context,
    .parse_packet     = asfrtp_parse_packet,
};
EOF

# ====================================================================================================
# test 10

my $struct_details10 = <<EOF;
typedef struct URLProtocol {
    const char *name;
    int (*url_open)(URLContext *h, const char *filename, int flags);
    int (*url_read)(URLContext *h, unsigned char *buf, int size);
    int (*url_write)(URLContext *h, unsigned char *buf, int size);
    int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
    int (*url_close)(URLContext *h);
    struct URLProtocol *next;
    int (*url_read_pause)(URLContext *h, int pause);
    int64_t (*url_read_seek)(URLContext *h, int stream_index,
                             int64_t timestamp, int flags);
    int (*url_get_file_handle)(URLContext *h);
} URLProtocol;
EOF

my $gcc_struct10 = <<EOF;
URLProtocol tcp_protocol = {
    "tcp",
    tcp_open,
    tcp_read,
    tcp_write,
    NULL, /* seek */
    tcp_close,
    .url_get_file_handle = tcp_get_file_handle,
};
EOF

# ====================================================================================================
# test 11

my $struct_details11 = <<EOF;
typedef struct {
    uint32_t type;
    int64_t offset;
    int64_t size; /* total size (excluding the size and type fields) */
} MOVAtom;
EOF

my $gcc_struct11 = <<EOF;
  MOVAtom fake_atom = { .size = size - (url_ftell(pb) - start_pos) };
EOF


# ====================================================================================================
# test 12

my $struct_details12 = <<EOF;
/// muxer options struct
typedef struct {
	nut_output_stream_tt output;    ///< output stream function pointers
	nut_alloc_tt alloc;             ///< memory allocation function pointers
	int write_index;               ///< whether or not to write an index
	int realtime_stream;           ///< Implies no write_index.
	int max_distance;              ///< Valid values are 32-65536, the recommended value is 32768. Lower values give better seekability and error detection and recovery but cause higher overhead.
	nut_frame_table_input_tt * fti; ///< Framecode table, may be NULL.
} nut_muxer_opts_tt;
EOF

my $gcc_struct12 = <<EOF;
    nut_muxer_opts_tt mopts = {
        .output = {
            .priv = bc,
            .write = av_write,
        },
        .alloc = { av_malloc, av_realloc, av_free },
        .write_index = 1,
        .realtime_stream = 0,
        .max_distance = 32768,
        .fti = NULL,
    };
EOF


# ====================================================================================================
# test 13

my $struct_details13 = <<EOF;
/// demuxer options struct
typedef struct {
	nut_input_stream_tt input;  ///< input stream function pointers
	nut_alloc_tt alloc;         ///< memory allocation function pointers
	int read_index;            ///< Seeks to end-of-file at beginning of playback to search for index. Implies cache_syncpoints.
	int cache_syncpoints;      ///< Improves seekability and error recovery greatly, but costs some memory (0.5MB for very large files).
	void * info_priv;          ///< opaque priv pointer to be passed to #new_info
	void (*new_info)(void * priv, nut_info_packet_tt * info); ///< Function to be called when info is found mid-stream. May be NULL.
} nut_demuxer_opts_tt;
EOF

my $gcc_struct13 = <<EOF;
    nut_demuxer_opts_tt dopts = {
        .input = {
            .priv = bc,
            .seek = av_seek,
            .read = av_read,
            .eof = NULL,
            .file_pos = 0,
        },
        .alloc = { av_malloc, av_realloc, av_free },
        .read_index = 1,
        .cache_syncpoints = 1,
    };
EOF

# ====================================================================================================
# test 14

my $struct_details14 = <<EOF;
/// input stream struct
typedef struct {
	void * priv;                                            ///< opaque priv pointer to be passed to function calls
	size_t (*read)(void * priv, size_t len, uint8_t * buf); ///< Input stream read function, must return amount of bytes actually read.
	off_t (*seek)(void * priv, long long pos, int whence);  ///< Input stream seek function, must return position in file after seek.
	int (*eof)(void * priv);                                ///< Returns if EOF has been met in stream in case of read error.
	off_t file_pos;                                         ///< file position at beginning of read
} nut_input_stream_tt;
EOF

my $gcc_struct14 = <<EOF;
nut_input_stream_tt input = {
            .priv = bc,
            .seek = av_seek,
            .read = av_read,
            .eof = NULL,
            .file_pos = 0,
        };
EOF


# ====================================================================================================
# test 15

my $struct_details15 = <<EOF;
typedef struct {
    uint64_t pos;
    uint64_t back_ptr;
//    uint64_t global_key_pts;
    int64_t ts;
} Syncpoint;
EOF

my $gcc_struct15_1 = <<EOF;
    Syncpoint dummy={.ts= pts*av_q2d(st->time_base)*AV_TIME_BASE};
EOF

my $gcc_struct15 = <<EOF;
    Syncpoint nopts_sp= {.ts= AV_NOPTS_VALUE, .back_ptr= AV_NOPTS_VALUE};
EOF

# ====================================================================================================
# test 16

my $struct_details16 = <<EOF;
struct ogg_codec {
    const int8_t *magic;
    uint8_t magicsize;
    const int8_t *name;
    /**
     * Attempt to process a packet as a header
     * \@return 1 if the packet was a valid header,
     *         0 if the packet was not a header (was a data packet)
     *         -1 if an error occurred or for unsupported stream
     */
    int (*header)(AVFormatContext *, int);
    int (*packet)(AVFormatContext *, int);
    uint64_t (*gptopts)(AVFormatContext *, int, uint64_t);
};
EOF

my $gcc_struct16 = <<EOF;
const struct ogg_codec ff_flac_codec = {
    .magic = "\177FLAC",
    .magicsize = 5,
    .header = flac_header
};
EOF


# ====================================================================================================
# test 17

my $struct_details17 = <<EOF;
typedef struct FFPsyModel {
    const char *name;
    int  (*init)   (FFPsyContext *apc);
    FFPsyWindowInfo (*window)(FFPsyContext *ctx, const int16_t *audio, const int16_t *la, int channel, int prev_type);
    void (*analyze)(FFPsyContext *ctx, int channel, const float *coeffs, FFPsyWindowInfo *wi);
    void (*end)    (FFPsyContext *apc);
} FFPsyModel;
EOF

my $gcc_struct17 = <<EOF;
const FFPsyModel ff_aac_psy_model =
{
    .name    = "3GPP TS 26.403-inspired model",
    .init    = psy_3gpp_init,
    .window  = psy_3gpp_window,
    .analyze = psy_3gpp_analyze,
    .end     = psy_3gpp_end,
};
EOF


my $test_max = 17;

#============ *TBD*
# ====================================================================================================
# test ______

# /* Log level */
# #define X264_LOG_NONE          (-1)
# #define X264_LOG_ERROR          0
# #define X264_LOG_WARNING        1
# #define X264_LOG_INFO           2
# #define X264_LOG_DEBUG          3
# NEED TO SETUP AN ENUMERATION!!!

my $gcc_struct_anon1 = <<EOF;
    static const int level_map[] = {
        [X264_LOG_ERROR]   = AV_LOG_ERROR,
        [X264_LOG_WARNING] = AV_LOG_WARNING,
        [X264_LOG_INFO]    = AV_LOG_INFO,
        [X264_LOG_DEBUG]   = AV_LOG_DEBUG
    };
EOF

# see convstranon.pl for this
#define ID3v1_GENRE_MAX 125
my $ID3v1_GENRE_MAX = 125;
my $gcc_struct_anon2 = <<EOF;
const char *ff_id3v1_genre_str[$ID3v1_GENRE_MAX + 1] = {
      [0] = "Blues",
      [1] = "Classic Rock",
      [2] = "Country",
      ...
    [124] = "Euro-House",
    [125] = "Dance Hall",
};
EOF

# default test
my $enum_details = $enum_pixfmt;
my $struct_details = $struct_details1;
my $gcc_struct = $gcc_struct1;
sub set_test_strings($) {
	my ($tst) = shift;
   my $test = '';
	if ($tst == 1) {
		# test 1
		$enum_details = $enum_pixfmt;
		$struct_details = $struct_details1;
		$gcc_struct = $gcc_struct1;
      $test = $struct_details1;
	} elsif ($tst == 2) {
		# test 2
		$enum_details = '';
		$struct_details = $struct_details2;
		$gcc_struct = $gcc_struct2;
      $test = $struct_details2;
	} elsif ($tst == 3) {
		# test 3
		$enum_details = '';
		$struct_details = $struct_details3;
		$gcc_struct = $gcc_struct3;
      $test = $struct_details3;
	} elsif ($tst == 4) {
		# test 4
		$enum_details = $enum_pixfmt;;
		$struct_details = $struct_details4;
		$gcc_struct = $gcc_struct4;
      $test = $struct_details4;
	} elsif ($tst == 5) {
		# test 5
		$enum_details = '';
		$struct_details = $struct_details5;
		$gcc_struct = $gcc_struct5;
      $test = $struct_details5;
	} elsif ($tst == 6) {
		# test 6
		$enum_details = '';
		$struct_details = $struct_details6;
		$gcc_struct = $gcc_struct6;
      $test = $struct_details6;
	} elsif ($tst == 7) {
		# test 7
		$enum_details = '';
		$struct_details = $struct_details7;
		$gcc_struct = $gcc_struct7;
      $test = $struct_details7;
	} elsif ($tst == 8) {
		# test 8
		$enum_details = '';
		$struct_details = $struct_details8;
		$gcc_struct = $gcc_struct8;
      $test = $struct_details8;
	} elsif ($tst == 9) {
		# test 9
		$enum_details = '';
		$struct_details = $struct_details9;
		$gcc_struct = $gcc_struct9;
      $test = $struct_details9;
	} elsif ($tst == 10) {
		# test 10
		$enum_details = '';
		$struct_details = $struct_details10;
		$gcc_struct = $gcc_struct10;
      $test = $struct_details10;
	} elsif ($tst == 11) {
		# test 11
		$enum_details = '';
		$struct_details = $struct_details11;
		$gcc_struct = $gcc_struct11;
      $test = $struct_details11;
	} elsif ($tst == 12) {
		# test 12
		$enum_details = '';
		$struct_details = $struct_details12;
		$gcc_struct = $gcc_struct12;
      $test = $struct_details12;
	} elsif ($tst == 13) {
		# test 13
		$enum_details = '';
		$struct_details = $struct_details13;
		$gcc_struct = $gcc_struct13;
      $test = $struct_details13;
	} elsif ($tst == 14) {
		# test 14
		$enum_details = '';
		$struct_details = $struct_details14;
		$gcc_struct = $gcc_struct14;
      $test = $struct_details14;
	} elsif ($tst == 15) {
		# test 15
		$enum_details = '';
		$struct_details = $struct_details15;
		$gcc_struct = $gcc_struct15;
      $test = $struct_details15;
	} elsif ($tst == 16) {
		# test 16
		$enum_details = '';
		$struct_details = $struct_details16;
		$gcc_struct = $gcc_struct16;
      $test = $struct_details16;
	} elsif ($tst == 17) {
		# test 17
		$enum_details = '';
		$struct_details = $struct_details17;
		$gcc_struct = $gcc_struct17;
      $test = $struct_details17;
    } elsif ($tst == $twinvq_spl) {
        # SPECIAL twinvq files
        if (( -f $twinvq_str ) && ( -f $twinvq_inst )) {
            if (open INF, "<$twinvq_str") {
                my @tvq_lns1 = <INF>;
                close INF;
                if (open INF2, "<$twinvq_inst") {
                    my @tvq_lns2 = <INF2>;
                    close INF2;
            		$enum_details = '';
		            $struct_details = join("\n",@tvq_lns1)."\n";
		            $gcc_struct = join("\n",@tvq_lns2)."\n";
                    $test = $gcc_struct;
                } else {
            		my_exit(1, "ERROR: twinvq: Unable to open [$twinvq_inst] file!\n" );
                }
            } else {
        		my_exit(1, "ERROR: twinvq: Unable to open [$twinvq_str] file!\n" );
            }
        } else {
    		my_exit(1, "ERROR: twinvq: Unable to find [$twinvq_str] or [$twinvq_inst] files!\n" );
        }
	} else {
		my_exit(1, "ERROR: invalid do_test_num value = [$tst]!\n" );
	}
   return $test;
}


# this is really only for DEBUG
sub show_struct_hash($$) { # like (\%h);
	my ($dbg,$rh) = @_;
	my ($cnt, $key, $val, $msg, $mt, $typ, $len, $equ, $name, $mcnt, $fnm, $bit);
	$cnt = scalar keys(%$rh);
   if ($dbg & 2) {
      my $mind = $memb_indent;
      $msg = "// Output of structure ";
   	$key = $str_nam; # 'NAME'
      my $strname = "UNKNOWN";
   	if (defined $$rh{$key}) {
	   	$val = $$rh{$key};
         $val =~ s/;$//;
         $strname = $val;
      }
  		$msg .= "$strname\n";

      # first line
   	$key = $str_tag; # 'TAG'
   	if (defined $$rh{$key}) {
	   	$val = $$rh{$key};
   		$msg .= "$val {\n";
      }

      # add members
   	foreach $key (sort keys %$rh) {
	   	$val = $$rh{$key};
		   if ($key =~ /^$mem_bgn/) { # = member
   	   	$val = $$rh{$key};
            $typ = $$val[$O_TYP];
            $name = $$val[$O_NAM];
            $bit = $$val[$O_BIT];
            $msg .= $mind;
            $msg .= "$typ ";
            $msg .= $name;
            $msg .= " : $bit" if ($bit != -1);
            $msg .= ";\n";
         }
   	}

      # and name at end
      $msg .= "} $strname ;\n";
      return $msg;
   }
	prt( "=== Showing structure HASH... $cnt keys... flag = $dbg\n" );
	$cnt = 0;
	$mt = 1;
	my %done = ();    # keep DONE keys
	$mcnt = 0;
	foreach $key (keys %$rh) {
		if ($key =~ /^$mem_bgn/) { # = member
			$val = $$rh{$key};
			$typ = $$val[$O_TYP];  # [0];
			$name = $$val[$O_NAM]; # [1];
			$equ = $$val[$O_VAL];  # [2];
			$len = length($typ);
			$mt = $len if ($len > $mt);
			$mcnt++;
		}
	}

	$mt += 8;
	$key = $str_tag; # 'TAG'
	$done{$key} = 1;
	if (defined $$rh{$key}) {
		$val = $$rh{$key};
		$cnt++;
		$msg = sprintf("%2d: ", $cnt);
		$msg .= "$val {";
		prt("$msg\n");
	}

   # member keys only - sorted, thus in ORDER
   # ADD what it equals, if ($dbg & 1)
	foreach $key (sort keys %$rh) {
		$val = $$rh{$key};
		if ($key =~ /^$mem_bgn/) { # = member
			$done{$key} = 1;
			$cnt++;
			$msg = sprintf("%2d: ", $cnt);
			$msg .= "$key ";
			$typ = " type=[".$$val[$O_TYP]."]";
			$typ .= ' ' while (length($typ) < $mt);
			$msg .= $typ;
			$msg .= " name=[".$$val[$O_NAM]."]";
			$fnm = $$val[$O_FNM];
			$msg .= "[$fnm]" if (length($fnm));
         $bit = $$val[$O_BIT];
         $msg .= ":$bit" if ($bit != -1);
			$equ = $$val[$O_VAL];
			$msg .= ", equ[$equ]" if ($dbg & 1);
			prt( "$msg\n" );
		}
	}

	$key = $str_nam; # 'NAME'
	$done{$key} = 1;
	if (defined $$rh{$key}) {
		$val = $$rh{$key};
		$cnt++;
		$msg = sprintf("%2d: ", $cnt);
		$msg .= "} $val";
		prt("$msg\n");
	}

	foreach $key (sort keys %$rh) {
		if ( !(defined $done{$key}) ) {
			$val = $$rh{$key};
			$done{$key} = 1;
			$cnt++;
			$msg = sprintf("%2d: ", $cnt);
			if ($key eq 'ENUMERATION') {
            # NOTE: This enumeration no longer kept in this block instance hash
            # enumerations are now kept in the MASTER hash
				my ($k2,$v2,$c2);
				$c2 = scalar keys(%{$val});
				$msg .= "$key => Enumeration HASH - $c2 items";
				if ($dbg17) {
					$msg .= "\n";
					$c2 = 0;
					foreach $k2 (keys %{$val}) {
						$v2 = ${$val}{$k2};
						$c2++;
						$msg .= "  $c2: $k2 = $v2\n";
					}
					$msg .= "  End $c2 enumerations";
				}
			} else {
				$msg .= "$key => $val";
			}
			prt("$msg\n");
		}
	}
	prt( "=== Done show of structure HASH... $cnt keys... flag = $dbg\n" );
   $msg = '';
   return $msg;
}

sub split_alphanum($) {
   my ($t) = shift;
   my ($mx,$i,$c,$tg);
   my @a = ();
   $mx = length($t);
   $tg = '';    # no length, yet
   for ($i = 0; $i < $mx; $i++) {
      $c = substr($t,$i,1); # get next char...
      if ($c =~ /\s/) { # if it is SPACEY
         push(@a,$tg) if length($tg); # stack tag, if length
         $tg = '';   # and clear
      } elsif ($c =~ /\w/) {
         if ( length($tg) && !($tg =~ /^\w+$/) ) {
             push(@a,$tg); # stack tag, if length and NOT alphanum
             $tg = '';  # 20090926 - clear tag
         }
         $tg .= $c;  # add to tag
      } else {
         # not spacey, nor alphanumeric
         push(@a,$tg) if length($tg); # stack tag, if length
         $tg = $c;   # and set this char
      }
   }
   push(@a,$tg) if length($tg);
   return @a;
}

sub get_potential_struct_name($) {
   my ($tx) = shift;
   my (@arr, $tg);
   @arr = split_alphanum($tx);
   foreach $tg (@arr) {
      if ($tg =~ /^\w+$/) {
         ### prt( "Seems alphanumeric [$tg]\n" );
         if (!word_in_res_words($tg)) {
             prt( "[dbg31] Returning potential name [$tg], from [$tx]\n" ) if ($dbg31);
            return $tg;
         }
      }
      ### else {
         ### prt( "Seems punctuation [$tg]\n" );
      ### }
   }
   return "";
}

sub deal_with_member($$$$) {
	my ($lnn, $line, $rnxt, $rh) = @_;
	my (@arr, $ac, $typ, $bs, $j, $sec, $akey, $msg, $fnm, $pw, $bit);
	my $nxt_member = $$rnxt;	# get the NEXT member value - starts 0
	@arr = split(/\s/,$line);
	$ac = scalar @arr;
	$typ = $arr[0];
	prt("[dbg00] $lnn:deal_with_member: [$line], split=$ac, type=$typ, nxt_mem=$nxt_member\n" ) if ($dbg00);
	if ($ac < 2) {
		prtw( "$lnn: WARNING: Line [$line] did not give two elements...\n" );
	} else {
		## if ($ac >= 2) {
		$pw = $arr[-1];
		if ($pw =~ /\w+\{$/) {
			$pw = substr($pw,0, length($pw) - 1);
			push(@arr,'{');
			$ac = scalar @arr;
			prt("[dbg00] $lnn:deal_with_member: put space ater name and '{'!\n" ) if ($dbg00);
		}
		$bs = 1;
		if ( ($ac > 2) && word_in_res_words($typ) ) {
			prt("[dbg00] $lnn:deal_with_member: type=$typ is res word\n" ) if ($dbg00);
			$fnm = $typ;
			while ($bs < $ac) {
				$pw = $fnm;
				$fnm = $arr[$bs];
				prt("[dbg00] $lnn:deal_with_member: type=$typ check next $fnm\n" ) if ($dbg00);
				while ( (($pw eq 'enum')||($pw eq 'struct')||($pw eq 'const')) && (($bs + 1) < $ac) ) {
					$typ .= " $fnm";
					$bs++;
					$pw = $fnm;
					$fnm = $arr[$bs];
				}
				if ( ( word_in_res_words($fnm) || ($fnm eq '*') ) && (($bs + 1) < $ac) ) {
					$typ .= " $fnm";
					$bs++;
					if ( (($fnm eq 'enum')||($fnm eq 'struct')||($pw eq 'const')) && (($bs + 1) < $ac) ) {
						$fnm = $arr[$bs];
						$typ .= " $fnm";
						$bs++;
					}
				} else {
					last;
				}
			}
			#if (($typ eq 'enum')||($typ eq 'const')) {
			#	$typ .= " $arr[1]";
			#	$bs++
			#}
		}
		$sec = '';
		for ($j = $bs; $j < $ac; $j++) {
			$sec .= ' ' if length($sec);
			$sec .= $arr[$j];
		}
		if (substr($sec,0,1) eq '*') {
			$typ .= ' *';
			$sec = substr($sec,1);
		}
		$sec =~ s/\s$// while ($sec =~ /\s$/);
		$sec =~ s/;$//;
		$sec =~ s/\s$// while ($sec =~ /\s$/);
		# 20090825 - try to deal with function pointer, like '(*foo)(int *, char * p, ...)'
		$fnm = '';
		if ($sec =~ /^\(\s*\*\s*(\w+)\s*\)\s*\(.*\)/) {
			$fnm = $1;
		}
      # 20090829 - added to handle BITS, line 'name : 2'
      $bit = -1;
      if ( $sec =~ /^(\w+)\s+:\s+(\d+)$/ ) {
         $sec = $1;
         $bit = $2;
         prt("[dbg23] $lnn:deal_with_member: got BITS split name=[$sec], bits=[$bit]\n") if ($dbg23);
      }
      $sec = trim_ends($sec); # 20090901 - ensure no SPACE added
		$nxt_member++;
		$akey = sprintf("%s%04d",$mem_bgn,$nxt_member);	# member and number
		#                0       1      2      3      4      5      6
		# offsets        $O_TYP  $O_NAM $O_ORG $O_VAL $O_DEC $O_FNM $O_BIT
		prt("[dbg00] $lnn:deal_with_member: added [$akey] = typ=[$typ] nam=[$sec] fnm=[$fnm] bit=[$bit] into hash\n" ) if ($dbg00);
		$$rh{$akey} = [ $typ,    $sec,  $line,  "",   "",    $fnm,  $bit ];
		$msg = sprintf("%3d: ",$lnn);
		$msg .= "$line // $nxt_member";
		prt("[dbg01] $msg\n") if ($dbg01);
		$$rnxt = $nxt_member;
	}
}

sub is_struct_tag($) {
   my ($txt) = shift;
   if ($txt =~ /^\s*\w+\s*\{/m) {
      ###prt( "txt[$txt] is struct tag\n" );
      ###exit(1);
      return 1;
   }
   return 0;
}

# convert the GCC struct, to a MSVC struct
# comments /* ... */ and // to end of line
# 20090829 - change behaviour
# when in the structure ONLY ';' semicolon ends a member line
# not the newline character!
sub build_struct_hash($) {
    my ($as) = shift;
    my %hash = ();
    my $next_member = 0;
    my $depth = 0;
    ## my $as = reline_structure_string(\$depth, $as_in);
	# need to read code string, and build a hash of type
	my ($i, $len, $ch, $word, $pc, $nc, $line, $stst, @arr, $sec, $j, $ac, $akey, $typ, $bs, $lnn, $msg, $com);
    my $pname = '';     # NAME of structure - VERY IMPORTANT
	$len = length($as);
	$word = '';
	$line = '';
	$stst = 0;
	$lnn = 1;
    $ch = '';
	prt( "[dbg25|31] Bulding structure hash... $len chars...\n" ) if ($dbg25 || $dbg31);
	for ($i = 0; $i < $len; $i++) {
        $pc = $ch;
		$ch = substr($as,$i,1);	# char by char
		$nc = (($i + 1) < $len) ? substr($as,$i+1,1) : " ";
		# if END OF LINE
		if ($ch eq "\n") {
            if (!$stst) {
                prt( "$lnn:$stst:extra: got end of line ($i) word=[$word] line=[$line]\n" ) if ($dbgext);
                if ($stst && length($line)) {
                    # ($line, $rnxt, $rh) = @_;
                    deal_with_member($lnn, $line, \$next_member, \%hash);
                } elsif (length($line)) {
                    $msg = sprintf( "%3d: ", $lnn );
                    $msg .= $line;
                    prtw("WARNING: NO struct start [$msg]\n");
                }
                $lnn++;
                $line = '';
            }
			next;
		}
		prt( "$lnn:$stst:extra: got space ($i) word=[$word] line=[$line]\n" ) if (($ch =~ /\s/) && $dbgext);
		next if ($ch =~ /\s/);

		# got the START of a WORD
		if ($stst && ($ch eq '}')) {
			$stst = 0; # end of member definitions
			prt( "$lnn:$stst:extra: got closing brace ($i) word=[$word] line=[$line]\n" ) if ($dbgext);
			if (length($word)) {
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
				deal_with_member($lnn, $line, \$next_member, \%hash);
				$line = '';
			}
			$i++;
         $word = '';
			for (; $i < $len; $i++) {
            $pc = $ch;
				$ch = substr($as,$i,1);	# char by char
				$nc = (($i + 1) < $len) ? substr($as,$i+1,1) : " ";
				$word .= $ch;
				last if ($ch eq ';');
			}

			# $hash{'NAME'} = $word;
         $word = trim_ends($word);
         $word =~ s/;$//;
         $word = trim_ends($word);
         if (length($word)) {
            if (defined $hash{$str_nam}) {
               prtw("WARNING:$lnn: Replacing name [".$hash{$str_nam}."] with [$word] - CHECKME!\n");
            }
            $hash{$str_nam} = $word;   # SET NAME OF STRUCTURE - an important item
         }
         if ($dbg27) {
            $msg = sprintf( "%3d: ", $lnn );
            $msg .= "}$word";
            prt("[dbg27] Closing: $msg\n") ;
         }
			$word = '';
			$line = '';
			next;
		}

		$word = $ch;
		if ($ch eq '{') {
			prt( "$lnn:$stst:extra: got openning brace ($i) word=[$word] line=[$line]\n" ) if ($dbgext);
			if (length($line)) {
				#$hash{'TAG'} = $line;
				$hash{$str_tag} = $line;
				$line .= " $ch";
			} else {
				$line = $ch;
			}
			$msg = sprintf( "%3d: ", $lnn );
			$msg .= $line;
            $pname = get_potential_struct_name($line);
			prt("[dbg26] Start of structure: [$msg] pname=[$pname]\n") if ($dbg26);
			$line = '';
			$stst = 1;	# start of struct
			next;
		}

		$i++;
		if (($ch eq '/') && ($nc eq '*')) {
			prt( "$lnn:$stst:extra: got start of a comment /* ... */ ($i) word=[$word] line=[$line]\n" ) if ($dbgext);
			$i += 2;
			$com = '/*';
			for (; $i < $len; $i++) {
            $pc = $ch;
				$ch = substr($as,$i,1);	# char by char
				$lnn++ if ($ch eq "\n");
				$nc = (($i + 1) < $len) ? substr($as,$i+1,1) : " ";
				if (($ch eq '*') && ($nc eq '/')) {
					$i++;
					$com .= $ch;
					$com .= $nc;
					$msg = sprintf( "%3d: ", $lnn );
					$msg .= "Discarding:1: [$com]";
					$word =~ s/\/$//; # remove this char from the word
					prt("[dbg04] $msg W[$word] L[$line]\n") if ($dbg04);
					$pc = $nc;
					last;
				}
				$com .= $ch;
			}
			next;
		} elsif (($ch eq '/') && ($nc eq '/')) {
			prt( "$lnn:$stst:extra: got start of a comment //... ($i) word=[$word] line=[$line]\n" ) if ($dbgext);
			#$i++;	# jump this
			#$com = $ch;
			$word =~ s/\/$//; # remove this char from the word
			$com = $ch;
			for (; $i < $len; $i++) {
            $pc = $ch;
				$ch = substr($as,$i,1);	# char by char
				if ($ch eq "\n") {
					$msg = sprintf( "%3d: ", $lnn );
					$msg .= "Discarding:2: [$com]EOL";
					prt("[dbg04] $msg W[$word] L[$line]\n") if ($dbg04);
					$i--;	# back up to this important CHAR
					last;
				}
				$com .= $ch;
				$pc = $ch;
			}
			next;
		}

		for (; $i < $len; $i++) {
			# accumulating the next WORD
            $pc = $ch;
			$ch = substr($as,$i,1);	# char by char
			$nc = (($i + 1) < $len) ? substr($as,$i+1,1) : " ";
			if ($ch =~ /\s/) {
				prt( "$lnn:$stst:extra: got space - exit with last - word=[$word] line=[$line] ($i)\n" ) if ($dbgext);
				last;
			} elsif ($ch eq '{') {
				# hmmm, the '{' would be attached to the word
				$i--;	# back up to this char in string
				last;	# exit here, to add this word to the line
			} elsif (($ch eq '/') && ($nc eq '*')) {
				prt( "$lnn:$stst:extra: got start of a comment /* ... */...(2) ($i) word=[$word] line=[$line]\n" ) if ($dbgext);
				$i += 2;
				$com = '/*';
				for (; $i < $len; $i++) {
                    $pc = $ch;
					$ch = substr($as,$i,1);	# char by char
					$com .= $ch;
					$lnn++ if ($ch eq "\n");
					$nc = (($i + 1) < $len) ? substr($as,$i+1,1) : " ";
					if (($ch eq '*') && ($nc eq '/')) {
						$i++;
						$com .= $ch.$nc;
						$msg = sprintf( "%3d: ", $lnn );
						$msg .= "Discard2: [$com]";
						prt("[dbg04] $msg W[$word] L[$line]\n") if ($dbg04);
						last;
					}
				}
				last;
			} elsif (($ch eq '/') && ($nc eq '/')) {
				prt( "$lnn:$stst:extra: got start of a comment //...(2) ($i) word=[$word] line=[$line]\n" ) if ($dbgext);
				$i += 2;
				$com = $ch.$nc;
				for (; $i < $len; $i++) {
                    $pc = $ch;
					$ch = substr($as,$i,1);	# char by char
					$nc = (($i + 1) < $len) ? substr($as,$i+1,1) : " ";
					if ($ch eq "\n") {
						$msg = sprintf( "%3d: ", $lnn );
						$msg .= "Discard2: [$com]";
						prt("[dbg04] $msg W[$word] L[$line]\n") if ($dbg04);
						last;
					}
					$com .= $ch;
				}
				last;
			}
			$word .= $ch;	# add to word
            last if ($stst && ($ch eq ';'));
		}

		# exit on a spacey char - back up if spacey char is new line
		$i-- if ($ch eq "\n");
		if (length($word)) {
			$line .= ' ' if (length($line));
			$line .= $word;
			$word = '';	# restart word
		}

		# if semicolon END OF LINE
		if ($stst && ($ch eq ';')) {
         prt( "$lnn:$stst:extra: got $ch = end of line struct line ($i) line=[$line]\n" ) if ($dbgext);
         deal_with_member($lnn, $line, \$next_member, \%hash) if (length($line));
         $line = '';
		}

	}
	if (length($line)) {
		$msg = sprintf( "%3d: ", $lnn );
		$msg .= $line;
		prtw("WARNING: LINE NOT HANDLED $msg\n");
	}

	if ($next_member == 0) {
		prt( "ERROR: structure hash has NO members!\n" );
      my_exit(1, "$lnn lines, input=[$as]\n" );
	}
   if (length($pname) && !(defined $hash{$str_nam})) {
      $hash{$str_nam} = $pname;   # SET NAME OF STRUCTURE - an important item
      prt( "Set structure name to (potential) [$pname] - CHECK!\n" );
   }

   $word = "NAME_UNKNOWN - WARNING - CHECKME!";
   if (defined $hash{$str_nam}) {
      $word = $hash{$str_nam};
   }
	prt("Done structure [$word] building... with $next_member members...\n")  if ($dbg25);
	$hash{$mem_cnt} = $next_member;
	$hash{$mem_nxt} = 0;	# start a next member counter
	#return %hash;
	return \%hash;
}


sub set_debug_on_str_parse() {
	###$dbgext = 1; # show lots of stages in decode of structure - 
	$dbg00 = 1;	# show prt("$lnn: deal with member [$line], split=$ac, type=$typ, next=$nxt\n" ) if ($dbg00);
	$dbg01 = 1;	# show each line of structure 
	$dbg04 = 1;	# show discarded comments in building structure members
	$load_log = 1;	# load the LOG file contents

   $dbg25 = 1; # show prt( "[dbg25] Bulding structure hash... $len chars...\n" ) if ($dbg25);
   $dbg26 = 1; # show prt("[dbg26] Start of structure: [$msg]\n") if ($dbg26);
   $dbg27 = 1; # show prt("[dbg27] Closing: $msg\n") if ($dbg27); + line number, and word found = structure NAME
	$dbg02 = 1;	# show after decode
	prtw( "WARNING: setting DEBUG on str parse (dbg 00, 01, 04) and load_log\n" );
}

sub set_debug_on_fill_str() {	# make the filling of values VERY NOISY
	$dbg03 = 1;	# show def re-lining
	$dbg09 = 1;	# show level information
	$dbg07 = 1;  # show prt( "Added [$equ] to key [$key], for off[$off]\n" )
   $dbg08 = 1;  # show each line in structure filling
	$load_log = 1;	# load the LOG file contents
	prtw( "WARNING: setting DEBUG on fill str (dbg 03, 09, 07) and load_log\n" );
}

# level dependant things kept
#my $L_EQU = 0;	# equal sign
#my $L_CMA = 1;	# comma
#my $L_DOT = 2;	# dot
#my $L_QOT = 3;	# double quotes
#my $L_QT1 = 4;  # single quotes
#my $L_BRA = 5;  # inc on '(' dec on ')'
#my $L_BRC = 6;  # inc on '{' dec on '}'
#my $L_SQU = 7;  # inc on '[' dec on ']'

sub brace_closes_in_this_line($) {
	my ($txt) = shift;	# = (substr($ln,$i+1)
	my $ll = length($txt);
	my $brcnt = 1;	# we have one OPEN brace at this point
	for (my $j = 0; $j < $ll; $j++) {
		my $c = substr($txt,$j,1);
		if ($c eq "\n") {
			last;	# reached END OF LINE
		} elsif ($c eq '{') {
			$brcnt++;	# bump counter
		} elsif ($c eq '}') {
			$brcnt-- if ($brcnt);
		}
	}
	if ($brcnt == 0) {
		return 1;
	}
	return 0;
}

sub just_space_to_semi_colon($) { # = substr($as,$i+1)
   my ($tx) = shift;
   my ($ll,$j,$c);
   $ll =length($tx);
   for ($j = 0; $j < $ll; $j++) {
      $c = substr($tx,$j,1);
      if ($c eq ';') {
         return 1;
      } elsif ($c =~ /\s/) {
         next;
      }
      return 0;
   }
   return 0;
}

# strip comments
# /* ... */ and
# // to EOL
sub strip_comments($) {
    my ($ln) = shift;
    my $nln = '';
    my $len = length($ln);
    my ($k, $pc, $cc, $nc);
    $cc = '';
    for ($k = 0; $k < $len; $k++) {
        $pc = $cc;
        $cc = substr($ln,$k,1);
        $nc = (($k + 1) < $len) ? substr($ln,$k+1,1) : '';
        if (($cc eq '/') && ($nc eq '*')) {
            # locked in comment /* ... */
            $cc = $nc;
            $k += 2;
            for (; $k < $len; $k++) {
                $pc = $cc;
                $cc = substr($ln,$k,1);
                $nc = (($k + 1) < $len) ? substr($ln,$k+1,1) : '';
                if (($cc eq '/') && ($pc eq '*')) {
                    last;
                }
            }
            next;
        } elsif (($cc eq '/') && ($nc eq '/')) {
            # locked in comment /* ... */
            $cc = $nc;
            $k += 2;
            for (; $k < $len; $k++) {
                $pc = $cc;
                $cc = substr($ln,$k,1);
                $nc = (($k + 1) < $len) ? substr($ln,$k+1,1) : '';
                if ($cc eq "\n") {
                    $k--;   # back up to this char
                    last;
                }
            }
            next;
        }
        $nln .= $cc;
    }
    return $nln;
}

# reline instance string
# try to be very flexible, but keep certain things INLINE
# =======================================================
sub reline_instance_string($$) {
	my ($rdep,$ln) = @_;
	my ($len, $i, $pc, $cc, $nc, $word, $line, $max, $bcnt, $dcnt, $lnn);
	my ($hadcoma, $haddot, $hadequ, $nln);
	my $ntxts = '';
    $ln = strip_comments($ln) if ($strip_comments);
	$len = length($ln);
	$word = '';
	$line = '';
	my @brcstk = ();
	my @brkstk = ();
	my @depitems = ();
	# items           EQU CMA DOT QOT QT1 BRA BRC SQU
	push(@depitems, [ 0,  0,  0,  0,  0,  0,  0,  0 ]);	# add one extra
	prt( "Re-lining $len characters...\n" );
	$max = 0;
	$dcnt = 0;
	$hadcoma = 0;
	$haddot  = 0;
	$hadequ  = 0;
	$bcnt = 0;	# brace count = LEVEL
	$cc = "\n";
	$lnn = 0;
    $nln = 0;
    for ($i = 0; $i < $len; $i++) {
        $pc = $cc;	# update previous
		$cc = substr($ln,$i,1); # get current
		$nc = (($i + 1) < $len) ? substr($ln,$i+1,1) : " ";   # and next
		if ($cc eq "\n") {
            $lnn++;
            $nln++;
        }

		# BEFORE character added
		# ======================
		if ($cc eq "\n") {
			next if ($bcnt == 0);	# join this to one line until first '{'

			if (length($word)) {
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
			}

			# next if ($bcnt > 2);	# 20090826 - above 2 keep inline
			next if ($bcnt >= 2);	# 20090903 - above or equal 2 KEEP INLINE

            # 20090904 - keep a '.member = ' INLINE
            next if ($line =~ /^\.\w+\s+=\s*$/);

			if (length($line)) {
				prt("[dbg03] $lnn:$nln: [$line] lev=$bcnt\n") if ($dbg03);
				if (($haddot > 1) && ($hadequ > 1) && ($hadcoma > 1)) {
					my $ll = length($line);
					# maybe this line should be SPLIT, with second, or more '.', each to a NEW line...
					prt( "[dbg03] CHECK: SPLIT of line=[$line]\n" ) if ($dbg03);
					while ($ll) {
						my ($j, $c, $part);
						$hadcoma = 0;
						$haddot = 0;
						$hadequ = 0;
						$part = '';
						for ($j = 0; $j < $ll; $j++) {
							$c = substr($line,$j,1);
							if (length($part) == 0) {
								next if ($c =~ /\s/);
							}
							$part .= $c; # add to part
							if ($c eq '.') {
								$haddot++;
							} elsif ($c eq '=') {
								$hadequ++;
							} elsif ($c eq ',') {
								if ($haddot && $hadequ) {
									$j++;	# include comma
									last;
								}
							}
						}
						if (length($part)) {
							$ntxts .= $part;
							$ntxts .= "\n";
                     $nln++ if ($part ne $line);
							prt("[dbg03] $lnn:$nln: ADDING part=[$part] to new text. lev=$bcnt\n") if ($dbg03);
						}
						if ($j < length($line)) {
							$line = substr($line,$j); # reduce line to balance
							$ll = length($line);      # and get length remaining
						} else {
							$line = '';
							$ll = 0;
						}
					}
				} else {
   				prt("[dbg03] $lnn:$nln: ADDING line=[$line] to new text. lev=$bcnt\n") if ($dbg03);
					$ntxts .= "$line";
					$ntxts .= "\n";	# = $cc
				}
				$line = '';
			}
			$hadcoma = 0;
			$haddot = 0;
			$hadequ = 0;
			next;
		} elsif ($cc =~ /\s/) {
			if (length($word)) {
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
			}
			$pc = $cc;	# update previous
			next;
		} elsif ($cc eq '{') {                    ### ***** OPEN BRACE *****
			push(@brcstk,$i);
			$bcnt = scalar @brcstk;
			$max = $bcnt if ($bcnt > $max); # get MAXIMUM depth
			while ($max > $dcnt) {
				# items           EQU CMA DOT QOT QT1 BRA BRC SQU
				push(@depitems, [ 0,  0,  0,  0,  0,  0,  0,  0 ]);	# add one extra
				$dcnt++;
			}
			# clear seen items, at this depth/level
			$depitems[$bcnt][$L_EQU] = 0;	# equal
			$depitems[$bcnt][$L_CMA] = 0;	# comma
			$depitems[$bcnt][$L_DOT] = 0;	# dot
			$depitems[$bcnt][$L_QOT] = 0;	# double quotes
			$depitems[$bcnt][$L_QT1] = 0;	# single quotes
			$depitems[$bcnt][$L_BRA] = 0;	# brackets ( )
			$depitems[$bcnt][$L_BRC] = 1;	# brace { }
			$depitems[$bcnt][$L_SQU] = 0;	# brace [ ]
         prt( "[dbg03] $lnn:$nln: OPEN brace - W=[$word] L=[$line] - bcnt=$bcnt\n" ) if ($dbg03);
		} elsif ($cc eq '}') {                    ### ***** CLOSE BRACE *****
			if ($depitems[$bcnt][$L_BRC]) {
				$depitems[$bcnt][$L_BRC]--;
			} else {
				prtw( "WARNING:reline_def: Closing brace without open - level $dcnt\n" );
			}
			if (@brcstk) {
				pop @brcstk;
			} else {
				prtw("WARNING:reline_def: Encountered $cc, with no stack!\n");
			}
			$bcnt = scalar @brcstk;
         prt( "[dbg03] $lnn:$nln: CLOSE brace - W=[$word] L=[$line] - bcnt=$bcnt\n" ) if ($dbg03);
		} elsif ($cc eq '(') {
			$depitems[$bcnt][$L_BRA]++;	      # brackets ( )
			push(@brkstk,$i);
		} elsif ($cc eq ')') {
			if ($depitems[$bcnt][$L_BRA]) {     # brackets ( )
				$depitems[$bcnt][$L_BRA]--;
			} else {
				prtw( "WARNING: closing bracket without open - level $dcnt\n" );
			}
			if (@brkstk) {
				pop @brkstk;
			} else {
				prtw("WARNING: Encountered $cc, with no stack!\n");
			}
		}

      # 20090831 - if end of structure stuff - bcnt==0, and this is the closer, '}', and the next is ';'
      # take a new line
      if (($bcnt == 0) && ($cc eq '}') && (($nc eq ';') || just_space_to_semi_colon( substr($ln,$i+1) ) ) ) {
         prt( "[dbg03] $lnn:$nln: Got '}s*;' = Take a NEW line! after W=[$word] L=[$line]\n" ) if ($dbg03);
			if (length($word)) {
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
			}
			if (length($line)) {
            $ntxts .= $line;
				$ntxts .= "\n";
            $nln++;
            $line = '';
         }
      }

        # 20090901 - if a .member take a new line
        # 20090903 - BUT not if the previous char is \w - eg .name = "3GPP TS 26.403-inspired model",
        # this dot within the quotes should NOT be a NEW LINE
        # if (($cc eq '.') && ($nc =~ /\w/) && ($bcnt < 2)) {
        # if (($cc eq '.') && ($nc =~ /\w/) && ($bcnt < 2) && ($depitems[$bcnt][$L_QOT] == 0)) {
        # if ($cc eq '.') {
        # 20090926 - avoid splitting a DECIMAL number
        if ( ($cc eq '.') && ( !($pc =~ /\d/) ) ) {
            # if (($nc =~ /\w/) && ($bcnt < 2) && ($depitems[$bcnt][$L_QOT] == 0)) {
            if (($nc =~ /\w/) && ($depitems[$bcnt][$L_QOT] == 0)) {
                prt( "[dbg03] $lnn:$nln: Got '.w+' = Inserted NEW line before! W=[$word] L=[$line]\n" ) if ($dbg03);
                if (length($word)) {
                    $line .= ' ' if (length($line));
                    $line .= $word;
                    $word = '';
                }
                if (length($line)) {
                    $ntxts .= $line;
                    $ntxts .= "\n";
                    $nln++;
                    $line = '';
                }
            } else {
                if ($nc =~ /\w/) {
                    #if ($bcnt < 2) {
                        if ($depitems[$bcnt][$L_QOT] == 0) {
                            my_exit(1, "FAILED IN TESTING!\n" );
                        } else {
                            prt( "[dbg03] $lnn:$nln: Got '.\w+' & bcnt < 2 ($bcnt), but L_QOT=".$depitems[$bcnt][$L_QOT]." not 0 - Missed Inserted NEW line! W=[$word] L=[$line]\n" ) if ($dbg03);
                        }
                    #} else {
                    #    prt( "[dbg03] $lnn:$nln: Got '.\w+', but bcnt=$bcnt, not LT 2 - Missed Inserted NEW line! W=[$word] L=[$line]\n" ) if ($dbg03);
                    #}
                } else {
                    prt( "[dbg03] $lnn:$nln: Got '.', but NEXT not 'w' - Missed Inserted NEW line! W=[$word] L=[$line]\n" ) if ($dbg03);
                }
            }
        }

        $word .= $cc;     # committed - add character
        prt("[dbg03] $lnn:$nln: Added char [$cc], to W=[$word] L=[$line] nc=spacey\n") if (($nc =~ /\s/) && $dbg03);
		# ===============================

		# after it is ADDED
		######################################
		if ($cc eq ',') {
			$hadcoma++;
			$depitems[$bcnt][$L_CMA]++;	# comma
		} elsif ($cc eq '.') {
			$haddot++;
			$depitems[$bcnt][$L_DOT]++;	# dot
		} elsif ($cc eq '=') {
			$hadequ++;
			$depitems[$bcnt][$L_EQU]++;	# equ
		} elsif ($cc eq '"') {
         # 20090903 - ensure it is NOT escaped
         if ($pc ne "\\") {
            if ($depitems[$bcnt][$L_QOT]) {
               $depitems[$bcnt][$L_QOT]--;	# double quotes
            } else {
               $depitems[$bcnt][$L_QOT]++;	# double quotes
            }
         }
		} elsif ($cc eq "'") {
			if ($depitems[$bcnt][$L_QT1]) {
				$depitems[$bcnt][$L_QT1]--;	# single quotes
			} else {
				$depitems[$bcnt][$L_QT1]++;	# single quotes
			}
		} elsif ($cc eq '[') {
			$depitems[$bcnt][$L_SQU]++;	# brace [ ]
		} elsif ($cc eq ']') {
			if ($depitems[$bcnt][$L_SQU]) {
				$depitems[$bcnt][$L_SQU]--;	# double quotes
			} else {
				prtw( "WARNING: closing square bracket without open - level $dcnt\n" );
			}
		# } elsif (($cc eq "{") && !($nc eq "\n"))
		#} elsif (($cc eq "{") && !($nc eq "\n") && !brace_closes_in_this_line(substr($ln,$i+1)) )
		} elsif (($cc eq "{") && !($nc eq "\n") && # 20090831 - if brace count = 1, goto NEW line
         ( ($bcnt == 1) || !brace_closes_in_this_line(substr($ln,$i+1)) ) ) {
			#if (scalar @brcstk < 3) {
			#if ($bcnt < 3) {
			if ($bcnt < 2) {  # 20090904 - reduce this to 2, from 3?!?!?!?
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
				$ntxts .= "$line";
				$ntxts .= "\n";
            $nln++;
				prt("[dbg03] $lnn:$nln: Due '{', [$line] to new line. (lev=$bcnt)\n") if ($dbg03);
				$line = '';
				$pc = $cc;
				next;
			}
		}
	} # process each character

	# all done = clear any remaining items
	if (length($word)) {
		$line .= ' ' if (length($line));
		$line .= $word;
		$word = '';
	}
	if (length($line)) {
		prt("[dbg03] $lnn:$nln: EL=[$line] bcnt=$bcnt\n") if ($dbg03);
		#$ntxts .= "$line$cc";
		$ntxts .= "$line\n";
		$line = '';
	}

	# ========================================================================
	# done relineing, and in exit
	if ( !@brcstk && !@brkstk ) {
		prt( "Appears brace and bracket stacks cleared.\n" );
	} else {
		if (@brcstk) {
			prtw("\n*****************************\nWARNING: brace stack NOT cleared!\n*****************************\n");
		}
		if (@brkstk) {
			prtw("\n*****************************\nWARNING: bracket stack NOT cleared!\n*****************************\n");
		}
      my_exit(1, "reline_instance_string: FAILED!\n");
	}
	$len = length($ntxts);
	prt( "Done Re-lining - got $len characters, depth=$max...\n" );
	$$rdep = $max;	# return MAX depth of BRACES
	write2file($ntxts,"tempntxt.txt");
    prt( "Written re-lined text to 'tempntxt.txt'...\n" );
    ### my_exit(1, "TEMP EXIT");
	return $ntxts;
}

sub reline_instance_string_OK($$) {
	my ($rdep,$ln) = @_;
	my ($len, $i, $pc, $cc, $nc, $word, $line, $max, $bcnt);
	my ($hadcoma, $haddot, $hadequ);
	my $ntxts = '';
	$len = length($ln);
	$word = '';
	$line = '';
	my @brcstk = ();
	my @brkstk = ();
	prt( "Re-lining $len characters...\n" );
	$max = 0;
	$hadcoma = 0;
	$haddot  = 0;
	$hadequ  = 0;
	$bcnt = 0;
	$pc = "\n";
	for ($i = 0; $i < $len; $i++) {
		$cc = substr($ln,$i,1);
		$nc = (($i + 1) < $len) ? substr($ln,$i+1,1) : " ";

		# BEFORE character added
		# ======================
		if ($cc eq "\n") {
			next if ($bcnt == 0);	# join this to one line until first '{'
			if (length($word)) {
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
			}
			if (length($line)) {
				prt("[dbg03] $line\n") if ($dbg03);
				if (($haddot > 1) && ($hadequ > 1) && ($hadcoma > 1)) {
					my $ll = length($line);
					# maybe this line should be SPLIT, with second, or more '.', each to a NEW line...
					prt( "[dbg03] CHECK: SPLIT of line...\n" ) if ($dbg03);
					while ($ll) {
						my ($j, $c, $part);
						$hadcoma = 0;
						$haddot = 0;
						$hadequ = 0;
						$part = '';
						for ($j = 0; $j < $ll; $j++) {
							$c = substr($line,$j,1);
							if (length($part) == 0) {
								next if ($c =~ /\s/);
							}
							$part .= $c; # add to part
							if ($c eq '.') {
								$haddot++;
							} elsif ($c eq '=') {
								$hadequ++;
							} elsif ($c eq ',') {
								if ($haddot && $hadequ) {
									$j++;	# include comma
									last;
								}
							}
						}
						if (length($part)) {
							$ntxts .= $part;
							$ntxts .= "\n";
							prt("[dbg03] $part\n") if ($dbg03);
						}
						if ($j < length($line)) {
							$line = substr($line,$j); # reduce line to balance
							$ll = length($line);      # and get length remaining
						} else {
							$line = '';
							$ll = 0;
						}
					}
				} else {
					$ntxts .= "$line";
					$ntxts .= "\n";	# = $cc
				}
				$line = '';
			}
			$hadcoma = 0;
			$haddot = 0;
			$hadequ = 0;
			$pc = $cc;	# update previous
			next;
		} elsif ($cc =~ /\s/) {
			if (length($word)) {
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
			}
			$pc = $cc;	# update previous
			next;
		} elsif ($cc eq '{') {
			push(@brcstk,$i);
			$bcnt = scalar @brcstk;
			$max = $bcnt if ($bcnt > $max); # get MAXIMUM depth
		} elsif ($cc eq '}') {
			if (@brcstk) {
				pop @brcstk;
				$bcnt = scalar @brcstk;
			} else {
				prtw("WARNING: Encountered $cc, with no stack!\n");
			}
		} elsif ($cc eq '(') {
			push(@brkstk,$i);
		} elsif ($cc eq ')') {
			if (@brkstk) {
				pop @brkstk;
			} else {
				prtw("WARNING: Encountered $cc, with no stack!\n");
			}
		}

		# ===============================
		$word .= $cc;
		# ===============================

		# after it is ADDED
		######################################
		if (($cc eq "{") && !($nc eq "\n")) {
			#if (scalar @brcstk < 3) {
			if ($bcnt < 3) {
				$line .= ' ' if (length($line));
				$line .= $word;
				$word = '';
				prt("[dbg03] $line\n") if ($dbg03);
				$ntxts .= "$line";
				$ntxts .= "\n";
				$line = '';
				$pc = $cc;
				next;
			}
		} elsif ($cc eq ',') {
			$hadcoma++;
		} elsif ($cc eq '.') {
			$haddot++;
		} elsif ($cc eq '=') {
			$hadequ++;
		}
		$pc = $cc;	# update previous
	}

	# all done = clear any remaining items
	if (length($word)) {
		$line .= ' ' if (length($line));
		$line .= $word;
		$word = '';
	}
	if (length($line)) {
		prt("[dbg03] $line\n") if ($dbg03);
		$ntxts .= "$line$cc";
		$line = '';
	}
	if ( !@brcstk && !@brkstk ) {
		prt( "Appears brace and bracket stacks cleared.\n" );
	} else {
		if (@brcstk) {
			prtw("\n*****************************\nWARNING: brace stack NOT cleared!\n*****************************\n");
		}
		if (@brkstk) {
			prtw("\n*****************************\nWARNING: bracket stack NOT cleared!\n*****************************\n");
		}
      my_exit(1, "reline_instance_string_OK: FAILED!\n");
	}
	$len = length($ntxts);
	prt( "Done Re-lining - got $len characters, depth=$max...\n" );
	$$rdep = $max;	# return MAX depth of BRACES
	return $ntxts;
}

sub get_struc_mem_names($) {
	my ($rh) = @_;
	my ($k, $v, $n, $n2);
   my $names = '';
	foreach $k (keys %{$rh}) {
		if ($k =~ /^$mem_bgn/) { # member - use only MEMBER keys
			$v = ${$rh}{$k};	# extract the array
			$n = $$v[$O_NAM];	# [1] - get the name of the member
			$n2 = $$v[$O_FNM];	# function pointer name
         $names .= ' ' if length($names);
         if (length($n2)) {
            $names .= $n2;
         } else {
            $names .= $n;
         }
		}
	}
	return $names;
}


sub offset_in_hash($$) {
	my ($off,$rh) = @_;
	my ($k, $v, $n, $n2);
	foreach $k (keys %{$rh}) {
		if ($k =~ /^$mem_bgn/) { # member - use only MEMBER keys
			$v = ${$rh}{$k};	# extract the array
			$n = $$v[$O_NAM];	# [1] - get the name of the member
			if ($n eq $off) {
				return $k;
			}
			$n2 = $$v[$O_FNM];	# function pointer name
			if (length($n2) && ($n2 eq $off)) {
				return $k;
			}
         # 20090830 - what about names like 'enc_name[50]'...
         if ($n =~ /^(\w+)\s*\[/) {
            $n2 = $1;
            if ($n2 eq $off) {
               return $k
            }
         }
			# 20090827 - exclude this, can be a problem, like 'name' and 'long-name' for example
			#if ($n =~ /$off/) {
			#	return $k;
			#}
		}
	}
	return "";
}

sub word_is_rh_name($$) {
	my ($wd,$rh) = @_;
	my ($k,$v);
	$k = $str_nam;
	if (defined ${$rh}{$k}) {
		$v = trim_all(${$rh}{$k});
		$v =~ s/;$//;	# remove the semi-colon for the compare
		$v = trim_all($v);
		if ($v eq $wd) {
			return 1;
		} else {
			prt("[dbg15] Note: hash [$k]=[$v], NOT equal to [$wd]!\n") if ($dbg15);
		}
	} else {
		prtw("WARNING: No [$k] key in hash!\n");
	}
   show_struc_defines( 1, $rh, $wd );
	return 0;
}

sub instance_space_split($) {
	my ($txt) = shift;
	my @a = ();
	my $ll = length($txt);
	my ($j, $c, $wd);
	$wd = '';
	for ($j = 0; $j < $ll; $j++) {
		$c = substr($txt,$j,1); #// char by char
		if ($c =~ /\s/) {	# if a SPACEY char
			push(@a,$wd) if length($wd);	# stack word, if any
			$wd = '';	# and clear word
		} elsif ($c =~ /\w/) {	# if alpha numeric
			$wd .= $c;	# store it
      } elsif ($c eq '[') {
         # 20090829 - ensure this '[' is together with ']', 
         # and is split from name - so 'foo[1]' becomes 'foo [1]'
      	push(@a,$wd) if length($wd);
         $wd = $c;
         $j++;
      	for (; $j < $ll; $j++) {
            $c = substr($txt,$j,1); #// char by char
            $wd .= $c;
            if ($c eq ']') {
      			push(@a,$wd) if length($wd);
               $wd = '';
               last;
            }
         }
		} else {
         # not spacey, nor alphanumeric - is punctuation and other specials
			push(@a,$wd) if length($wd);
			$wd = $c;
		}
	}
	push(@a,$wd) if length($wd);
	return @a;
}

# is it something like
# static const DVprofile dv_profiles[] = {
sub is_instance_definition($$$) {
	my ($ln,$rh,$rmh) = @_;
	my ($len, $i, $cc, $word, $line, @arr, $sname, $iname, $al, $msg, $isize, $snum, $key, $stage);
	$len = length($ln);
	#@arr = split(/\s/,$ln);
	@arr = instance_space_split($ln);
	$al = scalar @arr;
	$line = '';
	$iname = '';
	$sname = '';
	$snum = '';
   $stage = 0;
	$isize = $bad_posn; # = -200;
   if ($dbg22) {
      prt("[dbg22] Doing is id - split $al...\n");
      for ($i = 0; $i < $al; $i++) {
      	$word = $arr[$i];
      	prt( "".($i + 1)." $word\n" );
      }
   }
	if ( !($ln =~ /=\s*\{$/) ) {
		prt( "[dbg16] Line [$ln] is NOT instance definition...\n" ) if ($dbg16);
		return 0;
	}
	prt( "Line [$ln] looks like an instance definition...\n" );
	for ($i = 0; $i < $al; $i++) {
		$word = $arr[$i];
		next if ($word eq '}');
		$msg = "Checking [$word] ";

		# skip over these words
		if ( word_in_array($word, \@res_words) ) {
			$line .= ' ' if (length($line));
			$line .= $word;
			prt( "[dbg16] $msg - it is in res_words array\n" ) if ($dbg16);
			next;
		}

		# must have structure name, and instance name
		if (length($sname) && length($iname)) {
			next if ($word eq '=');
			next if ($word eq '{');
			next if (($word eq '};')||($word =~ /}\s*;/));
			next if ($word eq '}');
		}

		# check if it is the structure name...
		#if ( word_is_rh_name($word,$rh) ) {
      # 20090903 - do NOT do this if already had 'sname'
		if ( (length($sname) == 0) && word_is_rh_name($word,$rh) ) {
			$sname = $word;
         $stage++;
			prt( "[dbg16] $msg - it is the struct name\n" ) if ($dbg16);
			next;
		}

		# must have structure NAME first
      # 20090829 - change in special space split ensures this SHOULD be the 'instance' name
      # this will FAIL on 'anonymous' structure
      if (length($sname) && !length($iname) ) {
         $iname = $word;
         $stage++;
			prt( "[dbg16] $msg - assumed instance name...\n" ) if ($dbg16);
         next;
      }

		#if ($word =~ /^[\w\[\]]$/ ) {
		#if ($word =~ /^\w+[\[\]\w]*$/) {
		#if (length($sname) && ($word =~ /^\w+\s*\[(\w*)\]$/))
		#if (length($sname) && ($word =~ /^\w+\s*(\[(\w*)\])?$/))
		#if (length($sname) && ($word =~ /^\w*\s*(\[(\w*)\])?$/)) {  # 20090829 - allow no 'alphanums' before [...]
		if ( ($stage >= 2) && ($word =~ /^\[\s*(\w*)\s*\]$/) ) {  # 20090829 - in fact new special split separates [...]
			if (defined $1) {
				$snum = $1;
				$snum =~ s/^\[//;
				$snum =~ s/\]$//;
				# 20090827 - clear any space
            $snum = trim_ends($snum);
				# $snum = substr($snum,1) while ($snum =~ /^\s/);	# clear leading
				# $snum = substr($snum,0,length($snum)-1) while ($snum =~ /\s$/);	# and trailing
				if (length($snum)) {
					prt("[dbg21] Got length [$snum](".length($snum).") - decode or lookup in enum...\n") if ($dbg21);
					if ($snum =~ /^\d+$/) {
						# is a whole number
						$isize = $snum;
					} else {
						# assume alphanumeric
						# $str_enum = 'ENUMERATION';
						#if (defined ${$rh}{$str_enum}) {
						#	my $reh = ${$rh}{$str_enum};
						$key = get_unique_key($str_enum);
						if (defined ${$rmh}{$key}) {
							my $reh = ${$rmh}{$key};
							foreach my $k (keys %{$reh}) {
								if ($k eq $snum) {
									$isize = ${$reh}{$k};
									last;
								}
							}
							prtw("WARNING: $msg - found [$key], checked [$snum], but isize=[$isize]!\n") if ($isize < 0);
							#prtw("WARNING: $msg - found [$str_enum], but isize=[$isize]!\n") if ($isize < 0);
						} else {
							prtw( "WARNING: $msg gave [$snum] as size, but no [$str_enum] in ref hash!\n" );
						}
					}
				}
            next;
			}
			
         #prt( "[dbg16] $msg - assumed instance name... num=[$snum], if any\n" ) if ($dbg16);
			#if (length($iname)) {
			#	prtw( "WARNING: $msg - Already HAVE iname=[$iname]!\n" );
			#} else {
         #   $iname = $word;
         #}
			next;
		}

		# must have structure name, and instance name
		if (length($sname) && length($iname)) {
			next if ($word eq '=');
			next if ($word eq '{');
			next if (($word eq '};')||($word =~ /}\s*;/));
			next if ($word eq '}');
		}

		prtw( "WARNING: $msg - NOT PARSED in is_instance_definition!\n" );
      my_exit(1, "is_instance_definition: line=[$ln]\n" );
	}

	if (length($sname) && length($iname)) {
      # put entries decoded in the MASTER HASH

		# ${$rh}{$str_inst} = $iname;
      $key = get_unique_key($mast_iname);
		${$rmh}{$key} = $iname;	# store ONLY in master HASH
  		prt( "[dbg16] Set key=[$key], with iname=[$iname]\n" ) if ($dbg16);

      #${$rh}{$str_inst} = $ln;
		$key = get_unique_key($mast_inst);
		${$rmh}{$key} = $ln;	# store ONLY in master HASH

		#${$rh}{$str_len} = $isize if ($isize > 0);
		if ($isize > 0) {
			$key = get_unique_key($mast_len);
			${$rmh}{$key} = $isize; # AND the SIZE of the structure, if ANY...
   		prt( "[dbg16] Set key=[$key], with isize=[$isize]\n" ) if ($dbg16);
		}

		return 1;
	}

	return 0;
}

#my $F_HADID  = 1;
#my $F_HADEND = 2;
#my $F_HADDOT = 4;
sub add_line_2_hash($$$$$$) {
	my ($rfsflag, $lvl, $lnn, $ln, $rh, $rmh) = @_;
	my $wn = "WARNING:$lnn:$lvl:";
	my ($key, $off, $equ);
	prt("[dbg20] Add [$ln] to hash...(fsflag=$$rfsflag)\n") if ($dbg20);
	if ($$rfsflag & $F_HADEND) {
		prtw("wn: add line called after structure CLOSED\n");
		return;
	} elsif ($$rfsflag & $F_HADID) {
		###if ($ln =~ /^\.(.+)=(.+)/) {
		if ($ln =~ /^\.\w{1}(.+)=(.+)/) {
			# begins with a dot entries...
			my @a = split('=',$ln);
			my $ca = scalar @a;
			if ($ca != 2) {
				prtw("$wn Split FAILED on [$ln]!\n");
			} else {
				# got two elements
				$$rfsflag |= $F_HADDOT;
				$off = trim_all($a[0]);
				$equ = trim_all($a[1]);
				if ($off =~ /^\./) {
					$off = substr($off,1);
					$equ =~ s/,$//;
					$key = offset_in_hash($off,$rh);
					if (length($key)) {
						# success
						$$rh{$key}[$O_DEC] = "$ln";
						$$rh{$key}[$O_VAL] = "$equ";
						prt( "[dbg07] Added [$equ] to key [$key], for off[$off]\n" ) if ($dbg07);
                  ${$rfsflag} |= $F_HADMEM;
					} else {
						prtw( "$wn NO FIND split [$off] = [$equ] NOT HANDLED! line[$ln] (4)\n" );
                  $key = get_struc_mem_names($rh);
                  prtw( "list=[$key]\n" );
					}
				} else {
					prtw( "$wn CHECK split [$off] = [$equ] NOT HANDLED! (5)\n" );

				}
			}
		} else {
			# ==========================================================================
			# NOT a .abc=def, entry
			if ($ln eq '{') {
				prt( "[dbg18] $lnn:$lvl: Open new BLOCK... on [$ln]\n") if ($dbg18);
			} elsif ($lvl == 0) {
				if ($ln =~ /}\s*;/) {
					prt( "$lnn:$lvl: End of definitions... on [$ln]\n");
					$$rfsflag |= $F_HADEND;	# signal END of structure
				} else {
					prtw( "$wn line[$ln] NOT HANDLED! (1)\n" );
				}
			} elsif ($lvl == 1) {
				if ($ln =~ /}\s*,/) {
					prt( "[dbg18] $lnn:$lvl: End of BLOCK... on [$ln]\n") if ($dbg18);
				} elsif ($ln eq '}') {
					# what is this??? but skip it anyway
				} else {
					if (!($$rfsflag & $F_HADDOT) && ($ln =~ /,$/)) {
						# assume a member VALUE
						$ln =~ s/,$//;	# clear the comma
						$off = ${$rh}{$mem_nxt};	# get next member counter
						$off++;	# bump to NEXT
						${$rh}{$mem_nxt} = $off;
						$key = sprintf("%s%04d",$mem_bgn,$off);	# member and number
						${$rh}{$key}[$O_VAL] = $ln;
						prt( "[dbg18|20|07] $lnn:$lvl: Set member [$key] value to [$ln]\n") if ($dbg18 | $dbg20 | $dbg07);
                  ${$rfsflag} |= $F_HADMEM;
					} else {
						prtw( "$wn line[$ln] NOT HANDLED! (2)\n" );
                  if (!($$rfsflag & $F_HADDOT)) {
                     prt( "Have NOT had a DOT member!\n" );
                  }
                  if (!($ln =~ /,$/)) {
                     prt( "Line does NOT end in comma!\n" );
                  }
                  my_exit(1, "FIX ME!\n");
					}
				}
			} else {
				# handle things like - '[PIX_FMT_YUV420P] = {'
				if ($ln =~ /^\[(\w+)\]/) {
					$off = $1;
					prt( "[dbg19] $lnn:$lvl: [$ln] as offset [$off]\n") if ($dbg19);
					# $str_enum = 'ENUMERATION';
					my $num = $bad_posn; #-200;
					my $key = get_unique_key($str_enum);
					if (defined ${$rmh}{$key}) {
						my $reh = ${$rmh}{$key};
						foreach my $k (keys %{$reh}) {
							if ($k eq $off) {
								$num = ${$reh}{$k};
								last;
							}
						}
						prt( "[dbg19] $lnn:$lvl: [$off] has val [$num]\n") if ($dbg19);
						# $copy_hash{$str_off} = $blknum;	# OFFSET = order of this block (-1 = no order)!!!
						$key = $str_off;
						if ($num != $bad_posn) {
							${$rh}{$key} = $num;	# $bad_posn (was -200) is NO NUMBER, else a value given
						}
					} else {
						prtw( "$wn NO ENUMERATION rh! to solve $off\n" );
					}
				} else {
					prtw( "$wn line[$ln] NOT HANDLED! (3)\n" );
				}
			}
		}
	} else {
		if ( is_instance_definition($ln,$rh,$rmh) ) {
			$key = get_unique_key($mast_inst);
			$equ = ${$rmh}{$key};
			prt( "$lnn:$lvl: Set Mast.Inst[$key]=[$equ]\n" );
			$key = get_unique_key($mast_len);
			if (defined ${$rmh}{$key}) {
				$off = ${$rmh}{$key};
				prt( "$lnn:$lvl: Set Mast.Leng[$key]=[$off]\n" );
			} else {
				$off = $bad_posn;
			}
			$$rfsflag |= $F_HADID;	# had ID
		}
	}
	prt("[dbg20] Done [$ln] to hash...(fsflag=$$rfsflag)\n") if ($dbg20);
}

sub test_depth($$) {
	my ($gcc, $rh) = @_;
	my $depth = 0;
	$dbg03 = 1;	# set DEBUG ON
	$gcc = reline_instance_string(\$depth, $gcc);	# remove some spaces...
}

sub clear_hash_values($) {
	my ($rh) = shift;
	my ($k,$v,$ko, $kd);
	$ko = $str_off;
	$kd = $str_done;
	foreach $k (keys %$rh) {
		if ($k =~ /^$mem_bgn/) { # member
			$$rh{$k}[$O_VAL] = "";
			if (defined ${$rh}{$ko}) {
				delete $rh->{$ko};
			}
			if (defined ${$rh}{$kd}) {
				delete $rh->{$kd};
			}
		}
	}
	${$rh}{$mem_nxt} = 0;	# set the next member counter to zero
}

sub get_full_str_txt($$$$) {
   my ($sn, $ln, $tx, $rni) = @_;
   my $ft = "$sn tempinst = ";
   my ($j,$c,$max,$opn);
   $opn = 0;
   $max = length($ln);
   prt("For [$sn] have L=[$ln] T=[$tx]${$rni}\n");
   for ($j = 0; $j < $max; $j++) {
      $c = substr($ln,$j,1);
      if ($c eq '{') {
         last;
      }
   }
   if ($c eq '{') {
      # use up any balance of the line
      $ft .= $c;
      $ft .= "\n";
      $j++;
      $opn++;
      for (; $j < $max; $j++) {
         $c = substr($ln,$j,1);
         $c = ' ' if ($c eq "\n");
         $ft .= $c;
         $opn++ if ($c eq '{');
         if ($c eq '}') {
            $opn-- if ($opn);
            return $ft if ($opn == 0);
         }
      }
      $max = length($tx);
      $j = 0;
   } else {
      # else search begin in line
      $max = length($tx);
      for ($j = 0; $j < $max; $j++) {
         $c = substr($ln,$j,1);
         if ($c eq '{') {
            $ft .= $c;
            $ft .= "\n";
            $opn++;
            $j++;
            last;
         }
      }
   }

   if ($opn) {
      my ($pc,$nc);
      $c = '';
      for (; $j < $max; $j++) {
         $pc = $c;
         $c = substr($tx,$j,1);
         $nc = (($j + 1) < $max) ? substr($tx,$j+1,1) : '';
         $c = ' ' if ($c eq "\n");
         if ($c =~ /\s/) {
            #if (!($ft =~ /(\s|,)$/))
            if ($ft =~ /\w$/) {
               $ft .= $c;
            }
         } else {
            if (($c eq '.')&&($nc =~ /\w/)) {
               $ft .= "\n";
            }
            if (($c eq '=')&&($nc =~ /\w/)) {
               $ft .= " ";
            }
            $ft .= $c;
         }
         $opn++ if ($c eq '{');
         if ($c eq '}') {
            $opn-- if ($opn);
            if ($opn == 0) {
               $ft =~ s/\}$//;   # remove this TAIL item
               $ft .= "\n";      # go to new line
               $ft .= "};\n";    # add END
               ${$rni} += $j;    # bump return - posn to restart in gcc text block
               return $ft;
            }
         }
      }
   }
   return "";
}

sub complain_if_mast_len($) {
   my ($trmh) = shift;
   my $tk = get_unique_key($mast_len);
   if (defined ${$trmh}{$tk}) {
      prtw("WARNING: HOW DID [$tk] get defined to ".${$trmh}{$tk}."?\n");
   } else {
      prtw("WARNING: Key [$tk] NOT DEFINED\n");
   }
}

# my $mast_copied = 'COPIED';   # count of FILLED members COPIED to master
sub bump_master_copied($) {
   my ($rmh) = shift;
   my $k = get_unique_key($mast_copied);
   if (defined ${$rmh}{$k}) {
      ${$rmh}{$k}++;
   } else {
      ${$rmh}{$k} = 1;
   }
}

sub copy_hash_to_master($$$) {
   my ($inst, $rh, $rmh) = @_;
   my ($msg, $k, $v);
   $msg = sprintf("$mem_bgn%08d", $inst);
	my %copy_hash = ();
   foreach $k (keys %{$rh}) {
      $v = $$rh{$k};
      if ($k =~ /^$mem_bgn/) { # member
         $copy_hash{$k} = [@{$v}]; # store COPY of ARRAY
      } else {
         $copy_hash{$k} = $v; # store string, or hash-ref, or value, or ...
      }
   }
	${$rmh}{$msg} = \%copy_hash;	# THIS SEEMS TO WORK ;=))
}


## comments /* ... */, or // to end of line
##sub fill_struct_per_gcc($$) { # like ($gcc_struct, \%h);
##	my ($gcc, $rh) = @_;
sub fill_struct_per_gcc($$$$) { # like ($gcc_struct, \%h);
	my ($flg, $gcc, $rh, $rmh) = @_;
	my ($i, $len, $pc, $cc, $nc, $ic1, $ic2, $lnn);
	my ($bclvl, $bklvl, $line, $msg, $comm, $inst, $blknum);
	my ($k, $v, $v2);
	my $depth = 0;
	$gcc = reline_instance_string(\$depth, $gcc);	# remove some spaces...
	my @brcstk = ();
	my @brkstk = ();
	my @depitems = ();
	my $flag = 0;
	$len = $depth;
	if ($len == 0) {
		my_exit(1, "CRITICAL ERROR: Got NO DEPTH!\n");
	}
	push(@depitems, [ 0, 0, 0 ]);	# add one extra
	while ($len) {
		push(@depitems, [ 0, 0, 0 ]);
		$len--;
	}
	$ic1 = 0;
	$ic2 = 0;
	$lnn = 1;
	$inst = 0;	# expect mutiple instances
	$len = length($gcc);
	$bclvl = 0;
	$bklvl = 0;
	$blknum = -1;	# order per as found
	prt( "Processing fill struct, $len chars, depth = $depth...\n" );
   prt( "[$dbg08] content[$gcc]\n" ) if ($dbg08);
	for ($i = 0; $i < $len; $i++) {
		$cc = substr($gcc,$i,1);
		$nc = (($i + 1) < $len) ? substr($gcc,$i+1,1) : " ";
		if ($cc eq "\n") {
			if (length($line)) {
            # 20090901 - But this can be a '.' member, which is in fact another structure
            if (($line =~ /^\.(\w+)\s*/) && !($flg & 1)) {
               $k = $1;
					$v = offset_in_hash($k,$rh);
					if (length($v)) {
                  # this IS a member name in this HASH
                  my ($t,$n,$tk);
                  $v2 = ${$rh}{$v};
                  $t = ${$v2}[$O_TYP];
                  $n = ${$v2}[$O_NAM];
                  my ($rmhoh2); # = get_master_hoh();
                  if (defined $mast_ref_hoh) {
                     $rmhoh2 = $mast_ref_hoh;
                  } else {
                     $rmhoh2 = get_master_hoh();
                     $mast_ref_hoh = $rmhoh2;
                  }
                  # complain_if_mast_len($rmhoh2);
                  if (defined ${$rmhoh2}{$t}) {
                     $dbg16 = 1;
                     my $nrh = ${$rmhoh2}{$t};
                     my $sn = ${$nrh}{$str_nam};
                     my $feats = $features;
                     my $newi = $i + 1;   # start from HERE
                     # $feats &= ~($FF_MSCV | $FF_MSC2 | $FF_MSC3 | $FF_MSC4 | $FF_BLAN | $FF_COMM | $FF_COM1 | $FF_COMA | $FF_SORG);	# remove unwanted items
                     $feats &= ~($FF_MSVC_SET | $FF_BLAN | $FF_COMM | $FF_COM1 | $FF_COMA | $FF_SORG);	# remove unwanted items
                     $feats |= ($FF_INLN | $FF_NIND | $FF_NHED);  # add in desired items
                     prt( "$lnn: [$k] is member=[$v]=[$t $n] is another struct [$sn]\n" );
                     my $fline = get_full_str_txt($sn, $line, substr($gcc,$newi), \$newi);
                     if ((length($fline)) && ($newi >= $i)) {
                        prt( "Full line = [$fline]\n" );
                        my $filledrmhoh = fill_struct_per_gcc(1,$fline,$nrh,$rmhoh2);
                        # complain_if_mast_len($filledrmhoh);
                        prt( "$lnn: [$k] is member=[$v]=[$t $n] is another struct [$sn]\n" );
                        prt( "Full line = [$fline]\n" );
                        my $sstg = get_struct_inst_stg($feats,$filledrmhoh);
                        # complain_if_mast_len($filledrmhoh);
                        prt("Suggest = [$sstg]\n");
                        if ($sstg =~ /^\{(.+)\};$/) {
                           # it looks OK
                           prt( "$lnn: OK [$k] [$v]=[$t $n] struct [$sn] VALUE [$sstg] $newi\n" );
                           my $mxrem = $len - $newi;
                           $mxrem = 16 if ($mxrem > 16);
                           my $consum = substr($gcc,$i,$newi-$i);
                           my $remtxt = substr($gcc,$newi,$mxrem);
                           prt( "Check restart - consumed\n[$consum]\nrestart at\n[$remtxt]\n" );
                           $sstg =~ s/;$//;
                           $line =~ s/{$//;
                           $line .= $sstg;
                           $i = $newi;
                        } else {
                           prtw( "WARNING: instance string does NOT conform [$sstg]!\n" );
                        }

                     }
                  } else {
                     prt( "$lnn: [$k] is member=[$v]=[$t $n] in the hash\n" );
                  }

                  #my_exit(1, "TEMPORARY EXIT\n");
               }
            }
				$msg = sprintf("%3d: ", $lnn);
				$msg .= "[$line] passed to add_line_2_hash()";
				prt( "[dbg08] $msg\n" ) if ($dbg08);
				###add_line_2_hash($bclvl, $lnn, $line, $rh, \%mh);
				add_line_2_hash(\$flag, $bclvl, $lnn, $line, $rh, $rmh);
				$line = '';
			}
			$lnn++;
			#if ($lnn == 2) { exit(1); }
			if ($ic2) {
				$msg = sprintf("%3d: ", $lnn);
				$msg .= "Discard: [$comm]";
				prt( "[dbg06] $msg\n" ) if ($dbg06);
			}
			$ic2 = 0;
			$pc = $cc;
			next;
		}
		if ($ic1) {
			# locked in comment - stay to END
			$comm .= $cc;
			if (($cc eq '/') && ($pc eq '*')) {
				$ic1 = 0; # end of comment
				$msg = sprintf("%3d: ", $lnn);
				$msg .= "Discard: [$comm]";
				prt( "[dbg05] $msg\n" ) if ($dbg05);
			}
		} elsif ($ic2) {
			# locked in comment - stay to end of line
			$comm .= $cc;
		} else {
			if (($cc eq '/') && ($nc eq '*')){
				$ic1 = 1;	# process a comment
				$comm = $cc;	# start
				$pc = $cc;	# update previous char
				next;
			}
			if (($cc eq '/') && ($nc eq '/')){
				$ic2 = 1;	# start comment, until EOL
				$comm = $cc; # start comment
				$pc = $cc;  # update prev char
				next;
			}
			#####################################################################
			$line .= $cc; # ADD to line
			if ($cc eq '{') {
				push(@brcstk,[$i, $lnn] );
				$bclvl++;
				# clear depth flags
				$depitems[$bclvl][0] = 0;
				$depitems[$bclvl][1] = 0;
				$depitems[$bclvl][2] = 0;
			} elsif ($cc eq '}') {
				if (@brcstk) {
					# show depth items
					prt( "[dbg09] $bclvl: equ=[".$depitems[$bclvl][0]."], coma=[".$depitems[$bclvl][1]."] dot [".$depitems[$bclvl][2]."]\n" ) if ($dbg09);
					if (($depitems[$bclvl][0] > 0)&&($depitems[$bclvl][2] > 0)) {
						# we have a completed instance - COPY, and SAVE TO master HASH
						# ============================================================
						# At this time this hash copy is in the ORDER found,
						# but by using the [OFF_NUM] = { notation, this could be
						# set at a specific block number (in ascii, but could probably use number?)
						$msg = sprintf("$mem_bgn%08d", $inst);
						$inst++;
						if ($use_copy_hash) {
							my %copy_hash = ();
							foreach $k (keys %{$rh}) {
								$v = $$rh{$k};
								if ($k =~ /^$mem_bgn/) { # member
									$copy_hash{$k} = [@{$v}]; # store COPY of ARRAY
								} else {
									$copy_hash{$k} = $v; # store string, or hash-ref, or value, or ...
								}
							}
							# $copy_hash{$str_off} = $blknum;	# OFFSET = order of this block (-1 = no order)!!!
							#$mh{$msg} = [ %copy_hash ];
							#$master_hash{$msg} = \%copy_hash;	# THIS SEEMS TO WORK ;=))
							${$rmh}{$msg} = \%copy_hash;	# THIS SEEMS TO WORK ;=))
						} else {
							# can NOT seem to get ANY of these working!!!
							my $href2 = {%{$rh}};	# copy an (anonymous) hash ??? maybe, maybe NOT!!!
							#$mh{$msg} = $href2;
							#$master_hash{$msg} = [ $href2 ];
							${$rmh}{$msg} = [ $href2 ];
							#$mh{$msg} = {%{$rh}};
							### my $href_copy = $rh;
							### $mh{$msg} = [ $href_copy ];
						}
						# clear the current HASH values
						clear_hash_values($rh);	# ready for NEXT
                  $flag &= ~$F_HADMEM; # now copied, so remove bit
                  bump_master_copied($rmh);
					}
					pop @brcstk;
				} else {
					prtw("$lnn:$i: WARNING:fill_str: Encountered $cc, with no stack!\n");
				}
				$bclvl-- if ($bclvl);
			} elsif ($cc eq '(') {
				push(@brkstk, [$i, $lnn] );
				$bklvl++;
			} elsif ($cc eq ')') {
				if (@brkstk) {
					pop @brkstk;
				} else {
					prtw("$lnn:$i: WARNING:fill_str: Encountered $cc, with no stack!\n");
				}
				$bklvl-- if ($bklvl);
			} elsif ($cc eq '=') {
				$depitems[$bclvl][0]++;
			} elsif ($cc eq ',') {
            # this is an important CLOSE of an entry
            # but it has to be processed at the SAME level only
				$depitems[$bclvl][1]++;
				prt( "[dbg08] Had COMMA, at level=$bclvl L=[$line]\n" ) if ($dbg08);
			} elsif (($cc eq '.') && ($nc =~ /\w/)) {
				$depitems[$bclvl][2]++;
			}
		}
		$pc = $cc;
	}

   if ($flag & $F_HADMEM) {
		$msg = sprintf("$mem_bgn%08d", $inst);
      $inst++;
      if ($use_copy_hash) {
         my %copy_hash = ();
         foreach $k (keys %{$rh}) {
            $v = $$rh{$k};
            if ($k =~ /^$mem_bgn/) { # member
               $copy_hash{$k} = [@{$v}]; # store COPY of ARRAY
            } else {
               $copy_hash{$k} = $v; # store string, or hash-ref, or value, or ...
            }
         }
         # $copy_hash{$str_off} = $blknum;	# OFFSET = order of this block (-1 = no order)!!!
         #$mh{$msg} = [ %copy_hash ];
         #$master_hash{$msg} = \%copy_hash;	# THIS SEEMS TO WORK ;=))
         ${$rmh}{$msg} = \%copy_hash;	# THIS SEEMS TO WORK ;=))
      } else {
         # can NOT seem to get ANY of these working!!!
         my $href2 = {%{$rh}};	# copy an (anonymous) hash ??? maybe, maybe NOT!!!
         #$mh{$msg} = $href2;
         #$master_hash{$msg} = [ $href2 ];
         ${$rmh}{$msg} = [ $href2 ];
         #$mh{$msg} = {%{$rh}};
         ### my $href_copy = $rh;
         ### $mh{$msg} = [ $href_copy ];
      }
      # clear the current HASH values
      clear_hash_values($rh);	# ready for NEXT
      $flag &= ~$F_HADMEM; # now copied, so remove bit
      bump_master_copied($rmh);
   }

	if (@brcstk) {
		prtw( "WARNING: ".scalar @brcstk." items in brace stack!\n" );
	}
	if (@brkstk) {
		prtw( "WARNING: ".scalar @brkstk." items in bracket stack!\n" );
	}
	$ic1 = 0;
	$ic2 = 0;
	foreach $k (keys %{$rmh}) {
		$ic1++;
		if (!key_is_unique_type($k)) {
			$ic2++;
		}
	}
	$k = get_total_blocks($rmh);
	if ($k > 0) {
		$cc = "total = $k";
	} else {
		$cc = "with no total blocks";
	}
	prt("Done fill struct, with $ic1 members, $ic2 blocks, $cc...\n" );
	##return \%mh;
	return $rmh;
}

sub set_debug_on_fill() {
	$dbg08 = 1;  # show each line in structure filling
}

sub get_hash_instance($) {
	my ($rh) = shift;
	my ($msg, $key, $val, $equ, $cnt);
	$cnt = 0;
	foreach $key (keys %$rh) {
		$val = $$rh{$key};
		if ($key =~ /^$mem_bgn/) { # member
			$cnt++;
		}
	}

	$msg = '';
	$key = $str_tag; # 'TAG'
	if (defined $$rh{$key}) {
		$val = $$rh{$key};
		$msg .= "$val {\n";
	}
	foreach $key (sort keys %$rh) {
		$val = $$rh{$key};
		$cnt-- if ($cnt);
		if ($key =~ /^member/) {
			$equ = $$val[$O_VAL];
			$msg .= " $equ";
			$msg .= ',' if ($cnt);
			$msg .= "\n";
		}
	}
	$key = $str_nam; # 'NAME'
	if (defined $$rh{$key}) {
		$val = $$rh{$key};
		$msg .= "} $val ;\n";
	}
	prt("************************************************\n");
	prt($msg);
	prt("************************************************\n");
	return $msg;	
}

# 20090825 - add dealing with feature flags
# these are only added under certain program conditions
# my $FF_BLAN = 512;	# generate a BLANK instance block
# my $FF_WNUM = 1024;	# we have an instance with set number of blocks in head
# my $FF_WPOS = 2048;	# this member has a specific position
sub get_hash_instance2($$$$$) {
	my ($feat, $max, $cur, $rh, $rmh) = @_;
	my ($msg, $key, $val, $equ, $cnt, $iind, $mind, $typ, $nam, $min, $tst, $tlen, $min2, $org);
	my ($fnm,$iname,$cont,$tmp, $tmp2);
    my $add_blln = 1;
    $iname = "Unknown_FIXME";  # start as UNKNOWN
	$cnt = 0;
	foreach $key (keys %$rh) {
		$val = $$rh{$key};
		if ($key =~ /^$mem_bgn/) { # member
			$cnt++;
		}
	}
	$mind = $memb_indent;
	$iind = $inst_indent;
	$mind = $memb_indent.$inst_indent if ($max > 1);
   $key = get_unique_key($mast_iname);
   if (defined ${$rmh}{$key}) {
      $iname = ${$rmh}{$key}; # get the instance NAME
   }

	$min = 0;
	$min2 = 0;
	if ($feat & $FF_COMM) {
		foreach $key (sort keys %$rh) {
			$val = $$rh{$key};
			if ($key =~ /^$mem_bgn/) { # member
				$typ = $$val[$O_TYP];
				$equ = $$val[$O_VAL];
   			$fnm = $$val[$O_FNM];	# get function name, if ANY
				$nam = $$val[$O_NAM];
				$org = $$val[$O_ORG];

            if (length($equ) == 0) {
               if (($typ =~ /\*$/) || (length($fnm) && ($nam =~ /\*/))) {
                  $equ = "NULL";
               } elsif ($typ =~ /enum\s+CodecID/) {
                  $equ = 'CODEC_ID_NONE';
               } else {
                  $equ = "0";
               }
            }
            # 20090904 - watch for these shortenned names, like $tmp = "_s_AVC_".$iname;
            if (($feat & $FF_MSC2) && ($equ =~ /\(\s*const\s+AVCodecTag\s*\*\s*const\s*\[\]\s*\)\s*\{(.+)\}/)) {
               $tlen = length($mind) + 1 + 7 + length($iname) + 1;
            } elsif (($feat & $FF_MSC3) && ($equ =~ /\(\s*enum\s+PixelFormat\s*\[\s*\]\s*\)\s*\{(.+)\}/)) {
               $tlen = length($mind) + 1 + 7 + length($iname) + 1;
            } elsif (($feat & $FF_MSC4) && ($equ =~ /\(\s*enum\s+SampleFormat\s*\[\s*\]\s*\)\s*\{(.+)\}/)) {
               $tlen = length($mind) + 1 + 7 + length($iname) + 1;
            } elsif (($feat & $FF_MSC5) && ($equ =~ /\(\s*(\w+)\s*\[\s*\]\s*\)\s*\{(.+)\}/)) {
               $tmp2 = $1;
               $cont = $2;
               $tmp = "_s_".$tmp2."_".$iname;
               $tlen = length($tmp);
            } else {
   				$tst = "$mind $equ,";
   				$tlen = length($tst);
            }
				$min = $tlen if ($tlen > $min);

				$tst = "$typ $nam";
				$tlen = length($tst);
				$min2 = $tlen if ($tlen > $min2);
			}
		}
	}

   # 20090903 limit the 'spacing' added
   $min = $max_spacing_out if ($min > $max_spacing_out);
   $min2 = $max_spacing_out2 if ($min2 > $max_spacing_out2);

	# START building string returned
	# ==============================
	$msg = '';  # blank it
	if ($cur == 1) {	# if FIRST instance
      #$key = get_unique_key($mast_iname);
      #if (defined ${$rmh}{$key}) {
      #   $iname = ${$rmh}{$key}; # get the instance NAME
      #}

      if ($feat & $FF_NHED) {
         $msg .= "{ ";
      } else {
         $key = get_unique_key($mast_inst); # 'INSTANCE' - should have been SAVED
         if (defined ${$rmh}{$key}) {
            $val = ${$rmh}{$key};
            $msg .= "$val";	# should be up to and including ' = {'
         } else {
            # kludge an instance
            $key = $str_tag; # 'TAG'
            if (defined $$rh{$key}) {
               $val = $$rh{$key};
               $msg .= "$val UNKNOWN_FIXME";
               $msg .= "[$max]" if ($max > 1);
               $msg .= " {"; # start the HEADER
            } else {
               # ok MUST have SOME instance heading, so
               $key = $str_nam;	# name of structure
               if (defined $$rh{$key}) {
                  $val = $$rh{$key};
                  $msg .= "typedef struct $val INSTANCE_FIXME[] = {\n";
               } else {
                  $msg .= "typedef struct NAME_FIXME INSTANCE_FIXME[] = {";
               }
            }
         }
         if ($feat & $FF_COMM) {
            if ($feat & $FF_WNUM) {
               $val = get_total_blocks($rmh);
               if ($val > 0) {
                  if ($feat & $FF_COM1) {
                     $msg .= " /* total blocks = $val */"
                  } else {
                     $msg .= " // total blocks = $val"
                  }
               }
            }
         }
      }  # skip header or not

      if ($feat & $FF_INLN) {
         $msg .= " " if ($msg =~ /\w$/);
      } else {
         $msg .= "\n"; # done the HEADER
      }

      # AFTER HEADER
		if ($max > 1) {
			$msg .= $iind."{";
			if ($feat & $FF_COMM) {
				if ($feat & $FF_COM1) {
					$msg .= " /* block = $cur */"
				} else {
					$msg .= " // block = $cur"
				}
			}
			$msg .= "\n";
		}
	} else {
		$msg .= $iind."{";	# open next instance
		if ($feat & $FF_COMM) {
			if ($feat & $FF_COM1) {
				$msg .= " /* block = $cur */"
			} else {
				$msg .= " // block = $cur"
			}
		}
		$msg .= $iind."\n";	# open next instance
	}

	# add the values of the members
    # =============================
	foreach $key (sort keys %$rh) {
	    $val = $$rh{$key};
		if ($key =~ /^$mem_bgn/) { # member
			$cnt-- if ($cnt);	# decement counter, to know last member
			if ($feat & $FF_SORG) {
				$org = $$val[$O_DEC];
				$msg .= $mind."/* $org */\n";
			}
			$typ = $$val[$O_TYP]; # [0]
			$nam = $$val[$O_NAM]; # [1]
			$equ = $$val[$O_VAL]; # [3]
			$fnm = $$val[$O_FNM];	# get function name, if ANY
			#$equ = "0" if (length($equ) == 0);
			if (length($equ) == 0) {
				if (($typ =~ /\*$/) || (length($fnm) && ($nam =~ /\*/))) {
					$equ = "NULL";
            } elsif ($typ =~ /enum\s+CodecID/) {
                    $equ = 'CODEC_ID_NONE';
				} else {
					$equ = "0";
				}
			}

            # IF generating a BLANK strcuture view
			if ($feat & $FF_BLAN) {
				# if ($typ =~ /\*$/)
				if (($typ =~ /\*$/) || (length($fnm) && ($nam =~ /\*/))) {
					$equ = "NULL";
				} else {
					$equ = "0";
				}
            }

            # potential MODIFIERS of the $equ string
            # 1 - if AVCodecTag
            if ($feat & $FF_MSC2) {
                # watch for .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0},
                if ($equ =~ /AVCodecTag/) {
                    ### prt("CHECKME [$equ]\n"); # (const AVCodecTag* const []){ff_codec_wav_tags, 0}
                    if ($equ =~ /\(\s*const\s+AVCodecTag\s*\*\s*const\s*\[\]\s*\)\s*\{(.+)\}/) {
                        $cont = $1;
                        $tmp = "_s_AVC_".$iname;
                        prt( "Fixing [$iname][$tmp] for AVCodecTag [$cont]!\n" );
                        if ($cont =~ /^(\s*\w+\s*,)+\s*0\s*$/) {
                            # 20090907 - get this RIGHT!
                            # need like 'static const AVCodecTag * _s_AVC_wav_demuxer[] = {ff_codec_wav_tags, 0};
                            $tst = "static const AVCodecTag * ".$tmp."[] = {$cont};\n";
                            # $tst = "static AVCodecTag ".$tmp."[] = {$cont};\n";
                            $msg = $tst.$msg;
                            $equ = $tmp;
                        } else {
                            prtw( "WARNING: On [$equ], does not look right [$cont]!\n" );
                            my_exit(1, "FIXME\n");
                        }
                    } else {
                        prtw( "WARNING: Did regex FAIL on [$equ]! - CHECKME!\n" );
                    }
                }
            }
            # 2 - if enum PixelFormat
            if ($feat & $FF_MSC3) {
                # fix (enum PixelFormat[]) {PIX_FMT_YUV411P, PIX_FMT_YUV422P, PIX_FMT_YUV420P, PIX_FMT_NONE},
                if ($equ =~ /enum\s+PixelFormat/) {
                    if ($equ =~ /\(\s*enum\s+PixelFormat\s*\[\s*\]\s*\)\s*\{(.+)\}/) {
                        $cont = $1;
                        $tmp = "_s_PF_".$iname;
                        prt( "Fixing [$iname][$tmp] for PixelFormat [$cont]!\n" );
                        if ($cont =~ /^(\s*\w+\s*,)+\s*(\w+|0)\s*$/) {
                            $tst = "static const enum PixelFormat ".$tmp."[] = {$cont};\n";
                            $msg = $tst.$msg;
                            #$equ = "(const enum PixelFormat *)$tmp";
                            $equ = "$tmp";
                        } else {
                            prtw( "WARNING: On [$equ], does not look right [$cont]! CHECKME!\n" );
                            my_exit(1, "get_hash_instance2: FIXME!");
                        }
                    } else {
                        prtw( "WARNING:2: Did regex FAIL on [$equ]! - CHECKME!\n" );
                        my_exit(1, "get_hash_instance2: FIXME!");
                    }
                }
            }
            # 3 - if enum SampleFormat
            if ($feat & $FF_MSC4) {
                # (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE}
                if ($equ =~ /enum\s+SampleFormat/) {
                    if ($equ =~ /\(\s*enum\s+SampleFormat\s*\[\s*\]\s*\)\s*\{(.+)\}/) {
                        $cont = $1;
                        $tmp = "_s_SF_".$iname;
                        prt( "Fixing [$iname][$tmp] for SampleFormat [$cont]!\n" );
                        if ($cont =~ /^(\s*\w+\s*,)+\s*(\w+|0)\s*$/) {
                            $tst = "static const enum SampleFormat ".$tmp."[] = {$cont};\n";
                            $msg = $tst.$msg;
                            $equ = "$tmp";
                        } else {
                            prtw( "WARNING: On [$equ], does not look right [$cont]! CHECKME!\n" );
                            my_exit(1, "get_hash_instance: FIXME!");
                        }
                    } else {
                        prtw( "WARNING: Did regex FAIL on [$equ]! - CHECKME!\n" );
                        my_exit(1, "get_hash_instance: FIXME!");
                    }
                }
            }
            # 4 if an anonymous structure in structure
            if ($feat & $FF_MSC5) {
                # (int64_t[]){ CH_LAYOUT_MONO, CH_LAYOUT_STEREO, ..., 0 }  /* const int64_t * channel_layouts */
                if ($equ =~ /\(\s*(\w+)\s*\[\s*\]\s*\)\s*\{(.+)\}/) {
                    $tmp2 = $1;
                    $cont = $2;
                    $tmp = "_s_".$tmp2."_".$iname;
                    prt( "Fixing [$iname][$tmp] for anon array [$cont]!\n" );
                    #if ($cont =~ /^(\s*(\w+|\||\(|\))\s*,)+\s*(\w+|\||0|\(|\))\s*$/) {
                    $tst = "static $tmp2 ".$tmp."[] = {$cont};\n";
                    $msg = $tst.$msg;
                    $equ = "$tmp";
                #} else {
                #   prtw( "ERROR: On\n[$equ]\ndoes not look right\n[$cont]!\nCHECKME!\n" );
                #   exit(1);
                }
            }


            if ( $add_blln && ($feat & $FF_BLLN) && (length($equ) > $max_long) && ($equ =~ /,/)) {
                # we can TRY to SPLIT the equ, if very LONG
                my @arr = split(",",$equ);  # split on the COMMA
                my $acnt = scalar @arr;
                my $ntxt = '';
                $tst = '';
                $tst .= "\n" if ($cur == 1);    # start a NEW line, if FIRST member
                for (my $a = 0; $a < $acnt; $a++) {
                    if ($feat & $FF_NIND) {
                        $ntxt .= ',' if (length($ntxt));
                    } else {
                        if (length($ntxt) == 0) {
                            $ntxt = "$mind ";
                        } else {
                            $ntxt .= ',';
                        }
                    }
                    $ntxt .= $arr[$a];
                    if (length($ntxt) > $max_long) {
                        if (($a + 1) < $acnt) {
                            $ntxt .= ',';
                        }
                        $tst .= $ntxt."\n";
                        $ntxt = '';
                    }
                }
                $tst .= $ntxt if (length($ntxt));
            } else {
                if ($feat & $FF_NIND) {
                    $tst = "$equ";
                } else {
                    $tst = "$mind $equ";
                }
            }
            # CLOSING the definition
			$tst .= ',' if ($cnt);	# if NOT last member

            # Adding a comment after the definition
			if ($feat & $FF_COMM) {
				$tst .= ' ' while (length($tst) < $min);
			}
			$msg .= $tst;

			if ($feat & $FF_COMM) {
				$tst = "$typ $nam";
				if ($feat & $FF_COM1) {
					if ($feat & $FF_COMA) {
						$tst .= ' ' while (length($tst) < $min2);
					}
					$msg .= " /* $tst */";
				} else {
					$msg .= " // $tst";
				}
			}

            if ($feat & $FF_INLN) {
                $msg .= " " if ($msg =~ /(\w|,)$/);
            } else {
                $msg .= "\n"; # to next line
            }
		}
	}

	if ($cur == $max) {	# last instance
        $msg .= "\n"; # 20090927 - add a NEW line at the END
		$msg .= $iind."}\n" if ($max > 1);
		$msg .= "};";
        $msg .= "\n";   # 20090927 - add a NEW line at the END
	} elsif ($max > 1) {
		$msg .= $iind."},"; # not last, so just close instance - more to come
    }

    $msg .= "\n" if !($feat & $FF_INLN);

	#prt("************************************************\n");
	#prt($msg);
	#prt("************************************************\n");
	return $msg;	
}

sub find_block_at($$$) {
	my ( $cnt, $rmh, $rrh ) = @_;
	my ($k, $rh, $kd, $k2, $pos);
	$kd = $str_done;
	$k2 = $str_off;
	foreach $k (keys %{$rmh}) {
		if ( !key_is_unique_type($k)) { # like say $k =~ /^\@_/, or ...
			$rh = ${$rmh}{$k};
			${$rrh} = $rh;
			if (${$rh}{$kd} == 0) {
				# not done
				if (defined ${$rh}{$k2}) {
					$pos = ${$rh}{$k2};
					if ($pos >= 0) {
						if ($pos == $cnt) {
							return 1;
						}
					}
				}
			}
		}
	}
	# ok FAILED to find block with THIS POSITION set
	# take the NEXT block, with NO position set
	foreach $k (keys %{$rmh}) {
		if ( !key_is_unique_type($k)) { # like say $k =~ /^\@_/, or ...
			$rh = ${$rmh}{$k};
			${$rrh} = $rh;
			if (${$rh}{$kd} == 0) {
				# not done
				if (defined ${$rh}{$k2}) {
					$pos = ${$rh}{$k2};
					if ($pos >= 0) {
						# this has a position mark - must WAIT its turn
					} else {
						# bad positon mark is like NO position mark
						return 1;
					}
				} else {
					# no position entry
					return 1;
				}
			}
		}
	}
	return 0;	# no record FOUND - gen a BLANK
}

# deal with .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0},
sub extract_avcodectag($$$) {
   my ($txt,$rh,$rmh) = @_;
   my (@arr,$line,$cont,$iname,$key);
   @arr = split(/\n/,$txt);
   $key = get_unique_key($mast_iname);
	$iname = ${$rmh}{$key};	# stored ONLY in master HASH
   foreach $line (@arr) {
      if ($line =~ /\s*const\s+AVCodecTag\s*\*\s*const\s*\[\]\s*\)\s*\{(.+)\}\s*,/) {
         $cont = $1;
         my_exit(1, "NEED FIX of [$iname] for [$cont]!\n" );
      }
   }
}


sub get_struct_inst_stg($$) {
	my ($feat_in,$rmh) = @_;
	my ($msg, $imax, $ccnt, $rh, $k1, $k2, $len, $pcnt, $pos, $f, $kd, $feat, $nuniq);
	$imax = 0;
	$pcnt = 0;
	my %hposn = ();
	my @aposn = ();
	$len = get_total_blocks($rmh);
   $imax = get_copied_count($rmh);
	$k2 = $str_off;
	$kd = $str_done;
	$feat = $feat_in;
	$feat |= $FF_WNUM if ($len > 0);	# we HAVE a fixed NUMBER to do
   $nuniq = 0;
   $msg = '';
	foreach $k1 (keys %{$rmh}) {
		# skip unique keys in master
		if ( !key_is_unique_type($k1)) { # like say $k =~ /^\@_/, or ...
			$rh = ${$rmh}{$k1};
			${$rh}{$kd} = 0;	# mark as NOT done
         if ($k1 =~ /^$mem_bgn/) {  # ONLY check 'member' keys
            if (defined ${$rh}{$k2}) {
               $pos = ${$rh}{$k2};
               if ($pos >= 0) {
                  $pcnt++;
                  $hposn{$pos} = $k1;
                  push(@aposn,[ $pos, $k1 ]);
                  $feat |= $FF_WPOS;	# at least ONE member with BLOCK position
               }
            }
         }
			$nuniq++;	# count not unique members in master
         $msg .= ' ' if length($msg);
         $msg .= $k1;
		}
	}
	prt( "[dbg29] Get struct instance string - total=$len, not-unique=$nuniq, blk/pos=$pcnt copied=$imax\n" ) if ($dbg29);
   prt( "[dbg30] Keys:[$msg]\n") if ($dbg30);
	if (scalar keys(%hposn) != $pcnt) {
		prtw("WARNING: Some position values are repeated! Generation may NOT be SANE!\n");
	}

   # start of MESSAGE returned
   # =========================
   $msg = '';
   $msg .= "#ifdef _MSC_VER /* until MSVC supports dot(.) aligned members, etc */\n" if ($feat & $FF_MSCV);
	$ccnt = 0; # start block counter
	if ($pcnt > 0) {
		$imax = $len if ($len > $imax);
		while( $ccnt < $len ) {
			$f = $feat;	# reset FEATURES
			if ( !find_block_at( $ccnt, $rmh, \$rh ) ) {
				$f |= $FF_BLAN;
			}
			$ccnt++;
			$msg .= get_hash_instance2($f, $imax, $ccnt, $rh, $rmh);
			if ( !( $f & $FF_BLAN ) ) {
				# if NOT a BLANK
				${$rh}{$kd} = 1;	# MARK AS DONE
			}
		}
	} else {
		# no block has a specified position - use decoded position
		foreach $k1 (sort keys %{$rmh}) {
			if (!key_is_unique_type($k1)) { # like say $k =~ /^\@_/, or ...
            if ($k1 =~ /^$mem_bgn/) {  # ONLY check 'member' keys
	   			$rh = ${$rmh}{$k1};
		   		$ccnt++;
			   	$msg .= get_hash_instance2($feat, $imax, $ccnt, $rh, $rmh);
            }
			}
		}
		$f = $feat | $FF_BLAN;
		while ($ccnt < $len) {
			$ccnt++;
			$msg .= get_hash_instance2($f, $imax, $ccnt, $rh, $rmh);
		}
	}
   $msg .= "#else /* !_MSC_VER */\n#endif /* _MSC_VER y/n */\n" if ($feat & $FF_MSCV);
	if ($ccnt < $len) {
		$msg .= "// WARNING: Still to generate ".($len - $ccnt)." BLANK blocks\n";
		prtw( "WARNING: Still to generate ".($len - $ccnt)." BLANK blocks\n" );
	}
   # no, should be done during fetch
   # $msg = extract_avcodectag($msg,$rh,$rmh) if ($feat & $FF_MSC2);
	return $msg;
}


sub show_full_hash_of_hashes($) {
	my ($rfh) = shift;
	my ($k1, $rh, $k2, $v2, @ar, $ct);
	$ct = scalar keys(%$rfh);
	prt( "\nShowing full information on $ct keys...\n" );
	$ct = 0;
	foreach $k1 (sort keys %$rfh) {
		$ct++;
		if (key_is_unique_type($k1)) {
			$v2 = ${$rfh}{$k1};
			prt( "MK:$ct: Unique key [$k1] = value [$v2]\n" );
		} else {
			prt( "MK:$ct: Showing $k1 hash... \n" );
			$rh = ${$rfh}{$k1};	# extract REFERENCE

			#prt( Dumper($rh) );
			show_struct_hash(1, $rh);
		}
	}
	prt( "Done full information show of $ct keys...\n" );
}

sub process_comment($$$$$) {
	my ($onc,$i,$len,$stg,$rlnn) = @_;
	my ($comm, $nc, $cc, $pc);
	$comm = '/';
	$comm .= $onc;
	$i += 2;
	$cc = $onc;
	for (; $i < $len; $i++) {
		$pc = $cc;
		$cc = substr($stg,$i,1);
		$nc = (($i + 1) < $len) ? substr($stg,$i+1,1) : " ";
		if ($onc eq '/') {
			if ($cc eq "\n") {
				$i--;
				last;
			}
			$comm .= $cc;
		} else {
			$comm .= $cc;
			$$rlnn++ if ($cc eq "\n");
			if (($cc eq '/')&&($pc eq '*')) {
				last;
			}
		}
	}
	prt( "[dbg11] Discarded comment [$comm]\n" ) if ($dbg11);
	return $i;
}

sub do_br_stack($$$) {
	my ($cc, $ln, $rbr) = @_;
	my ($lv);
	if ($cc eq '{') {
		push(@{$rbr},$ln);
		$lv = scalar @{$rbr};
		prt( "[dbg12] $ln: Brace stack increased to $lv...\n" ) if ($dbg12);
	} elsif ($cc eq '}') {
		if (@{$rbr}) {
			pop @{$rbr};
			$lv = scalar @{$rbr};
			prt( "[dbg12] $ln: Brace stack decreased to $lv...\n" ) if ($dbg12);
		} else {
			prtw("WARNING: Found $cc, BUT NO STACK!\n");
		}
	}
}

sub deal_with_enum_line($$$$$) {
	my ($lvl, $ln, $lnn, $rh, $rnxt) = @_;
	my ($msg, $len, $itm, $val, $key, $cnt);
	$len = length($ln);
	if ($len) {
		$msg = sprintf("%4d",$lnn);
		prt( "[dbg13] $msg:$lvl: [$ln]\n" ) if ($dbg13);
		if ($lvl == 0) {
			if ($ln =~ /^\w+$/) {
				$key = get_unique_key($str_tag); # something like "\@_".$str_tag."_\@", or...
				${$rh}{$key} = $ln;
			} else {
				if ($ln eq '{') {
					prt( "$lnn:$lvl: Enumeration OPENED on [$ln] line...\n" );
				} elsif ($ln eq '};') {
               $cnt = scalar keys(%{$rh});
					prt( "$lnn:$lvl: Enumeration CLOSED with $cnt keys on [$ln] line.\n" );
				} elsif ($ln =~ /^}\s*(\w*)\s*;$/) {
					if (defined $1) {
						$val = $1;
						$key = get_unique_key($str_nam); # like say "\@_".$str_nam."_\@", or...
						${$rh}{$key} = $val;
                  $cnt = scalar keys(%{$rh});
						prt( "$lnn:$lvl: Enumeration CLOSED, with name=[$val] - $cnt keys\n" );
					} else {
                  $cnt = scalar keys(%{$rh});
						prt( "$lnn:$lvl: Enumeration CLOSED - no name - $cnt keys\n" );
					}
				} else {
					prtw( "WARNING: $lnn:$lvl: Unknown level 0 item [$ln]\n" );
				}
			}
		} else {
			$ln =~ s/,$//;	# lose the comma ending, if any
			if ($ln =~ /^\s*\{\s*$/) {
				prt( "$lnn:$lvl: Enumeration OPENED with [$ln] line.\n" );
			} elsif ($ln =~ /.+=.+/) {
				my @a = split('=',$ln);
				if (scalar @a == 2) {
					$itm = trim_all($a[0]);
					$val = trim_all($a[1]);
					${$rh}{$itm} = $val;
					$val++;
					$$rnxt = $val;
				} else {
					prtw( "WARNING: $lnn:$lvl: Split NOT 2 [$ln]\n" );
				}
			} else {
				$itm = $ln;
				$val = $$rnxt;
				${$rh}{$itm} = $val;
				$$rnxt++;
			}
		}
	}
}

sub show_enum_hash($$) {
	my ($flag,$rh) = @_;
	my ($k, $v, $min, $max, $msg, $nxt, $lmin, $len, $tmp, $cnt, $in, $iv, $iind, $mcnt);
	my ($rmsg, $line);
	$min = 9999999999999999999;
	$max = -1;
	$lmin = 0;
	$iind = $memb_indent;
	$cnt = scalar keys(%{$rh});
	prt( "Show of 'enum' hash... flag = $flag\n" ) if ($flag);
	$mcnt = 0;
	$msg = '';
	foreach $k (keys %{$rh}) {
		$v = ${$rh}{$k};
		if (key_is_unique_type($k)) { # like say $k =~ /^\@_/, or ...
			prt("$k = $v\n") if ($flag & 1);
		} else {
			$len = length($k);
			$lmin = $len if ($len > $lmin);
			$min = $v if ($v < $min);
			$max = $v if ($v > $max);
			$mcnt++;
		}
	}
	prt( "Enum min=[$min], max=[$max]\n" ) if ($flag & 1);
	my %h;
	foreach $k (keys %{$rh}) {
		$v = ${$rh}{$k};
		if ( !key_is_unique_type($k) ) { # like say $k =~ /^\@_/
			$tmp = "$k";
			$tmp .= ' ' while (length($tmp) < $lmin);
			prt("$tmp = $v\n") if ($flag & 2);
			# establish ORDERED hash key
			$msg = sprintf("member%08d", $v);
			$h{$msg} = ["$tmp = $v", $k, $v];
		}
	}

	# OUTPUT the ENUMERATIONS, as coded
	######################################
	$k = get_unique_key($str_tag);	# get say "\@_".$str_tag."_\@"
	prt( "enum" ) if ($flag);
	$rmsg = 'enum';
	if (defined ${$rh}{$k}) {
		prt( " ".${$rh}{$k} ) if ($flag);
		$rmsg .= ' ';
		$rmsg .= ${$rh}{$k};
	}
	prt( " {\n" ) if ($flag);
	$rmsg .= " {\n";
	$nxt = 0;
	$cnt = $mcnt;
	foreach $k (sort keys %h) {
		$v = $h{$k}[0];
		$in = $h{$k}[1];
		$iv = $h{$k}[2];
		$cnt-- if ($cnt);
		$line = $iind."$in";
		if ($iv != $nxt) {
			$nxt = $iv;
			$line .= " = $nxt";
		}
		$line .= "," if ($cnt);
		$line .= "\n";
		if ($flag & 2) {
			#prt("$k = $v\n");
			prt("$v\n");
		} else {
			prt("$line") if ($flag);
		}
		$rmsg .= $line;
		$nxt++;
	}
	prt( "}" ) if ($flag);
	$rmsg .= "}";
	$k = get_unique_key($str_nam); # like say "\@_".$str_nam."_\@", or ...
	if (defined ${$rh}{$k}) {
		prt( ${$rh}{$k} ) if ($flag);
		$rmsg .= ${$rh}{$k};
	}
	prt( ";\n" ) if ($flag);
	$rmsg .= ";\n";
	######################################
	prt( "Done show of 'enum' hash... flag = $flag\n" ) if ($flag);
	return $rmsg;
}

sub get_hash_ref_enum($) { # =($enum_pixfmt);
	my ($stg) = shift;
	my ($len, $i, $pc, $cc, $nc, $word, $line, $comm, $lnn, $msg, $lvl, $nxt);
	my %h = ();
	$len = length($stg);
	if ($len == 0) {
		prt("No 'enum' details...\n");
		return \%h;
	}
	prt("Decoding $len chars for an enum...\n");
	my @brstk = ();
	$cc = '';
	$word = '';
	$line = '';
	$lnn = 1;
	$lvl = 0;
	$nxt = 0;
	for ($i = 0; $i < $len; $i++) {
		$pc = $cc;
		$cc = substr($stg,$i,1);
		if (($cc eq '{')||($cc eq '}')) {
			if ($cc eq '}') {
				do_br_stack($cc,$lnn,\@brstk);
				$lvl = scalar @brstk;
				prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
			}
			deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
			$line = '';
			if ($cc eq '{') {
				do_br_stack($cc,$lnn,\@brstk);
				$lvl = scalar @brstk;
				prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
			}
		}
		$nc = (($i + 1) < $len) ? substr($stg,$i+1,1) : " ";
		$lnn++ if ($cc eq "\n");
		if (($cc eq '/')&&($nc eq '*')) {
			# entered comment /*...*/ - stay until END
			$i = process_comment($nc,$i,$len,$stg,\$lnn);
			next;
		}
		if (($cc eq '/')&&($nc eq '/')) {
			# entered comment // - stay until END OF LINE
			$i = process_comment($nc,$i,$len,$stg,\$lnn);
			next;
		}
		next if ($cc =~ /\s/);
		# start of a word, on a line
		$word = $cc;
		$i++;
		for (; $i < $len; $i++) {
			$pc = $cc;
			$cc = substr($stg,$i,1);
			if (($cc eq '{')||($cc eq '}')) {
				if ($cc eq '}') {
					do_br_stack($cc,$lnn,\@brstk);
					$lvl = scalar @brstk;
					prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
				}
				deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
				$line = '';
				if ($cc eq '{') {
					do_br_stack($cc,$lnn,\@brstk);
					$lvl = scalar @brstk;
					prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
				}
			}
			$nc = (($i + 1) < $len) ? substr($stg,$i+1,1) : " ";
			if ($cc =~ /\s/) {
				last;
			}
			$word .= $cc;
		}
		if ($word eq 'enum') {
			last;
		}
	}
	if ($i >= $len) {
		prtw( "WARNING: FAILED to find 'enum' before end...\n" );
		return \%h;
	}
	prt( "Found enum... after $i chars\n" );
	for (; $i < $len; $i++) {
		$pc = $cc;
		$cc = substr($stg,$i,1);
		if ($cc eq "\n") {
			deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
			$line = '';
		}
		if (($cc eq '{')||($cc eq '}')) {
			if ($cc eq '}') {
				do_br_stack($cc,$lnn,\@brstk);
				$lvl = scalar @brstk;
				prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
			}
			deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
			$line = '';
			if ($cc eq '{') {
				do_br_stack($cc,$lnn,\@brstk);
				$lvl = scalar @brstk;
				prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
			}
		}
		$lnn++ if ($cc eq "\n");
		$nc = (($i + 1) < $len) ? substr($stg,$i+1,1) : " ";
		if (($cc eq '/')&&($nc eq '*')) {
			# entered comment /*...*/ - stay until END
			$i = process_comment($nc,$i,$len,$stg,\$lnn);
			next;
		}
		if (($cc eq '/')&&($nc eq '/')) {
			# entered comment // - stay until END OF LINE
			$i = process_comment($nc,$i,$len,$stg,\$lnn);
			next;
		}
		next if ($cc =~ /\s/);
		$word = $cc;
		if ($cc eq '{') {
			$line .= ' ' if length($line);
			$line .= $word;
			$word = '';
			deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
			$line = '';
			next;
		}
		$i++;	# bump, and get to END OF WORD
		for (; $i < $len; $i++) {
			$pc = $cc;
			$cc = substr($stg,$i,1);
			if (($cc eq '{')||($cc eq '}')) {
				if ($cc eq '}') {
					do_br_stack($cc,$lnn,\@brstk);
					$lvl = scalar @brstk;
					prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
				}
				deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
				$line = '';
				if ($cc eq '{') {
					do_br_stack($cc,$lnn,\@brstk);
					$lvl = scalar @brstk;
					prt( "[dbg12] $lnn: Brace stack = $lvl\n" ) if ($dbg12);
				}
			}
			$nc = (($i + 1) < $len) ? substr($stg,$i+1,1) : " ";
			if (($cc eq '/')&&($nc eq '*')) {
				# entered comment /*...*/ - stay until END
				$i = process_comment($nc,$i,$len,$stg,\$lnn);
				next;
			}
			if (($cc eq '/')&&($nc eq '/')) {
				# entered comment // - stay until END OF LINE
				$i = process_comment($nc,$i,$len,$stg,\$lnn);
				next;
			}
			if ($cc =~ /\s/) {
				last;
			}
			$word .= $cc;
			if (($cc eq ',')||($cc eq '{')) {
				$line .= ' ' if length($line);
				$line .= $word;
				$word = '';
				deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
				$line = '';
			}
		}
		$line .= ' ' if length($line);
		$line .= $word;
	}
	# get any residual
	deal_with_enum_line($lvl,$line,$lnn,\%h,\$nxt);
	#$msg = sprintf("%4d:", $lnn);
	#prt( "$msg [$line]\n" ) if (length($line));
	#$line = '';
	if (@brstk) {
		prtw("WARNING: brace stack NOT closed!\n");
	}
	return \%h;
}

sub do_struct_conv($$$$$) {
	my ($feat,$enum,$struct,$inst,$out) = @_;

	my %master_hash = ();
	my $rmh = \%master_hash;

	my $rpf = get_hash_ref_enum($enum);
	prt("[dbg14]\n***************\n".show_enum_hash(0,$rpf)."***************\n") if ($dbg14);
	# show_enum_hash(1,$rpf);
	# close_log($outfile,$load_log);
	# exit(1);

	set_debug_on_str_parse() if ($dbg_str_parse);	# MAKE building structure VERY NOISY
	my $ref_h = build_struct_hash($struct);

	#${$ref_h}{$str_enum} = $rpf;	# 'ENUMERATION'
	${$rmh}{get_unique_key($str_enum)} = $rpf;	# 'ENUMERATION'

	#show_struct_hash(0, \%h) if ($dbg02);
	show_struct_hash(0, $ref_h) if ($dbg02);

	if ($test_only) {
		test_depth($inst, $ref_h);
      my_exit(1, "test_only is on\n");
	}

	set_debug_on_fill_str() if ($dbg_fill_action);	# make the filling of values VERY NOISY
	fill_struct_per_gcc(0, $inst, $ref_h, $rmh);
	show_full_hash_of_hashes( $rmh ) if ($dbg10);

	my $sstg = get_struct_inst_stg($feat,$rmh);
	# minimum instance string 'n i={0};'
	if (length($sstg) < 8) {
		prtw( "WARNING: Instance string TOO SHORT (".length($sstg).")! No FILE written\n" );
	} else {
		write2file( $sstg, $out);
		prt( "Written to $out...\n" );
		system($out) if ($load_out);;
	}

	#prt( "\nShow of HASH, with values...\n" );
	#show_struct_hash(1, \%h);
	#prt( "Done show of contents...\n" );
	#write2file( get_hash_instance(\%h), 'tempstruct.txt');
	prt( "All done...\n" );

}

sub get_master_hoh() {
    my ($i);
    my %hash = ();
    my ($msg,$sav31);
    $sav31 = $dbg31;    # dbg31 can be confusing, if doing a single instance, so OFF it
    $dbg31 = 0 if ( !$do_multi_sets );
    for ($i = 1; $i <= $test_max; $i++) {
        # prt( "Loading test $i...\n" );
        my $sd = set_test_strings($i);	# set the appropriate strings
        my $rh = build_struct_hash($struct_details);
        ###my $rh = build_struct_hash($sd);
        my $key = $str_nam; # 'NAME'
        if (defined $$rh{$key}) {
            my $val = $$rh{$key};
            #$msg = show_struct_hash(2, $rh);
            #prt("$msg");
            if (defined $hash{$val}) {
                prtw("WARNING: Loading $i test - Already got def for [$val]...\n");
            } else {
                $hash{$val} = { %{$rh} };
            }
        } else {
            prtw("WARNING: failed to get NAME [$key] for test $i...\n");
        }
    }
    $dbg31 = $sav31;
    return \%hash;
}

sub get_master_hoh2() {
    my ($i);
    my %hash2 = ();
    my ($msg,$sav31);
    $sav31 = $dbg31;    # dbg31 can be confusing, if doing a single instance, so OFF it
    $dbg31 = 0 if ( !$do_multi_sets );
    for ($i = 1; $i <= $test_max; $i++) {
        # prt( "Loading test $i...\n" );
        my $sd = set_test_strings($i);	# set the appropriate strings
   	    my $rh = build_struct_hash($struct_details);
   	    ###my $rh = build_struct_hash($sd);
        my $key = $str_nam; # 'NAME'
        if (defined $$rh{$key}) {
            my $val = $$rh{$key};
      	    #$msg = show_struct_hash(2, $rh);
            #prt("$msg");
            if (defined $hash2{$val}) {
                prtw("WARNING:2: Already got def for [$val]...\n");
            } else {
                $hash2{$val} = { %{$rh} };
            }
        } else {
            prtw("WARNING: failed to get NAME [$key] for test $i...\n");
        }
    }
    $dbg31 = $sav31;
    return \%hash2;
}


sub show_str_hash($) {
   my ($rsh) = shift;
   my ($k,$rv,$m,$c);
   $c = scalar keys(%{$rsh});
   if ($dbg24) {
      prt( "\n[dbg24] Display of $c structures loaded...\n" );
   } else {
      prt( "Display of $c structures loaded...\n" );
   }
   foreach $k (sort keys %{$rsh}) {
      $rv = ${$rsh}{$k};
      $m = show_struct_hash(2, $rv);
      prt("$m\n");
   }
   prt( "Done $c structures loaded...\n" );
}

sub get_loaded_names_array_ref($) {
   my ($rsh) = shift;
   my @name = ();
   my ($k, $rv, $nm);
   foreach $k (sort keys %{$rsh}) {
      $rv = ${$rsh}{$k};
      $nm = 'Unknown';
      if (defined ${$rv}{$str_nam}) {
         $nm = ${$rv}{$str_nam};
         $nm =~ s/;$//;
      }
      push(@name,$nm);
   }
   return \@name;
}

# do we have this STRUCTURE defined in the hash of hashes?
sub word_is_rh_name_2($$$) {
	my ($wd,$rhoh,$rrh) = @_;
   my ($msg, $k);
   prt( "check word [$wd] is in HoH! " );
   if (defined ${$rhoh}{$wd}) {
      ${$rrh} = ${$rhoh}{$wd};
      $act_href = ${$rhoh}{$wd};
      prt( "OK rh2 should be set!\n" );
      return 1;
   }
   prt( " NO\n" );
   show_struc_defines( 2, $rhoh, $wd );
	return 0;
}

# is it something like
# 'static const DVprofile dv_profiles[] = {'
# But at this point do NOT know which structure is being defined
# ???????? dv_profile = {
sub is_instance_definition_2($$$$) {
	my ($ln,$rhoh,$rmh,$rrh2) = @_;
	my ($len, $i, $cc, $word, $line, @arr, $sname, $iname, $al, $msg, $isize, $snum, $key, $stage);
	$len = length($ln);
	#@arr = split(/\s/,$ln);
	@arr = instance_space_split($ln);
	$al = scalar @arr;
	$line = '';
	$iname = '';
	$sname = '';
	$snum = '';
   $stage = 0;
	$isize = $bad_posn; # = -200;
   if ($dbg22) {
      prt("[dbg22] Doing is id - split $al...\n");
      for ($i = 0; $i < $al; $i++) {
      	$word = $arr[$i];
      	prt( "".($i + 1)." $word\n" );
      }
   }
	if ( !($ln =~ /=\s*\{$/) ) {
		prt( "[dbg16] Line [$ln] is NOT instance definition...\n" ) if ($dbg16);
		return 0;
	}
	prt( "Line [$ln] looks like an instance definition 2...\n" );
	for ($i = 0; $i < $al; $i++) {
		$word = $arr[$i];
		next if ($word eq '}');
		$msg = "Checking [$word] ";

		# skip over these words
		if ( word_in_array($word, \@res_words) ) {
			$line .= ' ' if (length($line));
			$line .= $word;
			prt( "[dbg16] $msg - it is in res_words array\n" ) if ($dbg16);
			next;
		}

		# if got structure name, and instance name
		if (length($sname) && length($iname)) {
			next if ($word eq '=');
			next if ($word eq '{');
			next if (($word eq '};')||($word =~ /}\s*;/));
			next if ($word eq '}');
		}

		# check if it is the structure name...
		if ( !length($sname) && word_is_rh_name_2($word,$rhoh,$rrh2) ) {
         $rrh2 = $act_href;
			$sname = $word;
         $stage++;
			prt( "[dbg16] $msg - it is the struct name\n" ) if ($dbg16);
			next;
		}

		# must have structure NAME first
      # 20090829 - change in special space split ensures this SHOULD be the 'instance' name
      # this will FAIL on 'anonymous' structure
      if (length($sname) && !length($iname) ) {
         $iname = $word;
         $stage++;
			prt( "[dbg16] $msg - assumed instance name...\n" ) if ($dbg16);
         next;
      }

		#if ($word =~ /^[\w\[\]]$/ ) {
		#if ($word =~ /^\w+[\[\]\w]*$/) {
		#if (length($sname) && ($word =~ /^\w+\s*\[(\w*)\]$/))
		#if (length($sname) && ($word =~ /^\w+\s*(\[(\w*)\])?$/))
		#if (length($sname) && ($word =~ /^\w*\s*(\[(\w*)\])?$/)) {  # 20090829 - allow no 'alphanums' before [...]
		if ( ($stage >= 2) && ($word =~ /^\[\s*(\w*)\s*\]$/) ) {  # 20090829 - in fact new special split separates [...]
			if (defined $1) {
				$snum = $1;
				$snum =~ s/^\[//;
				$snum =~ s/\]$//;
				# 20090827 - clear any space
            $snum = trim_ends($snum);
				# $snum = substr($snum,1) while ($snum =~ /^\s/);	# clear leading
				# $snum = substr($snum,0,length($snum)-1) while ($snum =~ /\s$/);	# and trailing
				if (length($snum)) {
					prt("[dbg21] Got length [$snum](".length($snum).") - decode or lookup in enum...\n") if ($dbg21);
					if ($snum =~ /^\d+$/) {
						# is a whole number
						$isize = $snum;
					} else {
						# assume alphanumeric
						# $str_enum = 'ENUMERATION';
						#if (defined ${$rh}{$str_enum}) {
						#	my $reh = ${$rh}{$str_enum};
						$key = get_unique_key($str_enum);
						if (defined ${$rmh}{$key}) {
							my $reh = ${$rmh}{$key};
							foreach my $k (keys %{$reh}) {
								if ($k eq $snum) {
									$isize = ${$reh}{$k};
									last;
								}
							}
							prtw("WARNING: $msg - found [$key], checked [$snum], but isize=[$isize]!\n") if ($isize < 0);
							#prtw("WARNING: $msg - found [$str_enum], but isize=[$isize]!\n") if ($isize < 0);
						} else {
							prtw( "WARNING: $msg gave [$snum] as size, but no [$str_enum] in ref hash!\n" );
						}
					}
				}
            next;
			}
			
         #prt( "[dbg16] $msg - assumed instance name... num=[$snum], if any\n" ) if ($dbg16);
			#if (length($iname)) {
			#	prtw( "WARNING: $msg - Already HAVE iname=[$iname]!\n" );
			#} else {
         #   $iname = $word;
         #}
			next;
		}

		# must have structure name, and instance name
		if (length($sname) && length($iname)) {
			next if ($word eq '=');
			next if ($word eq '{');
			next if (($word eq '};')||($word =~ /}\s*;/));
			next if ($word eq '}');
		}

		prtw( "WARNING: $msg - NOT PARSED in is_instance_definition! 2\n" );
      my_exit(1,  "is_instance_definition_2: line=[$ln]\n" );

	}

	if (length($sname) && length($iname)) {
      # put entries decoded in the MASTER HASH

		# ${$rh}{$str_inst} = $iname;
      $key = get_unique_key($mast_iname);
		${$rmh}{$key} = $iname;	# store ONLY in master HASH

      #${$rh}{$str_inst} = $ln;
		$key = get_unique_key($mast_inst);
		${$rmh}{$key} = $ln;	# store ONLY in master HASH

		#${$rh}{$str_len} = $isize if ($isize > 0);
		if ($isize > 0) {
			$key = get_unique_key($mast_len);
			${$rmh}{$key} = $isize; # AND the SIZE of the structure, if ANY...
		}

		return 1;
	}

	return 0;
}

sub add_line_2_hash_2($$$$$$$) {
	my ($rfsflag, $lvl, $lnn, $ln, $rhoh, $rmh, $rrh2) = @_;
	my $wn = "WARNING:$lnn:$lvl:";
	my ($key, $off, $equ);
   $ln = trim_ends($ln);
	prt("[dbg20] Add [$ln] to hash...(fsflag=$$rfsflag)\n") if ($dbg20);
	if ($$rfsflag & $F_HADEND) {
		prtw("wn: add line called after structure CLOSED\n");
		return;
	} elsif ($$rfsflag & $F_HADID) {
		###if ($ln =~ /^\.(.+)=(.+)/) {
		if ($ln =~ /^\.\w{1}(.+)=(.+)/) {
			# begins with a dot entries...
			my @a = split('=',$ln);
			my $ca = scalar @a;
			if ($ca != 2) {
				prtw("$wn Split FAILED on [$ln]!\n");
			} else {
				# got two elements
				$$rfsflag |= $F_HADDOT;
				$off = trim_all($a[0]);
				$equ = trim_all($a[1]);
				if ($off =~ /^\./) {
					$off = substr($off,1);
					$equ =~ s/,$//;
               $rrh2 = $act_href;
					$key = offset_in_hash($off,$rrh2);
					if (length($key)) {
						# success
						$$rrh2{$key}[$O_DEC] = "$ln";
						$$rrh2{$key}[$O_VAL] = "$equ";
						prt( "[dbg07] Added [$equ] to key [$key], for off[$off]\n" ) if ($dbg07);
                  ${$rfsflag} |= $F_HADMEM;
					} else {
						prtw( "$wn NO FIND split 2[$off] = [$equ] NOT HANDLED! line[$ln] (4)\n" );
                  $key = get_struc_mem_names($rrh2);
                  prtw( "list=[$key]\n" );
					}
				} else {
					prtw( "$wn CHECK split [$off] = [$equ] NOT HANDLED! (5)\n" );
				}
			}
		} else {
			# ==========================================================================
			# NOT a .abc=def, entry
			if ($ln eq '{') {
				prt( "[dbg18] $lnn:$lvl: Open new BLOCK... on [$ln]\n") if ($dbg18);
			} elsif ($lvl == 0) {
				if ($ln =~ /}\s*;/) {
					prt( "$lnn:$lvl: End of definitions 2... on [$ln]\n");
					$$rfsflag |= $F_HADEND;	# signal END of structure
				} else {
					prtw( "$wn line[$ln] NOT HANDLED! (1)\n" );
				}
			} elsif ($lvl == 1) {
				if ($ln =~ /}\s*,/) {
					prt( "[dbg18] $lnn:$lvl: End of BLOCK... on [$ln]\n") if ($dbg18);
				} elsif ($ln eq '}') {
					# what is this??? but skip it anyway
				} else {
					#if (!($$rfsflag & $F_HADDOT) && ($ln =~ /,$/)) {
               # 20090903 - found a case where a space was added
					if (!($$rfsflag & $F_HADDOT) && ($ln =~ /,$/)) {
						# assume a member VALUE
						$ln =~ s/,$//;	# clear the comma
                  $rrh2 = $act_href;
						$off = ${$rrh2}{$mem_nxt};	# get next member counter
						$off++;	# bump to NEXT
						${$rrh2}{$mem_nxt} = $off;
						$key = sprintf("%s%04d",$mem_bgn,$off);	# member and number
						${$rrh2}{$key}[$O_VAL] = $ln;
						prt( "[dbg18|20|07] $lnn:$lvl: Set member 2 [$key] value to [$ln]\n") if ($dbg18 | $dbg20 | $dbg07);
                  ${$rfsflag} |= $F_HADMEM;
					} else {
						prtw( "$wn line[$ln] NOT HANDLED 2! (2)\n" );
                  if ($$rfsflag & $F_HADDOT) {
                     prt( "Had a DOT member!\n" );
                  }
                  if (!($ln =~ /,$/)) {
                     prt( "Line does NOT end in comma!\n" );
                  }
                  my_exit(1, "add_line_2_hash_2: FIXME!\n");
					}
				}
			} else {
				# handle things like - '[PIX_FMT_YUV420P] = {'
				if ($ln =~ /^\[(\w+)\]/) {
					$off = $1;
					prt( "[dbg19] $lnn:$lvl: [$ln] as offset [$off]\n") if ($dbg19);
					# $str_enum = 'ENUMERATION';
					my $num = $bad_posn; #-200;
					my $key = get_unique_key($str_enum);
					if (defined ${$rmh}{$key}) {
						my $reh = ${$rmh}{$key};
						foreach my $k (keys %{$reh}) {
							if ($k eq $off) {
								$num = ${$reh}{$k};
								last;
							}
						}
						prt( "[dbg19] $lnn:$lvl: [$off] has val [$num]\n") if ($dbg19);
						# $copy_hash{$str_off} = $blknum;	# OFFSET = order of this block (-1 = no order)!!!
						$key = $str_off;
						if ($num != $bad_posn) {
							${$rrh2}{$key} = $num;	# $bad_posn (was -200) is NO NUMBER, else a value given
						}
					} else {
						prtw( "$wn NO ENUMERATION rh! to solve $off\n" );
					}
				} else {
					prtw( "$wn line[$ln] NOT HANDLED! (3)\n" );
				}
			}
		}
	} else {
		if ( is_instance_definition_2($ln,$rhoh,$rmh,$rrh2) ) {
         ${$rrh2} = $act_href;
			$key = get_unique_key($mast_inst);
			$equ = ${$rmh}{$key};
			prt( "$lnn:$lvl: Set Mast.Inst[$key]=[$equ]\n" );
			$key = get_unique_key($mast_len);
			if (defined ${$rmh}{$key}) {
				$off = ${$rmh}{$key};
				prt( "$lnn:$lvl: Set Mast.Leng[$key]=[$off]\n" );
			} else {
				$off = $bad_posn;
			}
			$$rfsflag |= $F_HADID;	# had ID
		}
	}
	prt("[dbg20] Done [$ln] to hash...(fsflag=$$rfsflag)\n") if ($dbg20);
}

## comments /* ... */, or // to end of line
##sub fill_struct_per_gcc($$) { # like ($gcc_struct, \%h);
##	my ($gcc, $rh) = @_;
sub fill_struct_per_gcc_2($$$$) { # like ($gcc_struct, \%h);
	my ($flg, $gcc, $rhoh, $rmh) = @_;
	my ($i, $len, $pc, $cc, $nc, $ic1, $ic2, $lnn);
	my ($bclvl, $bklvl, $line, $msg, $comm, $inst, $blknum, $cnt);
	my ($k, $v);
	my $depth = 0;
	$gcc = reline_instance_string(\$depth, $gcc);	# remove some spaces...
	my @brcstk = ();
	my @brkstk = ();
	my @depitems = ();
	my $flag = 0;
   my ($rh2);  ## this is the structure HASH, when found!
	$len = $depth;
	if ($len == 0) {
		prt("CRITICAL ERROR: Got NO DEPTH!\n");
		exit 1;
	}
	push(@depitems, [ 0, 0, 0 ]);	# add one extra
	while ($len) {
		push(@depitems, [ 0, 0, 0 ]);
		$len--;
	}
	$ic1 = 0;
	$ic2 = 0;
	$lnn = 1;
	$inst = 0;	# expect mutiple instances
	$len = length($gcc);
	$bclvl = 0;
	$bklvl = 0;
	$blknum = -1;	# order per as found
	prt( "Processing fill struct 2, $len chars, depth = $depth...\n" );
	for ($i = 0; $i < $len; $i++) {
		$cc = substr($gcc,$i,1);
		$nc = (($i + 1) < $len) ? substr($gcc,$i+1,1) : " ";
		if ($cc eq "\n") {
			if (length($line)) {
				$msg = sprintf("%3d: ", $lnn);
				$msg .= $line;
				prt( "[dbg08] $msg\n" ) if ($dbg08);
				###add_line_2_hash($bclvl, $lnn, $line, $rh, \%mh);
				add_line_2_hash_2(\$flag, $bclvl, $lnn, $line, $rhoh, $rmh, \$rh2);
				$line = '';
			}
			$lnn++;
			#if ($lnn == 2) { exit(1); }
			if ($ic2) {
				$msg = sprintf("%3d: ", $lnn);
				$msg .= "Discard: [$comm]";
				prt( "[dbg06] $msg\n" ) if ($dbg06);
			}
			$ic2 = 0;
			$pc = $cc;
			next;
		}
		if ($ic1) {
			# locked in comment - stay to END
			$comm .= $cc;
			if (($cc eq '/') && ($pc eq '*')) {
				$ic1 = 0; # end of comment
				$msg = sprintf("%3d: ", $lnn);
				$msg .= "Discard: [$comm]";
				prt( "[dbg05] $msg\n" ) if ($dbg05);
			}
		} elsif ($ic2) {
			# locked in comment - stay to end of line
			$comm .= $cc;
		} else {
			if (($cc eq '/') && ($nc eq '*')){
				$ic1 = 1;	# process a comment
				$comm = $cc;	# start
				$pc = $cc;	# update previous char
				next;
			}
			if (($cc eq '/') && ($nc eq '/')){
				$ic2 = 1;	# start comment, until EOL
				$comm = $cc; # start comment
				$pc = $cc;  # update prev char
				next;
			}
			#####################################################################
			$line .= $cc; # ADD to line
			if ($cc eq '{') {
				push(@brcstk,[$i, $lnn] );
				$bclvl++;
				# clear depth flags
				$depitems[$bclvl][0] = 0;
				$depitems[$bclvl][1] = 0;
				$depitems[$bclvl][2] = 0;
			} elsif ($cc eq '}') {
				if (@brcstk) {
					# show depth items
					prt( "[dbg09] $bclvl: equ=[".$depitems[$bclvl][0]."], coma=[".$depitems[$bclvl][1]."] dot [".$depitems[$bclvl][2]."]\n" ) if ($dbg09);
					if (($depitems[$bclvl][0] > 0)&&($depitems[$bclvl][2] > 0)) {
						# we have a completed instance - COPY, and SAVE TO master HASH
						# ============================================================
						# At this time this hash copy is in the ORDER found,
						# but by using the [OFF_NUM] = { notation, this could be
						# set at a specific block number (in ascii, but could probably use number?)
                  my %copy_hash = ();
                  $cnt = scalar keys(%{$rh2});
                  prt( "Copying $cnt keys of block hash...\n" );
						$msg = sprintf("$mem_bgn%08d", $inst);
						$inst++;
                  foreach $k (keys %{$rh2}) {
                     $v = $$rh2{$k};
                     if ($k =~ /^$mem_bgn/) { # member
                        $copy_hash{$k} = [@{$v}]; # store COPY of ARRAY
                     } else {
                        $copy_hash{$k} = $v; # store string, or hash-ref, or value, or ...
                     }
                  }
						# clear the current HASH values
						${$rmh}{$msg} = \%copy_hash;	# THIS SEEMS TO WORK ;=))
						clear_hash_values($rh2);	# ready for NEXT
                  $flag &= ~$F_HADMEM; # now copied, so remove bit
                  bump_master_copied($rmh);
					}
					pop @brcstk;
				} else {
					prtw("$lnn:$i: WARNING: Encountered $cc, with no stack!\n");
				}
				$bclvl-- if ($bclvl);
			} elsif ($cc eq '(') {
				push(@brkstk, [$i, $lnn] );
				$bklvl++;
			} elsif ($cc eq ')') {
				if (@brkstk) {
					pop @brkstk;
				} else {
					prtw("$lnn:$i: WARNING: Encountered $cc, with no stack!\n");
				}
				$bklvl-- if ($bklvl);
			} elsif ($cc eq '=') {
				$depitems[$bclvl][0]++;
			} elsif ($cc eq ',') {
				$depitems[$bclvl][1]++;
			} elsif (($cc eq '.') && ($nc =~ /\w/)) {
				$depitems[$bclvl][2]++;
			}
		}
		$pc = $cc;
	}
	if (@brcstk) {
		prtw( "WARNING: ".scalar @brcstk." items in brace stack!\n" );
	}
	if (@brkstk) {
		prtw( "WARNING: ".scalar @brkstk." items in bracket stack!\n" );
	}

   if ($flag & $F_HADMEM) { # not yet COPIED
      my %copy_hash = ();
      $cnt = scalar keys(%{$rh2});
      prt( "Copying $cnt keys of block hash...\n" );
		$msg = sprintf("$mem_bgn%08d", $inst);
      $inst++;
      foreach $k (keys %{$rh2}) {
         $v = $$rh2{$k};
         if ($k =~ /^$mem_bgn/) { # member
            $copy_hash{$k} = [@{$v}]; # store COPY of ARRAY
         } else {
            $copy_hash{$k} = $v; # store string, or hash-ref, or value, or ...
         }
      }
      # clear the current HASH values
      ${$rmh}{$msg} = \%copy_hash;	# THIS SEEMS TO WORK ;=))
      clear_hash_values($rh2);	# ready for NEXT
      $flag &= ~$F_HADMEM; # now copied, so remove bit
      bump_master_copied($rmh);
   }

	$ic1 = 0;
	$ic2 = 0;
	foreach $k (keys %{$rmh}) {
		$ic1++;
		if (!key_is_unique_type($k)) {
			$ic2++;
		}
	}

	$k = get_total_blocks($rmh);
	if ($k > 0) {
		$cc = "total = $k";
	} else {
		$cc = "with no total blocks";
	}
	prt("Done fill struct, with $ic1 members, $ic2 blocks, $cc...\n" );
	##return \%mh;
	return $rmh;
}

sub process_in_file($$$$) {
   my ($feat, $inf, $rsh, $out) = @_;
   my (@lines, $gcc, $tmp);
	my %master_hash = ();
	my $rmh = \%master_hash;
   if (open INF, "<$inf") {
      @lines = <INF>;
      close INF;
      $gcc = join("\n",@lines);
      $gcc .= "\n";
     	set_debug_on_fill_str() if ($dbg_fill_action);	# make the filling of values VERY NOISY
      my $mh = fill_struct_per_gcc_2(0, $gcc,$rsh,$rmh);
   	show_full_hash_of_hashes( $mh ) if ($dbg10);
      my $sstg = get_struct_inst_stg($feat,$rmh);
      # minimum instance string 'n i={0};'
      if (length($sstg) < 8) {
         prtw( "WARNING: Instance string TOO SHORT (".length($sstg).")! No FILE written\n" );
      } else {
         $tmp = join("",@lines);
         $tmp .= "\n" if ($tmp =~ /\n$/);
         $tmp .= $sstg;
         add_to_done_file($tmp);
         write2file( $sstg, $out);
         prt( "Written to $out...\n" );
         system($out) if ($load_out);;
      }

   } else {
      prt("ERROR: can not open file [$inf]...\n" );
   }
}

sub output_null_set() {
   my ($rsh, $rarr, $nm, $txt, $rh, $k, $sstg);
   my ($k1,$ccnt,$inst,$f, $key);
   my $ocnt = 0;
   # load of ALL structures
   $rsh = get_master_hoh();
   ##show_str_hash($rsh);
   $rarr = get_loaded_names_array_ref($rsh);
   prt("Names: cnt=".(scalar @{$rarr}).", [".join(" ",@{$rarr})."]\n");
   $inst = 0;
   $k = get_unique_key($mast_copied);
   ${$rsh}{$k} = 1;  # SET master count to 1 COPIED
	$f = ($FF_BLAN | $FF_COMM | $FF_COM1 | $FF_COMA);
	$f = ($FF_BLAN | $FF_COMM | $FF_COM1 | $FF_COMA);
   $ocnt = 0;
   foreach $nm (@{$rarr}) {
      $ocnt++;
      $txt = "$nm $nm"."_NULL = {";
      prt("// $ocnt: Doing: $txt\n");
      $key = get_unique_key($mast_inst); # 'INSTANCE' - set in master
      ${$rsh}{$key} = $txt;
      if (defined ${$rsh}{$nm}) {
         $rh = ${$rsh}{$nm};
         #prt( "Found it in master...\n" );
         #foreach $k (keys %{$rh}) {
         #   prt( "Key: $k\n" );
         #}
         copy_hash_to_master($inst, $rh, $rsh);
         # $inst++;  # overwrite previous - saves clearing
         $ccnt = 0;
         if (scalar( @gen_null_for ) > 0) {
            next if !(word_in_array($nm, \@gen_null_for));
         	##$f = $FF_BLAN; # only a BLANK
         	$f = ($FF_BLAN | $FF_COMM | $FF_COMA);
         }
         foreach $k1 (sort keys %{$rsh}) {
            if (!key_is_unique_type($k1)) { # like say $k =~ /^\@_/, or ...
               if ($k1 =~ /^$mem_bgn/) {  # ONLY check 'member' keys
                  $rh = ${$rsh}{$k1};
                  $ccnt++;
                  $sstg = get_struct_inst_stg($f,$rsh);
                  ### $msg .= get_hash_instance2($feat, $imax, $ccnt, $rh, $rmh);
                  prt( "$sstg\n" );
               }
            }
         }
         # prt( "Got $ccnt member count...\n" ); # will always be 1 in this case
      } else {
         prtw( "WARNING: [$nm] NOT in master HoH!\n" );
      }
      #exit(1);
   }
   my_exit(0,"process_a_file: Clean exit");
}

sub process_a_file($$$) {
   my ($feat,$file,$out) = @_;
   # load of ALL structures
   my $rsh = get_master_hoh();
   show_str_hash($rsh) if ($dbg24);
   process_in_file( $feat, $file, $rsh, $out );
   my_exit(0,"output_null_set: Clean exit");
}


output_null_set() if ($gen_null_set);
process_a_file($features, $in_file, $out_file) if ($do_multi_sets);

prt( "Doing s SINGLE instance... Test number = $do_test_num (test $do_test_num)\n" );
set_test_strings($do_test_num);	# set the appropriate strings
do_struct_conv($features, $enum_details, $struct_details, $gcc_struct, $out_file);
my_exit(0,"Clean exit");

# eof - convstruct.pl
