<% symbols = { 'descriptor=' => nil, 'headers=' => nil, 'data=' => nil, 'header_type' => nil, 'to_s' => nil, 'xml' => nil, 'name_value' => nil, } wmq_structs = [ # Message Descriptor { file: 'cmqc.h', struct: 'MQMD' }, # Message Descriptor 1 { file: 'cmqc.h', struct: 'MQMD1', other_keys: [:remote_q_name, :remote_q_mgr_name] }, # Rules and formatting header2 { file: 'cmqc.h', struct: 'MQRFH2', header: 'rf_header_2', struct_id: 'MQRFH_STRUC_ID', other_keys: [:xml], custom: true }, # Implement custom Message_build_rf_header_2 and Message_deblock_rf_header_2 # Rules and formatting header { file: 'cmqc.h', struct: 'MQRFH', header: 'rf_header', other_keys: [:name_value], custom: true }, # Implement custom Message_build_rf_header and Message_deblock_rf_header # Dead Letter Header { file: 'cmqc.h', struct: 'MQDLH', header: 'dead_letter_header', defaults: 'MQDLH_DEF.CodedCharSetId = MQCCSI_INHERIT;' }, # CICS bridge header { file: 'cmqc.h', struct: 'MQCIH', header: 'cics' }, # Distribution header { file: 'cmqc.h', struct: 'MQDH', header: 'dist_header' }, # IMS information header { file: 'cmqc.h', struct: 'MQIIH', header: 'ims' }, # Reference message header (send large files over channels) { file: 'cmqc.h', struct: 'MQRMH', header: 'ref_msg_header' }, # Trigger Message { file: 'cmqc.h', struct: 'MQTM', header: 'trigger', format: false }, # Trigger Message 2 (character format) { file: 'cmqc.h', struct: 'MQTMC2' }, # Work Information header { file: 'cmqc.h', struct: 'MQWIH', header: 'work_info_header' }, # Transmission-queue header - Todo: Need to deal with MQMDE { file: 'cmqc.h', struct: 'MQXQH', header: 'xmit_q_header', format: 'MsgDesc.Format' }, ] wmq_structs.each do |struct| # Parse WebSphere MQ 'C' Header file and extract elements elements = extract_struct(@path+'/'+struct[:file], struct[:struct]) struct[:elements] = elements # Add symbol for each struct name symbols[struct[:header]]=nil if struct[:header] # Add symbols for each element in C Struct elements.each do |item| symbols[rubyize_name(item[1])] = nil unless @@field_ignore_list.include?(item[1]) end end %> /* -------------------------------------------------------------------------- * * WARNING: DO NOT MODIFY THIS FILE * * This file was generated by generate_structs.rb. * * --------------------------------------------------------------------------*/ #include "wmq.h" /* -------------------------------------------------------------------------- * Static's to hold Symbols * --------------------------------------------------------------------------*/ <% header_file = 'cmqc.h' struct = 'MQMD' # Define static variables to hold Ruby symbols key_list = symbols.keys.sort key_list.each do |key, value| %><%="static ID ID_#{key.sub('=', '_set')};\n" %><% end # initialize symbols %> /* -------------------------------------------------------------------------- * Initialize Symbols * --------------------------------------------------------------------------*/ void wmq_structs_id_init() { <% key_list.each do |key, value| %><%=" ID_%-20s = rb_intern(\"%s\");\n"% [key.sub('=', '_set'), key] %><% end %>} <% # Generate functions to move to/from a Ruby Hash of the symbols defined above wmq_structs.each do |struct| elements = struct[:elements] struct_name = struct[:struct] variable = 'p'+struct_name.downcase %> /* -------------------------------------------------------------------------- * Convert between <%=struct_name%> and Hash * --------------------------------------------------------------------------*/ void Message_from_<%=struct_name.downcase%>(VALUE hash, <%=struct_name%>* <%=variable%>) { VALUE str; size_t size; size_t length; size_t i; char* pChar; <% elements.each do |item| type = item[0] name = item[1] next if @@field_ignore_list.include?(name) || (name=='Format' && struct[:header]) match = /(MQ\D+)/.match(type) type = "#{match[1]}S" if match[1] != type %><%= if type == 'MQMDS' " %-16s(hash, &#{variable}->%s);\n" % ['Message_from_mqmd1', name] else " %-16s(hash, %-30s #{variable}->%s)\n" % ["WMQ_#{type}2HASH", rubyize_name(name)+',',name] end %><% end %>} static int Message_to_<%=struct_name.downcase%>_each (VALUE key, VALUE value, <%=struct_name%>* p<%=struct_name.downcase%>) { VALUE str; size_t size; size_t length; VALUE val; ID id = rb_to_id(key); <% contains = nil elements.each do |item| type = item[0] name = item[1] next if @@field_ignore_list.include?(name) || (name=='Format' && struct[:header]) match = /(MQ\D+)/.match(type) type = "#{match[1]}S" if match[1] != type %><%= if type == 'MQMDS' contains = 'mqmd1' "" else "%-35s { %-16s(value,#{variable}->#{name}) }\n else" % [" if(id == ID_#{rubyize_name(name)})", "WMQ_STR2#{type}"] end%><% end if struct[:other_keys] struct[:other_keys].each do |key| %> if(id == ID_<%=key.to_s%>) {} else<% end end %><%=struct[:header]?" if(id != ID_header_type)":""%><% if contains %> { Message_to_<%= contains%>_each(key, value, &pmqxqh->MsgDesc); }<% else%> { val = rb_funcall(key, ID_to_s, 0); rb_raise(rb_eArgError, "WMQ::Message#to_<%=struct_name.downcase%> Unknown symbol :%s supplied", RSTRING_PTR(val)); } <% end%> return 0; } void Message_to_<%=struct_name.downcase%>(VALUE hash, <%=struct_name%>* p<%=struct_name.downcase%>) { rb_hash_foreach(hash, Message_to_<%=struct_name.downcase%>_each, (VALUE)p<%=struct_name.downcase%>); } <% end # wmq_structs.each %> /* -------------------------------------------------------------------------- * Extract message data and headers * --------------------------------------------------------------------------*/ void Message_deblock(VALUE self, PMQMD pmqmd, PMQBYTE p_buffer, MQLONG total_length, MQLONG trace_level) { PMQCHAR p_format = pmqmd->Format; /* Start with format in MQMD */ PMQBYTE p_data = p_buffer; /* Pointer to start of data */ MQLONG data_length= total_length; /* length of data portion */ VALUE headers = rb_ary_new(); VALUE descriptor = rb_hash_new(); MQLONG size = 0; while (p_format) { <% wmq_structs.each do |struct| if struct[:header] %> /* <%=struct[:struct]%>: <%=struct[:header]%> */ if(strncmp(p_format, MQFMT_<%=struct[:header].upcase%>, MQ_FORMAT_LENGTH) == 0) { VALUE hash = rb_hash_new(); P<%=struct[:struct]%> p_header = (P<%=struct[:struct]%>)p_data; if(trace_level>2) printf("WMQ::Message#deblock Found <%=struct[:header]%>\n"); if(memcmp(p_header->StrucId, <%=struct[:struct_id] || "#{struct[:struct].upcase}_STRUC_ID"%>, sizeof(p_header->StrucId)) != 0) { if(trace_level>1) printf("WMQ::Message#deblock MQFMT_<%=struct[:header].upcase%> received, but message does not contain <%=struct[:struct].upcase%>\n"); break; /* Bad Message received, do not deblock headers */ } else { Message_from_<%=struct[:struct].downcase%>(hash, p_header); rb_hash_aset(hash, ID2SYM(ID_header_type), ID2SYM(ID_<%=struct[:header]%>)); rb_ary_push(headers, hash); size = <%=if struct[:custom] then "Message_deblock_#{struct[:header]} (hash, p_data, data_length);\n"+ " if (!size) break; /* Poison Message */" elsif struct[:elements].include?(['MQLONG', 'StrucLength']) 'p_header->StrucLength;' else "sizeof(#{struct[:struct]});" end %> p_data += size; data_length -= size; <%=if struct[:format] == nil 'p_format = p_header->Format' elsif struct[:format] == false 'break' else "p_format = p_header->#{struct[:format]}" end %>; } } else <% end end # wmq_structs.each %> { break; } } /* Copy the last recognised header found to the Descriptor */ if(p_format && p_format != pmqmd->Format) { strncpy(pmqmd->Format, p_format, MQ_FORMAT_LENGTH); } Message_from_mqmd(descriptor, pmqmd); rb_funcall(self, ID_descriptor_set, 1, descriptor); rb_funcall(self, ID_headers_set, 1, headers); rb_funcall(self, ID_data_set, 1, rb_str_new(p_data, data_length)); } void Message_build_set_format(ID header_type, PMQBYTE p_format) { <% wmq_structs.each do |struct| if struct[:header] %> if(header_type == ID_<%=struct[:header]%>) { memcpy(p_format, MQFMT_<%=struct[:header].upcase%>, MQ_FORMAT_LENGTH); return;} <% end end # wmq_structs.each %> rb_raise(rb_eArgError, "Invalid/Unknown header_type supplied in WMQ::Message#headers array"); } /* -------------------------------------------------------------------------- * Build message headers * --------------------------------------------------------------------------*/ int Message_build_header (VALUE hash, struct Message_build_header_arg* parg) { VALUE val = rb_hash_aref(hash, ID2SYM(ID_header_type)); PMQBYTE p_data = 0; if (!NIL_P(val) && (TYPE(val) == T_SYMBOL)) { ID header_id = rb_to_id(val); <% wmq_structs.each do |struct| if struct[:header] %> if (header_id == ID_<%=struct[:header]%>) /* Build <%=struct[:struct]%> */ { <% if struct[:custom] %> Message_build_<%=struct[:header]%> (hash, parg); <% else %> static <%=struct[:struct]%> <%=struct[:struct]%>_DEF = {<%=struct[:struct]%>_DEFAULT}; <%=struct[:defaults]%> if(parg->trace_level>2) printf ("WMQ::Message#build_header Found <%=struct[:header]%>\n"); p_data = Message_autogrow_data_buffer(parg, sizeof(<%=struct[:struct]%>)); memcpy(p_data, &<%=struct[:struct]%>_DEF, sizeof(<%=struct[:struct]%>)); Message_to_<%=struct[:struct].downcase%>(hash, (P<%=struct[:struct]%>)p_data); <% if struct[:format] != false%> if(parg->next_header_id) { Message_build_set_format(parg->next_header_id, ((P<%=struct[:struct]%>)p_data)-><%=struct[:format] || 'Format'%>); } else { memcpy(((P<%=struct[:struct]%>)p_data)-><%=struct[:format] || 'Format'%>, parg->data_format, MQ_FORMAT_LENGTH); } <% end %> *(parg->p_data_offset) += sizeof(<%=struct[:struct]%>); if(parg->trace_level>2) printf ("WMQ::Message#build_header data offset:%ld\n", (long)(*(parg->p_data_offset))); <% end %> } else <% end end # wmq_structs.each %> { rb_raise(rb_eArgError, "Unknown :header_type supplied in WMQ::Message#headers array"); } } else { rb_raise(rb_eArgError, "Mandatory parameter :header_type missing from header entry in WMQ::Message#headers array"); } return 0; /* Continue */ }