[r8766]: main / branches / 4.1 / trunk / extensions / platform / windows / oodialog / APICommon.cpp Maximize Restore History

Download this file

APICommon.cpp    1304 lines (1200 with data), 40.6 kB

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
/*----------------------------------------------------------------------------*/
/* */
/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
/* Copyright (c) 2005-2013 Rexx Language Association. All rights reserved. */
/* */
/* This program and the accompanying materials are made available under */
/* the terms of the Common Public License v1.0 which accompanies this */
/* distribution. A copy is also available at the following address: */
/* http://www.oorexx.org/license.html */
/* */
/* Redistribution and use in source and binary forms, with or */
/* without modification, are permitted provided that the following */
/* conditions are met: */
/* */
/* Redistributions of source code must retain the above copyright */
/* notice, this list of conditions and the following disclaimer. */
/* Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in */
/* the documentation and/or other materials provided with the distribution. */
/* */
/* Neither the name of Rexx Language Association nor the names */
/* of its contributors may be used to endorse or promote products */
/* derived from this software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/*----------------------------------------------------------------------------*/
/**
* APICommon.cpp
*
* This module contains generic convenience functions that might be useful in
* any code that uses the ooRexx native API. Include APICommon.hpp to use them.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "oorexxapi.h"
#include "APICommon.hpp"
/**
* 49.900
* 49 -> A severe error was detected in the language processor or execution
* process during internal self-consistency checks.
*
* 900 -> User message
*
* @param c
* @param msg
*/
void severeErrorException(RexxThreadContext *c, const char *msg)
{
c->RaiseException1(Rexx_Error_Interpretation_user_defined, c->String(msg));
}
void systemServiceException(RexxThreadContext *c, const char *msg)
{
c->RaiseException1(Rexx_Error_System_service_user_defined, c->String(msg));
}
void systemServiceException(RexxThreadContext *context, const char *msg, const char *sub)
{
if ( sub != NULL )
{
char buffer[128];
snprintf(buffer, sizeof(buffer), msg, sub);
systemServiceException(context, buffer);
}
else
{
systemServiceException(context, msg);
}
}
void systemServiceExceptionCode(RexxThreadContext *context, const char *msg, const char *arg1, uint32_t rc)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), msg, arg1, rc);
systemServiceException(context, buffer);
}
void outOfMemoryException(RexxThreadContext *c)
{
systemServiceException(c, NO_MEMORY_MSG);
}
/**
* Error 98.900
*
* 98 The language processor detected a specific error during execution.
*
* 900 User message.
*
* The number of active dialogs has reached the maximum (20) allowed
*
* @param c
* @param msg
*/
void *executionErrorException(RexxThreadContext *c, CSTRING msg)
{
c->RaiseException1(Rexx_Error_Execution_user_defined, c->CString(msg));
return NULL;
}
/**
* Error 98.900
*
* 98 The language processor detected a specific error during execution. The
* associated error gives the reason for the error.
*
* 900 User message.
*
* The base class has not been initialized correctly
*
* @param c The method context we are operating under.
*
* @return Returns a null pointer. This allows this type of code:
*
* if ( pCSelf == NULL )
* {
* return baseClassIntializationException(c);
* }
*
* @remarks This error is intended to be used when the CSelf pointer is null.
* It can only happen (I believe) when the user inovkes a method on
* self in init() before the super class init() has run.
*/
void *baseClassIntializationException(RexxMethodContext *c)
{
return executionErrorException(c->threadContext, "The base class has not been initialized correctly");
}
/**
* Error 98.900
*
* 98 The language processor detected a specific error during execution. The
* associated error gives the reason for the error.
*
* 900 User message.
*
* The ooSQLiteDB base class has not been initialized correctly
*
* @param c The method context we are operating under.
* @param clsName The name of the base class.
*
* @return A null pointer to void
*
* @remarks This error is intended to be used when a CSelf pointer, is null. It
* can only happen (I believe) when the user inovkes a method on self
* in init() before the super class init() has run.
*
* Identifying the actual base class may make it easier for the user to
* understand what the problem is.
*/
void *baseClassIntializationException(RexxMethodContext *c, CSTRING clsName)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "The %s base class has not been initialized correctly", clsName);
return executionErrorException(c->threadContext, buffer);
}
/**
* Message
*
* Argument 1, the database connection object, can not be null
*
* Raises 88.900
*
* @param c Thread context we are executing in.
* @param msg "Some message"
*/
void userDefinedMsgException(RexxThreadContext *c, CSTRING msg)
{
c->RaiseException1(Rexx_Error_Invalid_argument_user_defined, c->String(msg));
}
/**
* Some kind of %d message
*
* The number of property sheet dialogs being concurrently created has reached
* the maximum (5) allowed.
*
* Raises 88.900
*
* @param *c Thread context we are executing in.
* @param formatStr Format string with 1 %d contained in it.
* @param number Replacement arg.
*/
void userDefinedMsgException(RexxThreadContext *c, CSTRING formatStr, int number)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), formatStr, number);
userDefinedMsgException(c, buffer);
}
/**
* Argument 'argument' 'message'
*
* Argument 2 must be a whole number greater than 100; actual 100.5
*
* Raises 88.900
*
* @param *c Thread context we are executing in.
* @param pos Argument position.
* @param msg "Some message"
*/
void userDefinedMsgException(RexxThreadContext *c, int pos, CSTRING msg)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d %s", pos, msg);
userDefinedMsgException(c, buffer);
}
/**
* Message
*
* The 'methodName' argument must be less than 256 characters
*
* Raises 93.900
*
* @param c Method context we are executing in.
* @param msg "Some message"
*/
void userDefinedMsgException(RexxMethodContext *c, CSTRING msg)
{
c->RaiseException1(Rexx_Error_Incorrect_method_user_defined, c->String(msg));
}
/**
* Method argument 'argument' 'message'
*
* Method argument 2 is not a handle
*
* Raises 93.900
*
* @param c Method context we are executing in.
* @param msg "Some message"
*/
void userDefinedMsgException(RexxMethodContext *c, size_t pos, CSTRING msg)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Method argument %d %s", pos, msg);
userDefinedMsgException(c, buffer);
}
/**
* Argument 'argument' must be of the 'class' class
*
* Argument 4 must be of the ImageList class
*
* Raises 88.914
*
* @param c The thread context we are operating under.
* @param pos The 'argument' position.
* @param n The name of the class expected.
*
* @return Pointer to void, could be used in the return statement of a method
* to return NULLOBJECT after the exeception is raised.
*/
RexxObjectPtr wrongClassException(RexxThreadContext *c, size_t pos, const char *n)
{
c->RaiseException2(Rexx_Error_Invalid_argument_noclass, c->WholeNumber(pos), c->String(n));
return NULLOBJECT;
}
/**
* Argument 'argument' must be of the 'class' class; found 'actual'
*
* Argument 4 must be of the Directory class; found a Stem
*
* Similar to 88.914
* Raises 88.900
*
* @param c The thread context we are operating under.
* @param pos The 'argument' position.
* @param n The name of the class expected.
* @param actual Some Rexx object.
*
* @return Pointer to void, could be used in the return statement of a method
* to return NULLOBJECT after the exeception is raised.
*
* @remarks If _actual is a stem object without an assigned name, then
* ObjectToStringValue() will return the empty string, which is
* confusing in the error message. Hence the work around. What would
* be better is to use the real class name for _actual, but currently
* I get Stem, rather than 'a Stem' or Array rather than 'an Array'.
* Need to figure out how to get an Array.
*/
RexxObjectPtr wrongClassException(RexxThreadContext *c, size_t pos, const char *n, RexxObjectPtr _actual)
{
char buffer[256];
CSTRING actual = c->ObjectToStringValue(_actual);
if ( strlen(actual) == 0 )
{
actual = strPrintClassID(c, _actual);
}
snprintf(buffer, sizeof(buffer), "Argument %d must be of the %s class; found %s",
pos, n, actual);
userDefinedMsgException(c, buffer);
return NULLOBJECT;
}
/**
* Argument 'argument' is not a valid 'msg'
*
* Argument 3 is not a valid menu handle
*
* Raises 88.900
*
* @param c Thread context we are executing in.
* @param pos Argumet position
* @param msg "Some message"
*/
RexxObjectPtr invalidTypeException(RexxThreadContext *c, size_t pos, const char *type)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d is not a valid %s", pos, type);
userDefinedMsgException(c, buffer);
return NULLOBJECT;
}
void invalidImageException(RexxThreadContext *c, size_t pos, CSTRING type, CSTRING actual)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d must be a %s image; found %s", pos, type, actual);
userDefinedMsgException(c, buffer);
}
/**
* Argument <argPos> must be less than <len> characters in length; length is
* <realLen>
*
* Argument 2 must be less than 255 characters in length; length is 260
*
* Raises 88.900
*
* @param c Thread context we are executing in.
* @param pos Argumet position
* @param len Fixed length
* @param realLen Actual length
*/
void stringTooLongException(RexxThreadContext *c, size_t pos, size_t len, size_t realLen)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d must be less than %d characters in length; length is %d",
pos, len, realLen);
userDefinedMsgException(c, buffer);
}
/**
* Argument <argPos> must be a whole number greater than <min>; found <actual>
*
* Argument 10 must be a whole number greater than 5; found 0
*
* Raises 88.900
*
* @param c Thread context we are executing in.
* @param pos Argumet position
* @param min Minimum - 1
* @param actual Actual Rexx object
*/
void numberTooSmallException(RexxThreadContext *c, int pos, int min, RexxObjectPtr actual)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d must be a whole number greater than %d; actual %s",
pos, min, c->ObjectToStringValue(actual));
userDefinedMsgException(c, buffer);
}
/**
* Argument <argPos> must be true or false; found "<actual>"
*
* Argument 5 must be true or fals; found "an Array"
*
* Similar to:
*
* 88.904
* Argument argument must be zero or a positive whole number; found "value"
*
* Raises 88.900
*
* @param c Thread context we are executing in.
* @param pos Argumet position
* @param actual Actual Rexx object
*/
RexxObjectPtr notBooleanException(RexxThreadContext *c, size_t pos, RexxObjectPtr actual)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d must be true or false; found \"%s\"",
pos, c->ObjectToStringValue(actual));
userDefinedMsgException(c, buffer);
return NULLOBJECT;
}
void wrongObjInArrayException(RexxThreadContext *c, size_t argPos, size_t index, CSTRING obj, RexxObjectPtr actual)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Index %d of the array, argument %d, must be %s; found \"%s\"",
index, argPos, obj, c->ObjectToStringValue(actual));
userDefinedMsgException(c, buffer);
}
void wrongObjInArrayException(RexxThreadContext *c, size_t argPos, size_t index, CSTRING obj)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Index %d of the array, argument %d, must be %s", index, argPos, obj);
userDefinedMsgException(c, buffer);
}
void wrongObjInDirectoryException(RexxThreadContext *c, int argPos, CSTRING index, CSTRING needed, RexxObjectPtr actual)
{
char buffer[256];
snprintf(buffer, sizeof(buffer),
"Index, %s, of argument %d, must be %s; found \"%s\"",
index, argPos, needed, c->ObjectToStringValue(actual));
userDefinedMsgException(c, buffer);
}
void missingIndexInDirectoryException(RexxThreadContext *c, int argPos, CSTRING index)
{
char buffer[256];
snprintf(buffer, sizeof(buffer),
"Index, %s, of argument %d, is required",
index, argPos);
userDefinedMsgException(c, buffer);
}
/**
* Aargument <pos> must contain at least one of the indexes: <indexes>"
*
* Argument 1 must contain at least one of the indexes: constDirUsage,
* symbolSrc, autoDetction, fontName, or fontSize
*
*
* @param c
* @param argPos
* @param indexes
*/
void missingIndexesInDirectoryException(RexxThreadContext *c, int argPos, CSTRING indexes)
{
char buffer[512];
snprintf(buffer, sizeof(buffer),
"The directory object, argument %d, most contain at least one of the indexes, %s",
argPos, indexes);
userDefinedMsgException(c, buffer);
}
/**
* Index, <index>, of argument <pos> must be one of <list>; found "<actual>"
*
* Index, PART, of argument 1 must be one of calendar, next, prev, or none;
* found "today"
*
* @param c
* @param pos
* @param index
* @param list
* @param actual
*
* @return RexxObjectPtr
*/
void directoryIndexExceptionList(RexxThreadContext *c, size_t pos, CSTRING index, CSTRING list, CSTRING actual)
{
char buffer[512];
snprintf(buffer, sizeof(buffer),
"Index, %s, of argument %d must be one of %s; found \"%s\"", index, pos, list, actual);
userDefinedMsgException(c, buffer);
}
/**
* Index, <index>, of argument <pos> <msg>; found "<actual>"
*
* Index, PART, of argument 1 must contain at least one of the keywords: date,
* rect, or name; found "today"
*
* @param c
* @param pos
* @param index
* @param list
* @param actual
*
* @return RexxObjectPtr
*/
void directoryIndexExceptionMsg(RexxThreadContext *c, size_t pos, CSTRING index, CSTRING msg, CSTRING actual)
{
char buffer[512];
snprintf(buffer, sizeof(buffer),
"Index, %s, of argument %d %s; found \"%s\"", index, pos, msg, actual);
userDefinedMsgException(c, buffer);
}
void emptyArrayException(RexxThreadContext *c, int argPos)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d must be a non-empty array", argPos);
userDefinedMsgException(c, buffer);
}
void arrayToLargeException(RexxThreadContext *c, uint32_t found, uint32_t max, int argPos)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d, array items (%d) exceeds maximum (%d) allowed", argPos, found, max);
userDefinedMsgException(c, buffer);
}
void sparseArrayException(RexxThreadContext *c, size_t argPos, size_t index)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d must be a non-sparse array, index %d is missing", argPos, index);
userDefinedMsgException(c, buffer);
}
/**
* Error 98.913
*
* 98 The language processor detected a specific error during execution.
*
* 913: Unable to convert object "a MyThings" to a single-dimensional array
* value
*
* @param c Method context we are executing in.
* @param obj The "MyThings" object.
*
* @Note This would be the exception most often seen in a do n over c statement
* when c does not have a makeArray() method.
*/
void doOverException(RexxThreadContext *c, RexxObjectPtr obj)
{
c->RaiseException1(Rexx_Error_Execution_noarray, obj);
}
/**
* Error 98.900
*
* Produces a message:
*
* Could not retrieve the "value" information for "object"
*
* Could not retrive the window handle information for a PlainBaseDialog object.
*
* similar to old 98.921
*
* @param c Method context we are operating in.
* @param item What was to be retrieved
* @param source The object it was being retrieved from.
*/
void failedToRetrieveException(RexxThreadContext *c, CSTRING item, RexxObjectPtr source)
{
char buf[128];
RexxObjectPtr name = c->SendMessage0(source, "OBJECTNAME");
snprintf(buf, sizeof(buf), "Could not retrieve the %s information for %s",
item, c->ObjectToStringValue(name));
c->RaiseException1(Rexx_Error_Execution_user_defined, c->String(buf));
}
void nullObjectException(RexxThreadContext *c, CSTRING name, size_t pos)
{
char buffer[256];
if ( pos == 0 )
{
snprintf(buffer, sizeof(buffer), "The %s object must not be null", name);
}
else
{
snprintf(buffer, sizeof(buffer), "Argument %d, the %s object, must not be null", pos, name);
}
userDefinedMsgException(c, buffer);
}
void nullStringMethodException(RexxMethodContext *c, size_t pos)
{
char buffer[256];
snprintf(buffer, sizeof(buffer), "Argument %d, must not be the empty string", pos);
c->RaiseException1(Rexx_Error_Incorrect_method_user_defined, c->String(buffer));
}
void nullObjectException(RexxThreadContext *c, CSTRING name)
{
nullObjectException(c, name, 0);
}
void nullPointerException(RexxThreadContext *c, int pos)
{
c->RaiseException1(Rexx_Error_Invalid_argument_null, c->WholeNumber(pos));
}
void notNonNegativeException(RexxThreadContext *c, size_t pos, RexxObjectPtr actual)
{
c->RaiseException2(Rexx_Error_Invalid_argument_nonnegative, c->StringSize(pos), actual);
}
void notPositiveException(RexxThreadContext *c, size_t pos, RexxObjectPtr actual)
{
c->RaiseException2(Rexx_Error_Invalid_argument_positive, c->StringSize(pos), actual);
}
RexxObjectPtr wrongRangeException(RexxThreadContext *c, size_t pos, int min, int max, RexxObjectPtr actual)
{
c->RaiseException(Rexx_Error_Invalid_argument_range,
c->ArrayOfFour(c->WholeNumber(pos), c->WholeNumber(min), c->WholeNumber(max), actual));
return NULLOBJECT;
}
RexxObjectPtr wrongRangeException(RexxThreadContext *c, size_t pos, int min, int max, int actual)
{
return wrongRangeException(c, pos, min, max, c->WholeNumber(actual));
}
RexxObjectPtr wrongRangeException(RexxThreadContext *c, size_t pos, uint32_t min, uint32_t max, uint32_t actual)
{
c->RaiseException(Rexx_Error_Invalid_argument_range,
c->ArrayOfFour(c->StringSize(pos),
c->UnsignedInt32(min),
c->UnsignedInt32(max),
c->UnsignedInt32(actual)));
return NULLOBJECT;
}
RexxObjectPtr wrongArgValueException(RexxThreadContext *c, size_t pos, const char *list, RexxObjectPtr actual)
{
c->RaiseException(Rexx_Error_Invalid_argument_list,
c->ArrayOfThree(c->WholeNumber(pos), c->String(list), actual));
return NULLOBJECT;
}
RexxObjectPtr wrongArgValueException(RexxThreadContext *c, size_t pos, const char *list, const char *actual)
{
return wrongArgValueException(c, pos, list, c->String(actual));
}
/**
* Similar to 93.914
*
* Method argument <pos>, must contain one or more of <list>; found "<actual>"
*
* Method argument 2 must contain one or more of SKIPINVISIBLE, SKIPDISABLED,
* SKIPTRANSPARENT, or ALL; found "BOGUS NOTVISIBLE"
*
* @param c Thread context
* @param pos
* @param list
* @param actual
*
* @return RexxObjectPtr
*/
RexxObjectPtr wrongArgKeywordsException(RexxThreadContext *c, size_t pos, CSTRING list, CSTRING actual)
{
char buffer[512];
snprintf(buffer, sizeof(buffer), "Method argument %d, must contain one or more of %s; found \"%s\"",
pos, list, actual);
userDefinedMsgException(c, buffer);
return NULLOBJECT;
}
RexxObjectPtr wrongArgKeywordsException(RexxThreadContext *c, size_t pos, CSTRING list, RexxObjectPtr actual)
{
return wrongArgOptionException(c, pos, list, c->ObjectToStringValue(actual));
}
/**
* Similar to 93.915 and 93.914 (actually a combination of the two.)
*
* Method argument <pos>, option must be one of <list>; found "<actual>"
*
* Method argument 2 must be one of [P]artially, or [E]ntirely; found "G"
*
* @param c
* @param pos
* @param list
* @param actual
*
* @return RexxObjectPtr
*/
RexxObjectPtr wrongArgOptionException(RexxThreadContext *c, size_t pos, CSTRING list, CSTRING actual)
{
char buffer[512];
snprintf(buffer, sizeof(buffer), "Method argument %d, option must be one of %s; found \"%s\"", pos, list, actual);
userDefinedMsgException(c, buffer);
return NULLOBJECT;
}
RexxObjectPtr wrongArgOptionException(RexxThreadContext *c, size_t pos, CSTRING list, RexxObjectPtr actual)
{
return wrongArgOptionException(c, pos, list, c->ObjectToStringValue(actual));
}
/**
* Similar to error 43.001 Could not find routine <routine>
*
* Argument <pos>, (the <rtnName> routine,) could not be found
*
* Argument 2, (the "myCallback" routine,) could not be found
*
* @param c
* @param pos
* @param list
* @param actual
*
* @return RexxObjectPtr
*/
RexxObjectPtr noSuchRoutineException(RexxThreadContext *c, CSTRING rtnName, size_t pos)
{
char buf[512];
snprintf(buf, sizeof(buf), "Argument %d, (the \"%s\" routine,) could not be found", pos, rtnName);
c->RaiseException1(Rexx_Error_Invalid_argument_user_defined, c->String(buf));
return NULLOBJECT;
}
/**
* Similar to error 93.963 Call to unsupported or unimplemented method
*
* Call to unsupported or unimplemented routine (<rtnName)
*
* Argument 2, (the "myCallback" routine,) could not be found
*
* @param c
* @param pos
* @param list
* @param actual
*
* @return RexxObjectPtr
*/
RexxObjectPtr unsupportedRoutineException(RexxCallContext *c, CSTRING rtnName)
{
char buf[512];
snprintf(buf, sizeof(buf), "Call to unsupported or unimplemented routine (\"%s\")", rtnName);
c->RaiseException1(Rexx_Error_Incorrect_call_user_defined, c->String(buf));
return NULLOBJECT;
}
/**
* 98.900
* Error 98 - Execution error
* The language processor detected a specific error during execution.
*
* The return from method "name"() must be a whole number; found "actual"
* or
* The return from routine "name"() must be a whole number; found "actual"
*
* The return from method commitHookCallBack() must be a whole number; found an
* array
*
*/
RexxObjectPtr invalidReturnWholeNumberException(RexxThreadContext *c, CSTRING name, RexxObjectPtr actual, bool isMethod)
{
char buf[256];
snprintf(buf, sizeof(buf), "The return from %s %s() must be a whole number; found %s",
isMethod ? "method" : "routine", name, c->ObjectToStringValue(actual));
c->RaiseException1(Rexx_Error_Execution_user_defined, c->String(buf));
return NULLOBJECT;
}
CSTRING rxGetStringAttribute(RexxMethodContext *context, RexxObjectPtr obj, CSTRING name)
{
CSTRING value = NULL;
RexxObjectPtr rxString = context->SendMessage0(obj, name);
if ( rxString != NULLOBJECT )
{
value = context->ObjectToStringValue(rxString);
}
return value;
}
bool rxGetNumberAttribute(RexxMethodContext *context, RexxObjectPtr obj, CSTRING name, wholenumber_t *pNumber)
{
bool result = false;
RexxObjectPtr rxNumber = context->SendMessage0(obj, name);
if ( rxNumber != NULLOBJECT )
{
wholenumber_t number;
if ( context->WholeNumber(rxNumber, &number) )
{
*pNumber = number;
result = true;
}
}
return result;
}
bool rxGetUIntPtrAttribute(RexxMethodContext *context, RexxObjectPtr obj, CSTRING name, uintptr_t *pNumber)
{
bool result = false;
RexxObjectPtr rxNumber = context->SendMessage0(obj, name);
if ( rxNumber != NULLOBJECT )
{
uintptr_t number;
if ( context->ObjectToUintptr(rxNumber, &number) )
{
*pNumber = number;
result = true;
}
}
return result;
}
bool rxGetUInt32Attribute(RexxMethodContext *context, RexxObjectPtr obj, CSTRING name, uint32_t *pNumber)
{
bool result = false;
RexxObjectPtr rxNumber = context->SendMessage0(obj, name);
if ( rxNumber != NULLOBJECT )
{
uint32_t number;
if ( context->ObjectToUnsignedInt32(rxNumber, &number) )
{
*pNumber = number;
result = true;
}
}
return result;
}
bool requiredClass(RexxThreadContext *c, RexxObjectPtr obj, const char *name, size_t pos)
{
if ( obj == NULLOBJECT )
{
wrongClassException(c, pos, name);
return false;
}
else if ( ! c->IsOfType(obj, name) )
{
wrongClassException(c, pos, name, obj);
return false;
}
return true;
}
/**
* Converts a Rexx object to a logical value, 0 or 1. Returns -1 if the object
* can not be converted.
*
* @param c Thread context we are operating in.
* @param obj The object to convert.
*
* @return On success return 0 or 1 depending on what obj is. Otherwise return
* -1 to signal failure.
*/
int32_t getLogical(RexxThreadContext *c, RexxObjectPtr obj)
{
if ( obj != NULLOBJECT )
{
if ( obj == c->True() )
{
return 1;
}
if ( obj == c->False() )
{
return 0;
}
logical_t val;
if ( c->Logical(obj, &val) )
{
return (val == 0 ? 0 : 1);
}
}
return -1;
}
/**
* Return the number of existing arguments in an ooRexx method invocation. In
* others words, it is intended to count neither the omitted args in the ooRexx
* method, nor the pseudo-arguments to the native API function, like OSELF,
* CSELF, etc..
*
* @param context The method context pointer.
*
* @return The count of existing arguments in an ooRexx method invocation.
*/
size_t rxArgCount(RexxMethodContext * context)
{
RexxObjectPtr items = context->SendMessage0(context->GetArguments(), "ITEMS");
wholenumber_t count;
context->ObjectToWholeNumber(items, &count);
return (size_t)count;
}
/**
* Converts a string representing a number into an unsigned 64 bit number and
* raises an exception if the conversion fails.
*
* The string must have a format of 123456789 or 0xFFAB. A leading 0 without the
* following X will cause the string to be interpreted as an octal number, which
* may or may not trigger a failure. It is not the intent that this function be
* used for octal numbers.
*
* Note that it is the use of 0 as the third argument that allows _strtoui64()
* to interpret the string as decimal or hexadecimal based.
*
* @param c Method context we are operating in.
* @param str String to convert.
* @param number [OUT] Converted number is returned here.
* @param pos Argument position. Used for exception.
*
* @return True if the number was converted, false if an exceptions is raised.
*
* @note There is no way to tell the difference between a valid _UI64_MAX
* number and an error. The function simply assumes a return of
* _UI64_MAX is an error signal.
*
* @note This function is using some things that work on Windows, but cause
* errors on Linux. Just comment out until it can be researched.
* TODO PLEASE fix this.
*/
#ifdef _WIN32
bool rxStr2Number(RexxMethodContext *c, CSTRING str, uint64_t *number, size_t pos)
{
char *end;
*number = _strtoui64(str, &end, 0);
if ( (end - str != strlen(str)) || errno == EINVAL || *number == _UI64_MAX )
{
invalidTypeException(c->threadContext, pos, "number");
return false;
}
return true;
}
#endif
/*
* This function behaves exactly like rxStr2Number(), except it is for 32-bit
* numbers, and ERANGE can differentiate between a valid ULONG_MAX and an error
* return.
*/
bool rxStr2Number32(RexxMethodContext *c, CSTRING str, uint32_t *number, size_t pos)
{
char *end;
*number = strtoul(str, &end, 0);
if ( (end - str != strlen(str)) || errno == ERANGE )
{
invalidTypeException(c->threadContext, pos, "number");
return false;
}
return true;
}
/**
* Gets a Class object.
*
* This is for classes visible within the scope of a method context, like say
* .PlainBaseDialog, or .Rect. Use c->FindClass() to directly get classes from
* the environment like .Bag or .Directory. Use rxGetPackageClass() to get a
* class from a thread context when a method context is not available.
*
* @param c The method context we are operating in.
* @param name The name of the class to try and find.
*
* @return The class object or null on failure.
*
* @remarks When null is returned an error has been raised: 98.909
*
* 98: The language processor detected a specific error during execution. The
* associated error gives the reason for the error.
*
* 909: Class "class" not found
*/
RexxClassObject rxGetContextClass(RexxMethodContext *c, CSTRING name)
{
RexxClassObject theClass = c->FindContextClass(name);
if ( theClass == NULL )
{
c->RaiseException1(Rexx_Error_Execution_noclass, c->String(name));
}
return theClass;
}
/**
* Gets a Class object.
*
* This is for use when a method context is not available. Use
* rxGetContextClass() for classes visible within the scope of a method context,
* like say .PlainBaseDialog, or .Rect. Use c->FindClass() to directly get
* classes from the environment like .Bag or .Directory.
*
* @param c The thread context we are operating in.
* @param pkgName The name of the package the class is located in.
* @param clsName The name of the class to try and find.
*
* @return The class object or null on failure.
*
* @remarks When null is returned an error has been raised: 98.909
*
* 98: The language processor detected a specific error during execution. The
* associated error gives the reason for the error.
*
* 909: Class "class" not found
*
* This function will load the package named by pkgName. If the
* pacakge is already loaded this should be relatively expensive.
* This also implies that this function could be used to load a
* package that has not been loaded.
*/
RexxClassObject rxGetPackageClass(RexxThreadContext *c, CSTRING pkgName, CSTRING clsName)
{
RexxClassObject theClass = NULL;
RexxPackageObject pkg = c->LoadPackage(pkgName);
if ( pkg != NULL )
{
theClass = c->FindPackageClass(pkg, clsName);
}
if ( theClass == NULL )
{
c->RaiseException1(Rexx_Error_Execution_noclass, c->String(clsName));
}
return theClass;
}
/**
* Sets an object variable value and returns the existing value. With the
* caveat that if the object variable did not have a value set, .nil is
* returned.
*
* @param c The method context we are operating in.
* @param varName The object variable's name.
* @param val The value to set.
*
* @return The previous value of the object variable, if it was set, otherwise
* .nil.
*/
RexxObjectPtr rxSetObjVar(RexxMethodContext *c, CSTRING varName, RexxObjectPtr val)
{
RexxObjectPtr result = c->GetObjectVariable(varName);
if ( result == NULLOBJECT )
{
result = c->Nil();
}
c->SetObjectVariable(varName, val);
return result;
}
/**
* Return a new object of one of the builtin ooRexx classes.
*
* This should never fail, provided the caller sends the right class name,
* but, raise an exception if it does.
*
* @param c
* @param className
*
* @return RexxObjectPtr
*/
RexxObjectPtr rxNewBuiltinObject(RexxThreadContext *c, CSTRING className)
{
RexxObjectPtr o = NULLOBJECT;
RexxClassObject classObj = c->FindClass(className);
if ( classObj != NULL )
{
o = c->SendMessage0(classObj, "NEW");
if ( o == NULLOBJECT )
{
c->RaiseException2(Rexx_Error_No_method_name, classObj, c->String("NEW"));
}
}
else
{
c->RaiseException1(Rexx_Error_Execution_noclass, c->String(className));
}
return o;
}
RexxObjectPtr rxNewBuiltinObject(RexxMethodContext *c, CSTRING className)
{
return rxNewBuiltinObject(c->threadContext, className);
}
bool isOutOfMemoryException(RexxThreadContext *c)
{
RexxCondition condition;
RexxDirectoryObject condObj = c->GetConditionInfo();
if ( condObj != NULLOBJECT )
{
c->DecodeConditionInfo(condObj, &condition);
if ( condition.code == 48900 )
{
return true;
}
}
return false;
}
/**
* Outputs the typical condition message. For example:
*
* 4 *-* say dt~number
* Error 97 running C:\work\qTest.rex line 4: Object method not found
* Error 97.1: Object "a DateTime" does not understand message "NUMBER"
*
* @param c The thread context we are operating in.
* @param condObj The condition information object. The object returned from
* the C++ API GetConditionInfo()
* @param condition The RexxCondition struct. The filled in struct from the
* C++ API DecodeConditionInfo().
*
* @assumes There is a condition and that condObje and condition are valid.
*/
void standardConditionMsg(RexxThreadContext *c, RexxDirectoryObject condObj, RexxCondition *condition)
{
RexxObjectPtr list = c->SendMessage0(condObj, "TRACEBACK");
if ( list != NULLOBJECT )
{
RexxArrayObject a = (RexxArrayObject)c->SendMessage0(list, "ALLITEMS");
if ( a != NULLOBJECT )
{
size_t count = c->ArrayItems(a);
for ( size_t i = 1; i <= count; i++ )
{
RexxObjectPtr o = c->ArrayAt(a, i);
if ( o != NULLOBJECT )
{
printf("%s\n", c->ObjectToStringValue(o));
}
}
}
}
printf("Error %d running %s line %d: %s\n", condition->rc, c->CString(condition->program),
condition->position, c->CString(condition->errortext));
printf("Error %d.%03d: %s\n", condition->rc, conditionSubCode(condition), c->CString(condition->message));
}
/**
* Given a thread context, checks for a raised condition, and prints out the
* standard condition message if there is a condition.
*
* @param c Thread context we are operating in.
* @param clear True if the condition should be cleared, false if it should not
* be cleared.
*
* @return True if there was a condition, otherwise false.
*/
bool checkForCondition(RexxThreadContext *c, bool clear)
{
if ( c->CheckCondition() )
{
RexxCondition condition;
RexxDirectoryObject condObj = c->GetConditionInfo();
if ( condObj != NULLOBJECT )
{
c->DecodeConditionInfo(condObj, &condition);
standardConditionMsg(c, condObj, &condition);
if ( clear )
{
c->ClearCondition();
}
return true;
}
}
return false;
}
/**
* Test if a generic Rexx object is exactly some int.
*
* @param testFor The int value being tested for.
* @param val The generic Rexx object, which could be null.
* @param c The thread context we are executing under.
*
* @return True if val is the int number we are testing for, otherwise false.
*/
bool isInt(int testFor, RexxObjectPtr val, RexxThreadContext *c)
{
if ( val != NULLOBJECT )
{
int n;
if ( c->ObjectToInt32(val, &n) )
{
return n == testFor;
}
}
return false;
}
/**
* Test if a genric Rexx object is the type of specified class object.
*
* @param c The method context we are executing under.
* @param obj The object to test.
* @param classID The ID string of the class we are looking for.
*
* @return True if obj is a class object of the type specified, otherwise false.
*
* @note This is changed to be case sensitive because of stricmp problems.
* TODO PLEASE fix this.
*/
bool isOfClassType(RexxMethodContext *c, RexxObjectPtr obj, CSTRING classID)
{
if ( obj != NULLOBJECT && c->IsOfType(obj, "CLASS") )
{
RexxStringObject clsID = (RexxStringObject)c->SendMessage0(obj, "ID");
if ( clsID != NULLOBJECT && strcmp(c->StringData(clsID), classID) == 0 )
{
return true;
}
}
return false;
}
/**
* Print out the class ID of a Rexx object. Useful in debugging to identify
* exactly what a Rexx object is. Will work with class objects or instance
* objects.
*
* @param c The method context we are operating in.
* @param obj The object to identify.
*/
void dbgPrintClassID(RexxThreadContext *c, RexxObjectPtr obj)
{
if ( ! c->IsOfType(obj, "CLASS") )
{
obj = c->SendMessage0(obj, "CLASS");
}
CSTRING name = "<null>";
if ( obj != NULLOBJECT )
{
RexxStringObject id = (RexxStringObject)c->SendMessage0(obj, "ID");
if ( id != NULLOBJECT )
{
name = c->CString(id);
}
}
printf("Class: %s\n", name);
}
/**
* Returns the class ID of a Rexx object as a string, rather than printing it.
*
* Not that good of a function name, but meant to go hand in hand with
* dbgPrintClassID.
*
* Useful in exception messages to identify exactly what a Rexx object is. Will
* work with class objects or instance objects.
*
* @param c The thread context we are operating in.
* @param obj The object to identify.
*/
CSTRING strPrintClassID(RexxThreadContext *c, RexxObjectPtr obj)
{
if ( ! c->IsOfType(obj, "CLASS") )
{
obj = c->SendMessage0(obj, "CLASS");
}
if ( obj != NULLOBJECT )
{
RexxStringObject id = (RexxStringObject)c->SendMessage0(obj, "ID");
if ( id != NULLOBJECT )
{
return c->CString(id);
}
else
{
return "<not known>";
}
}
else
{
return "<not known>";
}
}
void dbgPrintClassID(RexxMethodContext *c, RexxObjectPtr obj)
{
dbgPrintClassID(c->threadContext, obj);
}
CSTRING strPrintClassID(RexxMethodContext *c, RexxObjectPtr obj)
{
return strPrintClassID(c->threadContext, obj);
}