Compare commits

..

36 Commits

Author SHA1 Message Date
Anatol Belski
b15cdb1f92 Prepare 2.1.2 2018-03-14 11:53:04 +01:00
Anatol Belski
91302e8142 Use SSL explicitly for communitation with windows.php.net 2018-03-12 14:03:00 +01:00
Anatol Belski
f655bcf7d1 Upgrade vswhere 2018-03-12 11:22:11 +01:00
Alexander Gabriel
89bc6e0eb8 Using PHP-X.Y would not work. 2018-03-05 11:29:18 +01:00
Anatol Belski
4d9b189d04 Increase version for dev 2018-02-20 15:33:05 +01:00
Anatol Belski
ff33ae5143 Prepare 2.1.1 2018-02-20 15:32:09 +01:00
Anatol Belski
3cf0f67f27 More robust network error handling 2018-02-20 14:37:15 +01:00
Anatol Belski
b0a93f01c5 Send user agent when fetching 2018-02-20 10:34:30 +01:00
Anatol Belski
e10c86c2d5 Avoid fetching series more than once in the same run 2018-02-20 09:31:08 +01:00
Anatol Belski
20ccc545bd Further notes on custom training case implementation 2018-02-02 17:03:02 +01:00
Anatol Belski
0be0ba3a84 Back to dev 2018-02-02 13:55:54 +01:00
Anatol Belski
c2e3b0ec40 Prepare 2.1.0 2018-02-02 13:54:32 +01:00
Anatol Belski
b0b61457b4 Add note on training case contributing 2018-02-02 13:18:06 +01:00
Anatol Belski
c4ba07a627 Make it a link 2018-02-02 13:15:12 +01:00
Anatol Belski
2c54b0baf5 Edits to PGO description 2018-02-02 13:13:39 +01:00
Anatol Belski
ca942978ee Upgrade 7za 2018-02-02 12:53:12 +01:00
Anatol Belski
6153bb9af2 Mention phpsdk_pgo 2018-02-02 12:44:38 +01:00
Anatol Belski
c4ce390679 Change wording 2018-02-02 09:57:11 +01:00
Anatol Belski
2040ea78bd Use new URLs 2018-02-02 09:42:46 +01:00
Anatol Belski
90f5c1633e Make it a link 2018-02-02 09:41:53 +01:00
Anatol Belski
5a44f0b05d Extend PGO doc 2018-02-02 09:40:14 +01:00
Anatol Belski
c84b3e6b9e Inc minor
The addition of the PGO features is what makes impact.
2018-02-02 08:41:50 +01:00
Anatol Belski
a861392d45 Fix typos 2018-02-02 08:40:11 +01:00
Anatol Belski
0474318721 Remove irrelevant part 2018-02-02 08:31:10 +01:00
Anatol Belski
b21fad7268 Update doc 2018-02-02 08:28:44 +01:00
Anatol Belski
5748dedb3b Update year and fix eol 2018-02-01 17:33:37 +01:00
Anatol Belski
4cea7a4f66 Upgrade bundled PHP 2018-02-01 17:25:23 +01:00
Anatol Belski
7e8235f1a1 Upgrade vswhere 2018-02-01 17:18:20 +01:00
Anatol Belski
1122cbd9d9 Merged PGO integration branch
Squashed commit of the following:

commit 0b963bf9926cfb23b82de5c5ecb802c23ee1d91b
Merge: b0b5b9c 1684c7e
Author: Anatol Belski <ab@php.net>
Date:   Fri Nov 17 15:11:22 2017 +0100

    Merge branch 'master' into pgo_integration

    * master:
      Back to dev
      Prepare 2.0.13
      Upgrade vswhere
      Upgrade bundled PHP
      Unset some tmp vars
      Note on unattended build
      Check for Windows SDK 10.0 for VC14, too
      Pass nologo to vcvarsall.bat
      Unify EOL
      Ensure starter scripts keep the current directory
      Update version in readme
      Add comment
      Fix curl error handling

commit b0b5b9c6e7c2695968b8c184ba4f1542d83261ec
Author: Anatol Belski <ab@php.net>
Date:   Mon Oct 30 14:58:33 2017 +0100

    Warn if a job file is not present, maybe SDK needs reinit

commit d84a2e8432d424471d5aeb77911f71b2d2bb377c
Author: Anatol Belski <ab@php.net>
Date:   Mon Oct 30 07:39:33 2017 +0100

    Add --scenario to the help

commit 9556fad5e5869a6d9ac150ace863c5c304d7c100
Author: Anatol Belski <ab@php.net>
Date:   Sat Oct 28 18:22:31 2017 +0200

    Add scenario based on https://github.com/01org/php_pgo_training_scripts

commit c4e32bbc7142680796a726980a089d98d310797a
Merge: 11dcbc8 1ba1bf1
Author: Anatol Belski <ab@php.net>
Date:   Thu Oct 26 19:32:24 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Back to dev
      Prepare 2.0.12
      Reflect re2c version
      Note about fetching
      Add note about UNIX flavors
      Reflect bison version
      Rephrase
      Back to dev
      Prepare beta3
      Rebase MSYS2 DLLs
      Turn back to dev
      Prepare 2.0.12beta2
      Add missing DLLs
      Back to dev
      Prepare 2.0.12beta1
      Upgrade vswhere
      Upgrade msys2 tools
      Back to dev
      2.0.11

commit 11dcbc88b754729c97aef70442bb1223a142ce09
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 11:23:34 2017 +0200

    Add locking to the PGO training and init actions

commit aca33a7e3813e894fa2a0457e31efabaf3e9d3fb
Merge: bcb8fcf c7c874e
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 10:48:06 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Improve messaging for locked dependency path

commit bcb8fcf366353b69c6091d30bf3f9859b890ea66
Merge: d86027f 97112e4
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 10:36:50 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Refactor lock also wrt shared/exclusive
      Folds

commit d86027fdcca2916c5a31cf24afa540ce90a18249
Merge: 253d590 a5afa11
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 09:22:41 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Integrate locking into the dep update process
      Fix and improve lock class
      Add locker class
      Lock while caching
      Folds

commit 253d5908fb57a4e79f08ecbc36a924f0abb42481
Merge: ea6d9d9 d802183
Author: Anatol Belski <ab@php.net>
Date:   Tue Sep 5 18:28:01 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Adjust description
      Support branch recognition when working under dev package

commit ea6d9d957407d98dd05651d87aa3bb173030e679
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 16:47:06 2017 +0200

    Increase runs number

commit 157af24f4b3bfc3fee123bdb1ae466cd5295260e
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 14:19:07 2017 +0200

    Prepare some debug piece

commit 74ce6dd35020fb7de6277335a17ac7487fddd23b
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 14:10:03 2017 +0200

    More for error logging

commit d17b00261ee7d1b70e202010d7946f411b10db7b
Merge: 30dc3ff a97d0bd
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 15:57:21 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Fix Arch determintion
      Add pretty option
      Rework dllmap script
      Note pwgen presence

commit 30dc3ff3c2944dfca7b6d7446ca0cf365c12746e
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 14:18:41 2017 +0200

    Fix binary path

commit e1f2d9c4aaa61ba176cdc22ecd667d617ce315a4
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 14:10:01 2017 +0200

    Extend the firewall template

commit 7cab2769a146fdbd85e4118589962f984d3ca521
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:40:57 2017 +0200

    Fix syntax error

commit 74760b1d339ed66ff02f09b1a3ccd11fb9823a8a
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:39:31 2017 +0200

    Fix syntax error

commit 9ee0f9f564edcf82893cc8cbe57942b816f54edc
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:37:50 2017 +0200

    Typehints

commit 6a86ff3399425224affd35ef97e58f416f9724cb
Merge: a71e63d de669c7
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:08:55 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Back to dev
      2.0.10

commit a71e63d44046d503af4a9cbc759ff41f2bc27246
Merge: 5021a30 ceececf
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:06:12 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Improve the pack command, show more info and translate the exit code

commit 5021a30fa1a1d9f2f28925504aa4f5b6cacedfae
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 12:42:15 2017 +0200

    Add possibility to mark cases inactive

    and turn off the mediawiki case for now.

commit 04f267114f3f5a9d2e53dc7b37dc16e948f71199
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 25 11:23:17 2017 +0200

    Rework HTTP code evaluation and URL setup

commit c6c405968e99c1ceb169eed45f07cef3259aa376
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 15:08:00 2017 +0200

    Further INI templating per scenario

commit 9be8f65856c5ff6d7f313d7b4693f5730e20dc9a
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 13:34:41 2017 +0200

    Decrease numbers yet more, otherwise it's an issue on 32-bit

    Still need to workout something for 64/32-bit separation

commit 6dfe66dcafc8c3c68448a1b1c1fe46d5a5d5ab8e
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 13:31:08 2017 +0200

    Fix wrong ini, no Opcache cli

commit c0556fac6bcb0c609367f93fae302f149d1cde48
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 13:25:26 2017 +0200

    Revert numbers and increase timeout

commit dbc86f72c8de1a7851632285e5eb1efcee1189ca
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 12:50:20 2017 +0200

    Show the training scenario being used

commit c67a5eea36bb97dc2bcae5097abc143c15676e81
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 12:45:23 2017 +0200

    Don't enable opcache on CLI and adjust some numbers

commit 0ec768ca40d11bd84b53b040a42aaf994d9a9f23
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 10:42:55 2017 +0200

    Set fastcgi_read_timeout

commit 6145b841b5f086b7c7f9a02f0d9fd1d41fae4cf2
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 10:30:43 2017 +0200

    Set select timeout

commit 600ea8518f5ca2bbbbcc65c8772d283da0da2a15
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 22:56:28 2017 +0200

    Keep FCGI childer some longer alive

commit f6a95c50c5bcb2673721bb63146f87a8fbdcf2c5
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 22:51:47 2017 +0200

    Exclude most of the extension not directly trained

commit 87f4d7393167944108b40b34a6eee1c250f4587d
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 18:36:54 2017 +0200

    Adjust error_log filename

commit e22caaeb390433d3cf6d6dc3322d6ab385780436
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 16:48:47 2017 +0200

    Write error log into the build dir

commit 7bd80a6952bbcef1bbd6e446964285731d898b8e
Merge: acadf54 64c2ac9
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 00:20:01 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Fix deps path recognition
      add deps package command
      reset errorlevel before tool run, set the current on exit

commit acadf54f1576aa81c25613a0121898675777edf7
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 22:40:12 2017 +0200

    Rework the server up routines a bit

commit 6948d0fb99f8f9d52c26d8a6f20aa8de5869b878
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 17:48:48 2017 +0200

    Increase/add startup timeouts

commit d494d3cec28072eb0bf50c5a778a36ec4e86e7ce
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 14:09:59 2017 +0200

    Add redirect URL to the stats

commit 1172928f360b6363bc559c176a3557a821c0e478
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 13:54:33 2017 +0200

    Fix warning

commit ec37bbca6d5ca5a42b4287cceb1decbe414a103a
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 13:48:15 2017 +0200

    Improve Mediawiki URL generation

commit 66280db114863ef221fb33a04734e227adadbb0b
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 13:41:51 2017 +0200

    Add more info about non 200 codes

commit 2fcab615715922ff83076e82ba24a7389a1f1d09
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 11:33:36 2017 +0200

    Set error_log = syslog

commit 0ac29c3d5dd3f5e929970f59c647100c4432ebab
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 11:09:44 2017 +0200

    Back to 8 max children

commit 67cced2a4220b8af809e8ebe7d508c84b7c85735
Author: Anatol Belski <ab@php.net>
Date:   Sat Aug 19 11:07:46 2017 +0200

    set explicit timeouts

commit 491abac200aae57f379be0393f7ed7b061af8089
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 23:43:22 2017 +0200

    Use generated config, if available

commit 2ae06304248b0b149a5a3201d619e7edcd330455
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 23:07:01 2017 +0200

    Revert "extend is initialized check"

    This reverts commit f365e530cff348bb656a9dd8c887143e9e0559a5.

commit f365e530cff348bb656a9dd8c887143e9e0559a5
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 12:36:16 2017 +0200

    extend is initialized check

commit 7905dccad49fc55c26e5d07a8f731c2e21bbbf26
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 10:50:25 2017 +0200

    lower default number of fcgi processes

commit 5df59c3a3f0f8c46520bf498e52bfe76506d54d9
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 02:59:08 2017 +0200

    some new keys can also be added to the env

commit 5ee2edca7a94a60505924ae998cc647fd332916a
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 00:15:27 2017 +0200

    fix image name

commit b3cadbd2061f0e9c10516fed07e03d6999bd9117
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 23:35:51 2017 +0200

    deactivate joomla training case for now

commit 23baf7931c3d08b6e95d8425cb197365429a0e7e
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 22:21:58 2017 +0200

    fix mysql availability for the external tools

commit 77f6519255bb6ab57bf9c5014ba7a3b8ea394eb2
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 20:25:12 2017 +0200

    fix path separator

commit 63bc4d515256f2bcd68a32b87b5dd095575e49b2
Merge: e4a51d6 eae3aab
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 18:19:40 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      revert the deps path reset part and sync

commit e4a51d67c417829ae78ae5c90fa3b7f9936bdb96
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:35:32 2017 +0200

    should be fixed by the previous commit

commit 77e0b65e218710baf456633f880564a8ab50fd37
Merge: 104f57c e7e92b3
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:34:33 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      yet more path recognition variant

commit 104f57c232e5f2689a6e7d10415fcb5e95d96003
Merge: aa62653 d158c3c
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:19:31 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      add possibility to reevaluate the deps path

commit aa62653187c356897cdd9f0967b8c6553e5e0ba9
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:19:08 2017 +0200

    reevaluate deps path

commit 5b54583f7a512a5d774907d9693950b6c82a5241
Merge: 295d9ca 69fb69f
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 15:34:07 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      no realpath needed

commit 295d9cad733884a9588a1949078f5fd4f61e98a6
Merge: c2e9b1d aee165f
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 14:06:43 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      refactor dependency dir recognition

commit c2e9b1d1645e6ff7f54ec308b82292ced9080e56
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 11:19:12 2017 +0200

    rephrase

commit d7f8be2b954fa3eddca8ba0ad7947230c2cdf45a
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 11:14:50 2017 +0200

    some PGO doc

commit 16434a8aff4fcff85d68ecb431691f6d50be5f6e
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 10:37:45 2017 +0200

    add template script for opening required ports

commit 4aa9cba50a9f44fa021f1680ddbfe8073aa4cfcc
Merge: d7f5e8c 0223331
Author: Anatol Belski <ab@php.net>
Date:   Sat Aug 12 14:36:23 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      upgrade vswhere
      extend .gitignore

commit d7f5e8cc6cd331814fe5650bb5a7a97e41453e73
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 9 22:58:34 2017 +0200

    add ready mode for pgo

commit 8b64fb7f5e43b488c8628440df28698443908e9b
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 7 18:30:19 2017 +0200

    add 7.3 inis

commit 323188a802abcb1a32fb5a14a64ba52fa51cfd19
Merge: e18835e 7d72596
Author: Anatol Belski <ab@php.net>
Date:   Wed Jul 26 17:04:27 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      back to dev
      prepare 2.0.9
      sync with eol change

commit e18835e055ecc41818d1b1bfac7ba7705153a515
Author: Anatol Belski <ab@php.net>
Date:   Sun Jul 23 21:00:44 2017 +0200

    EOL changes

commit 678173e046b0beac56182a31e16354c0533b0a50
Merge: dd2527b eaa6ff5
Author: Anatol Belski <ab@php.net>
Date:   Sun Jul 23 20:58:32 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      add more file types for eol mitigation
      extend redme

commit dd2527b248798bcbff1b0f675b40015069c07d4f
Merge: 0922158 0319dc0
Author: Anatol Belski <ab@php.net>
Date:   Sun Jul 23 20:43:00 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      add gitattributes
      add comment

commit 092215893e3480ec693fba67702b9b65d494402c
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:52:24 2017 +0200

    improve url extraction

commit f650e1e7ebef4d43fa0e9e9cc9054baa090be90b
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:35:45 2017 +0200

    add basic mediawiki support

commit 538fe384e708a3f5194eed153a933e73cd4278e8
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:34:49 2017 +0200

    comment out PostgreSQL for now

commit 84e7a027d366ada3aafe3d9cf988660d0060c73a
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:31:43 2017 +0200

    comment out debug piece

commit e096090f17f14a681a32285ad5ffdda45ca91cc8
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 18:19:25 2017 +0200

    some reworks, mainly to improve postgres handling

commit 263786e8300fa1a4f8b3ee1ab3a21d8bd8802dac
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 11:12:28 2017 +0200

    enable pgsql ext for training

commit 4471fc5dfce5a9c75b818540c8a0772a4445c4f7
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 09:42:18 2017 +0200

    remove debug output

commit fd1467850919d003d4e66beb18d4005ceb212774
Merge: ccb26ee 55fddef
Author: Anatol Belski <ab@php.net>
Date:   Thu Jul 20 23:55:26 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      back to dev
      prepare 2.0.8

commit ccb26eebeed1c637c4ce603bc68ff45aaebc680e
Author: Anatol Belski <ab@php.net>
Date:   Thu Jul 20 18:15:11 2017 +0200

    add Joomla support

commit 9e71002f9017c2ebc9509b75c3798207e18e8e87
Author: Anatol Belski <ab@php.net>
Date:   Thu Jul 20 15:56:23 2017 +0200

    add basic composer fetch

commit 21956c5dca4a7c0f99cc15cf3457b5d9722d3c6f
Merge: 63f3263 8e3d439
Author: Anatol Belski <ab@php.net>
Date:   Tue Jul 18 20:35:31 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Support also preview releases
      upgrade bundled php
      back to dev
      prepare 2.0.7
      improve branch name guessing
      fixed option handling, thanks Kalle
      upgrade to vswhere 2.0.2
      extend deps update comment
      task.exe commen

commit 63f3263b2b129d1de4e83533f9b6d2b8eb1712e4
Merge: a0d8788 9e5e7e6
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 16 02:43:11 2017 +0200

    Merge branch 'master' into pgo_integration

commit a0d8788233633231ac1f7a5208284edacbb7ec6b
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 17:48:25 2017 +0200

    change default pg port, add some util methods

commit 661fe8992638c4af92793f8464038ac5dc044f5b
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 14:24:14 2017 +0200

    basic Postgres stuff

commit 7b3b0b96184cfe89c052292ef6e71aa05f96b548
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 14:23:34 2017 +0200

    remove dead code

commit 00670fdc005244c26ff9248857de264e344d9348
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 13:23:34 2017 +0200

    respect mariadb port, user creation is still to go if needed

commit b73f3eda83152e526bd6eaba8a3c3470a696b300
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 13:22:28 2017 +0200

    fix wrong merge

commit 6ca5d948e173956618bd541a2daf26e92bfe7748
Merge: 7d8bd88 99efb73
Author: Anatol Belski <ab@php.net>
Date:   Mon Jun 5 21:01:47 2017 +0200

    Merge branch 'master' into pgo_integration

commit 7d8bd88b029b3c05e072f77d2c287bee51f58672
Author: Anatol Belski <ab@php.net>
Date:   Mon Jun 5 13:39:33 2017 +0200

    forcibly propagate errorlevel

commit d2f3bb5245640e3f5a1b44530be3ed2df775ee53
Author: Anatol Belski <ab@php.net>
Date:   Mon Jun 5 13:38:16 2017 +0200

    forcibly propagate errorlevel

commit 0d5c0dc71ce4dd4b4578d490cccd28ebcd830de3
Author: Anatol Belski <ab@php.net>
Date:   Sat Jun 3 10:21:41 2017 +0200

    hide warning

commit 276c3cdd6214d974e294bf177f601ebf8d33f92d
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:46:56 2017 +0200

    remove existing dir before renaming

commit 2bc6e2324de50d43c74e48e30a6a0799f892aa22
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:35:32 2017 +0200

    fix reinit and clean init mode

commit 8527d983cf43b32d5efbf3674cebfb62302e4e7a
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:11:48 2017 +0200

    lower wp-cli version, seems there are issues with 1.2.0

commit fbad30b92e9d498e2fadee4ac38f99c0ab825a17
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:07:30 2017 +0200

    more compact code using a worker for init preparation

commit 83c24e93f6ceaa2d55f070e92713a8b91362e27f
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 17:19:59 2017 +0200

    allow rename dest dir when unzip

commit 81f0d6f24db4af54a161e1cd1b258618cea47809
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 21:44:02 2017 +0200

    don't keep merged pgc files

commit 8b9fd7ee7c2437645755b69560630399e15ac31e
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 21:21:23 2017 +0200

    fix wptest dir name

commit e29b5bb7d89f7da5f71eabfa2c3f06e7a514a059
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 21:20:36 2017 +0200

    ups

commit d18fba6792e23f17fac605d1ea432fc3048e862d
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 20:56:27 2017 +0200

    full implement wordpress init/train

commit 2a5000c399f799ed3c56bbd61305c4fd7a395c09
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 19:43:45 2017 +0200

    more fine clean

commit 7b736c135fa3c1131d0a2f53b2de477f77904f12
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 19:12:06 2017 +0200

    cleanup the pgc files before training starts

commit 63ea1c84425ba56df8fd0f789a884bfe6c859018
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 18:03:48 2017 +0200

    Implement training with PGO data dumping

commit 57b529646182344f7962a966347957da97d6c934
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 16:12:02 2017 +0200

    fix nginx init

commit 76aee824bb21f2298bb484aa6d60d5448cb4c985
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 15:55:55 2017 +0200

    next round refactor already done stuff

commit c8ce3afec0225028375c81fcc40a13ba7e0cd23a
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 00:05:15 2017 +0200

    start to implement training, improve templating

commit 61837905abb18bef86ad56bc4b52132c0cd1e3a6
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 19:35:44 2017 +0200

    almost finished setting up the symfony demo case

commit 1a3c9ebfd428ba21a65dd9e2be34c6b3a2f88960
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 16:22:04 2017 +0200

    remove debug out

    remove echos

commit 70d937c18bae8b7baf4ed313c47f2001e8e43e1d
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 16:21:13 2017 +0200

    start with training case implementation

commit 414fd54cfe8b14500eb7663396cc4157d1c52d1d
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:34:27 2017 +0200

    improvements to db interface

commit e0b1a86dbed3377682b4057542809d343a3598e8
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:33:38 2017 +0200

    ignore *.swp

commit c9aa8cad0888d82753b32d6a4c0457b67bd2e81b
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:18:08 2017 +0200

    implement force, fix NGINX config

commit 6c61d14140e45552dabd45a13fad1844c9e84329
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:17:46 2017 +0200

    remove not required file

commit c1bec7398c130a288549a90ef1ed26bfe9d3fcc0
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 13:46:31 2017 +0200

    basic PHP setup and usable CLI

commit d2227d31799030334b0a635ea1fb0474dea23416
Author: Anatol Belski <ab@php.net>
Date:   Fri May 26 13:27:23 2017 +0200

    add license

commit f96743bd1a89d068c49954ac5e46a8e302e44d85
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 18:31:20 2017 +0200

    basic init/up/down for MariaDB and some bug fixes

commit 14bf57ceab9586e365ad43de2250629249f8a198
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 17:39:22 2017 +0200

    improve config handling, more on nginx management

commit 8c407130658ac56b2d360b664c35bb95f5ffb5ec
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 17:29:09 2017 +0200

    switch to json for internal conf

commit e744887d307e8e65a2666fd9baf1b94ae33f1e12
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 17:28:04 2017 +0200

    extend gitignore

commit 88dd8f0cd5928b25e8af919b61168056946b64b5
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 16:10:57 2017 +0200

    basic nginx init routines and expand on config

commit 0c4f660904370b3aa9d002118a8b923ffaa132e7
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 20:46:04 2017 +0200

    add unzip to fileops and some more refactoring

commit f1aeb9ac43dd817c0ac208714943162117329e3f
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 19:17:01 2017 +0200

    group ns

commit f92a4b45a58f6969fdb139278157ff5556cc9879
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 19:15:56 2017 +0200

    use curl for fetches

commit 09e01d62cb74aba6158943e0418c94f09e136248
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 17:58:55 2017 +0200

    fix branch name recognition when no cli opt passed

commit 50c54bdacc0bc0383ed5feb592bfc16092ffb173
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 17:22:50 2017 +0200

    simplify

commit 5e293210c678729c67c75ea4112f12832375bdf3
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 17:14:13 2017 +0200

    yet basic PGO stuff
2018-01-12 18:02:50 +01:00
Anatol Belski
7a054e9e6d Revert "Upgrade vswhere"
This reverts commit a6f819dd75.
2018-01-12 18:01:22 +01:00
Anatol Belski
a6f819dd75 Upgrade vswhere 2018-01-10 17:45:18 +01:00
Anatol Belski
b8b32aaa27 Avoid each() 2018-01-10 17:34:19 +01:00
Anatol Belski
dbeb065486 Use spl_autoload_register() 2018-01-10 17:33:51 +01:00
Anatol Belski
c2880591f3 Mention ConEmu 2017-11-24 10:34:24 +01:00
Anatol Belski
6911eacb83 Update example cmd 2017-11-24 10:32:22 +01:00
姚文强
218f23ab93 fix typo (#23)
Thanks :)
2017-11-24 10:31:19 +01:00
114 changed files with 26262 additions and 14436 deletions

4
.gitignore vendored
View File

@@ -20,3 +20,7 @@ oracle
#pgo-build
#rmtools*
phpsdk-local.bat
pgo/work
!pgo/tpl/php
!lib/php/libsdk/SDK/Build/PGO/Server/PHP
*.swp

18
LICENSE
View File

