<% ################################################################################ # Copyright 2006 J. Reid Morrison. Dimension Solutions, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ 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 %> /* -------------------------------------------------------------------------- * Copyright 2006 J. Reid Morrison. Dimension Solutions, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * -------------------------------------------------------------------------- * * 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 %>} #if RUBY_VERSION_CODE > 183 static int Message_to_<%=struct_name.downcase%>_each (VALUE key, VALUE value, <%=struct_name%>* p<%=struct_name.downcase%>) { #else static int Message_to_<%=struct_name.downcase%>_each (VALUE array, <%=struct_name%>* p<%=struct_name.downcase%>) { VALUE key = rb_ary_shift(array); VALUE value = rb_ary_shift(array); #endif 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 %> { #if RUBY_VERSION_CODE > 183 Message_to_<%= contains%>_each(key, value, &pmqxqh->MsgDesc); #else rb_ary_push(array, key); rb_ary_push(array, value); Message_to_<%= contains%>_each(array, &pmqxqh->MsgDesc); #endif }<% else%> { val = rb_funcall(key, ID_to_s, 0); rb_raise(rb_eArgError, "WMQ::Message#to_<%=struct_name.downcase%> Unknown symbol :%s supplied", RSTRING(val)->ptr); } <% end%> return 0; } void Message_to_<%=struct_name.downcase%>(VALUE hash, <%=struct_name%>* p<%=struct_name.downcase%>) { #if RUBY_VERSION_CODE > 183 rb_hash_foreach(hash, Message_to_<%=struct_name.downcase%>_each, (VALUE)p<%=struct_name.downcase%>); #else rb_iterate (rb_each, hash, Message_to_<%=struct_name.downcase%>_each, (VALUE)p<%=struct_name.downcase%>); #endif } <% 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) { break; /* Bad Message received, do not deblock headers */ if(trace_level>1) printf("WMQ::Message#deblock MQFMT_<%=struct[:header].upcase%> received, but message does not contain <%=struct[:struct].upcase%>\n"); } 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", *(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 */ }