Annotation of OpenXM/src/ruby/ox-c.rb, Revision 1.1
1.1 ! takayama 1: # ox-c.rb OpenXM client written by Ruby
! 2: # (takayama's version based on ogino's ox.rb)
! 3: #
! 4: # $OpenXM$
! 5: #
! 6: require 'socket'
! 7: include Socket::Constants
! 8:
! 9: # define for CMO constants
! 10:
! 11: # Moved from oxtag.h
! 12: LARGEID = 0x7f000000
! 13: CMO_PRIVATE = 0x7fff0000
! 14: CMO_ERROR = (LARGEID+1)
! 15: CMO_ERROR2 = (LARGEID+2)
! 16: CMO_NULL = 1
! 17: CMO_INT32 = 2
! 18: CMO_DATUM = 3
! 19: CMO_STRING = 4
! 20: CMO_MATHCAP = 5
! 21:
! 22: CMO_START_SIGNATURE = 0x7fabcd03
! 23: CMO_LOCAL_OBJECT = 0x7fcdef03
! 24: CMO_LOCAL_OBJECT_ASIR = (CMO_LOCAL_OBJECT+0)
! 25: CMO_LOCAL_OBJECT_SM1 = (CMO_LOCAL_OBJECT+1)
! 26: # for OpenMathematica
! 27: MLO_FUNCTION = (CMO_LOCAL_OBJECT+2)
! 28:
! 29: OX_LOCAL_OBJECT = 0x7fcdef30
! 30: OX_LOCAL_OBJECT_ASIR = (OX_LOCAL_OBJECT+0)
! 31: OX_LOCAL_OBJECT_SM1 = (OX_LOCAL_OBJECT+1)
! 32: OX_LOCAL_OBJECT_MATH = (OX_LOCAL_OBJECT+2)
! 33:
! 34: CMO_ARRAY = 16
! 35: CMO_LIST = 17
! 36: CMO_ATOM = 18
! 37: CMO_MONOMIAL32 = 19
! 38: CMO_ZZ = 20
! 39: CMO_QQ = 21
! 40: CMO_ZERO = 22
! 41: # CMO_DMS = 23
! 42: CMO_DMS_GENERIC = 24
! 43: CMO_DMS_OF_N_VARIABLES = 25
! 44: CMO_RING_BY_NAME = 26
! 45: CMO_RECURSIVE_POLYNOMIAL = 27
! 46: CMO_LIST_R = 28
! 47:
! 48: CMO_INT32COEFF = 30
! 49: CMO_DISTRIBUTED_POLYNOMIAL = 31
! 50: # CMO_ZZ_OLD = 32
! 51: CMO_POLYNOMIAL_IN_ONE_VARIABLE = 33
! 52: CMO_RATIONAL = 34
! 53:
! 54: CMO_64BIT_MACHINE_DOUBLE = 40
! 55: CMO_ARRAY_OF_64BIT_MACHINE_DOUBLE = 41
! 56: CMO_128BIT_MACHINE_DOUBLE = 42
! 57: CMO_ARRAY_OF_128BIT_MACHINE_DOUBLE = 43
! 58:
! 59: CMO_BIGFLOAT = 50
! 60: CMO_IEEE_DOUBLE_FLOAT = 51
! 61:
! 62: CMO_INDETERMINATE = 60
! 63: CMO_TREE = 61
! 64: CMO_LAMBDA = 62 # for function definition
! 65:
! 66:
! 67: OX_COMMAND = 513
! 68: OX_DATA = 514
! 69: OX_SYNC_BALL = 515 # ball to interrupt
! 70:
! 71: # level 2 stack machine with programming facility.
! 72: OX_START_OF_FUNCTION_BLOCK = 518
! 73: OX_END_OF_FUNCTION_BLOCK = 519
! 74: OX_ADDRESS = 520
! 75:
! 76: OX_DATA_WITH_SIZE = 521
! 77: OX_DATA_ASIR_BINARY_EXPRESSION = 522 # This number should be changed
! 78: OX_DATA_OPENMATH_XML = 523
! 79: OX_DATA_OPENMATH_BINARY = 524
! 80: OX_DATA_MP = 525
! 81:
! 82: # OX BYTE command
! 83: OX_BYTE_NETWORK_BYTE_ORDER = 0
! 84: OX_BYTE_LITTLE_ENDIAN = 1
! 85: OX_BYTE_BIG_ENDIAN = 0xff
! 86:
! 87: # ox_function_id.h
! 88: SM_popSerializedLocalObject = 258
! 89: SM_popCMO = 262
! 90: SM_popString = 263 # result ==> string and send the string by CMO
! 91:
! 92: SM_mathcap = 264
! 93: SM_pops = 265
! 94: SM_setName = 266
! 95: SM_evalName = 267
! 96: SM_executeStringByLocalParser = 268
! 97: SM_executeFunction = 269
! 98: SM_beginBlock = 270
! 99: SM_endBlock = 271
! 100: SM_shutdown = 272
! 101: SM_setMathCap = 273
! 102: SM_executeStringByLocalParserInBatchMode = 274
! 103: SM_getsp = 275
! 104: SM_dupErrors = 276
! 105:
! 106: SM_DUMMY_sendcmo = 280
! 107: SM_sync_ball = 281
! 108:
! 109: SM_control_kill = 1024
! 110: SM_control_reset_connection = 1030
! 111: SM_control_to_debug_mode = 1025
! 112: SM_control_exit_debug_mode = 1026
! 113: SM_control_ping = 1027
! 114: SM_control_start_watch_thread = 1028
! 115: SM_control_stop_watch_thread = 1029
! 116:
! 117: # end of CMO constants
! 118:
! 119: class CMO
! 120: def set_tag(tag)
! 121: @tag = tag
! 122: end
! 123: attr_accessor :tag
! 124: end
! 125: class CMONull < CMO
! 126: def initialize
! 127: set_tag(CMO_NULL)
! 128: end
! 129: end
! 130: class CMOInt32 < CMO
! 131: def initialize(i)
! 132: set_tag(CMO_INT32)
! 133: @i = i
! 134: end
! 135: attr_accessor :i
! 136: end
! 137: class CMOString < CMO
! 138: def initialize(str)
! 139: set_tag(CMO_STRING)
! 140: @str = str
! 141: @len = str.length
! 142: end
! 143: attr_accessor :len, :str
! 144: end
! 145:
! 146: class OX < CMO
! 147: end
! 148:
! 149: class OXCommand < OX
! 150: def initialize(command)
! 151: set_tag(OX_COMMAND)
! 152: @command = command
! 153: end
! 154: attr_accessor :command
! 155: end
! 156: class OXData < OX
! 157: def initialize(cmo)
! 158: set_tag(OX_DATA)
! 159: @cmo = cmo
! 160: end
! 161: attr_accessor :cmo
! 162: end
! 163:
! 164: class OXSession
! 165: def initialize(
! 166: oxserver = "ox_sm1",
! 167: host = "localhost",
! 168: byteorder = 0
! 169: )
! 170: @serial = 0
! 171:
! 172: if ENV.include?("OpenXM_HOME")
! 173: oxhome = ENV["OpenXM_HOME"]+"/"
! 174: else
! 175: oxhome = "/usr/local/OpenXM/"
! 176: end
! 177:
! 178: oxserver = oxhome+"bin/"+oxserver
! 179: srand()
! 180: @controlport = rand(20000)+1024
! 181: @dataport = @controlport+1
! 182: printf("Starting the server %s\n",oxserver)
! 183: $stdout.flush
! 184: controlThread =
! 185: Thread.start {
! 186: printf("Connection from %s, \n", host)
! 187: printf("Waiting a connection to controlport %d, \n", @controlport)
! 188: $stdout.flush
! 189: @controlp = TCPserver.open(@controlport)
! 190: @controlp = controlp.accept
! 191: }
! 192: printf("Waiting a connection to dataport %d, \n", @dataport)
! 193: $stdout.flush
! 194: @datap = TCPserver.open(@dataport)
! 195:
! 196: sleep 3 # Heuristic wait that TCPserver switches to accept mode.
! 197: printf(oxhome+"\n")
! 198: ox = oxhome+"bin/ox"
! 199: system("oxlog /usr/X11R6/bin/xterm -geometry 80x24-0-0 -e "+ox+" -ox "+oxserver+" -control "+@controlport.to_s()+" -data "+@dataport.to_s()+" -reverse -pass a &");
! 200: if $? == nil
! 201: printf("failed to start the ox server.\n")
! 202: exit()
! 203: end
! 204:
! 205: # rescue
! 206:
! 207: @datap = datap.accept
! 208: Thread#join controlThread
! 209:
! 210: # byte oder negotiation
! 211: @byteorder = decide_byte_order(byteorder)
! 212:
! 213: datap.read(2); ## I do not understand the reason why I need to read
! 214: ## these extra two bytes.
! 215:
! 216: end
! 217:
! 218: attr_accessor :controlp, :datap
! 219:
! 220: def decide_byte_order(b_or_l)
! 221: if b_or_l == 0
! 222: controlp.read(1) # do not use @controlp.read(1)
! 223: datap.read(1)
! 224: controlp.putc("\000");
! 225: datap.putc("\000");
! 226: controlp.flush
! 227: datap.flush
! 228: return 0
! 229: end
! 230: end
! 231:
! 232: def send(data)
! 233: case data.tag
! 234: when OX_DATA
! 235: send_ox_tag(OX_DATA)
! 236: send_cmo(data.cmo)
! 237: when OX_COMMAND
! 238: send_ox_tag(OX_COMMAND);
! 239: send_int32(data.command);
! 240: end
! 241: end
! 242:
! 243: def send_ox_tag(tag)
! 244: send_int32(tag)
! 245: send_int32(@serial)
! 246: @serial += 1;
! 247: end
! 248:
! 249: def send_int32(n)
! 250: b = n.to_a.pack("N")
! 251: return datap.write(b)
! 252: end
! 253:
! 254: def send_cmo(data)
! 255: tag = data.tag
! 256: send_int32(tag)
! 257: case tag
! 258: when CMO_NULL
! 259: m = send_cmo_null
! 260: when CMO_INT32
! 261: m = send_cmo_int32(data)
! 262: when CMO_STRING
! 263: m = send_cmo_string(data)
! 264: when CMO_MATHCAP
! 265: m = send_cmo_mathcap(data)
! 266: when CMO_LIST
! 267: m = send_cmo_list(data)
! 268: end
! 269: return m
! 270: end
! 271:
! 272: def send_cmo_null
! 273: return 0
! 274: end
! 275:
! 276: def send_cmo_int32(cmo)
! 277: send_int32(cmo.i)
! 278: end
! 279:
! 280: def send_cmo_string(cmo)
! 281: send_int32(cmo.len)
! 282: datap.write(cmo.str)
! 283: end
! 284:
! 285: def receive
! 286: oxtag = receive_int32
! 287: printf("oxtag = %d \n",oxtag)
! 288: seqNum = receive_int32
! 289: printf("seqNum = %d \n", seqNum)
! 290: $stdout.flush
! 291: if oxtag == OX_DATA then
! 292: tag = receive_int32
! 293: else
! 294: printf("Cannot handle this OX tag %d\n",oxtag)
! 295: $stdout.flush
! 296: end
! 297: printf("cmotag = %d \n",tag)
! 298: $stdout.flush
! 299: case tag
! 300: when CMO_NULL
! 301: m = receive_cmo_null
! 302: when CMO_INT32
! 303: m = receive_cmo_int32
! 304: when CMO_STRING
! 305: m = receive_cmo_string
! 306: when CMO_MATHCAP
! 307: m = receive_cmo_mathcap
! 308: when CMO_LIST
! 309: m = receive_cmo_list
! 310: # when CMO_MONOMIAL32
! 311: # m = receive_cmo_monomial32
! 312: # when CMO_ZZ
! 313: # m = receive_cmo_zz
! 314: # when CMO_ZERO
! 315: # m = receive_cmo_zero
! 316: # when CMO_DMS_GENERIC
! 317: # m = receive_cmo_dms_generic
! 318: # when CMO_RING_BY_NAME
! 319: # m = receive_cmo_ring_by_name
! 320: # when CMO_DISTRIBUTED_POLYNOMIAL
! 321: # m = receive_cmo_distributed_polynomial
! 322: # when CMO_ERROR2
! 323: # m = receive_cmo_error2
! 324: # when CMO_DATUM
! 325: # m = receive_cmo_datum
! 326: # when CMO_QQ
! 327: # m = receive_cmo_qq
! 328: else
! 329: printf("the CMO (%d) is not implemented.\n", tag)
! 330: $stdout.flush
! 331: end
! 332:
! 333: return m;
! 334: end
! 335:
! 336: def receive_int32
! 337: hoge = datap.read(4)
! 338: printf("[ ");
! 339: hoge.each_byte { |c| printf("%2x ",c) }
! 340: printf(" ]\n");
! 341: return hoge.unpack("N").pop
! 342: # return datap.read(4).unpack("N").pop
! 343: end
! 344:
! 345: def receive_cmo_null
! 346: return CMONull.new
! 347: end
! 348:
! 349: def receive_cmo_int32
! 350: return CMOInt32.new(receive_int32)
! 351: end
! 352:
! 353: def receive_cmo_string
! 354: size = receive_int32
! 355: s = datap.read(size)
! 356: return(s)
! 357: end
! 358:
! 359: def rpc(s)
! 360: # when s is a string
! 361: self.send(OXData.new(CMOString.new(s)))
! 362: self.send(OXCommand.new(SM_executeStringByLocalParser))
! 363: self.send(OXCommand.new(SM_popString))
! 364: return(self.receive())
! 365: end
! 366: def submit(s)
! 367: # when s is a string
! 368: self.send(OXData.new(CMOString.new(s)))
! 369: self.send(OXCommand.new(SM_executeStringByLocalParser))
! 370: end
! 371:
! 372: # attr_accessor :send, :receive
! 373: end
! 374:
! 375: # Usage
! 376: # % ruby ox-taka.rb
! 377: #
! 378:
! 379: s = OXSession.new()
! 380:
! 381: s.submit(" [(oxWatch) 1] extension ");
! 382: ## sample
! 383: a = s.rpc(" 1 1 add ")
! 384: printf("The result of << 1 1 add >> is ====> %s\n",a)
! 385: ## define some useful macros for ruby-sm1
! 386: s.submit(" /run {/@@@.run.filename set [(parse) @@@.run.filename pushfile] extension} def");
! 387: s.submit(" /quit (Type in ctrl-C to quit.) def ");
! 388: $stdout.flush
! 389:
! 390: ## sample
! 391: ## 1 3 add
! 392: while 1
! 393: printf("\nruby-sm1>")
! 394: STDOUT.flush
! 395: input = gets
! 396: break if not input
! 397: str = input
! 398: str.chop!
! 399: eval("print(s.rpc(\""+str+"\"))")
! 400: end
! 401:
! 402:
! 403: while 1
! 404: print '> '
! 405: STDOUT.flush
! 406: input = gets
! 407: break if not input
! 408: str = input
! 409: str.chop!
! 410: eval(str)
! 411: end
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>