@@ -292,18 +292,25 @@ end);
292
292
# # This is a counterpart of the OpenMath function OMgetObjectXMLTree
293
293
# #
294
294
InstallGlobalFunction( OMgetObjectXMLTreeWithAttributes,
295
- function ( string )
296
- local return_tree, return_deferred, node, attrs, t, obj, pos, name;
297
-
295
+ function ( string )
296
+ local return_tree,
297
+ return_deferred,
298
+ node,
299
+ attrs,
300
+ t,
301
+ obj,
302
+ pos,
303
+ name;
304
+
298
305
if ValueOption(" return_tree" ) <> fail then
299
306
return_tree := true ;
300
307
else
301
- return_tree := false ;
308
+ return_tree := false ;
302
309
fi ;
303
310
304
311
OMTempVars.OMBIND := rec ( );
305
312
OMTempVars.OMREF := rec ( );
306
-
313
+
307
314
# This is the difference from OMgetObjectXMLTree
308
315
OMTempVars.OMATTR := rec ( );
309
316
@@ -312,198 +319,144 @@ InstallGlobalFunction( OMgetObjectXMLTreeWithAttributes,
312
319
node.content := Filtered( node.content, OMIsNotDummyLeaf );
313
320
314
321
# Print( "ParseTreeXMLString( string ) = ", node.content, "\n" );
315
-
316
322
attrs := List( Filtered( node.content[ 1 ] .content, t -> t.name = " OMATP" ), OMParseXmlObj );
317
-
323
+
318
324
if Length(attrs)= 1 then
319
- attrs:= attrs[ 1 ] ;
325
+ attrs:= attrs[ 1 ] ;
320
326
fi ;
321
-
327
+
322
328
# At this point we already know attributes BEFORE the the real computation is started.
323
329
# This allows us to know in advance which kind of return (object/cookie/tree)
324
330
# is expected, and which runtime and memory limits were specified, if any.
325
331
326
- # Now we will check that this is really procedure_call message and that
327
- # the procedure is allowed, that is, it is from scscp{1,2} or scscp_transient_X CD
328
-
329
- if SCSCPserverMode then
330
-
331
- SCSCP_UNBIND_MODE := false ;
332
+ # Now we will check that this is really procedure_call message and that
333
+ # the procedure is allowed, that is, it is from scscp{1,2} or scscp_transient_X CD
334
+
335
+ if SCSCPserverMode then
336
+ SCSCP_UNBIND_MODE := false ;
332
337
SCSCP_STORE_SESSION_MODE := true ;
333
-
334
- pos:= PositionProperty( node.content[ 1 ] .content, r -> r.name= " OMA" ); # expected scscp1.procedure_call
335
- if pos= fail then
336
- return rec ( object := [ " Message rejected: it must be a proper scscp1.procedure_call" ] ,
337
- attributes := attrs, is_error:= true );
338
- else
339
- node.content[ 1 ] .content[ pos] .content :=
340
- Filtered( node.content[ 1 ] .content[ pos] .content, OMIsNotDummyLeaf );
341
- if not IsBound ( node.content[ 1 ] .content[ pos] .content[ 1 ] ) or
342
- not IsBound ( node.content[ 1 ] .content[ pos] .content[ 1 ] .attributes ) or
343
- not node.content[ 1 ] .content[ pos] .content[ 1 ] .attributes in
344
- [ rec ( name := " procedure_call" , cd := " scscp1" ),
345
- rec ( name := " procedure_completed" , cd := " scscp1" ),
346
- rec ( name := " procedure_terminated" , cd := " scscp1" ) ]
347
- then
348
- return rec ( object := [ " Message rejected because it is not a proper scscp1.procedure_call" ] ,
349
- attributes := attrs, is_error:= true );
350
- else
351
- node.content[ 1 ] .content[ pos] .content[ 2 ] .content :=
352
- Filtered( node.content[ 1 ] .content[ pos] .content[ 2 ] .content, OMIsNotDummyLeaf );
353
- if not IsBound ( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] ) or
354
- not IsBound ( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes ) or
355
- not IsBound ( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd ) then
356
- return rec ( object := [ " Message rejected because it is not properly formatted" ] ,
357
- attributes := attrs, is_error:= true );
358
- elif SCSCPserverAcceptsOnlyTransientCD and
359
- ( Length( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd ) < 5 or
360
- not node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd{[ 1 .. 5 ]} = " scscp" ) then
361
- return rec ( object := [
362
- " Message rejected because the procedure " ,
363
- node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd, " ." ,
364
- node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.name,
365
- " is not allowed" ] ,
366
- attributes := attrs, is_error:= true );
367
- else
368
- # some checks for some particular special procedures might be here
369
- if node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd = " scscp2" then
370
- name := node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.name;
371
- if name = " unbind" then
372
- SCSCP_UNBIND_MODE := true ;
373
- elif name = " store_persistent" then
374
- SCSCP_STORE_SESSION_MODE := false ;
375
- fi ;
376
- fi ;
377
- fi ;
378
- fi ;
379
- fi ;
380
-
381
- fi ;
382
-
383
- # if the security check is done, we may proceed
384
-
385
- if ForAny( attrs, t -> t[ 1 ] = " option_return_deferred" ) then
386
- return_deferred := true ;
387
- else
388
- return_deferred := false ;
389
- fi ;
390
-
338
+
339
+ pos:= PositionProperty( node.content[ 1 ] .content, r -> r.name= " OMA" ); # expected scscp1.procedure_call
340
+ if pos= fail then
341
+ return rec ( object := [ " Message rejected: it must be a proper scscp1.procedure_call" ] ,
342
+ attributes := attrs, is_error:= true );
343
+ else
344
+ node.content[ 1 ] .content[ pos] .content :=
345
+ Filtered( node.content[ 1 ] .content[ pos] .content, OMIsNotDummyLeaf );
346
+ if not IsBound ( node.content[ 1 ] .content[ pos] .content[ 1 ] ) or
347
+ not IsBound ( node.content[ 1 ] .content[ pos] .content[ 1 ] .attributes ) or
348
+ not node.content[ 1 ] .content[ pos] .content[ 1 ] .attributes in
349
+ [ rec ( name := " procedure_call" , cd := " scscp1" ),
350
+ rec ( name := " procedure_completed" , cd := " scscp1" ),
351
+ rec ( name := " procedure_terminated" , cd := " scscp1" ) ]
352
+ then
353
+ return rec ( object := [ " Message rejected because it is not a proper scscp1.procedure_call" ] ,
354
+ attributes := attrs, is_error:= true );
355
+ else
356
+ node.content[ 1 ] .content[ pos] .content[ 2 ] .content :=
357
+ Filtered( node.content[ 1 ] .content[ pos] .content[ 2 ] .content, OMIsNotDummyLeaf );
358
+ if not IsBound ( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] ) or
359
+ not IsBound ( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes ) or
360
+ not IsBound ( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd ) then
361
+ return rec ( object := [ " Message rejected because it is not properly formatted" ] ,
362
+ attributes := attrs, is_error:= true );
363
+ elif SCSCPserverAcceptsOnlyTransientCD and
364
+ ( Length( node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd ) < 5 or
365
+ not node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd{[ 1 .. 5 ]} = " scscp" ) then
366
+ return rec ( object := [
367
+ " Message rejected because the procedure " ,
368
+ node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd, " ." ,
369
+ node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.name,
370
+ " is not allowed" ] ,
371
+ attributes := attrs, is_error:= true );
372
+ else
373
+ # some checks for some particular special procedures might be here
374
+ if node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.cd = " scscp2" then
375
+ name := node.content[ 1 ] .content[ pos] .content[ 2 ] .content[ 1 ] .attributes.name;
376
+ if name = " unbind" then
377
+ SCSCP_UNBIND_MODE := true ;
378
+ elif name = " store_persistent" then
379
+ SCSCP_STORE_SESSION_MODE := false ;
380
+ fi ;
381
+ fi ;
382
+ fi ;
383
+ fi ;
384
+ fi ;
385
+ fi ;
386
+ # if the security check is done, we may proceed
387
+ if ForAny( attrs, t -> t[ 1 ] = " option_return_deferred" ) then
388
+ return_deferred := true ;
389
+ else
390
+ return_deferred := false ;
391
+ fi ;
391
392
if return_tree or return_deferred then
392
393
obj := node.content[ 1 ] ;
393
394
else
394
395
obj := OMParseXmlObj( node.content[ 1 ] );
395
396
fi ;
396
-
397
- # the next check was is a temporary measure to verify that
398
- # attributes were identified properly
399
-
400
- # if OMTempVars.OMATTR <> rec() then
401
- # if OMParseXmlObj( OMTempVars.OMATTR ) <> attrs then
402
- # Error("Attributes were not properly identified:\n",
403
- # "OMParseXmlObj( OMTempVars.OMATTR ) = ", OMParseXmlObj( OMTempVars.OMATTR ), "\n",
404
- # "attrs = ", attrs );
405
- # fi;
406
- # fi;
407
-
408
397
return rec ( object:= obj, attributes:= attrs );
409
-
410
398
end );
411
399
412
-
413
- # ############################################################################
414
- # #
415
- # # OMObjects.OMATTR( node )
416
- # #
417
- # # we overwrite the OpenMath function OMObjects.OMATTR with our definition
418
- # # (if OMObjects.OMATTR will be called from OpenMath, the OMTempWars.OMATTR
419
- # # will be ignored)
420
- # #
421
- OMObjects.OMATTR := function ( node )
422
- OMTempVars.OMATTR:= Filtered( node.content,
423
- function ( x )
424
- return x.name = " OMATP" ;
425
- end )[ 1 ] ;
426
- node.content := Filtered( node.content,
427
- function ( x )
428
- return x.name <> " OMATP" ;
429
- end );
430
- return OMParseXmlObj( node.content[ 1 ] );
431
- end ;
432
-
433
-
434
- # ############################################################################
435
- # #
436
- # # OMObjects.OMATP( node )
437
- # #
438
- # # We add OMObjects.OMATP function to the list of functions OMObjects
439
- # # defined as a global variable in the OpenMath package
440
- # #
441
- OMObjects.OMATP := function ( node )
442
- local i;
443
- # DisplayXMLStructure(node);
444
- return List( [ 1 ,3 .. Length(node.content)- 1 ] , i ->
445
- [ OMParseXmlObj(node.content[ i] ), OMParseXmlObj(node.content[ i+ 1 ] ) ] );
446
- end ;
447
-
448
-
449
400
# ############################################################################
450
401
# #
451
402
# # OMObjects.OMR( node )
452
403
# #
453
404
# # This overwrites OMObjects.OMR defined in OpenMath package as
454
405
# # return OMTempVars.OMREF.(node.attributes.href);
455
- # #
406
+ # #
407
+ # # FIXME: Move as much as possible of this into the OpenMath package,
408
+ # # maybe a configurable retrieval mechanism for "foreign" objects?
456
409
OMObjects.OMR := function ( node )
457
- local ref, pos1, pos2, pos3, name, server, port;
458
- if IsBound ( node.attributes.href ) then
459
- ref := node.attributes.href;
460
- pos1:= PositionSublist( ref, " ://" );
461
- pos2:= PositionNthOccurrence( ref, ' :' , 2 );
462
- if pos1= fail then
463
- # reference to an object within the same OpenMath document
464
- if ref[ 1 ] = CHAR_INT(35 ) then
465
- return OMTempVars.OMREF.(ref{[ 2 .. Length(ref)]} );
466
- else
467
- Error( " OpenMath reference: the first symbol must be " , CHAR_INT(35 ), " \n " );
468
- fi ;
469
- elif pos2= fail then
470
- # reference to an object in a file
471
- Error(" References to files are not implemented yet" );
472
- else
473
- # reference to a remote object
474
- if not ref{[ 1 .. pos1+ 2 ]} = " scscp://" then
475
- Error(" Can not parse the reference " , ref, " \n " );
476
- fi ;
477
- pos3 := PositionNthOccurrence( ref, ' /' , 3 );
478
- server:= ref{[ pos1+ 3 .. pos2- 1 ]} ;
479
- port:= Int(ref{[ pos2+ 1 .. pos3- 1 ]} );
480
- name := ref{[ pos3+ 1 .. Length(ref)]} ;
481
- if SCSCPserverMode then
482
- # check that the object is on the same server
483
- if [ server,port] = [ SCSCPserverAddress,SCSCPserverPort] then
484
- if IsBoundGlobal( name ) and
485
- Length( name ) > 12 and
486
- StartsWith( name, " TEMPVarSCSCP" ) then
487
- if SCSCP_UNBIND_MODE then
488
- SCSCP_UNBIND_MODE := false ;
489
- return name;
490
- else
491
- return EvalString( name );
492
- fi ;
410
+ local ref, pos1, pos2, pos3, name, server, port;
411
+ if IsBound ( node.attributes.href ) then
412
+ ref := node.attributes.href;
413
+ pos1:= PositionSublist( ref, " ://" );
414
+ pos2:= PositionNthOccurrence( ref, ' :' , 2 );
415
+ if pos1= fail then
416
+ # reference to an object within the same OpenMath document
417
+ if ref[ 1 ] = CHAR_INT(35 ) then
418
+ return OMTempVars.OMREF.(ref{[ 2 .. Length(ref)]} );
419
+ else
420
+ Error( " OpenMath reference: the first symbol must be " , CHAR_INT(35 ), " \n " );
421
+ fi ;
422
+ elif pos2= fail then
423
+ # reference to an object in a file
424
+ Error(" References to files are not implemented yet" );
493
425
else
494
- Error( " Client request refers to an unbound variable " , node.attributes.href, " \n " );
495
- fi ;
496
- else # for a "foreign" object
497
- return EvaluateBySCSCP( " retrieve" , [ name ] , server, port ).object;
498
- fi ;
499
- else # in the client's mode
500
- return RemoteObject( node.attributes.href, server, port );
426
+ # reference to a remote object
427
+ if not ref{[ 1 .. pos1+ 2 ]} = " scscp://" then
428
+ Error(" Can not parse the reference " , ref, " \n " );
429
+ fi ;
430
+ pos3 := PositionNthOccurrence( ref, ' /' , 3 );
431
+ server:= ref{[ pos1+ 3 .. pos2- 1 ]} ;
432
+ port:= Int(ref{[ pos2+ 1 .. pos3- 1 ]} );
433
+ name := ref{[ pos3+ 1 .. Length(ref)]} ;
434
+ if SCSCPserverMode then
435
+ # check that the object is on the same server
436
+ if [ server,port] = [ SCSCPserverAddress,SCSCPserverPort] then
437
+ if IsBoundGlobal( name ) and
438
+ Length( name ) > 12 and
439
+ StartsWith( name, " TEMPVarSCSCP" ) then
440
+ if SCSCP_UNBIND_MODE then
441
+ SCSCP_UNBIND_MODE := false ;
442
+ return name;
443
+ else
444
+ return EvalString( name );
445
+ fi ;
446
+ else
447
+ Error( " Client request refers to an unbound variable " , node.attributes.href, " \n " );
448
+ fi ;
449
+ else # for a "foreign" object
450
+ return EvaluateBySCSCP( " retrieve" , [ name ] , server, port ).object;
451
+ fi ;
452
+ else # in the client's mode
453
+ return RemoteObject( node.attributes.href, server, port );
454
+ fi ;
455
+ fi ;
456
+ else
457
+ Error( " OpenMath reference: only href is supported !\n " );
501
458
fi ;
502
- fi ;
503
- else
504
- Error( " OpenMath reference: only href is supported !\n " );
505
- fi ;
506
- end ;
459
+ end ;
507
460
508
461
509
462
# ############################################################################
0 commit comments