├── .gitignore ├── INSTALL.md ├── README.md ├── bin ├── build.sh ├── clean ├── clean.sh ├── mkdist.sh ├── tests.sh └── valgrind_phpunit.sh ├── builds ├── README.md ├── php_sapnwrfc_5.5_VC11_NTS_x86.dll ├── php_sapnwrfc_5.6_VC11_NTS_x86.dll └── php_sapnwrfc_5.6_VC11_TS_x86.dll ├── config.m4 ├── examples ├── 01-check.php ├── 02-ping.php ├── 03-ping-alternative.php ├── 04-call-simple.php └── 05-call-advanced.php ├── php_sapnwrfc.h ├── sapnwrfc.c ├── tests ├── .gitignore ├── Offline │ ├── FunctionsTest.php │ ├── SapNwRfcFunctionTest.php │ └── SapNwRfcTest.php ├── Online │ ├── AbstractOnlineTestCase.php │ ├── SapNwRfcFunctionTest.php │ └── SapNwRfcTest.php ├── Z_old │ ├── ConnTest.php │ ├── FuncChangeTest.php │ ├── FuncDataTest.php │ ├── FuncDescTest.php │ ├── FuncTest.php │ ├── ReadTableTest.php │ ├── SSOTest.php │ ├── sap.yml │ ├── sap_config.php │ └── spyc.php ├── connection.config.php.dist └── resources │ └── Z_TEST_DATA.abap └── tools └── u16lit.pl /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .buildpath 3 | .settings 4 | *.trc 5 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | 2 | # Install sapnwrfc 3 | 4 | Below are the install instructions for Unix and Windows 5 | 6 | 7 | ## Unix 8 | 9 | ### Requirements 10 | - PHP sources (http://www.php.net/downloads.php) 11 | - php-devel package for installation sapnwrfc as dynamic module 12 | - GNU tools (autoconf, automake, flex, libtool, gcc, m4, make) 13 | - Non-Unicode SAP RFCSDK 6.20 for your platform (see below) 14 | 15 | If you are SAP customer you can download it from http://service.sap.com/swdc under 16 | ) 18 | 19 | 20 | ### Install the SAP NW RFC SDK 21 | 22 | You must obtain and install the NW RFC SDK from SAP for this extension to work. 23 | [http://service.sap.com](http://service.sap.com) 24 | 25 | Please follow OSS note 1056472, 1058327, 1236530 26 | 27 | See also https://help.sap.com/saphelp_46c/helpdata/de/22/042887488911d189490000e829fbbd/content.htm?frameset=/de/22/04287a488911d189490000e829fbbd/frameset.htm¤t_toc=/de/22/0438e7488911d189490000e829fbbd/plain.htm&node_id=7 28 | 29 | 30 | ### Build static into PHP 31 | 32 | Extract source tarball to PHP source tree (under ext/ directory) and rebuild PHP with commands 33 | ``` 34 | rm ./configure 35 | ./buildconf --force 36 | ./configure --with-sapnwrfc= (+ your configuration directives) 37 | make 38 | ``` 39 | 40 | 41 | ### As a dynamic extension 42 | 43 | Extract source tarball to some directory and build dynamic module with commands 44 | ``` 45 | cd 46 | phpize 47 | ./configure 48 | ./configure --with-sapnwrfc= 49 | make 50 | make install 51 | ``` 52 | 53 | Enable sapnwrfc extension editing your php.ini 54 | ``` 55 | extension = sapnwrfc.so 56 | ``` 57 | 58 | see also the example [build.sh](build.sh) 59 | 60 | 61 | ## Windows 62 | 63 | 64 | ### Install the SAP NW RFC SDK 65 | 66 | - Get the `SAP NW RFC SDK` from http://service.sap.com. 67 | - Extract the SDK archive with SAPCAR 68 | - Copy the `*.dll` files from the `lib` folder to (just use the same like your PHP installation) 69 | - x86 (32bit): C:\Windows\system32 70 | - x64 (64bit): C:\Windows\SysWOW64 71 | 72 | 73 | ### Install the precompiled PHP extension 74 | 75 | - copy the right compiled version `php_sapnwrfc_*.dll` from [builds](builds) to your `php/ext` folder 76 | - active it in your `php.ini` (extension = php_sapnwrfc_*.dll) 77 | 78 | 79 | ### Build it on your own 80 | 81 | NOTE: This is harder than you think :-) 82 | 83 | - download SAP NW RFC SDK (i used 7.2.xxx) 84 | - extract with SAPCAR.exe to C:\SAP\sapcar_x86\nwrfcsdk (for x64 C:\SAP\sapcar_x64\nwrfcsdk) 85 | - get PHP "Development package (SDK to develop PHP extension)" http://windows.php.net/snapshots/ 86 | - install to C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86 87 | - install VS2012 (can be express for free) 88 | - create a new project (Visual C++ -> Win32 Project -> choose DLL -> choose empty project) 89 | - add the files from `php-sapnwrfc` to the project (i think `php_sapnwrfc.h` and `sapnwrfc.c` are enough, but i copied all) 90 | - also add them not just to folder, but to the header files! 91 | - add c++ paths for *.h files 92 | - C:\SAP\sapcar_x86\nwrfcsdk\include; 93 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include; 94 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\Zend; 95 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\win32; 96 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\TSRM; 97 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\sapi; 98 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\main; 99 | - Declare c++ preprocessors: 100 | - PHP_WIN32 101 | - ZEND_WIN32 102 | - ZEND_DEBUG=0 103 | - COMPILE_DL_SAPNWRFC 104 | - _UNICODE 105 | - UNICODE 106 | - SAPwithUNICODE 107 | - Linker add paths: 108 | - C:\SAP\sapcar_x86\nwrfcsdk\lib 109 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\lib 110 | - Linker add: 111 | - libsapucum.lib 112 | - sapnwrfc.lib 113 | - php5.lib 114 | 115 | #### Helping articles 116 | 117 | - https://wiki.php.net/internals/windows/stepbystepbuild 118 | - http://blog.slickedit.com/2007/09/creating-a-php-5-extension-with-visual-c-2005/ 119 | - https://jojokahanding.wordpress.com/2014/05/26/writing-php-extensions-for-windowsbuilding-a-compile-environment/ 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # SAPNWRFC extension for PHP 3 | 4 | ``` 5 | +----------------------------------------------------------------------+ 6 | | PHP Version 7 | 7 | +----------------------------------------------------------------------+ 8 | | Copyright (c) 2009-2015 Piers Harding | 9 | +----------------------------------------------------------------------+ 10 | | This source file is subject to version 3.01 of the PHP license, | 11 | | that is bundled with this package in the file LICENSE, and is | 12 | | available through the world-wide-web at the following url: | 13 | | http://www.php.net/license/3_01.txt | 14 | | If you did not receive a copy of the PHP license and are unable to | 15 | | obtain it through the world-wide-web, please send a note to | 16 | | license@php.net so we can mail you a copy immediately. | 17 | +----------------------------------------------------------------------+ 18 | | Author: Piers Harding | 19 | +----------------------------------------------------------------------+ 20 | ``` 21 | 22 | ## Summary 23 | 24 | Welcome to the sapnwrfc PHP package. This package is intended to facilitate RFC calls to an SAP R/3 system of release NW2004x and above. It may work for earlier versions but it hasn't been tested. 25 | The fundamental purpose of the production of this package, is to provide a clean object oriented interface to RFC calls from within PHP. This will hopefully have a number of effects: 26 | 27 | * make it really easy to do RFC calls to SAP from PHP in an object oriented fashion (Doh!) 28 | * promote PHP as the interface/scripting/glue language of choice for interaction with SAP R/3. 29 | * make the combination of Linux, Apache, and PHP the killer app for internet connectivity with SAP. 30 | * Establish a small fun open source project that people are more than welcome to contribute to, if they so wish. 31 | 32 | 33 | ## Installation 34 | 35 | Please see [INSTALL.md](INSTALL.md) 36 | 37 | 38 | ### Check if it works 39 | 40 | #### Listed as module? 41 | 42 | Should list `sapnwrfc` in the extension list 43 | 44 | ``` 45 | php -m 46 | ``` 47 | 48 | 49 | #### Display the installed versions 50 | 51 | ```php 52 | var_dump(sapnwrfc_version()); 53 | var_dump(sapnwrfc_rfcversion()); 54 | ``` 55 | 56 | #### Examples 57 | 58 | We provides [here](examples) some examples, to try your connection and do some RFC calls. 59 | 60 | 61 | #### Execute unit tests 62 | 63 | If you have downloaded the complete repository and you have `phpunit` installed globaly, you can execute from this repo root directory 64 | ``` 65 | phpunit 66 | ``` 67 | 68 | 69 | ## Getting started 70 | 71 | ```php 72 | use sapnwrfc; 73 | use sapnwrfcConnectionException; 74 | use sapnwrfcCallException; 75 | 76 | // see parameters here: http://help.sap.com/saphelp_nwpi711/helpdata/en/48/c7bb09da5e31ebe10000000a42189b/content.htm 77 | // example when using a message server 78 | $config = [ 79 | 'MSHOST' => '...', 80 | 81 | 'CLIENT' => '...', 82 | 83 | 'R3NAME' => '...', 84 | 'GROUP' => '...', 85 | 86 | 'CODEPAGE' => '...', 87 | 88 | 'LANG' => 'en', 89 | 90 | 'LCHECK' => true, 91 | 'TRACE' => true, 92 | 93 | 'user' => '...', 94 | 'passwd' => '...' 95 | ]; 96 | 97 | try { 98 | $conn = new sapnwrfc($config); 99 | } catch(sapnwrfcConnectionException $ex){ 100 | // do something! 101 | } 102 | 103 | if($conn->ping() === true){ 104 | //call a real method 105 | try { 106 | $func = $conn->function_lookup('RFC_PING'); 107 | 108 | /** 109 | * Call the function and return the result 110 | * @return array 111 | */ 112 | $result = $func->invoke([]); 113 | } catch (sapnwrfcCallException $ex){ 114 | // do something 115 | } 116 | } 117 | ``` 118 | 119 | ## Documentation 120 | 121 | ### Hint: change the log directory 122 | 123 | The sapnwrfc will create a logfile, if you enable `TRACE` 124 | It will by default use the current working dir. You can view your with `getcwd()` 125 | 126 | If you want to log it in the directory where you have your logfiles, just change the directory when you connect 127 | ```php 128 | $cwd = getcwd(); 129 | chdir('../your/log/folder'); 130 | try { 131 | $conn = new sapnwrfc($config); 132 | } catch(sapnwrfcConnectionException $ex){ 133 | // do something! e.g. log it 134 | } 135 | chdir($cwd); //change the cwd back to the previous value 136 | ``` 137 | 138 | ### Functions and classes 139 | 140 | A list of all available functions/methods and their parameters + return values 141 | 142 | ```php 143 | Win32 Project -> choose DLL -> choose empty project) 25 | - add the files from `php-sapnwrfc` to the project (i think `php_sapnwrfc.h` and `sapnwrfc.c` are enough, but i copied all) 26 | - also add them not just to folder, but to the header files! 27 | - add c++ paths for *.h files -> C:\SAP\sapcar_x86\nwrfcsdk\include;C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include;C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\Zend;C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\win32;C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\TSRM;C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\sapi;C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\include\main; 28 | - Declare c++ preprocessors: PHP_WIN32 29 | ZEND_WIN32 30 | ZEND_DEBUG=0 31 | COMPILE_DL_SAPNWRFC 32 | _UNICODE 33 | UNICODE 34 | SAPwithUNICODE 35 | - Linker add paths: 36 | - C:\SAP\sapcar_x86\nwrfcsdk\lib 37 | - C:\php-sdk\phpdev\vc11\x86\php-5.6.9-dev-devel-VC11-x86\lib 38 | - Linker add: 39 | - libsapucum.lib 40 | - sapnwrfc.lib 41 | - php5.lib 42 | - 43 | 44 | # Helping articles 45 | http://blog.slickedit.com/2007/09/creating-a-php-5-extension-with-visual-c-2005/ 46 | https://wiki.php.net/internals/windows/stepbystepbuild 47 | https://jojokahanding.wordpress.com/2014/05/26/writing-php-extensions-for-windowsbuilding-a-compile-environment/ 48 | -------------------------------------------------------------------------------- /builds/php_sapnwrfc_5.5_VC11_NTS_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piersharding/php-sapnwrfc/f521c9c359bae75f9af8889793d447a9c7da7d8a/builds/php_sapnwrfc_5.5_VC11_NTS_x86.dll -------------------------------------------------------------------------------- /builds/php_sapnwrfc_5.6_VC11_NTS_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piersharding/php-sapnwrfc/f521c9c359bae75f9af8889793d447a9c7da7d8a/builds/php_sapnwrfc_5.6_VC11_NTS_x86.dll -------------------------------------------------------------------------------- /builds/php_sapnwrfc_5.6_VC11_TS_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piersharding/php-sapnwrfc/f521c9c359bae75f9af8889793d447a9c7da7d8a/builds/php_sapnwrfc_5.6_VC11_TS_x86.dll -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl config.m4 for extension sapnwrfc 2 | dnl don't forget to call PHP_EXTENSION(sapnwrfc) 3 | 4 | dnl 5 | dnl PHP_ADD_SOURCES_X(source-path, sources[, special-flags[, target-var[, shared[, special-post-flags]]]]) 6 | dnl 7 | dnl Additional to PHP_ADD_SOURCES (see above), this lets you set the 8 | dnl name of the array target-var directly, as well as whether 9 | dnl shared objects will be built from the sources. 10 | dnl 11 | dnl Should not be used directly. 12 | dnl 13 | AC_DEFUN([PHP_ADD_SOURCES_X],[ 14 | dnl relative to source- or build-directory? 15 | dnl ac_srcdir/ac_bdir include trailing slash 16 | 17 | 18 | case $1 in 19 | ""[)] ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;; 20 | /*[)] ac_srcdir=`echo "$1"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;; 21 | *[)] ac_srcdir="$abs_srcdir/$1/"; ac_bdir="$1/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;; 22 | esac 23 | 24 | dnl how to build .. shared or static? 25 | ifelse($5,yes,_PHP_ASSIGN_BUILD_VARS(shared),_PHP_ASSIGN_BUILD_VARS(php)) 26 | 27 | dnl iterate over the sources 28 | old_IFS=[$]IFS 29 | for ac_src in $2; do 30 | 31 | dnl remove the suffix 32 | IFS=. 33 | set $ac_src 34 | ac_obj=[$]1 35 | IFS=$old_IFS 36 | 37 | dnl append to the array which has been dynamically chosen at m4 time 38 | $4="[$]$4 [$]ac_bdir[$]ac_obj.lo" 39 | 40 | dnl sort out the unix flag 41 | my_extra_flags=" -D_LARGEFILE_SOURCE -mno-3dnow -fno-strict-aliasing -pipe -fexceptions -funsigned-char -Wall -Wno-uninitialized -Wno-long-long -Wcast-align -DSAPwithUNICODE -DSAPonUNIX -D__NO_MATH_INLINES -fPIC -DSAPwithTHREADS" 42 | case "$host" in 43 | s390x-ibm-linux) 44 | my_extra_flags=" -D_LARGEFILE_SOURCE -mno-3dnow -fno-strict-aliasing -pipe -fexceptions -funsigned-char -Wall -Wno-uninitialized -Wno-long-long -Wcast-align -DSAPwithUNICODE -DSAPonUNIX -D__NO_MATH_INLINES -fPIC -DSAPwithTHREADS" 45 | ;; 46 | *-linux-*) 47 | my_extra_flags=" -D_LARGEFILE_SOURCE -mno-3dnow -fno-strict-aliasing -pipe -fexceptions -funsigned-char -Wall -Wno-uninitialized -Wno-long-long -Wcast-align -DSAPwithUNICODE -DSAPonUNIX -D__NO_MATH_INLINES -fPIC -DSAPwithTHREADS" 48 | ;; 49 | *mswin32*) 50 | my_extra_flags=" -DWIN32 -D_CONSOLE -DUNICODE -D_UNICODE -DSAPwithUNICODE -DSAPonNT -DSAP_PLATFORM_MAKENAME=ntintel" 51 | ;; 52 | *mingw32*) 53 | my_extra_flags=" -DWIN32 -D_CONSOLE -DUNICODE -D_UNICODE -DSAPwithUNICODE -DSAPonNT -DSAP_PLATFORM_MAKENAME=ntintel" 54 | ;; 55 | esac 56 | 57 | my_ac_comp="$b_c_pre $3 $ac_inc $b_c_meta $my_extra_flags -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" 58 | AC_CANONICAL_HOST 59 | case "$host" in 60 | *-linux-*) 61 | shared_c_pre_1='rm -f $<.ii $<.i && $(CC) -E ' 62 | shared_c_pre_2=' $< -o $<.ii && perl ./tools/u16lit.pl -le $<.ii && $(LIBTOOL) --mode=compile $(CC) ' 63 | my_ac_comp="$shared_c_pre_1 $3 $ac_inc $b_c_meta $my_extra_flags $shared_c_pre_2 $3 $ac_inc $b_c_meta $my_extra_flags -c $ac_srcdir$ac_src.i -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" 64 | ;; 65 | esac 66 | dnl choose the right compiler/flags/etc. for the source-file 67 | dnl *.c[)] ac_comp="$my_ac_comp" ;; 68 | dnl *.c[)] ac_comp="$b_c_pre $3 $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" ;; 69 | case $ac_src in 70 | *.c[)] ac_comp="$my_ac_comp" ;; 71 | *.s[)] ac_comp="$b_c_pre $3 $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" ;; 72 | *.S[)] ac_comp="$b_c_pre $3 $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" ;; 73 | *.cpp|*.cc|*.cxx[)] ac_comp="$b_cxx_pre $3 $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_cxx_post" ;; 74 | esac 75 | 76 | dnl create a rule for the object/source combo 77 | cat >>Makefile.objects< '...', 13 | 14 | 'CLIENT' => '...', 15 | 16 | 'R3NAME' => '...', 17 | 'GROUP' => '...', 18 | 19 | 'CODEPAGE' => '...', 20 | 21 | 'LANG' => 'en', 22 | 23 | 'LCHECK' => true, 24 | 'TRACE' => true, 25 | 26 | 'user' => '...', 27 | 'passwd' => '...' 28 | ]; 29 | 30 | $conn = new sapnwrfc($config); 31 | 32 | if ($conn->ping() === true) { 33 | echo 'Successfully pinged the SAP system'; 34 | } else { 35 | echo 'Could not ping the SAP system'; 36 | } 37 | 38 | $conn->close(); 39 | -------------------------------------------------------------------------------- /examples/03-ping-alternative.php: -------------------------------------------------------------------------------- 1 | '...', 13 | 14 | 'CLIENT' => '...', 15 | 16 | 'R3NAME' => '...', 17 | 'GROUP' => '...', 18 | 19 | 'CODEPAGE' => '...', 20 | 21 | 'LANG' => 'en', 22 | 23 | 'LCHECK' => true, 24 | 'TRACE' => true, 25 | 26 | 'user' => '...', 27 | 'passwd' => '...' 28 | ]; 29 | 30 | // change the directory for logging 31 | $cwd = getcwd(); 32 | chdir('my/log/dir'); 33 | 34 | try { 35 | $conn = new sapnwrfc($config); 36 | } catch (Exception $ex) { 37 | throw $ex; 38 | } finally { 39 | // change the cwd always back to the previous value 40 | chdir($cwd); 41 | } 42 | 43 | $func = $conn->function_lookup('RFC_PING'); 44 | 45 | $result = $func->invoke([]); 46 | 47 | // is an empty array 48 | if (is_array($result)) { 49 | echo 'Successfully pinged the SAP system'; 50 | } else { 51 | echo 'Could not ping the SAP system'; 52 | } 53 | 54 | $conn->close(); 55 | -------------------------------------------------------------------------------- /examples/04-call-simple.php: -------------------------------------------------------------------------------- 1 | '...', 13 | 14 | 'CLIENT' => '...', 15 | 16 | 'R3NAME' => '...', 17 | 'GROUP' => '...', 18 | 19 | 'CODEPAGE' => '...', 20 | 21 | 'LANG' => 'en', 22 | 23 | 'LCHECK' => true, 24 | 'TRACE' => true, 25 | 26 | 'user' => '...', 27 | 'passwd' => '...' 28 | ]; 29 | 30 | $conn = new sapnwrfc($config); 31 | 32 | $func = $conn->function_lookup('RFC_SYSTEM_INFO'); 33 | 34 | $result = $func->invoke([]); 35 | 36 | // is an empty array 37 | if (is_array($result)) { 38 | var_dump($result); 39 | } else { 40 | echo 'Could not ping the SAP system'; 41 | } 42 | 43 | $conn->close(); 44 | -------------------------------------------------------------------------------- /examples/05-call-advanced.php: -------------------------------------------------------------------------------- 1 | '...', 13 | 14 | 'CLIENT' => '...', 15 | 16 | 'R3NAME' => '...', 17 | 'GROUP' => '...', 18 | 19 | 'CODEPAGE' => '...', 20 | 21 | 'LANG' => 'en', 22 | 23 | 'LCHECK' => true, 24 | 'TRACE' => true, 25 | 26 | 'user' => '...', 27 | 'passwd' => '...' 28 | ]; 29 | 30 | $conn = new sapnwrfc($config); 31 | 32 | $fds = $conn->function_lookup('STFC_DEEP_STRUCTURE'); 33 | $fdt = $conn->function_lookup('STFC_DEEP_TABLE'); 34 | 35 | $parms = [ 36 | 'IMPORTSTRUCT' => [ 37 | 'I' => 123, 38 | 'C' => 'AbCdEf', 39 | 'STR' => 'The quick brown fox ...' 40 | ] 41 | ]; 42 | $results = $fds->invoke($parms); 43 | 44 | var_dump($results); 45 | 46 | $parms = [ 47 | 'IMPORT_TAB' => [ 48 | [ 49 | 'I' => 123, 50 | 'C' => 'AbCdEf', 51 | 'STR' => 'The quick brown fox ...' 52 | ] 53 | ] 54 | ]; 55 | $results = $fdt->invoke($parms); 56 | 57 | var_dump($results); 58 | 59 | $conn->close(); 60 | -------------------------------------------------------------------------------- /php_sapnwrfc.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2003 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id: php_sapnwrfc.h,v 1.1.1.1 2004/02/04 21:13:46 boerger Exp $ */ 20 | 21 | #ifndef PHP_SAPNWRFC_H 22 | #define PHP_SAPNWRFC_H 23 | 24 | extern zend_module_entry sapnwrfc_module_entry; 25 | #define phpext_sapnwrfc_ptr &sapnwrfc_module_entry 26 | 27 | #ifdef PHP_WIN32 28 | #define PHP_SAPNWRFC_API __declspec(dllexport) 29 | #else 30 | #define PHP_SAPNWRFC_API 31 | #endif 32 | 33 | #ifdef ZTS 34 | #include "TSRM.h" 35 | #endif 36 | 37 | PHP_MINIT_FUNCTION(sapnwrfc); 38 | PHP_MSHUTDOWN_FUNCTION(sapnwrfc); 39 | PHP_RINIT_FUNCTION(sapnwrfc); 40 | PHP_RSHUTDOWN_FUNCTION(sapnwrfc); 41 | PHP_MINFO_FUNCTION(sapnwrfc); 42 | 43 | PHP_FUNCTION(confirm_sapnwrfc_compiled); /* For testing, remove later. */ 44 | 45 | /* 46 | Declare any global variables you may need between the BEGIN 47 | and END macros here: 48 | 49 | ZEND_BEGIN_MODULE_GLOBALS(sapnwrfc) 50 | long global_value; 51 | char *global_string; 52 | ZEND_END_MODULE_GLOBALS(sapnwrfc) 53 | */ 54 | 55 | /* In every utility function you add that needs to use variables 56 | in php_sapnwrfc_globals, call TSRM_FETCH(); after declaring other 57 | variables used by that function, or better yet, pass in TSRMLS_CC 58 | after the last function argument and declare your utility function 59 | with TSRMLS_DC after the last declared argument. Always refer to 60 | the globals in your function as SAPNWRFC_G(variable). You are 61 | encouraged to rename these macros something shorter, see 62 | examples in any other php module directory. 63 | */ 64 | 65 | #ifdef ZTS 66 | #define SAPNWRFC_G(v) TSRMG(sapnwrfc_globals_id, zend_sapnwrfc_globals *, v) 67 | #else 68 | #define SAPNWRFC_G(v) (sapnwrfc_globals.v) 69 | #endif 70 | 71 | #endif /* PHP_SAPNWRFC_H */ 72 | 73 | 74 | /* 75 | * Local variables: 76 | * tab-width: 4 77 | * c-basic-offset: 4 78 | * End: 79 | * vim600: noet sw=4 ts=4 fdm=marker 80 | * vim<600: noet sw=4 ts=4 81 | */ 82 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | connection.config.php 2 | -------------------------------------------------------------------------------- /tests/Offline/FunctionsTest.php: -------------------------------------------------------------------------------- 1 | assertInternalType('string', sapnwrfc_version()); 12 | } 13 | 14 | public function testVersionArray() 15 | { 16 | $actual = sapnwrfc_version_array(); 17 | 18 | $this->assertInternalType('array', $actual); 19 | $this->assertArrayHasKey('major', $actual); 20 | $this->assertArrayHasKey('minor', $actual); 21 | $this->assertArrayHasKey('cvs', $actual); 22 | $this->assertArrayHasKey('ver', $actual); 23 | } 24 | 25 | public function testRfcVersion() 26 | { 27 | $this->assertInternalType('string', sapnwrfc_rfcversion()); 28 | } 29 | 30 | /** 31 | * Empty ini path 32 | * 33 | * @expectedException \Exception 34 | */ 35 | public function testIniPathException() 36 | { 37 | $actual = sapnwrfc_setinipath(); 38 | } 39 | 40 | /** 41 | * Empty ini path 42 | */ 43 | public function testIniPath() 44 | { 45 | $actual = sapnwrfc_setinipath('.tmp'); 46 | 47 | $this->assertTrue($actual); 48 | } 49 | 50 | public function testReloadInifile() 51 | { 52 | $actual = sapnwrfc_reloadinifile(); 53 | 54 | $this->assertTrue($actual); 55 | } 56 | 57 | /** 58 | * Missing parameter 59 | * 60 | * @expectedException \Exception 61 | */ 62 | public function testRemoveFunctionNoParameterException() 63 | { 64 | $actual = sapnwrfc_removefunction(''); 65 | } 66 | 67 | /** 68 | * Missing parameter 69 | * 70 | * @expectedException \Exception 71 | */ 72 | public function testRemoveFunctionOnlyOneParameterException() 73 | { 74 | $actual = sapnwrfc_removefunction(''); 75 | } 76 | 77 | /** 78 | * Missing parameter 79 | */ 80 | public function testRemoveFunction() 81 | { 82 | $actual = sapnwrfc_removefunction('', 'RFC_READ_REPORT'); 83 | 84 | $this->assertTrue($actual); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/Offline/SapNwRfcFunctionTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('sapnwrfc_function', $func); 15 | } 16 | 17 | /** 18 | * @expectedException \Exception 19 | * @expectedExceptionMessage sapnwrfc_function::invoke() expects exactly 1 parameter, 0 given 20 | */ 21 | public function testInvokeNoParameterException() 22 | { 23 | $func = new sapnwrfc_function(); 24 | 25 | $func->invoke(); 26 | } 27 | 28 | /** 29 | * @expectedException \Exception 30 | * @expectedExceptionMessage sapnwrfc_function::invoke() expects parameter 1 to be array, string given 31 | */ 32 | public function testInvokeWrongParameterTypeException() 33 | { 34 | $func = new sapnwrfc_function(); 35 | 36 | $func->invoke('something'); 37 | } 38 | 39 | /** 40 | * @expectedException \Exception 41 | * @expectedExceptionMessage sapnwrfc_function::activate() expects exactly 1 parameter, 0 given 42 | */ 43 | public function testActivateNoParameterException() 44 | { 45 | $func = new sapnwrfc_function(); 46 | 47 | $func->activate(); 48 | } 49 | 50 | /** 51 | * @expectedException \Exception 52 | * @expectedExceptionMessage sapnwrfc_function::activate() expects parameter 1 to be string, array given 53 | */ 54 | public function testActivateWrongParameterTypeException() 55 | { 56 | $func = new sapnwrfc_function(); 57 | 58 | $func->activate([]); 59 | } 60 | 61 | /** 62 | * @expectedException \Exception 63 | * @expectedExceptionMessage sapnwrfc_function::deactivate() expects exactly 1 parameter, 0 given 64 | */ 65 | public function testDeactivateNoParameterException() 66 | { 67 | $func = new sapnwrfc_function(); 68 | 69 | $func->deactivate(); 70 | } 71 | 72 | /** 73 | * @expectedException \Exception 74 | * @expectedExceptionMessage sapnwrfc_function::deactivate() expects parameter 1 to be string, array given 75 | */ 76 | public function testDeactivateWrongParameterTypeException() 77 | { 78 | $func = new sapnwrfc_function(); 79 | 80 | $func->deactivate([]); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tests/Offline/SapNwRfcTest.php: -------------------------------------------------------------------------------- 1 | 123 36 | ]); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Online/AbstractOnlineTestCase.php: -------------------------------------------------------------------------------- 1 | markTestSkipped('Configuration file for a SAP testsystem required "tests/connection.config.php"'); 15 | } 16 | 17 | $this->config = include 'tests/connection.config.php'; 18 | 19 | if (! is_array($this->config)) { 20 | throw new \Exception('config needs to be an array!'); 21 | } 22 | } 23 | 24 | protected function getConfig() 25 | { 26 | return $this->config; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Online/SapNwRfcFunctionTest.php: -------------------------------------------------------------------------------- 1 | conn = new sapnwrfc($this->getConfig()); 21 | } catch (\Exception $ex) { 22 | $this->markTestSkipped('Valid connection is required'); 23 | } 24 | } 25 | 26 | /** 27 | * 28 | * @return sapnwrfc 29 | */ 30 | protected function getConnection() 31 | { 32 | return $this->conn; 33 | } 34 | 35 | public function testInvoke() 36 | { 37 | $conn = $this->getConnection(); 38 | 39 | $func = $conn->function_lookup('RFC_PING'); 40 | 41 | $actual = $func->invoke([]); 42 | 43 | $this->assertInternalType('array', $actual); 44 | $this->assertCount(0, $actual); 45 | } 46 | 47 | /** 48 | * @expectedException \sapnwrfcCallException 49 | * @expectedExceptionCode 20 50 | * @expectedExceptionMessage field 'something' not found 51 | */ 52 | public function testInvokeUnknownParameterException() 53 | { 54 | $conn = $this->getConnection(); 55 | 56 | $func = $conn->function_lookup('RFC_PING'); 57 | 58 | $actual = $func->invoke([ 59 | 'something' => 123 60 | ]); 61 | } 62 | 63 | /** 64 | * @expectedException \sapnwrfcCallException 65 | * @expectedExceptionCode 20 66 | * @expectedExceptionMessage field 'asdf' not found 67 | */ 68 | public function testActivateUnknownParameterException() 69 | { 70 | $conn = $this->getConnection(); 71 | 72 | $func = $conn->function_lookup('RFC_PING'); 73 | 74 | $actual = $func->activate('asdf'); 75 | } 76 | 77 | /** 78 | * @expectedException \sapnwrfcCallException 79 | * @expectedExceptionCode 20 80 | * @expectedExceptionMessage field 'asdf2' not found 81 | */ 82 | public function testDeactivateUnknownParameterException() 83 | { 84 | $conn = $this->getConnection(); 85 | 86 | $func = $conn->function_lookup('RFC_PING'); 87 | 88 | $actual = $func->deactivate('asdf2'); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /tests/Online/SapNwRfcTest.php: -------------------------------------------------------------------------------- 1 | getConfig()); 16 | 17 | $this->assertInstanceOf('sapnwrfc', $conn); 18 | } 19 | 20 | /** 21 | * @expectedException \sapnwrfcConnectionException 22 | * @expectedExceptionCode 2 23 | * @expectedExceptionMessage Name or password is incorrect (repeat logon) 24 | */ 25 | public function testInvalidUsernameException() 26 | { 27 | $config = $this->getConfig(); 28 | if (! isset($config['user'])) { 29 | $this->markTestSkipped('Only available with "user" connection parameter'); 30 | } 31 | $config['user'] = 'bla'; 32 | 33 | $conn = new sapnwrfc($config); 34 | 35 | $this->assertInstanceOf('sapnwrfc', $conn); 36 | } 37 | 38 | /** 39 | * @expectedException \sapnwrfcConnectionException 40 | * @expectedExceptionCode 2 41 | * @expectedExceptionMessage Name or password is incorrect (repeat logon) 42 | */ 43 | public function testInvalidPasswordException() 44 | { 45 | $config = $this->getConfig(); 46 | if (! isset($config['passwd'])) { 47 | $this->markTestSkipped('Only available with "passwd" connection parameter'); 48 | } 49 | 50 | $config['passwd'] = 'bla'; 51 | 52 | $conn = new sapnwrfc($config); 53 | 54 | $this->assertInstanceOf('sapnwrfc', $conn); 55 | } 56 | 57 | /** 58 | * @expectedException \sapnwrfcConnectionException 59 | * @expectedExceptionCode 2 60 | * @expectedExceptionMessage Client bla is not available in this system 61 | */ 62 | public function testInvalidClientException() 63 | { 64 | $config = $this->getConfig(); 65 | if (! isset($config['CLIENT'])) { 66 | $this->markTestSkipped('Only available with "CLIENT" connection parameter'); 67 | } 68 | 69 | $config['CLIENT'] = 'bla'; 70 | 71 | $conn = new sapnwrfc($config); 72 | 73 | $this->assertInstanceOf('sapnwrfc', $conn); 74 | } 75 | 76 | /** 77 | * @expectedException \sapnwrfcConnectionException 78 | * @expectedExceptionCode 1 79 | */ 80 | public function testInvalidR3nameException() 81 | { 82 | $config = $this->getConfig(); 83 | if (! isset($config['R3NAME'])) { 84 | $this->markTestSkipped('Only available with "R3NAME" connection parameter'); 85 | } 86 | 87 | $config['R3NAME'] = 'bla'; 88 | 89 | try { 90 | $conn = new sapnwrfc($config); 91 | } catch (sapnwrfcConnectionException $ex) { 92 | $this->assertContains('ERROR', $ex->getMessage()); 93 | $this->assertContains('service \'?\' unknown', $ex->getMessage()); 94 | 95 | throw $ex; 96 | } 97 | } 98 | 99 | /** 100 | * @expectedException \sapnwrfcConnectionException 101 | * @expectedExceptionCode 1 102 | */ 103 | public function testInvalidGroupException() 104 | { 105 | $config = $this->getConfig(); 106 | if (! isset($config['GROUP'])) { 107 | $this->markTestSkipped('Only available with "GROUP" connection parameter'); 108 | } 109 | 110 | $config['GROUP'] = 'bla'; 111 | 112 | try { 113 | $conn = new sapnwrfc($config); 114 | } catch (sapnwrfcConnectionException $ex) { 115 | $this->assertContains('ERROR', $ex->getMessage()); 116 | $this->assertContains('Group bla not found', $ex->getMessage()); 117 | 118 | throw $ex; 119 | } 120 | } 121 | 122 | public function testConnectionAttributes() 123 | { 124 | $conn = new sapnwrfc($this->getConfig()); 125 | 126 | $actual = $conn->connection_attributes(); 127 | 128 | $this->assertInternalType('array', $actual); 129 | 130 | $this->assertArrayHasKey('dest', $actual); 131 | $this->assertArrayHasKey('host', $actual); 132 | $this->assertArrayHasKey('partnerHost', $actual); 133 | $this->assertArrayHasKey('sysNumber', $actual); 134 | $this->assertArrayHasKey('sysId', $actual); 135 | $this->assertArrayHasKey('client', $actual); 136 | $this->assertArrayHasKey('user', $actual); 137 | $this->assertArrayHasKey('language', $actual); 138 | $this->assertArrayHasKey('trace', $actual); 139 | $this->assertArrayHasKey('isoLanguage', $actual); 140 | $this->assertArrayHasKey('codepage', $actual); 141 | $this->assertArrayHasKey('partnerCodepage', $actual); 142 | $this->assertArrayHasKey('rfcRole', $actual); 143 | $this->assertArrayHasKey('type', $actual); 144 | $this->assertArrayHasKey('rel', $actual); 145 | $this->assertArrayHasKey('partnerType', $actual); 146 | $this->assertArrayHasKey('partnerRel', $actual); 147 | $this->assertArrayHasKey('kernelRel', $actual); 148 | $this->assertArrayHasKey('cpicConvId', $actual); 149 | $this->assertArrayHasKey('progName', $actual); 150 | } 151 | 152 | public function testClose() 153 | { 154 | $conn = new sapnwrfc($this->getConfig()); 155 | 156 | $actual = $conn->close(); 157 | 158 | $this->assertTrue($actual); 159 | } 160 | 161 | public function testPing() 162 | { 163 | $conn = new sapnwrfc($this->getConfig()); 164 | 165 | $actual = $conn->ping(); 166 | 167 | $this->assertTrue($actual); 168 | } 169 | 170 | /** 171 | * @expectedException \sapnwrfcConnectionException 172 | * @expectedExceptionCode 20 173 | * @expectedExceptionMessage Invalid parameter 'SAP_UC*' was passed to the API call 174 | */ 175 | public function testGetSsoTicketException() 176 | { 177 | $conn = new sapnwrfc($this->getConfig()); 178 | 179 | $actual = $conn->get_sso_ticket(); 180 | } 181 | 182 | public function testFunctionLookup() 183 | { 184 | $conn = new sapnwrfc($this->getConfig()); 185 | 186 | $actual = $conn->function_lookup('RFC_PING'); 187 | 188 | $this->assertInstanceOf('sapnwrfc_function', $actual); 189 | 190 | $this->assertEquals('RFC_PING', $actual->name); 191 | } 192 | 193 | /** 194 | * @expectedException \sapnwrfcConnectionException 195 | * @expectedExceptionCode 5 196 | * @expectedExceptionMessage ID:FL Type:E Number:046 RFC_NOT_EXISTENT 197 | */ 198 | public function testFunctionLookupNotAvailableException() 199 | { 200 | $conn = new sapnwrfc($this->getConfig()); 201 | 202 | $actual = $conn->function_lookup('RFC_NOT_EXISTENT'); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /tests/Z_old/ConnTest.php: -------------------------------------------------------------------------------- 1 | config = Spyc::YAMLLoad($SAP_CONFIG); 15 | echo "sapnwrfc version: ".sapnwrfc_version()."\n"; 16 | echo "nw rfc sdk version: ".sapnwrfc_rfcversion()."\n"; 17 | } 18 | 19 | public function testConnection() 20 | { 21 | try { 22 | $conn = new sapnwrfc($this->config); 23 | // we must have a valid connection 24 | $this->assertNotNull($conn); 25 | } catch (Exception $e) { 26 | echo "Exception message: ".$e->getMessage(); 27 | throw new Exception('Assertion failed.'); 28 | } 29 | } 30 | 31 | public function testConnectionAttr() 32 | { 33 | try { 34 | $conn = new sapnwrfc($this->config); 35 | // we must have a valid connection 36 | $this->assertNotNull($conn); 37 | $attr = $conn->connection_attributes(); 38 | $this->assertEquals($attr['partnerHost'], 'gecko'); 39 | } catch (Exception $e) { 40 | echo "Exception message: ".$e->getMessage(); 41 | throw new Exception('Connection failed.'); 42 | } 43 | } 44 | 45 | public function testConnectionAttrLots() 46 | { 47 | try { 48 | $conn = new sapnwrfc($this->config); 49 | // we must have a valid connection 50 | $this->assertNotNull($conn); 51 | for ($i=0; $i<100; $i++) { 52 | $attr = $conn->connection_attributes(); 53 | $this->assertEquals($attr['partnerHost'], 'gecko'); 54 | } 55 | } catch (Exception $e) { 56 | echo "Exception message: ".$e->getMessage(); 57 | throw new Exception('Connection failed.'); 58 | } 59 | } 60 | 61 | public function testConnectionAttrLots2() 62 | { 63 | try { 64 | for ($i=0; $i<100; $i++) { 65 | $conn = new sapnwrfc($this->config); 66 | // we must have a valid connection 67 | $this->assertNotNull($conn); 68 | $attr = $conn->connection_attributes(); 69 | $this->assertEquals($attr['partnerHost'], 'gecko'); 70 | $this->assertNotNull($conn->close()); 71 | } 72 | } catch (Exception $e) { 73 | echo "Exception message: ".$e->getMessage(); 74 | throw new Exception('Connection failed.'); 75 | } 76 | } 77 | 78 | public function testConnectionThrow() 79 | { 80 | try { 81 | $config = $this->config; 82 | $config['sysnr'] = sprintf('%02d', ((int) $config['sysnr']) + 1); 83 | $conn = new sapnwrfc($config); 84 | } catch (sapnwrfcConnectionException $e) { 85 | echo "Exception type: ".$e."\n"; 86 | echo "Exception key: ".$e->key."\n"; 87 | echo "Exception code: ".$e->code."\n"; 88 | echo "Exception message: ".$e->getMessage(); 89 | $this->assertTrue(true); 90 | } catch (Exception $e) { 91 | echo "Exception type: ".$e."\n"; 92 | echo "Exception key: ".$e->key."\n"; 93 | echo "Exception code: ".$e->code."\n"; 94 | echo "Exception message: ".$e->getMessage(); 95 | throw new Exception('Connection failed.'); 96 | } 97 | } 98 | 99 | public function testConnectionThrow2() 100 | { 101 | try { 102 | $conn = new sapnwrfc($this->config); 103 | $h = $conn->function_lookup('RFC_READ_TABLE'); 104 | $h->invoke(array('DOES_NOT_EXIST' => 1)); 105 | } catch (sapnwrfcCallException $e) { 106 | echo "Exception type: ".$e."\n"; 107 | echo "Exception key: ".$e->key."\n"; 108 | echo "Exception code: ".$e->code."\n"; 109 | echo "Exception message: ".$e->getMessage(); 110 | $this->assertTrue(true); 111 | } catch (Exception $e) { 112 | echo "Exception type: ".$e."\n"; 113 | echo "Exception key: ".$e->key."\n"; 114 | echo "Exception code: ".$e->code."\n"; 115 | echo "Exception message: ".$e->getMessage(); 116 | throw new Exception('Connection failed.'); 117 | } 118 | } 119 | 120 | public function testConnectionThrow3() 121 | { 122 | try { 123 | $conn = new sapnwrfc($this->config); 124 | $h = $conn->function_lookup('RFC_READ_TABLE'); 125 | $h->invoke(array('DATA' => array(array('NOT_THERE' => 1)))); 126 | } catch (sapnwrfcCallException $e) { 127 | echo "Exception type: ".$e."\n"; 128 | echo "Exception key: ".$e->key."\n"; 129 | echo "Exception code: ".$e->code."\n"; 130 | echo "Exception message: ".$e->getMessage(); 131 | $this->assertTrue(true); 132 | } catch (Exception $e) { 133 | echo "Exception type: ".$e."\n"; 134 | echo "Exception key: ".$e->key."\n"; 135 | echo "Exception code: ".$e->code."\n"; 136 | echo "Exception message: ".$e->getMessage(); 137 | throw new Exception('Connection failed.'); 138 | } 139 | } 140 | 141 | public function testConnectionCert() 142 | { 143 | try { 144 | $conn = new sapnwrfc($this->config); 145 | $ticket = $conn->get_sso_ticket(); 146 | echo "ticket: $ticket \n"; 147 | } catch (Exception $e) { 148 | echo "Exception type: ".$e."\n"; 149 | echo "Exception key: ".$e->key."\n"; 150 | echo "Exception code: ".$e->code."\n"; 151 | echo "Exception message: ".$e->getMessage(); 152 | throw new Exception('Connection failed.'); 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /tests/Z_old/FuncChangeTest.php: -------------------------------------------------------------------------------- 1 | config = Spyc::YAMLLoad($SAP_CONFIG); 15 | echo "sapnwrfc version: ".sapnwrfc_version()."\n"; 16 | echo "nw rfc sdk version: ".sapnwrfc_rfcversion()."\n"; 17 | } 18 | 19 | 20 | public static function str_hex($string) 21 | { 22 | $hex=''; 23 | for ($i=0; $i < strlen($string); $i++) { 24 | $hex .= dechex(ord($string[$i])); 25 | } 26 | return $hex; 27 | } 28 | 29 | 30 | public static function hex_str($hex) 31 | { 32 | $string=''; 33 | for ($i=0; $i < strlen($hex)-1; $i+=2) { 34 | $string .= chr(hexdec($hex[$i].$hex[$i+1])); 35 | } 36 | return $string; 37 | } 38 | 39 | public function testFuncDataCall1() 40 | { 41 | echo "testFuncDataCall1\n"; 42 | try { 43 | $conn = new sapnwrfc($this->config); 44 | $attr = $conn->connection_attributes(); 45 | var_dump($attr); 46 | // we must have a valid connection 47 | $this->assertNotNull($conn); 48 | $func = $conn->function_lookup("Z_TEST_DATA"); 49 | $this->assertEquals($func->name, "Z_TEST_DATA"); 50 | $parms = array( 51 | 'CHAR' => "German: öäüÖÄÜß", 52 | 'INT1' => 123, 53 | 'INT2' => 1234, 54 | 'INT4' => 123456, 55 | 'FLOAT' => 123456.00, 56 | 'NUMC' => "12345", 57 | 'DATE' => "20060709", 58 | 'TIME' => "200607", 59 | 'BCD' => '200607.123', 60 | 'ISTRUCT' => array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 61 | 'DATA' => array( 62 | array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 63 | array( 'ZCHAR' => "Slovenian: čćšČĆŠ", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 64 | ) 65 | ); 66 | $results = $func->invoke($parms); 67 | var_dump($results); 68 | $this->assertEquals(trim($results['ECHAR']), $parms['CHAR']); 69 | $this->assertEquals($results['EINT1'], $parms['INT1']); 70 | $this->assertEquals($results['EINT2'], $parms['INT2']); 71 | $this->assertEquals($results['EINT4'], $parms['INT4']); 72 | $this->assertEquals($results['EFLOAT'], $parms['FLOAT']); 73 | $this->assertEquals($results['ENUMC'], $parms['NUMC']); 74 | $this->assertEquals($results['EDATE'], $parms['DATE']); 75 | $this->assertEquals($results['ETIME'], $parms['TIME']); 76 | $this->assertEquals($results['EBCD'], $parms['BCD']); 77 | $this->assertEquals(chop($results['DATA'][0]['ZCHAR']), $parms['DATA'][0]['ZCHAR']); 78 | $this->assertEquals(chop($results['DATA'][1]['ZCHAR']), $parms['DATA'][1]['ZCHAR']); 79 | sleep(10); 80 | sapnwrfc_removefunction($attr['sysId'], 'Z_TEST_DATA'); 81 | $func = $conn->function_lookup("Z_TEST_DATA"); 82 | $parms = array( 83 | 'ICHAR' => "German: öäüÖÄÜß", 84 | 'INT1' => 123, 85 | 'INT2' => 1234, 86 | 'INT4' => 123456, 87 | 'FLOAT' => 123456.00, 88 | 'NUMC' => "12345", 89 | 'DATE' => "20060709", 90 | 'TIME' => "200607", 91 | 'BCD' => '200607.123', 92 | 'ISTRUCT' => array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 93 | 'DATA' => array( 94 | array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 95 | array( 'ZCHAR' => "Slovenian: čćšČĆŠ", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 96 | ) 97 | ); 98 | $results = $func->invoke($parms); 99 | var_dump($results); 100 | $this->assertEquals(trim($results['ECHAR']), $parms['CHAR']); 101 | $this->assertEquals($results['EINT1'], $parms['INT1']); 102 | $this->assertEquals($results['EINT2'], $parms['INT2']); 103 | $this->assertEquals($results['EINT4'], $parms['INT4']); 104 | $this->assertEquals($results['EFLOAT'], $parms['FLOAT']); 105 | $this->assertEquals($results['ENUMC'], $parms['NUMC']); 106 | $this->assertEquals($results['EDATE'], $parms['DATE']); 107 | $this->assertEquals($results['ETIME'], $parms['TIME']); 108 | $this->assertEquals($results['EBCD'], $parms['BCD']); 109 | $this->assertEquals(chop($results['DATA'][0]['ZCHAR']), $parms['DATA'][0]['ZCHAR']); 110 | $this->assertEquals(chop($results['DATA'][1]['ZCHAR']), $parms['DATA'][1]['ZCHAR']); 111 | $this->assertEquals($conn->close(), true); 112 | } catch (Exception $e) { 113 | echo "Exception message: ".$e->getMessage(); 114 | throw new Exception('Assertion failed.'); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /tests/Z_old/FuncDataTest.php: -------------------------------------------------------------------------------- 1 | config = Spyc::YAMLLoad($SAP_CONFIG); 15 | echo "sapnwrfc version: ".sapnwrfc_version()."\n"; 16 | echo "nw rfc sdk version: ".sapnwrfc_rfcversion()."\n"; 17 | } 18 | 19 | 20 | public static function str_hex($string) 21 | { 22 | $hex=''; 23 | for ($i=0; $i < strlen($string); $i++) { 24 | $hex .= dechex(ord($string[$i])); 25 | } 26 | return $hex; 27 | } 28 | 29 | 30 | public static function hex_str($hex) 31 | { 32 | $string=''; 33 | for ($i=0; $i < strlen($hex)-1; $i+=2) { 34 | $string .= chr(hexdec($hex[$i].$hex[$i+1])); 35 | } 36 | return $string; 37 | } 38 | 39 | public function testFuncDataCall1() 40 | { 41 | echo "testFuncDataCall1\n"; 42 | try { 43 | $conn = new sapnwrfc($this->config); 44 | // we must have a valid connection 45 | $this->assertNotNull($conn); 46 | $func = $conn->function_lookup("Z_TEST_DATA"); 47 | $this->assertEquals($func->name, "Z_TEST_DATA"); 48 | for ($i=0; $i<100; $i++) { 49 | $parms = array( 50 | 'CHAR' => "German: öäüÖÄÜß", 51 | 'INT1' => 123, 52 | 'INT2' => 1234, 53 | 'INT4' => 123456, 54 | 'FLOAT' => 123456.00, 55 | 'NUMC' => "12345", 56 | 'DATE' => "20060709", 57 | 'TIME' => "200607", 58 | 'BCD' => '200607.123', 59 | 'ISTRUCT' => array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 60 | 'DATA' => array( 61 | array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 62 | array( 'ZCHAR' => "Slovenian: čćšČĆŠ", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 63 | // array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 64 | // array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123'), 65 | // array( 'ZCHAR' => "German: öäüÖÄÜß", 'ZINT1' => 54, 'ZINT2' => 134, 'ZIT4' => 123456, 'ZFLT' => 123456.00, 'ZNUMC' => '12345', 'ZDATE' => '20060709', 'ZTIME' => '200607', 'ZBCD' => '200607.123') 66 | ) 67 | ); 68 | $results = $func->invoke($parms); 69 | // var_dump($results); 70 | // echo "ECHAR: ", $results['ECHAR']; 71 | $this->assertEquals(trim($results['ECHAR']), $parms['CHAR']); 72 | //echo "INT1: ", $results['EINT1']; 73 | $this->assertEquals($results['EINT1'], $parms['INT1']); 74 | //echo "INT2: ", $results['EINT2']; 75 | $this->assertEquals($results['EINT2'], $parms['INT2']); 76 | //echo "INT4: ", $results['EINT4']; 77 | $this->assertEquals($results['EINT4'], $parms['INT4']); 78 | //echo "FLOAT: ", $results['EFLOAT']; 79 | $this->assertEquals($results['EFLOAT'], $parms['FLOAT']); 80 | //echo "NUMC: ", $results['ENUMC']; 81 | $this->assertEquals($results['ENUMC'], $parms['NUMC']); 82 | //echo "DATE: ", $results['EDATE']; 83 | $this->assertEquals($results['EDATE'], $parms['DATE']); 84 | //echo "TIME: ", $results['ETIME']; 85 | $this->assertEquals($results['ETIME'], $parms['TIME']); 86 | //echo "BCD: ", $results['EBCD']; 87 | $this->assertEquals($results['EBCD'], $parms['BCD']); 88 | //echo "ESTRUCT: ", $results['ESTRUCT']; 89 | //echo "DATA: ", $results['DATA']; 90 | //echo "RESULTS: ", $results['RESULT']; 91 | //echo "['EXPORT_TABLE'][0]['ZCHAR']: '", $results['EXPORT_TABLE'][0]['ZCHAR'], "'\n"; 92 | //echo "['EXPORT_TABLE'][1]['ZCHAR']: '", $results['EXPORT_TABLE'][1]['ZCHAR'], "'\n"; 93 | $this->assertEquals(chop($results['DATA'][0]['ZCHAR']), $parms['DATA'][0]['ZCHAR']); 94 | $this->assertEquals(chop($results['DATA'][1]['ZCHAR']), $parms['DATA'][1]['ZCHAR']); 95 | } 96 | $this->assertEquals($conn->close(), true); 97 | } catch (Exception $e) { 98 | echo "Exception message: ".$e->getMessage(); 99 | throw new Exception('Assertion failed.'); 100 | } 101 | } 102 | 103 | public function testFuncChanging1() 104 | { 105 | echo "testFuncChanging1\n"; 106 | try { 107 | $conn = new sapnwrfc($this->config); 108 | // we must have a valid connection 109 | $this->assertNotNull($conn); 110 | $func = $conn->function_lookup("STFC_CHANGING"); 111 | $this->assertEquals($func->name, "STFC_CHANGING"); 112 | for ($i=0; $i<100; $i++) { 113 | $cnt = (int) $i; 114 | $parms = array('START_VALUE' => $cnt, 115 | 'COUNTER' => $cnt); 116 | // echo "start: $cnt count: $cnt \n"; 117 | $results = $func->invoke($parms); 118 | // var_dump($results); 119 | $this->assertEquals((int)$results['RESULT'], ($cnt + $cnt)); 120 | $this->assertEquals((int)$results['COUNTER'], ($cnt + 1)); 121 | } 122 | $this->assertEquals($conn->close(), true); 123 | } catch (Exception $e) { 124 | echo "Exception message: ".$e->getMessage(); 125 | throw new Exception('Assertion failed.'); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /tests/Z_old/FuncDescTest.php: -------------------------------------------------------------------------------- 1 | config = Spyc::YAMLLoad($SAP_CONFIG); 15 | echo "sapnwrfc version: ".sapnwrfc_version()."\n"; 16 | echo "nw rfc sdk version: ".sapnwrfc_rfcversion()."\n"; 17 | } 18 | 19 | public function testFuncDesc1() 20 | { 21 | try { 22 | $conn = new sapnwrfc($this->config); 23 | // we must have a valid connection 24 | $this->assertNotNull($conn); 25 | $func = $conn->function_lookup("RFC_READ_REPORT"); 26 | $this->assertEquals($func->name, "RFC_READ_REPORT"); 27 | $this->assertNotNull(sapnwrfc_removefunction("", "RFC_READ_REPORT")); 28 | $this->assertNotNull(sapnwrfc_removefunction("N4S", "RFC_READ_REPORT")); 29 | } catch (Exception $e) { 30 | echo "Exception message: ".$e->getMessage(); 31 | throw new Exception('Assertion failed.'); 32 | } 33 | } 34 | 35 | public function testFuncDesc2() 36 | { 37 | try { 38 | foreach (array("STFC_CHANGING", "STFC_XSTRING", "RFC_READ_TABLE", "RFC_READ_REPORT", "RPY_PROGRAM_READ", "RFC_PING", "RFC_SYSTEM_INFO") as $i) { 39 | $conn = new sapnwrfc($this->config); 40 | // we must have a valid connection 41 | $this->assertNotNull($conn); 42 | $func = $conn->function_lookup($i); 43 | $this->assertEquals($func->name, $i); 44 | } 45 | } catch (Exception $e) { 46 | echo "Exception message: ".$e->getMessage(); 47 | throw new Exception('Assertion failed.'); 48 | } 49 | } 50 | 51 | public function testFuncDesc3() 52 | { 53 | try { 54 | $conn = new sapnwrfc($this->config); 55 | // we must have a valid connection 56 | $this->assertNotNull($conn); 57 | foreach (array("STFC_CHANGING", "STFC_XSTRING", "RFC_READ_TABLE", "RFC_READ_REPORT", "RPY_PROGRAM_READ", "RFC_PING", "RFC_SYSTEM_INFO") as $f) { 58 | $func = $conn->function_lookup($f); 59 | $this->assertEquals($func->name, $f); 60 | } 61 | } catch (Exception $e) { 62 | echo "Exception message: ".$e->getMessage(); 63 | throw new Exception('Assertion failed.'); 64 | } 65 | } 66 | 67 | public function testFuncDesc4() 68 | { 69 | try { 70 | $conn = new sapnwrfc($this->config); 71 | // we must have a valid connection 72 | $this->assertNotNull($conn); 73 | for ($i=0; $i<100; $i++) { 74 | //echo "iter: $i\n"; 75 | foreach (array("STFC_CHANGING", "STFC_XSTRING", "RFC_READ_TABLE", "RFC_READ_REPORT", "RPY_PROGRAM_READ", "RFC_PING", "RFC_SYSTEM_INFO") as $f) { 76 | $func = $conn->function_lookup($f); 77 | $this->assertEquals($func->name, $f); 78 | } 79 | } 80 | } catch (Exception $e) { 81 | echo "Exception message: ".$e->getMessage(); 82 | throw new Exception('Assertion failed.'); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tests/Z_old/FuncTest.php: -------------------------------------------------------------------------------- 1 | config = Spyc::YAMLLoad($SAP_CONFIG); 15 | echo "sapnwrfc version: ".sapnwrfc_version()."\n"; 16 | echo "nw rfc sdk version: ".sapnwrfc_rfcversion()."\n"; 17 | } 18 | 19 | public function testFuncCall1() 20 | { 21 | try { 22 | $conn = new sapnwrfc($this->config); 23 | // we must have a valid connection 24 | $this->assertNotNull($conn); 25 | 26 | $func = $conn->function_lookup("RFC_READ_TABLE"); 27 | //var_dump($fd); 28 | $this->assertEquals($func->name, "RFC_READ_TABLE"); 29 | $parms = array('QUERY_TABLE' => "TRDIR", 30 | 'ROWCOUNT' => 50, 31 | 'OPTIONS' => array(array('TEXT' => "NAME LIKE 'RS%'"))); 32 | $results = $func->invoke($parms); 33 | //var_dump($results); 34 | $this->assertEquals(count($results['DATA']), 50); 35 | $this->assertEquals($conn->close(), true); 36 | } catch (Exception $e) { 37 | echo "Exception message: ".$e->getMessage(); 38 | throw new Exception('Assertion failed.'); 39 | } 40 | } 41 | 42 | 43 | public function testFuncCall2() 44 | { 45 | try { 46 | for ($i=0; $i<100; $i++) { 47 | //echo "iter: $i\n"; 48 | $conn = new sapnwrfc($this->config); 49 | // we must have a valid connection 50 | $this->assertNotNull($conn); 51 | $func = $conn->function_lookup("RFC_READ_TABLE"); 52 | $parms = array('QUERY_TABLE' => "TRDIR", 53 | 'ROWCOUNT' => 50, 54 | 'OPTIONS' => array(array('TEXT' => "NAME LIKE 'RS%'"))); 55 | $results = $func->invoke($parms); 56 | $this->assertEquals(count($results['DATA']), 50); 57 | $this->assertEquals($conn->close(), true); 58 | } 59 | } catch (Exception $e) { 60 | echo "Exception message: ".$e->getMessage(); 61 | throw new Exception('Assertion failed.'); 62 | } 63 | } 64 | 65 | 66 | public function testFuncCall3() 67 | { 68 | echo "testFuncCall3\n"; 69 | try { 70 | $conn = new sapnwrfc($this->config); 71 | // we must have a valid connection 72 | $this->assertNotNull($conn); 73 | for ($i=0; $i<100; $i++) { 74 | //echo "iter: $i\n"; 75 | $func = $conn->function_lookup("RFC_READ_TABLE"); 76 | $parms = array('QUERY_TABLE' => "TRDIR", 77 | 'ROWCOUNT' => 50, 78 | 'OPTIONS' => array(array('TEXT' => "NAME LIKE 'RS%'"))); 79 | $results = $func->invoke($parms); 80 | $this->assertEquals(count($results['DATA']), 50); 81 | } 82 | $this->assertEquals($conn->close(), true); 83 | } catch (Exception $e) { 84 | echo "Exception message: ".$e->getMessage(); 85 | throw new Exception('Assertion failed.'); 86 | } 87 | } 88 | 89 | 90 | public function testFuncCall4() 91 | { 92 | echo "testFuncCall4\n"; 93 | try { 94 | $conn = new sapnwrfc($this->config); 95 | // we must have a valid connection 96 | $this->assertNotNull($conn); 97 | $func = $conn->function_lookup("RFC_READ_TABLE"); 98 | for ($i=0; $i<100; $i++) { 99 | $parms = array('QUERY_TABLE' => "TRDIR", 100 | 'ROWCOUNT' => 50, 101 | 'OPTIONS' => array(array('TEXT' => "NAME LIKE 'RS%'"))); 102 | $results = $func->invoke($parms); 103 | $this->assertEquals(count($results['DATA']), 50); 104 | } 105 | $this->assertEquals($conn->close(), true); 106 | } catch (Exception $e) { 107 | echo "Exception message: ".$e->getMessage(); 108 | throw new Exception('Assertion failed.'); 109 | } 110 | } 111 | 112 | public static function str_hex($string) 113 | { 114 | $hex=''; 115 | for ($i=0; $i < strlen($string); $i++) { 116 | $hex .= dechex(ord($string[$i])); 117 | } 118 | return $hex; 119 | } 120 | 121 | 122 | public static function hex_str($hex) 123 | { 124 | $string=''; 125 | for ($i=0; $i < strlen($hex)-1; $i+=2) { 126 | $string .= chr(hexdec($hex[$i].$hex[$i+1])); 127 | } 128 | return $string; 129 | } 130 | 131 | public function testFuncDeepCall() 132 | { 133 | echo "testFuncDeepCall\n"; 134 | try { 135 | $conn = new sapnwrfc($this->config); 136 | // we must have a valid connection 137 | $this->assertNotNull($conn); 138 | $fds = $conn->function_lookup("STFC_DEEP_STRUCTURE"); 139 | $this->assertEquals($fds->name, "STFC_DEEP_STRUCTURE"); 140 | $fdt = $conn->function_lookup("STFC_DEEP_TABLE"); 141 | $this->assertEquals($fdt->name, "STFC_DEEP_TABLE"); 142 | for ($i=0; $i<100; $i++) { 143 | $parms = array('IMPORTSTRUCT' => array('I' => 123, 'C' => 'AbCdEf', 'STR' => 'The quick brown fox ...', 'XSTR' => FuncTest::str_hex("deadbeef"))); 144 | $results = $fds->invoke($parms); 145 | // var_dump($results); 146 | $echostruct = $results['ECHOSTRUCT']; 147 | // echo "I is ".$echostruct['I']."\n"; 148 | $this->assertEquals($echostruct['I'], 123); 149 | $this->assertEquals(trim($echostruct['C']), 'AbCdEf'); 150 | $this->assertEquals($echostruct['STR'], 'The quick brown fox ...'); 151 | $this->assertEquals(FuncTest::hex_str($echostruct['XSTR']), 'deadbeef'); 152 | $parms = array('IMPORT_TAB' => array(array('I' => 123, 'C' => 'AbCdEf', 'STR' => 'The quick brown fox ...', 'XSTR' => FuncTest::str_hex("deadbeef")))); 153 | $results = $fdt->invoke($parms); 154 | // var_dump($results); 155 | $import_tab = $results['EXPORT_TAB']; 156 | foreach ($import_tab as $r) { 157 | if (trim($r['C']) == 'Appended') { 158 | continue; 159 | } 160 | $this->assertEquals($r['I'], 123); 161 | $this->assertEquals(trim($r['C']), 'AbCdEf'); 162 | $this->assertEquals($r['STR'], 'The quick brown fox ...'); 163 | $this->assertEquals(FuncTest::hex_str($r['XSTR']), 'deadbeef'); 164 | } 165 | } 166 | $this->assertEquals($conn->close(), true); 167 | } catch (Exception $e) { 168 | echo "Exception message: ".$e->getMessage(); 169 | throw new Exception('Assertion failed.'); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /tests/Z_old/ReadTableTest.php: -------------------------------------------------------------------------------- 1 | config = Spyc::YAMLLoad($SAP_CONFIG); 15 | echo "sapnwrfc version: ".sapnwrfc_version()."\n"; 16 | echo "nw rfc sdk version: ".sapnwrfc_rfcversion()."\n"; 17 | } 18 | 19 | 20 | public function testReadTable() 21 | { 22 | try { 23 | $conn = new sapnwrfc($this->config); 24 | $h = $conn->function_lookup('RFC_GET_TABLE_ENTRIES'); 25 | $parms = array('BYPASS_BUFFER' => 'X', 26 | 'MAX_ENTRIES' => 1, 27 | 'TABLE_NAME' => 'T005ZR'); 28 | $h->invoke($parms); 29 | } catch (sapnwrfcCallException $e) { 30 | //echo "Exception type: ".$e."\n"; 31 | echo "Exception key: ".$e->key."\n"; 32 | echo "Exception code: ".$e->code."\n"; 33 | echo "Exception message: ".$e->getMessage()."\n"; 34 | $this->assertTrue(true); 35 | } catch (Exception $e) { 36 | echo "Exception type: ".$e."\n"; 37 | echo "Exception key: ".$e->key."\n"; 38 | echo "Exception code: ".$e->code."\n"; 39 | echo "Exception message: ".$e->getMessage()."\n"; 40 | throw new Exception('Connection failed.'); 41 | } 42 | echo "I am a happy piece of code that carried on....\n"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Z_old/SSOTest.php: -------------------------------------------------------------------------------- 1 | config = Spyc::YAMLLoad($SAP_CONFIG); 15 | echo "sapnwrfc version: ".sapnwrfc_version()."\n"; 16 | echo "nw rfc sdk version: ".sapnwrfc_rfcversion()."\n"; 17 | } 18 | 19 | public function testConnection() 20 | { 21 | try { 22 | $conn = new sapnwrfc($this->config); 23 | // we must have a valid connection 24 | $this->assertNotNull($conn); 25 | } catch (Exception $e) { 26 | echo "Exception message: ".$e->getMessage(); 27 | throw new Exception('Assertion failed.'); 28 | } 29 | } 30 | 31 | public function testConnectionSSO() 32 | { 33 | try { 34 | unset($this->config['user']); 35 | unset($this->config['passwd']); 36 | $this->config['x509cert'] = "MIIB0TCCAToCByAJAgYAGBYwDQYJKoZIhvcNAQEFBQAwLjELMAkGA1UEBhMCTloxETAPBgNVBAoTCEtFUklLRVJJMQwwCgYDVQQDEwNSRkMwHhcNMDkwMjA2MDAxODE2WhcNMzgwMTAxMDAwMDAxWjAuMQswCQYDVQQGEwJOWjERMA8GA1UEChMIS0VSSUtFUkkxDDAKBgNVBAMTA1JGQzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA/+55h8dAKzW9YNwV2Bv4sf1aLjOdyQNFLOXJneTrmT9ALbBh5QDnAH/A1YBwpMmlmmEzmrSSd3wpdqz8d82hWECPd1t3Co3EkSZVvBMWeTk6vvQSYnXYeMOZqDzl2YZ/mARLBrou/nKQJHEG+ImjlPo4VUltJULNv3C/9sBvBcsCAwEAATANBgkqhkiG9w0BAQUFAAOBgQD4WB1CEY9nCYTozVnVRH0+jIQA4tqLvLUq6X83boOrhPqTHYlpWMABe+azsf0UT22UsZLgJQzO+d+1pQE55ZfVr5kaJnc79riD7dvlUm8goeaFnFS65p6fjQ/DWHE+60+ET99ibKP7tOuIq757AV1YwB+AhwEmE6597ylDKLexfg"; 37 | $this->config['snc_mode'] = 1; 38 | $this->config['snc_qop'] = 3; 39 | $this->config['snc_myname'] = "p:CN=RFC, O=KERIKERI, C=NZ"; 40 | $this->config['snc_partnername'] = "p:CN=N4S, O=KERIKERI, C=NZ"; 41 | $this->config['snc_lib'] = "/home/piers/code/sec/libsapcrypto.so"; 42 | // var_dump($this->config); 43 | $conn = new sapnwrfc($this->config); 44 | // we must have a valid connection 45 | $this->assertNotNull($conn); 46 | $attr = $conn->connection_attributes(); 47 | $this->assertEquals($attr['partnerHost'], 'gecko'); 48 | $fd = $conn->function_lookup("SUSR_CHECK_LOGON_DATA"); 49 | //$res = $fd->invoke(array( 'AUTH_METHOD' => "E", 'AUTH_DATA' => "p:ompka\\piers", 'EXTID_TYPE' => "NT")); 50 | $res = $fd->invoke(array( 'AUTH_METHOD' => "E", 'AUTH_DATA' => "SME\\PIERS", 'EXTID_TYPE' => "NT")); 51 | var_dump($res); 52 | $ticket = $res['TICKET']; 53 | unset($this->config['x509cert']); 54 | unset($this->config['snc_mode']); 55 | unset($this->config['snc_qop']); 56 | unset($this->config['snc_myname']); 57 | unset($this->config['snc_partnername']); 58 | unset($this->config['snc_lib']); 59 | $this->config['mysapsso2'] = $ticket; 60 | //var_dump($this->config); 61 | $conn2 = new sapnwrfc($this->config); 62 | } catch (sapnwrfcConnectionException $e) { 63 | echo "Exception type: ".$e."\n"; 64 | echo "Exception key: ".$e->key."\n"; 65 | echo "Exception code: ".$e->code."\n"; 66 | echo "Exception message: ".$e->getMessage(); 67 | $this->assertTrue(true); 68 | } catch (Exception $e) { 69 | echo "Exception type: ".$e."\n"; 70 | echo "Exception key: ".$e->key."\n"; 71 | echo "Exception code: ".$e->code."\n"; 72 | echo "Exception message: ".$e->getMessage(); 73 | throw new Exception('Connection failed.'); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/Z_old/sap.yml: -------------------------------------------------------------------------------- 1 | ashost: nplhost 2 | sysnr: "42" 3 | client: "001" 4 | user: developer 5 | passwd: developer 6 | lang: EN 7 | trace: 1 8 | loglevel: warn -------------------------------------------------------------------------------- /tests/Z_old/sap_config.php: -------------------------------------------------------------------------------- 1 | 6 | * @author Chris Wanstrath 7 | * @link http://code.google.com/p/spyc/ 8 | * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2009 Vlad Andersen 9 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 10 | * @package Spyc 11 | */ 12 | 13 | if (!function_exists('spyc_load')) { 14 | /** 15 | * Parses YAML to array. 16 | * @param string $string YAML string. 17 | * @return array 18 | */ 19 | function spyc_load($string) 20 | { 21 | return Spyc::YAMLLoadString($string); 22 | } 23 | } 24 | 25 | if (!function_exists('spyc_load_file')) { 26 | /** 27 | * Parses YAML to array. 28 | * @param string $file Path to YAML file. 29 | * @return array 30 | */ 31 | function spyc_load_file($file) 32 | { 33 | return Spyc::YAMLLoad($file); 34 | } 35 | } 36 | 37 | /** 38 | * The Simple PHP YAML Class. 39 | * 40 | * This class can be used to read a YAML file and convert its contents 41 | * into a PHP array. It currently supports a very limited subsection of 42 | * the YAML spec. 43 | * 44 | * Usage: 45 | * 46 | * $Spyc = new Spyc; 47 | * $array = $Spyc->load($file); 48 | * 49 | * or: 50 | * 51 | * $array = Spyc::YAMLLoad($file); 52 | * 53 | * or: 54 | * 55 | * $array = spyc_load_file($file); 56 | * 57 | * @package Spyc 58 | */ 59 | class spyc 60 | { 61 | 62 | // SETTINGS 63 | 64 | /** 65 | * Setting this to true will force YAMLDump to enclose any string value in 66 | * quotes. False by default. 67 | * 68 | * @var bool 69 | */ 70 | public $setting_dump_force_quotes = false; 71 | 72 | /** 73 | * Setting this to true will forse YAMLLoad to use syck_load function when 74 | * possible. False by default. 75 | * @var bool 76 | */ 77 | public $setting_use_syck_is_possible = false; 78 | 79 | 80 | 81 | /**#@+ 82 | * @access private 83 | * @var mixed 84 | */ 85 | private $_dumpIndent; 86 | private $_dumpWordWrap; 87 | private $_containsGroupAnchor = false; 88 | private $_containsGroupAlias = false; 89 | private $path; 90 | private $result; 91 | private $LiteralPlaceHolder = '___YAML_Literal_Block___'; 92 | private $SavedGroups = array(); 93 | private $indent; 94 | /** 95 | * Path modifier that should be applied after adding current element. 96 | * @var array 97 | */ 98 | private $delayedPath = array(); 99 | 100 | /**#@+ 101 | * @access public 102 | * @var mixed 103 | */ 104 | public $_nodeId; 105 | 106 | /** 107 | * Load a valid YAML string to Spyc. 108 | * @param string $input 109 | * @return array 110 | */ 111 | public function load($input) 112 | { 113 | return $this->__loadString($input); 114 | } 115 | 116 | /** 117 | * Load a valid YAML file to Spyc. 118 | * @param string $file 119 | * @return array 120 | */ 121 | public function loadFile($file) 122 | { 123 | return $this->__load($file); 124 | } 125 | 126 | /** 127 | * Load YAML into a PHP array statically 128 | * 129 | * The load method, when supplied with a YAML stream (string or file), 130 | * will do its best to convert YAML in a file into a PHP array. Pretty 131 | * simple. 132 | * Usage: 133 | * 134 | * $array = Spyc::YAMLLoad('lucky.yaml'); 135 | * print_r($array); 136 | * 137 | * @access public 138 | * @return array 139 | * @param string $input Path of YAML file or string containing YAML 140 | */ 141 | public static function YAMLLoad($input) 142 | { 143 | $Spyc = new Spyc; 144 | return $Spyc->__load($input); 145 | } 146 | 147 | /** 148 | * Load a string of YAML into a PHP array statically 149 | * 150 | * The load method, when supplied with a YAML string, will do its best 151 | * to convert YAML in a string into a PHP array. Pretty simple. 152 | * 153 | * Note: use this function if you don't want files from the file system 154 | * loaded and processed as YAML. This is of interest to people concerned 155 | * about security whose input is from a string. 156 | * 157 | * Usage: 158 | * 159 | * $array = Spyc::YAMLLoadString("---\n0: hello world\n"); 160 | * print_r($array); 161 | * 162 | * @access public 163 | * @return array 164 | * @param string $input String containing YAML 165 | */ 166 | public static function YAMLLoadString($input) 167 | { 168 | $Spyc = new Spyc; 169 | return $Spyc->__loadString($input); 170 | } 171 | 172 | /** 173 | * Dump YAML from PHP array statically 174 | * 175 | * The dump method, when supplied with an array, will do its best 176 | * to convert the array into friendly YAML. Pretty simple. Feel free to 177 | * save the returned string as nothing.yaml and pass it around. 178 | * 179 | * Oh, and you can decide how big the indent is and what the wordwrap 180 | * for folding is. Pretty cool -- just pass in 'false' for either if 181 | * you want to use the default. 182 | * 183 | * Indent's default is 2 spaces, wordwrap's default is 40 characters. And 184 | * you can turn off wordwrap by passing in 0. 185 | * 186 | * @access public 187 | * @return string 188 | * @param array $array PHP array 189 | * @param int $indent Pass in false to use the default, which is 2 190 | * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) 191 | */ 192 | public static function YAMLDump($array, $indent = false, $wordwrap = false) 193 | { 194 | $spyc = new Spyc; 195 | return $spyc->dump($array, $indent, $wordwrap); 196 | } 197 | 198 | 199 | /** 200 | * Dump PHP array to YAML 201 | * 202 | * The dump method, when supplied with an array, will do its best 203 | * to convert the array into friendly YAML. Pretty simple. Feel free to 204 | * save the returned string as tasteful.yaml and pass it around. 205 | * 206 | * Oh, and you can decide how big the indent is and what the wordwrap 207 | * for folding is. Pretty cool -- just pass in 'false' for either if 208 | * you want to use the default. 209 | * 210 | * Indent's default is 2 spaces, wordwrap's default is 40 characters. And 211 | * you can turn off wordwrap by passing in 0. 212 | * 213 | * @access public 214 | * @return string 215 | * @param array $array PHP array 216 | * @param int $indent Pass in false to use the default, which is 2 217 | * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) 218 | */ 219 | public function dump($array, $indent = false, $wordwrap = false) 220 | { 221 | // Dumps to some very clean YAML. We'll have to add some more features 222 | // and options soon. And better support for folding. 223 | 224 | // New features and options. 225 | if ($indent === false or !is_numeric($indent)) { 226 | $this->_dumpIndent = 2; 227 | } else { 228 | $this->_dumpIndent = $indent; 229 | } 230 | 231 | if ($wordwrap === false or !is_numeric($wordwrap)) { 232 | $this->_dumpWordWrap = 40; 233 | } else { 234 | $this->_dumpWordWrap = $wordwrap; 235 | } 236 | 237 | // New YAML document 238 | $string = "---\n"; 239 | 240 | // Start at the base of the array and move through it. 241 | if ($array) { 242 | $array = (array)$array; 243 | $first_key = key($array); 244 | 245 | $previous_key = -1; 246 | foreach ($array as $key => $value) { 247 | $string .= $this->_yamlize($key, $value, 0, $previous_key, $first_key); 248 | $previous_key = $key; 249 | } 250 | } 251 | return $string; 252 | } 253 | 254 | /** 255 | * Attempts to convert a key / value array item to YAML 256 | * @access private 257 | * @return string 258 | * @param $key The name of the key 259 | * @param $value The value of the item 260 | * @param $indent The indent of the current node 261 | */ 262 | private function _yamlize($key, $value, $indent, $previous_key = -1, $first_key = 0) 263 | { 264 | if (is_array($value)) { 265 | if (empty($value)) { 266 | return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key); 267 | } 268 | // It has children. What to do? 269 | // Make it the right kind of item 270 | $string = $this->_dumpNode($key, null, $indent, $previous_key, $first_key); 271 | // Add the indent 272 | $indent += $this->_dumpIndent; 273 | // Yamlize the array 274 | $string .= $this->_yamlizeArray($value, $indent); 275 | } elseif (!is_array($value)) { 276 | // It doesn't have children. Yip. 277 | $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key); 278 | } 279 | return $string; 280 | } 281 | 282 | /** 283 | * Attempts to convert an array to YAML 284 | * @access private 285 | * @return string 286 | * @param $array The array you want to convert 287 | * @param $indent The indent of the current level 288 | */ 289 | private function _yamlizeArray($array, $indent) 290 | { 291 | if (is_array($array)) { 292 | $string = ''; 293 | $previous_key = -1; 294 | $first_key = key($array); 295 | foreach ($array as $key => $value) { 296 | $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key); 297 | $previous_key = $key; 298 | } 299 | return $string; 300 | } else { 301 | return false; 302 | } 303 | } 304 | 305 | /** 306 | * Returns YAML from a key and a value 307 | * @access private 308 | * @return string 309 | * @param $key The name of the key 310 | * @param $value The value of the item 311 | * @param $indent The indent of the current node 312 | */ 313 | private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0) 314 | { 315 | // do some folding here, for blocks 316 | if (is_string($value) && ((strpos($value, "\n") !== false || strpos($value, ": ") !== false || strpos($value, "- ") !== false || 317 | strpos($value, "*") !== false || strpos($value, "#") !== false || strpos($value, "<") !== false || strpos($value, ">") !== false || 318 | strpos($value, "[") !== false || strpos($value, "]") !== false || strpos($value, "{") !== false || strpos($value, "}") !== false) || substr($value, -1, 1) == ':')) { 319 | $value = $this->_doLiteralBlock($value, $indent); 320 | } else { 321 | $value = $this->_doFolding($value, $indent); 322 | if (is_bool($value)) { 323 | $value = ($value) ? "true" : "false"; 324 | } 325 | } 326 | 327 | if ($value === array()) { 328 | $value = '[ ]'; 329 | } 330 | 331 | $spaces = str_repeat(' ', $indent); 332 | 333 | if (is_int($key) && $key - 1 == $previous_key && $first_key===0) { 334 | // It's a sequence 335 | $string = $spaces.'- '.$value."\n"; 336 | } else { 337 | if ($first_key===0) { 338 | throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"'); 339 | } 340 | // It's mapped 341 | if (strpos($key, ":") !== false) { 342 | $key = '"' . $key . '"'; 343 | } 344 | $string = $spaces.$key.': '.$value."\n"; 345 | } 346 | return $string; 347 | } 348 | 349 | /** 350 | * Creates a literal block for dumping 351 | * @access private 352 | * @return string 353 | * @param $value 354 | * @param $indent int The value of the indent 355 | */ 356 | private function _doLiteralBlock($value, $indent) 357 | { 358 | if (strpos($value, "\n") === false && strpos($value, "'") === false) { 359 | return sprintf("'%s'", $value); 360 | } 361 | if (strpos($value, "\n") === false && strpos($value, '"') === false) { 362 | return sprintf('"%s"', $value); 363 | } 364 | $exploded = explode("\n", $value); 365 | $newValue = '|'; 366 | $indent += $this->_dumpIndent; 367 | $spaces = str_repeat(' ', $indent); 368 | foreach ($exploded as $line) { 369 | $newValue .= "\n" . $spaces . trim($line); 370 | } 371 | return $newValue; 372 | } 373 | 374 | /** 375 | * Folds a string of text, if necessary 376 | * @access private 377 | * @return string 378 | * @param $value The string you wish to fold 379 | */ 380 | private function _doFolding($value, $indent) 381 | { 382 | // Don't do anything if wordwrap is set to 0 383 | 384 | if ($this->_dumpWordWrap !== 0 && is_string($value) && strlen($value) > $this->_dumpWordWrap) { 385 | $indent += $this->_dumpIndent; 386 | $indent = str_repeat(' ', $indent); 387 | $wrapped = wordwrap($value, $this->_dumpWordWrap, "\n$indent"); 388 | $value = ">\n".$indent.$wrapped; 389 | } else { 390 | if ($this->setting_dump_force_quotes && is_string($value)) { 391 | $value = '"' . $value . '"'; 392 | } 393 | } 394 | 395 | 396 | return $value; 397 | } 398 | 399 | // LOADING FUNCTIONS 400 | 401 | private function __load($input) 402 | { 403 | $Source = $this->loadFromSource($input); 404 | return $this->loadWithSource($Source); 405 | } 406 | 407 | private function __loadString($input) 408 | { 409 | $Source = $this->loadFromString($input); 410 | return $this->loadWithSource($Source); 411 | } 412 | 413 | private function loadWithSource($Source) 414 | { 415 | if (empty($Source)) { 416 | return array(); 417 | } 418 | if ($this->setting_use_syck_is_possible && function_exists('syck_load')) { 419 | $array = syck_load(implode('', $Source)); 420 | return is_array($array) ? $array : array(); 421 | } 422 | 423 | $this->path = array(); 424 | $this->result = array(); 425 | 426 | $cnt = count($Source); 427 | for ($i = 0; $i < $cnt; $i++) { 428 | $line = $Source[$i]; 429 | 430 | $this->indent = strlen($line) - strlen(ltrim($line)); 431 | $tempPath = $this->getParentPathByIndent($this->indent); 432 | $line = self::stripIndent($line, $this->indent); 433 | if (self::isComment($line)) { 434 | continue; 435 | } 436 | if (self::isEmpty($line)) { 437 | continue; 438 | } 439 | $this->path = $tempPath; 440 | 441 | $literalBlockStyle = self::startsLiteralBlock($line); 442 | if ($literalBlockStyle) { 443 | $line = rtrim($line, $literalBlockStyle . " \n"); 444 | $literalBlock = ''; 445 | $line .= $this->LiteralPlaceHolder; 446 | 447 | while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) { 448 | $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle); 449 | } 450 | $i--; 451 | } 452 | 453 | while (++$i < $cnt && self::greedilyNeedNextLine($line)) { 454 | $line = rtrim($line, " \n\t\r") . ' ' . ltrim($Source[$i], " \t"); 455 | } 456 | $i--; 457 | 458 | 459 | 460 | if (strpos($line, '#')) { 461 | if (strpos($line, '"') === false && strpos($line, "'") === false) { 462 | $line = preg_replace('/\s+#(.+)$/', '', $line); 463 | } 464 | } 465 | 466 | $lineArray = $this->_parseLine($line); 467 | 468 | if ($literalBlockStyle) { 469 | $lineArray = $this->revertLiteralPlaceHolder($lineArray, $literalBlock); 470 | } 471 | 472 | $this->addArray($lineArray, $this->indent); 473 | 474 | foreach ($this->delayedPath as $indent => $delayedPath) { 475 | $this->path[$indent] = $delayedPath; 476 | } 477 | 478 | $this->delayedPath = array(); 479 | } 480 | return $this->result; 481 | } 482 | 483 | private function loadFromSource($input) 484 | { 485 | if (!empty($input) && strpos($input, "\n") === false && file_exists($input)) { 486 | return file($input); 487 | } 488 | 489 | return $this->loadFromString($input); 490 | } 491 | 492 | private function loadFromString($input) 493 | { 494 | $lines = explode("\n", $input); 495 | foreach ($lines as $k => $_) { 496 | $lines[$k] = rtrim($_, "\r"); 497 | } 498 | return $lines; 499 | } 500 | 501 | /** 502 | * Parses YAML code and returns an array for a node 503 | * @access private 504 | * @return array 505 | * @param string $line A line from the YAML file 506 | */ 507 | private function _parseLine($line) 508 | { 509 | if (!$line) { 510 | return array(); 511 | } 512 | $line = trim($line); 513 | 514 | if (!$line) { 515 | return array(); 516 | } 517 | $array = array(); 518 | 519 | $group = $this->nodeContainsGroup($line); 520 | if ($group) { 521 | $this->addGroup($line, $group); 522 | $line = $this->stripGroup($line, $group); 523 | } 524 | 525 | if ($this->startsMappedSequence($line)) { 526 | return $this->returnMappedSequence($line); 527 | } 528 | 529 | if ($this->startsMappedValue($line)) { 530 | return $this->returnMappedValue($line); 531 | } 532 | 533 | if ($this->isArrayElement($line)) { 534 | return $this->returnArrayElement($line); 535 | } 536 | 537 | if ($this->isPlainArray($line)) { 538 | return $this->returnPlainArray($line); 539 | } 540 | 541 | 542 | return $this->returnKeyValuePair($line); 543 | } 544 | 545 | /** 546 | * Finds the type of the passed value, returns the value as the new type. 547 | * @access private 548 | * @param string $value 549 | * @return mixed 550 | */ 551 | private function _toType($value) 552 | { 553 | if ($value === '') { 554 | return null; 555 | } 556 | $first_character = $value[0]; 557 | $last_character = substr($value, -1, 1); 558 | 559 | $is_quoted = false; 560 | do { 561 | if (!$value) { 562 | break; 563 | } 564 | if ($first_character != '"' && $first_character != "'") { 565 | break; 566 | } 567 | if ($last_character != '"' && $last_character != "'") { 568 | break; 569 | } 570 | $is_quoted = true; 571 | } while (0); 572 | 573 | if ($is_quoted) { 574 | return strtr(substr($value, 1, -1), array('\\"' => '"', '\'\'' => '\'', '\\\'' => '\'')); 575 | } 576 | 577 | if (strpos($value, ' #') !== false) { 578 | $value = preg_replace('/\s+#(.+)$/', '', $value); 579 | } 580 | 581 | if ($first_character == '[' && $last_character == ']') { 582 | // Take out strings sequences and mappings 583 | $innerValue = trim(substr($value, 1, -1)); 584 | if ($innerValue === '') { 585 | return array(); 586 | } 587 | $explode = $this->_inlineEscape($innerValue); 588 | // Propagate value array 589 | $value = array(); 590 | foreach ($explode as $v) { 591 | $value[] = $this->_toType($v); 592 | } 593 | return $value; 594 | } 595 | 596 | if (strpos($value, ': ')!==false && $first_character != '{') { 597 | $array = explode(': ', $value); 598 | $key = trim($array[0]); 599 | array_shift($array); 600 | $value = trim(implode(': ', $array)); 601 | $value = $this->_toType($value); 602 | return array($key => $value); 603 | } 604 | 605 | if ($first_character == '{' && $last_character == '}') { 606 | $innerValue = trim(substr($value, 1, -1)); 607 | if ($innerValue === '') { 608 | return array(); 609 | } 610 | // Inline Mapping 611 | // Take out strings sequences and mappings 612 | $explode = $this->_inlineEscape($innerValue); 613 | // Propagate value array 614 | $array = array(); 615 | foreach ($explode as $v) { 616 | $SubArr = $this->_toType($v); 617 | if (empty($SubArr)) { 618 | continue; 619 | } 620 | if (is_array($SubArr)) { 621 | $array[key($SubArr)] = $SubArr[key($SubArr)]; 622 | continue; 623 | } 624 | $array[] = $SubArr; 625 | } 626 | return $array; 627 | } 628 | 629 | if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') { 630 | return null; 631 | } 632 | 633 | if (intval($first_character) > 0 && preg_match('/^[1-9]+[0-9]*$/', $value)) { 634 | $intvalue = (int)$value; 635 | if ($intvalue != PHP_INT_MAX) { 636 | $value = $intvalue; 637 | } 638 | return $value; 639 | } 640 | 641 | if (in_array($value, 642 | array('true', 'on', '+', 'yes', 'y', 'True', 'TRUE', 'On', 'ON', 'YES', 'Yes', 'Y'))) { 643 | return true; 644 | } 645 | 646 | if (in_array(strtolower($value), 647 | array('false', 'off', '-', 'no', 'n'))) { 648 | return false; 649 | } 650 | 651 | if (is_numeric($value)) { 652 | if ($value === '0') { 653 | return 0; 654 | } 655 | if (trim($value, 0) === $value) { 656 | $value = (float)$value; 657 | } 658 | return $value; 659 | } 660 | 661 | return $value; 662 | } 663 | 664 | /** 665 | * Used in inlines to check for more inlines or quoted strings 666 | * @access private 667 | * @return array 668 | */ 669 | private function _inlineEscape($inline) 670 | { 671 | // There's gotta be a cleaner way to do this... 672 | // While pure sequences seem to be nesting just fine, 673 | // pure mappings and mappings with sequences inside can't go very 674 | // deep. This needs to be fixed. 675 | 676 | $seqs = array(); 677 | $maps = array(); 678 | $saved_strings = array(); 679 | 680 | // Check for strings 681 | $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; 682 | if (preg_match_all($regex, $inline, $strings)) { 683 | $saved_strings = $strings[0]; 684 | $inline = preg_replace($regex, 'YAMLString', $inline); 685 | } 686 | unset($regex); 687 | 688 | $i = 0; 689 | do { 690 | 691 | // Check for sequences 692 | while (preg_match('/\[([^{}\[\]]+)\]/U', $inline, $matchseqs)) { 693 | $seqs[] = $matchseqs[0]; 694 | $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1); 695 | } 696 | 697 | // Check for mappings 698 | while (preg_match('/{([^\[\]{}]+)}/U', $inline, $matchmaps)) { 699 | $maps[] = $matchmaps[0]; 700 | $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1); 701 | } 702 | 703 | if ($i++ >= 10) { 704 | break; 705 | } 706 | } while (strpos($inline, '[') !== false || strpos($inline, '{') !== false); 707 | 708 | $explode = explode(', ', $inline); 709 | $stringi = 0; 710 | $i = 0; 711 | 712 | while (1) { 713 | 714 | // Re-add the sequences 715 | if (!empty($seqs)) { 716 | foreach ($explode as $key => $value) { 717 | if (strpos($value, 'YAMLSeq') !== false) { 718 | foreach ($seqs as $seqk => $seq) { 719 | $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'), $seq, $value); 720 | $value = $explode[$key]; 721 | } 722 | } 723 | } 724 | } 725 | 726 | // Re-add the mappings 727 | if (!empty($maps)) { 728 | foreach ($explode as $key => $value) { 729 | if (strpos($value, 'YAMLMap') !== false) { 730 | foreach ($maps as $mapk => $map) { 731 | $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value); 732 | $value = $explode[$key]; 733 | } 734 | } 735 | } 736 | } 737 | 738 | 739 | // Re-add the strings 740 | if (!empty($saved_strings)) { 741 | foreach ($explode as $key => $value) { 742 | while (strpos($value, 'YAMLString') !== false) { 743 | $explode[$key] = preg_replace('/YAMLString/', $saved_strings[$stringi], $value, 1); 744 | unset($saved_strings[$stringi]); 745 | ++$stringi; 746 | $value = $explode[$key]; 747 | } 748 | } 749 | } 750 | 751 | $finished = true; 752 | foreach ($explode as $key => $value) { 753 | if (strpos($value, 'YAMLSeq') !== false) { 754 | $finished = false; 755 | break; 756 | } 757 | if (strpos($value, 'YAMLMap') !== false) { 758 | $finished = false; 759 | break; 760 | } 761 | if (strpos($value, 'YAMLString') !== false) { 762 | $finished = false; 763 | break; 764 | } 765 | } 766 | if ($finished) { 767 | break; 768 | } 769 | 770 | $i++; 771 | if ($i > 10) { 772 | break; 773 | } // Prevent infinite loops. 774 | } 775 | 776 | return $explode; 777 | } 778 | 779 | private function literalBlockContinues($line, $lineIndent) 780 | { 781 | if (!trim($line)) { 782 | return true; 783 | } 784 | if (strlen($line) - strlen(ltrim($line)) > $lineIndent) { 785 | return true; 786 | } 787 | return false; 788 | } 789 | 790 | private function referenceContentsByAlias($alias) 791 | { 792 | do { 793 | if (!isset($this->SavedGroups[$alias])) { 794 | echo "Bad group name: $alias."; 795 | break; 796 | } 797 | $groupPath = $this->SavedGroups[$alias]; 798 | $value = $this->result; 799 | foreach ($groupPath as $k) { 800 | $value = $value[$k]; 801 | } 802 | } while (false); 803 | return $value; 804 | } 805 | 806 | private function addArrayInline($array, $indent) 807 | { 808 | $CommonGroupPath = $this->path; 809 | if (empty($array)) { 810 | return false; 811 | } 812 | 813 | foreach ($array as $k => $_) { 814 | $this->addArray(array($k => $_), $indent); 815 | $this->path = $CommonGroupPath; 816 | } 817 | return true; 818 | } 819 | 820 | private function addArray($incoming_data, $incoming_indent) 821 | { 822 | 823 | // print_r ($incoming_data); 824 | 825 | if (count($incoming_data) > 1) { 826 | return $this->addArrayInline($incoming_data, $incoming_indent); 827 | } 828 | 829 | $key = key($incoming_data); 830 | $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null; 831 | if ($key === '__!YAMLZero') { 832 | $key = '0'; 833 | } 834 | 835 | if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values. 836 | if ($key || $key === '' || $key === '0') { 837 | $this->result[$key] = $value; 838 | } else { 839 | $this->result[] = $value; 840 | end($this->result); 841 | $key = key($this->result); 842 | } 843 | $this->path[$incoming_indent] = $key; 844 | return; 845 | } 846 | 847 | 848 | 849 | $history = array(); 850 | // Unfolding inner array tree. 851 | $history[] = $_arr = $this->result; 852 | foreach ($this->path as $k) { 853 | $history[] = $_arr = $_arr[$k]; 854 | } 855 | 856 | if ($this->_containsGroupAlias) { 857 | $value = $this->referenceContentsByAlias($this->_containsGroupAlias); 858 | $this->_containsGroupAlias = false; 859 | } 860 | 861 | 862 | // Adding string or numeric key to the innermost level or $this->arr. 863 | if (is_string($key) && $key == '<<') { 864 | if (!is_array($_arr)) { 865 | $_arr = array(); 866 | } 867 | 868 | $_arr = array_merge($_arr, $value); 869 | } elseif ($key || $key === '' || $key === '0') { 870 | $_arr[$key] = $value; 871 | } else { 872 | if (!is_array($_arr)) { 873 | $_arr = array($value); 874 | $key = 0; 875 | } else { 876 | $_arr[] = $value; 877 | end($_arr); 878 | $key = key($_arr); 879 | } 880 | } 881 | 882 | $reverse_path = array_reverse($this->path); 883 | $reverse_history = array_reverse($history); 884 | $reverse_history[0] = $_arr; 885 | $cnt = count($reverse_history) - 1; 886 | for ($i = 0; $i < $cnt; $i++) { 887 | $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i]; 888 | } 889 | $this->result = $reverse_history[$cnt]; 890 | 891 | $this->path[$incoming_indent] = $key; 892 | 893 | if ($this->_containsGroupAnchor) { 894 | $this->SavedGroups[$this->_containsGroupAnchor] = $this->path; 895 | if (is_array($value)) { 896 | $k = key($value); 897 | if (!is_int($k)) { 898 | $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k; 899 | } 900 | } 901 | $this->_containsGroupAnchor = false; 902 | } 903 | } 904 | 905 | private static function startsLiteralBlock($line) 906 | { 907 | $lastChar = substr(trim($line), -1); 908 | if ($lastChar != '>' && $lastChar != '|') { 909 | return false; 910 | } 911 | if ($lastChar == '|') { 912 | return $lastChar; 913 | } 914 | // HTML tags should not be counted as literal blocks. 915 | if (preg_match('#<.*?>$#', $line)) { 916 | return false; 917 | } 918 | return $lastChar; 919 | } 920 | 921 | private static function greedilyNeedNextLine($line) 922 | { 923 | $line = trim($line); 924 | if (!strlen($line)) { 925 | return false; 926 | } 927 | if (substr($line, -1, 1) == ']') { 928 | return false; 929 | } 930 | if ($line[0] == '[') { 931 | return true; 932 | } 933 | if (preg_match('#^[^:]+?:\s*\[#', $line)) { 934 | return true; 935 | } 936 | return false; 937 | } 938 | 939 | private function addLiteralLine($literalBlock, $line, $literalBlockStyle) 940 | { 941 | $line = self::stripIndent($line); 942 | $line = rtrim($line, "\r\n\t ") . "\n"; 943 | if ($literalBlockStyle == '|') { 944 | return $literalBlock . $line; 945 | } 946 | if (strlen($line) == 0) { 947 | return rtrim($literalBlock, ' ') . "\n"; 948 | } 949 | if ($line == "\n" && $literalBlockStyle == '>') { 950 | return rtrim($literalBlock, " \t") . "\n"; 951 | } 952 | if ($line != "\n") { 953 | $line = trim($line, "\r\n ") . " "; 954 | } 955 | return $literalBlock . $line; 956 | } 957 | 958 | public function revertLiteralPlaceHolder($lineArray, $literalBlock) 959 | { 960 | foreach ($lineArray as $k => $_) { 961 | if (is_array($_)) { 962 | $lineArray[$k] = $this->revertLiteralPlaceHolder($_, $literalBlock); 963 | } elseif (substr($_, -1 * strlen($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder) { 964 | $lineArray[$k] = rtrim($literalBlock, " \r\n"); 965 | } 966 | } 967 | return $lineArray; 968 | } 969 | 970 | private static function stripIndent($line, $indent = -1) 971 | { 972 | if ($indent == -1) { 973 | $indent = strlen($line) - strlen(ltrim($line)); 974 | } 975 | return substr($line, $indent); 976 | } 977 | 978 | private function getParentPathByIndent($indent) 979 | { 980 | if ($indent == 0) { 981 | return array(); 982 | } 983 | $linePath = $this->path; 984 | do { 985 | end($linePath); 986 | $lastIndentInParentPath = key($linePath); 987 | if ($indent <= $lastIndentInParentPath) { 988 | array_pop($linePath); 989 | } 990 | } while ($indent <= $lastIndentInParentPath); 991 | return $linePath; 992 | } 993 | 994 | 995 | private function clearBiggerPathValues($indent) 996 | { 997 | if ($indent == 0) { 998 | $this->path = array(); 999 | } 1000 | if (empty($this->path)) { 1001 | return true; 1002 | } 1003 | 1004 | foreach ($this->path as $k => $_) { 1005 | if ($k > $indent) { 1006 | unset($this->path[$k]); 1007 | } 1008 | } 1009 | 1010 | return true; 1011 | } 1012 | 1013 | 1014 | private static function isComment($line) 1015 | { 1016 | if (!$line) { 1017 | return false; 1018 | } 1019 | if ($line[0] == '#') { 1020 | return true; 1021 | } 1022 | if (trim($line, " \r\n\t") == '---') { 1023 | return true; 1024 | } 1025 | return false; 1026 | } 1027 | 1028 | private static function isEmpty($line) 1029 | { 1030 | return (trim($line) === ''); 1031 | } 1032 | 1033 | 1034 | private function isArrayElement($line) 1035 | { 1036 | if (!$line) { 1037 | return false; 1038 | } 1039 | if ($line[0] != '-') { 1040 | return false; 1041 | } 1042 | if (strlen($line) > 3) { 1043 | if (substr($line, 0, 3) == '---') { 1044 | return false; 1045 | } 1046 | } 1047 | 1048 | return true; 1049 | } 1050 | 1051 | private function isHashElement($line) 1052 | { 1053 | return strpos($line, ':'); 1054 | } 1055 | 1056 | private function isLiteral($line) 1057 | { 1058 | if ($this->isArrayElement($line)) { 1059 | return false; 1060 | } 1061 | if ($this->isHashElement($line)) { 1062 | return false; 1063 | } 1064 | return true; 1065 | } 1066 | 1067 | 1068 | private static function unquote($value) 1069 | { 1070 | if (!$value) { 1071 | return $value; 1072 | } 1073 | if (!is_string($value)) { 1074 | return $value; 1075 | } 1076 | if ($value[0] == '\'') { 1077 | return trim($value, '\''); 1078 | } 1079 | if ($value[0] == '"') { 1080 | return trim($value, '"'); 1081 | } 1082 | return $value; 1083 | } 1084 | 1085 | private function startsMappedSequence($line) 1086 | { 1087 | return ($line[0] == '-' && substr($line, -1, 1) == ':'); 1088 | } 1089 | 1090 | private function returnMappedSequence($line) 1091 | { 1092 | $array = array(); 1093 | $key = self::unquote(trim(substr($line, 1, -1))); 1094 | $array[$key] = array(); 1095 | $this->delayedPath = array(strpos($line, $key) + $this->indent => $key); 1096 | return array($array); 1097 | } 1098 | 1099 | private function returnMappedValue($line) 1100 | { 1101 | $array = array(); 1102 | $key = self::unquote(trim(substr($line, 0, -1))); 1103 | $array[$key] = ''; 1104 | return $array; 1105 | } 1106 | 1107 | private function startsMappedValue($line) 1108 | { 1109 | return (substr($line, -1, 1) == ':'); 1110 | } 1111 | 1112 | private function isPlainArray($line) 1113 | { 1114 | return ($line[0] == '[' && substr($line, -1, 1) == ']'); 1115 | } 1116 | 1117 | private function returnPlainArray($line) 1118 | { 1119 | return $this->_toType($line); 1120 | } 1121 | 1122 | private function returnKeyValuePair($line) 1123 | { 1124 | $array = array(); 1125 | $key = ''; 1126 | if (strpos($line, ':')) { 1127 | // It's a key/value pair most likely 1128 | // If the key is in double quotes pull it out 1129 | if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/', $line, $matches)) { 1130 | $value = trim(str_replace($matches[1], '', $line)); 1131 | $key = $matches[2]; 1132 | } else { 1133 | // Do some guesswork as to the key and the value 1134 | $explode = explode(':', $line); 1135 | $key = trim($explode[0]); 1136 | array_shift($explode); 1137 | $value = trim(implode(':', $explode)); 1138 | } 1139 | // Set the type of the value. Int, string, etc 1140 | $value = $this->_toType($value); 1141 | if ($key === '0') { 1142 | $key = '__!YAMLZero'; 1143 | } 1144 | $array[$key] = $value; 1145 | } else { 1146 | $array = array($line); 1147 | } 1148 | return $array; 1149 | } 1150 | 1151 | 1152 | private function returnArrayElement($line) 1153 | { 1154 | if (strlen($line) <= 1) { 1155 | return array(array()); 1156 | } // Weird %) 1157 | $array = array(); 1158 | $value = trim(substr($line, 1)); 1159 | $value = $this->_toType($value); 1160 | $array[] = $value; 1161 | return $array; 1162 | } 1163 | 1164 | 1165 | private function nodeContainsGroup($line) 1166 | { 1167 | $symbolsForReference = 'A-z0-9_\-'; 1168 | if (strpos($line, '&') === false && strpos($line, '*') === false) { 1169 | return false; 1170 | } // Please die fast ;-) 1171 | if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) { 1172 | return $matches[1]; 1173 | } 1174 | if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) { 1175 | return $matches[1]; 1176 | } 1177 | if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) { 1178 | return $matches[1]; 1179 | } 1180 | if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) { 1181 | return $matches[1]; 1182 | } 1183 | if (preg_match('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) { 1184 | return $matches[1]; 1185 | } 1186 | return false; 1187 | } 1188 | 1189 | private function addGroup($line, $group) 1190 | { 1191 | if ($group[0] == '&') { 1192 | $this->_containsGroupAnchor = substr($group, 1); 1193 | } 1194 | if ($group[0] == '*') { 1195 | $this->_containsGroupAlias = substr($group, 1); 1196 | } 1197 | //print_r ($this->path); 1198 | } 1199 | 1200 | private function stripGroup($line, $group) 1201 | { 1202 | $line = trim(str_replace($group, '', $line)); 1203 | return $line; 1204 | } 1205 | } 1206 | 1207 | // Enable use of Spyc from command line 1208 | // The syntax is the following: php spyc.php spyc.yaml 1209 | 1210 | define('SPYC_FROM_COMMAND_LINE', false); 1211 | 1212 | do { 1213 | if (!SPYC_FROM_COMMAND_LINE) { 1214 | break; 1215 | } 1216 | if (empty($_SERVER['argc']) || $_SERVER['argc'] < 2) { 1217 | break; 1218 | } 1219 | if (empty($_SERVER['PHP_SELF']) || $_SERVER['PHP_SELF'] != 'spyc.php') { 1220 | break; 1221 | } 1222 | $file = $argv[1]; 1223 | printf("Spyc loading file: %s\n", $file); 1224 | print_r(spyc_load_file($file)); 1225 | } while (0); 1226 | -------------------------------------------------------------------------------- /tests/connection.config.php.dist: -------------------------------------------------------------------------------- 1 | '...', 4 | 5 | 'CLIENT' => '...', 6 | 7 | 'R3NAME' => '...', 8 | 'GROUP' => '...', 9 | 10 | 'CODEPAGE' => '...', 11 | 12 | 'LANG' => 'en', 13 | 14 | 'LCHECK' => true, 15 | 'TRACE' => true, 16 | 17 | 'user' => '...', 18 | 'passwd' => '...' 19 | ]; 20 | -------------------------------------------------------------------------------- /tests/resources/Z_TEST_DATA.abap: -------------------------------------------------------------------------------- 1 | FUNCTION Z_TEST_DATA. 2 | *"---------------------------------------------------------------------- 3 | *"*"Local Interface: 4 | *" IMPORTING 5 | *" VALUE(INT1) LIKE ZTABLE-ZINT1 OPTIONAL 6 | *" VALUE(INT2) LIKE ZTABLE-ZINT2 OPTIONAL 7 | *" VALUE(INT4) LIKE ZTABLE-ZINT4 OPTIONAL 8 | *" VALUE(FLOAT) LIKE ZTABLE-ZFLT OPTIONAL 9 | *" VALUE(CHAR) LIKE ZTABLE-ZCHAR OPTIONAL 10 | *" VALUE(DATE) LIKE ZTABLE-ZDATE OPTIONAL 11 | *" VALUE(TIME) LIKE ZTABLE-ZTIME OPTIONAL 12 | *" VALUE(NUMC) LIKE ZTABLE-ZNUMC OPTIONAL 13 | *" VALUE(BCD) LIKE ZTABLE-ZBCD OPTIONAL 14 | *" VALUE(ISTRUCT) LIKE ZTABLE STRUCTURE ZTABLE OPTIONAL 15 | *" VALUE(IMPORT_TABLE) TYPE ZTABLET OPTIONAL 16 | *" EXPORTING 17 | *" VALUE(EINT1) LIKE ZTABLE-ZINT1 18 | *" VALUE(EINT2) LIKE ZTABLE-ZINT2 19 | *" VALUE(EINT4) LIKE ZTABLE-ZINT4 20 | *" VALUE(EFLOAT) LIKE ZTABLE-ZFLT 21 | *" VALUE(ECHAR) LIKE ZTABLE-ZCHAR 22 | *" VALUE(EDATE) LIKE ZTABLE-ZDATE 23 | *" VALUE(ETIME) LIKE ZTABLE-ZTIME 24 | *" VALUE(ENUMC) LIKE ZTABLE-ZNUMC 25 | *" VALUE(EBCD) LIKE ZTABLE-ZBCD 26 | *" VALUE(ESTRUCT) LIKE ZTABLE STRUCTURE ZTABLE 27 | *" VALUE(EXPORT_TABLE) TYPE ZTABLET 28 | *" TABLES 29 | *" DATA STRUCTURE ZTABLE OPTIONAL 30 | *" RESULT STRUCTURE TAB512 OPTIONAL 31 | *"---------------------------------------------------------------------- 32 | 33 | 34 | data: val(50) type c. 35 | 36 | data: begin of out, 37 | fld(20), 38 | val(256), 39 | end of out. 40 | 41 | 42 | refresh result. 43 | 44 | if int1 is not initial. 45 | write int1 to out-val left-justified. 46 | out-fld = 'INT1'. 47 | append out to result. 48 | eint1 = int1. 49 | endif. 50 | 51 | if int2 is not initial. 52 | write int2 to out-val left-justified. 53 | out-fld = 'INT2'. 54 | append out to result. 55 | eint2 = int2. 56 | endif. 57 | 58 | if int4 is not initial. 59 | write int4 to out-val left-justified. 60 | out-fld = 'INT4'. 61 | append out to result. 62 | eint4 = int4. 63 | endif. 64 | 65 | if float is not initial. 66 | write float to out-val left-justified. 67 | out-fld = 'FLOAT'. 68 | append out to result. 69 | efloat = float. 70 | endif. 71 | 72 | 73 | if char is not initial. 74 | write char to out-val. 75 | out-fld = 'CHAR'. 76 | append out to result. 77 | echar = char. 78 | endif. 79 | 80 | if date is not initial. 81 | write date to out-val using edit mask '__/__/____'. 82 | out-fld = 'DATE'. 83 | append out to result. 84 | edate = date. 85 | endif. 86 | 87 | if time is not initial. 88 | write time to out-val using edit mask '__:__:__'. 89 | out-fld = 'TIME'. 90 | append out to result. 91 | etime = time. 92 | endif. 93 | 94 | if numc is not initial. 95 | write numc to out-val left-justified. 96 | out-fld = 'NUMC'. 97 | append out to result. 98 | enumc = numc. 99 | endif. 100 | 101 | if bcd is not initial. 102 | write bcd to out-val left-justified. 103 | out-fld = 'BCD'. 104 | append out to result. 105 | ebcd = bcd. 106 | endif. 107 | 108 | result = ''. 109 | append result. 110 | result = 'START-OF-ISTRUCT-DATA'. 111 | append result. 112 | if istruct-zint1 is not initial. 113 | write istruct-zint1 to out-val left-justified. 114 | out-fld = 'INT1'. 115 | append out to result. 116 | endif. 117 | 118 | if istruct-zint2 is not initial. 119 | write istruct-zint2 to out-val left-justified. 120 | out-fld = 'INT2'. 121 | append out to result. 122 | endif. 123 | 124 | if istruct-zint4 is not initial. 125 | write istruct-zint4 to out-val left-justified. 126 | out-fld = 'INT4'. 127 | append out to result. 128 | endif. 129 | 130 | if istruct-zflt is not initial. 131 | write istruct-zflt to out-val left-justified. 132 | out-fld = 'FLOAT'. 133 | append out to result. 134 | endif. 135 | 136 | 137 | if istruct-zchar is not initial. 138 | write istruct-zchar to out-val. 139 | out-fld = 'CHAR'. 140 | append out to result. 141 | endif. 142 | 143 | if istruct-zdate is not initial. 144 | write istruct-zdate to out-val using edit mask '__/__/____'. 145 | out-fld = 'DATE'. 146 | append out to result. 147 | endif. 148 | 149 | if istruct-ztime is not initial. 150 | write istruct-ztime to out-val using edit mask '__:__:__'. 151 | out-fld = 'TIME'. 152 | append out to result. 153 | endif. 154 | 155 | if istruct-znumc is not initial. 156 | write istruct-znumc to out-val left-justified. 157 | out-fld = 'NUMC'. 158 | append out to result. 159 | endif. 160 | 161 | if istruct-zbcd is not initial. 162 | write istruct-zbcd to out-val left-justified. 163 | out-fld = 'BCD'. 164 | append out to result. 165 | endif. 166 | result = 'end-of-istruct-line'. 167 | append result. 168 | 169 | result = ''. 170 | append result. 171 | result = 'START-OF-TABLE-DATA'. 172 | append result. 173 | 174 | loop at data. 175 | if data-zint1 is not initial. 176 | write data-zint1 to out-val left-justified. 177 | out-fld = 'INT1'. 178 | append out to result. 179 | endif. 180 | 181 | if data-zint2 is not initial. 182 | write data-zint2 to out-val left-justified. 183 | out-fld = 'INT2'. 184 | append out to result. 185 | endif. 186 | 187 | if data-zint4 is not initial. 188 | write data-zint4 to out-val left-justified. 189 | out-fld = 'INT4'. 190 | append out to result. 191 | endif. 192 | 193 | if data-zflt is not initial. 194 | write data-zflt to out-val left-justified. 195 | out-fld = 'FLOAT'. 196 | append out to result. 197 | endif. 198 | 199 | 200 | if data-zchar is not initial. 201 | write data-zchar to out-val. 202 | out-fld = 'CHAR'. 203 | append out to result. 204 | endif. 205 | 206 | if data-zdate is not initial. 207 | write data-zdate to out-val using edit mask '__/__/____'. 208 | out-fld = 'DATE'. 209 | append out to result. 210 | endif. 211 | 212 | if data-ztime is not initial. 213 | write data-ztime to out-val using edit mask '__:__:__'. 214 | out-fld = 'TIME'. 215 | append out to result. 216 | endif. 217 | 218 | if data-znumc is not initial. 219 | write data-znumc to out-val left-justified. 220 | out-fld = 'NUMC'. 221 | append out to result. 222 | endif. 223 | 224 | if data-zbcd is not initial. 225 | write data-zbcd to out-val left-justified. 226 | out-fld = 'BCD'. 227 | append out to result. 228 | endif. 229 | result = 'end-of-one-line'. 230 | append result. 231 | endloop. 232 | 233 | clear data. 234 | data-zchar = 'another line'. 235 | append data. 236 | 237 | export_table[] = import_table[]. 238 | 239 | move-corresponding: istruct to estruct. 240 | 241 | 242 | ENDFUNCTION. -------------------------------------------------------------------------------- /tools/u16lit.pl: -------------------------------------------------------------------------------- 1 | # 2 | # @(#) $Id: //bas/BIN/src/maketools/u16lit.pl#22 $ SAP 3 | # 4 | # Copyright (C) 2001, SAP AG, Neurottstrasse 16, 69190 Walldorf, 5 | # GERMANY. 6 | # 7 | # This script converts C/C++ source code on platforms where the type 8 | # 'unsigned short' is used for Unicode characters and literals for 9 | # this type are not supported. 10 | # 11 | # Literals that are preceeded by _U16_LIT_iU are converted to array 12 | # initializers. Literals that are preceeded by _U16_LIT_cU are 13 | # converted to pointers to a constant unsigned short array (unless it 14 | # is "obvious" that they are array initializers). A special handling 15 | # is necessary if the literal is the argument of a sizeof. 16 | # 17 | # This script is called after the C/C++ preprocessor and before the 18 | # native compiler. 19 | # Invocation: 20 | # perl u16lit.pl [-cpp] [-le|-be] .ii 21 | # This will produce a file .i, which can be compiled by the 22 | # native compiler. 23 | # Options: 24 | # -cpp : C++ coding. 25 | # -le : The platform is little endian (auto-detected). 26 | # -be : The platform is big endian (auto-detected). 27 | # 28 | # Known restrictions: 29 | # - Initializers with optional braces are not supported, e.g. 30 | # SAP_UC s[8] = { iU("ABC") }; 31 | # - char s[3] = "ABC"; is correct in C, but an error in C++. We follow 32 | # C++ and do not support 33 | # SAP_UC s[3] = iU("ABC"); 34 | # - This script cannot detect if you use string literals as C++ template 35 | # arguments. 36 | 37 | use strict; 38 | 39 | ######################################################################## 40 | # Global variables 41 | ######################################################################## 42 | use vars qw($buf_size $buf_idx $litp_idx @buf $cur_pos @lit_ar $mod_line); 43 | use vars qw($iu_flag $char_flag $pre_pos); 44 | use vars qw($infile $cpp_flag $le_flag $asciistring_flag $debug_flag); 45 | use vars qw(@e2a $ebcdic2ascii_flag $os390_flag); 46 | use vars qw($backslash_a $backslash_b $backslash_f $backslash_n ); 47 | use vars qw($backslash_r $backslash_t $backslash_v ); 48 | 49 | ######################################################################## 50 | # check if any options are set 51 | ######################################################################## 52 | 53 | # C++ 54 | $cpp_flag = 0; 55 | # endianess (autodetect) 56 | if ( pack("s",1) eq "\1\0" ) { 57 | $le_flag = 1; # little-endian 58 | } else { 59 | $le_flag = 0; # big-endian 60 | } 61 | # normal ASCII strings or wchar style strings 62 | $asciistring_flag = 0; 63 | # insert debugging stuff 64 | $debug_flag = 0; 65 | 66 | 67 | ######################################################################## 68 | # support build of ASCII application on z/OS 69 | ######################################################################## 70 | # EBCDIC (IBM-1047 ) to ASCII (ISO8859-1) conversion table as needed when 71 | # building ASCII applications on z/OS 72 | 73 | @e2a = 74 | ( 75 | 0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15, # 00 76 | 16, 17, 18, 19, 157, 10, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31, # 10 77 | 128, 129, 130, 131, 132, 133, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7, # 20 78 | 144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26, # 30 79 | 32, 160, 226, 228, 224, 225, 227, 229, 231, 241, 162, 46, 60, 40, 43, 124, # 40 80 | 38, 233, 234, 235, 232, 237, 238, 239, 236, 223, 33, 36, 42, 41, 59, 94, # 50 81 | 45, 47, 194, 196, 192, 193, 195, 197, 199, 209, 166, 44, 37, 95, 62, 63, # 60 82 | 248, 201, 202, 203, 200, 205, 206, 207, 204, 96, 58, 35, 64, 39, 61, 34, # 70 83 | 216, 97, 98, 99, 100, 101, 102, 103, 104, 105, 171, 187, 240, 253, 254, 177, # 80 84 | 176, 106, 107, 108, 109, 110, 111, 112, 113, 114, 170, 186, 230, 184, 198, 164, # 90 85 | 181, 126, 115, 116, 117, 118, 119, 120, 121, 122, 161, 191, 208, 91, 222, 174, # A0 86 | 172, 163, 165, 183, 169, 167, 182, 188, 189, 190, 221, 168, 175, 93, 180, 215, # B0 87 | 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, 173, 244, 246, 242, 243, 245, # C0 88 | 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, 185, 251, 252, 249, 250, 255, # D0 89 | 92, 247, 83, 84, 85, 86, 87, 88, 89, 90, 178, 212, 214, 210, 211, 213, # E0 90 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 179, 219, 220, 217, 218, 159 # F0 91 | ); 92 | # 0 1 2 3 4 5 6 7 8 9 A B C D E F 93 | 94 | $ebcdic2ascii_flag = 0; # convert characters to ASCII if 1 95 | 96 | $os390_flag = 0; # do z/OS (OS/390) specific handling 97 | 98 | while( $ARGV[0] =~ /^-/ ) 99 | { 100 | my $notfound = 1; 101 | 102 | if( $ARGV[0] eq "-cpp" ) 103 | { 104 | $cpp_flag = 1; 105 | $notfound = 0; 106 | shift @ARGV; 107 | } 108 | if( $ARGV[0] eq "-le" ) 109 | { 110 | if ( $le_flag eq 0 ) { 111 | print "WARNING (u16lit.pl): Overriding autodetected big-endian mode !\n"; 112 | } 113 | $le_flag = 1; 114 | $notfound = 0; 115 | shift @ARGV; 116 | } 117 | if( $ARGV[0] eq "-be" ) 118 | { 119 | if ( $le_flag eq 1 ) { 120 | print "WARNING (u16lit.pl): Overriding autodetected little-endian mode !\n"; 121 | } 122 | $le_flag = 0; 123 | $notfound = 0; 124 | shift @ARGV; 125 | } 126 | if( $ARGV[0] eq "-asciistring" ) 127 | { 128 | $asciistring_flag = 1; 129 | $notfound = 0; 130 | shift @ARGV; 131 | } 132 | if( $ARGV[0] eq "-wcharstring" ) 133 | { 134 | $asciistring_flag = 0; 135 | $notfound = 0; 136 | shift @ARGV; 137 | } 138 | if( $ARGV[0] eq "-ebcdic2ascii" ) 139 | { 140 | $ebcdic2ascii_flag = 1; 141 | $notfound = 0; 142 | shift @ARGV; 143 | } 144 | if( $ARGV[0] eq "-os390" ) 145 | { 146 | $os390_flag = 1; 147 | $notfound = 0; 148 | shift @ARGV; 149 | } 150 | if( $ARGV[0] eq "-debug" ) 151 | { 152 | $debug_flag = 1; 153 | $notfound = 0; 154 | shift @ARGV; 155 | } 156 | if( $ARGV[0] eq "-sp" ) 157 | { 158 | # Ignore this (obsolete) flag. 159 | $notfound = 0; 160 | shift @ARGV; 161 | } 162 | if ( $ARGV[0] =~ /^-/ ) 163 | { 164 | # option not supported ? 165 | if ($notfound == 1) 166 | { 167 | error_die( "option \'" .$ARGV[0]. "\' not supported" ); 168 | } 169 | } 170 | } 171 | 172 | ######################################################################## 173 | # Initialize global variables 174 | ######################################################################## 175 | # number of lines to be buffered 176 | $buf_size = 40; 177 | $buf_idx = -1; 178 | 179 | # current position in current line $_; all what is before $cur_pos has already 180 | # been written to $mod_line (perhaps after modification). 181 | $cur_pos = 0; 182 | 183 | # integer array to hold literals 184 | @lit_ar = ( ); 185 | 186 | # modified line to be written to OUTF 187 | $mod_line = ""; 188 | 189 | # define code points for escape characters like \n 190 | 191 | $backslash_a = 0x7; 192 | $backslash_b = 0x8; 193 | $backslash_f = 0xc; 194 | $backslash_n = 0xa; 195 | $backslash_r = 0xd; 196 | $backslash_t = 0x9; 197 | $backslash_v = 0xb; 198 | 199 | # on OS/390 or z/OS we have EBCDIC and some of the 200 | # escape characters have different code points 201 | 202 | if ($os390_flag) 203 | { 204 | $backslash_a = ord("\a"); 205 | $backslash_b = ord("\b"); 206 | $backslash_n = ord("\n"); 207 | $backslash_t = ord("\t"); 208 | } 209 | 210 | ######################################################################## 211 | # Open input and output files. 212 | ######################################################################## 213 | $_ = $ARGV[0]; 214 | $infile = $_ ; 215 | open( INF, $_ ) || error_die("open $_ failed"); 216 | s/\.ii/.i/ ; 217 | open( OUTF, ">$_" ) || error_die ("open $_ failed"); 218 | 219 | ######################################################################## 220 | # Loop over input lines 221 | ######################################################################## 222 | while(1 == get_line( ) ) 223 | { 224 | my $parsing_line = 1; 225 | while ($parsing_line == 1) 226 | { 227 | # Does the rest of the cur. line have a _U16_LIT_ ? 228 | $pre_pos = index( $_, "_U16_LIT_", $cur_pos ) ; 229 | if ($pre_pos == -1) 230 | { 231 | # No literal. Write the rest of the current line. 232 | if ($cur_pos < length ) 233 | { 234 | $mod_line .= substr( $_, $cur_pos ); 235 | } 236 | # Exit the loop 237 | $parsing_line = 0; 238 | } 239 | else 240 | { 241 | # Write what comes before the literal 242 | $mod_line .= substr( $_, $cur_pos, $pre_pos - $cur_pos ); 243 | 244 | $cur_pos = $pre_pos; 245 | $litp_idx = $buf_idx; 246 | if ( search_quote( ) == 0 ) 247 | { 248 | # No literal. 249 | error_die( "No cU/iU literal after _U16_LIT_" ); 250 | } 251 | if ($char_flag == 1) 252 | { 253 | single_quote( ); 254 | } 255 | elsif ($char_flag == 0) 256 | { 257 | double_quote( ); 258 | } 259 | } 260 | } 261 | print OUTF "$mod_line" ; 262 | } 263 | 264 | exit 0; 265 | #### end of the main program ########################################### 266 | 267 | ######################################################################## 268 | # Search for the beginning of a literal. 269 | # - Start search at $cur_pos in $_. 270 | # - Set $char_flag. 271 | # - Set $iu_flag. 272 | # - Set $cur_pos to position of (single or double) quote. 273 | # - Return 0 if there is no literal. Else return 1. 274 | ######################################################################## 275 | sub search_quote 276 | { 277 | my $t_str = substr( $_, $cur_pos ); 278 | if ( $t_str =~ /^\s*_U16_LIT_cU/ ) 279 | { 280 | $cur_pos = index( $_, "_U16_LIT_cU", $cur_pos ) 281 | + length("_U16_LIT_cU"); 282 | $iu_flag = 0; 283 | } 284 | elsif ( $t_str =~ /^\s*_U16_LIT_iU/ ) 285 | { 286 | $cur_pos = index( $_, "_U16_LIT_iU", $cur_pos ) 287 | + length("_U16_LIT_iU"); 288 | $iu_flag = 1; 289 | } 290 | elsif ( $t_str =~ /^\s*$/ ) 291 | { 292 | # We have to look at the next line. 293 | # First, finish the current line. 294 | print OUTF "$mod_line\n" ; 295 | if ( 0 == get_line( ) ) 296 | { 297 | error_die( "Unexpected end of file" ); 298 | } 299 | if ( /^\s*_U16_LIT_cU/ ) 300 | { 301 | $cur_pos = index( $_, "_U16_LIT_cU" ) 302 | + length("_U16_LIT_cU"); 303 | $iu_flag = 0; 304 | } 305 | elsif ( /^\s*_U16_LIT_iU/ ) 306 | { 307 | $cur_pos = index( $_, "_U16_LIT_iU" ) 308 | + length("_U16_LIT_iU"); 309 | $iu_flag = 1; 310 | } 311 | else 312 | { 313 | return 0; 314 | } 315 | } 316 | else 317 | { 318 | return 0; 319 | } 320 | # Find the single or double quote 321 | $t_str = substr( $_, $cur_pos ); 322 | if ( $t_str =~ /^\s*\"/ ) 323 | { 324 | $cur_pos = index( $_, "\"", $cur_pos ); 325 | $char_flag = 0; 326 | } 327 | elsif ( $t_str =~ /^\s*\'/ ) 328 | { 329 | $cur_pos = index( $_, "'", $cur_pos ); 330 | $char_flag = 1; 331 | } 332 | elsif ( $t_str =~ /^\s*$/ ) 333 | { 334 | # We have to look at the next line. 335 | # First, finish the current line. 336 | print OUTF "$mod_line\n" ; 337 | if ( 0 == get_line( ) ) 338 | { 339 | error_die( "Unexpected end of file" ); 340 | } 341 | if ( /^\s*\"/ ) 342 | { 343 | $cur_pos = index( $_, "\"" ); 344 | $char_flag = 0; 345 | } 346 | elsif ( /^\s*\'/ ) 347 | { 348 | $cur_pos = index( $_, "'" ); 349 | $char_flag = 1; 350 | } 351 | else 352 | { 353 | error_die( "No literal after _U16_LIT_..." ); 354 | } 355 | } 356 | elsif ( $t_str =~ /^ *\\\"/ ) 357 | { 358 | # set char_flag=-1 -> ignore this literal since we are inside a string (e.g. in assert()), 359 | # changed d040425 December 4th 2002 360 | $char_flag = -1; 361 | } 362 | else 363 | { 364 | error_die( "No literal after _U16_LIT_...(".$t_str.")" ); 365 | } 366 | return 1; 367 | } 368 | 369 | 370 | ######################################################################## 371 | # Deal with a single quote in $_ at position $cur_pos 372 | # - Append to $mod_line 373 | # - Increment $cur_pos 374 | ######################################################################## 375 | sub single_quote 376 | { 377 | # Find closing ' ; first consider special case '\''. 378 | # $cont_pos is the position after the closing ' 379 | my $cont_pos; 380 | if ( "'\\''" eq substr( $_, $cur_pos, 4 ) ) 381 | { 382 | $cont_pos = $cur_pos + 4; 383 | } 384 | else 385 | { 386 | $cont_pos = 1 + index( $_, "'", $cur_pos + 1 ); 387 | if ($cont_pos == 0) 388 | { 389 | error_die("Can't find closing \"'\" "); 390 | } 391 | } 392 | if ( $cpp_flag == 1 ) 393 | { 394 | # For C++, insert a cast 395 | $mod_line .= "(SAP_UTF16)"; 396 | } 397 | # Write '...' 398 | $mod_line .= substr( $_, $cur_pos, $cont_pos - $cur_pos ); 399 | $cur_pos = $cont_pos; 400 | } 401 | 402 | ######################################################################## 403 | # Deal with a double quote in $_ at position $cur_pos 404 | # - Check whether the literal is the argument of a sizeof 405 | # - Append to $mod_line 406 | # - Increment $cur_pos 407 | ######################################################################## 408 | sub double_quote 409 | { 410 | # Is the string literal the argument of a sizeof or a simple 411 | # array initializer? 412 | my $ar_sizeof_flag = search_ar_sizeof( ); 413 | 414 | # Parse till the end of the literal and increment $cur_pos. 415 | parse_string_lit( ); 416 | 417 | if ( $ar_sizeof_flag == 1 ) 418 | { 419 | write_sizeof_arg( ); 420 | } 421 | elsif ( $iu_flag == 1 || $ar_sizeof_flag == 2 ) 422 | { 423 | write_ini_array( ); 424 | } 425 | else 426 | { 427 | write_ptr_lit( ); 428 | } 429 | } 430 | 431 | ######################################################################## 432 | # Search backwards to see whether the string literal is 433 | # (1) the argument of a sizeof or 434 | # (2) the initializer of a "simple" array. 435 | # - Start search at $pre_pos - 1 . 436 | # - Return 1 in case (1), 2 in case (2), else 0. 437 | ######################################################################## 438 | sub search_ar_sizeof 439 | { 440 | # Line where the _U16_LIT_ occurred. 441 | my $back_idx = $litp_idx; 442 | 443 | my $z_str = ""; 444 | if ( $pre_pos > 0 ) 445 | { 446 | $z_str = substr( $buf[$back_idx], 0, $pre_pos - 1 ); 447 | } 448 | 449 | # state has following values: 450 | # 1 if '(' was consumed; 451 | # 2 if '=' was consumed. 452 | my $state = 0; 453 | 454 | while (1 == 1) 455 | { 456 | if ( $z_str =~ /sizeof(\s*\()*\s*$/ ) 457 | { 458 | # We have ... sizeof ( ... ( 459 | if ( $state == 2 ) 460 | { 461 | error_die( "Unexpected '='" ); 462 | } 463 | return 1; 464 | } 465 | elsif ( $z_str =~ /^\s*$/ ) 466 | { 467 | # Only whitespace. 468 | # Don't change state. 469 | } 470 | elsif ( $state != 2 && ( $z_str =~ /^(\s*\()+\s*$/ ) ) 471 | { 472 | # We have ... ( ... ( 473 | $state = 1; 474 | } 475 | elsif ( $state != 1 && ( $z_str =~ /^\s*=\s*$/ ) ) 476 | { 477 | # We have ... = 478 | $state = 2; 479 | } 480 | elsif ( ( $state == 2 && 481 | $z_str =~ /\WSAP_CHAR\s+\w+\s*\[\s*[0-9]*\s*\]\s*$/ ) || 482 | ( $state == 2 && 483 | $z_str =~ /\WSAP_UC\s+\w+\s*\[\s*[0-9]*\s*\]\s*$/ ) || 484 | ( $state == 0 && 485 | $z_str =~ /\WSAP_CHAR\s+\w+\s*\[\s*[0-9]*\s*\]\s*=\s*$/ ) || 486 | ( $state == 0 && 487 | $z_str =~ /\WSAP_UC\s+\w+\s*\[\s*[0-9]*\s*\]\s*=\s*$/ ) 488 | ) 489 | { 490 | # Simple array initialization 491 | return 2; 492 | } 493 | else 494 | { 495 | return 0; 496 | } 497 | # We must look at the previous line 498 | $back_idx = ( $back_idx - 1 ) % $buf_size; 499 | if ( $back_idx == $buf_idx ) 500 | { 501 | # @buf is exhausted. 502 | error_die( "Statement exceeds $buf_size lines" ); 503 | } 504 | $z_str = $buf[$back_idx] ; 505 | } 506 | } 507 | 508 | ######################################################################## 509 | # Parse string literal till closing '"'. 510 | # - Opening '"' is in $_ at position $cur_pos. 511 | # - The position after the closing '"' will be returned. 512 | # - The literal is stored in @lit_ar as an array of integers. 513 | ######################################################################## 514 | sub parse_string_lit 515 | { 516 | @lit_ar = ( ); 517 | my $num_str; 518 | 519 | # index in array @lit_ar 520 | my $c_idx = 0; 521 | 522 | # position in $_ 523 | $cur_pos += 1; 524 | 525 | while (1 == 1) 526 | { 527 | if ( $cur_pos > length ) 528 | { 529 | error_die( "Unexpected end of line" ); 530 | } 531 | 532 | my $s_str = substr( $_, $cur_pos ); 533 | if ( $s_str =~ /^\\[\'\"\?\\]/ ) 534 | { 535 | # escaped ' " ? \ 536 | $lit_ar[$c_idx++] = ord( substr( $s_str, 1 ) ); 537 | $cur_pos += 2; 538 | } 539 | elsif ( $s_str =~ /^\\a/ ) 540 | { 541 | $lit_ar[$c_idx++] = $backslash_a; 542 | $cur_pos += 2; 543 | } 544 | elsif ( $s_str =~ /^\\b/ ) 545 | { 546 | $lit_ar[$c_idx++] = $backslash_b; 547 | $cur_pos += 2; 548 | } 549 | elsif ( $s_str =~ /^\\f/ ) 550 | { 551 | $lit_ar[$c_idx++] = $backslash_f; 552 | $cur_pos += 2; 553 | } 554 | elsif ( $s_str =~ /^\\n/ ) 555 | { 556 | $lit_ar[$c_idx++] = $backslash_n; 557 | $cur_pos += 2; 558 | } 559 | elsif ( $s_str =~ /^\\r/ ) 560 | { 561 | $lit_ar[$c_idx++] = $backslash_r; 562 | $cur_pos += 2; 563 | } 564 | elsif ( $s_str =~ /^\\t/ ) 565 | { 566 | $lit_ar[$c_idx++] = $backslash_t; 567 | $cur_pos += 2; 568 | } 569 | elsif ( $s_str =~ /^\\v/ ) 570 | { 571 | $lit_ar[$c_idx++] = $backslash_v; 572 | $cur_pos += 2; 573 | } 574 | elsif ( ($num_str) = ( $s_str =~ /^\\([0-7]+)/ ) ) 575 | { 576 | # octal number, at most 3 digits 577 | $num_str = substr( $num_str, 0, 3 ); 578 | $lit_ar[$c_idx++] = oct( $num_str ); 579 | $cur_pos += length( $num_str ) + 1; 580 | } 581 | elsif ( ($num_str) = ( $s_str =~ /^\\x([0-9a-fA-F]+)/ ) ) 582 | { 583 | # hexadecimal number, no limit on number of digits 584 | $lit_ar[$c_idx++] = hex( $num_str ); 585 | $cur_pos += length( $num_str ) + 2; 586 | } 587 | elsif ( ($num_str) = ( $s_str =~ /^\\u([0-9a-fA-F]+)/ ) ) 588 | { 589 | # universal character name, at most 4 digits 590 | # (Standard says: exactly 4 digits) 591 | $num_str = substr( $num_str, 0, 4 ); 592 | $lit_ar[$c_idx++] = hex( $num_str ); 593 | $cur_pos += length( $num_str ) + 2; 594 | } 595 | elsif ( ($num_str) = ( $s_str =~ /^\\U([0-9a-fA-F]+)/ ) ) 596 | { 597 | # universal character name, at most 8 digits 598 | # (Standard says: exactly 8 digits) 599 | # TODO: convert from UTF-32 to UTF-16 600 | $num_str = substr( $num_str, 0, 8 ); 601 | $lit_ar[$c_idx++] = hex( $num_str ); 602 | $cur_pos += length( $num_str ) + 2; 603 | } 604 | elsif ( $s_str =~ /^\\/ ) 605 | { 606 | error_die( "String literal contains undefined escape sequence" ); 607 | } 608 | elsif ( $s_str =~ /^\"/ ) 609 | { 610 | # Closing '"' 611 | $cur_pos += 1; 612 | 613 | # Check if another string literal follows 614 | if ( search_quote( ) == 0 ) 615 | { 616 | last; 617 | } 618 | else 619 | { 620 | # Another string literal follows 621 | if ($char_flag == 1) 622 | { 623 | error_die( "Syntax error" ); 624 | } 625 | $cur_pos += 1; 626 | } 627 | } 628 | else 629 | { 630 | # Ordinary character 631 | $lit_ar[$c_idx++] = ord( $s_str ); 632 | $cur_pos += 1; 633 | } 634 | } # End of while loop 635 | } 636 | 637 | ######################################################################## 638 | # Read lines until there is a line that is not whitespace and does not 639 | # start with '#'. 640 | # - initialize $mod_line 641 | # - save line in @buf 642 | # - initialize $cur_pos 643 | ######################################################################## 644 | sub get_line 645 | { 646 | while() 647 | { 648 | my $s_str = ""; 649 | $mod_line = ""; 650 | # Only whitespace in cur. line? 651 | if ( /^\s*$/ ) 652 | { 653 | $mod_line = $_; 654 | next; 655 | } 656 | # Does line start with '#' ? ('\#' because of Emacs indentation) 657 | if ( /^\#/ ) 658 | { 659 | $mod_line = $_; 660 | next; 661 | } 662 | 663 | # on z/OS (OS/390) concatenate lines split by a backslash 664 | 665 | if ( $os390_flag == 1) 666 | { 667 | $s_str = $_; 668 | while ( $s_str =~ /\\\n$/ ) 669 | { 670 | $s_str =~ s/\\\n//e; 671 | $s_str .= ; 672 | } 673 | $_ = $s_str; 674 | } 675 | 676 | $buf_idx = ( $buf_idx + 1 ) % $buf_size ; 677 | $buf[$buf_idx] = $_ ; 678 | 679 | # current position in current line 680 | $cur_pos = 0; 681 | return 1; 682 | } continue 683 | { 684 | print OUTF "$mod_line" ; 685 | } 686 | return 0; 687 | } 688 | 689 | ######################################################################## 690 | # Format the contents of @lit_ar as 691 | # {0x41,0x42,0} (for instance) 692 | # - if -ebcdic2ascii option set convert values to ascii 693 | # - Append to $mod_line. 694 | ######################################################################## 695 | sub write_ini_array 696 | { 697 | $mod_line .= "{"; 698 | my $c_int; 699 | my $c_int_a; 700 | foreach $c_int (@lit_ar) 701 | { 702 | if ( $ebcdic2ascii_flag == 0 ) 703 | { 704 | $c_int_a = $c_int; 705 | } 706 | else 707 | { 708 | $c_int_a = $e2a[$c_int]; 709 | } 710 | $mod_line .= sprintf("0x%x,", $c_int_a ); 711 | } 712 | $mod_line .= "0}"; 713 | } 714 | 715 | ######################################################################## 716 | # Process the contents of @lit_ar to get 717 | # "+++++" (5 '+' if there are 2 characters in @lit_ar). 718 | # - Append to $mod_line. 719 | # 720 | # Further remark: 721 | # sizeof(SAP_UC[3]) would also work, but 722 | # sizeof SAP_UC[3] and sizeof((SAP_UC[3])) would be syntax errors. 723 | ######################################################################## 724 | sub write_sizeof_arg 725 | { 726 | # $#lit_ar is the index of the last element in @lit_ar. 727 | # One terminating zero-byte is appended anyway. 728 | my $cnt = $#lit_ar * 2 + 3; 729 | $mod_line .= "\"" . ( "+" x $cnt ) . "\"" ; 730 | } 731 | 732 | ######################################################################## 733 | # Format the contents of @lit_ar. Example: 734 | # @lit_ar = ( 0x41, 0x42, 0x43, 0x44, 0x45 ); 735 | # On a big endian machine, this gives: 736 | # ((SAP_UTF16 *)L"\x410042\x430044\x450000") 737 | # On a little endian machine: 738 | # ((SAP_UTF16 *)L"\x420041\x440043\x000045") 739 | # 740 | # - Append to $mod_line. 741 | # 742 | # Further remarks: 743 | # 744 | # We do not write (const SAP_UTF16 *) because that results in too many 745 | # warnings. 746 | # 747 | # The C Standard ISO 9899:1999 allows "compound literals", see Section 748 | # 6.5.2.5: 749 | # memcpy( s1, (unsigned short []){ 'A', 'B', 0 }, 6 ) ; 750 | # With gcc version 2.95.2 and egcs-2.91.66 on Linux, this works 751 | # (in C and C++). 752 | # On HP-UX 11 and Digital Unix 4.0, this gives a syntax error. 753 | # 754 | # On HP-UX 11, (unsigned short *)"\000A\000B\000" gives the message: 755 | # "Casting from loose to strict alignment: Resulting pointer may be misaligned." 756 | # And in fact we need the correct alignment for SAP_UTF16* . 757 | # Alternatives: 758 | # a) Initialize a static variable (with a generated name) at the 759 | # beginning of the file. 760 | # b) Generate xU("\000A\000B\000\000A\000B\000"). Here our string occurs 761 | # twice with different alignment, and xU() is a function that selects 762 | # the correctly aligned array at run time. 763 | # c) Misuse L"..." 764 | # 765 | ######################################################################## 766 | sub write_ptr_lit_wcharstring 767 | { 768 | $mod_line .= "((SAP_UTF16*)L\""; 769 | my $ar_len = $#lit_ar + 1; 770 | # length of @lit_ar might be odd, but we want to read an even number 771 | # of characters. So append a '\0'. 772 | $lit_ar[$ar_len] = 0; 773 | my $cur_c = 0; 774 | my $x_str; 775 | 776 | while ( $cur_c < $ar_len ) 777 | { 778 | if ( $le_flag == 1 ) 779 | { 780 | # Little endian 781 | $x_str = sprintf("\\x%04x%04x", $lit_ar[$cur_c + 1], 782 | $lit_ar[$cur_c]); 783 | } 784 | else 785 | { 786 | # Big endian 787 | if ( $ebcdic2ascii_flag == 0 ) 788 | { 789 | $x_str = sprintf("\\x%04x%04x", $lit_ar[$cur_c], 790 | $lit_ar[$cur_c + 1]); 791 | } 792 | else 793 | { 794 | $x_str = sprintf("\\x%04x%04x", $e2a[$lit_ar[$cur_c]], 795 | $e2a[$lit_ar[$cur_c + 1]]); 796 | } 797 | } 798 | $cur_c += 2; 799 | $mod_line .= $x_str; 800 | } 801 | $mod_line .= "\")"; 802 | } 803 | 804 | 805 | ############################################################################# 806 | # Format the contents of @lit_ar in style of standard ASCII strings. Example: 807 | # @lit_ar = ( 0x61, 0x62, 0x63 ); 808 | # On a big endian machine, this gives: 809 | # ((SAP_UTF16 *) "\0A\0B\0C\0"; 810 | # On a little endian machine: 811 | # ((SAP_UTF16 *) "A\0B\0C\0") 812 | # 813 | # - Append to $mod_line. 814 | # 815 | # NOTES: 816 | # 817 | # - currently we use this function for AIX 5.1 only. 818 | # - at the end we add an \0 byte. The other needed one will be added by the compiler. 819 | # 820 | ############################################################################# 821 | sub write_ptr_lit_asciistring 822 | { 823 | if ( $debug_flag ) { 824 | $mod_line .= "dbgAlignCheckStringU16(\""; 825 | } else { 826 | $mod_line .= "((SAP_UTF16*) \""; 827 | } 828 | my $ar_len = $#lit_ar; 829 | my $cur_c = 0; 830 | my $x_str; 831 | my $a; 832 | 833 | while ( $cur_c <= $ar_len ) 834 | { 835 | $a = $lit_ar[$cur_c]; 836 | 837 | if ( chr($a) =~ /[a-zA-Z !&\/\?\(\);:,\-]/ ) { 838 | # it's a printable ascii character... 839 | # (except digits, which could be interpreted as octals) 840 | if ( $le_flag == 1 ) { 841 | $x_str = sprintf("%c\\0", $a ); # Little endian 842 | } else { 843 | $x_str = sprintf("\\0%c", $a ); # Big endian 844 | } 845 | 846 | } else { 847 | 848 | # we need to print the hex notation 849 | if ( $le_flag == 1 ) { 850 | # Little endian 851 | if ( $a < 256 ) { # shorten the string if possible. 852 | $x_str = sprintf("\\x%02x\\0", $a ); 853 | } else { 854 | $x_str = sprintf("\\x%02x\\x%02x", $a % 256, $a / 256 ); 855 | } 856 | } else { 857 | # Big endian 858 | if ( $a < 256 ) { # shorten the string if possible. 859 | if ( $ebcdic2ascii_flag == 1 ) 860 | { 861 | $a = $e2a[$a]; 862 | } 863 | $x_str = sprintf("\\0\\x%02x", $a ); 864 | } else { 865 | $x_str = sprintf("\\x%02x\\x%02x", $a / 256, $a % 256 ); 866 | } 867 | } 868 | 869 | } 870 | 871 | $cur_c += 1; 872 | $mod_line .= $x_str; 873 | } 874 | 875 | # add the trailing 0-byte, another one will be added by the compiler. 876 | $mod_line .= "\\0"; 877 | $mod_line .= "\")"; 878 | } 879 | 880 | 881 | sub write_ptr_lit() 882 | { 883 | if ($asciistring_flag ne 0) { 884 | write_ptr_lit_asciistring( ); 885 | } else { 886 | write_ptr_lit_wcharstring( ); 887 | } 888 | } 889 | 890 | 891 | ######################################################################## 892 | # Output compiler-like message and die 893 | ######################################################################## 894 | sub error_die 895 | { 896 | my $txt = $_[0]; 897 | # $. is the line number in the input file . 898 | print STDERR "$infile:$.: $txt --"; 899 | die "dying"; 900 | } 901 | --------------------------------------------------------------------------------