Annotation of OpenXM/src/ruby/ox.rb, Revision 1.2
1.2 ! ogino 1: # ox.rb OpenXM client written by Ruby
! 2: #
! 3: # $OpenXM$
! 4: #
1.1 ogino 5: require 'socket'
6: include Socket::Constants
7:
8: # define for CMO constants
9:
10: # Moved from oxtag.h
11: LARGEID = 0x7f000000
12: CMO_PRIVATE = 0x7fff0000
13: CMO_ERROR = (LARGEID+1)
14: CMO_ERROR2 = (LARGEID+2)
15: CMO_NULL = 1
16: CMO_INT32 = 2
17: CMO_DATUM = 3
18: CMO_STRING = 4
19: CMO_MATHCAP = 5
20:
21: CMO_START_SIGNATURE = 0x7fabcd03
22: CMO_LOCAL_OBJECT = 0x7fcdef03
23: CMO_LOCAL_OBJECT_ASIR = (CMO_LOCAL_OBJECT+0)
24: CMO_LOCAL_OBJECT_SM1 = (CMO_LOCAL_OBJECT+1)
25: # for OpenMathematica
26: MLO_FUNCTION = (CMO_LOCAL_OBJECT+2)
27:
28: OX_LOCAL_OBJECT = 0x7fcdef30
29: OX_LOCAL_OBJECT_ASIR = (OX_LOCAL_OBJECT+0)
30: OX_LOCAL_OBJECT_SM1 = (OX_LOCAL_OBJECT+1)
31: OX_LOCAL_OBJECT_MATH = (OX_LOCAL_OBJECT+2)
32:
33: CMO_ARRAY = 16
34: CMO_LIST = 17
35: CMO_ATOM = 18
36: CMO_MONOMIAL32 = 19
37: CMO_ZZ = 20
38: CMO_QQ = 21
39: CMO_ZERO = 22
40: # CMO_DMS = 23
41: CMO_DMS_GENERIC = 24
42: CMO_DMS_OF_N_VARIABLES = 25
43: CMO_RING_BY_NAME = 26
44: CMO_RECURSIVE_POLYNOMIAL = 27
45: CMO_LIST_R = 28
46:
47: CMO_INT32COEFF = 30
48: CMO_DISTRIBUTED_POLYNOMIAL = 31
49: # CMO_ZZ_OLD = 32
50: CMO_POLYNOMIAL_IN_ONE_VARIABLE = 33
51: CMO_RATIONAL = 34
52:
53: CMO_64BIT_MACHINE_DOUBLE = 40
54: CMO_ARRAY_OF_64BIT_MACHINE_DOUBLE = 41
55: CMO_128BIT_MACHINE_DOUBLE = 42
56: CMO_ARRAY_OF_128BIT_MACHINE_DOUBLE = 43
57:
58: CMO_BIGFLOAT = 50
59: CMO_IEEE_DOUBLE_FLOAT = 51
60:
61: CMO_INDETERMINATE = 60
62: CMO_TREE = 61
63: CMO_LAMBDA = 62 # for function definition
64:
65:
66: OX_COMMAND = 513
67: OX_DATA = 514
68: OX_SYNC_BALL = 515 # ball to interrupt
69:
70: # level 2 stack machine with programming facility.
71: OX_START_OF_FUNCTION_BLOCK = 518
72: OX_END_OF_FUNCTION_BLOCK = 519
73: OX_ADDRESS = 520
74:
75: OX_DATA_WITH_SIZE = 521
76: OX_DATA_ASIR_BINARY_EXPRESSION = 522 # This number should be changed
77: OX_DATA_OPENMATH_XML = 523
78: OX_DATA_OPENMATH_BINARY = 524
79: OX_DATA_MP = 525
80:
81: # OX BYTE command
82: OX_BYTE_NETWORK_BYTE_ORDER = 0
83: OX_BYTE_LITTLE_ENDIAN = 1
84: OX_BYTE_BIG_ENDIAN = 0xff
85:
86: # ox_function_id.h
87: SM_popSerializedLocalObject = 258
88: SM_popCMO = 262
89: SM_popString = 263 # result ==> string and send the string by CMO
90:
91: SM_mathcap = 264
92: SM_pops = 265
93: SM_setName = 266
94: SM_evalName = 267
95: SM_executeStringByLocalParser = 268
96: SM_executeFunction = 269
97: SM_beginBlock = 270
98: SM_endBlock = 271
99: SM_shutdown = 272
100: SM_setMathCap = 273
101: SM_executeStringByLocalParserInBatchMode = 274
102: SM_getsp = 275
103: SM_dupErrors = 276
104:
105: SM_DUMMY_sendcmo = 280
106: SM_sync_ball = 281
107:
108: SM_control_kill = 1024
109: SM_control_reset_connection = 1030
110: SM_control_to_debug_mode = 1025
111: SM_control_exit_debug_mode = 1026
112: SM_control_ping = 1027
113: SM_control_start_watch_thread = 1028
114: SM_control_stop_watch_thread = 1029
115:
116: # end of CMO constants
117:
118: class CMO
1.2 ! ogino 119: def set_tag(tag)
1.1 ogino 120: @tag = tag
121: end
1.2 ! ogino 122: attr_accessor :tag
1.1 ogino 123: end
124: class CMONull < CMO
125: def initialize
1.2 ! ogino 126: set_tag(CMO_NULL)
1.1 ogino 127: end
128: end
129: class CMOInt32 < CMO
130: def initialize(i)
1.2 ! ogino 131: set_tag(CMO_INT32)
1.1 ogino 132: @i = i
133: end
134: attr_accessor :i
135: end
136: class CMOString < CMO
137: def initialize(str)
1.2 ! ogino 138: set_tag(CMO_STRING)
1.1 ogino 139: @str = str
140: @len = str.length
141: end
142: attr_accessor :len, :str
143: end
144:
145: class OX < CMO
146: end
147:
148: class OXCommand < OX
149: def initialize(command)
1.2 ! ogino 150: set_tag(OX_COMMAND)
1.1 ogino 151: @command = command
152: end
153: attr_accessor :command
154: end
155: class OXData < OX
156: def initialize(cmo)
1.2 ! ogino 157: set_tag(OX_DATA)
1.1 ogino 158: @cmo = cmo
159: end
160: attr_accessor :cmo
161: end
162:
163: class OXSession
164: def initialize(host = "localhost",
165: controlport = 1200,
166: dataport = 1300,
167: byteorder = 0)
168: @serial = 0
169: begin
170: printf("Connecting to %s, \n", host)
171: printf("Trying to connect to controlport %d, \n", controlport)
172: @controlp = TCPSocket.new(host, controlport)
173: sleep 2
174: printf("Trying to connect to dataport %d, \n", dataport)
175: @datap = TCPSocket.new(host, dataport)
176: sleep 2
177: rescue
178: end
179:
180: # byte oder negotiation
181: @byteorder = decide_byte_order(byteorder)
182: end
183:
184: attr_accessor :controlp, :datap
185:
186: def decide_byte_order(b_or_l)
187: if b_or_l == 0
188: @controlp.read(1)
189: @datap.read(1)
190: @controlp.flush
191: @datap.flush
192: @controlp.write(0)
193: @datap.write(0)
194: return 0
195: end
196: end
197:
198: def send(data)
199: case data.tag
200: when OX_DATA
201: send_ox_tag(OX_DATA)
202: send_cmo(data.cmo)
203: when OX_COMMAND
204: send_ox_tag(OX_COMMAND);
205: send_int32(data.command);
206: end
207: end
208:
209: def send_ox_tag(tag)
210: send_int32(tag)
211: send_int32(@serial)
212: @serial += 1;
213: end
214:
215: def send_int32(n)
216: b = n.to_a.pack("N")
217: return datap.write(b)
218: end
219:
220: def send_cmo(data)
221: tag = data.tag
222: send_int32(tag)
223: case tag
224: when CMO_NULL
225: m = send_cmo_null
226: when CMO_INT32
227: m = send_cmo_int32(data)
228: when CMO_STRING
229: m = send_cmo_string(data)
230: when CMO_MATHCAP
231: m = send_cmo_mathcap(data)
232: when CMO_LIST
233: m = send_cmo_list(data)
234: end
235: return m
236: end
237:
238: def send_cmo_null
239: return 0
240: end
241:
242: def send_cmo_int32(cmo)
243: send_int32(cmo.i)
244: end
245:
246: def send_cmo_string(cmo)
247: send_int32(cmo.len)
248: datap.write(cmo.str)
249: end
250:
251: def receive
252: case tag = receive_int32
253: when CMO_NULL
254: m = receive_cmo_null
255: when CMO_INT32
256: m = receive_cmo_int32
257: when CMO_STRING
258: m = receive_cmo_string
259: when CMO_MATHCAP
260: m = receive_cmo_mathcap
261: when CMO_LIST
262: m = receive_cmo_list
263: # when CMO_MONOMIAL32
264: # m = receive_cmo_monomial32
265: # when CMO_ZZ
266: # m = receive_cmo_zz
267: # when CMO_ZERO
268: # m = receive_cmo_zero
269: # when CMO_DMS_GENERIC
270: # m = receive_cmo_dms_generic
271: # when CMO_RING_BY_NAME
272: # m = receive_cmo_ring_by_name
273: # when CMO_DISTRIBUTED_POLYNOMIAL
274: # m = receive_cmo_distributed_polynomial
275: # when CMO_ERROR2
276: # m = receive_cmo_error2
277: # when CMO_DATUM
278: # m = receive_cmo_datum
279: # when CMO_QQ
280: # m = receive_cmo_qq
281: else
282: fprintf(stderr, "the CMO (%d) is not implemented.\n", tag)
283: end
284:
285: return m;
286: end
287:
288: def receive_int32
289: return datap.read(4).unpack("N").pop
290: end
291:
292: def receive_cmo_null
293: return CMONull.new
294: end
295:
296: def receive_cmo_int32
297: return CMOInt32.new(receive_int32)
298: end
299:
300: # attr_accessor :send, :receive
301: end
302:
303: # Usage:
304: #
1.2 ! ogino 305: # Very simple example to connect to OpenXM server from Ruby.
1.1 ogino 306: # % ox -ox ../ox_toolkit/ox_Xsample
307: #
308: # % ruby ox.rb
309: #
310:
311: s = OXSession.new()
312:
1.2 ! ogino 313: s.send(OXData.new(CMOInt32.new(100)))
! 314: s.send(OXData.new(CMOInt32.new(100)))
! 315: s.send(OXData.new(CMOInt32.new(2)))
! 316: s.send(OXData.new(CMOString.new("lineto")))
! 317: s.send(OXCommand.new(SM_executeFunction))
1.1 ogino 318:
319: while 1
1.2 ! ogino 320: print '> '
! 321: STDOUT.flush
! 322: input = gets
! 323: break if not input
! 324: str = input
! 325: str.chop!
! 326: eval(str)
1.1 ogino 327: end
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>