@@ -1,9 +1,9 @@
Copyright 2017 Anatol Belski
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright 2017-2018 Anatol Belski
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,6 +1,6 @@
# PHP SDK
PHP SDK is a tool kit for Windows PHP builds
PHP SDK is a tool kit for Windows PHP builds.
# License
@@ -8,7 +8,7 @@ The PHP SDK itself and the SDK own tools and code are licensed under the BSD 2-C
# Overview
The PHP SDK 2.0 is compatible with PHP 7.0 and above. The compatibility with [older versions](http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip "php-sdk-binary-tools-20110915.zip") is kept, also available from the [legacy branch](https://github.com/OSTC/php-sdk-binary-tools/tree/legacy). The toolset was significantly revamped. Newer tools are now available, better workflows are now possible. The toolset consists on a mix of the hand written scripts, selected MSYS2 parts and standalone programs.
The PHP SDK 2.0+ is compatible with PHP 7.0 and above. The compatibility with [older versions](http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip "php-sdk-binary-tools-20110915.zip") is kept, also available from the [legacy branch](https://github.com/Microsoft/php-sdk-binary-tools/tree/legacy). The toolset was significantly revamped. Newer tools are now available, better workflows are now possible. The toolset consists on a mix of the hand written scripts, selected MSYS2 parts and standalone programs.
# Requirements
@@ -26,8 +26,9 @@ All the tools included are either scripts or 32-bit binaries. They are therefore
- starter scripts, named phpsdk-&lt;crt&gt;-&lt;arch&gt;.bat
- `phpsdk_buildtree` - initialize the development filesystem structure
- `phpsdk_deps` - handle dependency libraries
- `phpsdk_version` - show SDK version
- `phpsdk_dllmap` - create a JSON listing of DLLs contained in zip files
- `phpsdk_pgo` - run PGO training
- `phpsdk_version` - show SDK version
- `task.exe` - wrapper to hide the given command line
## Other tools
@@ -47,6 +48,7 @@ These are not included with the PHP SDK, but might be useful. While Visual C++ i
- `Cppcheck` - used for static analysis
- `clang` - useful for experimental builds and for static analysis
- `ICC` - useful for experimental builds
- `ConEmu` - console emulator with tabs and more
# Usage
@@ -58,33 +60,33 @@ It is not required to hold the source in the PHP SDK directory. It could be usef
## Basic usage example
- `git clone https://github.com/OSTC/php-sdk-binary-tools.git c:\php-sdk`
- `git clone https://github.com/Microsoft/php-sdk-binary-tools.git c:\php-sdk`
- `cd c:\php-sdk`
- `git checkout php-sdk-2.0.12` or later
- invoke `phpsdk-vc15-x64.bat`
- `phpsdk_buildtree phpmaster`
- `git clone https://github.com/php/php-src.git && cd php-src`, or fetch a zipball
- `phpsdk_deps --update --branch master`, use PHP-X.Y for a non master branch
- `phpsdk_deps --update --branch master`, use `phpsdk_deps --update --branch X.Y` for a non master branch
- do the build, eg. `buildconf && configure --enable-cli && nmake`
More extensive documentation can be found on the [wiki](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2 "PHP wiki page").
## The old way
- `git clone https://github.com/OSTC/php-sdk-binary-tools.git c:\php-sdk`
- `git clone https://github.com/Microsoft/php-sdk-binary-tools.git c:\php-sdk`
- follow the instructions on the PHP [wiki page](https://wiki.php.net/internals/windows/stepbystepbuild "PHP wiki page")
# Customizing
## Custom environment setup
A sript called phpsdk-local.bat has to be put into the PHP SDK root. If present, it will be automatically picked up by the starter script. A template for such a script is included with the PHP SDK. This allows to automatically meet any required preparations, that are not foreseen by the standard PHP SDK startup. Be careful while creating your own phpsdk-local. It's your responsibility to ensure the regular PHP SDK startup isn't broken after phpsdk-local.bat was injected into the startup sequence.
A script called phpsdk-local.bat has to be put into the PHP SDK root. If present, it will be automatically picked up by the starter script. A template for such a script is included with the PHP SDK. This allows to automatically meet any required preparations, that are not foreseen by the standard PHP SDK startup. Be careful while creating your own phpsdk-local. It's your responsibility to ensure the regular PHP SDK startup isn't broken after phpsdk-local.bat was injected into the startup sequence.
## Console emulator integration
The starter scripts can be also easy integrated with the consoles other than standard cmd.exe. For the reference, here's an example ConEmu task
`C:\php-sdk\phpsdk-vc14-x64.bat -cur_console:d:C:\php-sdk\php70\vc14\x64\php-src`
`C:\php-sdk\phpsdk-vc15-x64.bat -cur_console:d:C:\php-sdk\php72\vc15\x64\php-src`
## Unattended builds
@@ -106,6 +108,37 @@ If the PHP SDK is kept as a git checkout, merely what is needed instead is to gi
The SDK tools are based on the KISS principle and should be kept so. Basic tools are implemented as simple batch script. The minimalistic `PHP` is available for internal SDK purposes. It can be used, if more complexity is required. A suitable PHP binary is bound with the PHP SDK. If you have an idea for some useful tool or workflow, please open a ticket or PR, so it can be discussed, implemented and added to the SDK. By contributing an implementation, you should also accept the SDK license.
# PGO
As of the version 2.1.0, the SDK includes a tool for the [PGO](https://docs.microsoft.com/en-us/cpp/build/reference/profile-guided-optimizations) optimization. Several training cases are included by default, which are based on the real life opensource applications. The PGO optimization can give an overall speedup up to 30%. The work on adding more training scenarios for the widely used opensource apps is ongoing. If you have a training scenario to share, please create a PR to this repo. Any new training cases are thoroughly validated through the extensive performance tests.
## Preparing PGO training environment
- the pgo folder in the SDK root dir contains templates and scenarios for PGO training
- adjust and execute [doc/phpsdk_pgo_prep_elevated.bat.example](doc/phpsdk_pgo_prep_elevated.bat.example) to open ports required for PHP SDK training servers
- run `phpsdk_pgo --init`
## Creating PGO build
- compile PHP configured using `--enable-pgi`
- run `phpsdk_pgo --train`
- run `nmake clean-pgo`
- rebuild PHP `--with-pgo`
## Adding custom PGO training scenario
A custom scenario can be used to produce a custom PHP binary dedicated to an arbitrary application.
The existing training cases can be found in [pgo/cases](pgo/cases). Assumed the case would be named `myapp`, the general steps to setup were
- create the case directory under `pgo/cases/myapp`
- create `pgo/cases/myapp/phpsdk_pgo.json` with the necessary definitions
- create `pgo/cases/myapp/nginx.partial.conf` with a partial NGINX template
- create `pgo/cases/myapp/TrainingCaseHandler.php` with a class as defined in the [interface](lib/php/libsdk/SDK/Build/PGO/Interfaces/TrainingCase.php)
After a training case is implemented and put under `pgo/cases`, the work environment needs to be reinitialized. The tool puts all the training data and necessary applications under `pgo/work`. Rename or remove that directory and rerun `phpsdk_pgo --init`.
To skip a training case, add a file named `inactive` into the case folder.
# Pitfalls
- SDK or PHP sources put into paths including spaces might cause issue.
@@ -115,6 +148,7 @@ The SDK tools are based on the KISS principle and should be kept so. Basic tools
- Tools, based on MSYS2, only accept paths with forward slashes.
- Both Visual C++ toolset and the Windows SDK components have to be installed for the PHP SDK to work properly.
- The VC++ toolset is still requried, even if another compiler, fe. clang, is intended to be used.
- task.exe is not a console application, some systems might not propagate exit code except the batch is explicitly run from `cmd /c`, etc.
- `task.exe` is not a console application, some systems might not propagate exit code except the batch is explicitly run from `cmd /c`, etc.
- `7za` should be prefered over `unzip` and `zip` for compatibility reasons.

View File

@@ -1 +1 @@
2.0.14-dev
2.1.2

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,6 @@
<?php
include dirname(__FILE__) . "/../lib/php/libsdk/autoload.php";
include dirname(__FILE__) . "/../lib/php/autoload.php";
use SDK\{Config, Exception};

14
bin/phpsdk_pgo.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
if "%PHP_SDK_PHP_CMD%"=="" (
call %~dp0phpsdk_setvars.bat
if "!PHP_SDK_PHP_CMD!"=="" (
echo PHP SDK is not setup
exit /b 3
)
)
cmd /c %PHP_SDK_PHP_CMD% %PHP_SDK_BIN_PATH%\phpsdk_pgo.php %*
exit /b %errorlevel%

127
bin/phpsdk_pgo.php Normal file
View File

@@ -0,0 +1,127 @@
<?php
include dirname(__FILE__) . "/../lib/php/autoload.php";
use SDK\Config;
use SDK\Exception;
use SDK\Build\PGO\Controller;
$sopt = "itudhs:fr";
$lopt = array("init", "train", "up", "down", "help", "scenario:", "force", "ready");
$cmd = NULL;
/* TODO For now we simply check the current php build, this could be extended to take arbitrary binaries. */
$deps_root = NULL;
$php_root = NULL;
$scenario = NULL;
$force = false;
try {
$opt = getopt($sopt, $lopt);
foreach ($opt as $name => $val) {
switch ($name) {
case "i":
case "init":
$cmd = "init";
break;
case "ready":
$cmd = "check_init";
break;
case "t":
case "train":
$cmd = "train";
break;
case "u":
case "up":
$cmd = "up";
break;
case "d":
case "down":
$cmd = "down";
break;
case "s":
case "scenario":
$scenario = $val;
break;
case "f":
case "force":
$force = true;
break;
case "h": case "help":
usage(0);
break;
}
}
if (NULL === $cmd) {
usage();
}
$deps_root = Config::getDepsLocalPath();
if ("check_init" != $cmd) {
/* XXX Need these checks for more safety, as long as the dist zipballs are not supported. */
if (!file_exists("Makefile")) {
throw new Exception("Makefile not found. Arbitrary php snapshots are not supported yet, switch to the php source dir.");
}
if (preg_match(",BUILD_DIR=(.+),", file_get_contents("Makefile"), $m)) {
$php_root = trim($m[1]);
}
if (!$php_root || !file_exists($php_root)) {
throw new Exception("Invalid php root dir encountered '$php_root'.");
}
}
$controller = new Controller($cmd, $scenario);
$controller->handle($force);
if ("check_init" == $cmd) {
/* 0 for success, fail otherwise. */
$ret = ($controller->isInitialized() === false);
exit((int)$ret);
}
/*$env = getenv();
$env["PATH"] = $deps_root . DIRECTORY_SEPARATOR . "bin;" . $env["PATH"];
$php = $php_root . DIRECTORY_SEPARATOR . "php.exe";
$php = $php_root . DIRECTORY_SEPARATOR . "php.exe";*/
} catch (Throwable $e) {
throw $e;
exit(3);
}
function usage(int $code = -1)
{
echo "PHP SDK PGO training tool.", PHP_EOL;
echo "Usage: ", PHP_EOL, PHP_EOL;
echo "Commands:", PHP_EOL;
echo " -i --init Initialize training environment.", PHP_EOL;
echo " -t --train Run training. This involves startup, training and shutdown.", PHP_EOL;
echo " -u --up Startup training environment.", PHP_EOL;
echo " -d --down Shutdown training environment.", PHP_EOL;
echo " -f --force Force requested operation. Not every option can be forced.", PHP_EOL;
echo " -s --scenario Run training with a specified scenario.", PHP_EOL;
/*echo " -p --php-root PHP binary to train.", PHP_EOL;*/
$code = -1 == $code ? 0 : $code;
exit($code);
}
function msg(string $s, int $code = 0) {
echo $s, PHP_EOL;
exit($code);
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@@ -26,7 +26,7 @@ if ""=="%PHP_SDK_VC:~2%" (
goto malformed_vc_string
)
set /a TMP_CHK=%PHP_SDK_VC:~2%
if 11 gtr %TMP_CHK% (
if 14 gtr %TMP_CHK% (
if "0"=="%TMP_CHK%" (
if not "0"=="%PHP_SDK_VC:~2%" (
set TMP_CHK=
@@ -34,7 +34,7 @@ if 11 gtr %TMP_CHK% (
)
)
echo At least vc11 is required
echo At least vc14 is required
set PHP_SDK_VC=
set TMP_CHK=
goto out_error

View File

@@ -17,9 +17,5 @@ set PHP_SDK_PHP_CMD=%PHP_SDK_BIN_PATH%\php\do_php.bat
set PATH=%PHP_SDK_BIN_PATH%;%PHP_SDK_MSYS2_PATH%;%PATH%
if 11 equ %PHP_SDK_VC_NUM% (
set "PATH=%PHP_SDK_ROOT_PATH%\compat5\bin;%PATH%"
)
exit /b %errorlevel%

Binary file not shown.

Binary file not shown.

View File

@@ -1,761 +0,0 @@
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
#line 3 "bison.simple"
/* This file comes from bison-1.27. */
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
/* This is the parser code that is written into each bison parser
when the %semantic_parser declaration is not specified in the grammar.
It was written by Richard Stallman by simplifying the hairy parser
used when %semantic_parser is specified. */
#ifndef YYSTACK_USE_ALLOCA
#ifdef alloca
#define YYSTACK_USE_ALLOCA
#else /* alloca not defined */
#ifdef __GNUC__
#define YYSTACK_USE_ALLOCA
#define alloca __builtin_alloca
#else /* not GNU C. */
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
#define YYSTACK_USE_ALLOCA
#include <alloca.h>
#else /* not sparc */
/* We think this test detects Watcom and Microsoft C. */
/* This used to test MSDOS, but that is a bad idea
since that symbol is in the user namespace. */
#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
#if 0 /* No need for malloc.h, which pollutes the namespace;
instead, just don't use alloca. */
#include <malloc.h>
#endif
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
/* I don't know what this was needed for, but it pollutes the namespace.
So I turned it off. rms, 2 May 1997. */
/* #include <malloc.h> */
#pragma alloca
#define YYSTACK_USE_ALLOCA
#else /* not MSDOS, or __TURBOC__, or _AIX */
#if 0
#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
and on HPUX 10. Eventually we can turn this on. */
#define YYSTACK_USE_ALLOCA
#define alloca __builtin_alloca
#endif /* __hpux */
#endif
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
#endif /* not sparc */
#endif /* not GNU C */
#endif /* alloca not defined */
#endif /* YYSTACK_USE_ALLOCA not defined */
#ifdef YYSTACK_USE_ALLOCA
#define YYSTACK_ALLOC alloca
#else
#define YYSTACK_ALLOC malloc
#endif
/* Note: there must be only one dollar sign in this file.
It is replaced by the list of actions, each action
as one case of the switch. */
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY -2
#define YYEOF 0
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
#define YYERROR goto yyerrlab1
/* Like YYERROR except do call yyerror.
This remains here temporarily to ease the
transition to the new meaning of YYERROR, for GCC.
Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
#define YYRECOVERING() (!!yyerrstatus)
#define YYBACKUP(token, value) \
do \
if (yychar == YYEMPTY && yylen == 1) \
{ yychar = (token), yylval = (value); \
yychar1 = YYTRANSLATE (yychar); \
YYPOPSTACK; \
goto yybackup; \
} \
else \
{ yyerror ("syntax error: cannot back up"); YYERROR; } \
while (0)
#define YYTERROR 1
#define YYERRCODE 256
#ifndef YYPURE
#define YYLEX yylex()
#endif
#ifdef YYPURE
#ifdef YYLSP_NEEDED
#ifdef YYLEX_PARAM
#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
#else
#define YYLEX yylex(&yylval, &yylloc)
#endif
#else /* not YYLSP_NEEDED */
#ifdef YYLEX_PARAM
#define YYLEX yylex(&yylval, YYLEX_PARAM)
#else
#define YYLEX yylex(&yylval)
#endif
#endif /* not YYLSP_NEEDED */
#endif
/* If nonreentrant, generate the variables here */
#ifndef YYPURE
int yychar; /* the lookahead symbol */
YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
#ifdef YYLSP_NEEDED
YYLTYPE yylloc; /* location data for the lookahead */
/* symbol */
#endif
int yynerrs; /* number of parse errors so far */
#endif /* not YYPURE */
#if YYDEBUG != 0
int yydebug; /* nonzero means print parse trace */
/* Since this is uninitialized, it does not stop multiple parsers
from coexisting. */
#endif
/* YYINITDEPTH indicates the initial size of the parser's stacks */
#ifndef YYINITDEPTH
#define YYINITDEPTH 200
#endif
/* YYMAXDEPTH is the maximum size the stacks can grow to
(effective only if the built-in stack extension method is used). */
#if YYMAXDEPTH == 0
#undef YYMAXDEPTH
#endif
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif
/* Define __yy_memcpy. Note that the size argument
should be passed with type unsigned int, because that is what the non-GCC
definitions require. With GCC, __builtin_memcpy takes an arg
of type size_t, but it can handle unsigned int. */
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
#else /* not GNU C or C++ */
#ifndef __cplusplus
/* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */
static void
__yy_memcpy (to, from, count)
char *to;
char *from;
unsigned int count;
{
register char *f = from;
register char *t = to;
register int i = count;
while (i-- > 0)
*t++ = *f++;
}
#else /* __cplusplus */
/* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */
static void
__yy_memcpy (char *to, char *from, unsigned int count)
{
register char *t = to;
register char *f = from;
register int i = count;
while (i-- > 0)
*t++ = *f++;
}
#endif
#endif
#line 216 "bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
It should actually point to an object.
Grammar actions can access the variable by casting it
to the proper pointer type. */
#ifdef YYPARSE_PARAM
#ifdef __cplusplus
#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
#define YYPARSE_PARAM_DECL
#else /* not __cplusplus */
#define YYPARSE_PARAM_ARG YYPARSE_PARAM
#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
#endif /* not __cplusplus */
#else /* not YYPARSE_PARAM */
#define YYPARSE_PARAM_ARG
#define YYPARSE_PARAM_DECL
#endif /* not YYPARSE_PARAM */
/* Prevent warning if -Wstrict-prototypes. */
#ifdef __GNUC__
#ifdef YYPARSE_PARAM
int yyparse (void *);
#else
int yyparse (void);
#endif
#endif
int
yyparse(YYPARSE_PARAM_ARG)
YYPARSE_PARAM_DECL
{
register int yystate;
register int yyn;
register short *yyssp;
register YYSTYPE *yyvsp;
int yyerrstatus; /* number of tokens to shift before error messages enabled */
int yychar1 = 0; /* lookahead token as an internal (translated) token number */
short yyssa[YYINITDEPTH]; /* the state stack */
YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
short *yyss = yyssa; /* refer to the stacks thru separate pointers */
YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
#ifdef YYLSP_NEEDED
YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
YYLTYPE *yyls = yylsa;
YYLTYPE *yylsp;
#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
#else
#define YYPOPSTACK (yyvsp--, yyssp--)
#endif
int yystacksize = YYINITDEPTH;
int yyfree_stacks = 0;
#ifdef YYPURE
int yychar;
YYSTYPE yylval;
int yynerrs;
#ifdef YYLSP_NEEDED
YYLTYPE yylloc;
#endif
#endif
YYSTYPE yyval; /* the variable used to return */
/* semantic values from the action */
/* routines */
int yylen;
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Starting parse\n");
#endif
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
yyssp = yyss - 1;
yyvsp = yyvs;
#ifdef YYLSP_NEEDED
yylsp = yyls;
#endif
/* Push a new state, which is found in yystate . */
/* In all cases, when you get here, the value and location stacks
have just been pushed. so pushing a state here evens the stacks. */
yynewstate:
*++yyssp = yystate;
if (yyssp >= yyss + yystacksize - 1)
{
/* Give user a chance to reallocate the stack */
/* Use copies of these so that the &'s don't force the real ones into memory. */
YYSTYPE *yyvs1 = yyvs;
short *yyss1 = yyss;
#ifdef YYLSP_NEEDED
YYLTYPE *yyls1 = yyls;
#endif
/* Get the current used size of the three stacks, in elements. */
int size = yyssp - yyss + 1;
#ifdef yyoverflow
/* Each stack pointer address is followed by the size of
the data in use in that stack, in bytes. */
#ifdef YYLSP_NEEDED
/* This used to be a conditional around just the two extra args,
but that might be undefined if yyoverflow is a macro. */
yyoverflow("parser stack overflow",
&yyss1, size * sizeof (*yyssp),
&yyvs1, size * sizeof (*yyvsp),
&yyls1, size * sizeof (*yylsp),
&yystacksize);
#else
yyoverflow("parser stack overflow",
&yyss1, size * sizeof (*yyssp),
&yyvs1, size * sizeof (*yyvsp),
&yystacksize);
#endif
yyss = yyss1; yyvs = yyvs1;
#ifdef YYLSP_NEEDED
yyls = yyls1;
#endif
#else /* no yyoverflow */
/* Extend the stack our own way. */
if (yystacksize >= YYMAXDEPTH)
{
yyerror("parser stack overflow");
if (yyfree_stacks)
{
free (yyss);
free (yyvs);
#ifdef YYLSP_NEEDED
free (yyls);
#endif
}
return 2;
}
yystacksize *= 2;
if (yystacksize > YYMAXDEPTH)
yystacksize = YYMAXDEPTH;
#ifndef YYSTACK_USE_ALLOCA
yyfree_stacks = 1;
#endif
yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
__yy_memcpy ((char *)yyss, (char *)yyss1,
size * (unsigned int) sizeof (*yyssp));
yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
__yy_memcpy ((char *)yyvs, (char *)yyvs1,
size * (unsigned int) sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
__yy_memcpy ((char *)yyls, (char *)yyls1,
size * (unsigned int) sizeof (*yylsp));
#endif
#endif /* no yyoverflow */
yyssp = yyss + size - 1;
yyvsp = yyvs + size - 1;
#ifdef YYLSP_NEEDED
yylsp = yyls + size - 1;
#endif
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Stack size increased to %d\n", yystacksize);
#endif
if (yyssp >= yyss + yystacksize - 1)
YYABORT;
}
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Entering state %d\n", yystate);
#endif
goto yybackup;
yybackup:
/* Do appropriate processing given the current state. */
/* Read a lookahead token if we need one and don't already have one. */
/* yyresume: */
/* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
if (yyn == YYFLAG)
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
/* yychar is either YYEMPTY or YYEOF
or a valid token in external form. */
if (yychar == YYEMPTY)
{
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Reading a token: ");
#endif
yychar = YYLEX;
}
/* Convert token to internal form (in yychar1) for indexing tables with */
if (yychar <= 0) /* This means end of input. */
{
yychar1 = 0;
yychar = YYEOF; /* Don't call YYLEX any more */
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Now at end of input.\n");
#endif
}
else
{
yychar1 = YYTRANSLATE(yychar);
#if YYDEBUG != 0
if (yydebug)
{
fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
/* Give the individual parser a way to print the precise meaning
of a token, for further debugging info. */
#ifdef YYPRINT
YYPRINT (stderr, yychar, yylval);
#endif
fprintf (stderr, ")\n");
}
#endif
}
yyn += yychar1;
if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
goto yydefault;
yyn = yytable[yyn];
/* yyn is what to do for this token type in this state.
Negative => reduce, -yyn is rule number.
Positive => shift, yyn is new state.
New state is final state => don't bother to shift,
just return success.
0, or most negative number => error. */
if (yyn < 0)
{
if (yyn == YYFLAG)
goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
else if (yyn == 0)
goto yyerrlab;
if (yyn == YYFINAL)
YYACCEPT;
/* Shift the lookahead token. */
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
#endif
/* Discard the token being shifted unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
*++yyvsp = yylval;
#ifdef YYLSP_NEEDED
*++yylsp = yylloc;
#endif
/* count tokens shifted since error; after three, turn off error status. */
if (yyerrstatus) yyerrstatus--;
yystate = yyn;
goto yynewstate;
/* Do the default action for the current state. */
yydefault:
yyn = yydefact[yystate];
if (yyn == 0)
goto yyerrlab;
/* Do a reduction. yyn is the number of a rule to reduce with. */
yyreduce:
yylen = yyr2[yyn];
if (yylen > 0)
yyval = yyvsp[1-yylen]; /* implement default value of the action */
#if YYDEBUG != 0
if (yydebug)
{
int i;
fprintf (stderr, "Reducing via rule %d (line %d), ",
yyn, yyrline[yyn]);
/* Print the symbols being reduced, and their result. */
for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
fprintf (stderr, "%s ", yytname[yyrhs[i]]);
fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
}
#endif
$ /* the action file gets copied in in place of this dollarsign */
#line 542 "bison.simple"
yyvsp -= yylen;
yyssp -= yylen;
#ifdef YYLSP_NEEDED
yylsp -= yylen;
#endif
#if YYDEBUG != 0
if (yydebug)
{
short *ssp1 = yyss - 1;
fprintf (stderr, "state stack now");
while (ssp1 != yyssp)
fprintf (stderr, " %d", *++ssp1);
fprintf (stderr, "\n");
}
#endif
*++yyvsp = yyval;
#ifdef YYLSP_NEEDED
yylsp++;
if (yylen == 0)
{
yylsp->first_line = yylloc.first_line;
yylsp->first_column = yylloc.first_column;
yylsp->last_line = (yylsp-1)->last_line;
yylsp->last_column = (yylsp-1)->last_column;
yylsp->text = 0;
}
else
{
yylsp->last_line = (yylsp+yylen-1)->last_line;
yylsp->last_column = (yylsp+yylen-1)->last_column;
}
#endif
/* Now "shift" the result of the reduction.
Determine what state that goes to,
based on the state we popped back to
and the rule number reduced by. */
yyn = yyr1[yyn];
yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
yystate = yytable[yystate];
else
yystate = yydefgoto[yyn - YYNTBASE];
goto yynewstate;
yyerrlab: /* here on detecting error */
if (! yyerrstatus)
/* If not already recovering from an error, report this error. */
{
++yynerrs;
#ifdef YYERROR_VERBOSE
yyn = yypact[yystate];
if (yyn > YYFLAG && yyn < YYLAST)
{
int size = 0;
char *msg;
int x, count;
count = 0;
/* Start X at -yyn if nec to avoid negative indexes in yycheck. */
for (x = (yyn < 0 ? -yyn : 0);
x < (sizeof(yytname) / sizeof(char *)); x++)
if (yycheck[x + yyn] == x)
size += strlen(yytname[x]) + 15, count++;
msg = (char *) malloc(size + 15);
if (msg != 0)
{
strcpy(msg, "parse error");
if (count < 5)
{
count = 0;
for (x = (yyn < 0 ? -yyn : 0);
x < (sizeof(yytname) / sizeof(char *)); x++)
if (yycheck[x + yyn] == x)
{
strcat(msg, count == 0 ? ", expecting `" : " or `");
strcat(msg, yytname[x]);
strcat(msg, "'");
count++;
}
}
yyerror(msg);
free(msg);
}
else
yyerror ("parse error; also virtual memory exceeded");
}
else
#endif /* YYERROR_VERBOSE */
yyerror("parse error");
}
goto yyerrlab1;
yyerrlab1: /* here on error raised explicitly by an action */
if (yyerrstatus == 3)
{
/* if just tried and failed to reuse lookahead token after an error, discard it. */
/* return failure if at end of input */
if (yychar == YYEOF)
YYABORT;
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
#endif
yychar = YYEMPTY;
}
/* Else will try to reuse lookahead token
after shifting the error token. */
yyerrstatus = 3; /* Each real token shifted decrements this */
goto yyerrhandle;
yyerrdefault: /* current state does not do anything special for the error token. */
#if 0
/* This is wrong; only states that explicitly want error tokens
should shift them. */
yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
if (yyn) goto yydefault;
#endif
yyerrpop: /* pop the current state because it cannot handle the error token */
if (yyssp == yyss) YYABORT;
yyvsp--;
yystate = *--yyssp;
#ifdef YYLSP_NEEDED
yylsp--;
#endif
#if YYDEBUG != 0
if (yydebug)
{
short *ssp1 = yyss - 1;
fprintf (stderr, "Error: state stack now");
while (ssp1 != yyssp)
fprintf (stderr, " %d", *++ssp1);
fprintf (stderr, "\n");
}
#endif
yyerrhandle:
yyn = yypact[yystate];
if (yyn == YYFLAG)
goto yyerrdefault;
yyn += YYTERROR;
if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
goto yyerrdefault;
yyn = yytable[yyn];
if (yyn < 0)
{
if (yyn == YYFLAG)
goto yyerrpop;
yyn = -yyn;
goto yyreduce;
}
else if (yyn == 0)
goto yyerrpop;
if (yyn == YYFINAL)
YYACCEPT;
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Shifting error token, ");
#endif
*++yyvsp = yylval;
#ifdef YYLSP_NEEDED
*++yylsp = yylloc;
#endif
yystate = yyn;
goto yynewstate;
yyacceptlab:
/* YYACCEPT comes here. */
if (yyfree_stacks)
{
free (yyss);
free (yyvs);
#ifdef YYLSP_NEEDED
free (yyls);
#endif
}
return 0;
yyabortlab:
/* YYABORT comes here. */
if (yyfree_stacks)
{
free (yyss);
free (yyvs);
#ifdef YYLSP_NEEDED
free (yyls);
#endif
}
return 1;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,48 +0,0 @@
# bison-i18n.m4 serial 2
dnl Copyright (C) 2005-2006 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Bruno Haible.
dnl Support for internationalization of bison-generated parsers.
dnl BISON_I18N
dnl should be used in configure.ac, after AM_GNU_GETTEXT. If USE_NLS is yes, it
dnl sets BISON_LOCALEDIR to indicate where to find the bison-runtime.mo files
dnl and defines YYENABLE_NLS if there are bison-runtime.mo files at all.
AC_DEFUN([BISON_I18N],
[
if test -z "$USE_NLS"; then
echo "The BISON-I18N macro is used without being preceded by AM-GNU-GETTEXT." 1>&2
exit 1
fi
BISON_LOCALEDIR=
BISON_USE_NLS=no
if test "$USE_NLS" = yes; then
dnl Determine bison's localedir.
dnl AC_PROG_YACC sets the YACC variable; other macros set the BISON variable.
dnl But even is YACC is called "yacc", it may be a script that invokes bison
dnl and accepts the --print-localedir option.
dnl YACC's default value is empty; BISON's default value is :.
if (${YACC-${BISON-:}} --print-localedir) >/dev/null 2>&1; then
BISON_LOCALEDIR=`${YACC-${BISON-:}} --print-localedir`
fi
AC_SUBST([BISON_LOCALEDIR])
if test -n "$BISON_LOCALEDIR"; then
dnl There is no need to enable internationalization if the user doesn't
dnl want message catalogs. So look at the language/locale names for
dnl which the user wants message catalogs. This is $LINGUAS. If unset
dnl or empty, he wants all of them.
USER_LINGUAS="${LINGUAS-%UNSET%}"
if test -n "$USER_LINGUAS"; then
BISON_USE_NLS=yes
fi
fi
fi
if test $BISON_USE_NLS = yes; then
AC_DEFINE([YYENABLE_NLS], 1,
[Define to 1 to internationalize bison runtime messages.])
fi
])

View File

@@ -1,70 +0,0 @@
-*- outline -*-
This directory contains data needed by Bison.
* Skeletons
Bison skeletons: the general shapes of the different parser kinds,
that are specialized for specific grammars by the bison program.
Currently, the supported skeletons are:
- yacc.c
It used to be named bison.simple: it corresponds to C Yacc
compatible LALR(1) parsers.
- lalr1.cc
Produces a C++ parser class.
- lalr1.java
Produces a Java parser class.
- glr.c
A Generalized LR C parser based on Bison's LALR(1) tables.
- glr.cc
A Generalized LR C++ parser. Actually a C++ wrapper around glr.c.
These skeletons are the only ones supported by the Bison team.
Because the interface between skeletons and the bison program is not
finished, *we are not bound to it*. In particular, Bison is not
mature enough for us to consider that ``foreign skeletons'' are
supported.
* m4sugar
This directory contains M4sugar, sort of an extended library for M4,
which is used by Bison to instantiate the skeletons.
* xslt
This directory contains XSLT programs that transform Bison's XML output
into various formats.
- bison.xsl
A library of routines used by the other XSLT programs.
- xml2dot.xsl
Conversion into GraphViz's dot format.
- xml2text.xsl
Conversion into text.
- xml2xhtml.xsl
Conversion into XHTML.
-----
Copyright (C) 2002, 2008 Free Software Foundation, Inc.
This file is part of GNU Bison.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@@ -1,556 +0,0 @@
-*- Autoconf -*-
# Language-independent M4 Macros for Bison.
# Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008 Free Software Foundation,
# Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
## ---------------- ##
## Identification. ##
## ---------------- ##
# b4_copyright(TITLE, YEARS)
# --------------------------
m4_define([b4_copyright],
[b4_comment([A Bison parser, made by GNU Bison b4_version.])
b4_comment([$1
m4_text_wrap([Copyright (C) $2 Free Software Foundation, Inc.], [ ])
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.])
b4_comment([As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison.])])
## ---------------- ##
## Error handling. ##
## ---------------- ##
# The following error handling macros print error directives that should not
# become arguments of other macro invocations since they would likely then be
# mangled. Thus, they print to stdout directly.
# b4_cat(TEXT)
# ------------
# Write TEXT to stdout. Precede the final newline with an @ so that it's
# escaped. For example:
#
# b4_cat([[@complain(invalid input@)]])
m4_define([b4_cat],
[m4_syscmd([cat <<'_m4eof'
]m4_bpatsubst(m4_dquote($1), [_m4eof], [_m4@`eof])[@
_m4eof
])dnl
m4_if(m4_sysval, [0], [], [m4_fatal([$0: cannot write to stdout])])])
# b4_error(KIND, FORMAT, [ARG1], [ARG2], ...)
# -------------------------------------------
# Write @KIND(FORMAT@,ARG1@,ARG2@,...@) to stdout.
#
# For example:
#
# b4_error([[warn]], [[invalid value for `%s': %s]], [[foo]], [[3]])
m4_define([b4_error],
[b4_cat([[@]$1[(]$2[]]dnl
[m4_if([$#], [2], [],
[m4_foreach([b4_arg],
m4_dquote(m4_shift(m4_shift($@))),
[[@,]b4_arg])])[@)]])])
# b4_error_at(KIND, START, END, FORMAT, [ARG1], [ARG2], ...)
# ----------------------------------------------------------
# Write @KIND_at(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
#
# For example:
#
# b4_error_at([[complain]], [[input.y:2.3]], [[input.y:5.4]],
# [[invalid %s]], [[foo]])
m4_define([b4_error_at],
[b4_cat([[@]$1[_at(]$2[@,]$3[@,]$4[]]dnl
[m4_if([$#], [4], [],
[m4_foreach([b4_arg],
m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))),
[[@,]b4_arg])])[@)]])])
# b4_warn(FORMAT, [ARG1], [ARG2], ...)
# ------------------------------------
# Write @warn(FORMAT@,ARG1@,ARG2@,...@) to stdout.
#
# For example:
#
# b4_warn([[invalid value for `%s': %s]], [[foo]], [[3]])
#
# As a simple test suite, this:
#
# m4_divert(-1)
# m4_define([asdf], [ASDF])
# m4_define([fsa], [FSA])
# m4_define([fdsa], [FDSA])
# b4_warn([[[asdf), asdf]]], [[[fsa), fsa]]], [[[fdsa), fdsa]]])
# b4_warn([[asdf), asdf]], [[fsa), fsa]], [[fdsa), fdsa]])
# b4_warn()
# b4_warn(1)
# b4_warn(1, 2)
#
# Should produce this without newlines:
#
# @warn([asdf), asdf]@,[fsa), fsa]@,[fdsa), fdsa]@)
# @warn(asdf), asdf@,fsa), fsa@,fdsa), fdsa@)
# @warn(@)
# @warn(1@)
# @warn(1@,2@)
m4_define([b4_warn],
[b4_error([[warn]], $@)])
# b4_warn_at(START, END, FORMAT, [ARG1], [ARG2], ...)
# ---------------------------------------------------
# Write @warn(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
#
# For example:
#
# b4_warn_at([[input.y:2.3]], [[input.y:5.4]], [[invalid %s]], [[foo]])
m4_define([b4_warn_at],
[b4_error_at([[warn]], $@)])
# b4_complain(FORMAT, [ARG1], [ARG2], ...)
# ----------------------------------------
# Write @complain(FORMAT@,ARG1@,ARG2@,...@) to stdout.
#
# See b4_warn example.
m4_define([b4_complain],
[b4_error([[complain]], $@)])
# b4_complain_at(START, END, FORMAT, [ARG1], [ARG2], ...)
# -------------------------------------------------------
# Write @complain(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
#
# See b4_warn_at example.
m4_define([b4_complain_at],
[b4_error_at([[complain]], $@)])
# b4_fatal(FORMAT, [ARG1], [ARG2], ...)
# -------------------------------------
# Write @fatal(FORMAT@,ARG1@,ARG2@,...@) to stdout and exit.
#
# See b4_warn example.
m4_define([b4_fatal],
[b4_error([[fatal]], $@)dnl
m4_exit(1)])
# b4_fatal_at(START, END, FORMAT, [ARG1], [ARG2], ...)
# ----------------------------------------------------
# Write @fatal(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout and exit.
#
# See b4_warn_at example.
m4_define([b4_fatal_at],
[b4_error_at([[fatal]], $@)dnl
m4_exit(1)])
## ---------------- ##
## Default values. ##
## ---------------- ##
# m4_define_default([b4_lex_param], []) dnl breaks other skeletons
m4_define_default([b4_pre_prologue], [])
m4_define_default([b4_post_prologue], [])
m4_define_default([b4_epilogue], [])
m4_define_default([b4_parse_param], [])
# The initial column and line.
m4_define_default([b4_location_initial_column], [1])
m4_define_default([b4_location_initial_line], [1])
## ------------ ##
## Data Types. ##
## ------------ ##
# b4_ints_in(INT1, INT2, LOW, HIGH)
# ---------------------------------
# Return 1 iff both INT1 and INT2 are in [LOW, HIGH], 0 otherwise.
m4_define([b4_ints_in],
[m4_eval([$3 <= $1 && $1 <= $4 && $3 <= $2 && $2 <= $4])])
## ------------------ ##
## Decoding options. ##
## ------------------ ##
# b4_flag_if(FLAG, IF-TRUE, IF-FALSE)
# -----------------------------------
# Run IF-TRUE if b4_FLAG_flag is 1, IF-FALSE if FLAG is 0, otherwise fail.
m4_define([b4_flag_if],
[m4_case(b4_$1_flag,
[0], [$3],
[1], [$2],
[m4_fatal([invalid $1 value: ]$1)])])
# b4_define_flag_if(FLAG)
# -----------------------
# Define "b4_FLAG_if(IF-TRUE, IF-FALSE)" that depends on the
# value of the Boolean FLAG.
m4_define([b4_define_flag_if],
[_b4_define_flag_if($[1], $[2], [$1])])
# _b4_define_flag_if($1, $2, FLAG)
# --------------------------------
# This macro works around the impossibility to define macros
# inside macros, because issuing `[$1]' is not possible in M4 :(.
# This sucks hard, GNU M4 should really provide M5 like $$1.
m4_define([_b4_define_flag_if],
[m4_if([$1$2], $[1]$[2], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl
m4_define([b4_$3_if],
[b4_flag_if([$3], [$1], [$2])])])
# b4_FLAG_if(IF-TRUE, IF-FALSE)
# -----------------------------
# Expand IF-TRUE, if FLAG is true, IF-FALSE otherwise.
b4_define_flag_if([defines]) # Whether headers are requested.
b4_define_flag_if([error_verbose]) # Whether error are verbose.
b4_define_flag_if([glr]) # Whether a GLR parser is requested.
b4_define_flag_if([locations]) # Whether locations are tracked.
b4_define_flag_if([nondeterministic]) # Whether conflicts should be handled.
b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated.
## ------------------------- ##
## Assigning token numbers. ##
## ------------------------- ##
## ----------- ##
## Synclines. ##
## ----------- ##
# b4_basename(NAME)
# -----------------
# Similar to POSIX basename; the differences don't matter here.
# Beware that NAME is not evaluated.
m4_define([b4_basename],
[m4_bpatsubst([$1], [^.*/\([^/]+\)/*$], [\1])])
# b4_syncline(LINE, FILE)
# -----------------------
m4_define([b4_syncline],
[b4_flag_if([synclines], [
b4_sync_end([__line__], [b4_basename(m4_quote(__file__))])
b4_sync_start([$1], [$2])])])
m4_define([b4_sync_end], [b4_comment([Line $1 of $2])])
m4_define([b4_sync_start], [b4_comment([Line $1 of $2])])
# b4_user_code(USER-CODE)
# -----------------------
# Emit code from the user, ending it with synclines.
m4_define([b4_user_code],
[$1
b4_syncline([@oline@], [@ofile@])])
# b4_define_user_code(MACRO)
# --------------------------
# From b4_MACRO, build b4_user_MACRO that includes the synclines.
m4_define([b4_define_user_code],
[m4_define([b4_user_$1],
[b4_user_code([b4_$1])])])
# b4_user_actions
# b4_user_initial_action
# b4_user_post_prologue
# b4_user_pre_prologue
# b4_user_stype
# ----------------------
# Macros that issue user code, ending with synclines.
b4_define_user_code([actions])
b4_define_user_code([initial_action])
b4_define_user_code([post_prologue])
b4_define_user_code([pre_prologue])
b4_define_user_code([stype])
# b4_check_user_names(WHAT, USER-LIST, BISON-NAMESPACE)
# --------------------------------------------------------
# Warn if any name of type WHAT is used by the user (as recorded in USER-LIST)
# but is not used by Bison (as recorded by macros in the namespace
# BISON-NAMESPACE).
#
# USER-LIST must expand to a list specifying all grammar occurrences of all
# names of type WHAT. Each item in the list must be a triplet specifying one
# occurrence: name, start boundary, and end boundary. Empty string names are
# fine. An empty list is fine.
#
# For example, to define b4_foo_user_names to be used for USER-LIST with three
# name occurrences and with correct quoting:
#
# m4_define([b4_foo_user_names],
# [[[[[[bar]], [[parser.y:1.7]], [[parser.y:1.16]]]],
# [[[[bar]], [[parser.y:5.7]], [[parser.y:5.16]]]],
# [[[[baz]], [[parser.y:8.7]], [[parser.y:8.16]]]]]])
#
# The macro BISON-NAMESPACE(bar) must be defined iff the name bar of type WHAT
# is used by Bison (in the front-end or in the skeleton). Empty string names
# are fine, but it would be ugly for Bison to actually use one.
#
# For example, to use b4_foo_bison_names for BISON-NAMESPACE and define that
# the names bar and baz are used by Bison:
#
# m4_define([b4_foo_bison_names(bar)])
# m4_define([b4_foo_bison_names(baz)])
#
# To invoke b4_check_user_names with TYPE foo, with USER-LIST
# b4_foo_user_names, with BISON-NAMESPACE b4_foo_bison_names, and with correct
# quoting:
#
# b4_check_user_names([[foo]], [b4_foo_user_names],
# [[b4_foo_bison_names]])
m4_define([b4_check_user_names],
[m4_foreach([b4_occurrence], $2,
[m4_pushdef([b4_occurrence], b4_occurrence)dnl
m4_pushdef([b4_user_name], m4_car(b4_occurrence))dnl
m4_pushdef([b4_start], m4_car(m4_shift(b4_occurrence)))dnl
m4_pushdef([b4_end], m4_shift(m4_shift(b4_occurrence)))dnl
m4_ifndef($3[(]m4_quote(b4_user_name)[)],
[b4_warn_at([b4_start], [b4_end],
[[%s `%s' is not used]],
[$1], [b4_user_name])])[]dnl
m4_popdef([b4_occurrence])dnl
m4_popdef([b4_user_name])dnl
m4_popdef([b4_start])dnl
m4_popdef([b4_end])dnl
])])
# b4_percent_define_get(VARIABLE)
# -------------------------------
# Mimic muscle_percent_define_get in ../src/muscle_tab.h exactly. That is, if
# the %define variable VARIABLE is defined, emit its value. Also, record
# Bison's usage of VARIABLE by defining
# b4_percent_define_bison_variables(VARIABLE).
#
# For example:
#
# b4_percent_define_get([[foo]])
m4_define([b4_percent_define_get],
[m4_define([b4_percent_define_bison_variables(]$1[)])dnl
m4_ifdef([b4_percent_define(]$1[)], [m4_indir([b4_percent_define(]$1[)])])])
# b4_percent_define_get_loc(VARIABLE)
# -----------------------------------
# Mimic muscle_percent_define_get_loc in ../src/muscle_tab.h exactly. That is,
# if the %define variable VARIABLE is undefined, complain fatally since that's
# a Bison or skeleton error. Otherwise, return its definition location in a
# form approriate for the first two arguments of b4_warn_at, b4_complain_at, or
# b4_fatal_at. Don't record this as a Bison usage of VARIABLE as there's no
# reason to suspect that the user-supplied value has yet influenced the output.
#
# For example:
#
# b4_complain_at(b4_percent_define_get_loc([[foo]]), [[invalid foo]])
m4_define([b4_percent_define_get_loc],
[m4_ifdef([b4_percent_define_loc(]$1[)],
[m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl
b4_loc[]dnl
m4_popdef([b4_loc])],
[b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_get_loc]], [$1])])])
# b4_percent_define_get_syncline(VARIABLE)
# ----------------------------------------
# Mimic muscle_percent_define_get_syncline in ../src/muscle_tab.h exactly.
# That is, if the %define variable VARIABLE is undefined, complain fatally
# since that's a Bison or skeleton error. Otherwise, return its definition
# location as a b4_syncline invocation. Don't record this as a Bison usage of
# VARIABLE as there's no reason to suspect that the user-supplied value has yet
# influenced the output.
#
# For example:
#
# b4_percent_define_get_syncline([[foo]])
m4_define([b4_percent_define_get_syncline],
[m4_ifdef([b4_percent_define_syncline(]$1[)],
[m4_indir([b4_percent_define_syncline(]$1[)])],
[b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_get_syncline]], [$1])])])
# b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE])
# ------------------------------------------------------
# Mimic muscle_percent_define_ifdef in ../src/muscle_tab.h exactly. That is,
# if the %define variable VARIABLE is defined, expand IF-TRUE, else expand
# IF-FALSE. Also, record Bison's usage of VARIABLE by defining
# b4_percent_define_bison_variables(VARIABLE).
#
# For example:
#
# b4_percent_define_ifdef([[foo]], [[it's defined]], [[it's undefined]])
m4_define([b4_percent_define_ifdef],
[m4_ifdef([b4_percent_define(]$1[)],
[m4_define([b4_percent_define_bison_variables(]$1[)])$2],
[$3])])
# b4_percent_define_flag_if(VARIABLE, IF-TRUE, [IF-FALSE])
# --------------------------------------------------------
# Mimic muscle_percent_define_flag_if in ../src/muscle_tab.h exactly. That is,
# if the %define variable VARIABLE is defined to "" or "true", expand IF-TRUE.
# If it is defined to "false", expand IF-FALSE. Complain if it is undefined
# (a Bison or skeleton error since the default value should have been set
# already) or defined to any other value (possibly a user error). Also, record
# Bison's usage of VARIABLE by defining
# b4_percent_define_bison_variables(VARIABLE).
#
# For example:
#
# b4_percent_define_flag_if([[foo]], [[it's true]], [[it's false]])
m4_define([b4_percent_define_flag_if],
[b4_percent_define_ifdef([$1],
[m4_case(b4_percent_define_get([$1]),
[], [$2], [true], [$2], [false], [$3],
[m4_expand_once([b4_complain_at(b4_percent_define_get_loc([$1]),
[[invalid value for %%define Boolean variable `%s']],
[$1])],
[[b4_percent_define_flag_if($1)]])])],
[b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_flag_if]], [$1])])])
# b4_percent_define_default(VARIABLE, DEFAULT)
# --------------------------------------------
# Mimic muscle_percent_define_default in ../src/muscle_tab.h exactly. That is,
# if the %define variable VARIABLE is undefined, set its value to DEFAULT.
# Don't record this as a Bison usage of VARIABLE as there's no reason to
# suspect that the value has yet influenced the output.
#
# For example:
#
# b4_percent_define_default([[foo]], [[default value]])
m4_define([b4_percent_define_default],
[m4_ifndef([b4_percent_define(]$1[)],
[m4_define([b4_percent_define(]$1[)], [$2])dnl
m4_define([b4_percent_define_loc(]$1[)],
[[[[[Bison:b4_percent_define_default]:1.0]], [[[Bison:b4_percent_define_default]:1.0]]]])dnl
m4_define([b4_percent_define_syncline(]$1[)],
[[]b4_syncline(1, [["[Bison:b4_percent_define_default]"]])[
]])])])
# b4_percent_define_check_values(VALUES)
# --------------------------------------
# Mimic muscle_percent_define_check_values in ../src/muscle_tab.h exactly
# except that the VALUES structure is more appropriate for M4. That is, VALUES
# is a list of sublists of strings. For each sublist, the first string is the
# name of a %define variable, and all remaining strings in that sublist are the
# valid values for that variable. Complain if such a variable is undefined (a
# Bison error since the default value should have been set already) or defined
# to any other value (possibly a user error). Don't record this as a Bison
# usage of the variable as there's no reason to suspect that the value has yet
# influenced the output.
#
# For example:
#
# b4_percent_define_check_values([[[[foo]], [[foo-value1]], [[foo-value2]]]],
# [[[[bar]], [[bar-value1]]]])
m4_define([b4_percent_define_check_values],
[m4_foreach([b4_sublist], m4_quote($@),
[_b4_percent_define_check_values(b4_sublist)])])
m4_define([_b4_percent_define_check_values],
[m4_ifdef([b4_percent_define(]$1[)],
[m4_pushdef([b4_good_value], [0])dnl
m4_if($#, 1, [],
[m4_foreach([b4_value], m4_dquote(m4_shift($@)),
[m4_if(m4_indir([b4_percent_define(]$1[)]), b4_value,
[m4_define([b4_good_value], [1])])])])dnl
m4_if(b4_good_value, [0],
[b4_complain_at(b4_percent_define_get_loc([$1]),
[[invalid value for %%define variable `%s': `%s']],
[$1],
m4_dquote(m4_indir([b4_percent_define(]$1[)])))])dnl
m4_popdef([b4_good_value])],
[b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_check_values]], [$1])])])
# b4_percent_code_get([QUALIFIER])
# --------------------------------
# If any %code blocks for QUALIFIER are defined, emit them beginning with a
# comment and ending with synclines and a newline. If QUALIFIER is not
# specified or empty, do this for the unqualified %code blocks. Also, record
# Bison's usage of QUALIFIER (if specified) by defining
# b4_percent_code_bison_qualifiers(QUALIFIER).
#
# For example, to emit any unqualified %code blocks followed by any %code
# blocks for the qualifier foo:
#
# b4_percent_code_get
# b4_percent_code_get([[foo]])
m4_define([b4_percent_code_get],
[m4_pushdef([b4_macro_name], [[b4_percent_code(]$1[)]])dnl
m4_ifval([$1], [m4_define([b4_percent_code_bison_qualifiers(]$1[)])])dnl
m4_ifdef(b4_macro_name,
[b4_comment([m4_if([$#], [0], [[Unqualified %code]],
[["%code ]$1["]])[ blocks.]])
b4_user_code([m4_indir(b4_macro_name)])
])dnl
m4_popdef([b4_macro_name])])
# b4_percent_code_ifdef(QUALIFIER, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------
# If any %code blocks for QUALIFIER (or unqualified %code blocks if
# QUALIFIER is empty) are defined, expand IF-TRUE, else expand IF-FALSE.
# Also, record Bison's usage of QUALIFIER (if specified) by defining
# b4_percent_code_bison_qualifiers(QUALIFIER).
m4_define([b4_percent_code_ifdef],
[m4_ifdef([b4_percent_code(]$1[)],
[m4_ifval([$1], [m4_define([b4_percent_code_bison_qualifiers(]$1[)])])$2],
[$3])])
## ----------------------------------------------------------- ##
## After processing the skeletons, check that all the user's ##
## %define variables and %code qualifiers were used by Bison. ##
## ----------------------------------------------------------- ##
m4_define([b4_check_user_names_wrap],
[m4_ifdef([b4_percent_]$1[_user_]$2[s],
[b4_check_user_names([[%]$1 $2],
[b4_percent_]$1[_user_]$2[s],
[[b4_percent_]$1[_bison_]$2[s]])])])
m4_wrap_lifo([
b4_check_user_names_wrap([[define]], [[variable]])
b4_check_user_names_wrap([[code]], [[qualifier]])
])

View File

@@ -1,25 +0,0 @@
-*- Autoconf -*-
# C++ skeleton dispatching for Bison.
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
b4_glr_if( [m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.cc]])])
b4_nondeterministic_if([m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.cc]])])
m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[lalr1.cc]])
m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"])
m4_include(b4_used_skeleton)

View File

@@ -1,170 +0,0 @@
-*- Autoconf -*-
# C++ skeleton for Bison
# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation,
# Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
m4_include(b4_pkgdatadir/[c.m4])
## ---------------- ##
## Default values. ##
## ---------------- ##
# Default parser class name.
b4_percent_define_default([[parser_class_name]], [[parser]])
b4_percent_define_default([[location_type]], [[location]])
b4_percent_define_default([[filename_type]], [[std::string]])
b4_percent_define_default([[namespace]], m4_defn([b4_prefix]))
b4_percent_define_default([[global_tokens_and_yystype]], [[false]])
b4_percent_define_default([[define_location_comparison]],
[m4_if(b4_percent_define_get([[filename_type]]),
[std::string], [[true]], [[false]])])
## ----------- ##
## Namespace. ##
## ----------- ##
m4_define([b4_namespace_ref], [b4_percent_define_get([[namespace]])])
# Don't permit an empty b4_namespace_ref. Any `::parser::foo' appended to it
# would compile as an absolute reference with `parser' in the global namespace.
# b4_namespace_open would open an anonymous namespace and thus establish
# internal linkage. This would compile. However, it's cryptic, and internal
# linkage for the parser would be specified in all translation units that
# include the header, which is always generated. If we ever need to permit
# internal linkage somehow, surely we can find a cleaner approach.
m4_if(m4_bregexp(b4_namespace_ref, [^[ ]*$]), [-1], [],
[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
[[namespace reference is empty]])])
# Instead of assuming the C++ compiler will do it, Bison should reject any
# invalid b4_namepsace_ref that would be converted to a valid
# b4_namespace_open. The problem is that Bison doesn't always output
# b4_namespace_ref to uncommented code but should reserve the ability to do so
# in future releases without risking breaking any existing user grammars.
# Specifically, don't allow empty names as b4_namespace_open would just convert
# those into anonymous namespaces, and that might tempt some users.
m4_if(m4_bregexp(b4_namespace_ref, [::[ ]*::]), [-1], [],
[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
[[namespace reference has consecutive "::"]])])
m4_if(m4_bregexp(b4_namespace_ref, [::[ ]*$]), [-1], [],
[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
[[namespace reference has a trailing "::"]])])
m4_define([b4_namespace_open],
[b4_user_code([b4_percent_define_get_syncline([[namespace]])
[namespace ]m4_bpatsubst(m4_dquote(m4_bpatsubst(m4_dquote(b4_namespace_ref),
[^\(.\)[ ]*::], [\1])),
[::], [ { namespace ])[ {]])])
m4_define([b4_namespace_close],
[b4_user_code([b4_percent_define_get_syncline([[namespace]])
m4_bpatsubst(m4_dquote(m4_bpatsubst(m4_dquote(b4_namespace_ref),
[^\(.\)[ ]*\(::\)?\([^][:]\|:[^][:]\)*],
[\1])),
[::\([^][:]\|:[^][:]\)*], [} ])[} // ]b4_namespace_ref])])
# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
# -----------------------------------------------------
# Output the definition of the tokens as enums.
m4_define([b4_token_enums],
[/* Tokens. */
enum yytokentype {
m4_map_sep([ b4_token_enum], [,
],
[$@])
};
])
## ----------------- ##
## Semantic Values. ##
## ----------------- ##
# b4_lhs_value([TYPE])
# --------------------
# Expansion of $<TYPE>$.
m4_define([b4_lhs_value],
[(yyval[]m4_ifval([$1], [.$1]))])
# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
# --------------------------------------
# Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
# symbols on RHS.
m4_define([b4_rhs_value],
[(yysemantic_stack_@{($1) - ($2)@}m4_ifval([$3], [.$3]))])
# b4_lhs_location()
# -----------------
# Expansion of @$.
m4_define([b4_lhs_location],
[(yyloc)])
# b4_rhs_location(RULE-LENGTH, NUM)
# ---------------------------------
# Expansion of @NUM, where the current rule has RULE-LENGTH symbols
# on RHS.
m4_define([b4_rhs_location],
[(yylocation_stack_@{($1) - ($2)@})])
# b4_parse_param_decl
# -------------------
# Extra formal arguments of the constructor.
# Change the parameter names from "foo" into "foo_yyarg", so that
# there is no collision bw the user chosen attribute name, and the
# argument name in the constructor.
m4_define([b4_parse_param_decl],
[m4_ifset([b4_parse_param],
[m4_map_sep([b4_parse_param_decl_1], [, ], [b4_parse_param])])])
m4_define([b4_parse_param_decl_1],
[$1_yyarg])
# b4_parse_param_cons
# -------------------
# Extra initialisations of the constructor.
m4_define([b4_parse_param_cons],
[m4_ifset([b4_parse_param],
[
b4_cc_constructor_calls(b4_parse_param)])])
m4_define([b4_cc_constructor_calls],
[m4_map_sep([b4_cc_constructor_call], [,
], [$@])])
m4_define([b4_cc_constructor_call],
[$2 ($2_yyarg)])
# b4_parse_param_vars
# -------------------
# Extra instance variables.
m4_define([b4_parse_param_vars],
[m4_ifset([b4_parse_param],
[
/* User arguments. */
b4_cc_var_decls(b4_parse_param)])])
m4_define([b4_cc_var_decls],
[m4_map_sep([b4_cc_var_decl], [
], [$@])])
m4_define([b4_cc_var_decl],
[ $1;])

View File

@@ -1,25 +0,0 @@
-*- Autoconf -*-
# C skeleton dispatching for Bison.
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
b4_glr_if( [m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.c]])])
b4_nondeterministic_if([m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.c]])])
m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[yacc.c]])
m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"])
m4_include(b4_used_skeleton)

View File

@@ -1,477 +0,0 @@
-*- Autoconf -*-
# C M4 Macros for Bison.
# Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008 Free Software
# Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
## ---------------- ##
## Identification. ##
## ---------------- ##
# b4_comment(TEXT)
# ----------------
m4_define([b4_comment], [/* m4_bpatsubst([$1], [
], [
]) */])
# b4_identification
# -----------------
# Depends on individual skeletons to define b4_pure_flag, b4_push_flag, or
# b4_pull_flag if they use the values of the %define variables api.pure or
# api.push_pull.
m4_define([b4_identification],
[[/* Identify Bison output. */
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "]b4_version["
/* Skeleton name. */
#define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[
/* Pure parsers. */
#define YYPURE ]b4_pure_flag])[]m4_ifdef([b4_push_flag], [[
/* Push parsers. */
#define YYPUSH ]b4_push_flag])[]m4_ifdef([b4_pull_flag], [[
/* Pull parsers. */
#define YYPULL ]b4_pull_flag])[
/* Using locations. */
#define YYLSP_NEEDED ]b4_locations_flag[
]])
## ---------------- ##
## Default values. ##
## ---------------- ##
# If the %union is not named, its name is YYSTYPE.
m4_define_default([b4_union_name], [YYSTYPE])
# If the %name-prefix is not given, it is yy.
m4_define_default([b4_prefix], [yy])
## ------------------------ ##
## Pure/impure interfaces. ##
## ------------------------ ##
# b4_user_args
# ------------
m4_define([b4_user_args],
[m4_ifset([b4_parse_param], [, b4_c_args(b4_parse_param)])])
# b4_parse_param
# --------------
# If defined, b4_parse_param arrives double quoted, but below we prefer
# it to be single quoted.
m4_define([b4_parse_param],
b4_parse_param)
# b4_parse_param_for(DECL, FORMAL, BODY)
# ---------------------------------------
# Iterate over the user parameters, binding the declaration to DECL,
# the formal name to FORMAL, and evaluating the BODY.
m4_define([b4_parse_param_for],
[m4_foreach([$1_$2], m4_defn([b4_parse_param]),
[m4_pushdef([$1], m4_unquote(m4_car($1_$2)))dnl
m4_pushdef([$2], m4_shift($1_$2))dnl
$3[]dnl
m4_popdef([$2])dnl
m4_popdef([$1])dnl
])])
# b4_parse_param_use
# ------------------
# `YYUSE' all the parse-params.
m4_define([b4_parse_param_use],
[b4_parse_param_for([Decl], [Formal], [ YYUSE (Formal);
])dnl
])
## ------------ ##
## Data Types. ##
## ------------ ##
# b4_int_type(MIN, MAX)
# ---------------------
# Return the smallest int type able to handle numbers ranging from
# MIN to MAX (included).
m4_define([b4_int_type],
[m4_if(b4_ints_in($@, [0], [255]), [1], [unsigned char],
b4_ints_in($@, [-128], [127]), [1], [signed char],
b4_ints_in($@, [0], [65535]), [1], [unsigned short int],
b4_ints_in($@, [-32768], [32767]), [1], [short int],
m4_eval([0 <= $1]), [1], [unsigned int],
[int])])
# b4_int_type_for(NAME)
# ---------------------
# Return the smallest int type able to handle numbers ranging from
# `NAME_min' to `NAME_max' (included).
m4_define([b4_int_type_for],
[b4_int_type($1_min, $1_max)])
## ---------##
## Values. ##
## ---------##
# b4_null
---------
# Return a null pointer constant. NULL infringes on the user name
# space in C, so use 0 rather than NULL.
m4_define([b4_null], [0])
## ------------------------- ##
## Assigning token numbers. ##
## ------------------------- ##
# b4_token_define(TOKEN-NAME, TOKEN-NUMBER)
# -----------------------------------------
# Output the definition of this token as #define.
m4_define([b4_token_define],
[#define $1 $2
])
# b4_token_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
# -------------------------------------------------------
# Output the definition of the tokens (if there are) as #defines.
m4_define([b4_token_defines],
[m4_if([$#$1], [1], [],
[/* Tokens. */
m4_map([b4_token_define], [$@])])
])
# b4_token_enum(TOKEN-NAME, TOKEN-NUMBER)
# ---------------------------------------
# Output the definition of this token as an enum.
m4_define([b4_token_enum],
[$1 = $2])
# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
# -----------------------------------------------------
# Output the definition of the tokens (if there are) as enums.
m4_define([b4_token_enums],
[m4_if([$#$1], [1], [],
[/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
m4_map_sep([ b4_token_enum], [,
],
[$@])
};
#endif
])])
# b4_token_enums_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
# -------------------------------------------------------------
# Output the definition of the tokens (if there are any) as enums and, if POSIX
# Yacc is enabled, as #defines.
m4_define([b4_token_enums_defines],
[b4_token_enums($@)b4_yacc_if([b4_token_defines($@)], [])
])
## --------------------------------------------- ##
## Defining C functions in both K&R and ANSI-C. ##
## --------------------------------------------- ##
# b4_modern_c
# -----------
# A predicate useful in #if to determine whether C is ancient or modern.
#
# If __STDC__ is defined, the compiler is modern. IBM xlc 7.0 when run
# as 'cc' doesn't define __STDC__ (or __STDC_VERSION__) for pedantic
# reasons, but it defines __C99__FUNC__ so check that as well.
# Microsoft C normally doesn't define these macros, but it defines _MSC_VER.
# Consider a C++ compiler to be modern if it defines __cplusplus.
#
m4_define([b4_c_modern],
[[(defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)]])
# b4_c_function_def(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
# ----------------------------------------------------------
# Declare the function NAME.
m4_define([b4_c_function_def],
[#if b4_c_modern
b4_c_ansi_function_def($@)
#else
$2
$1 (b4_c_knr_formal_names(m4_shift2($@)))
b4_c_knr_formal_decls(m4_shift2($@))
#endif[]dnl
])
# b4_c_ansi_function_def(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
# ---------------------------------------------------------------
# Declare the function NAME in ANSI.
m4_define([b4_c_ansi_function_def],
[$2
$1 (b4_c_ansi_formals(m4_shift2($@)))[]dnl
])
# b4_c_ansi_formals([DECL1, NAME1], ...)
# --------------------------------------
# Output the arguments ANSI-C definition.
m4_define([b4_c_ansi_formals],
[m4_if([$#], [0], [void],
[$#$1], [1], [void],
[m4_map_sep([b4_c_ansi_formal], [, ], [$@])])])
m4_define([b4_c_ansi_formal],
[$1])
# b4_c_knr_formal_names([DECL1, NAME1], ...)
# ------------------------------------------
# Output the argument names.
m4_define([b4_c_knr_formal_names],
[m4_map_sep([b4_c_knr_formal_name], [, ], [$@])])
m4_define([b4_c_knr_formal_name],
[$2])
# b4_c_knr_formal_decls([DECL1, NAME1], ...)
# ------------------------------------------
# Output the K&R argument declarations.
m4_define([b4_c_knr_formal_decls],
[m4_map_sep([b4_c_knr_formal_decl],
[
],
[$@])])
m4_define([b4_c_knr_formal_decl],
[ $1;])
## ------------------------------------------------------------ ##
## Declaring (prototyping) C functions in both K&R and ANSI-C. ##
## ------------------------------------------------------------ ##
# b4_c_function_decl(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
# -----------------------------------------------------------
# Declare the function NAME.
m4_define([b4_c_function_decl],
[#if defined __STDC__ || defined __cplusplus
b4_c_ansi_function_decl($@)
#else
$2 $1 ();
#endif[]dnl
])
# b4_c_ansi_function_decl(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
# ----------------------------------------------------------------
# Declare the function NAME.
m4_define([b4_c_ansi_function_decl],
[$2 $1 (b4_c_ansi_formals(m4_shift2($@)));[]dnl
])
## --------------------- ##
## Calling C functions. ##
## --------------------- ##
# b4_c_function_call(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
# -----------------------------------------------------------
# Call the function NAME with arguments NAME1, NAME2 etc.
m4_define([b4_c_function_call],
[$1 (b4_c_args(m4_shift2($@)))[]dnl
])
# b4_c_args([DECL1, NAME1], ...)
# ------------------------------
# Output the arguments NAME1, NAME2...
m4_define([b4_c_args],
[m4_map_sep([b4_c_arg], [, ], [$@])])
m4_define([b4_c_arg],
[$2])
## ----------- ##
## Synclines. ##
## ----------- ##
# b4_sync_start(LINE, FILE)
# -----------------------
m4_define([b4_sync_start], [[#]line $1 $2])
## -------------- ##
## User actions. ##
## -------------- ##
# b4_case(LABEL, STATEMENTS)
# --------------------------
m4_define([b4_case],
[ case $1:
$2
break;])
# b4_symbol_actions(FILENAME, LINENO,
# SYMBOL-TAG, SYMBOL-NUM,
# SYMBOL-ACTION, SYMBOL-TYPENAME)
# -------------------------------------------------
m4_define([b4_symbol_actions],
[m4_pushdef([b4_dollar_dollar],
[m4_ifval([$6], [(yyvaluep->$6)], [(*yyvaluep)])])dnl
m4_pushdef([b4_at_dollar], [(*yylocationp)])dnl
case $4: /* $3 */
b4_syncline([$2], [$1])
$5;
b4_syncline([@oline@], [@ofile@])
break;
m4_popdef([b4_at_dollar])dnl
m4_popdef([b4_dollar_dollar])dnl
])
# b4_yydestruct_generate(FUNCTION-DECLARATOR)
# -------------------------------------------
# Generate the "yydestruct" function, which declaration is issued using
# FUNCTION-DECLARATOR, which may be "b4_c_ansi_function_def" for ISO C
# or "b4_c_function_def" for K&R.
m4_define_default([b4_yydestruct_generate],
[[/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
/*ARGSUSED*/
]$1([yydestruct],
[static void],
[[const char *yymsg], [yymsg]],
[[int yytype], [yytype]],
[[YYSTYPE *yyvaluep], [yyvaluep]][]dnl
b4_locations_if( [, [[YYLTYPE *yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
YYUSE (yyvaluep);
]b4_locations_if([ YYUSE (yylocationp);
])dnl
b4_parse_param_use[]dnl
[
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
switch (yytype)
{
]m4_map([b4_symbol_actions], m4_defn([b4_symbol_destructors]))[
default:
break;
}
}]dnl
])
# b4_yy_symbol_print_generate(FUNCTION-DECLARATOR)
# ------------------------------------------------
# Generate the "yy_symbol_print" function, which declaration is issued using
# FUNCTION-DECLARATOR, which may be "b4_c_ansi_function_def" for ISO C
# or "b4_c_function_def" for K&R.
m4_define_default([b4_yy_symbol_print_generate],
[[
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
/*ARGSUSED*/
]$1([yy_symbol_value_print],
[static void],
[[FILE *yyoutput], [yyoutput]],
[[int yytype], [yytype]],
[[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
if (!yyvaluep)
return;
]b4_locations_if([ YYUSE (yylocationp);
])dnl
b4_parse_param_use[]dnl
[# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# else
YYUSE (yyoutput);
# endif
switch (yytype)
{
]m4_map([b4_symbol_actions], m4_defn([b4_symbol_printers]))dnl
[ default:
break;
}
}
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
]$1([yy_symbol_print],
[static void],
[[FILE *yyoutput], [yyoutput]],
[[int yytype], [yytype]],
[[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
if (yytype < YYNTOKENS)
YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
else
YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
]b4_locations_if([ YY_LOCATION_PRINT (yyoutput, *yylocationp);
YYFPRINTF (yyoutput, ": ");
])dnl
[ yy_symbol_value_print (yyoutput, yytype, yyvaluep]dnl
b4_locations_if([, yylocationp])[]b4_user_args[);
YYFPRINTF (yyoutput, ")");
}]dnl
])

File diff suppressed because it is too large Load Diff

View File

@@ -1,377 +0,0 @@
-*- C -*-
# C++ GLR skeleton for Bison
# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
# Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This skeleton produces a C++ class that encapsulates a C glr parser.
# This is in order to reduce the maintenance burden. The glr.c
# skeleton is clean and pure enough so that there are no real
# problems. The C++ interface is the same as that of lalr1.cc. In
# fact, glr.c can replace yacc.c without the user noticing any
# difference, and similarly for glr.cc replacing lalr1.cc.
#
# The passing of parse-params
#
# The additional arguments are stored as members of the parser
# object, yyparser. The C routines need to carry yyparser
# throughout the C parser; that easy: just let yyparser become an
# additional parse-param. But because the C++ skeleton needs to
# know the "real" original parse-param, we save them
# (b4_parse_param_orig). Note that b4_parse_param is overquoted
# (and c.m4 strips one level of quotes). This is a PITA, and
# explains why there are so many levels of quotes.
#
# The locations
#
# We use location.cc just like lalr1.cc, but because glr.c stores
# the locations in a (C++) union, the position and location classes
# must not have a constructor. Therefore, contrary to lalr1.cc, we
# must not define "b4_location_constructors". As a consequence the
# user must initialize the first positions (in particular the
# filename member).
# We require a pure interface using locations.
m4_define([b4_locations_flag], [1])
m4_define([b4_pure_flag], [1])
# The header is mandatory.
b4_defines_if([],
[b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
m4_include(b4_pkgdatadir/[c++.m4])
m4_include(b4_pkgdatadir/[location.cc])
m4_define([b4_parser_class_name],
[b4_percent_define_get([[parser_class_name]])])
# Save the parse parameters.
m4_define([b4_parse_param_orig], m4_defn([b4_parse_param]))
# b4_yy_symbol_print_generate
# ---------------------------
# Bypass the default implementation to generate the "yy_symbol_print"
# and "yy_symbol_value_print" functions.
m4_define([b4_yy_symbol_print_generate],
[[
/*--------------------.
| Print this symbol. |
`--------------------*/
]b4_c_ansi_function_def([yy_symbol_print],
[static void],
[[FILE *], []],
[[int yytype], [yytype]],
[[const b4_namespace_ref::b4_parser_class_name::semantic_type *yyvaluep],
[yyvaluep]],
[[const b4_namespace_ref::b4_parser_class_name::location_type *yylocationp],
[yylocationp]],
b4_parse_param)[
{
]b4_parse_param_use[]dnl
[ yyparser.yy_symbol_print_ (yytype, yyvaluep]b4_locations_if([, yylocationp])[);
}
]])
# Declare yyerror.
m4_append([b4_post_prologue],
[b4_syncline([@oline@], [@ofile@])
b4_c_ansi_function_decl([yyerror],
[static void],
[[b4_namespace_ref::b4_parser_class_name::location_type *yylocationp], [yylocationp]],
b4_parse_param,
[[const char* msg], [msg]])])
# Define yyerror.
m4_append([b4_epilogue],
[b4_syncline([@oline@], [@ofile@])[
/*------------------.
| Report an error. |
`------------------*/
]b4_c_ansi_function_def([yyerror],
[static void],
[[b4_namespace_ref::b4_parser_class_name::location_type *yylocationp], [yylocationp]],
b4_parse_param,
[[const char* msg], [msg]])[
{
]b4_parse_param_use[]dnl
[ yyparser.error (*yylocationp, msg);
}
]b4_namespace_open[
]dnl In this section, the parse param are the original parse_params.
m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
[ /// Build a parser object.
]b4_parser_class_name::b4_parser_class_name[ (]b4_parse_param_decl[)]m4_ifset([b4_parse_param], [
:])[
#if YYDEBUG
]m4_ifset([b4_parse_param], [ ], [ :])[yydebug_ (false),
yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[
#endif]b4_parse_param_cons[
{
}
]b4_parser_class_name::~b4_parser_class_name[ ()
{
}
int
]b4_parser_class_name[::parse ()
{
return ::yyparse (*this]b4_user_args[);
}
#if YYDEBUG
/*--------------------.
| Print this symbol. |
`--------------------*/
inline void
]b4_parser_class_name[::yy_symbol_value_print_ (int yytype,
const semantic_type* yyvaluep, const location_type* yylocationp)
{
/* Pacify ``unused variable'' warnings. */
YYUSE (yyvaluep);
YYUSE (yylocationp);
switch (yytype)
{
]m4_map([b4_symbol_actions], m4_defn([b4_symbol_printers]))dnl
[ default:
break;
}
}
void
]b4_parser_class_name[::yy_symbol_print_ (int yytype,
const semantic_type* yyvaluep, const location_type* yylocationp)
{
*yycdebug_ << (yytype < YYNTOKENS ? "token" : "nterm")
<< ' ' << yytname[yytype] << " ("
<< *yylocationp << ": ";
yy_symbol_value_print_ (yytype, yyvaluep, yylocationp);
*yycdebug_ << ')';
}
std::ostream&
]b4_parser_class_name[::debug_stream () const
{
return *yycdebug_;
}
void
]b4_parser_class_name[::set_debug_stream (std::ostream& o)
{
yycdebug_ = &o;
}
]b4_parser_class_name[::debug_level_type
]b4_parser_class_name[::debug_level () const
{
return yydebug_;
}
void
]b4_parser_class_name[::set_debug_level (debug_level_type l)
{
yydebug_ = l;
}
#endif
]m4_popdef([b4_parse_param])dnl
b4_namespace_close[
]])
# Let glr.c believe that the user arguments include the parser itself.
m4_ifset([b4_parse_param],
[m4_pushdef([b4_parse_param],
m4_dquote([[[b4_namespace_ref::b4_parser_class_name& yyparser], [[yyparser]]],]
m4_defn([b4_parse_param])))],
[m4_pushdef([b4_parse_param],
[[[[b4_namespace_ref::b4_parser_class_name& yyparser], [[yyparser]]]]])
])
m4_include(b4_pkgdatadir/[glr.c])
m4_popdef([b4_parse_param])
m4_divert_push(0)
@output(b4_spec_defines_file@)
b4_copyright([Skeleton interface for Bison GLR parsers in C++],
[2002, 2003, 2004, 2005, 2006])[
/* C++ GLR parser skeleton written by Akim Demaille. */
#ifndef PARSER_HEADER_H
# define PARSER_HEADER_H
]b4_percent_code_get([[requires]])[
#include <string>
#include <iostream>
/* Using locations. */
#define YYLSP_NEEDED ]b4_locations_flag[
]b4_namespace_open[
class position;
class location;
]b4_namespace_close[
#include "location.hh"
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG ]b4_debug_flag[
#endif
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends
the previous symbol: RHS[0] (always defined). */
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N) \
do \
if (N) \
{ \
(Current).begin = YYRHSLOC (Rhs, 1).begin; \
(Current).end = YYRHSLOC (Rhs, N).end; \
} \
else \
{ \
(Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \
} \
while (/*CONSTCOND*/ 0)
#endif
]b4_namespace_open[
/// A Bison parser.
class ]b4_parser_class_name[
{
public:
/// Symbol semantic values.
#ifndef YYSTYPE
]m4_ifdef([b4_stype],
[ union semantic_type
{
b4_user_stype
};],
[m4_if(b4_tag_seen_flag, 0,
[[ typedef int semantic_type;]],
[[ typedef YYSTYPE semantic_type;]])])[
#else
typedef YYSTYPE semantic_type;
#endif
/// Symbol locations.
typedef ]b4_percent_define_get([[location_type]])[ location_type;
/// Tokens.
struct token
{
]b4_token_enums(b4_tokens)[
};
/// Token type.
typedef token::yytokentype token_type;
/// Build a parser object.
]b4_parser_class_name[ (]b4_parse_param_decl[);
virtual ~]b4_parser_class_name[ ();
/// Parse.
/// \returns 0 iff parsing succeeded.
virtual int parse ();
/// The current debugging stream.
std::ostream& debug_stream () const;
/// Set the current debugging stream.
void set_debug_stream (std::ostream &);
/// Type for debugging levels.
typedef int debug_level_type;
/// The current debugging level.
debug_level_type debug_level () const;
/// Set the current debugging level.
void set_debug_level (debug_level_type l);
private:
public:
/// Report a syntax error.
/// \param loc where the syntax error is found.
/// \param msg a description of the syntax error.
virtual void error (const location_type& loc, const std::string& msg);
private:
#if YYDEBUG
public:
/// \brief Report a symbol value on the debug stream.
/// \param yytype The token type.
/// \param yyvaluep Its semantic value.
/// \param yylocationp Its location.
virtual void yy_symbol_value_print_ (int yytype,
const semantic_type* yyvaluep,
const location_type* yylocationp);
/// \brief Report a symbol on the debug stream.
/// \param yytype The token type.
/// \param yyvaluep Its semantic value.
/// \param yylocationp Its location.
virtual void yy_symbol_print_ (int yytype,
const semantic_type* yyvaluep,
const location_type* yylocationp);
private:
/* Debugging. */
int yydebug_;
std::ostream* yycdebug_;
#endif
/// \brief Reclaim the memory associated to a symbol.
/// \param yymsg Why this token is reclaimed.
/// \param yytype The symbol type.
/// \param yyvaluep Its semantic value.
/// \param yylocationp Its location.
inline void yydestruct_ (const char* yymsg,
int yytype,
semantic_type* yyvaluep,
location_type* yylocationp);
]b4_parse_param_vars[
};
]dnl Redirections for glr.c.
b4_percent_define_flag_if([[global_tokens_and_yystype]],
[b4_token_defines(b4_tokens)])
[
#ifndef YYSTYPE
# define YYSTYPE ]b4_namespace_ref[::]b4_parser_class_name[::semantic_type
#endif
#ifndef YYLTYPE
# define YYLTYPE ]b4_namespace_ref[::]b4_parser_class_name[::location_type
#endif
]b4_namespace_close[
]b4_percent_code_get([[provides]])[]dnl
[#endif /* ! defined PARSER_HEADER_H */]
m4_divert_pop(0)

View File

@@ -1,25 +0,0 @@
-*- Autoconf -*-
# Java skeleton dispatching for Bison.
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
b4_glr_if( [b4_complain([%%glr-parser not supported for Java])])
b4_nondeterministic_if([b4_complain([%%nondeterministic-parser not supported for Java])])
m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[lalr1.java]])
m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"])
m4_include(b4_used_skeleton)

View File

@@ -1,303 +0,0 @@
-*- Autoconf -*-
# Java language support for Bison
# Copyright (C) 2007, 2008 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# b4_comment(TEXT)
# ----------------
m4_define([b4_comment], [/* m4_bpatsubst([$1], [
], [
]) */])
# b4_list2(LIST1, LIST2)
# --------------------------
# Join two lists with a comma if necessary.
m4_define([b4_list2],
[$1[]m4_ifval(m4_quote($1), [m4_ifval(m4_quote($2), [[, ]])])[]$2])
# b4_percent_define_get3(DEF, PRE, POST, NOT)
# -------------------------------------------
# Expand to the value of DEF surrounded by PRE and POST if it's %define'ed,
# otherwise NOT.
m4_define([b4_percent_define_get3],
[m4_ifval(m4_quote(b4_percent_define_get([$1])),
[$2[]b4_percent_define_get([$1])[]$3], [$4])])
# b4_flag_value(BOOLEAN-FLAG)
# ---------------------------
m4_define([b4_flag_value], [b4_flag_if([$1], [true], [false])])
# b4_public_if(TRUE, FALSE)
# -------------------------
b4_percent_define_default([[public]], [[false]])
m4_define([b4_public_if],
[b4_percent_define_flag_if([public], [$1], [$2])])
# b4_abstract_if(TRUE, FALSE)
# ---------------------------
b4_percent_define_default([[abstract]], [[false]])
m4_define([b4_abstract_if],
[b4_percent_define_flag_if([abstract], [$1], [$2])])
# b4_final_if(TRUE, FALSE)
# ---------------------------
b4_percent_define_default([[final]], [[false]])
m4_define([b4_final_if],
[b4_percent_define_flag_if([final], [$1], [$2])])
# b4_strictfp_if(TRUE, FALSE)
# ---------------------------
b4_percent_define_default([[strictfp]], [[false]])
m4_define([b4_strictfp_if],
[b4_percent_define_flag_if([strictfp], [$1], [$2])])
# b4_lexer_if(TRUE, FALSE)
# ------------------------
m4_define([b4_lexer_if],
[b4_percent_code_ifdef([[lexer]], [$1], [$2])])
# b4_identification
# -----------------
m4_define([b4_identification],
[ /** Version number for the Bison executable that generated this parser. */
public static final String bisonVersion = "b4_version";
/** Name of the skeleton that generated this parser. */
public static final String bisonSkeleton = b4_skeleton;
])
## ------------ ##
## Data types. ##
## ------------ ##
# b4_int_type(MIN, MAX)
# ---------------------
# Return the smallest int type able to handle numbers ranging from
# MIN to MAX (included).
m4_define([b4_int_type],
[m4_if(b4_ints_in($@, [-128], [127]), [1], [byte],
b4_ints_in($@, [-32768], [32767]), [1], [short],
[int])])
# b4_int_type_for(NAME)
# ---------------------
# Return the smallest int type able to handle numbers ranging from
# `NAME_min' to `NAME_max' (included).
m4_define([b4_int_type_for],
[b4_int_type($1_min, $1_max)])
# b4_null
# -------
m4_define([b4_null], [null])
## ------------------------- ##
## Assigning token numbers. ##
## ------------------------- ##
# b4_token_enum(TOKEN-NAME, TOKEN-NUMBER)
# ---------------------------------------
# Output the definition of this token as an enum.
m4_define([b4_token_enum],
[ /** Token number, to be returned by the scanner. */
public static final int $1 = $2;
])
# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
# -----------------------------------------------------
# Output the definition of the tokens (if there are) as enums.
m4_define([b4_token_enums],
[m4_if([$#$1], [1], [],
[/* Tokens. */
m4_map([b4_token_enum], [$@])])
])
# b4-case(ID, CODE)
# -----------------
# We need to fool Java's stupid unreachable code detection.
m4_define([b4_case], [ case $1:
if (yyn == $1)
$2;
break;
])
## ---------------- ##
## Default values. ##
## ---------------- ##
m4_define([b4_yystype], [b4_percent_define_get([[stype]])])
b4_percent_define_default([[stype]], [[Object]])])
# %name-prefix
m4_define_default([b4_prefix], [[YY]])
b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])])
m4_define([b4_parser_class_name], [b4_percent_define_get([[parser_class_name]])])
b4_percent_define_default([[lex_throws]], [[java.io.IOException]])])
m4_define([b4_lex_throws], [b4_percent_define_get([[lex_throws]])])
b4_percent_define_default([[throws]], [])])
m4_define([b4_throws], [b4_percent_define_get([[throws]])])
b4_percent_define_default([[location_type]], [Location])])
m4_define([b4_location_type], [b4_percent_define_get([[location_type]])])
b4_percent_define_default([[position_type]], [Position])])
m4_define([b4_position_type], [b4_percent_define_get([[position_type]])])
## ----------------- ##
## Semantic Values. ##
## ----------------- ##
# b4_lhs_value([TYPE])
# --------------------
# Expansion of $<TYPE>$.
m4_define([b4_lhs_value], [yyval])
# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
# --------------------------------------
# Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
# symbols on RHS.
#
# In this simple implementation, %token and %type have class names
# between the angle brackets.
m4_define([b4_rhs_value],
[(m4_ifval($3, [($3)])[](yystack.valueAt ($1-($2))))])
# b4_lhs_location()
# -----------------
# Expansion of @$.
m4_define([b4_lhs_location],
[(yyloc)])
# b4_rhs_location(RULE-LENGTH, NUM)
# ---------------------------------
# Expansion of @NUM, where the current rule has RULE-LENGTH symbols
# on RHS.
m4_define([b4_rhs_location],
[yystack.locationAt ($1-($2))])
# b4_lex_param
# b4_parse_param
# --------------
# If defined, b4_lex_param arrives double quoted, but below we prefer
# it to be single quoted. Same for b4_parse_param.
# TODO: should be in bison.m4
m4_define_default([b4_lex_param], [[]]))
m4_define([b4_lex_param], b4_lex_param))
m4_define([b4_parse_param], b4_parse_param))
# b4_lex_param_decl
# -------------------
# Extra formal arguments of the constructor.
m4_define([b4_lex_param_decl],
[m4_ifset([b4_lex_param],
[b4_remove_comma([$1],
b4_param_decls(b4_lex_param))],
[$1])])
m4_define([b4_param_decls],
[m4_map([b4_param_decl], [$@])])
m4_define([b4_param_decl], [, $1])
m4_define([b4_remove_comma], [m4_ifval(m4_quote($1), [$1, ], [])m4_shift2($@)])
# b4_parse_param_decl
# -------------------
# Extra formal arguments of the constructor.
m4_define([b4_parse_param_decl],
[m4_ifset([b4_parse_param],
[b4_remove_comma([$1],
b4_param_decls(b4_parse_param))],
[$1])])
# b4_lex_param_call
# -------------------
# Delegating the lexer parameters to the lexer constructor.
m4_define([b4_lex_param_call],
[m4_ifset([b4_lex_param],
[b4_remove_comma([$1],
b4_param_calls(b4_lex_param))],
[$1])])
m4_define([b4_param_calls],
[m4_map([b4_param_call], [$@])])
m4_define([b4_param_call], [, $2])
# b4_parse_param_cons
# -------------------
# Extra initialisations of the constructor.
m4_define([b4_parse_param_cons],
[m4_ifset([b4_parse_param],
[b4_constructor_calls(b4_parse_param)])])
m4_define([b4_constructor_calls],
[m4_map([b4_constructor_call], [$@])])
m4_define([b4_constructor_call],
[this.$2 = $2;
])
# b4_parse_param_vars
# -------------------
# Extra instance variables.
m4_define([b4_parse_param_vars],
[m4_ifset([b4_parse_param],
[
/* User arguments. */
b4_var_decls(b4_parse_param)])])
m4_define([b4_var_decls],
[m4_map_sep([b4_var_decl], [
], [$@])])
m4_define([b4_var_decl],
[ protected final $1;])
# b4_maybe_throws(THROWS)
# -----------------------
# Expand to either an empty string or "throws THROWS".
m4_define([b4_maybe_throws],
[m4_ifval($1, [throws $1])])

File diff suppressed because it is too large Load Diff

View File

@@ -1,880 +0,0 @@
# Java skeleton for Bison -*- autoconf -*-
# Copyright (C) 2007, 2008 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
m4_include(b4_pkgdatadir/[java.m4])
b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java], [b4_skeleton])])
m4_ifval(m4_defn([b4_symbol_destructors]),
[b4_fatal([%s: %%destructor does not make sense in Java], [b4_skeleton])],
[])
m4_divert_push(0)dnl
@output(b4_parser_file_name@)
b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
[2007, 2008])
b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);
])[/* First part of user declarations. */
]b4_pre_prologue
b4_percent_code_get([[imports]])
[/**
* A Bison parser, automatically generated from <tt>]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[</tt>.
*
* @@author LALR (1) parser skeleton written by Paolo Bonzini.
*/
]b4_public_if([public ])dnl
b4_abstract_if([abstract ])dnl
b4_final_if([final ])dnl
b4_strictfp_if([strictfp ])dnl
[class ]b4_parser_class_name[]dnl
b4_percent_define_get3([extends], [ extends ])dnl
b4_percent_define_get3([implements], [ implements ])[
{
]b4_identification[
/** True if verbose error messages are enabled. */
public boolean errorVerbose = ]b4_flag_value([error_verbose]);
b4_locations_if([[
/**
* A class defining a pair of positions. Positions, defined by the
* <code>]b4_position_type[</code> class, denote a point in the input.
* Locations represent a part of the input through the beginning
* and ending positions. */
public class ]b4_location_type[ {
/** The first, inclusive, position in the range. */
public ]b4_position_type[ begin;
/** The first position beyond the range. */
public ]b4_position_type[ end;
/**
* Create a <code>]b4_location_type[</code> denoting an empty range located at
* a given point.
* @@param loc The position at which the range is anchored. */
public ]b4_location_type[ (]b4_position_type[ loc) {
this.begin = this.end = loc;
}
/**
* Create a <code>]b4_location_type[</code> from the endpoints of the range.
* @@param begin The first position included in the range.
* @@param end The first position beyond the range. */
public ]b4_location_type[ (]b4_position_type[ begin, ]b4_position_type[ end) {
this.begin = begin;
this.end = end;
}
/**
* Print a representation of the location. For this to be correct,
* <code>]b4_position_type[</code> should override the <code>equals</code>
* method. */
public String toString () {
if (begin.equals (end))
return begin.toString ();
else
return begin.toString () + "-" + end.toString ();
}
}
]])
[ /** Token returned by the scanner to signal the end of its input. */
public static final int EOF = 0;]
b4_token_enums(b4_tokens)
b4_locations_if([[
private ]b4_location_type[ yylloc (YYStack rhs, int n)
{
if (n > 0)
return new ]b4_location_type[ (rhs.locationAt (1).begin, rhs.locationAt (n).end);
else
return new ]b4_location_type[ (rhs.locationAt (0).end);
}]])[
/**
* Communication interface between the scanner and the Bison-generated
* parser <tt>]b4_parser_class_name[</tt>.
*/
public interface Lexer {
]b4_locations_if([[/**
* Method to retrieve the beginning position of the last scanned token.
* @@return the position at which the last scanned token starts. */
]b4_position_type[ getStartPos ();
/**
* Method to retrieve the ending position of the last scanned token.
* @@return the first position beyond the last scanned token. */
]b4_position_type[ getEndPos ();]])[
/**
* Method to retrieve the semantic value of the last scanned token.
* @@return the semantic value of the last scanned token. */
]b4_yystype[ getLVal ();
/**
* Entry point for the scanner. Returns the token identifier corresponding
* to the next token and prepares to return the semantic value
* ]b4_locations_if([and beginning/ending positions ])[of the token.
* @@return the token identifier corresponding to the next token. */
int yylex () ]b4_maybe_throws([b4_lex_throws])[;
/**
* Entry point for error reporting. Emits an error
* ]b4_locations_if([referring to the given location ])[in a user-defined way.
*
* ]b4_locations_if([[@@param loc The location of the element to which the
* error message is related]])[
* @@param s The string for the error message. */
void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s);]
}
b4_lexer_if([[private class YYLexer implements Lexer {
]b4_percent_code_get([[lexer]])[
}
]])[/** The object doing lexical analysis for us. */
private Lexer yylexer;
]
b4_parse_param_vars
b4_lexer_if([[
/**
* Instantiates the Bison-generated parser.
*/
public ]b4_parser_class_name (b4_parse_param_decl([b4_lex_param_decl])[) {
this.yylexer = new YYLexer(]b4_lex_param_call[);
]b4_parse_param_cons[
}
]])
/**
* Instantiates the Bison-generated parser.
* @@param yylexer The scanner that will supply tokens to the parser.
*/
b4_lexer_if([[protected]], [[public]]) b4_parser_class_name[ (]b4_parse_param_decl([[Lexer yylexer]])[) {
this.yylexer = yylexer;
]b4_parse_param_cons[
}
private java.io.PrintStream yyDebugStream = System.err;
/**
* Return the <tt>PrintStream</tt> on which the debugging output is
* printed.
*/
public final java.io.PrintStream getDebugStream () { return yyDebugStream; }
/**
* Set the <tt>PrintStream</tt> on which the debug output is printed.
* @@param s The stream that is used for debugging output.
*/
public final void setDebugStream(java.io.PrintStream s) { yyDebugStream = s; }
private int yydebug = 0;
/**
* Answer the verbosity of the debugging output; 0 means that all kinds of
* output from the parser are suppressed.
*/
public final int getDebugLevel() { return yydebug; }
/**
* Set the verbosity of the debugging output; 0 means that all kinds of
* output from the parser are suppressed.
* @@param level The verbosity level for debugging output.
*/
public final void setDebugLevel(int level) { yydebug = level; }
private final int yylex () ]b4_maybe_throws([b4_lex_throws]) [{
return yylexer.yylex ();
}
protected final void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s) {
yylexer.yyerror (]b4_locations_if([loc, ])[s);
}
]b4_locations_if([
protected final void yyerror (String s) {
yylexer.yyerror ((]b4_location_type[)null, s);
}
protected final void yyerror (]b4_position_type[ loc, String s) {
yylexer.yyerror (new ]b4_location_type[ (loc), s);
}])
[protected final void yycdebug (String s) {
if (yydebug > 0)
yyDebugStream.println (s);
}
private final class YYStack {
private int[] stateStack = new int[16];
]b4_locations_if([[private ]b4_location_type[[] locStack = new ]b4_location_type[[16];]])[
private ]b4_yystype[[] valueStack = new ]b4_yystype[[16];
public int size = 16;
public int height = -1;
public final void push (int state, ]b4_yystype[ value]dnl
b4_locations_if([, ]b4_location_type[ loc])[) {
height++;
if (size == height)
{
int[] newStateStack = new int[size * 2];
System.arraycopy (stateStack, 0, newStateStack, 0, height);
stateStack = newStateStack;
]b4_locations_if([[
]b4_location_type[[] newLocStack = new ]b4_location_type[[size * 2];
System.arraycopy (locStack, 0, newLocStack, 0, height);
locStack = newLocStack;]])
b4_yystype[[] newValueStack = new ]b4_yystype[[size * 2];
System.arraycopy (valueStack, 0, newValueStack, 0, height);
valueStack = newValueStack;
size *= 2;
}
stateStack[height] = state;
]b4_locations_if([[locStack[height] = loc;]])[
valueStack[height] = value;
}
public final void pop () {
height--;
}
public final void pop (int num) {
// Avoid memory leaks... garbage collection is a white lie!
if (num > 0) {
java.util.Arrays.fill (valueStack, height - num + 1, height, null);
]b4_locations_if([[java.util.Arrays.fill (locStack, height - num + 1, height, null);]])[
}
height -= num;
}
public final int stateAt (int i) {
return stateStack[height - i];
}
]b4_locations_if([[public final ]b4_location_type[ locationAt (int i) {
return locStack[height - i];
}
]])[public final ]b4_yystype[ valueAt (int i) {
return valueStack[height - i];
}
// Print the state stack on the debug stream.
public void print (java.io.PrintStream out)
{
out.print ("Stack now");
for (int i = 0; i < height; i++)
{
out.print (' ');
out.print (stateStack[i]);
}
out.println ();
}
}
/**
* Returned by a Bison action in order to stop the parsing process and
* return success (<tt>true</tt>). */
public static final int YYACCEPT = 0;
/**
* Returned by a Bison action in order to stop the parsing process and
* return failure (<tt>false</tt>). */
public static final int YYABORT = 1;
/**
* Returned by a Bison action in order to start error recovery without
* printing an error message. */
public static final int YYERROR = 2;
/**
* Returned by a Bison action in order to print an error message and start
* error recovery. */
public static final int YYFAIL = 3;
private static final int YYNEWSTATE = 4;
private static final int YYDEFAULT = 5;
private static final int YYREDUCE = 6;
private static final int YYERRLAB1 = 7;
private static final int YYRETURN = 8;
private int yyerrstatus_ = 0;
/**
* Return whether error recovery is being done. In this state, the parser
* reads token until it reaches a known state, and then restarts normal
* operation. */
public final boolean recovering ()
{
return yyerrstatus_ == 0;
}
private int yyaction (int yyn, YYStack yystack, int yylen) ]b4_maybe_throws([b4_throws])[
{
]b4_yystype[ yyval;
]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[
/* If YYLEN is nonzero, implement the default value of the action:
`$$ = $1'. Otherwise, use the top of the stack.
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
users should not rely upon it. */
if (yylen > 0)
yyval = yystack.valueAt (yylen - 1);
else
yyval = yystack.valueAt (0);
yy_reduce_print (yyn, yystack);
switch (yyn)
{
]b4_user_actions[
default: break;
}
yy_symbol_print ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[);
yystack.pop (yylen);
yylen = 0;
/* Shift the result of the reduction. */
yyn = yyr1_[yyn];
int yystate = yypgoto_[yyn - yyntokens_] + yystack.stateAt (0);
if (0 <= yystate && yystate <= yylast_
&& yycheck_[yystate] == yystack.stateAt (0))
yystate = yytable_[yystate];
else
yystate = yydefgoto_[yyn - yyntokens_];
yystack.push (yystate, yyval]b4_locations_if([, yyloc])[);
return YYNEWSTATE;
}
/* Return YYSTR after stripping away unnecessary quotes and
backslashes, so that it's suitable for yyerror. The heuristic is
that double-quoting is unnecessary unless the string contains an
apostrophe, a comma, or backslash (other than backslash-backslash).
YYSTR is taken from yytname. */
private final String yytnamerr_ (String yystr)
{
if (yystr.charAt (0) == '"')
{
StringBuffer yyr = new StringBuffer ();
strip_quotes: for (int i = 1; i < yystr.length (); i++)
switch (yystr.charAt (i))
{
case '\'':
case ',':
break strip_quotes;
case '\\':
if (yystr.charAt(++i) != '\\')
break strip_quotes;
/* Fall through. */
default:
yyr.append (yystr.charAt (i));
break;
case '"':
return yyr.toString ();
}
}
else if (yystr.equals ("$end"))
return "end of input";
return yystr;
}
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
private void yy_symbol_print (String s, int yytype,
]b4_yystype[ yyvaluep]dnl
b4_locations_if([, Object yylocationp])[)
{
if (yydebug > 0)
yycdebug (s + (yytype < yyntokens_ ? " token " : " nterm ")
+ yytname_[yytype] + " ("]b4_locations_if([
+ yylocationp + ": "])[
+ (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
}
/**
* Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully.
*
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors.
*/
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
{
/// Lookahead and lookahead in internal form.
int yychar = yyempty_;
int yytoken = 0;
/* State. */
int yyn = 0;
int yylen = 0;
int yystate = 0;
YYStack yystack = new YYStack ();
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/// The location where the error started.
]b4_location_type[ yyerrloc = null;
/// ]b4_location_type[ of the lookahead.
]b4_location_type[ yylloc = new ]b4_location_type[ (null, null);
/// @@$.
]b4_location_type[ yyloc;])
/// Semantic value of the lookahead.
b4_yystype[ yylval = null;
int yyresult;
yycdebug ("Starting parse\n");
yyerrstatus_ = 0;
]m4_ifdef([b4_initial_action], [
m4_pushdef([b4_at_dollar], [yylloc])dnl
m4_pushdef([b4_dollar_dollar], [yylval])dnl
/* User initialization code. */
b4_user_initial_action
m4_popdef([b4_dollar_dollar])dnl
m4_popdef([b4_at_dollar])])dnl
[ /* Initialize the stack. */
yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
int label = YYNEWSTATE;
for (;;)
switch (label)
{
/* New state. Unlike in the C/C++ skeletons, the state is already
pushed when we come here. */
case YYNEWSTATE:
yycdebug ("Entering state " + yystate + "\n");
if (yydebug > 0)
yystack.print (yyDebugStream);
/* Accept? */
if (yystate == yyfinal_)
return true;
/* Take a decision. First try without lookahead. */
yyn = yypact_[yystate];
if (yyn == yypact_ninf_)
{
label = YYDEFAULT;
break;
}
/* Read a lookahead token. */
if (yychar == yyempty_)
{
yycdebug ("Reading a token: ");
yychar = yylex ();]
b4_locations_if([[
yylloc = new ]b4_location_type[(yylexer.getStartPos (),
yylexer.getEndPos ());]])
yylval = yylexer.getLVal ();[
}
/* Convert token to internal form. */
if (yychar <= EOF)
{
yychar = yytoken = EOF;
yycdebug ("Now at end of input.\n");
}
else
{
yytoken = yytranslate_ (yychar);
yy_symbol_print ("Next token is", yytoken,
yylval]b4_locations_if([, yylloc])[);
}
/* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */
yyn += yytoken;
if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken)
label = YYDEFAULT;
/* <= 0 means reduce or error. */
else if ((yyn = yytable_[yyn]) <= 0)
{
if (yyn == 0 || yyn == yytable_ninf_)
label = YYFAIL;
else
{
yyn = -yyn;
label = YYREDUCE;
}
}
else
{
/* Shift the lookahead token. */
yy_symbol_print ("Shifting", yytoken,
yylval]b4_locations_if([, yylloc])[);
/* Discard the token being shifted. */
yychar = yyempty_;
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus_ > 0)
--yyerrstatus_;
yystate = yyn;
yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
label = YYNEWSTATE;
}
break;
/*-----------------------------------------------------------.
| yydefault -- do the default action for the current state. |
`-----------------------------------------------------------*/
case YYDEFAULT:
yyn = yydefact_[yystate];
if (yyn == 0)
label = YYFAIL;
else
label = YYREDUCE;
break;
/*-----------------------------.
| yyreduce -- Do a reduction. |
`-----------------------------*/
case YYREDUCE:
yylen = yyr2_[yyn];
label = yyaction (yyn, yystack, yylen);
yystate = yystack.stateAt (0);
break;
/*------------------------------------.
| yyerrlab -- here on detecting error |
`------------------------------------*/
case YYFAIL:
/* If not already recovering from an error, report this error. */
if (yyerrstatus_ == 0)
{
++yynerrs_;
yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yystate, yytoken));
}
]b4_locations_if([yyerrloc = yylloc;])[
if (yyerrstatus_ == 3)
{
/* If just tried and failed to reuse lookahead token after an
error, discard it. */
if (yychar <= EOF)
{
/* Return failure if at end of input. */
if (yychar == EOF)
return false;
}
else
yychar = yyempty_;
}
/* Else will try to reuse lookahead token after shifting the error
token. */
label = YYERRLAB1;
break;
/*---------------------------------------------------.
| errorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
case YYERROR:
]b4_locations_if([yyerrloc = yystack.locationAt (yylen - 1);])[
/* Do not reclaim the symbols of the rule which action triggered
this YYERROR. */
yystack.pop (yylen);
yylen = 0;
yystate = yystack.stateAt (0);
label = YYERRLAB1;
break;
/*-------------------------------------------------------------.
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
case YYERRLAB1:
yyerrstatus_ = 3; /* Each real token shifted decrements this. */
for (;;)
{
yyn = yypact_[yystate];
if (yyn != yypact_ninf_)
{
yyn += yyterror_;
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
{
yyn = yytable_[yyn];
if (0 < yyn)
break;
}
}
/* Pop the current state because it cannot handle the error token. */
if (yystack.height == 1)
return false;
]b4_locations_if([yyerrloc = yystack.locationAt (0);])[
yystack.pop ();
yystate = yystack.stateAt (0);
if (yydebug > 0)
yystack.print (yyDebugStream);
}
]b4_locations_if([
/* Muck with the stack to setup for yylloc. */
yystack.push (0, null, yylloc);
yystack.push (0, null, yyerrloc);
yyloc = yylloc (yystack, 2);
yystack.pop (2);])[
/* Shift the error token. */
yy_symbol_print ("Shifting", yystos_[yyn],
yylval]b4_locations_if([, yyloc])[);
yystate = yyn;
yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
label = YYNEWSTATE;
break;
/* Accept. */
case YYACCEPT:
return true;
/* Abort. */
case YYABORT:
return false;
}
}
// Generate an error message.
private String yysyntax_error (int yystate, int tok)
{
if (errorVerbose)
{
int yyn = yypact_[yystate];
if (yypact_ninf_ < yyn && yyn <= yylast_)
{
StringBuffer res;
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. */
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = yylast_ - yyn + 1;
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
int count = 0;
for (int x = yyxbegin; x < yyxend; ++x)
if (yycheck_[x + yyn] == x && x != yyterror_)
++count;
// FIXME: This method of building the message is not compatible
// with internationalization.
res = new StringBuffer ("syntax error, unexpected ");
res.append (yytnamerr_ (yytname_[tok]));
if (count < 5)
{
count = 0;
for (int x = yyxbegin; x < yyxend; ++x)
if (yycheck_[x + yyn] == x && x != yyterror_)
{
res.append (count++ == 0 ? ", expecting " : " or ");
res.append (yytnamerr_ (yytname_[x]));
}
}
return res.toString ();
}
}
return "syntax error";
}
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
private static final ]b4_int_type_for([b4_pact])[ yypact_ninf_ = ]b4_pact_ninf[;
private static final ]b4_int_type_for([b4_pact])[ yypact_[] =
{
]b4_pact[
};
/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
doesn't specify something else to do. Zero means the default is an
error. */
private static final ]b4_int_type_for([b4_defact])[ yydefact_[] =
{
]b4_defact[
};
/* YYPGOTO[NTERM-NUM]. */
private static final ]b4_int_type_for([b4_pgoto])[ yypgoto_[] =
{
]b4_pgoto[
};
/* YYDEFGOTO[NTERM-NUM]. */
private static final ]b4_int_type_for([b4_defgoto])[
yydefgoto_[] =
{
]b4_defgoto[
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says. */
private static final ]b4_int_type_for([b4_table])[ yytable_ninf_ = ]b4_table_ninf[;
private static final ]b4_int_type_for([b4_table])[
yytable_[] =
{
]b4_table[
};
/* YYCHECK. */
private static final ]b4_int_type_for([b4_check])[
yycheck_[] =
{
]b4_check[
};
/* STOS_[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
private static final ]b4_int_type_for([b4_stos])[
yystos_[] =
{
]b4_stos[
};
/* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding
to YYLEX-NUM. */
private static final ]b4_int_type_for([b4_toknum])[
yytoken_number_[] =
{
]b4_toknum[
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
private static final ]b4_int_type_for([b4_r1])[
yyr1_[] =
{
]b4_r1[
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
private static final ]b4_int_type_for([b4_r2])[
yyr2_[] =
{
]b4_r2[
};
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
private static final String yytname_[] =
{
]b4_tname[
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
private static final ]b4_int_type_for([b4_rhs])[ yyrhs_[] =
{
]b4_rhs[
};
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
YYRHS. */
private static final ]b4_int_type_for([b4_prhs])[ yyprhs_[] =
{
]b4_prhs[
};
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
private static final ]b4_int_type_for([b4_rline])[ yyrline_[] =
{
]b4_rline[
};
// Report on the debug stream that the rule yyrule is going to be reduced.
private void yy_reduce_print (int yyrule, YYStack yystack)
{
if (yydebug == 0)
return;
int yylno = yyrline_[yyrule];
int yynrhs = yyr2_[yyrule];
/* Print the symbols being reduced, and their result. */
yycdebug ("Reducing stack by rule " + (yyrule - 1)
+ " (line " + yylno + "), ");
/* The symbols being reduced. */
for (int yyi = 0; yyi < yynrhs; yyi++)
yy_symbol_print (" $" + (yyi + 1) + " =",
yyrhs_[yyprhs_[yyrule] + yyi],
]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([,
b4_rhs_location(yynrhs, yyi + 1)])[);
}
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
private static final ]b4_int_type_for([b4_translate])[ yytranslate_table_[] =
{
]b4_translate[
};
private static final ]b4_int_type_for([b4_translate])[ yytranslate_ (int t)
{
if (t >= 0 && t <= yyuser_token_number_max_)
return yytranslate_table_[t];
else
return yyundef_token_;
}
private static final int yylast_ = ]b4_last[;
private static final int yynnts_ = ]b4_nterms_number[;
private static final int yyempty_ = -2;
private static final int yyfinal_ = ]b4_final_state_number[;
private static final int yyterror_ = 1;
private static final int yyerrcode_ = 256;
private static final int yyntokens_ = ]b4_tokens_number[;
private static final int yyuser_token_number_max_ = ]b4_user_token_number_max[;
private static final int yyundef_token_ = ]b4_undef_token_number[;
]/* User implementation code. */
b4_percent_code_get[]dnl
}
b4_epilogue
m4_divert_pop(0)dnl

View File

@@ -1,275 +0,0 @@
# C++ skeleton for Bison
# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation,
# Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# We do want M4 expansion after # for CPP macros.
m4_changecom()
m4_divert_push(0)dnl
@output(b4_dir_prefix[]position.hh@)
b4_copyright([Positions for Bison parsers in C++],
[2002, 2003, 2004, 2005, 2006])[
/**
** \file position.hh
** Define the ]b4_namespace_ref[::position class.
*/
#ifndef BISON_POSITION_HH
# define BISON_POSITION_HH
# include <iostream>
# include <string>
# include <algorithm>
]b4_namespace_open[
/// Abstract a position.
class position
{
public:
]m4_ifdef([b4_location_constructors], [
/// Construct a position.
position ()
: filename (0), line (]b4_location_initial_line[), column (]b4_location_initial_column[)
{
}
])[
/// Initialization.
inline void initialize (]b4_percent_define_get([[filename_type]])[* fn)
{
filename = fn;
line = ]b4_location_initial_line[;
column = ]b4_location_initial_column[;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// (line related) Advance to the COUNT next lines.
inline void lines (int count = 1)
{
column = ]b4_location_initial_column[;
line += count;
}
/// (column related) Advance to the COUNT next columns.
inline void columns (int count = 1)
{
column = std::max (]b4_location_initial_column[u, column + count);
}
/** \} */
public:
/// File name to which this position refers.
]b4_percent_define_get([[filename_type]])[* filename;
/// Current line number.
unsigned int line;
/// Current column number.
unsigned int column;
};
/// Add and assign a position.
inline const position&
operator+= (position& res, const int width)
{
res.columns (width);
return res;
}
/// Add two position objects.
inline const position
operator+ (const position& begin, const int width)
{
position res = begin;
return res += width;
}
/// Add and assign a position.
inline const position&
operator-= (position& res, const int width)
{
return res += -width;
}
/// Add two position objects.
inline const position
operator- (const position& begin, const int width)
{
return begin + -width;
}
]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two position objects.
inline bool
operator== (const position& pos1, const position& pos2)
{
return
(pos1.filename == pos2.filename
|| pos1.filename && pos2.filename && *pos1.filename == *pos2.filename)
&& pos1.line == pos2.line && pos1.column == pos2.column;
}
/// Compare two position objects.
inline bool
operator!= (const position& pos1, const position& pos2)
{
return !(pos1 == pos2);
}
]])[
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param pos a reference to the position to redirect
*/
inline std::ostream&
operator<< (std::ostream& ostr, const position& pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
]b4_namespace_close[
#endif // not BISON_POSITION_HH]
@output(b4_dir_prefix[]location.hh@)
b4_copyright([Locations for Bison parsers in C++],
[2002, 2003, 2004, 2005, 2006])[
/**
** \file location.hh
** Define the ]b4_namespace_ref[::location class.
*/
#ifndef BISON_LOCATION_HH
# define BISON_LOCATION_HH
# include <iostream>
# include <string>
# include "position.hh"
]b4_namespace_open[
/// Abstract a location.
class location
{
public:
]m4_ifdef([b4_location_constructors], [
/// Construct a location.
location ()
: begin (), end ()
{
}
])[
/// Initialization.
inline void initialize (]b4_percent_define_get([[filename_type]])[* fn)
{
begin.initialize (fn);
end = begin;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
inline void step ()
{
begin = end;
}
/// Extend the current location to the COUNT next columns.
inline void columns (unsigned int count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
inline void lines (unsigned int count = 1)
{
end.lines (count);
}
/** \} */
public:
/// Beginning of the located region.
position begin;
/// End of the located region.
position end;
};
/// Join two location objects to create a location.
inline const location operator+ (const location& begin, const location& end)
{
location res = begin;
res.end = end.end;
return res;
}
/// Add two location objects.
inline const location operator+ (const location& begin, unsigned int width)
{
location res = begin;
res.columns (width);
return res;
}
/// Add and assign a location.
inline location& operator+= (location& res, unsigned int width)
{
res.columns (width);
return res;
}
]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two location objects.
inline bool
operator== (const location& loc1, const location& loc2)
{
return loc1.begin == loc2.begin && loc1.end == loc2.end;
}
/// Compare two location objects.
inline bool
operator!= (const location& loc1, const location& loc2)
{
return !(loc1 == loc2);
}
]])[
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param loc a reference to the location to redirect
**
** Avoid duplicate information.
*/
inline std::ostream& operator<< (std::ostream& ostr, const location& loc)
{
position last = loc.end - 1;
ostr << loc.begin;
if (last.filename
&& (!loc.begin.filename
|| *loc.begin.filename != *last.filename))
ostr << '-' << last;
else if (loc.begin.line != last.line)
ostr << '-' << last.line << '.' << last.column;
else if (loc.begin.column != last.column)
ostr << '-' << last.column;
return ostr;
}
]b4_namespace_close[
#endif // not BISON_LOCATION_HH]
m4_divert_pop(0)
m4_changecom([#])

View File

@@ -1,400 +0,0 @@
# -*- Autoconf -*-
# This file is part of Autoconf.
# foreach-based replacements for recursive functions.
# Speeds up GNU M4 1.4.x by avoiding quadratic $@ recursion, but penalizes
# GNU M4 1.6 by requiring more memory and macro expansions.
#
# Copyright (C) 2008 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception, the Free Software Foundation gives unlimited
# permission to copy, distribute and modify the configure scripts that
# are the output of Autoconf. You need not follow the terms of the GNU
# General Public License when using or distributing such scripts, even
# though portions of the text of Autoconf appear in them. The GNU
# General Public License (GPL) does govern all other use of the material
# that constitutes the Autoconf program.
#
# Certain portions of the Autoconf source text are designed to be copied
# (in certain cases, depending on the input) into the output of
# Autoconf. We call these the "data" portions. The rest of the Autoconf
# source text consists of comments plus executable code that decides which
# of the data portions to output in any given case. We call these
# comments and executable code the "non-data" portions. Autoconf never
# copies any of the non-data portions into its output.
#
# This special exception to the GPL applies to versions of Autoconf
# released by the Free Software Foundation. When you make and
# distribute a modified version of Autoconf, you may extend this special
# exception to the GPL to apply to your modified version as well, *unless*
# your modified version has the potential to copy into its output some
# of the text that was the non-data portion of the version that you started
# with. (In other words, unless your change moves or copies text from
# the non-data portions to the data portions.) If your modification has
# such potential, you must delete any notice of this special exception
# to the GPL from your modified version.
#
# Written by Eric Blake.
#
# In M4 1.4.x, every byte of $@ is rescanned. This means that an
# algorithm on n arguments that recurses with one less argument each
# iteration will scan n * (n + 1) / 2 arguments, for O(n^2) time. In
# M4 1.6, this was fixed so that $@ is only scanned once, then
# back-references are made to information stored about the scan.
# Thus, n iterations need only scan n arguments, for O(n) time.
# Additionally, in M4 1.4.x, recursive algorithms did not clean up
# memory very well, requiring O(n^2) memory rather than O(n) for n
# iterations.
#
# This file is designed to overcome the quadratic nature of $@
# recursion by writing a variant of m4_foreach that uses m4_for rather
# than $@ recursion to operate on the list. This involves more macro
# expansions, but avoids the need to rescan a quadratic number of
# arguments, making these replacements very attractive for M4 1.4.x.
# On the other hand, in any version of M4, expanding additional macros
# costs additional time; therefore, in M4 1.6, where $@ recursion uses
# fewer macros, these replacements actually pessimize performance.
# Additionally, the use of $10 to mean the tenth argument violates
# POSIX; although all versions of m4 1.4.x support this meaning, a
# future m4 version may switch to take it as the first argument
# concatenated with a literal 0, so the implementations in this file
# are not future-proof. Thus, this file is conditionally included as
# part of m4_init(), only when it is detected that M4 probably has
# quadratic behavior (ie. it lacks the macro __m4_version__).
#
# Please keep this file in sync with m4sugar.m4.
# m4_foreach(VARIABLE, LIST, EXPRESSION)
# --------------------------------------
# Expand EXPRESSION assigning each value of the LIST to VARIABLE.
# LIST should have the form `item_1, item_2, ..., item_n', i.e. the
# whole list must *quoted*. Quote members too if you don't want them
# to be expanded.
#
# This version minimizes the number of times that $@ is evaluated by
# using m4_for to generate a boilerplate into VARIABLE then passing $@
# to that temporary macro. Thus, the recursion is done in m4_for
# without reparsing any user input, and is not quadratic. For an idea
# of how this works, note that m4_foreach(i,[1,2],[i]) defines i to be
# m4_define([$1],[$3])$2[]m4_define([$1],[$4])$2[]m4_popdef([i])
# then calls i([i],[i],[1],[2]).
m4_define([m4_foreach],
[m4_if([$2], [], [], [_$0([$1], [$3], $2)])])
m4_define([_m4_foreach],
[m4_define([$1], m4_pushdef([$1])_m4_for([$1], [3], [$#], [1],
[$0_([1], [2], _m4_defn([$1]))])[m4_popdef([$1])])m4_indir([$1], $@)])
m4_define([_m4_foreach_],
[[m4_define([$$1], [$$3])$$2[]]])
# m4_case(SWITCH, VAL1, IF-VAL1, VAL2, IF-VAL2, ..., DEFAULT)
# -----------------------------------------------------------
# Find the first VAL that SWITCH matches, and expand the corresponding
# IF-VAL. If there are no matches, expand DEFAULT.
#
# Use m4_for to create a temporary macro in terms of a boilerplate
# m4_if with final cleanup. If $# is even, we have DEFAULT; if it is
# odd, then rounding the last $# up in the temporary macro is
# harmless. For example, both m4_case(1,2,3,4,5) and
# m4_case(1,2,3,4,5,6) result in the intermediate _m4_case being
# m4_if([$1],[$2],[$3],[$1],[$4],[$5],_m4_popdef([_m4_case])[$6])
m4_define([m4_case],
[m4_if(m4_eval([$# <= 2]), [1], [$2],
[m4_pushdef([_$0], [m4_if(]m4_for([_m4_count], [2], m4_decr([$#]), [2],
[_$0_([1], _m4_count, m4_incr(_m4_count))])[_m4_popdef(
[_$0])]m4_dquote($m4_eval([($# + 1) & ~1]))[)])_$0($@)])])
m4_define([_m4_case_],
[[[$$1],[$$2],[$$3],]])
# m4_bmatch(SWITCH, RE1, VAL1, RE2, VAL2, ..., DEFAULT)
# -----------------------------------------------------
# m4 equivalent of
#
# if (SWITCH =~ RE1)
# VAL1;
# elif (SWITCH =~ RE2)
# VAL2;
# elif ...
# ...
# else
# DEFAULT
#
# We build the temporary macro _m4_b:
# m4_define([_m4_b], _m4_defn([_m4_bmatch]))_m4_b([$1], [$2], [$3])...
# _m4_b([$1], [$m-1], [$m])_m4_b([], [], [$m+1]_m4_popdef([_m4_b]))
# then invoke m4_unquote(_m4_b($@)), for concatenation with later text.
m4_define([m4_bmatch],
[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
[$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
[$#], 2, [$2],
[m4_define([_m4_b], m4_pushdef([_m4_b])[m4_define([_m4_b],
_m4_defn([_$0]))]_m4_for([_m4_b], [3], m4_eval([($# + 1) / 2 * 2 - 1]),
[2], [_$0_([1], m4_decr(_m4_b), _m4_b)])[_m4_b([], [],]m4_dquote(
[$]m4_incr(_m4_b))[_m4_popdef([_m4_b]))])m4_unquote(_m4_b($@))])])
m4_define([_m4_bmatch],
[m4_if(m4_bregexp([$1], [$2]), [-1], [], [[$3]m4_define([$0])])])
m4_define([_m4_bmatch_],
[[_m4_b([$$1], [$$2], [$$3])]])
# m4_cond(TEST1, VAL1, IF-VAL1, TEST2, VAL2, IF-VAL2, ..., [DEFAULT])
# -------------------------------------------------------------------
# Similar to m4_if, except that each TEST is expanded when encountered.
# If the expansion of TESTn matches the string VALn, the result is IF-VALn.
# The result is DEFAULT if no tests passed. This macro allows
# short-circuiting of expensive tests, where it pays to arrange quick
# filter tests to run first.
#
# m4_cond already guarantees either 3*n or 3*n + 1 arguments, 1 <= n.
# We only have to speed up _m4_cond, by building the temporary _m4_c:
# m4_define([_m4_c], _m4_defn([m4_unquote]))_m4_c([m4_if(($1), [($2)],
# [[$3]m4_define([_m4_c])])])_m4_c([m4_if(($4), [($5)],
# [[$6]m4_define([_m4_c])])])..._m4_c([m4_if(($m-2), [($m-1)],
# [[$m]m4_define([_m4_c])])])_m4_c([[$m+1]]_m4_popdef([_m4_c]))
# We invoke m4_unquote(_m4_c($@)), for concatenation with later text.
m4_define([_m4_cond],
[m4_define([_m4_c], m4_pushdef([_m4_c])[m4_define([_m4_c],
_m4_defn([m4_unquote]))]_m4_for([_m4_c], [2], m4_eval([$# / 3 * 3 - 1]), [3],
[$0_(m4_decr(_m4_c), _m4_c, m4_incr(_m4_c))])[_m4_c(]m4_dquote(m4_dquote(
[$]m4_eval([$# / 3 * 3 + 1])))[_m4_popdef([_m4_c]))])m4_unquote(_m4_c($@))])
m4_define([_m4_cond_],
[[_m4_c([m4_if(($$1), [($$2)], [[$$3]m4_define([_m4_c])])])]])
# m4_bpatsubsts(STRING, RE1, SUBST1, RE2, SUBST2, ...)
# ----------------------------------------------------
# m4 equivalent of
#
# $_ = STRING;
# s/RE1/SUBST1/g;
# s/RE2/SUBST2/g;
# ...
#
# m4_bpatsubsts already validated an odd number of arguments; we only
# need to speed up _m4_bpatsubsts. To avoid nesting, we build the
# temporary _m4_p:
# m4_define([_m4_p], [$1])m4_define([_m4_p],
# m4_bpatsubst(m4_dquote(_m4_defn([_m4_p])), [$2], [$3]))m4_define([_m4_p],
# m4_bpatsubst(m4_dquote(_m4_defn([_m4_p])), [$4], [$5]))m4_define([_m4_p],...
# m4_bpatsubst(m4_dquote(_m4_defn([_m4_p])), [$m-1], [$m]))m4_unquote(
# _m4_defn([_m4_p])_m4_popdef([_m4_p]))
m4_define([_m4_bpatsubsts],
[m4_define([_m4_p], m4_pushdef([_m4_p])[m4_define([_m4_p],
]m4_dquote([$]1)[)]_m4_for([_m4_p], [3], [$#], [2], [$0_(m4_decr(_m4_p),
_m4_p)])[m4_unquote(_m4_defn([_m4_p])_m4_popdef([_m4_p]))])_m4_p($@)])
m4_define([_m4_bpatsubsts_],
[[m4_define([_m4_p],
m4_bpatsubst(m4_dquote(_m4_defn([_m4_p])), [$$1], [$$2]))]])
# m4_shiftn(N, ...)
# -----------------
# Returns ... shifted N times. Useful for recursive "varargs" constructs.
#
# m4_shiftn already validated arguments; we only need to speed up
# _m4_shiftn. If N is 3, then we build the temporary _m4_s, defined as
# ,[$5],[$6],...,[$m]_m4_popdef([_m4_s])
# before calling m4_shift(_m4_s($@)).
m4_define([_m4_shiftn],
[m4_if(m4_incr([$1]), [$#], [], [m4_define([_m4_s],
m4_pushdef([_m4_s])_m4_for([_m4_s], m4_eval([$1 + 2]), [$#], [1],
[[,]m4_dquote([$]_m4_s)])[_m4_popdef([_m4_s])])m4_shift(_m4_s($@))])])
# m4_do(STRING, ...)
# ------------------
# This macro invokes all its arguments (in sequence, of course). It is
# useful for making your macros more structured and readable by dropping
# unnecessary dnl's and have the macros indented properly.
#
# Here, we use the temporary macro _m4_do, defined as
# $1[]$2[]...[]$n[]_m4_popdef([_m4_do])
m4_define([m4_do],
[m4_if([$#], [0], [],
[m4_define([_$0], m4_pushdef([_$0])_m4_for([_$0], [1], [$#], [1],
[$_$0[[]]])[_m4_popdef([_$0])])_$0($@)])])
# m4_dquote_elt(ARGS)
# -------------------
# Return ARGS as an unquoted list of double-quoted arguments.
#
# m4_foreach to the rescue. It's easier to shift off the leading comma.
m4_define([m4_dquote_elt],
[m4_shift(m4_foreach([_m4_elt], [$@], [,m4_dquote(_m4_defn([_m4_elt]))]))])
# m4_reverse(ARGS)
# ----------------
# Output ARGS in reverse order.
#
# Invoke _m4_r($@) with the temporary _m4_r built as
# [$m], [$m-1], ..., [$2], [$1]_m4_popdef([_m4_r])
m4_define([m4_reverse],
[m4_if([$#], [0], [], [$#], [1], [[$1]],
[m4_define([_m4_r], m4_dquote([$$#])m4_pushdef([_m4_r])_m4_for([_m4_r],
m4_decr([$#]), [1], [-1],
[[, ]m4_dquote([$]_m4_r)])[_m4_popdef([_m4_r])])_m4_r($@)])])
# m4_map(MACRO, LIST)
# -------------------
# Invoke MACRO($1), MACRO($2) etc. where $1, $2... are the elements
# of LIST. $1, $2... must in turn be lists, appropriate for m4_apply.
#
# m4_map/m4_map_sep only execute once; the speedup comes in fixing
# _m4_map. The mismatch in () is intentional, since $1 supplies the
# opening `(' (but it sure looks odd!). Build the temporary _m4_m:
# $1, [$3])$1, [$4])...$1, [$m])_m4_popdef([_m4_m])
m4_define([_m4_map],
[m4_if([$#], [2], [],
[m4_define([_m4_m], m4_pushdef([_m4_m])_m4_for([_m4_m], [3], [$#], [1],
[$0_([1], _m4_m)])[_m4_popdef([_m4_m])])_m4_m($@)])])
m4_define([_m4_map_],
[[$$1, [$$2])]])
# m4_transform(EXPRESSION, ARG...)
# --------------------------------
# Expand EXPRESSION([ARG]) for each argument. More efficient than
# m4_foreach([var], [ARG...], [EXPRESSION(m4_defn([var]))])
#
# Invoke the temporary macro _m4_transform, defined as:
# $1([$2])[]$1([$3])[]...$1([$m])[]_m4_popdef([_m4_transform])
m4_define([m4_transform],
[m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
[$#], [1], [],
[m4_define([_$0], m4_pushdef([_$0])_m4_for([_$0], [2], [$#], [1],
[_$0_([1], _$0)])[_m4_popdef([_$0])])_$0($@)])])
m4_define([_m4_transform_],
[[$$1([$$2])[]]])
# m4_transform_pair(EXPRESSION, [END-EXPR = EXPRESSION], ARG...)
# --------------------------------------------------------------
# Perform a pairwise grouping of consecutive ARGs, by expanding
# EXPRESSION([ARG1], [ARG2]). If there are an odd number of ARGs, the
# final argument is expanded with END-EXPR([ARGn]).
#
# Build the temporary macro _m4_transform_pair, with the $2([$m+1])
# only output if $# is odd:
# $1([$3], [$4])[]$1([$5], [$6])[]...$1([$m-1],
# [$m])[]m4_default([$2], [$1])([$m+1])[]_m4_popdef([_m4_transform_pair])
m4_define([m4_transform_pair],
[m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
[$#], [1], [m4_fatal([$0: too few arguments: $#: $1])],
[$#], [2], [],
[$#], [3], [m4_default([$2], [$1])([$3])[]],
[m4_define([_$0], m4_pushdef([_$0])_m4_for([_$0], [3],
m4_eval([$# / 2 * 2 - 1]), [2], [_$0_([1], _$0, m4_incr(_$0))])_$0_end(
[1], [2], [$#])[_m4_popdef([_$0])])_$0($@)])])
m4_define([_m4_transform_pair_],
[[$$1([$$2], [$$3])[]]])
m4_define([_m4_transform_pair_end],
[m4_if(m4_eval([$3 & 1]), [1], [[m4_default([$$2], [$$1])([$$3])[]]])])
# m4_join(SEP, ARG1, ARG2...)
# ---------------------------
# Produce ARG1SEPARG2...SEPARGn. Avoid back-to-back SEP when a given ARG
# is the empty string. No expansion is performed on SEP or ARGs.
#
# Use a self-modifying separator, since we don't know how many
# arguments might be skipped before a separator is first printed, but
# be careful if the separator contains $. m4_foreach to the rescue.
m4_define([m4_join],
[m4_pushdef([_m4_sep], [m4_define([_m4_sep], _m4_defn([m4_echo]))])]dnl
[m4_foreach([_m4_arg], [m4_shift($@)],
[m4_ifset([_m4_arg], [_m4_sep([$1])_m4_defn([_m4_arg])])])]dnl
[_m4_popdef([_m4_sep])])
# m4_joinall(SEP, ARG1, ARG2...)
# ------------------------------
# Produce ARG1SEPARG2...SEPARGn. An empty ARG results in back-to-back SEP.
# No expansion is performed on SEP or ARGs.
#
# A bit easier than m4_join. m4_foreach to the rescue.
m4_define([m4_joinall],
[[$2]m4_if(m4_eval([$# <= 2]), [1], [],
[m4_foreach([_m4_arg], [m4_shift2($@)],
[[$1]_m4_defn([_m4_arg])])])])
# m4_list_cmp(A, B)
# -----------------
# Compare the two lists of integer expressions A and B.
#
# m4_list_cmp takes care of any side effects; we only override
# _m4_list_cmp_raw, where we can safely expand lists multiple times.
# First, insert padding so that both lists are the same length; the
# trailing +0 is necessary to handle a missing list. Next, create a
# temporary macro to perform pairwise comparisons until an inequality
# is found. For example, m4_list_cmp([1], [1,2]) creates _m4_cmp as
# m4_if(m4_eval([($1) != ($3)]), [1], [m4_cmp([$1], [$3])],
# m4_eval([($2) != ($4)]), [1], [m4_cmp([$2], [$4])],
# [0]_m4_popdef([_m4_cmp], [_m4_size]))
# then calls _m4_cmp([1+0], [0], [1], [2+0])
m4_define([_m4_list_cmp_raw],
[m4_if([$1], [$2], 0, [m4_pushdef(
[_m4_size])_m4_list_cmp($1+0_m4_list_pad(m4_count($1), m4_count($2)),
$2+0_m4_list_pad(m4_count($2), m4_count($1)))])])
m4_define([_m4_list_pad],
[m4_if(m4_eval($1 < $2), [1],
[_m4_for([_m4_size], m4_incr([$1]), [$2], [1], [,0])])])
m4_define([_m4_list_cmp],
[m4_define([_m4_size], m4_eval([$# >> 1]))]dnl
[m4_define([_m4_cmp], m4_pushdef([_m4_cmp])[m4_if(]_m4_for([_m4_cmp],
[1], _m4_size, [1], [$0_(_m4_cmp, m4_eval(_m4_cmp + _m4_size))])[
[0]_m4_popdef([_m4_cmp], [_m4_size]))])_m4_cmp($@)])
m4_define([_m4_list_cmp_],
[[m4_eval([($$1) != ($$2)]), [1], [m4_cmp([$$1], [$$2])],
]])
# m4_max(EXPR, ...)
# m4_min(EXPR, ...)
# -----------------
# Return the decimal value of the maximum (or minimum) in a series of
# integer expressions.
#
# m4_foreach to the rescue; we only need to replace _m4_minmax. Here,
# we need a temporary macro to track the best answer so far, so that
# the foreach expression is tractable.
m4_define([_m4_minmax],
[m4_pushdef([_m4_best], m4_eval([$2]))m4_foreach([_m4_arg], [m4_shift2($@)],
[m4_define([_m4_best], $1(_m4_best, _m4_defn([_m4_arg])))])]dnl
[_m4_best[]_m4_popdef([_m4_best])])
# m4_set_add_all(SET, VALUE...)
# -----------------------------
# Add each VALUE into SET. This is O(n) in the number of VALUEs, and
# can be faster than calling m4_set_add for each VALUE.
#
# m4_foreach to the rescue. If no deletions have occurred, then avoid
# the speed penalty of m4_set_add.
m4_define([m4_set_add_all],
[m4_if([$#], [0], [], [$#], [1], [],
[m4_define([_m4_set_size($1)], m4_eval(m4_set_size([$1])
+ m4_len(m4_foreach([_m4_arg], [m4_shift($@)],
m4_ifdef([_m4_set_cleanup($1)],
[[m4_set_add([$1], _m4_defn([_m4_arg]))]],
[[m4_ifdef([_m4_set([$1],]_m4_defn([_m4_arg])[)], [],
[m4_define([_m4_set([$1],]_m4_defn([_m4_arg])[)],
[1])m4_pushdef([_m4_set([$1])],
_m4_defn([_m4_arg]))-])]])))))])])

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
bison.xsl - common templates for Bison XSLT.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:bison="http://www.gnu.org/software/bison/">
<xsl:key
name="bison:symbolByName"
match="/bison-xml-report/grammar/nonterminals/nonterminal"
use="@name"
/>
<xsl:key
name="bison:symbolByName"
match="/bison-xml-report/grammar/terminals/terminal"
use="@name"
/>
<xsl:key
name="bison:ruleByNumber"
match="/bison-xml-report/grammar/rules/rule"
use="@number"
/>
<xsl:key
name="bison:ruleByLhs"
match="/bison-xml-report/grammar/rules/rule[
@usefulness != 'useless-in-grammar']"
use="lhs"
/>
<xsl:key
name="bison:ruleByRhs"
match="/bison-xml-report/grammar/rules/rule[
@usefulness != 'useless-in-grammar']"
use="rhs/symbol"
/>
<!-- For the specified state, output: #sr-conflicts,#rr-conflicts -->
<xsl:template match="state" mode="bison:count-conflicts">
<xsl:variable name="transitions" select="actions/transitions"/>
<xsl:variable name="reductions" select="actions/reductions"/>
<xsl:variable
name="terminals"
select="
$transitions/transition[@type='shift']/@symbol
| $reductions/reduction/@symbol
"
/>
<xsl:variable name="conflict-data">
<xsl:for-each select="$terminals">
<xsl:variable name="name" select="."/>
<xsl:if test="generate-id($terminals[. = $name][1]) = generate-id(.)">
<xsl:variable
name="shift-count"
select="count($transitions/transition[@symbol=$name])"
/>
<xsl:variable
name="reduce-count"
select="count($reductions/reduction[@symbol=$name])"
/>
<xsl:if test="$shift-count > 0 and $reduce-count > 0">
<xsl:text>s</xsl:text>
</xsl:if>
<xsl:if test="$reduce-count > 1">
<xsl:text>r</xsl:text>
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="string-length(translate($conflict-data, 'r', ''))"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="string-length(translate($conflict-data, 's', ''))"/>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,206 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
xml2dot.xsl - transform Bison XML Report into DOT.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by Wojciech Polak <polak@gnu.org>.
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:bison="http://www.gnu.org/software/bison/">
<xsl:import href="bison.xsl"/>
<xsl:output method="text" encoding="UTF-8" indent="no"/>
<xsl:template match="/">
<xsl:apply-templates select="bison-xml-report"/>
</xsl:template>
<xsl:template match="bison-xml-report">
<xsl:apply-templates select="automaton"/>
</xsl:template>
<xsl:template match="automaton">
<xsl:text>digraph Automaton {&#10;</xsl:text>
<xsl:apply-templates select="state"/>
<xsl:text>}&#10;</xsl:text>
</xsl:template>
<xsl:template match="automaton/state">
<xsl:call-template name="output-node">
<xsl:with-param name="number" select="@number"/>
<xsl:with-param name="label">
<xsl:value-of select="@number"/>
<xsl:apply-templates select="itemset/item"/>
</xsl:with-param>
</xsl:call-template>
<xsl:apply-templates select="actions/transitions"/>
</xsl:template>
<xsl:template match="actions/transitions">
<xsl:apply-templates select="transition"/>
</xsl:template>
<xsl:template match="item">
<xsl:apply-templates select="key('bison:ruleByNumber', @rule-number)">
<xsl:with-param name="point" select="@point"/>
</xsl:apply-templates>
<xsl:apply-templates select="lookaheads"/>
</xsl:template>
<xsl:template match="rule">
<xsl:param name="point"/>
<xsl:text>&#10;</xsl:text>
<xsl:value-of select="lhs"/>
<xsl:text> -&gt;</xsl:text>
<xsl:if test="$point = 0">
<xsl:text> .</xsl:text>
</xsl:if>
<xsl:for-each select="rhs/symbol|rhs/empty">
<xsl:apply-templates select="."/>
<xsl:if test="$point = position()">
<xsl:text> .</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="symbol">
<xsl:text> </xsl:text>
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="empty"/>
<xsl:template match="lookaheads">
<xsl:text>[</xsl:text>
<xsl:apply-templates select="symbol"/>
<xsl:text>]</xsl:text>
</xsl:template>
<xsl:template match="lookaheads/symbol">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="transition">
<xsl:call-template name="output-edge">
<xsl:with-param name="src" select="../../../@number"/>
<xsl:with-param name="dst" select="@state"/>
<xsl:with-param name="style">
<xsl:choose>
<xsl:when test="@symbol = 'error'">
<xsl:text>dotted</xsl:text>
</xsl:when>
<xsl:when test="@type = 'shift'">
<xsl:text>solid</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>dashed</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="label">
<xsl:if test="not(@symbol = 'error')">
<xsl:value-of select="@symbol"/>
</xsl:if>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="output-node">
<xsl:param name="number"/>
<xsl:param name="label"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$number"/>
<xsl:text> [label="</xsl:text>
<xsl:call-template name="escape">
<xsl:with-param name="subject" select="$label"/>
</xsl:call-template>
<xsl:text>"]&#10;</xsl:text>
</xsl:template>
<xsl:template name="output-edge">
<xsl:param name="src"/>
<xsl:param name="dst"/>
<xsl:param name="style"/>
<xsl:param name="label"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$src"/>
<xsl:text> -> </xsl:text>
<xsl:value-of select="$dst"/>
<xsl:text> [style=</xsl:text>
<xsl:value-of select="$style"/>
<xsl:if test="$label and $label != ''">
<xsl:text> label="</xsl:text>
<xsl:call-template name="escape">
<xsl:with-param name="subject" select="$label"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:text>]&#10;</xsl:text>
</xsl:template>
<xsl:template name="escape">
<xsl:param name="subject"/> <!-- required -->
<xsl:call-template name="string-replace">
<xsl:with-param name="subject">
<xsl:call-template name="string-replace">
<xsl:with-param name="subject">
<xsl:call-template name="string-replace">
<xsl:with-param name="subject" select="$subject"/>
<xsl:with-param name="search" select="'\'"/>
<xsl:with-param name="replace" select="'\\'"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="search" select="'&quot;'"/>
<xsl:with-param name="replace" select="'\&quot;'"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="search" select="'&#10;'"/>
<xsl:with-param name="replace" select="'\n'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="string-replace">
<xsl:param name="subject"/>
<xsl:param name="search"/>
<xsl:param name="replace"/>
<xsl:choose>
<xsl:when test="contains($subject, $search)">
<xsl:variable name="before" select="substring-before($subject, $search)"/>
<xsl:variable name="after" select="substring-after($subject, $search)"/>
<xsl:value-of select="$before"/>
<xsl:value-of select="$replace"/>
<xsl:call-template name="string-replace">
<xsl:with-param name="subject" select="$after"/>
<xsl:with-param name="search" select="$search"/>
<xsl:with-param name="replace" select="$replace"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$subject"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,581 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
xml2text.xsl - transform Bison XML Report into plain text.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by Wojciech Polak <polak@gnu.org>.
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:bison="http://www.gnu.org/software/bison/">
<xsl:import href="bison.xsl"/>
<xsl:output method="text" encoding="UTF-8" indent="no"/>
<xsl:template match="/">
<xsl:apply-templates select="bison-xml-report"/>
</xsl:template>
<xsl:template match="bison-xml-report">
<xsl:apply-templates select="grammar" mode="reductions"/>
<xsl:apply-templates select="grammar" mode="useless-in-parser"/>
<xsl:apply-templates select="automaton" mode="conflicts"/>
<xsl:apply-templates select="grammar"/>
<xsl:apply-templates select="automaton"/>
</xsl:template>
<xsl:template match="grammar" mode="reductions">
<xsl:apply-templates select="nonterminals" mode="useless-in-grammar"/>
<xsl:apply-templates select="terminals" mode="unused-in-grammar"/>
<xsl:apply-templates select="rules" mode="useless-in-grammar"/>
</xsl:template>
<xsl:template match="nonterminals" mode="useless-in-grammar">
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text>Nonterminals useless in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="terminals" mode="unused-in-grammar">
<xsl:if test="terminal[@usefulness='unused-in-grammar']">
<xsl:text>Terminals unused in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
<xsl:sort select="@symbol-number" data-type="number"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="rules" mode="useless-in-grammar">
<xsl:variable name="set" select="rule[@usefulness='useless-in-grammar']"/>
<xsl:if test="$set">
<xsl:text>Rules useless in grammar&#10;</xsl:text>
<xsl:call-template name="style-rule-set">
<xsl:with-param name="rule-set" select="$set"/>
</xsl:call-template>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="grammar" mode="useless-in-parser">
<xsl:variable
name="set" select="rules/rule[@usefulness='useless-in-parser']"
/>
<xsl:if test="$set">
<xsl:text>Rules useless in parser due to conflicts&#10;</xsl:text>
<xsl:call-template name="style-rule-set">
<xsl:with-param name="rule-set" select="$set"/>
</xsl:call-template>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="grammar">
<xsl:text>Grammar&#10;</xsl:text>
<xsl:call-template name="style-rule-set">
<xsl:with-param
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
/>
</xsl:call-template>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:apply-templates select="terminals"/>
<xsl:apply-templates select="nonterminals"/>
</xsl:template>
<xsl:template name="style-rule-set">
<xsl:param name="rule-set"/>
<xsl:for-each select="$rule-set">
<xsl:apply-templates select=".">
<xsl:with-param name="pad" select="'3'"/>
<xsl:with-param name="prev-lhs">
<xsl:if test="position()>1">
<xsl:variable name="position" select="position()"/>
<xsl:value-of select="$rule-set[$position - 1]/lhs"/>
</xsl:if>
</xsl:with-param>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="grammar/terminals">
<xsl:text>Terminals, with rules where they appear&#10;&#10;</xsl:text>
<xsl:apply-templates select="terminal"/>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
<xsl:template match="grammar/nonterminals">
<xsl:text>Nonterminals, with rules where they appear&#10;&#10;</xsl:text>
<xsl:apply-templates select="nonterminal[@usefulness!='useless-in-grammar']"/>
</xsl:template>
<xsl:template match="terminal">
<xsl:value-of select="@name"/>
<xsl:call-template name="line-wrap">
<xsl:with-param name="first-line-length">
<xsl:choose>
<xsl:when test="string-length(@name) &gt; 66">0</xsl:when>
<xsl:otherwise>
<xsl:value-of select="66 - string-length(@name)" />
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="line-length" select="66" />
<xsl:with-param name="text">
<xsl:value-of select="concat(' (', @token-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:value-of select="concat(' ', @number)"/>
</xsl:for-each>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="nonterminal">
<xsl:value-of select="@name"/>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:text>&#10;</xsl:text>
<xsl:variable name="output">
<xsl:call-template name="line-wrap">
<xsl:with-param name="line-length" select="66" />
<xsl:with-param name="text">
<xsl:text> </xsl:text>
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>on@left:</xsl:text>
<xsl:for-each select="key('bison:ruleByLhs', @name)">
<xsl:value-of select="concat(' ', @number)"/>
</xsl:for-each>
</xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:text>on@right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:value-of select="concat(' ', @number)"/>
</xsl:for-each>
</xsl:if>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="translate($output, '@', ' ')" />
</xsl:template>
<xsl:template match="automaton" mode="conflicts">
<xsl:variable name="conflict-report">
<xsl:apply-templates select="state" mode="conflicts"/>
</xsl:variable>
<xsl:if test="string-length($conflict-report) != 0">
<xsl:value-of select="$conflict-report"/>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="state" mode="conflicts">
<xsl:variable name="conflict-counts">
<xsl:apply-templates select="." mode="bison:count-conflicts" />
</xsl:variable>
<xsl:variable
name="sr-count" select="substring-before($conflict-counts, ',')"
/>
<xsl:variable
name="rr-count" select="substring-after($conflict-counts, ',')"
/>
<xsl:if test="$sr-count > 0 or $rr-count > 0">
<xsl:value-of select="concat('State ', @number, ' conflicts:')"/>
<xsl:if test="$sr-count > 0">
<xsl:value-of select="concat(' ', $sr-count, ' shift/reduce')"/>
<xsl:if test="$rr-count > 0">
<xsl:value-of select="(',')"/>
</xsl:if>
</xsl:if>
<xsl:if test="$rr-count > 0">
<xsl:value-of select="concat(' ', $rr-count, ' reduce/reduce')"/>
</xsl:if>
<xsl:value-of select="'&#10;'"/>
</xsl:if>
</xsl:template>
<xsl:template match="automaton">
<xsl:apply-templates select="state">
<xsl:with-param name="pad" select="'3'"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="automaton/state">
<xsl:param name="pad"/>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:text>state </xsl:text>
<xsl:value-of select="@number"/>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:apply-templates select="itemset/item">
<xsl:with-param name="pad" select="$pad"/>
</xsl:apply-templates>
<xsl:apply-templates select="actions/transitions">
<xsl:with-param name="type" select="'shift'"/>
</xsl:apply-templates>
<xsl:apply-templates select="actions/errors"/>
<xsl:apply-templates select="actions/reductions"/>
<xsl:apply-templates select="actions/transitions">
<xsl:with-param name="type" select="'goto'"/>
</xsl:apply-templates>
<xsl:apply-templates select="solved-conflicts"/>
</xsl:template>
<xsl:template match="actions/transitions">
<xsl:param name="type"/>
<xsl:if test="transition[@type = $type]">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="transition[@type = $type]">
<xsl:with-param name="pad">
<xsl:call-template name="max-width-symbol">
<xsl:with-param name="node" select="transition[@type = $type]"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="actions/errors">
<xsl:if test="error">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="error">
<xsl:with-param name="pad">
<xsl:call-template name="max-width-symbol">
<xsl:with-param name="node" select="error"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="actions/reductions">
<xsl:if test="reduction">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="reduction">
<xsl:with-param name="pad">
<xsl:call-template name="max-width-symbol">
<xsl:with-param name="node" select="reduction"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="item">
<xsl:param name="pad"/>
<xsl:param name="prev-rule-number"
select="preceding-sibling::item[1]/@rule-number"/>
<xsl:apply-templates
select="key('bison:ruleByNumber', current()/@rule-number)"
>
<xsl:with-param name="itemset" select="'true'"/>
<xsl:with-param name="pad" select="$pad"/>
<xsl:with-param
name="prev-lhs"
select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
/>
<xsl:with-param name="point" select="@point"/>
<xsl:with-param name="lookaheads">
<xsl:apply-templates select="lookaheads"/>
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="rule">
<xsl:param name="itemset"/>
<xsl:param name="pad"/>
<xsl:param name="prev-lhs"/>
<xsl:param name="point"/>
<xsl:param name="lookaheads"/>
<xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:text> </xsl:text>
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="string(@number)"/>
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<!-- LHS -->
<xsl:choose>
<xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="lhs"/>
<xsl:text>:</xsl:text>
</xsl:otherwise>
</xsl:choose>
<!-- RHS -->
<xsl:for-each select="rhs/*">
<xsl:if test="position() = $point + 1">
<xsl:text> .</xsl:text>
</xsl:if>
<xsl:if test="$itemset = 'true' and name(.) != 'empty'">
<xsl:apply-templates select="."/>
</xsl:if>
<xsl:if test="$itemset != 'true'">
<xsl:apply-templates select="."/>
</xsl:if>
<xsl:if test="position() = last() and position() = $point">
<xsl:text> .</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="$lookaheads">
<xsl:value-of select="$lookaheads"/>
</xsl:if>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="symbol">
<xsl:text> </xsl:text>
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="empty">
<xsl:text> /* empty */</xsl:text>
</xsl:template>
<xsl:template match="lookaheads">
<xsl:text> [</xsl:text>
<xsl:apply-templates select="symbol"/>
<xsl:text>]</xsl:text>
</xsl:template>
<xsl:template match="lookaheads/symbol">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="transition">
<xsl:param name="pad"/>
<xsl:text> </xsl:text>
<xsl:call-template name="rpad">
<xsl:with-param name="str" select="string(@symbol)"/>
<xsl:with-param name="pad" select="number($pad) + 2"/>
</xsl:call-template>
<xsl:choose>
<xsl:when test="@type = 'shift'">
<xsl:text>shift, and go to state </xsl:text>
<xsl:value-of select="@state"/>
</xsl:when>
<xsl:when test="@type = 'goto'">
<xsl:text>go to state </xsl:text>
<xsl:value-of select="@state"/>
</xsl:when>
</xsl:choose>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="error">
<xsl:param name="pad"/>
<xsl:text> </xsl:text>
<xsl:call-template name="rpad">
<xsl:with-param name="str" select="string(@symbol)"/>
<xsl:with-param name="pad" select="number($pad) + 2"/>
</xsl:call-template>
<xsl:text>error</xsl:text>
<xsl:text> (</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>)</xsl:text>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="reduction">
<xsl:param name="pad"/>
<xsl:text> </xsl:text>
<xsl:call-template name="rpad">
<xsl:with-param name="str" select="string(@symbol)"/>
<xsl:with-param name="pad" select="number($pad) + 2"/>
</xsl:call-template>
<xsl:if test="@enabled = 'false'">
<xsl:text>[</xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="@rule = 'accept'">
<xsl:text>accept</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>reduce using rule </xsl:text>
<xsl:value-of select="@rule"/>
<xsl:text> (</xsl:text>
<xsl:value-of
select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
<xsl:text>)</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="@enabled = 'false'">
<xsl:text>]</xsl:text>
</xsl:if>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="solved-conflicts">
<xsl:if test="resolution">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="resolution"/>
</xsl:if>
</xsl:template>
<xsl:template match="resolution">
<xsl:text> Conflict between rule </xsl:text>
<xsl:value-of select="@rule"/>
<xsl:text> and token </xsl:text>
<xsl:value-of select="@symbol"/>
<xsl:text> resolved as </xsl:text>
<xsl:if test="@type = 'error'">
<xsl:text>an </xsl:text>
</xsl:if>
<xsl:value-of select="@type"/>
<xsl:text> (</xsl:text>
<xsl:value-of select="."/>
<xsl:text>).&#10;</xsl:text>
</xsl:template>
<xsl:template name="max-width-symbol">
<xsl:param name="node"/>
<xsl:variable name="longest">
<xsl:for-each select="$node">
<xsl:sort data-type="number" select="string-length(@symbol)"
order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="string-length(@symbol)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="$longest"/>
</xsl:template>
<xsl:template name="lpad">
<xsl:param name="str" select="''"/>
<xsl:param name="pad" select="0"/>
<xsl:variable name="diff" select="$pad - string-length($str)" />
<xsl:choose>
<xsl:when test="$diff &lt; 0">
<xsl:value-of select="$str"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="space">
<xsl:with-param name="repeat" select="$diff"/>
</xsl:call-template>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="rpad">
<xsl:param name="str" select="''"/>
<xsl:param name="pad" select="0"/>
<xsl:variable name="diff" select="$pad - string-length($str)"/>
<xsl:choose>
<xsl:when test="$diff &lt; 0">
<xsl:value-of select="$str"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
<xsl:call-template name="space">
<xsl:with-param name="repeat" select="$diff"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="space">
<xsl:param name="repeat">0</xsl:param>
<xsl:param name="fill" select="' '"/>
<xsl:if test="number($repeat) &gt;= 1">
<xsl:call-template name="space">
<xsl:with-param name="repeat" select="$repeat - 1"/>
<xsl:with-param name="fill" select="$fill"/>
</xsl:call-template>
<xsl:value-of select="$fill"/>
</xsl:if>
</xsl:template>
<xsl:template name="line-wrap">
<xsl:param name="line-length"/> <!-- required -->
<xsl:param name="first-line-length" select="$line-length"/>
<xsl:param name="text"/> <!-- required -->
<xsl:choose>
<xsl:when test="normalize-space($text) = ''" />
<xsl:when test="string-length($text) &lt;= $first-line-length">
<xsl:value-of select="concat($text, '&#10;')" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="break-pos">
<xsl:call-template name="ws-search">
<xsl:with-param name="text" select="$text" />
<xsl:with-param name="start" select="$first-line-length+1" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="substring($text, 1, $break-pos - 1)" />
<xsl:text>&#10;</xsl:text>
<xsl:call-template name="line-wrap">
<xsl:with-param name="line-length" select="$line-length" />
<xsl:with-param
name="text" select="concat(' ', substring($text, $break-pos+1))"
/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="ws-search">
<xsl:param name="text"/> <!-- required -->
<xsl:param name="start"/> <!-- required -->
<xsl:variable name="search-text" select="substring($text, $start)" />
<xsl:choose>
<xsl:when test="not(contains($search-text, ' '))">
<xsl:value-of select="string-length($text)+1" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of
select="$start + string-length(substring-before($search-text, ' '))"
/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,745 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
xml2html.xsl - transform Bison XML Report into XHTML.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by Wojciech Polak <polak@gnu.org>.
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:bison="http://www.gnu.org/software/bison/">
<xsl:import href="bison.xsl"/>
<xsl:output method="xml" encoding="UTF-8"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
indent="yes"/>
<xsl:template match="/">
<html>
<head>
<title>
<xsl:value-of select="bison-xml-report/filename"/>
<xsl:text> - GNU Bison XML Automaton Report</xsl:text>
</title>
<style type="text/css"><![CDATA[
body {
font-family: "Nimbus Sans L", Arial, sans-serif;
font-size: 9pt;
}
a:link {
color: #1f00ff;
text-decoration: none;
}
a:visited {
color: #1f00ff;
text-decoration: none;
}
a:hover {
color: red;
}
#menu a {
text-decoration: underline;
}
.i {
font-style: italic;
}
.pre {
font-family: monospace;
white-space: pre;
}
ol.decimal {
list-style-type: decimal;
}
ol.lower-alpha {
list-style-type: lower-alpha;
}
.point {
color: #cc0000;
}
#footer {
margin-top: 3.5em;
font-size: 7pt;
}
]]></style>
</head>
<body>
<xsl:apply-templates select="bison-xml-report"/>
<xsl:text>&#10;&#10;</xsl:text>
<div id="footer"><hr />This document was generated using
<a href="http://www.gnu.org/software/bison/" title="GNU Bison">
GNU Bison <xsl:value-of select="/bison-xml-report/@version"/></a>
XML Automaton Report.<br />
<!-- default copying notice -->
Verbatim copying and distribution of this entire page is
permitted in any medium, provided this notice is preserved.</div>
</body>
</html>
</xsl:template>
<xsl:template match="bison-xml-report">
<h1>GNU Bison XML Automaton Report</h1>
<p>
input grammar: <span class="i"><xsl:value-of select="filename"/></span>
</p>
<xsl:text>&#10;&#10;</xsl:text>
<h3>Table of Contents</h3>
<ul id="menu">
<li>
<a href="#reductions">Reductions</a>
<ul class="lower-alpha">
<li><a href="#nonterminals_useless_in_grammar">Nonterminals useless in grammar</a></li>
<li><a href="#terminals_unused_in_grammar">Terminals unused in grammar</a></li>
<li><a href="#rules_useless_in_grammar">Rules useless in grammar</a></li>
<xsl:if test="grammar/rules/rule[@usefulness='useless-in-parser']">
<li><a href="#rules_useless_in_parser">Rules useless in parser due to conflicts</a></li>
</xsl:if>
</ul>
</li>
<li><a href="#conflicts">Conflicts</a></li>
<li>
<a href="#grammar">Grammar</a>
<ul class="lower-alpha">
<li><a href="#grammar">Itemset</a></li>
<li><a href="#terminals">Terminal symbols</a></li>
<li><a href="#nonterminals">Nonterminal symbols</a></li>
</ul>
</li>
<li><a href="#automaton">Automaton</a></li>
</ul>
<xsl:apply-templates select="grammar" mode="reductions"/>
<xsl:apply-templates select="grammar" mode="useless-in-parser"/>
<xsl:apply-templates select="automaton" mode="conflicts"/>
<xsl:apply-templates select="grammar"/>
<xsl:apply-templates select="automaton"/>
</xsl:template>
<xsl:template match="grammar" mode="reductions">
<h2>
<a name="reductions"/>
<xsl:text> Reductions</xsl:text>
</h2>
<xsl:apply-templates select="nonterminals" mode="useless-in-grammar"/>
<xsl:apply-templates select="terminals" mode="unused-in-grammar"/>
<xsl:apply-templates select="rules" mode="useless-in-grammar"/>
</xsl:template>
<xsl:template match="nonterminals" mode="useless-in-grammar">
<h3>
<a name="nonterminals_useless_in_grammar"/>
<xsl:text> Nonterminals useless in grammar</xsl:text>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
<p class="pre">
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:text>&#10;&#10;</xsl:text>
</p>
</xsl:if>
</xsl:template>
<xsl:template match="terminals" mode="unused-in-grammar">
<h3>
<a name="terminals_unused_in_grammar"/>
<xsl:text> Terminals unused in grammar</xsl:text>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:if test="terminal[@usefulness='unused-in-grammar']">
<p class="pre">
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
<xsl:sort select="@symbol-number" data-type="number"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:text>&#10;&#10;</xsl:text>
</p>
</xsl:if>
</xsl:template>
<xsl:template match="rules" mode="useless-in-grammar">
<h3>
<a name="rules_useless_in_grammar"/>
<xsl:text> Rules useless in grammar</xsl:text>
</h3>
<xsl:text>&#10;</xsl:text>
<xsl:variable name="set" select="rule[@usefulness='useless-in-grammar']"/>
<xsl:if test="$set">
<p class="pre">
<xsl:call-template name="style-rule-set">
<xsl:with-param name="rule-set" select="$set"/>
</xsl:call-template>
<xsl:text>&#10;&#10;</xsl:text>
</p>
</xsl:if>
</xsl:template>
<xsl:template match="grammar" mode="useless-in-parser">
<xsl:variable
name="set" select="rules/rule[@usefulness='useless-in-parser']"
/>
<xsl:if test="$set">
<h2>
<a name="rules_useless_in_parser"/>
<xsl:text> Rules useless in parser due to conflicts</xsl:text>
</h2>
<xsl:text>&#10;</xsl:text>
<p class="pre">
<xsl:call-template name="style-rule-set">
<xsl:with-param name="rule-set" select="$set"/>
</xsl:call-template>
</p>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="grammar">
<h2>
<a name="grammar"/>
<xsl:text> Grammar</xsl:text>
</h2>
<xsl:text>&#10;</xsl:text>
<p class="pre">
<xsl:call-template name="style-rule-set">
<xsl:with-param
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
/>
</xsl:call-template>
</p>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:apply-templates select="terminals"/>
<xsl:apply-templates select="nonterminals"/>
</xsl:template>
<xsl:template name="style-rule-set">
<xsl:param name="rule-set"/>
<xsl:for-each select="$rule-set">
<xsl:apply-templates select=".">
<xsl:with-param name="pad" select="'3'"/>
<xsl:with-param name="prev-lhs">
<xsl:if test="position()>1">
<xsl:variable name="position" select="position()"/>
<xsl:value-of select="$rule-set[$position - 1]/lhs"/>
</xsl:if>
</xsl:with-param>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="automaton" mode="conflicts">
<h2>
<a name="conflicts"/>
<xsl:text> Conflicts</xsl:text>
</h2>
<xsl:text>&#10;&#10;</xsl:text>
<xsl:variable name="conflict-report">
<xsl:apply-templates select="state" mode="conflicts"/>
</xsl:variable>
<xsl:if test="string-length($conflict-report) != 0">
<p class="pre">
<xsl:copy-of select="$conflict-report"/>
<xsl:text>&#10;&#10;</xsl:text>
</p>
</xsl:if>
</xsl:template>
<xsl:template match="state" mode="conflicts">
<xsl:variable name="conflict-counts">
<xsl:apply-templates select="." mode="bison:count-conflicts" />
</xsl:variable>
<xsl:variable
name="sr-count" select="substring-before($conflict-counts, ',')"
/>
<xsl:variable
name="rr-count" select="substring-after($conflict-counts, ',')"
/>
<xsl:if test="$sr-count > 0 or $rr-count > 0">
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('#state_', @number)"/>
</xsl:attribute>
<xsl:value-of select="concat('State ', @number)"/>
</a>
<xsl:text> conflicts:</xsl:text>
<xsl:if test="$sr-count > 0">
<xsl:value-of select="concat(' ', $sr-count, ' shift/reduce')"/>
<xsl:if test="$rr-count > 0">
<xsl:value-of select="(',')"/>
</xsl:if>
</xsl:if>
<xsl:if test="$rr-count > 0">
<xsl:value-of select="concat(' ', $rr-count, ' reduce/reduce')"/>
</xsl:if>
<xsl:value-of select="'&#10;'"/>
</xsl:if>
</xsl:template>
<xsl:template match="grammar/terminals">
<h3>
<a name="terminals"/>
<xsl:text> Terminals, with rules where they appear</xsl:text>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
<p class="pre">
<xsl:apply-templates select="terminal"/>
</p>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
<xsl:template match="grammar/nonterminals">
<h3>
<a name="nonterminals"/>
<xsl:text> Nonterminals, with rules where they appear</xsl:text>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
<p class="pre">
<xsl:apply-templates
select="nonterminal[@usefulness!='useless-in-grammar']"
/>
</p>
</xsl:template>
<xsl:template match="terminal">
<b><xsl:value-of select="@name"/></b>
<xsl:value-of select="concat(' (', @token-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="nonterminal">
<b><xsl:value-of select="@name"/></b>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:text>&#10; </xsl:text>
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>on left:</xsl:text>
<xsl:for-each select="key('bison:ruleByLhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>&#10; </xsl:text>
</xsl:if>
<xsl:text>on right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</xsl:if>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="rule" mode="number-link">
<xsl:text> </xsl:text>
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('#rule_', @number)"/>
</xsl:attribute>
<xsl:value-of select="@number"/>
</a>
</xsl:template>
<xsl:template match="automaton">
<h2>
<a name="automaton"/>
<xsl:text> Automaton</xsl:text>
</h2>
<xsl:apply-templates select="state">
<xsl:with-param name="pad" select="'3'"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="automaton/state">
<xsl:param name="pad"/>
<xsl:text>&#10;&#10;</xsl:text>
<h3>
<a>
<xsl:attribute name="name">
<xsl:value-of select="concat('state_', @number)"/>
</xsl:attribute>
</a>
<xsl:text>state </xsl:text>
<xsl:value-of select="@number"/>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
<p class="pre">
<xsl:apply-templates select="itemset/item">
<xsl:with-param name="pad" select="$pad"/>
</xsl:apply-templates>
<xsl:apply-templates select="actions/transitions">
<xsl:with-param name="type" select="'shift'"/>
</xsl:apply-templates>
<xsl:apply-templates select="actions/errors"/>
<xsl:apply-templates select="actions/reductions"/>
<xsl:apply-templates select="actions/transitions">
<xsl:with-param name="type" select="'goto'"/>
</xsl:apply-templates>
<xsl:apply-templates select="solved-conflicts"/>
</p>
</xsl:template>
<xsl:template match="actions/transitions">
<xsl:param name="type"/>
<xsl:if test="transition[@type = $type]">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="transition[@type = $type]">
<xsl:with-param name="pad">
<xsl:call-template name="max-width-symbol">
<xsl:with-param name="node" select="transition[@type = $type]"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="actions/errors">
<xsl:if test="error">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="error">
<xsl:with-param name="pad">
<xsl:call-template name="max-width-symbol">
<xsl:with-param name="node" select="error"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="actions/reductions">
<xsl:if test="reduction">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="reduction">
<xsl:with-param name="pad">
<xsl:call-template name="max-width-symbol">
<xsl:with-param name="node" select="reduction"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="item">
<xsl:param name="pad"/>
<xsl:param name="prev-rule-number"
select="preceding-sibling::item[1]/@rule-number"/>
<xsl:apply-templates
select="key('bison:ruleByNumber', current()/@rule-number)"
>
<xsl:with-param name="itemset" select="'true'"/>
<xsl:with-param name="pad" select="$pad"/>
<xsl:with-param name="prev-lhs"
select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
/>
<xsl:with-param name="point" select="@point"/>
<xsl:with-param name="lookaheads">
<xsl:apply-templates select="lookaheads"/>
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="rule">
<xsl:param name="itemset"/>
<xsl:param name="pad"/>
<xsl:param name="prev-lhs"/>
<xsl:param name="point"/>
<xsl:param name="lookaheads"/>
<xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:if test="$itemset != 'true'">
<a>
<xsl:attribute name="name">
<xsl:value-of select="concat('rule_', @number)"/>
</xsl:attribute>
</a>
</xsl:if>
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="$itemset = 'true'">
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('#rule_', @number)"/>
</xsl:attribute>
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="string(@number)"/>
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="string(@number)"/>
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
<xsl:text> </xsl:text>
<!-- LHS -->
<xsl:choose>
<xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<span class="i">
<xsl:value-of select="lhs"/>
</span>
<xsl:text> &#8594;</xsl:text>
</xsl:otherwise>
</xsl:choose>
<!-- RHS -->
<xsl:for-each select="rhs/*">
<xsl:if test="position() = $point + 1">
<xsl:text> </xsl:text>
<span class="point">.</span>
</xsl:if>
<xsl:if test="$itemset = 'true' and name(.) != 'empty'">
<xsl:apply-templates select="."/>
</xsl:if>
<xsl:if test="$itemset != 'true'">
<xsl:apply-templates select="."/>
</xsl:if>
<xsl:if test="position() = last() and position() = $point">
<xsl:text> </xsl:text>
<span class="point">.</span>
</xsl:if>
</xsl:for-each>
<xsl:if test="$lookaheads">
<xsl:value-of select="$lookaheads"/>
</xsl:if>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="symbol">
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="name(key('bison:symbolByName', .)) = 'nonterminal'">
<span class="i"><xsl:value-of select="."/></span>
</xsl:when>
<xsl:otherwise>
<b><xsl:value-of select="."/></b>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="empty">
<xsl:text> &#949;</xsl:text>
</xsl:template>
<xsl:template match="lookaheads">
<xsl:text> [</xsl:text>
<xsl:apply-templates select="symbol"/>
<xsl:text>]</xsl:text>
</xsl:template>
<xsl:template match="lookaheads/symbol">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="transition">
<xsl:param name="pad"/>
<xsl:text> </xsl:text>
<xsl:call-template name="rpad">
<xsl:with-param name="str" select="string(@symbol)"/>
<xsl:with-param name="pad" select="number($pad) + 2"/>
</xsl:call-template>
<xsl:choose>
<xsl:when test="@type = 'shift'">
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('#state_', @state)"/>
</xsl:attribute>
<xsl:value-of select="concat('shift, and go to state ', @state)"/>
</a>
</xsl:when>
<xsl:when test="@type = 'goto'">
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('#state_', @state)"/>
</xsl:attribute>
<xsl:value-of select="concat('go to state ', @state)"/>
</a>
</xsl:when>
</xsl:choose>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="error">
<xsl:param name="pad"/>
<xsl:text> </xsl:text>
<xsl:call-template name="rpad">
<xsl:with-param name="str" select="string(@symbol)"/>
<xsl:with-param name="pad" select="number($pad) + 2"/>
</xsl:call-template>
<xsl:text>error</xsl:text>
<xsl:text> (</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>)</xsl:text>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="reduction">
<xsl:param name="pad"/>
<xsl:text> </xsl:text>
<xsl:call-template name="rpad">
<xsl:with-param name="str" select="string(@symbol)"/>
<xsl:with-param name="pad" select="number($pad) + 2"/>
</xsl:call-template>
<xsl:if test="@enabled = 'false'">
<xsl:text>[</xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="@rule = 'accept'">
<xsl:text>accept</xsl:text>
</xsl:when>
<xsl:otherwise>
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('#rule_', @rule)"/>
</xsl:attribute>
<xsl:value-of select="concat('reduce using rule ', @rule)"/>
</a>
<xsl:text> (</xsl:text>
<xsl:value-of
select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"
/>
<xsl:text>)</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="@enabled = 'false'">
<xsl:text>]</xsl:text>
</xsl:if>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="solved-conflicts">
<xsl:if test="resolution">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="resolution"/>
</xsl:if>
</xsl:template>
<xsl:template match="resolution">
<xsl:text> Conflict between </xsl:text>
<a>
<xsl:attribute name="href">
<xsl:value-of select="concat('#rule_', @rule)"/>
</xsl:attribute>
<xsl:value-of select="concat('rule ',@rule)"/>
</a>
<xsl:text> and token </xsl:text>
<xsl:value-of select="@symbol"/>
<xsl:text> resolved as </xsl:text>
<xsl:if test="@type = 'error'">
<xsl:text>an </xsl:text>
</xsl:if>
<xsl:value-of select="@type"/>
<xsl:text> (</xsl:text>
<xsl:value-of select="."/>
<xsl:text>).&#10;</xsl:text>
</xsl:template>
<xsl:template name="max-width-symbol">
<xsl:param name="node"/>
<xsl:variable name="longest">
<xsl:for-each select="$node">
<xsl:sort data-type="number" select="string-length(@symbol)"
order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="string-length(@symbol)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="$longest"/>
</xsl:template>
<xsl:template name="lpad">
<xsl:param name="str" select="''"/>
<xsl:param name="pad" select="0"/>
<xsl:variable name="diff" select="$pad - string-length($str)" />
<xsl:choose>
<xsl:when test="$diff &lt; 0">
<xsl:value-of select="$str"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="space">
<xsl:with-param name="repeat" select="$diff"/>
</xsl:call-template>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="rpad">
<xsl:param name="str" select="''"/>
<xsl:param name="pad" select="0"/>
<xsl:variable name="diff" select="$pad - string-length($str)"/>
<xsl:choose>
<xsl:when test="$diff &lt; 0">
<xsl:value-of select="$str"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
<xsl:call-template name="space">
<xsl:with-param name="repeat" select="$diff"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="space">
<xsl:param name="repeat">0</xsl:param>
<xsl:param name="fill" select="' '"/>
<xsl:if test="number($repeat) &gt;= 1">
<xsl:call-template name="space">
<xsl:with-param name="repeat" select="$repeat - 1"/>
<xsl:with-param name="fill" select="$fill"/>
</xsl:call-template>
<xsl:value-of select="$fill"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,5 @@
@echo off
rem edit if PGO scripts are present and are to be used
rem set PHP_SDK_PGO_TOOLS_ROOT_PATH=%PHP_SDK_ROOT_PATH%\pgo
rem set PATH=%PHP_SDK_PGO_TOOLS_ROOT_PATH%\bin;%PATH%
set PGSQL_TEST_CONNSTR=host=127.0.0.1 dbname=test port=5432 user=test password=test
set PDO_PGSQL_TEST_DSN=pgsql:host=127.0.0.1 port=5432 dbname=test user=test password=test

View File

@@ -0,0 +1,47 @@
@echo off
rem These are default ports for the servers used for the training. If these
rem ports are changed in the config templates, the commands have to be
rem adjusted as well. New servers have to be added here as well. Run this
rem file on the elevated shell before starting the PGO environment setup
rem using the relevant port numbers, especially for unattended PGO builds.
rem We add opens inbound ports from the default PGO config templates and
rem and the one increment by 1, just co cover a simple case the port number
rem was incremented by the auto configuration.
rem
rem Alternatively, the firewall can be disabled on the build host.
rem The commands to disable\enable firewall are
rem netsh advfirewall set allprofiles state on
rem netsh advfirewall set allprofiles state off
@echo on
rem NGINX
netsh advfirewall firewall add rule name="NGINX for PGO" dir=in action=allow program="C:\php-snap-build\php-sdk\pgo\work\server\nginx\nginx.exe" profile=private
for \l %%p in (8081, 1, 8091) do (
netsh advfirewall firewall add rule name="Open Port %%p for PHP PGO" dir=in action=allow protocol=TCP localport=%%p profile=private
netsh advfirewall firewall add rule name="Open Port %%p for PHP PGO" dir=in action=allow protocol=UDP localport=%%p profile=private
)
netsh advfirewall firewall add rule name="Open Port 80 for PHP PGO" dir=in action=allow protocol=TCP localport=80 profile=private
netsh advfirewall firewall add rule name="Open Port 80 for PHP PGO" dir=in action=allow protocol=UDP localport=80 profile=private
rem MariaDB
netsh advfirewall firewall add rule name="MariaDB for PGO" dir=in action=allow program="c:\php-snap-build\php-sdk\pgo\work\server\mariadb\bin\mysqld.exe" profile=private
netsh advfirewall firewall add rule name="Open Port 3307 for PHP PGO" dir=in action=allow protocol=TCP localport=3307 profile=private
netsh advfirewall firewall add rule name="Open Port 3307 for PHP PGO" dir=in action=allow protocol=UDP localport=3307 profile=private
netsh advfirewall firewall add rule name="Open Port 3308 for PHP PGO" dir=in action=allow protocol=TCP localport=3308 profile=private
netsh advfirewall firewall add rule name="Open Port 3308 for PHP PGO" dir=in action=allow protocol=UDP localport=3308 profile=private
rem Postgres
netsh advfirewall firewall add rule name="Open Port 5434 for PHP PGO" dir=in action=allow protocol=TCP localport=5434 profile=private
netsh advfirewall firewall add rule name="Open Port 5434 for PHP PGO" dir=in action=allow protocol=UDP localport=5434 profile=private
netsh advfirewall firewall add rule name="Open Port 5435 for PHP PGO" dir=in action=allow protocol=TCP localport=5435 profile=private
netsh advfirewall firewall add rule name="Open Port 5435 for PHP PGO" dir=in action=allow protocol=UDP localport=5435 profile=private
rem PHP
netsh advfirewall firewall add rule name="Open Port 9001 for PHP PGO" dir=in action=allow protocol=TCP localport=9001 profile=private
netsh advfirewall firewall add rule name="Open Port 9001 for PHP PGO" dir=in action=allow protocol=UDP localport=9001 profile=private
netsh advfirewall firewall add rule name="Open Port 9002 for PHP PGO" dir=in action=allow protocol=TCP localport=9002 profile=private
netsh advfirewall firewall add rule name="Open Port 9002 for PHP PGO" dir=in action=allow protocol=UDP localport=9002 profile=private

View File

@@ -3,12 +3,12 @@ rem Task batch example.
rem Create a task, put an action with the following data:
rem Action: start a program
rem Program/script: C:\php-sdk\bin\task.exe
rem Add arguments: "C:\php-sdk\phpsdk-starter.bat -c vc14 -a x64 -t C:\php-sdk\unattended-build-task.bat"
rem Add arguments: "C:\php-sdk\phpsdk-starter.bat -c vc15 -a x64 -t C:\php-sdk\unattended-build-task.bat"
rem Run the task
set LOG_NAME=%PHP_SDK_VC%-%PHP_SDK_ARCH%-task.log
pushd C:\php-sdk\php70\vc14\x64\php-src
pushd C:\php-sdk\php72\vc14\x64\php-src
git pull --rebase > %LOG_NAME% 2>&1

26
lib/php/autoload.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
spl_autoload_register(function($name) {
$fl = dirname(__FILE__) . DIRECTORY_SEPARATOR . "libsdk" . DIRECTORY_SEPARATOR . $name . ".php";
if (file_exists($fl)) {
require_once $fl;
}
});
spl_autoload_register(function($name) {
$fl = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "cases" . DIRECTORY_SEPARATOR . $name . ".php";
if (file_exists($fl)) {
require_once $fl;
}
});
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@@ -15,12 +15,13 @@ class Fetcher
protected $series;
public function __construct(string $host, int $port, string $arch = NULL, string $stability = NULL, Series $series = NULL)
public function __construct(string $host, int $port, string $scheme = "https", string $arch = NULL, string $stability = NULL, Series $series = NULL)
{/*{{{*/
$this->stability = $stability;
$this->arch = $arch;
$this->host = $host;
$this->port = $port;
$this->scheme = $scheme;
}/*}}}*/
public function getSeries() : Series
@@ -35,11 +36,23 @@ class Fetcher
/* TODO more robust implementation. */
/* TODO implement indicator. */
public function getByUri($uri) : string
public function getByUri(string $uri, int $retries = 3) : string
{/*{{{*/
$url = "http://{$this->host}:{$this->port}$uri";
$url = "{$this->scheme}://{$this->host}:{$this->port}$uri";
$ret = false;
return $this->download($url);
retry:
try {
$ret = $this->download($url);
} catch (Exception $e) {
if ($retries > 0) {
sleep(1);
$retries--;
goto retry;
}
}
return $ret;
}/*}}}*/
/*protected function fetch($uri) : string

View File

@@ -13,6 +13,7 @@ class Manager
protected $path;
protected $series;
protected $fetcher;
protected $updatesFlag = NULL;
public function __construct(string $path, string $stability, string $arch)
{/*{{{*/
@@ -23,7 +24,8 @@ class Manager
$host = Config::getDepsHost();
$port = Config::getDepsPort();
$fetcher = new Fetcher($host, $port, $this->arch, $this->stability);
$scheme = Config::getDepsUriScheme();
$fetcher = new Fetcher($host, $port, $scheme, $this->arch, $this->stability);
$series = new Series($this->stability, $this->arch, $this->cache, NULL);
$fetcher->setSeries($series);
$series->setFetcher($fetcher);
@@ -39,7 +41,12 @@ class Manager
public function updatesAvailable() : bool
{/*{{{*/
return $this->series->updatesAvailable() || !file_exists(Config::getDepsLocalPath());
if (!is_null($this->updatesFlag)) {
return $this->updatesFlag;
}
$this->updatesFlag = $this->series->updatesAvailable() || !file_exists(Config::getDepsLocalPath());
return $this->updatesFlag;
}/*}}}*/
/* FIXME implement rollback */

View File

@@ -2,11 +2,12 @@
namespace SDK\Build\Dependency;
use SDK\Config;
use SDK\Exception;
use SDK\{Config, Exception, FileOps};
class Package
{
use FileOps;
protected $name;
protected $series;
protected $fetcher;
@@ -44,15 +45,8 @@ class Package
if (!$this->filepath || !file_exists($this->filepath)) {
throw new Exception("Invalid filepath '{$this->filepath}'");
}
$zip = new \ZipArchive;
$ret = $zip->open($this->filepath);
if (true === $ret) {
$zip->extractTo($path);
$zip->close();
} else {
throw new Exception("Failed to unpack, error code '$ret'");
}
$this->unzip($this->filepath, $path);
}/*}}}*/
public function cleanup() : void

View File

@@ -0,0 +1,218 @@
<?php
namespace SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces\Server;
use SDK\Build\PGO\PHP\CLI;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
abstract class PHP
{
protected $php_root;
protected $php_ext_root;
protected function setupPaths()
{
$this->php_root = $this->getRootDir();
if ($this->isDist()) {
$this->php_ext_root = $this->php_root . DIRECTORY_SEPARATOR . "ext";
if (!file_exists($this->php_ext_root)) {
throw new Exception("Extension dir '{$this->php_ext_root}' doesn't exist.");
}
} else {
$this->php_ext_root = $this->php_root;
}
}
/* TODO Might be improved. */
public function isDist() : bool
{
return !file_exists("Makefile") && file_exists("php.exe");
}
protected function createEnv() : array
{
$env = getenv();
if (!$this->isDist()) {
$deps_root = SDKConfig::getDepsLocalPath();
foreach ($env as $k => $v) {
if (strtoupper($k) == "PATH") {
$env[$k] = "$deps_root" . DIRECTORY_SEPARATOR . "bin;" . $env[$k];
break;
}
}
}
return $env;
}
public function getExtRootDir() : string
{
return $this->php_ext_root;
}
public function getRootDir() : string
{
if ($this->php_root) {
return $this->php_root;
}
/* XXX adapt for any possible PHP variants. */
$root = getenv("PHP_SDK_PGO_TEST_PHP_ROOT");
if (!$root) {
if (!$this->isDist()) {
$s = file_get_contents("Makefile");
if (preg_match(",BUILD_DIR=(.+),", $s, $m) > 0) {
$root = trim($m[1]);
}
}
}
if (!file_exists($root)) {
throw new Exception("'$root' doesn't exist.");
}
return $root;
}
public function getVersion(bool $short = false) : string
{
$ret = NULL;
$cli = new CLI($this->conf, $this->scenario);
$out = shell_exec($cli->getExeFilename() . " -n -v");
if ($short) {
if (preg_match(",PHP (\d+\.\d+),", $out, $m)) {
$ret = $m[1];
}
} else {
if (preg_match(",PHP ([^ ]+),", $out, $m)) {
$ret = $m[1];
}
}
if (is_null($ret)) {
throw new Exception("Failed to determine the test PHP version.");
}
return $ret;
}
public function isThreadSafe() : bool
{
$cli = new CLI($this->conf, $this->scenario);
$out = shell_exec($cli->getExeFilename() . " -n -v");
if (preg_match(",NTS,", $out, $m) > 0) {
return false;
}
return true;
}
public function is64bit() : bool
{
$cli = new CLI($this->conf, $this->scenario);
$out = shell_exec($cli->getExeFilename() . " -n -v");
if (preg_match(",x64,", $out, $m) > 0) {
return true;
}
return false;
}
/* Need to cleanup it somewhere. */
public function getIniFilename()
{
$ret = tempnam(sys_get_temp_dir(), "ini");
$tpl_vars = array(
$this->conf->buildTplVarName("php", "extension_dir") => $this->php_ext_root,
$this->conf->buildTplVarName("php", "error_log") => $this->getRootDir() . DIRECTORY_SEPARATOR . "pgo_run_error.log",
);
$k = $this->is64bit() ? "x64" : "x86";
$scenario_vars = (array)$this->conf->getSectionItem("php", "scenario", $this->scenario, "ini", $k);
if ($scenario_vars) {
foreach ($scenario_vars as $k => $v) {
//$tpl_vars[$this->conf->buildTplVarName("php", "scenario", $this->scenario, str_replace(array(".", "-"), "_", $k))] = $v;
$tpl_vars[$this->conf->buildTplVarName("php", str_replace(array(".", "-"), "_", $k))] = $v;
}
}
$this->conf->processTplFile(
$this->getIniTplFilename(),
$ret,
$tpl_vars
);
return $ret;
}
protected function getIniTplFilename()
{
$tpl_path = $this->conf->getTplDir("php");
$version = $this->getVersion(true);
$ts = $this->isThreadSafe() ? "ts" : "nts";
$construct = $tpl_path . DIRECTORY_SEPARATOR . "php-$version-pgo-$ts" . ("default" == $this->scenario ? "" : "-{$this->scenario}") . ".ini";
if (!file_exists($construct)) {
throw new Exception("Couldn't locate PHP config under '$construct'.");
}
return $construct;
}
public function exec(string $php_cmd, string $args = NULL, array $extra_env = array()) : int
{
$env = $this->createEnv();
$exe = $this->getExeFilename();
$ini = $this->getIniFilename();
$cert_path = getenv("PHP_SDK_ROOT_PATH") . "\\msys2\\usr\\ssl\\cert.pem";
$ini .= " -d curl.cainfo=$cert_path";
$spent_key = array();
foreach ($env as $k0 => &$v0) {
foreach ($extra_env as $k1 => $v1) {
if (strtoupper($k0) == strtoupper($k1)) {
/* XXX some more things could require extra handling. */
if (strtoupper($k0) == "PATH") {
$v0 = "$v1;$v0";
} else {
$v0 = $v1;
}
$spent_key[] = $k1;
break;
}
}
}
foreach ($extra_env as $k => $v) {
if (in_array($k, $spent_key)) {
continue;
}
$env[$k] = $v;
}
$cmd = "$exe -n -c $ini " . ($args ? "$args " : "") . "$php_cmd";
$desc = array(
0 => array("file", "php://stdin", "r"),
1 => array("file", "php://stdout", "w"),
2 => array("file", "php://stderr", "w")
);
$p = proc_open($cmd, $desc, $pipes, $this->getRootDir(), $env);
return proc_close($p);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces;
class Server
{
public function getName() : string
{
return $this->name;
}
public function getPhp() : Interfaces\PHP
{
return $this->php;
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool;
class TrainingCase
{
use FileOps;
const TYPE_WEB = "web";
const TYPE_CLI = "cli";
protected $stat = array();
public function getType() : string
{
$type = $this->conf->getSectionItem($this->getName(), "type");
if (!$type) {
$type = "web";
}
return $type;
}
public function run() : void
{
$training = new Tool\Training($this->conf, $this);
$pgo = new Tool\PGO($this->conf, $this->php);
echo "Running " . $this->getName() . " training.\n";
$max_runs = $this->max_runs ?? 1;
$max_runs = (int)$max_runs > 0 ? $max_runs : 1;
$training->run($max_runs, $stat);
if ($this->getType() == "web") {
echo "HTTP responses:\n";
foreach ($stat["http_code"] as $code => $num) {
printf(" %d received %d times\n", $code, $num);
}
if (count($stat["not_ok"]) > 0) {
foreach($stat["not_ok"] as $st) {
echo "Code: $st[http_code], URL: $st[url]", ($st["redirect_url"] ? ", Redirected to: $st[redirect_url]" : ""), "\n";
}
printf("\033[31m WARNING: Not all HTTP responses have indicated success, the PGO data might be unsuitable!\033[0m\n");
}
}
echo $this->getName() . " training complete.\n";
echo "Dumping PGO data for " . $this->getName() . ".\n";
$pgo->dump();
echo "Finished dumping training data for " . $this->getName() . ".\n";
}
public function getHttpPort() : string
{
$port = $this->conf->getSectionItem($this->getName(), "http_port");
if (!$port) {
$port = $this->conf->getNextPort();
$this->conf->setSectionItem($this->getName(), "http_port", $port);
}
return $port;
}
public function getHttpHost() : string
{
$host = $this->conf->getSectionItem($this->getName(), "http_host");
if (!$host) {
$srv = $this->conf->getSrv(
$this->conf->getSectionItem($this->getName(), "srv_http")
);
if ($srv) {
$host = $this->conf->getSectionItem($srv->getName(), "host");
$this->conf->setSectionItem($this->getName(), "http_host", $host);
}
}
return $host;
}
protected function getDbConf(string $item) : string
{
$val = $this->conf->getSectionItem($this->getName(), "db_$item");
if (!$val) {
$srv = $this->conf->getSrv(
$this->conf->getSectionItem($this->getName(), "srv_db")
);
if ($srv) {
$val = $this->conf->getSectionItem($srv->getName(), $item);
$this->conf->setSectionItem($this->getName(), "db_$item", $val);
}
}
return $val;
}
public function getDbPass() : string
{
return $this->getDbConf("pass");
}
public function getDbUser() : string
{
return $this->getDbConf("user");
}
public function getDbHost() : string
{
return $this->getDbConf("host");
}
public function getDbPort() : string
{
return $this->getDbConf("port");
}
public function httpStatusOk(int $status) : bool
{
$ok = array();
$ok = array_merge($ok, range(200, 206));
$ok = array_merge($ok, range(300, 307));
return in_array($status, $ok);
}
public function probeUrl(string $url) : bool
{
$ret = false;
$c = curl_init($url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_exec($c);
if (!curl_errno($c)) {
$st = curl_getinfo($c, CURLINFO_HTTP_CODE);
$ret = $this->httpStatusOk((int)$st);
}
curl_close($c);
return $ret;
}
}

View File

@@ -0,0 +1,371 @@
<?php
namespace SDK\Build\PGO;
use SDK\{Config as SDKConfig, Exception};
class Config
{
const MODE_INIT = 0;
const MODE_RUN = 1;
const MODE_REINIT = 2; /* currently unused */
const MODE_CHECK_INIT = 3;
protected $mode;
protected $last_port = 8081;
protected $sections = array();
protected $scenario = "default";
protected $tpl_vars = array();
protected $srv = array();
public function __construct(int $mode = MODE_RUN)
{
if (self::MODE_CHECK_INIT == $mode) {
// XXX The check is simple right now, so this is sufficient.
return;
}
if (!$this->isInitialized()) {
$this->initWorkDir();
}
if (self::MODE_REINIT == $mode) {
$fn = $this->getWorkSectionsFilename();
if (file_exists($fn)) {
unlink($fn);
}
$mode = self::MODE_INIT;
}
$this->mode = $mode;
$base = getenv("PHP_SDK_ROOT_PATH");
if (self::MODE_INIT == $mode) {
foreach (array("nginx", "mariadb", "postgresql", "php") as $i) {
$this->importSectionFromDir($i, $this->getTplDir() . DIRECTORY_SEPARATOR . $i);
}
} else if (self::MODE_RUN == $mode) {
$fn = $this->getWorkSectionsFilename();
if (!file_exists($fn)) {
throw new Exception("Required config doesn't exist under '$fn'.");
}
$s = file_get_contents($fn);
$this->sections = json_decode($s, true);
foreach($this->sections as $k => $v) {
$this->importTplVars($k, $v);
}
} else {
throw new Exception("Unknown config mode '$mode'.");
}
}
protected function initWorkDir() : void
{
if (!mkdir($this->getWorkDir())) {
throw new Exception("Failed to create " . $this->getWorkDir());
}
}
public function isInitialized()
{
/* XXX Could be some better check. */
return is_dir($this->getWorkDir());
}
public function getToolsDir() : string
{
$base = $this->getWorkDir();
return $base . DIRECTORY_SEPARATOR . "tools";
}
public function getWorkDir() : string
{
$base = getenv("PHP_SDK_ROOT_PATH");
return $base . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "work";
}
public function getPkgCacheDir() : string
{
$base = $this->getWorkDir();
return $base . DIRECTORY_SEPARATOR . "package_cache";
}
public function getJobDir(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "job";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getSrvDir(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "server";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getHtdocs(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "htdocs";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getTplDir(string $name = NULL) : string
{
$ret = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "tpl";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getCaseWorkDir(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "htdocs";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getCasesTplDir(string $name = NULL) : string
{
$ret = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "cases";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function sectionItemExists(...$args) : bool
{
$i = 0;
$k = strtolower($args[$i]);
$it = $this->sections;
while (array_key_exists($k, $it)) {
$it = $it[$k];
if (++$i >= count($args)) break;
$k = strtolower($args[$i]);
}
return $i == count($args);
}
public function getSectionItem(...$args)
{
$i = 0;
$k = strtolower($args[$i]);
$it = $this->sections;
while (array_key_exists($k, $it)) {
$it = $it[$k];
if (++$i >= count($args)) break;
$k = strtolower($args[$i]);
}
if ($i != count($args)) {
return NULL;
}
return $it;
}
public function setSectionItem(...$args) : void
{
$val = array_pop($args);
$i = 0;
$k = strtolower($args[$i]);
$it = &$this->sections;
while (true) {
$it = &$it[$k];
if (++$i >= count($args)) break;
$k = strtolower($args[$i]);
}
$it = $val;
$this->syncTplVars();
$this->dump();
}
public function importSectionFromDir(string $name, string $dir) : void
{
$fn = $dir . DIRECTORY_SEPARATOR . "phpsdk_pgo.json";
if (!file_exists($fn)) {
throw new Exception("Couldn't import section, file '$fn' doesn't exist.");
}
$s = file_get_contents($fn);
$this->setSectionItem($name, json_decode($s, true));
}
protected function syncTplVars() : void
{
$this->tpl_vars = array();
foreach ($this->sections as $k => $v) {
$this->importTplVars($k, $v);
}
}
public function buildTplVarName(...$args) : string
{
$tpl_k = array("PHP_SDK_PGO");
foreach ($args as $a) {
$tpl_k[] = strtoupper($a);
}
return implode("_", $tpl_k);
}
protected function importTplVars(string $section_name, array $section) : void
{
foreach($section as $k0 => $v0) {
if (is_array($v0)) {
if (substr($k0, -4) == ":env") {
/* Don't put env vars as tpl vars for now. */
continue;
}
$this->importTplVars($section_name . "_" . $k0, $v0);
} else {
$tpl_k = $this->buildTplVarName($section_name, $k0);
$this->tpl_vars[$tpl_k] = $v0;
}
}
}
public function processTpl(string $s, array $additional_vars = array()) : string
{
$vars = array_merge($this->tpl_vars, $additional_vars);
$s = str_replace(array_keys($vars), array_values($vars), $s);
return $s;
}
public function processTplFile(string $tpl_fn, string $dst_fn, array $additional_vars = array()) : void
{
if (!file_exists($tpl_fn)) {
throw new Exception("Template file '$fn' doesn't exist.");
}
$s = file_get_contents($tpl_fn);
if (false === $s) {
throw new Exception("Couldn't read '$tpl_fn'.");
}
$s = $this->processTpl($s, $additional_vars);
if (false === file_put_contents($dst_fn, $s)) {
throw new Exception("Failed to write '$dst_fn'.");
}
}
public function getWorkSectionsFilename()
{
return $this->getWorkDir() . DIRECTORY_SEPARATOR . "phpsdk_pgo.json";
}
public function dump(string $fn = NULL) : void
{
$fn = $fn ? $fn : $this->getWorkSectionsFilename();
$s = json_encode($this->sections, JSON_PRETTY_PRINT);
$ret = file_put_contents($fn, $s);
if (false === $ret || strlen($s) !== $ret) {
throw new Exception("Errors with writing to '$fn'.");
}
}
public function setScenario(string $scenario) : void
{
if (!in_array($scenario, array("default", "cache"), true)) {
throw new Exception("Unknown scenario '$scenario'.");
}
$this->scenario = $scenario;
}
public function getScenario() : string
{
return $this->scenario;
}
public function getNextPort() : int
{
return ++$this->last_port;
}
public function setLastPort(int $port) : void
{
$this->last_port = $port;
}
public function getSdkPhpCmd() : string
{
return getenv("PHP_SDK_PHP_CMD");
}
public function addSrv($item) : void
{
$name = strtolower($item->getName());
if (isset($this->srv[$name])) {
throw new Exception("Server '$name' already exists.");
}
/* XXX Additional checks could not harm. */
$this->srv[$name] = $item;
}
public function getSrv(?string $name = NULL)
{
$ret = NULL;
$name = strtolower($name);
if (!$name) {
return NULL;
} else if ("all" == $name) {
return $this->srv;
} else if (isset($this->srv[$name])) {
return $this->srv[$name];
}
return $ret;
}
}

View File

@@ -0,0 +1,256 @@
<?php
namespace SDK\Build\PGO;
use SDK\{Config as SDKConfig, Exception, Lock};
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Server\{MariaDB, NGINX, PostgreSQL};
use SDK\Build\PGO\PHP;
use SDK\Build\PGO\Tool\{PGO, PackageWorkman};
use SDK\Build\PGO\Interfaces\TrainingCase;
use SDK\Build\PGO\TrainingCaseIterator;
/* TODO add bench action */
class Controller
{
protected $cmd;
protected $scenario;
protected $conf;
public function __construct(string $cmd, ?string $scenario)
{
$this->cmd = $cmd;
if (NULL == $scenario) {
$scenario = "default";
}
$this->scenario = $scenario;
}
protected function vitalizeSrv()
{
$all = $this->conf->getSrv("all");
if (empty($all)) {
$php_fcgi_tcp = new PHP\FCGI($this->conf, true);
$this->conf->addSrv(new NGINX($this->conf, $php_fcgi_tcp));
$this->conf->addSrv(new MariaDB($this->conf));
/* Uncomment to enable PostgreSQL*/
/* $this->conf->addSrv(new PostgreSQL($this->conf));*/
$all = $this->conf->getSrv("all");
}
return $all;
}
protected function setupConfig($cmd)
{
switch ($cmd) {
default:
throw new Exception("Unknown action '{$cmd}'.");
break;
case "check_init":
$cnf = new PGOConfig(PGOConfig::MODE_CHECK_INIT);
break;
case "init":
$cnf = new PGOConfig(PGOConfig::MODE_INIT);
break;
case "train":
case "up":
case "down":
$cnf = new PGOConfig(PGOConfig::MODE_RUN);
}
$cnf->setScenario($this->scenario);
return $cnf;
}
public function handle($force)
{
/*$mode = (int)("init" !== $this->cmd);
$mode = (PGOConfig::MODE_INIT == $mode && $force) ? PGOConfig::MODE_REINIT : $mode;
$this->conf = new PGOConfig("init" !== $this->cmd);
$this->conf->setScenario($this->scenario);*/
$this->conf = $this->setupConfig($this->cmd);
switch ($this->cmd) {
default:
throw new Exception("Unknown action '{$this->cmd}'.");
break;
case "init":
$lk = new Lock("pgo_init");
if (!$lk->locked()) {
echo "Another process runs initialization right now, waiting.", PHP_EOL;
$lk->exclusive(true);
echo "Another process finished running initialization, I quit as well.", PHP_EOL;
return;
}
$this->init($force);
break;
case "train":
$lk = new Lock("pgo_train");
if (!$lk->locked()) {
echo "Another process runs training right now, I have to wait.", PHP_EOL;
$lk->exclusive(true);
echo "Another process finished training, I may continue.", PHP_EOL;
}
$this->train();
break;
case "up":
$this->up();
break;
case "down":
$this->down($force);
break;
case "check_init":
// pass
break;
}
}
protected function initWorkDirs() : void
{
$dirs = array(
$this->conf->getSrvDir(),
$this->conf->getToolsDir(),
$this->conf->getHtdocs(),
$this->conf->getJobDir(),
$this->conf->getPkgCacheDir(),
);
foreach ($dirs as $dir) {
if (!is_dir($dir)) {
if (!mkdir($dir)) {
throw new Exception("Failed to create '$dir'.");
}
}
}
}
protected function prepareStandaloneTools(PackageWorkman $pw, bool $force = false) : void
{
$php = new PHP\CLI($this->conf);
$composer = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer.phar";
if (!file_exists($composer) || $force) {
/* XXX this needs to go into the config, specifically for composer maybe even separate class. */
$url = "https://getcomposer.org/installer";
$tool = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer-setup.php";
$pw->fetch($url, $tool, $force);
$php->exec("$tool --install-dir=" . $this->conf->getToolsDir());
unlink($tool);
}
}
public function init(bool $force = false)
{
echo "\nInitializing PGO training environment.\n\n";
$this->initWorkDirs();
$pw = new PackageWorkman($this->conf);
$this->prepareStandaloneTools($pw, $force);
$srvs = $this->vitalizeSrv();
foreach ($srvs as $srv) {
$srv->prepareInit($pw, $force);
}
foreach (new TrainingCaseIterator($this->conf) as $handler) {
$handler->prepareInit($pw, $force);
}
foreach ($srvs as $srv) {
$srv->init();
echo "\n";
}
echo "\n";
foreach (new TrainingCaseIterator($this->conf) as $handler) {
$handler->init();
echo "\n";
}
echo "PGO training environment Initialization complete.\n";
}
public function isInitialized()
{
return $this->conf->isinitialized();
}
public function train()
{
if (!$this->isInitialized()) {
throw new Exception("PGO training environment is not initialized.");
}
echo "\nStarting PGO training using scenario '{$this->scenario}'.\n\n";
$this->up();
/* Clean the PGO db files, only needed once.
Imply also, that any data created during init or
startup is wasted. It is done by dumpbing the data
from the current running processes and subsequently
removing the files. */
$php = $this->conf->getSrv("nginx")->getPhp();
$pgo = new PGO($this->conf, $php);
$pgo->waste();
$pgo->clean();
unset($pgo);
foreach (new TrainingCaseIterator($this->conf) as $handler) {
echo "\n";
$handler->run();
}
/* All the PGC files are merged, simply clean them out. */
$pgo = new PGO($this->conf, $php);
$pgo->clean(true, false);
unset($pgo);
$this->down();
echo "PGO training complete.\n";
}
public function up()
{
if (!$this->isInitialized()) {
throw new Exception("PGO training environment is not initialized.");
}
echo "\nStarting up PGO environment.\n\n";
foreach ($this->vitalizeSrv("all") as $srv) {
$srv->up();
echo "\n";
}
sleep(1);
echo "The PGO environment is up.\n";
}
public function down(bool $force = false)
{
if (!$this->isInitialized()) {
throw new Exception("PGO training environment is not initialized.");
}
/* XXX check it was started of course. */
echo "\nShutting down PGO environment.\n\n";
foreach ($this->vitalizeSrv("all") as $srv) {
$srv->down($force);
echo "\n";
}
sleep(1);
echo "The PGO environment has been shut down.\n";
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Tool\PackageWorkman;
interface PHP
{
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
public function init() : void;
public function up() : void;
public function down(bool $force = false) : void;
public function getVersion(bool $short = false) : string;
public function getExeFilename() : string;
}

View File

@@ -0,0 +1,17 @@
<?php
namespace SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Tool\PackageWorkman;
interface Server
{
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
public function init() : void;
public function up() : void;
public function down(bool $force = false) : void;
public function getName() : string;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace SDK\Build\PGO\Interfaces\Server;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Interfaces;
interface DB extends Interfaces\Server
{
public function __construct(Config $conf);
public function query(string $s, string $db = NULL) : void;
}

View File

@@ -0,0 +1,14 @@
<?php
namespace SDK\Build\PGO\Interfaces\Server;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Interfaces;
interface HTTP extends Interfaces\Server
{
public function __construct(Config $conf, Interfaces\PHP $php);
public function getPhp() : Interfaces\PHP;
public function addServer(string $part_tpl_fn, array $tpl_vars = array());
}

View File

@@ -0,0 +1,28 @@
<?php
namespace SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Tool\PackageWorkman;
interface TrainingCase
{
public function __construct(PGOConfig $conf, ?Server $srv_http, ?Server\DB $srv_db);
/* Name of the training case, usually should be same as dirname and namespace. */
public function getName() : string;
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
/* Initialize the case, run only once on a new checkout. */
public function init() : void;
/* Run training. */
public function run() : void;
/* Get training type, it's like "web", "cli", etc.*/
public function getType() : string;
}

View File

@@ -0,0 +1,56 @@
<?php
namespace SDK\Build\PGO\PHP;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class CLI extends Abstracts\PHP implements Interfaces\PHP
{
protected $conf;
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
$this->scenario = $conf->getScenario();
$this->setupPaths();
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
/* pass */
}
public function init() : void
{
/* pass */
}
public function up() : void
{
/* pass */
}
public function down(bool $force = false) : void
{
/* pass */
}
public function getExeFilename() : string
{
$exe = $this->getRootDir() . DIRECTORY_SEPARATOR . "php.exe";
if (!file_exists($exe)) {
throw new Exception("Path '$exe' doesn't exist.");
}
return $exe;
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace SDK\Build\PGO\PHP;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class FCGI extends Abstracts\PHP implements Interfaces\PHP
{
protected $conf;
protected $is_tcp;
public function __construct(PGOConfig $conf, bool $is_tcp)
{
if (!$is_tcp) {
throw new Exception("FCGI training other than through TCP is not implemented yet.");
}
$this->conf = $conf;
$this->is_tcp = $is_tcp;
$this->scenario = $conf->getScenario();
$this->setupPaths();
}
public function getExeFilename() : string
{
$exe = $this->getRootDir() . DIRECTORY_SEPARATOR . "php-cgi.exe";
if (!file_exists($exe)) {
throw new Exception("Path '$exe' doesn't exist.");
}
return $exe;
}
protected function createEnv() : array
{
$env = parent::createEnv();
$fcgi_env = (array)$this->conf->getSectionItem("php", "fcgi:env");
foreach ($fcgi_env as $k => $v) {
$env[$k] = $v;
}
return $env;
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
}
public function init() : void
{
/* echo "Initializing PHP FCGI.\n";
echo "PHP FCGI initialization done.\n";*/
}
public function up() : void
{
echo "Starting PHP FCGI.\n";
$exe = $this->getExeFilename();
$ini = $this->getIniFilename();
$host = $this->conf->getSectionItem("php", "fcgi", "host");
$port = $this->conf->getSectionItem("php", "fcgi", "port");
$cmd = "start /b $exe -n -c $ini -b $host:$port 2>&1";
$desc = array(
0 => array("file", "php://stdin", "r"),
1 => array("file", "php://stdout", "w"),
2 => array("file", "php://stderr", "w"),
);
$p = proc_open($cmd, $desc, $pipes, $this->getRootDir(), $this->createEnv());
/* Give some time, it might be slow on PGI enabled proc. */
sleep(3);
$c = proc_close($p);
if ($c) {
throw new Exception("PHP FCGI process exited with code '$c'.");
}
/* XXX for Opcache, setup also file cache. */
echo "PHP FCGI started.\n";
}
public function down(bool $force = false) : void
{
echo "Stopping PHP FCGI.\n";
exec("taskkill /f /im php-cgi.exe >nul 2>&1");
echo "PHP FCGI stopped.\n";
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace SDK\Build\PGO\Server;
use SDK\Build\PGO\Interfaces\Server\DB;
use SDK\Build\PGO\Abstracts\Server;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class MariaDB extends Server implements DB
{
use FileOps;
protected $conf;
protected $base;
protected $name = "MariaDB";
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
$this->base = $conf->getSrvDir(strtolower($this->name));
}
protected function setupDist()
{
/* pass */
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->name, "pkg_url");
$pw->fetchAndUnzip($url, "mariadb.zip", $this->conf->getSrvDir(), "mariadb", $force);
}
public function init() : void
{
echo "Initializing " . $this->name . ".\n";
$this->setupDist();
$this->up();
$this->down(true);
echo $this->name . " initialization done.\n";
}
public function up() : void
{
echo "Starting " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
$port = $this->conf->getSectionItem($this->name, "port");
//$h = popen("start /b .\\bin\\mysqld.exe --port=$port >nul 2>&1", "r");
$h = popen("start /b .\\bin\\mysqld.exe --port=$port 2>&1", "r");
if (!is_resource($h)) {
chdir($cwd);
throw new Exception("Failed to start MariaDB.");
}
sleep(3);
while (!feof($h)) {
echo fread($h, 1024);
}
pclose($h);
chdir($cwd);
echo $this->name . " started.\n";
}
public function down(bool $force = false) : void
{
echo "Stopping " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = sprintf(".\\bin\\mysqladmin.exe --host=$host --port=$port -u $user %s--shutdown_timeout=0 shutdown", ($pass ? "-p$pass " : ""));
exec($cmd);
if ($force) {
sleep(1);
exec("taskkill /f /im mysqld.exe >nul 2>&1");
}
chdir($cwd);
echo $this->name . " stopped.\n";
}
public function query(string $s, string $db = NULL) : void
{
$ret = NULL;
$cwd = getcwd();
chdir($this->base);
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$pass_arg = $pass ? "-p$pass " : "";
$ret = shell_exec(".\\bin\\mysql.exe -u $user $pass_arg -h $host -P $port -e \"$s\"");
//var_dump($this->base, getcwd(), ".\\bin\\mysql.exe -u $user $pass_arg -h $host -P $port -e \"$s\"");
chdir($cwd);
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace SDK\Build\PGO\Server;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\{Config as PGOConfig};
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class NGINX extends Abstracts\Server implements Interfaces\Server\HTTP
{
use FileOps;
protected $name = "NGINX";
protected $conf;
protected $base;
protected $php;
public function __construct(PGOConfig $conf, Interfaces\PHP $php)
{
$this->conf = $conf;
$this->base = $conf->getSrvDir(strtolower($this->name));
$this->php = $php;
}
protected function setupDist() : void
{
$nginx_conf_in = $this->conf->getTplDir($this->name) . DIRECTORY_SEPARATOR . "nginx.conf";
$conf_fn = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
$vars = array();
$port = $this->conf->getSectionItem($this->name, "port");
if (!$port) {
$port = $this->conf->getNextPort();
$this->conf->setSectionItem($this->name, "port", $port);
}
$vars = array(
$this->conf->buildTplVarName($this->name, "docroot") => str_replace("\\", "/", $this->base . DIRECTORY_SEPARATOR . "html"),
);
$this->conf->processTplFile(
$nginx_conf_in,
$conf_fn,
$vars
);
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->name, "pkg_url");
$pw->fetchAndUnzip($url, "nginx.zip", $this->conf->getSrvDir(), "nginx", $force);
}
public function init() : void
{
echo "Initializing " . $this->name . ".\n";
$this->setupDist();
$this->upMe();
$this->downMe(true);
echo $this->name . " initialization done.\n";
}
protected function upMe() : void
{
echo "Starting " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
$h = popen("start /b .\\nginx.exe 2>&1", "r");
if (!is_resource($h)) {
chdir($cwd);
throw new Exception("Failed to start MariaDB.");
}
sleep(3);
/* while (!feof($h)) {
echo fread($h, 1024);
}*/
pclose($h);
chdir($cwd);
echo $this->name . " started.\n";
}
public function up() : void
{
$this->php->up();
$this->upMe();
}
public function downMe(bool $force = false) : void
{
echo "Stopping " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
exec(".\\nginx.exe -s quit");
if ($force) {
sleep(1);
exec("taskkill /f /im nginx.exe >nul 2>&1");
}
chdir($cwd);
echo $this->name . " stopped.\n";
}
public function down(bool $force = false) : void
{
$this->php->down();
$this->downMe($force);
}
/* Use only for init phase! */
public function addServer(string $part_tpl_fn, array $tpl_vars = array())
{
if (!file_exists($part_tpl_fn)) {
throw new Exception("Template file '$part_tpl_fn' doesn't exist.");
}
/* We've already did a fresh (re)config, so use the work file now. */
$nginx_conf_in = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
$cur_conf = file_get_contents($nginx_conf_in);
$in = file_get_contents($part_tpl_fn);
$out = $this->conf->processTpl($in, $tpl_vars);
$tpl = " # PHP_SDK_PGO_NGINX_SERVERS_INC_TPL";
$new_conf = str_replace($tpl, "$out\n$tpl", $cur_conf);
$conf_fn = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
if (!file_put_contents($conf_fn, $new_conf)) {
throw new Exception("Couldn't write '$conf_fn'.");
}
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace SDK\Build\PGO\Server;
use SDK\Build\PGO\Interfaces\Server\DB;
use SDK\Build\PGO\Abstracts\Server;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class PostgreSQL extends Server implements DB
{
use FileOps;
protected $conf;
protected $base;
protected $data_dir;
protected $name = "PostgreSQL";
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
$this->base = $conf->getSrvDir(strtolower($this->name));
$this->data_dir = $this->base . DIRECTORY_SEPARATOR . "data";
}
protected function setupDist()
{
$user = $this->conf->getSectionItem($this->name, "user");
if (!$user) {
$user = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "user", $user);
}
$pass = $this->conf->getSectionItem($this->name, "pass");
if (!$pass) {
$pass = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "pass", $pass);
}
if (!is_dir($this->data_dir)) {
$pwfile = tempnam(sys_get_temp_dir(), "tmp");
if (strlen($pass) !== file_put_contents($pwfile, $pass)) {
throw new Exception("Couldn't write '$pwfile'.");
}
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "initdb.exe --auth=trust --nosync --username=$user --pwfile=$pwfile --encoding=UTF8 " . $this->data_dir;
//$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "initdb.exe --auth=trust --nosync --username=$user --encoding=UTF8 " . $this->data_dir;
/*echo "$cmd\n";
echo file_get_contents($pwfile) . "\n";*/
exec($cmd);
unlink($pwfile);
}
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->name, "pkg_url");
$pw->fetchAndUnzip($url, "postgresql.zip", $this->conf->getSrvDir(), "postgresql", $force);
}
public function init() : void
{
echo "Initializing " . $this->name . ".\n";
$this->setupDist();
$this->up();
$this->down(true);
echo $this->name . " initialization done.\n";
}
public function up() : void
{
echo "Starting " . $this->name . ".\n";
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "pg_ctl.exe start -D " . $this->data_dir . " -o \"-h $host -p $port\"";
$h = popen($cmd, "r");
/* XXX error check*/
pclose($h);
echo $this->name . " started.\n";
}
public function down(bool $force = false) : void
{
echo "Stopping " . $this->name . ".\n";
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "pg_ctl.exe stop -D " . $this->data_dir . " -m fast";
exec($cmd);
if ($force) {
//sleep(1);
//exec("taskkill /f /im nginx.exe >nul 2>&1");
}
echo $this->name . " stopped.\n";
}
public function createDb(string $db_name) : void
{
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "createdb.exe -h $host -p $port -U $user $db_name";
exec($cmd);
}
public function dropDb(string $db_name) : void
{
$user = $this->conf->getSectionItem($this->name, "user");
//$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "dropdb.exe --if-exists -h $host -p $port -U $user $db_name";
exec($cmd);
}
public function query(string $s, string $db = NULL) : void
{
$ret = NULL;
$user = $this->conf->getSectionItem($this->name, "user");
//$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$db_arg = $db ? "-d $db" : "";
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "psql.exe -h $host -p $port -U $user $db_arg -c \"$s\"";
$ret = shell_exec($cmd);
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace SDK\Build\PGO\Tool;
use SDK\{Config as SDKConfig, Exception};
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Interfaces;
class PGO
{
protected $php;
protected $conf;
protected $idx = 0;
public function __construct(PGOConfig $conf, Interfaces\PHP $php)
{
$this->conf = $conf;
$this->php = $php;
}
protected function getPgcName(string $fname) : string
{
$bn = basename($fname, substr($fname, -4, 4));
$dn = dirname($fname);
return $dn . DIRECTORY_SEPARATOR . $bn . "!" . $this->idx . ".pgc";
}
protected function getPgdName(string $fname) : string
{
$bn = basename($fname, substr($fname, -4, 4));
$dn = dirname($fname);
return $dn . DIRECTORY_SEPARATOR . $bn . ".pgd";
}
protected function getWorkItems() : array
{
$exe = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.exe");
$dll = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.dll");
$dll = array_merge($dll, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "php*.dll"));
/* find out next index */
$tpl = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "php7{ts,}.dll", GLOB_BRACE)[0];
if (!$tpl) {
throw new Exception("Couldn't find php7[ts].dll in the PHP root dir.");
}
do {
if (!file_exists($this->getPgcName($tpl))) {
break;
}
$this->idx++;
} while (true);
return array_unique(array_merge($exe, $dll));
}
public function dump(bool $merge = true) : void
{
$its = $this->getWorkItems();
foreach ($its as $base) {
$pgc = $this->getPgcName($base);
$pgd = $this->getPgdName($base);
`pgosweep $base $pgc`;
//passthru("pgosweep $base $pgc");
if ($merge) {
`pgomgr /merge:1000 $pgc $pgd`;
//passthru("pgomgr /merge:1000 $pgc $pgd");
/* File is already spent, no need to keep it.
If seeing linker warnings about no pgc
were found for some object - most
likely the object were not included in
any training scenario. */
@unlink($pgc);
}
}
}
public function waste() : void
{
$this->dump(false);
}
public function clean(bool $clean_pgc = true, bool $clean_pgd = true) : void
{
if ($clean_pgc) {
$its = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.pgc");
$its = array_merge($its, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "*" . DIRECTORY_SEPARATOR . "*.pgc"));
foreach (array_unique($its) as $pgc) {
unlink($pgc);
}
}
if ($clean_pgd) {
$its = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.pgd");
$its = array_merge($its, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "*" . DIRECTORY_SEPARATOR . "*.pgd"));
foreach (array_unique($its) as $pgd) {
`pgomgr /clear $pgd`;
//passthru("pgomgr /clear $pgd");
}
}
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace SDK\Build\PGO\Tool;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Config as PGOConfig;
class PackageWorkman
{
use FileOps;
protected $conf;
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
}
public function fetch(string $url, string $tgt_fn, bool $force = false) : void
{
$cache_fn = $this->conf->getPkgCacheDir() . DIRECTORY_SEPARATOR . basename($tgt_fn);
if ($force || !file_exists($cache_fn)) {
echo "Fetching '$url' into '$tgt_fn'\n";
$this->download($url, $cache_fn);
}
if ($force || !file_exists($tgt_fn)) {
if ($cache_fn != $tgt_fn && !$this->cp($cache_fn, $tgt_fn)) {
throw new Exception("Failed to copy '$cache_fn' to '$tgt_fn'.");
}
}
}
/* Only for zips! */
public function fetchAndUnzip(string $url, string $zip_bn, string $zip_tgt_dn, string $tgt_bn = NULL, bool $force = false) : void
{
$cache_fn = $this->conf->getPkgCacheDir() . DIRECTORY_SEPARATOR . $zip_bn;
if ($force || !file_exists($cache_fn)) {
$this->fetch($url, $cache_fn, $force);
}
$tgt_name = $zip_tgt_dn . ($tgt_bn ? DIRECTORY_SEPARATOR . $tgt_bn : "");
if ($force || $tgt_bn && !file_exists($tgt_name) || !$tgt_bn /* This means unzip always if no rename. */) {
echo "Unpacking '$cache_fn' to '$tgt_name'\n";
try {
$this->unzip($cache_fn, $zip_tgt_dn, $tgt_bn);
} catch (Throwable $e) {
$this->rm($cache_fn);
throw $e;
}
}
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace SDK\Build\PGO\Tool;
use SDK\{Config as SDKConfig, Exception};
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Interfaces\{TrainingCase, Server, Server\DB, PHP};
class Training
{
protected $conf;
protected $t_case;
public function __construct(PGOConfig $conf, TrainingCase $t_case)
{
$this->conf = $conf;
$this->t_case = $t_case;
if (!in_array($this->t_case->getType(), array("web", "cli"))) {
throw new Exception("Unknown training type '$type'.");
}
}
public function getCase() : TrainingCase
{
return $this->t_case;
}
public function runWeb(int $max_runs, ?array &$stat = array()) : void
{
$url_list_fn = $this->t_case->getJobFilename();
if (!file_exists($url_list_fn)) {
printf("\033[31m WARNING: Job file '$url_list_fn' not found!\033[0m\n");
}
$a = file($url_list_fn, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$stat = array("http_code" => array(), "not_ok" => array());
for ($k = 0; $k < $max_runs; $k++) {
echo ".";
$ch = array();
$mh = curl_multi_init();
foreach ($a as $i => $u) {
$ch[$i] = curl_init($u);
curl_setopt($ch[$i], CURLOPT_CONNECTTIMEOUT_MS, 500000);
curl_setopt($ch[$i], CURLOPT_TIMEOUT_MS, 500000);
curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch[$i], CURLOPT_USERAGENT, SDKConfig::getSdkUserAgentName());
/* ??? */
/*curl_setopt($ch[$i], CURLOPT_FOLLOWLOCATION, true);*/
curl_multi_add_handle($mh, $ch[$i]);
}
$active = NULL;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh, 42.0) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach ($ch as $h) {
curl_multi_remove_handle($mh, $h);
/* Gather some stats */
$info = curl_getinfo($h);
$http_code = $info["http_code"];
if (isset($stat["http_code"][$http_code])) {
$stat["http_code"][$http_code]++;
} else {
$stat["http_code"][$http_code] = 1;
}
if (!$this->t_case->httpStatusOk((int)$http_code)) {
$stat["not_ok"][] = $info;
//echo curl_multi_getcontent($h) ;
}
curl_close($h);
}
curl_multi_close($mh);
}
echo "\n";
}
/* TODO Extend with number runs. */
public function run(int $max_runs = 1, ?array &$stat = array()) : void
{
$type = $this->t_case->getType();
switch ($type)
{
case "web":
$this->runWeb($max_runs, $stat);
break;
case "cli":
default:
throw new Exception("Unknown training type '$type'.");
}
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace SDK\Build\PGO;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Config as PGOConfig;
class TrainingCaseIterator implements \Iterator
{
protected $conf;
protected $items = array();
protected $idx;
protected $el;
public function __construct(PGOConfig $conf)
{
$this->rewind();
$this->conf = $conf;
$items = glob($this->conf->getCasesTplDir() . DIRECTORY_SEPARATOR . "*");
foreach ($items as $it) {
if(!is_dir($it)) {
continue;
}
if (!file_exists($this->getHandlerFilename($it))) {
echo "Test case handler isn't present in '$it'.\n";
continue;
}
if ($this->isInactive($it)) {
echo "The test case in '$it' is marked inactive.\n";
continue;
}
$this->items[] = $it;
}
}
protected function isInactive(string $base) : bool
{
return file_exists($base . DIRECTORY_SEPARATOR . "inactive");
}
protected function getHandlerFilename(string $base) : string
{
return $base . DIRECTORY_SEPARATOR . "TrainingCaseHandler.php";
}
public function current()
{
$base = $this->items[$this->idx];
$ns = basename($base);
/* Don't overwrite generated config. */
$it = $this->conf->getSectionItem($ns);
if (!$it) {
$this->conf->importSectionFromDir($ns, $base);
}
require_once $this->getHandlerFilename($base);
$srv_http = $this->conf->getSrv($this->conf->getSectionItem($ns, "srv_http"));
$srv_db = $this->conf->getSrv($this->conf->getSectionItem($ns, "srv_db"));
$class = "$ns\\TrainingCaseHandler";
$this->el = new $class($this->conf, $srv_http, $srv_db);
return $this->el;
}
public function next()
{
$this->idx++;
}
public function rewind()
{
$this->idx = 0;
}
public function valid()
{
return $this->idx < count($this->items);
}
public function key()
{
if (!is_object($this->el)) {
return NULL;
}
return $this->el->getName();
}
}

View File

@@ -10,8 +10,9 @@ class Config
{
/* Config variables. */
protected static $depsHost = 'windows.php.net';
protected static $depsPort = 80;
protected static $depsBaseUri = "/downloads/php-sdk/backports/deps";
protected static $depsPort = 443;
protected static $depsUriScheme = "https";
protected static $depsBaseUri = "/downloads/php-sdk/deps";
/* protected static $sdkNugetFeedUrl = "http://127.0.0.1/sdk/nuget"; */
@@ -34,6 +35,11 @@ class Config
return self::$depsPort;
}/*}}}*/
public static function getDepsUriScheme() : string
{/*{{{*/
return self::$depsUriScheme;
}/*}}}*/
public static function getDepsBaseUri() : string
{/*{{{*/
return self::$depsBaseUri;
@@ -125,7 +131,7 @@ class Config
if (empty(self::$knownBranches)) {
$cache_file = "known_branches.txt";
$cache = new Cache(self::getDepsLocalPath());
$fetcher = new Fetcher(self::$depsHost, self::$depsPort);
$fetcher = new Fetcher(self::$depsHost, self::$depsPort, self::$depsUriScheme);
$tmp = $fetcher->getByUri(self::$depsBaseUri . "/series/");
if (false !== $tmp) {
@@ -247,7 +253,8 @@ class Config
$data = $branches[$current_branch_name][$cur_crt];
} else {
/* Evaluate CRTs, to avoid ambiquity. */
list($crt, $data) = each($branches[$current_branch_name]);
$crt = key($branches[$current_branch_name]);
$data = $branches[$current_branch_name][$crt];
if ($crt != $cur_crt) {
throw new Exception("The passed CRT '$cur_crt' doesn't match any availbale for branch '$current_branch_name'");
}
@@ -266,13 +273,10 @@ class Config
}
}
if (!isset($ret["arch"]) || !$ret["arch"]) {
throw new Exception("Failed to find config with arch '" . self::getCurrentArchName() . "'");
}
if (!isset($ret["stability"]) || !$ret["stability"]) {
if (!$ret["stability"]) {
throw new Exception("Failed to find config with stability '" . self::getCurrentStabilityName() . "'");
}
if (!isset($ret["crt"]) || !$ret["crt"]) {
if (!$ret["crt"]) {
throw new Exception("Failed to find config with arch '" . self::getCurrentArchName() . "'");
}

View File

@@ -116,28 +116,34 @@ trait FileOps
return $ret;
}/*}}}*/
protected function download(string $url, string $dest = NULL) : ?string
protected function download(string $url, string $dest_fn = NULL) : ?string
{/*{{{*/
$fd = NULL;
$ch = curl_init($url);
$ch = curl_init();
if ($dest) {
$fd = fopen($dest, "w+");
curl_setopt($ch, CURLOPT_URL, $url);
if ($dest_fn) {
$fd = fopen($dest_fn, "w+");
curl_setopt($ch, CURLOPT_FILE, $fd);
} else {
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
}
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, Config::getSdkUserAgentName());
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$ret = curl_exec($ch);
if (false === $ret) {
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (false === $ret || 200 !== $code) {
$err = curl_error($ch);
curl_close($ch);
if ($dest) {
if ($dest_fn) {
fclose($fd);
}
throw new Exception($err);
@@ -145,13 +151,67 @@ trait FileOps
curl_close($ch);
if ($dest) {
if ($dest_fn) {
fclose($fd);
return NULL;
}
return $ret;
}/*}}}*/
/* TODO More detailed zip errors. */
protected function unzip(string $zip_fn, string $dest_fn, string $dest_dn = NULL) : void
{/*{{{*/
$zip = new \ZipArchive;
$res = $zip->open($zip_fn);
if (true !== $res) {
throw new Exception("Failed to open '$zip_fn'.");
}
$res = $zip->extractTo($dest_fn);
if (true !== $res) {
$zip->close();
throw new Exception("Failed to unzip '$zip_fn'.");
}
/* Not robust, useful for zips containing one dir sibling only in the root. */
if ($dest_dn) {
$stat = $zip->statIndex(0);
if (false === $stat) {
$zip->close();
throw new Exception("Failed to stat first index in '$zip_fn'.");
}
$zip->close();
/* Index of zero might be not the zipped folder, unusual but true. */
/*$name = $stat["name"];
if ("/" != substr($name, -1)) {
throw new Exception("'$name' is not a directory.");
}
$name = substr($name, 0, -1);*/
$name = rtrim($stat["name"], "/");
while (strchr($name, '/') !== false) {
$name = dirname($name);
}
$old_dir = $dest_fn . DIRECTORY_SEPARATOR . $name;
$new_dir = $dest_fn . DIRECTORY_SEPARATOR . $dest_dn;
if (file_exists($new_dir)) {
if (!$this->rm($new_dir)) {
throw new Exception("Failed to remove '$new_dir'.");
}
}
/* if (!$this->mv($old_dir, $new_dir)) { */
if (!rename($old_dir, $new_dir)) {
throw new Exception("Failed to rename '$old_dir' to '$new_dir'.");
}
} else {
$zip->close();
}
}/*}}}*/
}
/*

View File

@@ -1,15 +0,0 @@
<?php
function __autoload($name)
{
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $name . ".php";
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@@ -0,0 +1,170 @@
<?php
namespace joomla;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\PHP;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool;
class TrainingCaseHandler extends Abstracts\TrainingCase implements Interfaces\TrainingCase
{
protected $conf;
protected $base;
protected $nginx;
protected $php;
protected $maria;
protected $max_runs = 4;
public function __construct(Config $conf, ?Interfaces\Server $nginx, ?Interfaces\Server\DB $maria)
{
if (!$nginx) {
throw new Exception("Invalid NGINX object");
}
$this->conf = $conf;
$this->base = $this->conf->getCaseWorkDir($this->getName());
$this->nginx = $nginx;
$this->php = $nginx->getPhp();
$this->maria = $maria;
}
public function getName() : string
{
return __NAMESPACE__;
}
public function getJobFilename() : string
{
return $this->conf->getJobDir() . DIRECTORY_SEPARATOR . $this->getName() . ".txt";
}
protected function getToolFn() : string
{
return $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, array("joomla", "vendor", "joomlatools", "console", "bin", "joomla"));
}
protected function setupDist() : void
{
$port = $this->getHttpPort();
$host = $this->getHttpHost();
$db_port = $this->getDbPort();
$db_host = $this->getDbHost();
$db_user = $this->getDbUser();
$db_pass = $this->getDbPass();
$vars = array(
$this->conf->buildTplVarName($this->getName(), "docroot") => str_replace("\\", "/", $this->base),
);
$tpl_fn = $this->conf->getCasesTplDir($this->getName()) . DIRECTORY_SEPARATOR . "nginx.partial.conf";
$this->nginx->addServer($tpl_fn, $vars);
$php = new PHP\CLI($this->conf);
$this->maria->up();
$this->nginx->up();
$this->maria->query("DROP DATABASE IF EXISTS " . $this->getName());
$this->maria->query("CREATE DATABASE " . $this->getName() . " CHARACTER SET utf8");
$htdocs = $this->conf->getCaseWorkDir($this->getName());
if (is_dir($htdocs . DIRECTORY_SEPARATOR . "_installation")) {
rename($htdocs . DIRECTORY_SEPARATOR . "_installation", $htdocs . DIRECTORY_SEPARATOR . "installation");
}
$env = array(
"PATH" => $this->conf->getSrvDir(strtolower($this->maria->getName())) . DIRECTORY_SEPARATOR . "bin",
);
$www = $this->conf->getCaseWorkDir();
$login = $db_pass ? "$db_user:$db_pass" : $db_user;
$cmd = $this->getToolFn() . " site:install --overwrite --sample-data=learn --mysql-database=" . $this->getName() . " --mysql-login=$login --mysql-host=$db_host --mysql-port=$db_port --www=$www " . $this->getName();
//$cmd = $this->getToolFn() . " site:install --drop --overwrite --sample-data=default --mysql-database=" . $this->getName() . " --mysql-login=$login --mysql-host=$db_host --mysql-port=$db_port --www=$www " . $this->getName();
//$cmd = $this->getToolFn() . " site:create --clear-cache --disable-ssl --release=3.7 --http-port=$port --sample-data=testing --mysql-database=" . $this->getName() . " --mysql-login=$login --mysql-host=$db_host --mysql-port=$db_port --www=$www " . $this->getName();
$php->exec($cmd, NULL, $env);
if (is_dir($htdocs . DIRECTORY_SEPARATOR . "installation")) {
rename($htdocs . DIRECTORY_SEPARATOR . "installation", $htdocs . DIRECTORY_SEPARATOR . "_installation");
}
$fn = $htdocs . DIRECTORY_SEPARATOR . "configuration.php";
$s = file_get_contents($fn);
$s = str_replace("public \$debug = '1';", "public \$debug = '0';", $s);
if (strlen($s) !== file_put_contents($fn, $s)) {
throw new Exception("Couldn't write '$fn'.");
}
$this->nginx->down(true);
$this->maria->down(true);
}
public function setupUrls()
{
$this->maria->up();
$this->nginx->up();
$url = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort();
$s = file_get_contents($url);
$this->nginx->down(true);
$this->maria->down(true);
echo "Generating training urls.\n";
$lst = array();
if (preg_match_all(", href=\"([^\"]+)\",", $s, $m)) {
foreach ($m[1] as $u) {
if ("/" == $u[0] && "/" != $u[1] && !in_array(substr($u, -3), array("css", "xml", "ico"))) {
$ur = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort() . $u;
if (!in_array($ur, $lst)) {
$lst[] = $ur;
}
}
}
}
if (empty($lst)) {
printf("\033[31m WARNING: Training URL list is empty, check the regex and the possible previous error messages!\033[0m\n");
}
$fn = $this->getJobFilename();
$s = implode("\n", $lst);
if (strlen($s) !== file_put_contents($fn, $s)) {
throw new Exception("Couldn't write '$fn'.");
}
}
public function prepareInit(Tool\PackageWorkman $pw, bool $force = false) : void
{
$php = new PHP\CLI($this->conf);
$composer = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer.phar";
$joomla_cli_base = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "joomla";
if (!file_exists($this->getToolFn()) || $force) {
if (!is_dir($joomla_cli_base)) {
mkdir($joomla_cli_base);
}
$cmd = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer.phar require joomlatools/console --working-dir=" . $joomla_cli_base;
$php->exec($cmd);
}
$url = $this->conf->getSectionItem($this->getName(), "joomla_zip_url");
$pw->fetchAndUnzip($url, "joomla.zip", $this->conf->getCaseWorkDir($this->getName()), $this->getName(), $force);
}
public function init() : void
{
echo "Initializing " . $this->getName() . ".\n";
echo "It is OK to see some warnings here, because the joomla tools are not fully Windows compatible.\n";
$this->setupDist();
$this->setupUrls();
echo $this->getName() . " initialization done.\n";
echo $this->getName() . " site configured to run under " . $this->getHttpHost() . ":" .$this->getHttpPort() . "\n";
}
}

View File

View File

@@ -0,0 +1,18 @@
server {
listen PHP_SDK_PGO_JOOMLA_HTTP_PORT;
server_name PHP_SDK_PGO_JOOMLA_HTTP_HOST;
root PHP_SDK_PGO_JOOMLA_DOCROOT;
index index.php index.html index.htm default.html default.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass PHP_SDK_PGO_PHP_FCGI_HOST:PHP_SDK_PGO_PHP_FCGI_PORT;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

View File

@@ -0,0 +1,6 @@
{
"joomla_zip_url": "https://github.com/joomla/joomla-cms/releases/download/3.7.2/Joomla_3.7.2-Stable-Full_Package.zip",
"type": "web",
"srv_http": "nginx",
"srv_db": "mariadb"
}

View File

@@ -0,0 +1,162 @@
<?php
namespace mediawiki;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\PHP;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool;
class TrainingCaseHandler extends Abstracts\TrainingCase implements Interfaces\TrainingCase
{
protected $conf;
protected $base;
protected $nginx;
protected $php;
protected $max_runs = 4;
public function __construct(Config $conf, ?Interfaces\Server $nginx, ?Interfaces\Server\DB $srv_db)
{
if (!$nginx) {
throw new Exception("Invalid NGINX object");
}
$this->conf = $conf;
$this->base = $this->conf->getCaseWorkDir($this->getName());
$this->nginx = $nginx;
$this->php = $nginx->getPhp();
}
public function getName() : string
{
return __NAMESPACE__;
}
public function getJobFilename() : string
{
return $this->conf->getJobDir() . DIRECTORY_SEPARATOR . $this->getName() . ".txt";
}
protected function getToolFn(string $what) : string
{
$ret = NULL;
if ("install" == $what) {
$ret = $this->conf->getCaseWorkDir($this->getName()) . DIRECTORY_SEPARATOR . "maintenance" . DIRECTORY_SEPARATOR . "install.php";
}
return $ret;
}
protected function setupDist() : void
{
$php = new PHP\CLI($this->conf);
$port = $this->getHttpPort();
$host = $this->getHttpHost();
$vars = array(
$this->conf->buildTplVarName($this->getName(), "docroot") => str_replace("\\", "/", $this->base),
);
$tpl_fn = $this->conf->getCasesTplDir($this->getName()) . DIRECTORY_SEPARATOR . "nginx.partial.conf";
$this->nginx->addServer($tpl_fn, $vars);
$settings = $this->conf->getCaseWorkDir($this->getName()) . DIRECTORY_SEPARATOR . "LocalSettings.php";
if (is_file($settings)) {
unlink($settings);
}
$site_adm = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "site_admin_user", $site_adm);
$site_pw = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "site_admin_pass", $site_pw);
$db_dir = $this->conf->getCaseWorkDir($this->getName()) . DIRECTORY_SEPARATOR . "database";
$nom = $this->getName();
$db_dir = $this->conf->getCaseWorkDir($this->getName()) . DIRECTORY_SEPARATOR . "database";
if (!is_dir($db_dir)) {
mkdir($db_dir);
}
$cmd = $this->getToolFn("install") . " --dbtype=sqlite --dbpath=$db_dir --pass=$site_pw --server=http://$host:$port/ $nom $site_adm";
echo "$cmd\n";
$php->exec($cmd);
}
public function setupUrls()
{
$this->nginx->up();
$url = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort();
$s = file_get_contents($url);
echo "Generating training urls.\n";
$lst = array();
if (preg_match_all(", href=\"([^\"]+)\",", $s, $m)) {
foreach ($m[1] as $u) {
if ("/" == $u[0] && "/" != $u[1] && !in_array(substr($u, -3), array("css", "xml", "ico"))) {
$u = str_replace(
array("&amp;"),
array("&"),
$u
);
$ur = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort() . $u;
if (!in_array($ur, $lst) && $this->probeUrl($ur)) {
$lst[] = $ur;
}
}
}
}
$this->nginx->down(true);
if (empty($lst)) {
printf("\033[31m WARNING: Training URL list is empty, check the regex and the possible previous error messages!\033[0m\n");
}
$fn = $this->getJobFilename();
$s = implode("\n", $lst);
if (strlen($s) !== file_put_contents($fn, $s)) {
throw new Exception("Couldn't write '$fn'.");
}
}
public function prepareInit(Tool\PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->getName(), "mediawiki_zip_url");
$pw->fetchAndUnzip($url, "mediawiki.zip", $this->conf->getCaseWorkDir(), $this->getName(), $force);
$php = new PHP\CLI($this->conf);
$lock = $this->conf->getCaseWorkDir($this->getName()) . DIRECTORY_SEPARATOR . "composer.lock";
if (!file_exists($lock) || $force) {
$composer = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer.phar";
$composer_cmd = file_exists($lock) ? "update" : "install";
$cmd = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer.phar $composer_cmd --no-dev --working-dir=" . $this->conf->getCaseWorkDir($this->getName());
$php->exec($cmd);
}
$skin_url = "https://github.com/wikimedia/mediawiki-skins-Vector/archive/master.zip";
$skin_path = $this->conf->getCaseWorkDir($this->getName()) . DIRECTORY_SEPARATOR . "skins" . DIRECTORY_SEPARATOR . "Vector";
if (!file_exists($skin_path . DIRECTORY_SEPARATOR . "SkinVector.php")) {
if (is_dir($skin_path)) {
rmdir($skin_path);
}
$pw->fetchAndUnzip($skin_url, "mediawiki_skin.zip", dirname($skin_path), "Vector", $force);
}
}
public function init() : void
{
echo "Initializing " . $this->getName() . ".\n";
$this->setupDist();
$this->setupUrls();
echo $this->getName() . " initialization done.\n";
echo $this->getName() . " site configured to run under " . $this->getHttpHost() . ":" .$this->getHttpPort() . "\n";
}
}

View File

View File

@@ -0,0 +1,30 @@
server {
listen PHP_SDK_PGO_MEDIAWIKI_HTTP_PORT;
server_name PHP_SDK_PGO_MEDIAWIKI_HTTP_HOST;
root PHP_SDK_PGO_MEDIAWIKI_DOCROOT;
index index.php index.html index.htm default.html default.htm;
client_max_body_size 5m;
client_body_timeout 60;
location / {
try_files $uri $uri/ @rewrite;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?title=$1&$args;
}
location ^~ /maintenance/ {
return 403;
}
location ~ \.php$ {
fastcgi_pass PHP_SDK_PGO_PHP_FCGI_HOST:PHP_SDK_PGO_PHP_FCGI_PORT;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
try_files $uri @rewrite;
}
}

View File

@@ -0,0 +1,6 @@
{
"mediawiki_zip_url": "https://github.com/wikimedia/mediawiki/archive/1.29.0.zip",
"type": "web",
"srv_http": "nginx",
"srv_db": null
}

View File

@@ -0,0 +1,134 @@
<?php
namespace pgo01org;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\PHP;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool;
class TrainingCaseHandler extends Abstracts\TrainingCase implements Interfaces\TrainingCase
{
protected $conf;
protected $base;
protected $nginx;
protected $maria;
protected $php;
protected $max_runs = 8;
public function __construct(Config $conf, ?Interfaces\Server $nginx, ?Interfaces\Server\DB $maria)
{
if (!$nginx) {
throw new Exception("Invalid NGINX object");
}
$this->conf = $conf;
$this->base = $this->conf->getCaseWorkDir($this->getName());
$this->nginx = $nginx;
$this->maria = $maria;
$this->php = $nginx->getPhp();
}
public function getName() : string
{
return __NAMESPACE__;
}
public function getJobFilename() : string
{
return $this->conf->getJobDir() . DIRECTORY_SEPARATOR . $this->getName() . ".txt";
}
protected function getToolFn() : string
{
return $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "wp-cli.phar";
}
protected function setupDist() : void
{
$cmd_path_arg = "--path=" . $this->base;
if (!is_dir($this->base)) {
echo "Setting up " . $this->getName() . " in '{$this->base}'\n";
/* XXX Use host PHP for this. */
$php = new PHP\CLI($this->conf);
$php->exec($this->getToolFn() . " core download --force $cmd_path_arg");
unset($php);
}
$http_port = $this->getHttpPort();
$http_host = $this->getHttpHost();
$db_port = $this->getDbPort();
$db_host = $this->getDbHost();
$db_user = $this->getDbUser();
$db_pass = $this->getDbPass();
$vars = array(
$this->conf->buildTplVarName($this->getName(), "docroot") => str_replace("\\", "/", $this->base),
);
$tpl_fn = $this->conf->getCasesTplDir($this->getName()) . DIRECTORY_SEPARATOR . "nginx.partial.conf";
$this->nginx->addServer($tpl_fn, $vars);
$php = new PHP\CLI($this->conf);
$this->maria->up();
$this->nginx->up();
// $this->maria->query("DROP DATABASE IF EXISTS " . $this->getName());
// $this->maria->query("CREATE DATABASE " . $this->getName());
$htdocs = $this->conf->getHtdocs($this->getName());
$fl = $htdocs . DIRECTORY_SEPARATOR . "constants.php";
$constants = file_get_contents($fl);
$constants = preg_replace(",define\('DB_USER'.+,", "define('DB_USER', '$db_user');", $constants);
$constants = preg_replace(",define\('DB_PASSWORD'.+,", "define('DB_PASSWORD', '$db_pass');", $constants);
$constants = preg_replace(",define\('DB_NAME'.+,", "define('DB_NAME', '" . $this->getName() . "');", $constants);
$constants = preg_replace(",define\('DB_HOST'.+,", "define('DB_HOST', '$db_host:$db_port');", $constants);
file_put_contents($fl, $constants);
//$php->exec($cmd, NULL, $env);
/* TODO check status or switch to cli. */
$out = file_get_contents("http://$http_host:$http_port/init.php");
echo $out, PHP_EOL;
$this->nginx->down(true);
$this->maria->down(true);
}
public function setupUrls()
{
$url = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort();
echo "Generating training urls.\n";
$fn = $this->getJobFilename();
if (strlen($url) !== file_put_contents($fn, $url)) {
throw new Exception("Couldn't write '$fn'.");
}
}
public function prepareInit(Tool\PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->getName(), "pgo01org_zip_url");
$pw->fetchAndUnzip($url, "php_pgo_training_scripts_01org.zip", $this->conf->getHtdocs(), "pgo01org", $force);
}
public function init() : void
{
echo "Initializing " . $this->getName() . ".\n";
$this->setupDist();
$this->setupUrls();
echo $this->getName() . " initialization done.\n";
echo $this->getName() . " site configured to run under " . $this->getHttpHost() . ":" .$this->getHttpPort() . "\n";
}
}

View File

@@ -0,0 +1,14 @@
server {
listen PHP_SDK_PGO_PGO01ORG_HTTP_PORT;
server_name PHP_SDK_PGO_PGO01ORG_HTTP_HOST;
root PHP_SDK_PGO_PGO01ORG_DOCROOT;
index index.html index.htm index.php;
location ~ \.php$ {
fastcgi_pass PHP_SDK_PGO_PHP_FCGI_HOST:PHP_SDK_PGO_PHP_FCGI_PORT;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

View File

@@ -0,0 +1,6 @@
{
"pgo01org_zip_url": "https://github.com/01org/php_pgo_training_scripts/archive/master.zip",
"type": "web",
"srv_http": "nginx",
"srv_db": "mariadb"
}

View File

@@ -0,0 +1,117 @@
<?php
namespace symfony_demo;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\PHP;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool;
class TrainingCaseHandler extends Abstracts\TrainingCase implements Interfaces\TrainingCase
{
protected $conf;
protected $base;
protected $nginx;
protected $php;
protected $max_runs = 4;
public function __construct(Config $conf, ?Interfaces\Server $nginx, ?Interfaces\Server\DB $srv_db)
{
if (!$nginx) {
throw new Exception("Invalid NGINX object");
}
$this->conf = $conf;
$this->base = $this->conf->getCaseWorkDir($this->getName());
$this->nginx = $nginx;
$this->php = $nginx->getPhp();
}
public function getName() : string
{
return __NAMESPACE__;
}
public function getJobFilename() : string
{
return $this->conf->getJobDir() . DIRECTORY_SEPARATOR . $this->getName() . ".txt";
}
protected function getToolFn() : string
{
return $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "symfony.phar";
}
protected function setupDist() : void
{
if (!is_dir($this->conf->getCaseWorkDir($this->getName()))) {
echo "Setting up in '{$this->base}'\n";
$php = new PHP\CLI($this->conf);
$php->exec($this->getToolFn() . " demo " . $this->base);
}
$port = $this->getHttpPort();
$host = $this->getHttpHost();
$vars = array(
$this->conf->buildTplVarName($this->getName(), "docroot") => str_replace("\\", "/", $this->base . DIRECTORY_SEPARATOR . "web"),
);
$tpl_fn = $this->conf->getCasesTplDir($this->getName()) . DIRECTORY_SEPARATOR . "nginx.partial.conf";
$this->nginx->addServer($tpl_fn, $vars);
}
public function setupUrls()
{
$this->nginx->up();
$url = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort() . "/en/blog/";
$s = file_get_contents($url);
echo "Generating training urls.\n";
$lst = array();
if (preg_match_all(", href=\"([^\"]+)\",", $s, $m)) {
foreach ($m[1] as $u) {
if (strlen($u) >= 2 && "/" == $u[0] && "/" != $u[1] && !in_array(substr($u, -3), array("css", "xml", "ico"))) {
$ur = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort() . $u;
if (!in_array($ur, $lst) && $this->probeUrl($ur)) {
$lst[] = $ur;
}
}
}
}
if (empty($lst)) {
printf("\033[31m WARNING: Training URL list is empty, check the regex and the possible previous error messages!\033[0m\n");
}
$this->nginx->down(true);
$fn = $this->getJobFilename();
$s = implode("\n", $lst);
if (strlen($s) !== file_put_contents($fn, $s)) {
throw new Exception("Couldn't write '$fn'.");
}
}
public function prepareInit(Tool\PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->getName(), "symfony_phar_url");
$pw->fetch($url, $this->getToolFn(), $force);
}
public function init() : void
{
echo "Initializing " . $this->getName() . ".\n";
$this->setupDist();
$this->setupUrls();
echo $this->getName() . " initialization done.\n";
echo $this->getName() . " site configured to run under " . $this->getHttpHost() . ":" .$this->getHttpPort() . "\n";
}
}

View File

@@ -0,0 +1,26 @@
server {
listen PHP_SDK_PGO_SYMFONY_DEMO_HTTP_PORT;
server_name PHP_SDK_PGO_SYMFONY_DEMO_HTTP_HOST;
root PHP_SDK_PGO_SYMFONY_DEMO_DOCROOT;
index index.html index.htm index.php;
# symfony
location / {
try_files $uri /app.php$is_args$args;
}
location ~ ^/app\.php(/|$) {
fastcgi_pass PHP_SDK_PGO_PHP_FCGI_HOST:PHP_SDK_PGO_PHP_FCGI_PORT;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
#internal;
}
location ~ \.php$ {
return 404;
}
}

View File

@@ -0,0 +1,6 @@
{
"symfony_phar_url": "https://symfony.com/installer",
"type": "web",
"srv_http": "nginx",
"srv_db": null
}

View File

@@ -0,0 +1,159 @@
<?php
namespace wordpress;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\PHP;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool;
class TrainingCaseHandler extends Abstracts\TrainingCase implements Interfaces\TrainingCase
{
protected $conf;
protected $base;
protected $nginx;
protected $maria;
protected $php;
protected $max_runs = 4;
public function __construct(Config $conf, ?Interfaces\Server $nginx, ?Interfaces\Server\DB $maria)
{
if (!$nginx) {
throw new Exception("Invalid NGINX object");
}
$this->conf = $conf;
$this->base = $this->conf->getCaseWorkDir($this->getName());
$this->nginx = $nginx;
$this->maria = $maria;
$this->php = $nginx->getPhp();
}
public function getName() : string
{
return __NAMESPACE__;
}
public function getJobFilename() : string
{
return $this->conf->getJobDir() . DIRECTORY_SEPARATOR . $this->getName() . ".txt";
}
protected function getToolFn() : string
{
return $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "wp-cli.phar";
}
protected function setupDist() : void
{
$cmd_path_arg = "--path=" . $this->base;
if (!is_dir($this->base)) {
echo "Setting up " . $this->getName() . " in '{$this->base}'\n";
/* XXX Use host PHP for this. */
$php = new PHP\CLI($this->conf);
$php->exec($this->getToolFn() . " core download --force $cmd_path_arg");
unset($php);
}
$http_port = $this->getHttpPort();
$http_host = $this->getHttpHost();
$db_port = $this->getDbPort();
$db_host = $this->getDbHost();
$db_user = $this->getDbUser();
$db_pass = $this->getDbPass();
$vars = array(
$this->conf->buildTplVarName($this->getName(), "docroot") => str_replace("\\", "/", $this->base),
);
$tpl_fn = $this->conf->getCasesTplDir($this->getName()) . DIRECTORY_SEPARATOR . "nginx.partial.conf";
$this->nginx->addServer($tpl_fn, $vars);
$php = new PHP\CLI($this->conf);
$this->maria->up();
$this->nginx->up();
$this->maria->query("DROP DATABASE IF EXISTS " . $this->getName());
$this->maria->query("CREATE DATABASE " . $this->getName());
$env = array(
"PATH" => $this->conf->getSrvDir(strtolower($this->maria->getName())) . DIRECTORY_SEPARATOR . "bin",
);
$cmd = $this->getToolFn() . " core config --force --dbname=" . $this->getName() . " --dbuser=$db_user --dbpass=$db_pass --dbhost=$db_host:$db_port $cmd_path_arg";
$php->exec($cmd, NULL, $env);
$site_adm = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "site_admin_user", $site_adm);
$site_pw = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "site_admin_pass", $site_pw);
//save admin user and pass to config
//$cmd = $this->getToolFn() . " core install --url=$http_host:$http_port --title=hello --admin_user=$site_adm_user --admin_password=$site_adm_pw --admin_email=a@bc.de --skip-email --path=" . $this->base;
$cmd = $this->getToolFn() . " core install --url=$http_host:$http_port --title=hello --admin_user=$site_adm --admin_password=$site_pw --admin_email=ostc@test.abc --skip-email $cmd_path_arg";
$php->exec($cmd, NULL, $env);
$cmd = $this->getToolFn() . " plugin install wordpress-importer --activate --allow-root $cmd_path_arg";
$php->exec($cmd, NULL, $env);
$cmd = $this->getToolFn() . " import " . $this->conf->getToolSDir() . DIRECTORY_SEPARATOR . "wptest/wptest.xml --authors=create --allow-root $cmd_path_arg";
$php->exec($cmd, NULL, $env);
$this->nginx->down(true);
$this->maria->down(true);
}
public function setupUrls()
{
$this->maria->up();
$this->nginx->up();
$url = "http://" . $this->getHttpHost() . ":" . $this->getHttpPort();
$s = file_get_contents($url);
$this->nginx->down(true);
$this->maria->down(true);
echo "Generating training urls.\n";
$lst = array();
if (preg_match_all(", href=\"([^\"]+" . $this->getHttpHost() . ":" . $this->getHttpPort() . "[^\"]+)\",", $s, $m)) {
$lst = array_unique($m[1]);
}
if (empty($lst)) {
printf("\033[31m WARNING: Training URL list is empty, check the regex and the possible previous error messages!\033[0m\n");
}
$fn = $this->getJobFilename();
$s = implode("\n", $lst);
if (strlen($s) !== file_put_contents($fn, $s)) {
throw new Exception("Couldn't write '$fn'.");
}
}
public function prepareInit(Tool\PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->getName(), "wp_cli_phar_url");
$pw->fetch($url, $this->getToolFn(), $force);
$url = $this->conf->getSectionItem($this->getName(), "wptest_zip_url");
$pw->fetchAndUnzip($url, "wptest.zip", $this->conf->getToolSDir(), "wptest", $force);
}
public function init() : void
{
echo "Initializing " . $this->getName() . ".\n";
$this->setupDist();
$this->setupUrls();
echo $this->getName() . " initialization done.\n";
echo $this->getName() . " site configured to run under " . $this->getHttpHost() . ":" .$this->getHttpPort() . "\n";
}
}

View File

@@ -0,0 +1,14 @@
server {
listen PHP_SDK_PGO_WORDPRESS_HTTP_PORT;
server_name PHP_SDK_PGO_WORDPRESS_HTTP_HOST;
root PHP_SDK_PGO_WORDPRESS_DOCROOT;
index index.html index.htm index.php;
location ~ \.php$ {
fastcgi_pass PHP_SDK_PGO_PHP_FCGI_HOST:PHP_SDK_PGO_PHP_FCGI_PORT;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

View File

@@ -0,0 +1,7 @@
{
"wp_cli_phar_url": "https://github.com/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar",
"wptest_zip_url": "https://github.com/manovotny/wptest/archive/master.zip",
"type": "web",
"srv_http": "nginx",
"srv_db": "mariadb"
}

View File

@@ -0,0 +1,7 @@
{
"pkg_url": "https://downloads.mariadb.com/MariaDB/mariadb-5.5.56/win32-packages/mariadb-5.5.56-win32.zip",
"host": "localhost",
"port": 3307,
"user": "root",
"pass": ""
}

36
pgo/tpl/nginx/nginx.conf Normal file
View File

@@ -0,0 +1,36 @@
worker_processes 4;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
# keepalive_timeout 65;
# gzip on;
fastcgi_read_timeout 1000;
server {
listen PHP_SDK_PGO_NGINX_PORT;
server_name PHP_SDK_PGO_NGINX_HOST;
root PHP_SDK_PGO_NGINX_DOCROOT;
index index.html index.htm index.php;
location ~ \.php$ {
fastcgi_pass PHP_SDK_PGO_PHP_FCGI_HOST:PHP_SDK_PGO_PHP_FCGI_PORT;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# PHP_SDK_PGO_NGINX_SERVERS_INC_TPL
}

View File

@@ -0,0 +1,5 @@
{
"pkg_url": "http://nginx.org/download/nginx-1.13.0.zip",
"host": "127.0.0.1",
"port": 8081
}

Some files were not shown because too many files have changed in this diff Show More