Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merged the use of libbcm_host from trunk with Oscar's new GPIO pull up/down setup code to get the best of both worlds. This requires a version of libbcm_host that was only just released: https://github.com/raspberrypi/firmware/issues/1161 |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | pi4-gpio-clean |
Files: | files | file ages | folders |
SHA3-256: |
1eee47198175cfc1bbe4b0d60b595471 |
User & Date: | tangent 2019-08-17 23:15:45.893 |
References
2024-03-14
| ||
05:36 | • Edit reply: pidp81-test output help artifact: d363059412 user: tangent | |
05:32 | • Reply: pidp81-test output help artifact: b6219ad54d user: tangent | |
Context
2020-05-20
| ||
04:58 | Merged trunk changes into pi4-gpio-clean. check-in: 4d51e218ef user: tangent tags: pi4-gpio-clean | |
2019-08-17
| ||
23:15 | Merged the use of libbcm_host from trunk with Oscar's new GPIO pull up/down setup code to get the best of both worlds. This requires a version of libbcm_host that was only just released: https://github.com/raspberrypi/firmware/issues/1161 check-in: 1eee471981 user: tangent tags: pi4-gpio-clean | |
2019-08-16
| ||
00:50 | Changed all references to "FOCAL 69" to "FOCAL,1969", and linked to the new "[Running FOCAL,1969]" wiki article which explains why this naming difference matters. check-in: d10da9f386 user: tangent tags: trunk | |
2019-08-15
| ||
00:22 | Added support for Pi 4 GPIO, based on code the Raspberry Pi Foundation published: https://github.com/RPi-Distro/raspi-gpio/commit/80fa7d04eafb3ea34fc6f2d32de5f1873b5fb369 This check-in is based on a version of gpio-common.c.in posted to the PiDP-8 Google Group by Oscar Vermeulen, which is why we're giving him credit for this check-in, even though I (tangent) have done quite a lot of changes to that code, mainly to match the existing code style. This is a branch because it conflicts with the current tip-of-trunk and because it's not yet tested on a Pi 4. It is unknown whether this branch will end up overriding the method we're using on trunk for Pi 0-3 or if we will instead wait for the Foundation to publish a new libbcm_host that obviates some of what this check-in does. Closed-Leaf check-in: bd10d4dde2 user: vermeulen.oscar tags: pi4-gpio-hack | |
Changes
Changes to HACKERS.md.
1 2 3 4 5 6 7 8 9 10 11 12 13 | Hacking on the PiDP-8/I Software ==== If you are going to make any changes to the PiDP-8/I software, here are some rules and hints to keep in mind while you work. <a id="gs-fossil"></a> Getting Started with Fossil ---- The PiDP-8/I software project is hosted using the [Fossil][fossil] [distributed version control system][dvcs]. Fossil provides most of the | | > > | | | | | < < | < | | > > > > > > | < > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | Hacking on the PiDP-8/I Software ==== If you are going to make any changes to the PiDP-8/I software, here are some rules and hints to keep in mind while you work. <a id="gs-fossil"></a> Getting Started with Fossil ---- The PiDP-8/I software project is hosted using the [Fossil][fossil] [distributed version control system][dvcs]. Fossil provides most of the features of GitHub without having to put up with all of the complexities of Git. In a lot of ways, Fossil is even simpler to use than Subversion. See [Fossil Versus Git][fvg] for a well-balanced comparison of the user-facing differences. This guide will introduce you to some of the basics, but you should also at least read the [Fossil Quick Start Guide][fqsg]. For a more thorough introduction, I recommend [the Schimpf book][fbook]. If you have questions about Fossil, you can ask on [the Fossil forum][ffor], where I, your humble project maintainer, am active. If you started with one of our PiDP-8/I [binary OS images][bosi] made in or after April 2017, Fossil is already installed. If you're starting from some other OS, Fossil won’t be installed by default, but if it’s Debian-based (e.g. Raspbian) you can easily install Fossil with: $ sudo apt install fossil That command assumes you’re running it on a derivative of Debian Buster, released in June 2019, or newer. Older Debian-based OSes shipped Fossil 1.x, which is too old to work with our Fossil repository. (We need 2.1 or higher.) You could dig up an old version of this document to learn our workaround for that problem, but it’s better to upgrade to an OS that includes a compatible version of Fossil. Fossil is also available for all common desktop platforms. One of [the official binaries][fbin] may work on your system. [bosi]: https://tangentsoft.com/pidp8i#bosi [fbin]: https://fossil-scm.org/index.html/uv/download.html [fvg]: https://fossil-scm.org/fossil/doc/trunk/www/fossil-v-git.wiki [dvcs]: https://en.wikipedia.org/wiki/Distributed_revision_control [fbook]: https://www.fossil-scm.org/schimpf-book/home [ffor]: https://fossil-scm.org/forum/ [fossil]: https://fossil-scm.org/ [fqsg]: https://fossil-scm.org/index.html/doc/trunk/www/quickstart.wiki |
︙ | ︙ | |||
121 122 123 124 125 126 127 | While Fossil does allow offline operation and local independent clones, its default mode of operation is to try and keep the clones in sync as much as possible. Git works the way it does because it was designed to meet the needs of the Linux kernel development project, which is inherently federated, so Git tries to operate in a federated model as well. Fossil is better for smaller, more coherent teams, where there is | | | > > > > | | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | While Fossil does allow offline operation and local independent clones, its default mode of operation is to try and keep the clones in sync as much as possible. Git works the way it does because it was designed to meet the needs of the Linux kernel development project, which is inherently federated, so Git tries to operate in a federated model as well. Fossil is better for smaller, more coherent teams, where there is a single, clear goal for the project and a single primary host for its project repository. Fossil helps remote developers cooperate, whereas Git helps remote developers go off on their own tangents for extended periods of time and optionally sync back up with each other occasionally. Fossil is a better match for the way the PiDP-8/I software project works: we want you to cooperate closely with us, not go off on wild tangents. For more on this topic, see [Fossil Versus Git][fvg] in the Fossil documentation. [fvg]: https://fossil-scm.org/fossil/doc/trunk/www/fossil-v-git.wiki [gitwt]: https://git-scm.com/docs/git-worktree <a id="login"></a> Fossil Developer Access ---- If you have a developer account on the `tangentsoft.com/pidp8i` Fossil |
︙ | ︙ |
Changes to Makefile.in.
︙ | ︙ | |||
36 37 38 39 40 41 42 | # Git commit ID and time of the latest version of the SIMH 4 project on # GitHub that has been merged into this source base. SGCID=4e0450cff96830c5aced36928a4427adfc5314f8 SGCTM=2019-04-18T20:03:17-07:00 # C build flags for the PDP-8 simulator and its PiDP-8/I extensions. | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # Git commit ID and time of the latest version of the SIMH 4 project on # GitHub that has been merged into this source base. SGCID=4e0450cff96830c5aced36928a4427adfc5314f8 SGCTM=2019-04-18T20:03:17-07:00 # C build flags for the PDP-8 simulator and its PiDP-8/I extensions. SIM_CFLAGS := @CFLAGS@ @PI_CFLAGS@ @BUILDMODE@ \ -Wno-unused-result -Wno-parentheses \ -DUSE_READER_THREAD -DHAVE_DLOPEN=$(subst .,,@SH_SOEXT@) -DPIDP8I \ -DSIM_ASYNCH_IO -DHAVE_REGEX_H -DHAVE_GLOB \ -DSIM_GIT_COMMIT_ID=$(SGCID) -DSIM_GIT_COMMIT_TIME=$(SGCTM) \ -D_GNU_SOURCE \ -U__STRICT_ANSI__ \ -I @srcdir@/src/SIMH -I @srcdir@/src/pidp8i -I src -I src/SIMH -I src/pidp8i |
︙ | ︙ | |||
686 687 688 689 690 691 692 | obj/cc8/os8/%.c: @srcdir@/src/cc8/examples/%.c sed '/^#include/d' $< > $@ $(BUILDDIRS): mkdir -p $@ $(PIDP8I_SIM): $(SIM_OBJS) obj/pidp8i/gpio-@LED_DRIVER_MODULE@ls.o | | | | | 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | obj/cc8/os8/%.c: @srcdir@/src/cc8/examples/%.c sed '/^#include/d' $< > $@ $(BUILDDIRS): mkdir -p $@ $(PIDP8I_SIM): $(SIM_OBJS) obj/pidp8i/gpio-@LED_DRIVER_MODULE@ls.o $(CC) -o $@ @PI_LFLAGS@ $^ $(LIBS) @PI_LIBS@ ln -f bin/pidp8i-sim bin/pdp8 bin/cc8: $(CC8_OBJS) $(CC) -o $@ $^ $(LIBS) bin/d8tape: $(D8TAPE_OBJS) $(CC) -o $@ $^ bin/palbart: $(PALBART_OBJS) $(CC) -o $@ $^ bin/pidp8i-test: obj/misc/test.o obj/pidp8i/gpio-nls.o obj/pidp8i/gpio-common.o $(CC) -o $@ $(CFLAGS) @PI_CFLAGS@ @PI_LFLAGS@ $^ $(LIBS) @PI_LIBS@ -lncurses bin/ptp2txt: obj/misc/ptp2txt.o $(CC) -o $@ $^ ln -f bin/ptp2txt bin/txt2ptp bin/txt2ptp: bin/ptp2txt ln -f bin/ptp2txt bin/txt2ptp bin/deeper: obj/misc/deeper.o obj/pidp8i/gpio-@LED_DRIVER_MODULE@ls.o obj/pidp8i/gpio-common.o $(CC) -o $@ $^ $(LIBS) libexec/scanswitch: obj/misc/scanswitch.o obj/pidp8i/gpio-nls.o obj/pidp8i/gpio-common.o $(CC) -o $@ $(CFLAGS) @PI_CFLAGS@ @PI_LFLAGS@ $^ $(LIBS) @PI_LIBS@ # Reconfigure whenever one of the *.in or autosetup files changes unless # this is "make clean". # # We purposely list only one of the OUTFILES on the left hand side # because to list them all is to invite Make to run N copies of the # configure script in parallel up to the limit of -j or the number of |
︙ | ︙ |
Changes to README.md.
︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 | somewhere your user has read/write access like `$HOME/src/pidp8i`. * We require several tools and libraries that aren't always installed: * A working C compiler and other standard Linux build tools, such as `make(1)`. * Python's `pexpect` library * The `ncurses` development libraries To install all of this on a Raspbian type OS, say: $ sudo apt update | > > | | > > > > > > > > > > > > > > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | somewhere your user has read/write access like `$HOME/src/pidp8i`. * We require several tools and libraries that aren't always installed: * A working C compiler and other standard Linux build tools, such as `make(1)`. * The Raspberry Pi development libraries * Python's `pexpect` library * The `ncurses` development libraries To install all of this on a Raspbian type OS, say: $ sudo apt update $ sudo apt install build-essential libraspberrypi-dev \ libncurses-dev python-pip $ sudo pip install pexpect [os]: https://tangentsoft.com/pidp8i/wiki?name=OS+Compatibility <a id="preparing"></a> ## Preparing Your Pi If you have a working Raspberry Pi setup, you can probably just skip ahead. If you’ve just barely unpacked Raspbian onto an SD card and are now trying to get the PiDP-8/I software distribution working on it, stop and go through the [Rasbperry Pi documentation][rpd] first. At the absolute minimum, run `raspi-config` and make sure the Localization settings are correct. The defaults are for the United Kingdom, home of the Raspberry Pi Foundation, so unless you live there, the defaults are probably not correct out of the box. [rpd]: https://www.raspberrypi.org/documentation/ <a id="unpacking"></a> ## Getting the Software onto Your Pi If you're reading this file within an unpacked distribution of the PiDP-8/I software, you may skip this section, because you have already achieved its aim. |
︙ | ︙ | |||
111 112 113 114 115 116 117 | above, so you can use Fossil to update your software to the current version at any time, as long as the Pi is connected to the Internet. <a id="unpacking"></a> ### Unpacking the Software on Your Pi | | < | < | | < | < | | | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | above, so you can use Fossil to update your software to the current version at any time, as long as the Pi is connected to the Internet. <a id="unpacking"></a> ### Unpacking the Software on Your Pi Having transferred the distribution file onto your Pi, unpack it with a command roughly like: $ tar xvf /path/to/pidp8i-VERSION.tar.gz The final argument to that command will vary depending on what you downloaded, [how you transferred it to the Pi](#transferring), and where you put it. If you used the `wget` command above, the path is simply `pidp8i.tar.gz`, for example. After unpacking the tarball, you will have a new directory beginning with `pidp8i`. `cd` into that directory, then proceed with the [configuration](#configuring) steps below. <a id="help"></a> ### If You Need More Help If the above material is not sufficient to get you started, you might |
︙ | ︙ | |||
154 155 156 157 158 159 160 | This software distribution builds and installs in the same way as most other Linux/Unix software these days. The short-and-sweet is: $ ./configure && make && sudo make install The `configure` step is generally needed only the first time you build | | | | | | | > > > > > | > > > > > > > | > > > > | > > | > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > | > > > > > > > > | > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | This software distribution builds and installs in the same way as most other Linux/Unix software these days. The short-and-sweet is: $ ./configure && make && sudo make install The `configure` step is generally needed only the first time you build the software in a new directory. You may want to add options, described [below](#options). Subsequent software updates and rebuilds should not require that you re-run the `configure` step, even if you gave custom options. The build system detects when the configuration is outdated and re-runs the `configure` script with the same options. If for some reason that automatic re-configuration fails, you can kick it off manually: $ make reconfig The “`make`” step above will take quite a while to run, especially on the slower Pi boards. The longest single step is building the OS/8 disk packs from source media. Be patient; the build process almost certainly isn’t frozen. If you’re on a multi-core Pi, You can speed the build process up some by running “`tools/mmake`” instead of directly calling “`make`”. It runs Make in a mode that lets it do a lot of work in parallel, making better use of your multiple CPU cores. That OS/8 media rebuild step is choked down to a single thread, though, so this won’t help with that. (This is a generic, portable script, so if you’re a software developer, feel free to reuse `mmake` and `corecount` on your own systems.) Only the `make install` step needs to be done via “`sudo`”. For the most part, we’ve tried very hard to minimize the places where you need to use root privileges to get something done within the PiDP-8/I software distribution. <a id="using"></a> ## Using the Software After running “`sudo make install`” the first time, you will have to log out and back in to get the installation’s “bin” directory into your `PATH`. For the most part, this software distribution works like the [old stable 2015.12.15 distribution][osd]. Its [documentation][oprj] therefore describes this software too, for the most part. Beyond that, you might find our [Learning More](/#learning) links helpful. The largest user-visible difference between the two software distributions is that many of the shell commands are different: 1. To start the simulator running in the background: $ pidp8i start This will happen automatically on reboot unless you disable the service, such as in order to run one of the various [forks of Deeper Thought][dt2]. 2. To attach the terminal you're working on to the simulator: $ pidp8i (Yes, it's the same base command as above. The `pidp8i` script uses its first argument to determine what you want it to do. Without arguments, this is what it does.) 3. To detach from the simulator's terminal interface while leaving the PiDP-8/I simulator running, type <kbd>Ctrl-A d</kbd>. You can re-attach to it later with a `pidp8i` command. 4. To shut the simulator down while attached to its terminal interface, type <kbd>Ctrl-E</kbd> to pause the simulator, then at the `simh>` prompt type `quit`. Type `help` at that prompt to get some idea of what else you can do with the simulator command language, or read the [SIMH Users' Guide][sdoc]. 5. To shut the simulator down from the Raspbian command line: $ pidp8i stop There are [other significant differences][mdif] between the old stable distribution and this one. You’ll want to be familiar with that documentation’s content before reading Oscar Vermeulen’s documentation, as it still refers to his last release in December 2015. <a id="systemd" name="unit"></a> ## The systemd Unit File Starting with release 2019.04.25, the PiDP-8/I software distribution is based on [systemd][systemd], since Raspbian is now on its third systemd-based release. One of the features systemd gives us is the ability to set the unit to run as user-level service rather than as a system-wide service, which means you no longer need the `sudo` prefix on commands to start, stop, restart, and query the service. The only time you now need root privileges when working with the PiDP-8/I software is when installing it. After that, the software runs under your normal user account, as do all of the commands you use to manipulate the background simulator service. As a result of these changes, none of these commands work any longer: $ sudo /etc/init.d/pidp8i start $ sudo service pidp8i stop $ sudo systemctl restart pidp8i The correct forms, respectively, are: $ systemctl --user start pidp8i $ systemctl --user stop pidp8i $ systemctl --user restart pidp8i These commands are long, so we have extended the `pidp8i` command to build and run `systemctl` commands for you when you pass it arguments: $ pidp8i start $ pidp8i stop $ pidp8i restart $ pidp8i status -l If you run it without arguments, it attaches to the GNU screen(1) session, just as it always has. The last command above shows that *all* arguments are passed to `systemctl`, not just the first, so you can pass any flags that `systemctl` accepts. Our systemd service starts at boot by default after you install the software. To disable the service so you can run something else against the PiDP-8/I front panel hardware instead, such as Deeper Thought 2: $ pidp8i stop $ pidp8i disable If you install this release on a system that has the old SysV init script on it, that service will be disabled and removed before we install and enable the replacement systemd user service. [svinit]: https://en.wikipedia.org/wiki/Init#SysV-style [systemd]: https://www.freedesktop.org/wiki/Software/systemd/ <a id="options"></a> ### Configure Script Options You can change many things about the way the software is built and installed by giving options to the `configure` script: |
︙ | ︙ | |||
244 245 246 247 248 249 250 251 252 253 254 255 | right thing." The simulator is configured to send lowercase input to the PDP-8 software running on it. Where we have the skill, will, need, and time for it, we have [patched][tty] some of the software we distribute that otherwise would not do the right thing with lowercase input to make it do so. This is *not* the option you want if you are a purist. * **upper** — This option tells the PDP-8 simulator to turn lowercase input into upper case. This is the behavior we used for all versions of the PiDP-8/I software up through v2017.04.04. Essentially, it tells the software that you want it to behave as through you've got | > > > > > > > > | > > | | | | < < < < < < < < | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | right thing." The simulator is configured to send lowercase input to the PDP-8 software running on it. Where we have the skill, will, need, and time for it, we have [patched][tty] some of the software we distribute that otherwise would not do the right thing with lowercase input to make it do so. This is *not* the option you want if you are a purist. * **pass** — This passes keyboard input through to the simulator unchanged, and no patches are applied to the PDP-8 software we distribute. This is the option for historical purists. If you run into trouble getting the software to work as you expect when built in this mode, try enabling CAPS LOCK. * **upper** — This option tells the PDP-8 simulator to turn lowercase input into upper case. This is the behavior we used for all versions of the PiDP-8/I software up through v2017.04.04. Essentially, it tells the software that you want it to behave as through you've got it connected to an uppercase-only terminal like the Teletype Model 33 ASR. The advantage of this mode is that you will have no problems running PDP-8 software that does not understand lowercase ASCII text. The disadvantage is obvious: you won't be able to input lowercase ASCII text. The SIMH option we enable in this mode is bidirectional, so that if you run a program that does emit lowercase ASCII text — such as Rick Murphy's version of Adventure — it will be uppercased, just like an ASR-33 would do. Another trap here is that the C programming language requires lowercase text, so you will get a warning if you leave the default option **--enable-os8-cc8** set. Pass **--disable-os8-cc8** when enabling **upper** mode. [sa]: http://homepage.cs.uiowa.edu/~jones/pdp8/faqs/#charsets [tty]: https://tangentsoft.com/pidp8i/wiki?name=OS/8+Console+TTY+Setup <a id="nls"></a> #### --no-lamp-simulator |
︙ | ︙ | |||
534 535 536 537 538 539 540 | That having been said, people don't go to a ren fair and expect to experience the historical ubiquity of typhoid fever, so do not feel guilty if you choose to try this option. [uvte]: https://tangentsoft.com/pidp8i/wiki?name=Using+VTEDIT * **--enable-os8-focal69** — Because the default installation includes | | | | | | | | | | > | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 | That having been said, people don't go to a ren fair and expect to experience the historical ubiquity of typhoid fever, so do not feel guilty if you choose to try this option. [uvte]: https://tangentsoft.com/pidp8i/wiki?name=Using+VTEDIT * **--enable-os8-focal69** — Because the default installation includes U/W FOCAL, we have chosen to leave [FOCAL,1969][f69] out by default to save space on the O/S 8 system disk. You can give this option to install this implementation alongside U/W FOCAL, or you can couple this option with `--disable-os8-uwfocal` to reverse our choice of which FOCAL implementation to install by default. You should know that the reason we made this choice is that the version of FOCAL,1969 we are currently shipping is fairly minimal: we believe we are shipping the original DEC version of FOCAL,1969 plus a few carefully-selected overlays. There are many more overlays and patches available on the Internet for FOCAL,1969, but we have not had time to sort through these and make choices of which ones to ship or how to manage which ones get installed. Thus our choice: we want to provide the most functional version of FOCAL by default, and within the limitations of the time we have chosen to spend on this, that is U/W FOCAL today. (See our [U/W FOCAL manual supplement][suppd] for a list of differences between these versions of FOCAL, which implicitly explains why we chose it.) It is possible that we will eventually add enough patches and overlays to FOCAL,1969 that it will become more powerful than U/W FOCAL, so we might then choose to switch the defaults, but that is just speculation at the time of this writing. [f69]: https://tangentsoft.com/pidp8i/wiki?name=Running+FOCAL%2C1969 [suppd]: https://tangentsoft.com/pidp8i/doc/trunk/doc/uwfocal-manual-supp.md#diffs #### --os8-minimal If you set this flag, it sets all `--enable-os8-*` flags to false and all `--disable-os8-*` flags to true. If you give this along with any |
︙ | ︙ | |||
805 806 807 808 809 810 811 | switches on the front panel. After you are done testing, you can start the PiDP-8/I simulator back up with: $ pidp8i start See [its documentation][test] for more details. | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 933 934 935 936 937 938 939 940 941 942 943 944 945 946 | switches on the front panel. After you are done testing, you can start the PiDP-8/I simulator back up with: $ pidp8i start See [its documentation][test] for more details. <a id="sshd"></a> ## Enabling the SSH Server on the Binary OS Images The OpenSSH server is enabled and running by default on the PiDP-8/I binary OS images, but for security reasons, the build process we use to create these OS images wipes out the SSH host keys generated here |
︙ | ︙ | |||
872 873 874 875 876 877 878 | You may be wondering why we don’t do this automatically, somehow. It’s because, over time, we’ve removed all dependence on root access in our software in the name of security, so that we no longer have permission to make system-wide changes like this in our startup scripts. We now rely on you, the system’s administrator, to do it interactively with `sudo` permissions. | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 956 957 958 959 960 961 962 963 964 965 966 967 968 969 | You may be wondering why we don’t do this automatically, somehow. It’s because, over time, we’ve removed all dependence on root access in our software in the name of security, so that we no longer have permission to make system-wide changes like this in our startup scripts. We now rely on you, the system’s administrator, to do it interactively with `sudo` permissions. ## License Copyright © 2016-2019 by Warren Young. This document is licensed under the terms of [the SIMH license][sl]. |
︙ | ︙ |
Changes to auto.def.
︙ | ︙ | |||
55 56 57 58 59 60 61 | set os8opts { advent 1 "Adventure" ba 1 "*.BA BASIC games and demos" cc8 1 "the native OS/8 CC8 compiler" chess 1 "the CHECKMO-II game of chess" crt 1 "CRT-style rubout processing" dcp 1 "the DCP disassembler" | | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | set os8opts { advent 1 "Adventure" ba 1 "*.BA BASIC games and demos" cc8 1 "the native OS/8 CC8 compiler" chess 1 "the CHECKMO-II game of chess" crt 1 "CRT-style rubout processing" dcp 1 "the DCP disassembler" focal69 0 "FOCAL,1969" fortran-ii 1 "FORTRAN II" fortran-iv 1 "FORTRAN IV" init 1 "the OS/8 INIT message" k12 1 "12-bit Kermit" macrel 1 "the MACREL assembler" music 0 "*.MU files" uwfocal 1 "U/W FOCAL (only)" |
︙ | ︙ | |||
86 87 88 89 90 91 92 | alt-serial-mod => "use GPIO drive scheme suitable for James L-W's serial mod method" boot-tape-config: => "Boot tape configuration: tc08, or td12k" boot-tape-version: => "OS/8 version for boot tape, either v3d or v3f" cc8-cross=1 => "do not build the cc8 cross-compiler on the host" debug-mode => "create a debug build (default is release)" lowercase: => "select how lowercase input is to be handled" no-lamp-simulator => "use simple LED driver instead of incandescent lamp simulator" | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | alt-serial-mod => "use GPIO drive scheme suitable for James L-W's serial mod method" boot-tape-config: => "Boot tape configuration: tc08, or td12k" boot-tape-version: => "OS/8 version for boot tape, either v3d or v3f" cc8-cross=1 => "do not build the cc8 cross-compiler on the host" debug-mode => "create a debug build (default is release)" lowercase: => "select how lowercase input is to be handled" no-lamp-simulator => "use simple LED driver instead of incandescent lamp simulator" os8-focal=1 => "leave FOCAL,1969 and U/W FOCAL off the built OS/8 RK05 image" os8-minimal => "set all --disable-os8-* options, giving minimal OS/8 bin disk" os8-src=1 => "do not build v3d-src.rk05 from OS/8 source tapes" savestate => "save simulator state (regs, core, devices) on exit; restore on restart" serial-mod => "use GPIO drive scheme suitable for Oscar Vermeulen's serial mod method" throttle: => "override the throttle values in the boot scripts" usb-automount=1 => "do not automatically mount USB drives for SING_STEP + DF" } |
︙ | ︙ | |||
343 344 345 346 347 348 349 350 351 352 353 354 355 356 | cc-check-includes time.h cc-check-function-in-lib clock_gettime rt cc-check-functions clock_nanosleep nanosleep usleep cc-check-functions sched_yield cc-with {-includes signal.h} { cc-check-types sighandler_t sig_t } # Ensure we have the libncurses development files installed here, else # pidp8i-test won't build. if {![cc-check-includes curses.h]} { user-error "Could not find curses.h. Try installing libncurses-dev." } elseif {![cc-check-function-in-lib initscr ncurses]} { user-error "Could not find initscr() in libncurses." | > > > > > > > > > > > > > > > > > > > > > > | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | cc-check-includes time.h cc-check-function-in-lib clock_gettime rt cc-check-functions clock_nanosleep nanosleep usleep cc-check-functions sched_yield cc-with {-includes signal.h} { cc-check-types sighandler_t sig_t } # Check for libraspberrypi-dev stuff set old_LIBS [get-define LIBS] ;# don't want LIBS modded directly if {![file isdirectory "/opt/vc"]} { msg-result "WARNING: Not building on a Pi or libraspberrypi-dev not installed!" define PI_CFLAGS "" define PI_LFLAGS "" define PI_LIBS "" } elseif {![cc-with {-cflags "-L/opt/vc/lib"} { cc-check-function-in-lib bcm_host_get_peripheral_address bcm_host }]} { user-error "Found /opt/vc but cannot link to -lbcm_host!" } elseif {![cc-with {-cflags "-I/opt/vc/include"} { cc-check-includes bcm_host.h }]} { user-error "Found /opt/vc but cannot #include bcm_host.h!" } else { define PI_CFLAGS "-I/opt/vc/include" define PI_LFLAGS "-L/opt/vc/lib" define PI_LIBS "-lbcm_host" } define LIBS $old_LIBS # Ensure we have the libncurses development files installed here, else # pidp8i-test won't build. if {![cc-check-includes curses.h]} { user-error "Could not find curses.h. Try installing libncurses-dev." } elseif {![cc-check-function-in-lib initscr ncurses]} { user-error "Could not find initscr() in libncurses." |
︙ | ︙ |
Changes to autosetup/autosetup.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/bin/sh # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # vim:se syntax=tcl: # \ dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@" set autosetup(version) 0.6.9 # Can be set to 1 to debug early-init problems set autosetup(debug) [expr {"--debug" in $argv}] ################################################################## # | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/bin/sh # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ # All rights reserved # vim:se syntax=tcl: # \ dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@" # Note that the version has a trailing + on unreleased versions set autosetup(version) 0.6.9 # Can be set to 1 to debug early-init problems set autosetup(debug) [expr {"--debug" in $argv}] ################################################################## # |
︙ | ︙ | |||
209 210 211 212 213 214 215 216 217 218 219 220 221 222 | } define AUTOREMAKE [file-normalize $autosetup(exe)] define-append AUTOREMAKE [get-define CONFIGURE_OPTS] # Log how we were invoked configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]" # Note that auto.def is *not* loaded in the global scope source $autosetup(autodef) # Could warn here if options {} was not specified show-notices | > | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | } define AUTOREMAKE [file-normalize $autosetup(exe)] define-append AUTOREMAKE [get-define CONFIGURE_OPTS] # Log how we were invoked configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]" configlog "Tclsh: [info nameofexecutable]" # Note that auto.def is *not* loaded in the global scope source $autosetup(autodef) # Could warn here if options {} was not specified show-notices |
︙ | ︙ |
Changes to autosetup/jimsh0.c.
︙ | ︙ | |||
55 56 57 58 59 60 61 | #define HAVE_MKSTEMP #define HAVE_LINK #define HAVE_SYS_TIME_H #define HAVE_DIRENT_H #define HAVE_UNISTD_H #define HAVE_UMASK #endif | | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #define HAVE_MKSTEMP #define HAVE_LINK #define HAVE_SYS_TIME_H #define HAVE_DIRENT_H #define HAVE_UNISTD_H #define HAVE_UMASK #endif #define JIM_VERSION 78 #ifndef JIM_WIN32COMPAT_H #define JIM_WIN32COMPAT_H #ifdef __cplusplus extern "C" { |
︙ | ︙ | |||
125 126 127 128 129 130 131 | char *name; } DIR; DIR *opendir(const char *name); int closedir(DIR *dir); struct dirent *readdir(DIR *dir); | < < < < < | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | char *name; } DIR; DIR *opendir(const char *name); int closedir(DIR *dir); struct dirent *readdir(DIR *dir); #endif #endif #ifdef __cplusplus } #endif |
︙ | ︙ | |||
371 372 373 374 375 376 377 378 379 380 381 382 383 384 | void *ptr; struct { void *ptr1; void *ptr2; } twoPtrValue; struct { struct Jim_Var *varPtr; unsigned long callFrameId; int global; } varValue; struct { | > > > > > > | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | void *ptr; struct { void *ptr1; void *ptr2; } twoPtrValue; struct { void *ptr; int int1; int int2; } ptrIntValue; struct { struct Jim_Var *varPtr; unsigned long callFrameId; int global; } varValue; struct { |
︙ | ︙ | |||
408 409 410 411 412 413 414 | int lineNumber; } sourceValue; struct { struct Jim_Obj *varNameObjPtr; struct Jim_Obj *indexObjPtr; } dictSubstValue; | < < < < < | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | int lineNumber; } sourceValue; struct { struct Jim_Obj *varNameObjPtr; struct Jim_Obj *indexObjPtr; } dictSubstValue; struct { int line; int argc; } scriptLineValue; } internalRep; struct Jim_Obj *prevObjPtr; struct Jim_Obj *nextObjPtr; |
︙ | ︙ | |||
570 571 572 573 574 575 576 | Jim_Obj *nullScriptObj; Jim_Obj *emptyObj; Jim_Obj *trueObj; Jim_Obj *falseObj; unsigned long referenceNextId; struct Jim_HashTable references; unsigned long lastCollectId; /* reference max Id of the last GC | | | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | Jim_Obj *nullScriptObj; Jim_Obj *emptyObj; Jim_Obj *trueObj; Jim_Obj *falseObj; unsigned long referenceNextId; struct Jim_HashTable references; unsigned long lastCollectId; /* reference max Id of the last GC execution. It's set to ~0 while the collection is running as sentinel to avoid to recursive calls via the [collect] command inside finalizers. */ time_t lastCollectTime; Jim_Obj *stackTrace; Jim_Obj *errorProc; Jim_Obj *unknown; |
︙ | ︙ | |||
635 636 637 638 639 640 641 | JIM_EXPORT void Jim_Free (void *ptr); JIM_EXPORT char * Jim_StrDup (const char *s); JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); JIM_EXPORT char **Jim_GetEnviron(void); JIM_EXPORT void Jim_SetEnviron(char **env); | | | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 | JIM_EXPORT void Jim_Free (void *ptr); JIM_EXPORT char * Jim_StrDup (const char *s); JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); JIM_EXPORT char **Jim_GetEnviron(void); JIM_EXPORT void Jim_SetEnviron(char **env); JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file); JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script); |
︙ | ︙ | |||
843 844 845 846 847 848 849 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr); JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, | | | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr); JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, Jim_Obj *exprObjPtr); JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr); JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int *booleanPtr); |
︙ | ︙ | |||
900 901 902 903 904 905 906 | JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); JIM_EXPORT void Jim_HistoryLoad(const char *filename); JIM_EXPORT void Jim_HistorySave(const char *filename); | | > | 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); JIM_EXPORT void Jim_HistoryLoad(const char *filename); JIM_EXPORT void Jim_HistorySave(const char *filename); JIM_EXPORT char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt); JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj); JIM_EXPORT void Jim_HistoryAdd(const char *line); JIM_EXPORT void Jim_HistoryShow(void); JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); JIM_EXPORT int Jim_IsBigEndian(void); |
︙ | ︙ | |||
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); void regfree(regex_t *preg); #ifdef __cplusplus } #endif #endif int Jim_bootstrapInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG)) return JIM_ERR; return Jim_EvalSource(interp, "bootstrap.tcl", 1, "\n" "\n" | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | | | 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 | size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); void regfree(regex_t *preg); #ifdef __cplusplus } #endif #endif #ifndef JIM_SIGNAL_H #define JIM_SIGNAL_H #ifdef __cplusplus extern "C" { #endif const char *Jim_SignalId(int sig); #ifdef __cplusplus } #endif #endif #ifndef JIMIOCOMPAT_H #define JIMIOCOMPAT_H #include <stdio.h> #include <errno.h> void Jim_SetResultErrno(Jim_Interp *interp, const char *msg); int Jim_OpenForWrite(const char *filename, int append); int Jim_OpenForRead(const char *filename); #if defined(__MINGW32__) #ifndef STRICT #define STRICT #endif #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <fcntl.h> #include <io.h> #include <process.h> typedef HANDLE pidtype; #define JIM_BAD_PID INVALID_HANDLE_VALUE #define JIM_NO_PID INVALID_HANDLE_VALUE #define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0) #define WEXITSTATUS(STATUS) ((STATUS) & 0x00ff) #define WIFSIGNALED(STATUS) (((STATUS) & 0xff00) != 0) #define WTERMSIG(STATUS) (((STATUS) >> 8) & 0xff) #define WNOHANG 1 int Jim_Errno(void); pidtype waitpid(pidtype pid, int *status, int nohang); #define HAVE_PIPE #define pipe(P) _pipe((P), 0, O_NOINHERIT) #elif defined(HAVE_UNISTD_H) #include <unistd.h> #include <fcntl.h> #include <sys/wait.h> #include <sys/stat.h> typedef int pidtype; #define Jim_Errno() errno #define JIM_BAD_PID -1 #define JIM_NO_PID 0 #ifndef HAVE_EXECVPE #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) #endif #endif #endif int Jim_bootstrapInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG)) return JIM_ERR; return Jim_EvalSource(interp, "bootstrap.tcl", 1, "\n" "\n" "proc package {cmd pkg args} {\n" " if {$cmd eq \"require\"} {\n" " foreach path $::auto_path {\n" " set pkgpath $path/$pkg.tcl\n" " if {$path eq \".\"} {\n" " set pkgpath $pkg.tcl\n" " }\n" " if {[file exists $pkgpath]} {\n" " uplevel #0 [list source $pkgpath]\n" " return\n" " }\n" " }\n" " }\n" "}\n" ); } |
︙ | ︙ | |||
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 | { if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG)) return JIM_ERR; return Jim_EvalSource(interp, "stdlib.tcl", 1, "\n" "\n" "\n" "proc lambda {arglist args} {\n" " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" "}\n" "\n" "proc lambda.finalizer {name val} {\n" " rename $name {}\n" | > > > > > > > | 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 | { if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG)) return JIM_ERR; return Jim_EvalSource(interp, "stdlib.tcl", 1, "\n" "\n" "if {![exists -command ref]} {\n" "\n" " proc ref {args} {{count 0}} {\n" " format %08x [incr count]\n" " }\n" "}\n" "\n" "\n" "proc lambda {arglist args} {\n" " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" "}\n" "\n" "proc lambda.finalizer {name val} {\n" " rename $name {}\n" |
︙ | ︙ | |||
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 | " if {$line ne \"\"} {\n" " lappend lines $line\n" " }\n" " }\n" " join $lines \\n\n" "}\n" "\n" "\n" "\n" "proc errorInfo {msg {stacktrace \"\"}} {\n" " if {$stacktrace eq \"\"} {\n" "\n" " set stacktrace [info stacktrace]\n" "\n" | > > > > > > > | 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 | " if {$line ne \"\"} {\n" " lappend lines $line\n" " }\n" " }\n" " join $lines \\n\n" "}\n" "\n" "\n" "\n" "proc defer {script} {\n" " upvar jim::defer v\n" " lappend v $script\n" "}\n" "\n" "\n" "\n" "proc errorInfo {msg {stacktrace \"\"}} {\n" " if {$stacktrace eq \"\"} {\n" "\n" " set stacktrace [info stacktrace]\n" "\n" |
︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 | " catch {$in close}\n" " }\n" "}\n" "\n" "\n" "\n" "proc popen {cmd {mode r}} {\n" | | > > > > | > > > > > > > > > > > | | 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 | " catch {$in close}\n" " }\n" "}\n" "\n" "\n" "\n" "proc popen {cmd {mode r}} {\n" " lassign [pipe] r w\n" " try {\n" " if {[string match \"w*\" $mode]} {\n" " lappend cmd <@$r &\n" " set pids [exec {*}$cmd]\n" " $r close\n" " set f $w\n" " } else {\n" " lappend cmd >@$w &\n" " set pids [exec {*}$cmd]\n" " $w close\n" " set f $r\n" " }\n" " lambda {cmd args} {f pids} {\n" " if {$cmd eq \"pid\"} {\n" " return $pids\n" " }\n" " if {$cmd eq \"getfd\"} {\n" " $f getfd\n" " }\n" " if {$cmd eq \"close\"} {\n" " $f close\n" "\n" " set retopts {}\n" " foreach p $pids {\n" " lassign [wait $p] status - rc\n" " if {$status eq \"CHILDSTATUS\"} {\n" " if {$rc == 0} {\n" " continue\n" " }\n" " set msg \"child process exited abnormally\"\n" " } else {\n" " set msg \"child killed: received signal\"\n" " }\n" " set retopts [list -code error -errorcode [list $status $p $rc] $msg]\n" " }\n" " return {*}$retopts\n" " }\n" " tailcall $f $cmd {*}$args\n" " }\n" " } on error {error opts} {\n" " $r close\n" " $w close\n" " error $error\n" |
︙ | ︙ | |||
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 | " return -code error \"can not find channel named \\\"$channelId\\\"\"\n" " }\n" " if {[catch {$channelId pid} pids]} {\n" " return \"\"\n" " }\n" " return $pids\n" "}\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" | > | 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 | " return -code error \"can not find channel named \\\"$channelId\\\"\"\n" " }\n" " if {[catch {$channelId pid} pids]} {\n" " return \"\"\n" " }\n" " return $pids\n" "}\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" |
︙ | ︙ | |||
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 | #include <sys/stat.h> #endif #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #ifdef HAVE_SYS_UN_H #include <sys/un.h> #endif #else #define JIM_ANSIC #endif #if defined(JIM_SSL) #include <openssl/ssl.h> #include <openssl/err.h> | > > > > | 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 | #include <sys/stat.h> #endif #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) #include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> #include <netdb.h> #ifdef HAVE_SYS_UN_H #include <sys/un.h> #endif #define HAVE_SOCKETS #elif defined (__MINGW32__) #else #define JIM_ANSIC #endif #if defined(JIM_SSL) #include <openssl/ssl.h> #include <openssl/err.h> |
︙ | ︙ | |||
1845 1846 1847 1848 1849 1850 1851 | #else #define IPV6 0 #ifndef PF_INET6 #define PF_INET6 0 #endif #endif | > | > > > | 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 | #else #define IPV6 0 #ifndef PF_INET6 #define PF_INET6 0 #endif #endif #ifdef JIM_ANSIC #undef HAVE_PIPE #undef HAVE_SOCKETPAIR #endif struct AioFile; typedef struct { int (*writer)(struct AioFile *af, const char *buf, int len); int (*reader)(struct AioFile *af, char *buf, int len); |
︙ | ︙ | |||
1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 | if (name) { Jim_SetResultFormatted(interp, "%#s: %s", name, JimAioErrorString(af)); } else { Jim_SetResultString(interp, JimAioErrorString(af), -1); } } static void JimAioDelProc(Jim_Interp *interp, void *privData) { AioFile *af = privData; JIM_NOTUSED(interp); | > > > > > > > > > | 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 | if (name) { Jim_SetResultFormatted(interp, "%#s: %s", name, JimAioErrorString(af)); } else { Jim_SetResultString(interp, JimAioErrorString(af), -1); } } static int JimCheckStreamError(Jim_Interp *interp, AioFile *af) { int ret = af->fops->error(af); if (ret) { JimAioSetError(interp, af->filename); } return ret; } static void JimAioDelProc(Jim_Interp *interp, void *privData) { AioFile *af = privData; JIM_NOTUSED(interp); |
︙ | ︙ | |||
2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 | af = Jim_AioFile(interp, command); if (af == NULL) { return NULL; } return af->fp; } static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); jim_wide count = 0; jim_wide maxlen = JIM_WIDE_MAX; AioFile *outf = Jim_AioFile(interp, argv[0]); | > > > > > > > > > > | 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 | af = Jim_AioFile(interp, command); if (af == NULL) { return NULL; } return af->fp; } static int aio_cmd_getfd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); fflush(af->fp); Jim_SetResultInt(interp, fileno(af->fp)); return JIM_OK; } static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); jim_wide count = 0; jim_wide maxlen = JIM_WIDE_MAX; AioFile *outf = Jim_AioFile(interp, argv[0]); |
︙ | ︙ | |||
2222 2223 2224 2225 2226 2227 2228 | Jim_SetResultInt(interp, feof(af->fp)); return JIM_OK; } static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc == 3) { | | | 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 | Jim_SetResultInt(interp, feof(af->fp)); return JIM_OK; } static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc == 3) { #if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN) static const char * const options[] = { "r", "w", NULL }; enum { OPT_R, OPT_W, }; int option; AioFile *af = Jim_CmdPrivData(interp); if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { return JIM_ERR; |
︙ | ︙ | |||
2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 | } (void)fcntl(af->fd, F_SETFL, fmode); } Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); return JIM_OK; } #endif #ifdef HAVE_FSYNC static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); fflush(af->fp); | > | 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 | } (void)fcntl(af->fd, F_SETFL, fmode); } Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); return JIM_OK; } #endif #ifdef HAVE_FSYNC static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { AioFile *af = Jim_CmdPrivData(interp); fflush(af->fp); |
︙ | ︙ | |||
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 | }, { "copyto", "handle ?size?", aio_cmd_copy, 1, 2, }, { "gets", "?var?", aio_cmd_gets, 0, 1, | > > > > > > > | 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 | }, { "copyto", "handle ?size?", aio_cmd_copy, 1, 2, }, { "getfd", NULL, aio_cmd_getfd, 0, 0, }, { "gets", "?var?", aio_cmd_gets, 0, 1, |
︙ | ︙ | |||
2620 2621 2622 2623 2624 2625 2626 | if (!filename) { filename = Jim_NewStringObj(interp, buf, -1); } Jim_IncrRefCount(filename); if (fh == NULL) { | < > > < | < > > > | < | | < | < < | < < < < | < | | < < < | < | < < < < | < | < | < < < > | | > > > | 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 | if (!filename) { filename = Jim_NewStringObj(interp, buf, -1); } Jim_IncrRefCount(filename); if (fh == NULL) { if (fd >= 0) { #ifndef JIM_ANSIC fh = fdopen(fd, mode); #endif } else fh = fopen(Jim_String(filename), mode); if (fh == NULL) { JimAioSetError(interp, filename); #ifndef JIM_ANSIC if (fd >= 0) { close(fd); } #endif Jim_DecrRefCount(interp, filename); return NULL; } } af = Jim_Alloc(sizeof(*af)); memset(af, 0, sizeof(*af)); af->fp = fh; af->filename = filename; af->openFlags = openFlags; #ifndef JIM_ANSIC af->fd = fileno(fh); #ifdef FD_CLOEXEC if ((openFlags & AIO_KEEPOPEN) == 0) { (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); } #endif #endif af->addr_family = family; af->fops = &stdio_fops; af->ssl = NULL; Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1))); return af; } #if defined(HAVE_PIPE) || (defined(HAVE_SOCKETPAIR) && defined(HAVE_SYS_UN_H)) static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename, const char *hdlfmt, int family, const char *mode[2]) { if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) { Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) { Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); Jim_SetResult(interp, objPtr); return JIM_OK; } } close(p[0]); close(p[1]); JimAioSetError(interp, NULL); return JIM_ERR; } #endif #ifdef HAVE_PIPE static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int p[2]; static const char *mode[2] = { "r", "w" }; if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, ""); return JIM_ERR; } if (pipe(p) != 0) { JimAioSetError(interp, NULL); return JIM_ERR; } return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode); } #endif int Jim_aioInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG)) return JIM_ERR; #if defined(JIM_SSL) Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL); #endif Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); #ifdef HAVE_SOCKETS Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL); #endif #ifdef HAVE_PIPE Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL); #endif JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r"); JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); return JIM_OK; |
︙ | ︙ | |||
2824 2825 2826 2827 2828 2829 2830 | #if defined(JIM_REGEXP) #else #include <regex.h> #endif static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { | | | | | | 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 | #if defined(JIM_REGEXP) #else #include <regex.h> #endif static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { regfree(objPtr->internalRep.ptrIntValue.ptr); Jim_Free(objPtr->internalRep.ptrIntValue.ptr); } static const Jim_ObjType regexpObjType = { "regexp", FreeRegexpInternalRep, NULL, NULL, JIM_TYPE_NONE }; static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned flags) { regex_t *compre; const char *pattern; int ret; if (objPtr->typePtr == ®expObjType && objPtr->internalRep.ptrIntValue.ptr && objPtr->internalRep.ptrIntValue.int1 == flags) { return objPtr->internalRep.ptrIntValue.ptr; } pattern = Jim_String(objPtr); compre = Jim_Alloc(sizeof(regex_t)); |
︙ | ︙ | |||
2868 2869 2870 2871 2872 2873 2874 | Jim_Free(compre); return NULL; } Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = ®expObjType; | | | | 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 | Jim_Free(compre); return NULL; } Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = ®expObjType; objPtr->internalRep.ptrIntValue.int1 = flags; objPtr->internalRep.ptrIntValue.ptr = compre; return compre; } int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int opt_indices = 0; |
︙ | ︙ | |||
3331 3332 3333 3334 3335 3336 3337 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif # ifndef MAXPATHLEN # define MAXPATHLEN JIM_PATH_LEN # endif | | > > > > > > > | 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif # ifndef MAXPATHLEN # define MAXPATHLEN JIM_PATH_LEN # endif #if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER) #define ISWINDOWS 1 #else #define ISWINDOWS 0 #endif #if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) #define STAT_MTIME_US(STAT) ((STAT).st_mtimespec.tv_sec * 1000000ll + (STAT).st_mtimespec.tv_nsec / 1000) #elif defined(HAVE_STRUCT_STAT_ST_MTIM) #define STAT_MTIME_US(STAT) ((STAT).st_mtim.tv_sec * 1000000ll + (STAT).st_mtim.tv_nsec / 1000) #endif static const char *JimGetFileType(int mode) { if (S_ISREG(mode)) { return "file"; } else if (S_ISDIR(mode)) { |
︙ | ︙ | |||
3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 | AppendStatElement(interp, listObj, "nlink", sb->st_nlink); AppendStatElement(interp, listObj, "uid", sb->st_uid); AppendStatElement(interp, listObj, "gid", sb->st_gid); AppendStatElement(interp, listObj, "size", sb->st_size); AppendStatElement(interp, listObj, "atime", sb->st_atime); AppendStatElement(interp, listObj, "mtime", sb->st_mtime); AppendStatElement(interp, listObj, "ctime", sb->st_ctime); Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); if (varName) { Jim_Obj *objPtr; objPtr = Jim_GetVariable(interp, varName, JIM_NONE); | > > > | 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 | AppendStatElement(interp, listObj, "nlink", sb->st_nlink); AppendStatElement(interp, listObj, "uid", sb->st_uid); AppendStatElement(interp, listObj, "gid", sb->st_gid); AppendStatElement(interp, listObj, "size", sb->st_size); AppendStatElement(interp, listObj, "atime", sb->st_atime); AppendStatElement(interp, listObj, "mtime", sb->st_mtime); AppendStatElement(interp, listObj, "ctime", sb->st_ctime); #ifdef STAT_MTIME_US AppendStatElement(interp, listObj, "mtimeus", STAT_MTIME_US(*sb)); #endif Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); if (varName) { Jim_Obj *objPtr; objPtr = Jim_GetVariable(interp, varName, JIM_NONE); |
︙ | ︙ | |||
3711 3712 3713 3714 3715 3716 3717 | argv++; } return JIM_OK; } static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { | | | 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 | argv++; } return JIM_OK; } static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL, 0); if (fd < 0) { return JIM_ERR; } close(fd); return JIM_OK; |
︙ | ︙ | |||
3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { return JIM_ERR; } Jim_SetResultInt(interp, sb.st_atime); return JIM_OK; } static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct stat sb; if (argc == 2) { | > > > > > > > > > > > > > > > > > > > < | < < | < < < < | < < < < < < < > > > > > > > > > > > > > > > > > > > > | 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 | if (file_stat(interp, argv[0], &sb) != JIM_OK) { return JIM_ERR; } Jim_SetResultInt(interp, sb.st_atime); return JIM_OK; } static int JimSetFileTimes(Jim_Interp *interp, const char *filename, jim_wide us) { #ifdef HAVE_UTIMES struct timeval times[2]; times[1].tv_sec = times[0].tv_sec = us / 1000000; times[1].tv_usec = times[0].tv_usec = us % 1000000; if (utimes(filename, times) != 0) { Jim_SetResultFormatted(interp, "can't set time on \"%s\": %s", filename, strerror(errno)); return JIM_ERR; } return JIM_OK; #else Jim_SetResultString(interp, "Not implemented", -1); return JIM_ERR; #endif } static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct stat sb; if (argc == 2) { jim_wide secs; if (Jim_GetWide(interp, argv[1], &secs) != JIM_OK) { return JIM_ERR; } return JimSetFileTimes(interp, Jim_String(argv[0]), secs * 1000000); } if (file_stat(interp, argv[0], &sb) != JIM_OK) { return JIM_ERR; } Jim_SetResultInt(interp, sb.st_mtime); return JIM_OK; } #ifdef STAT_MTIME_US static int file_cmd_mtimeus(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct stat sb; if (argc == 2) { jim_wide us; if (Jim_GetWide(interp, argv[1], &us) != JIM_OK) { return JIM_ERR; } return JimSetFileTimes(interp, Jim_String(argv[0]), us); } if (file_stat(interp, argv[0], &sb) != JIM_OK) { return JIM_ERR; } Jim_SetResultInt(interp, STAT_MTIME_US(sb)); return JIM_OK; } #endif static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { return Jim_EvalPrefix(interp, "file copy", argc, argv); } static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
︙ | ︙ | |||
3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 | { "mtime", "name ?time?", file_cmd_mtime, 1, 2, }, { "copy", "?-force? source dest", file_cmd_copy, 2, 3, }, | > > > > > > > > > | 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 | { "mtime", "name ?time?", file_cmd_mtime, 1, 2, }, #ifdef STAT_MTIME_US { "mtimeus", "name ?time?", file_cmd_mtimeus, 1, 2, }, #endif { "copy", "?-force? source dest", file_cmd_copy, 2, 3, }, |
︙ | ︙ | |||
4282 4283 4284 4285 4286 4287 4288 | return JIM_OK; } #else #include <errno.h> #include <signal.h> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < | < < < < < | | | < < > | < < < | < < < < | | | 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 | return JIM_OK; } #else #include <errno.h> #include <signal.h> #include <sys/stat.h> struct WaitInfoTable; static char **JimOriginalEnviron(void); static char **JimSaveEnv(char **env); static void JimRestoreEnv(char **env); static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr); static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr); static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj); static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv); #if defined(__MINGW32__) static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId); #endif static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) { int len; const char *s = Jim_GetString(objPtr, &len); if (len > 0 && s[len - 1] == '\n') { objPtr->length--; objPtr->bytes[objPtr->length] = '\0'; } } static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj) { char buf[256]; FILE *fh = fdopen(fd, "r"); int ret = 0; if (fh == NULL) { return -1; } while (1) { |
︙ | ︙ | |||
4450 4451 4452 4453 4454 4455 4456 | static void JimFreeEnv(char **env, char **original_environ) { if (env != original_environ) { Jim_Free(env); } } | < < < < < < < < < < < < < < < | | < | < > > | | | > > > | > > > | > > > > | > > > | | > > > > > > > > > > > > > > > > > > > | | > | | | | | 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 | static void JimFreeEnv(char **env, char **original_environ) { if (env != original_environ) { Jim_Free(env); } } static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) { Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); if (pid == JIM_BAD_PID || pid == JIM_NO_PID) { Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1)); Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1)); } else if (WIFEXITED(waitStatus)) { Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); } else { const char *type; const char *action; const char *signame; if (WIFSIGNALED(waitStatus)) { type = "CHILDKILLED"; action = "killed"; signame = Jim_SignalId(WTERMSIG(waitStatus)); } else { type = "CHILDSUSP"; action = "suspended"; signame = "none"; } Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1)); if (errStrObj) { Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL); } Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1)); } return errorCode; } static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) { if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) { return JIM_OK; } Jim_SetGlobalVariableStr(interp, "errorCode", JimMakeErrorCode(interp, pid, waitStatus, errStrObj)); return JIM_ERR; } struct WaitInfo { pidtype pid; int status; int flags; }; struct WaitInfoTable { struct WaitInfo *info; int size; int used; int refcount; }; #define WI_DETACHED 2 #define WAIT_TABLE_GROW_BY 4 static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData) { struct WaitInfoTable *table = privData; if (--table->refcount == 0) { Jim_Free(table->info); Jim_Free(table); } } static struct WaitInfoTable *JimAllocWaitInfoTable(void) { struct WaitInfoTable *table = Jim_Alloc(sizeof(*table)); table->info = NULL; table->size = table->used = 0; table->refcount = 1; return table; } static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid) { int i; for (i = 0; i < table->used; i++) { if (pid == table->info[i].pid) { if (i != table->used - 1) { table->info[i] = table->info[table->used - 1]; } table->used--; return 0; } } return -1; } static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int outputId; int errorId; pidtype *pidPtr; int numPids, result; int child_siginfo = 1; Jim_Obj *childErrObj; Jim_Obj *errStrObj; struct WaitInfoTable *table = Jim_CmdPrivData(interp); if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { Jim_Obj *listObj; int i; argc--; numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); if (numPids < 0) { return JIM_ERR; } listObj = Jim_NewListObj(interp, NULL, 0); for (i = 0; i < numPids; i++) { Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); } Jim_SetResult(interp, listObj); JimDetachPids(table, numPids, pidPtr); Jim_Free(pidPtr); return JIM_OK; } numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId); if (numPids < 0) { return JIM_ERR; } result = JIM_OK; errStrObj = Jim_NewStringObj(interp, "", 0); if (outputId != -1) { if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) { result = JIM_ERR; Jim_SetResultErrno(interp, "error reading from output pipe"); } } childErrObj = Jim_NewStringObj(interp, "", 0); Jim_IncrRefCount(childErrObj); if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) { result = JIM_ERR; } if (errorId != -1) { int ret; lseek(errorId, 0, SEEK_SET); ret = JimAppendStreamToString(interp, errorId, errStrObj); if (ret < 0) { Jim_SetResultErrno(interp, "error reading from error pipe"); result = JIM_ERR; } else if (ret > 0) { |
︙ | ︙ | |||
4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 | Jim_RemoveTrailingNewline(errStrObj); Jim_SetResult(interp, errStrObj); return result; } static void JimReapDetachedPids(struct WaitInfoTable *table) { struct WaitInfo *waitPtr; int count; int dest; if (!table) { return; } waitPtr = table->info; dest = 0; for (count = table->used; count > 0; waitPtr++, count--) { if (waitPtr->flags & WI_DETACHED) { int status; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < | | < < < < < < < < < < < < < < < < < < < < < > > > > > < < < | | | | | > > > > > | > > | | > | > | > | > | | > > | < > > > | > | > > | | | 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 | Jim_RemoveTrailingNewline(errStrObj); Jim_SetResult(interp, errStrObj); return result; } static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) { if (JimWaitRemove(table, pid) == 0) { waitpid(pid, statusPtr, 0); return pid; } return JIM_BAD_PID; } static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr) { int j; for (j = 0; j < numPids; j++) { int i; for (i = 0; i < table->used; i++) { if (pidPtr[j] == table->info[i].pid) { table->info[i].flags |= WI_DETACHED; break; } } } } static int JimGetChannelFd(Jim_Interp *interp, const char *name) { Jim_Obj *objv[2]; objv[0] = Jim_NewStringObj(interp, name, -1); objv[1] = Jim_NewStringObj(interp, "getfd", -1); if (Jim_EvalObjVector(interp, 2, objv) == JIM_OK) { jim_wide fd; if (Jim_GetWide(interp, Jim_GetResult(interp), &fd) == JIM_OK) { return fd; } } return -1; } static void JimReapDetachedPids(struct WaitInfoTable *table) { struct WaitInfo *waitPtr; int count; int dest; if (!table) { return; } waitPtr = table->info; dest = 0; for (count = table->used; count > 0; waitPtr++, count--) { if (waitPtr->flags & WI_DETACHED) { int status; pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG); if (pid == waitPtr->pid) { table->used--; continue; } } if (waitPtr != &table->info[dest]) { table->info[dest] = *waitPtr; } dest++; } } static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct WaitInfoTable *table = Jim_CmdPrivData(interp); int nohang = 0; pidtype pid; long pidarg; int status; Jim_Obj *errCodeObj; if (argc == 1) { JimReapDetachedPids(table); return JIM_OK; } if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) { nohang = 1; } if (argc != nohang + 2) { Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?"); return JIM_ERR; } if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) { return JIM_ERR; } pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0); errCodeObj = JimMakeErrorCode(interp, pid, status, NULL); if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) { JimWaitRemove(table, pid); } Jim_SetResult(interp, errCodeObj); return JIM_OK; } static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, ""); return JIM_ERR; } Jim_SetResultInt(interp, (jim_wide)getpid()); return JIM_OK; } static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr) { pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all * the pids of child processes. */ int numPids = 0; /* Actual number of processes that exist * at *pidPtr right now. */ int cmdCount; /* Count of number of distinct commands * found in argc/argv. */ |
︙ | ︙ | |||
4750 4751 4752 4753 4754 4755 4756 | * 2 means error is filehandle name. * All this is ignored if error is NULL */ const char *output = NULL; /* Holds name of output file to pipe to, * or NULL if output goes to stdout/pipe. */ const char *error = NULL; /* Holds name of stderr file to pipe to, * or NULL if stderr goes to stderr/pipe. */ | | | | | | > > > < < | | | | | 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 | * 2 means error is filehandle name. * All this is ignored if error is NULL */ const char *output = NULL; /* Holds name of output file to pipe to, * or NULL if output goes to stdout/pipe. */ const char *error = NULL; /* Holds name of stderr file to pipe to, * or NULL if stderr goes to stderr/pipe. */ int inputId = -1; int outputId = -1; int errorId = -1; int lastOutputId = -1; int pipeIds[2]; int firstArg, lastArg; /* Indexes of first and last arguments in * current command. */ int lastBar; int i; pidtype pid; char **save_environ; #ifndef __MINGW32__ char **child_environ; #endif struct WaitInfoTable *table = Jim_CmdPrivData(interp); char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1)); int arg_count = 0; if (inPipePtr != NULL) { *inPipePtr = -1; } if (outPipePtr != NULL) { *outPipePtr = -1; } if (errFilePtr != NULL) { *errFilePtr = -1; } pipeIds[0] = pipeIds[1] = -1; cmdCount = 1; lastBar = -1; for (i = 0; i < argc; i++) { const char *arg = Jim_String(argv[i]); if (arg[0] == '<') { |
︙ | ︙ | |||
4877 4878 4879 4880 4881 4882 4883 | } save_environ = JimSaveEnv(JimBuildEnv(interp)); if (input != NULL) { if (inputFile == FILE_TEXT) { | | | > > > > | | | > | | | | | | | | | | < | | | | | | | | | | | < | | | | | | | | | > > | | < > > > > > > > | > > > | > > > | > > > > > | > > | | > > > > > > > | > > > | > > > < > | 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 | } save_environ = JimSaveEnv(JimBuildEnv(interp)); if (input != NULL) { if (inputFile == FILE_TEXT) { inputId = Jim_MakeTempFile(interp, NULL, 1); if (inputId == -1) { goto error; } if (write(inputId, input, input_len) != input_len) { Jim_SetResultErrno(interp, "couldn't write temp file"); close(inputId); goto error; } lseek(inputId, 0L, SEEK_SET); } else if (inputFile == FILE_HANDLE) { int fd = JimGetChannelFd(interp, input); if (fd < 0) { goto error; } inputId = dup(fd); } else { inputId = Jim_OpenForRead(input); if (inputId == -1) { Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, strerror(Jim_Errno())); goto error; } } } else if (inPipePtr != NULL) { if (pipe(pipeIds) != 0) { Jim_SetResultErrno(interp, "couldn't create input pipe for command"); goto error; } inputId = pipeIds[0]; *inPipePtr = pipeIds[1]; pipeIds[0] = pipeIds[1] = -1; } if (output != NULL) { if (outputFile == FILE_HANDLE) { int fd = JimGetChannelFd(interp, output); if (fd < 0) { goto error; } lastOutputId = dup(fd); } else { lastOutputId = Jim_OpenForWrite(output, outputFile == FILE_APPEND); if (lastOutputId == -1) { Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, strerror(Jim_Errno())); goto error; } } } else if (outPipePtr != NULL) { if (pipe(pipeIds) != 0) { Jim_SetResultErrno(interp, "couldn't create output pipe"); goto error; } lastOutputId = pipeIds[1]; *outPipePtr = pipeIds[0]; pipeIds[0] = pipeIds[1] = -1; } if (error != NULL) { if (errorFile == FILE_HANDLE) { if (strcmp(error, "1") == 0) { if (lastOutputId != -1) { errorId = dup(lastOutputId); } else { error = "stdout"; } } if (errorId == -1) { int fd = JimGetChannelFd(interp, error); if (fd < 0) { goto error; } errorId = dup(fd); } } else { errorId = Jim_OpenForWrite(error, errorFile == FILE_APPEND); if (errorId == -1) { Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, strerror(Jim_Errno())); goto error; } } } else if (errFilePtr != NULL) { errorId = Jim_MakeTempFile(interp, NULL, 1); if (errorId == -1) { goto error; } *errFilePtr = dup(errorId); } pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); for (i = 0; i < numPids; i++) { pidPtr[i] = JIM_BAD_PID; } for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { int pipe_dup_err = 0; int origErrorId = errorId; for (lastArg = firstArg; lastArg < arg_count; lastArg++) { if (strcmp(arg_array[lastArg], "|") == 0) { break; } if (strcmp(arg_array[lastArg], "|&") == 0) { pipe_dup_err = 1; break; } } if (lastArg == firstArg) { Jim_SetResultString(interp, "missing command to exec", -1); goto error; } arg_array[lastArg] = NULL; if (lastArg == arg_count) { outputId = lastOutputId; lastOutputId = -1; } else { if (pipe(pipeIds) != 0) { Jim_SetResultErrno(interp, "couldn't create pipe"); goto error; } outputId = pipeIds[1]; } if (pipe_dup_err) { errorId = outputId; } #ifdef __MINGW32__ pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId); if (pid == JIM_BAD_PID) { Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); goto error; } #else i = strlen(arg_array[firstArg]); child_environ = Jim_GetEnviron(); pid = vfork(); if (pid < 0) { Jim_SetResultErrno(interp, "couldn't fork child process"); goto error; } if (pid == 0) { if (inputId != -1) { dup2(inputId, fileno(stdin)); close(inputId); } if (outputId != -1) { dup2(outputId, fileno(stdout)); if (outputId != errorId) { close(outputId); } } if (errorId != -1) { dup2(errorId, fileno(stderr)); close(errorId); } if (outPipePtr) { close(*outPipePtr); } if (errFilePtr) { close(*errFilePtr); } if (pipeIds[0] != -1) { close(pipeIds[0]); } if (lastOutputId != -1) { close(lastOutputId); } (void)signal(SIGPIPE, SIG_DFL); execvpe(arg_array[firstArg], &arg_array[firstArg], child_environ); if (write(fileno(stderr), "couldn't exec \"", 15) && write(fileno(stderr), arg_array[firstArg], i) && write(fileno(stderr), "\"\n", 2)) { } #ifdef JIM_MAINTAINER { static char *const false_argv[2] = {"false", NULL}; execvp(false_argv[0],false_argv); } #endif |
︙ | ︙ | |||
5068 5069 5070 5071 5072 5073 5074 | pidPtr[numPids] = pid; errorId = origErrorId; | | | | | < | | | | | | | | | | | | | | | | | | | | | | 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 | pidPtr[numPids] = pid; errorId = origErrorId; if (inputId != -1) { close(inputId); } if (outputId != -1) { close(outputId); } inputId = pipeIds[0]; pipeIds[0] = pipeIds[1] = -1; } *pidArrayPtr = pidPtr; cleanup: if (inputId != -1) { close(inputId); } if (lastOutputId != -1) { close(lastOutputId); } if (errorId != -1) { close(errorId); } Jim_Free(arg_array); JimRestoreEnv(save_environ); return numPids; error: if ((inPipePtr != NULL) && (*inPipePtr != -1)) { close(*inPipePtr); *inPipePtr = -1; } if ((outPipePtr != NULL) && (*outPipePtr != -1)) { close(*outPipePtr); *outPipePtr = -1; } if ((errFilePtr != NULL) && (*errFilePtr != -1)) { close(*errFilePtr); *errFilePtr = -1; } if (pipeIds[0] != -1) { close(pipeIds[0]); } if (pipeIds[1] != -1) { close(pipeIds[1]); } if (pidPtr != NULL) { for (i = 0; i < numPids; i++) { if (pidPtr[i] != JIM_BAD_PID) { JimDetachPids(table, 1, &pidPtr[i]); } } Jim_Free(pidPtr); } numPids = -1; goto cleanup; } |
︙ | ︙ | |||
5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 | Jim_Free(pidPtr); return result; } int Jim_execInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) return JIM_ERR; #ifdef SIGPIPE (void)signal(SIGPIPE, SIG_IGN); #endif | > > | > > > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 | Jim_Free(pidPtr); return result; } int Jim_execInit(Jim_Interp *interp) { struct WaitInfoTable *waitinfo; if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) return JIM_ERR; #ifdef SIGPIPE (void)signal(SIGPIPE, SIG_IGN); #endif waitinfo = JimAllocWaitInfoTable(); Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable); waitinfo->refcount++; Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable); Jim_CreateCommand(interp, "pid", Jim_PidCommand, 0, 0); return JIM_OK; } #if defined(__MINGW32__) static int JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH]) { int i; static char extensions[][5] = {".exe", "", ".bat"}; for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) { |
︙ | ︙ | |||
5489 5490 5491 5492 5493 5494 5495 | Jim_AppendString(interp, strObj, "\"", 1); } } return strObj; } static pidtype | | | | 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 | Jim_AppendString(interp, strObj, "\"", 1); } } return strObj; } static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId) { STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; HANDLE hProcess; char execPath[MAX_PATH]; pidtype pid = JIM_BAD_PID; Jim_Obj *cmdLineObj; char *winenv; if (JimWinFindExecutable(argv[0], execPath) < 0) { return JIM_BAD_PID; |
︙ | ︙ | |||
5515 5516 5517 5518 5519 5520 5521 | ZeroMemory(&startInfo, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.hStdInput = INVALID_HANDLE_VALUE; startInfo.hStdOutput= INVALID_HANDLE_VALUE; startInfo.hStdError = INVALID_HANDLE_VALUE; | | < | | < | | < | | | < < > | | < | > | > | < < < | | < | | 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 | ZeroMemory(&startInfo, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.hStdInput = INVALID_HANDLE_VALUE; startInfo.hStdOutput= INVALID_HANDLE_VALUE; startInfo.hStdError = INVALID_HANDLE_VALUE; if (inputId == -1) { inputId = _fileno(stdin); } DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(inputId), hProcess, &startInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); if (startInfo.hStdInput == INVALID_HANDLE_VALUE) { goto end; } if (outputId == -1) { outputId = _fileno(stdout); } DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(outputId), hProcess, &startInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) { goto end; } if (errorId == -1) { errorId = _fileno(stderr); } DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(errorId), hProcess, &startInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); if (startInfo.hStdError == INVALID_HANDLE_VALUE) { goto end; } if (env == NULL) { winenv = NULL; } |
︙ | ︙ | |||
5574 5575 5576 5577 5578 5579 5580 | WaitForInputIdle(procInfo.hProcess, 5000); CloseHandle(procInfo.hThread); pid = procInfo.hProcess; end: Jim_FreeNewObj(interp, cmdLineObj); | | | | < < < < < | < | < < < < < < < < < < < < < < < < < < < < < | 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 | WaitForInputIdle(procInfo.hProcess, 5000); CloseHandle(procInfo.hThread); pid = procInfo.hProcess; end: Jim_FreeNewObj(interp, cmdLineObj); if (startInfo.hStdInput != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdInput); } if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdOutput); } if (startInfo.hStdError != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdError); } return pid; } #else static char **JimOriginalEnviron(void) { return Jim_GetEnviron(); } static char **JimSaveEnv(char **env) { |
︙ | ︙ | |||
5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 | JimFreeEnv(Jim_GetEnviron(), env); Jim_SetEnviron(env); } #endif #endif #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 500 #endif #include <stdlib.h> #include <string.h> #include <stdio.h> #include <time.h> #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { char buf[100]; time_t t; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | > | | < | < > | < > > | | > > > > > > > > > > > > > > | > | > > > > > > > | | | 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 | JimFreeEnv(Jim_GetEnviron(), env); Jim_SetEnviron(env); } #endif #endif #ifdef STRPTIME_NEEDS_XOPEN_SOURCE #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 500 #endif #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <stdlib.h> #include <string.h> #include <stdio.h> #include <time.h> #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif struct clock_options { int gmt; const char *format; }; static int parse_clock_options(Jim_Interp *interp, int argc, Jim_Obj *const *argv, struct clock_options *opts) { static const char * const options[] = { "-gmt", "-format", NULL }; enum { OPT_GMT, OPT_FORMAT, }; int i; for (i = 0; i < argc; i += 2) { int option; if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { return JIM_ERR; } switch (option) { case OPT_GMT: if (Jim_GetBoolean(interp, argv[i + 1], &opts->gmt) != JIM_OK) { return JIM_ERR; } break; case OPT_FORMAT: opts->format = Jim_String(argv[i + 1]); break; } } return JIM_OK; } static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { char buf[100]; time_t t; jim_wide seconds; struct clock_options options = { 0, "%a %b %d %H:%M:%S %Z %Y" }; struct tm *tm; if (Jim_GetWide(interp, argv[0], &seconds) != JIM_OK) { return JIM_ERR; } if (argc % 2 == 0) { return -1; } if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) { return JIM_ERR; } t = seconds; tm = options.gmt ? gmtime(&t) : localtime(&t); if (tm == NULL || strftime(buf, sizeof(buf), options.format, tm) == 0) { Jim_SetResultString(interp, "format string too long or invalid time", -1); return JIM_ERR; } Jim_SetResultString(interp, buf, -1); return JIM_OK; } #ifdef HAVE_STRPTIME static time_t jim_timegm(const struct tm *tm) { int m = tm->tm_mon + 1; int y = 1900 + tm->tm_year - (m <= 2); int era = (y >= 0 ? y : y - 399) / 400; unsigned yoe = (unsigned)(y - era * 400); unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + tm->tm_mday - 1; unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; long days = (era * 146097 + (int)doe - 719468); int secs = tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; return days * 24 * 60 * 60 + secs; } static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { char *pt; struct tm tm; time_t now = time(NULL); struct clock_options options = { 0, NULL }; if (argc % 2 == 0) { return -1; } if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) { return JIM_ERR; } if (options.format == NULL) { return -1; } localtime_r(&now, &tm); pt = strptime(Jim_String(argv[0]), options.format, &tm); if (pt == 0 || *pt != 0) { Jim_SetResultString(interp, "Failed to parse time according to format", -1); return JIM_ERR; } Jim_SetResultInt(interp, options.gmt ? jim_timegm(&tm) : mktime(&tm)); return JIM_OK; } #endif static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { |
︙ | ︙ | |||
5739 5740 5741 5742 5743 5744 5745 | Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000); return JIM_OK; } static const jim_subcmd_type clock_command_table[] = { | < < < < < < < > > > > > > > < < < < < < < | < > > > > > > > > | 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 | Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000); return JIM_OK; } static const jim_subcmd_type clock_command_table[] = { { "clicks", NULL, clock_cmd_micros, 0, 0, }, { "format", "seconds ?-format string? ?-gmt boolean?", clock_cmd_format, 1, 5, }, { "microseconds", NULL, clock_cmd_micros, 0, 0, }, { "milliseconds", NULL, clock_cmd_millis, 0, 0, }, #ifdef HAVE_STRPTIME { "scan", "str -format format ?-gmt boolean?", clock_cmd_scan, 3, 5, }, #endif { "seconds", NULL, clock_cmd_seconds, 0, 0, }, { NULL } }; int Jim_clockInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG)) return JIM_ERR; |
︙ | ︙ | |||
6196 6197 6198 6199 6200 6201 6202 | int start; int end; pattern += utf8_tounicode_case(pattern, &start, nocase); if (pattern[0] == '-' && pattern[1]) { | | | 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 | int start; int end; pattern += utf8_tounicode_case(pattern, &start, nocase); if (pattern[0] == '-' && pattern[1]) { pattern++; pattern += utf8_tounicode_case(pattern, &end, nocase); if ((c >= start && c <= end) || (c >= end && c <= start)) { match = 1; } continue; |
︙ | ︙ | |||
7791 7792 7793 7794 7795 7796 7797 | { const char *start, *end; char *token; int len; start = pc->tstart; end = pc->tend; | > | < < < < | | | | | | | < | 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 | { const char *start, *end; char *token; int len; start = pc->tstart; end = pc->tend; len = (end - start) + 1; if (len < 0) { len = 0; } token = Jim_Alloc(len + 1); if (pc->tt != JIM_TT_ESC) { memcpy(token, start, len); token[len] = '\0'; } else { len = JimEscape(token, start, len); } return Jim_NewStringObjNoAlloc(interp, token, len); } static int JimParseListSep(struct JimParserCtx *pc); static int JimParseListStr(struct JimParserCtx *pc); |
︙ | ︙ | |||
8006 8007 8008 8009 8010 8011 8012 | dupPtr = Jim_NewObj(interp); if (objPtr->bytes == NULL) { dupPtr->bytes = NULL; } else if (objPtr->length == 0) { | < | 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 | dupPtr = Jim_NewObj(interp); if (objPtr->bytes == NULL) { dupPtr->bytes = NULL; } else if (objPtr->length == 0) { dupPtr->bytes = JimEmptyStringRep; dupPtr->length = 0; dupPtr->typePtr = NULL; return dupPtr; } else { dupPtr->bytes = Jim_Alloc(objPtr->length + 1); |
︙ | ︙ | |||
8050 8051 8052 8053 8054 8055 8056 | } int Jim_Length(Jim_Obj *objPtr) { if (objPtr->bytes == NULL) { | < | < < | > > > > > > > > > > > | > | | | < | < > | 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 | } int Jim_Length(Jim_Obj *objPtr) { if (objPtr->bytes == NULL) { Jim_GetString(objPtr, NULL); } return objPtr->length; } const char *Jim_String(Jim_Obj *objPtr) { if (objPtr->bytes == NULL) { Jim_GetString(objPtr, NULL); } return objPtr->bytes; } static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) { objPtr->bytes = Jim_StrDup(str); objPtr->length = strlen(str); } static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static const Jim_ObjType dictSubstObjType = { "dict-substitution", FreeDictSubstInternalRep, DupDictSubstInternalRep, NULL, JIM_TYPE_NONE, }; static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static const Jim_ObjType interpolatedObjType = { "interpolated", FreeInterpolatedInternalRep, DupInterpolatedInternalRep, NULL, JIM_TYPE_NONE, }; static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); } static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { dupPtr->internalRep = srcPtr->internalRep; Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr); } static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); static const Jim_ObjType stringObjType = { "string", NULL, |
︙ | ︙ | |||
8164 8165 8166 8167 8168 8169 8170 | if (len == -1) len = strlen(s); if (len == 0) { objPtr->bytes = JimEmptyStringRep; } else { | | < < | 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 | if (len == -1) len = strlen(s); if (len == 0) { objPtr->bytes = JimEmptyStringRep; } else { objPtr->bytes = Jim_StrDupLen(s, len); } objPtr->length = len; objPtr->typePtr = NULL; return objPtr; } |
︙ | ︙ | |||
8454 8455 8456 8457 8458 8459 8460 | static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) { char *buf; int len; const char *str; | < < < < < < < < | | 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 | static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) { char *buf; int len; const char *str; str = Jim_GetString(strObjPtr, &len); #ifdef JIM_UTF8 len *= 2; #endif buf = Jim_Alloc(len + 1); JimStrCopyUpperLower(buf, str, 0); return Jim_NewStringObjNoAlloc(interp, buf, -1); } static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) { char *buf; const char *str; int len; str = Jim_GetString(strObjPtr, &len); #ifdef JIM_UTF8 len *= 2; #endif buf = Jim_Alloc(len + 1); JimStrCopyUpperLower(buf, str, 1); return Jim_NewStringObjNoAlloc(interp, buf, -1); } static Jim_Obj *JimStringToTitle(Jim_Interp *interp, Jim_Obj *strObjPtr) { char *buf, *p; int len; int c; const char *str; str = Jim_GetString(strObjPtr, &len); #ifdef JIM_UTF8 len *= 2; #endif buf = p = Jim_Alloc(len + 1); str += utf8_tounicode(str, &c); p += utf8_getchars(p, utf8_title(c)); |
︙ | ︙ | |||
8746 8747 8748 8749 8750 8751 8752 | int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) { if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { return 1; } else { | < < | | 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 | int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) { if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { return 1; } else { if (strcmp(str, Jim_String(objPtr)) != 0) return 0; if (objPtr->typePtr != &comparedStringObjType) { Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &comparedStringObjType; } objPtr->internalRep.ptr = (char *)str; |
︙ | ︙ | |||
8944 8945 8946 8947 8948 8949 8950 | t = &tokenlist->list[tokenlist->count++]; t->token = token; t->len = len; t->type = type; t->line = line; } | | > > > > > > > | 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 | t = &tokenlist->list[tokenlist->count++]; t->token = token; t->len = len; t->type = type; t->line = line; } static int JimCountWordTokens(struct ScriptObj *script, ParseToken *t) { int expand = 1; int count = 0; if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { expand = -1; t++; } else { if (script->missing == ' ') { script->missing = '}'; script->linenr = t[1].line; } } } while (!TOKEN_IS_SEP(t->type)) { t++; count++; |
︙ | ︙ | |||
9027 9028 9029 9030 9031 9032 9033 | int wordtokens; while (tokenlist->list[i].type == JIM_TT_SEP) { i++; } | | | 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 | int wordtokens; while (tokenlist->list[i].type == JIM_TT_SEP) { i++; } wordtokens = JimCountWordTokens(script, tokenlist->list + i); if (wordtokens == 0) { if (lineargs) { linefirst->type = JIM_TT_LINE; linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); Jim_IncrRefCount(linefirst->objPtr); |
︙ | ︙ | |||
9100 9101 9102 9103 9104 9105 9106 | int Jim_ScriptIsComplete(Jim_Interp *interp, Jim_Obj *scriptObj, char *stateCharPtr) { ScriptObj *script = JimGetScript(interp, scriptObj); if (stateCharPtr) { *stateCharPtr = script->missing; } | | > > > | 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 | int Jim_ScriptIsComplete(Jim_Interp *interp, Jim_Obj *scriptObj, char *stateCharPtr) { ScriptObj *script = JimGetScript(interp, scriptObj); if (stateCharPtr) { *stateCharPtr = script->missing; } return script->missing == ' ' || script->missing == '}'; } static int JimParseCheckMissing(Jim_Interp *interp, int ch) { const char *msg; switch (ch) { case '\\': case ' ': return JIM_OK; case '[': msg = "unmatched \"[\""; break; case '{': msg = "missing close-brace"; break; case '}': msg = "extra characters after close-brace"; break; case '"': default: msg = "missing quote"; break; } Jim_SetResultString(interp, msg, -1); |
︙ | ︙ | |||
9257 9258 9259 9260 9261 9262 9263 | if (cmdPtr->prevCmd) { JimDecrCmdRefCount(interp, cmdPtr->prevCmd); } Jim_Free(cmdPtr); } } | < | 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 | if (cmdPtr->prevCmd) { JimDecrCmdRefCount(interp, cmdPtr->prevCmd); } Jim_Free(cmdPtr); } } static void JimVariablesHTValDestructor(void *interp, void *val) { Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr); Jim_Free(val); } |
︙ | ︙ | |||
9912 9913 9914 9915 9916 9917 9918 | result = Jim_SetVariableStr(interp, name, objPtr); interp->framePtr = savedFramePtr; return result; } int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) { | | < < | < | 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 | result = Jim_SetVariableStr(interp, name, objPtr); interp->framePtr = savedFramePtr; return result; } int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) { Jim_Obj *valObjPtr; int result; valObjPtr = Jim_NewStringObj(interp, val, -1); Jim_IncrRefCount(valObjPtr); result = Jim_SetVariableStr(interp, name, valObjPtr); Jim_DecrRefCount(interp, valObjPtr); return result; } int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame) { |
︙ | ︙ | |||
10233 10234 10235 10236 10237 10238 10239 | void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); } | | < | > | | < | 10249 10250 10251 10252 10253 10254 10255 10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 | void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); } static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { dupPtr->internalRep = srcPtr->internalRep; Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.varNameObjPtr); Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr); } static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { if (objPtr->typePtr != &dictSubstObjType) { Jim_Obj *varObjPtr, *keyObjPtr; |
︙ | ︙ | |||
10292 10293 10294 10295 10296 10297 10298 | Jim_DecrRefCount(interp, substKeyObjPtr); return resObjPtr; } static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) { | < < | | < < | 10307 10308 10309 10310 10311 10312 10313 10314 10315 10316 10317 10318 10319 10320 10321 10322 | Jim_DecrRefCount(interp, substKeyObjPtr); return resObjPtr; } static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) { if (Jim_EvalExpression(interp, objPtr) == JIM_OK) { return Jim_GetResult(interp); } return NULL; } static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj) { |
︙ | ︙ | |||
10378 10379 10380 10381 10382 10383 10384 10385 10386 10387 10388 10389 10390 10391 | } Jim_FreeStack(localCommands); Jim_Free(localCommands); } return JIM_OK; } #define JIM_FCF_FULL 0 #define JIM_FCF_REUSE 1 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) { JimDeleteLocalProcs(interp, cf->localCommands); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 10389 10390 10391 10392 10393 10394 10395 10396 10397 10398 10399 10400 10401 10402 10403 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 10442 10443 10444 10445 10446 10447 10448 | } Jim_FreeStack(localCommands); Jim_Free(localCommands); } return JIM_OK; } static int JimInvokeDefer(Jim_Interp *interp, int retcode) { Jim_Obj *objPtr; if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) { return retcode; } objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE); if (objPtr) { int ret = JIM_OK; int i; int listLen = Jim_ListLength(interp, objPtr); Jim_Obj *resultObjPtr; Jim_IncrRefCount(objPtr); resultObjPtr = Jim_GetResult(interp); Jim_IncrRefCount(resultObjPtr); Jim_SetEmptyResult(interp); for (i = listLen; i > 0; i--) { Jim_Obj *scriptObjPtr = Jim_ListGetIndex(interp, objPtr, i - 1); ret = Jim_EvalObj(interp, scriptObjPtr); if (ret != JIM_OK) { break; } } if (ret == JIM_OK || retcode == JIM_ERR) { Jim_SetResult(interp, resultObjPtr); } else { retcode = ret; } Jim_DecrRefCount(interp, resultObjPtr); Jim_DecrRefCount(interp, objPtr); } return retcode; } #define JIM_FCF_FULL 0 #define JIM_FCF_REUSE 1 static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) { JimDeleteLocalProcs(interp, cf->localCommands); |
︙ | ︙ | |||
10491 10492 10493 10494 10495 10496 10497 10498 10499 10500 10501 10502 10503 10504 | { Jim_CallFrame *cf, *cfx; Jim_Obj *objPtr, *nextObjPtr; for (cf = i->framePtr; cf; cf = cfx) { cfx = cf->parent; JimFreeCallFrame(i, cf, JIM_FCF_FULL); } Jim_DecrRefCount(i, i->emptyObj); Jim_DecrRefCount(i, i->trueObj); Jim_DecrRefCount(i, i->falseObj); | > > | 10548 10549 10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 10560 10561 10562 10563 | { Jim_CallFrame *cf, *cfx; Jim_Obj *objPtr, *nextObjPtr; for (cf = i->framePtr; cf; cf = cfx) { JimInvokeDefer(i, JIM_OK); cfx = cf->parent; JimFreeCallFrame(i, cf, JIM_FCF_FULL); } Jim_DecrRefCount(i, i->emptyObj); Jim_DecrRefCount(i, i->trueObj); Jim_DecrRefCount(i, i->falseObj); |
︙ | ︙ | |||
10521 10522 10523 10524 10525 10526 10527 10528 10529 10530 10531 10532 10533 10534 | if (i->liveList != NULL) { objPtr = i->liveList; printf("\n-------------------------------------\n"); printf("Objects still in the free list:\n"); while (objPtr) { const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; if (objPtr->bytes && strlen(objPtr->bytes) > 20) { printf("%p (%d) %-10s: '%.20s...'\n", (void *)objPtr, objPtr->refCount, type, objPtr->bytes); } else { printf("%p (%d) %-10s: '%s'\n", | > | 10580 10581 10582 10583 10584 10585 10586 10587 10588 10589 10590 10591 10592 10593 10594 | if (i->liveList != NULL) { objPtr = i->liveList; printf("\n-------------------------------------\n"); printf("Objects still in the free list:\n"); while (objPtr) { const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; Jim_String(objPtr); if (objPtr->bytes && strlen(objPtr->bytes) > 20) { printf("%p (%d) %-10s: '%.20s...'\n", (void *)objPtr, objPtr->refCount, type, objPtr->bytes); } else { printf("%p (%d) %-10s: '%s'\n", |
︙ | ︙ | |||
10941 10942 10943 10944 10945 10946 10947 | static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { double doubleValue; jim_wide wideValue; const char *str; | < < < > > | 11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 11014 11015 11016 11017 11018 11019 11020 11021 11022 11023 11024 11025 11026 11027 11028 11029 11030 | static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { double doubleValue; jim_wide wideValue; const char *str; #ifdef HAVE_LONG_LONG #define MIN_INT_IN_DOUBLE -(1LL << 53) #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) if (objPtr->typePtr == &intObjType && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { objPtr->typePtr = &coercedDoubleObjType; return JIM_OK; } #endif str = Jim_String(objPtr); if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &coercedDoubleObjType; objPtr->internalRep.wideValue = wideValue; return JIM_OK; } |
︙ | ︙ | |||
11550 11551 11552 11553 11554 11555 11556 | else { dst++; } ele[dst] = ele[src]; } | > > > | > | 11609 11610 11611 11612 11613 11614 11615 11616 11617 11618 11619 11620 11621 11622 11623 11624 11625 11626 11627 | else { dst++; } ele[dst] = ele[src]; } dst++; if (dst < listObjPtr->internalRep.listValue.len) { ele[dst] = ele[src]; } listObjPtr->internalRep.listValue.len = dst; } static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
︙ | ︙ | |||
12327 12328 12329 12330 12331 12332 12333 | "continue", "signal", "exit", "eval", NULL }; | | | 12390 12391 12392 12393 12394 12395 12396 12397 12398 12399 12400 12401 12402 12403 12404 | "continue", "signal", "exit", "eval", NULL }; #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes) - 1) static const Jim_ObjType returnCodeObjType = { "return-code", NULL, NULL, NULL, JIM_TYPE_NONE, |
︙ | ︙ | |||
12380 12381 12382 12383 12384 12385 12386 | static int JimParseExprOperator(struct JimParserCtx *pc); static int JimParseExprNumber(struct JimParserCtx *pc); static int JimParseExprIrrational(struct JimParserCtx *pc); static int JimParseExprBoolean(struct JimParserCtx *pc); | | | < | < < < < < < < < < < < < < < < < < < | < | 12443 12444 12445 12446 12447 12448 12449 12450 12451 12452 12453 12454 12455 12456 12457 12458 12459 12460 12461 12462 12463 12464 12465 12466 12467 12468 12469 12470 12471 12472 12473 12474 12475 12476 12477 12478 12479 12480 12481 12482 12483 12484 12485 12486 12487 12488 12489 12490 12491 12492 12493 12494 12495 12496 12497 12498 12499 | static int JimParseExprOperator(struct JimParserCtx *pc); static int JimParseExprNumber(struct JimParserCtx *pc); static int JimParseExprIrrational(struct JimParserCtx *pc); static int JimParseExprBoolean(struct JimParserCtx *pc); enum { JIM_EXPROP_MUL = JIM_TT_EXPR_OP, JIM_EXPROP_DIV, JIM_EXPROP_MOD, JIM_EXPROP_SUB, JIM_EXPROP_ADD, JIM_EXPROP_LSHIFT, JIM_EXPROP_RSHIFT, JIM_EXPROP_ROTL, JIM_EXPROP_ROTR, JIM_EXPROP_LT, JIM_EXPROP_GT, JIM_EXPROP_LTE, JIM_EXPROP_GTE, JIM_EXPROP_NUMEQ, JIM_EXPROP_NUMNE, JIM_EXPROP_BITAND, JIM_EXPROP_BITXOR, JIM_EXPROP_BITOR, JIM_EXPROP_LOGICAND, JIM_EXPROP_LOGICOR, JIM_EXPROP_TERNARY, JIM_EXPROP_COLON, JIM_EXPROP_POW, JIM_EXPROP_STREQ, JIM_EXPROP_STRNE, JIM_EXPROP_STRIN, JIM_EXPROP_STRNI, JIM_EXPROP_NOT, JIM_EXPROP_BITNOT, JIM_EXPROP_UNARYMINUS, JIM_EXPROP_UNARYPLUS, JIM_EXPROP_FUNC_INT, JIM_EXPROP_FUNC_WIDE, JIM_EXPROP_FUNC_ABS, JIM_EXPROP_FUNC_DOUBLE, JIM_EXPROP_FUNC_ROUND, JIM_EXPROP_FUNC_RAND, JIM_EXPROP_FUNC_SRAND, |
︙ | ︙ | |||
12472 12473 12474 12475 12476 12477 12478 | JIM_EXPROP_FUNC_LOG10, JIM_EXPROP_FUNC_SQRT, JIM_EXPROP_FUNC_POW, JIM_EXPROP_FUNC_HYPOT, JIM_EXPROP_FUNC_FMOD, }; | | > > | | < | | | | | < < < < | | | < < < | | < > > > > > | | 12515 12516 12517 12518 12519 12520 12521 12522 12523 12524 12525 12526 12527 12528 12529 12530 12531 12532 12533 12534 12535 12536 12537 12538 12539 12540 12541 12542 12543 12544 12545 12546 12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 12557 12558 12559 12560 12561 12562 12563 12564 12565 12566 | JIM_EXPROP_FUNC_LOG10, JIM_EXPROP_FUNC_SQRT, JIM_EXPROP_FUNC_POW, JIM_EXPROP_FUNC_HYPOT, JIM_EXPROP_FUNC_FMOD, }; struct JimExprNode { int type; struct Jim_Obj *objPtr; struct JimExprNode *left; struct JimExprNode *right; struct JimExprNode *ternary; }; typedef struct Jim_ExprOperator { const char *name; int (*funcop) (Jim_Interp *interp, struct JimExprNode *opnode); unsigned char precedence; unsigned char arity; unsigned char attr; unsigned char namelen; } Jim_ExprOperator; static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr); static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node); static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node); static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node) { int intresult = 1; int rc; double dA, dC = 0; jim_wide wA, wC = 0; Jim_Obj *A; if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { return rc; } if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { switch (node->type) { case JIM_EXPROP_FUNC_INT: case JIM_EXPROP_FUNC_WIDE: case JIM_EXPROP_FUNC_ROUND: case JIM_EXPROP_UNARYPLUS: wC = wA; break; case JIM_EXPROP_FUNC_DOUBLE: |
︙ | ︙ | |||
12536 12537 12538 12539 12540 12541 12542 | wC = !wA; break; default: abort(); } } else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { | | | 12577 12578 12579 12580 12581 12582 12583 12584 12585 12586 12587 12588 12589 12590 12591 | wC = !wA; break; default: abort(); } } else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { switch (node->type) { case JIM_EXPROP_FUNC_INT: case JIM_EXPROP_FUNC_WIDE: wC = dA; break; case JIM_EXPROP_FUNC_ROUND: wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); break; |
︙ | ︙ | |||
12571 12572 12573 12574 12575 12576 12577 | default: abort(); } } if (rc == JIM_OK) { if (intresult) { | | | | > | > | > > | > | | | | | | | | > | | > > > | | 12612 12613 12614 12615 12616 12617 12618 12619 12620 12621 12622 12623 12624 12625 12626 12627 12628 12629 12630 12631 12632 12633 12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644 12645 12646 12647 12648 12649 12650 12651 12652 12653 12654 12655 12656 12657 12658 12659 12660 12661 12662 12663 12664 12665 12666 12667 12668 12669 12670 12671 12672 12673 12674 12675 12676 12677 12678 12679 12680 12681 12682 12683 12684 12685 12686 12687 12688 12689 12690 12691 12692 12693 12694 12695 12696 12697 12698 | default: abort(); } } if (rc == JIM_OK) { if (intresult) { Jim_SetResultInt(interp, wC); } else { Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); } } Jim_DecrRefCount(interp, A); return rc; } static double JimRandDouble(Jim_Interp *interp) { unsigned long x; JimRandomBytes(interp, &x, sizeof(x)); return (double)x / (unsigned long)~0; } static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node) { jim_wide wA; Jim_Obj *A; int rc; if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { return rc; } rc = Jim_GetWide(interp, A, &wA); if (rc == JIM_OK) { switch (node->type) { case JIM_EXPROP_BITNOT: Jim_SetResultInt(interp, ~wA); break; case JIM_EXPROP_FUNC_SRAND: JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp))); break; default: abort(); } } Jim_DecrRefCount(interp, A); return rc; } static int JimExprOpNone(Jim_Interp *interp, struct JimExprNode *node) { JimPanic((node->type != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp))); return JIM_OK; } #ifdef JIM_MATH_FUNCTIONS static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprNode *node) { int rc; double dA, dC; Jim_Obj *A; if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { return rc; } rc = Jim_GetDouble(interp, A, &dA); if (rc == JIM_OK) { switch (node->type) { case JIM_EXPROP_FUNC_SIN: dC = sin(dA); break; case JIM_EXPROP_FUNC_COS: dC = cos(dA); break; case JIM_EXPROP_FUNC_TAN: |
︙ | ︙ | |||
12683 12684 12685 12686 12687 12688 12689 | break; case JIM_EXPROP_FUNC_SQRT: dC = sqrt(dA); break; default: abort(); } | | | > > | | > > > > > > > | | | | 12733 12734 12735 12736 12737 12738 12739 12740 12741 12742 12743 12744 12745 12746 12747 12748 12749 12750 12751 12752 12753 12754 12755 12756 12757 12758 12759 12760 12761 12762 12763 12764 12765 12766 12767 12768 12769 12770 12771 12772 12773 12774 12775 12776 12777 12778 | break; case JIM_EXPROP_FUNC_SQRT: dC = sqrt(dA); break; default: abort(); } Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); } Jim_DecrRefCount(interp, A); return rc; } #endif static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprNode *node) { jim_wide wA, wB; int rc; Jim_Obj *A, *B; if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { return rc; } if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { Jim_DecrRefCount(interp, A); return rc; } rc = JIM_ERR; if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { jim_wide wC; rc = JIM_OK; switch (node->type) { case JIM_EXPROP_LSHIFT: wC = wA << wB; break; case JIM_EXPROP_RSHIFT: wC = wA >> wB; break; case JIM_EXPROP_BITAND: |
︙ | ︙ | |||
12754 12755 12756 12757 12758 12759 12760 | unsigned long uA = (unsigned long)wA; unsigned long uB = (unsigned long)wB; const unsigned int S = sizeof(unsigned long) * 8; uB %= S; | | | < | > > > > > | < > > | | 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825 12826 12827 12828 12829 12830 12831 12832 12833 12834 12835 12836 12837 12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 12855 12856 12857 12858 12859 12860 12861 12862 12863 12864 12865 12866 12867 12868 | unsigned long uA = (unsigned long)wA; unsigned long uB = (unsigned long)wB; const unsigned int S = sizeof(unsigned long) * 8; uB %= S; if (node->type == JIM_EXPROP_ROTR) { uB = S - uB; } wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); break; } default: abort(); } Jim_SetResultInt(interp, wC); } Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return rc; } static int JimExprOpBin(Jim_Interp *interp, struct JimExprNode *node) { int rc = JIM_OK; double dA, dB, dC = 0; jim_wide wA, wB, wC = 0; Jim_Obj *A, *B; if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { return rc; } if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { Jim_DecrRefCount(interp, A); return rc; } if ((A->typePtr != &doubleObjType || A->bytes) && (B->typePtr != &doubleObjType || B->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { switch (node->type) { case JIM_EXPROP_POW: case JIM_EXPROP_FUNC_POW: if (wA == 0 && wB < 0) { Jim_SetResultString(interp, "exponentiation of zero by negative power", -1); rc = JIM_ERR; goto done; } |
︙ | ︙ | |||
12847 12848 12849 12850 12851 12852 12853 | goto intresult; case JIM_EXPROP_NUMNE: wC = wA != wB; goto intresult; } } if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { | | | 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923 12924 12925 | goto intresult; case JIM_EXPROP_NUMNE: wC = wA != wB; goto intresult; } } if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { switch (node->type) { #ifndef JIM_MATH_FUNCTIONS case JIM_EXPROP_POW: case JIM_EXPROP_FUNC_POW: case JIM_EXPROP_FUNC_ATAN2: case JIM_EXPROP_FUNC_HYPOT: case JIM_EXPROP_FUNC_FMOD: Jim_SetResultString(interp, "unsupported", -1); |
︙ | ︙ | |||
12919 12920 12921 12922 12923 12924 12925 | } else { int i = Jim_StringCompareObj(interp, A, B, 0); | | | 12983 12984 12985 12986 12987 12988 12989 12990 12991 12992 12993 12994 12995 12996 12997 | } else { int i = Jim_StringCompareObj(interp, A, B, 0); switch (node->type) { case JIM_EXPROP_LT: wC = i < 0; goto intresult; case JIM_EXPROP_GT: wC = i > 0; goto intresult; case JIM_EXPROP_LTE: |
︙ | ︙ | |||
12947 12948 12949 12950 12951 12952 12953 | rc = JIM_ERR; done: Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return rc; intresult: | | | > > | | > > | > > | > | > | > | | | | > > > > | | | | | < | | < < < < < | < < | < < < < | < | < < < < < < < < | | < | < < < | < < < | < | < < < | < < | < | < < | | < < < < < < < < | < < | < < | | | > | | | < < < < | | < < < < < < < < < < < < < | < | < < | < < | < | | < | < < < | | < | < < < < < < < | | < < | < | < < | | | 13011 13012 13013 13014 13015 13016 13017 13018 13019 13020 13021 13022 13023 13024 13025 13026 13027 13028 13029 13030 13031 13032 13033 13034 13035 13036 13037 13038 13039 13040 13041 13042 13043 13044 13045 13046 13047 13048 13049 13050 13051 13052 13053 13054 13055 13056 13057 13058 13059 13060 13061 13062 13063 13064 13065 13066 13067 13068 13069 13070 13071 13072 13073 13074 13075 13076 13077 13078 13079 13080 13081 13082 13083 13084 13085 13086 13087 13088 13089 13090 13091 13092 13093 13094 13095 13096 13097 13098 13099 13100 13101 13102 13103 13104 13105 13106 13107 13108 13109 13110 13111 13112 13113 13114 13115 13116 13117 13118 13119 13120 13121 13122 13123 13124 13125 13126 13127 13128 13129 13130 13131 13132 13133 13134 13135 13136 13137 13138 13139 13140 13141 13142 13143 13144 13145 13146 13147 13148 13149 13150 13151 13152 13153 13154 13155 13156 13157 13158 13159 13160 13161 13162 13163 13164 13165 13166 13167 | rc = JIM_ERR; done: Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return rc; intresult: Jim_SetResultInt(interp, wC); goto done; doubleresult: Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); goto done; } static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) { int listlen; int i; listlen = Jim_ListLength(interp, listObjPtr); for (i = 0; i < listlen; i++) { if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) { return 1; } } return 0; } static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node) { Jim_Obj *A, *B; jim_wide wC; int rc; if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { return rc; } if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { Jim_DecrRefCount(interp, A); return rc; } switch (node->type) { case JIM_EXPROP_STREQ: case JIM_EXPROP_STRNE: wC = Jim_StringEqObj(A, B); if (node->type == JIM_EXPROP_STRNE) { wC = !wC; } break; case JIM_EXPROP_STRIN: wC = JimSearchList(interp, B, A); break; case JIM_EXPROP_STRNI: wC = !JimSearchList(interp, B, A); break; default: abort(); } Jim_SetResultInt(interp, wC); Jim_DecrRefCount(interp, A); Jim_DecrRefCount(interp, B); return rc; } static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) { long l; double d; int b; int ret = -1; Jim_IncrRefCount(obj); if (Jim_GetLong(interp, obj, &l) == JIM_OK) { ret = (l != 0); } else if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { ret = (d != 0); } else if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) { ret = (b != 0); } Jim_DecrRefCount(interp, obj); return ret; } static int JimExprOpAnd(Jim_Interp *interp, struct JimExprNode *node) { int result = JimExprGetTermBoolean(interp, node->left); if (result == 1) { result = JimExprGetTermBoolean(interp, node->right); } if (result == -1) { return JIM_ERR; } Jim_SetResultInt(interp, result); return JIM_OK; } static int JimExprOpOr(Jim_Interp *interp, struct JimExprNode *node) { int result = JimExprGetTermBoolean(interp, node->left); if (result == 0) { result = JimExprGetTermBoolean(interp, node->right); } if (result == -1) { return JIM_ERR; } Jim_SetResultInt(interp, result); return JIM_OK; } static int JimExprOpTernary(Jim_Interp *interp, struct JimExprNode *node) { int result = JimExprGetTermBoolean(interp, node->left); if (result == 1) { return JimExprEvalTermNode(interp, node->right); } else if (result == 0) { return JimExprEvalTermNode(interp, node->ternary); } return JIM_ERR; } enum { OP_FUNC = 0x0001, OP_RIGHT_ASSOC = 0x0002, }; #define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1} #define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, 0) static const struct Jim_ExprOperator Jim_ExprOperators[] = { OPRINIT("*", 110, 2, JimExprOpBin), OPRINIT("/", 110, 2, JimExprOpBin), OPRINIT("%", 110, 2, JimExprOpIntBin), OPRINIT("-", 100, 2, JimExprOpBin), |
︙ | ︙ | |||
13192 13193 13194 13195 13196 13197 13198 | OPRINIT("==", 70, 2, JimExprOpBin), OPRINIT("!=", 70, 2, JimExprOpBin), OPRINIT("&", 50, 2, JimExprOpIntBin), OPRINIT("^", 49, 2, JimExprOpIntBin), OPRINIT("|", 48, 2, JimExprOpIntBin), | < | < < < | < < | < < < | < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 13181 13182 13183 13184 13185 13186 13187 13188 13189 13190 13191 13192 13193 13194 13195 13196 13197 13198 13199 13200 13201 13202 13203 13204 13205 13206 13207 13208 13209 13210 13211 13212 13213 13214 13215 13216 13217 13218 13219 13220 13221 13222 13223 13224 13225 13226 13227 13228 13229 13230 13231 13232 13233 13234 13235 13236 13237 13238 13239 13240 13241 13242 13243 13244 13245 13246 13247 | OPRINIT("==", 70, 2, JimExprOpBin), OPRINIT("!=", 70, 2, JimExprOpBin), OPRINIT("&", 50, 2, JimExprOpIntBin), OPRINIT("^", 49, 2, JimExprOpIntBin), OPRINIT("|", 48, 2, JimExprOpIntBin), OPRINIT("&&", 10, 2, JimExprOpAnd), OPRINIT("||", 9, 2, JimExprOpOr), OPRINIT_ATTR("?", 5, 3, JimExprOpTernary, OP_RIGHT_ASSOC), OPRINIT_ATTR(":", 5, 3, NULL, OP_RIGHT_ASSOC), OPRINIT_ATTR("**", 120, 2, JimExprOpBin, OP_RIGHT_ASSOC), OPRINIT("eq", 60, 2, JimExprOpStrBin), OPRINIT("ne", 60, 2, JimExprOpStrBin), OPRINIT("in", 55, 2, JimExprOpStrBin), OPRINIT("ni", 55, 2, JimExprOpStrBin), OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC), OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), OPRINIT_ATTR(" +", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), OPRINIT_ATTR("int", 200, 1, JimExprOpNumUnary, OP_FUNC), OPRINIT_ATTR("wide", 200, 1, JimExprOpNumUnary, OP_FUNC), OPRINIT_ATTR("abs", 200, 1, JimExprOpNumUnary, OP_FUNC), OPRINIT_ATTR("double", 200, 1, JimExprOpNumUnary, OP_FUNC), OPRINIT_ATTR("round", 200, 1, JimExprOpNumUnary, OP_FUNC), OPRINIT_ATTR("rand", 200, 0, JimExprOpNone, OP_FUNC), OPRINIT_ATTR("srand", 200, 1, JimExprOpIntUnary, OP_FUNC), #ifdef JIM_MATH_FUNCTIONS OPRINIT_ATTR("sin", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("cos", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("tan", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("asin", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("acos", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("atan", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("atan2", 200, 2, JimExprOpBin, OP_FUNC), OPRINIT_ATTR("sinh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("cosh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("tanh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("ceil", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("floor", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("exp", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("log", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("log10", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("sqrt", 200, 1, JimExprOpDoubleUnary, OP_FUNC), OPRINIT_ATTR("pow", 200, 2, JimExprOpBin, OP_FUNC), OPRINIT_ATTR("hypot", 200, 2, JimExprOpBin, OP_FUNC), OPRINIT_ATTR("fmod", 200, 2, JimExprOpBin, OP_FUNC), #endif }; #undef OPRINIT #undef OPRINIT_ATTR #define JIM_EXPR_OPERATORS_NUM \ (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) static int JimParseExpression(struct JimParserCtx *pc) { |
︙ | ︙ | |||
13410 13411 13412 13413 13414 13415 13416 13417 13418 13419 13420 | pc->tend = pc->p - 1; pc->tt = JIM_TT_EXPR_BOOLEAN; return JIM_OK; } } return JIM_ERR; } static int JimParseExprOperator(struct JimParserCtx *pc) { int i; | > > > > > > > > > > | < | | | | | | | | < < < < < < < < < | 13388 13389 13390 13391 13392 13393 13394 13395 13396 13397 13398 13399 13400 13401 13402 13403 13404 13405 13406 13407 13408 13409 13410 13411 13412 13413 13414 13415 13416 13417 13418 13419 13420 13421 13422 13423 13424 13425 13426 13427 13428 13429 13430 13431 13432 13433 13434 13435 13436 13437 13438 13439 13440 13441 13442 13443 13444 13445 13446 13447 13448 13449 13450 13451 13452 13453 13454 13455 | pc->tend = pc->p - 1; pc->tt = JIM_TT_EXPR_BOOLEAN; return JIM_OK; } } return JIM_ERR; } static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) { static Jim_ExprOperator dummy_op; if (opcode < JIM_TT_EXPR_OP) { return &dummy_op; } return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP]; } static int JimParseExprOperator(struct JimParserCtx *pc) { int i; const struct Jim_ExprOperator *bestOp = NULL; int bestLen = 0; for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { const struct Jim_ExprOperator *op = &Jim_ExprOperators[i]; if (op->name[0] != pc->p[0]) { continue; } if (op->namelen > bestLen && strncmp(op->name, pc->p, op->namelen) == 0) { bestOp = op; bestLen = op->namelen; } } if (bestOp == NULL) { return JIM_ERR; } if (bestOp->attr & OP_FUNC) { const char *p = pc->p + bestLen; int len = pc->len - bestLen; while (len && isspace(UCHAR(*p))) { len--; p++; } if (*p != '(') { return JIM_ERR; } } pc->tend = pc->p + bestLen - 1; pc->p += bestLen; pc->len -= bestLen; pc->tt = (bestOp - Jim_ExprOperators) + JIM_TT_EXPR_OP; return JIM_OK; } const char *jim_tt_name(int type) { static const char * const tt_names[JIM_TT_EXPR_OP] = { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", "DBL", "BOO", "$()" }; if (type < JIM_TT_EXPR_OP) { return tt_names[type]; |
︙ | ︙ | |||
13503 13504 13505 13506 13507 13508 13509 | FreeExprInternalRep, DupExprInternalRep, NULL, JIM_TYPE_REFERENCES, }; | | | > | | < | > | | > | > > > > > | | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < | > > > > | > > > > | > > > > > > > > > | > | | < > > | > > | > > > | > > > | > | > > > | | > | > | > > | > > > | > > > > > | > > > > > | > > > > | | > > | > > | > | > > > > | > > > | > > > > | < > > > | | | | | > > | > > > | > > | > > > > > > > > | < < > > < | | | | > > > | > | > > | < | | | > | | < < > | > | < > | | < > | | > > | | > > > | > | > > | < < | > | > > | < < | > > > > > > | | | < < | > < | | < | < | < < | | | | > > > | > | | | > > > | > > | > > | > > | > > > > | > > | > | | > > > > | | | > > > > > | > > > > < | | > > | > > | < | | < | > | | > > > > > | > | > | | | 13481 13482 13483 13484 13485 13486 13487 13488 13489 13490 13491 13492 13493 13494 13495 13496 13497 13498 13499 13500 13501 13502 13503 13504 13505 13506 13507 13508 13509 13510 13511 13512 13513 13514 13515 13516 13517 13518 13519 13520 13521 13522 13523 13524 13525 13526 13527 13528 13529 13530 13531 13532 13533 13534 13535 13536 13537 13538 13539 13540 13541 13542 13543 13544 13545 13546 13547 13548 13549 13550 13551 13552 13553 13554 13555 13556 13557 13558 13559 13560 13561 13562 13563 13564 13565 13566 13567 13568 13569 13570 13571 13572 13573 13574 13575 13576 13577 13578 13579 13580 13581 13582 13583 13584 13585 13586 13587 13588 13589 13590 13591 13592 13593 13594 13595 13596 13597 13598 13599 13600 13601 13602 13603 13604 13605 13606 13607 13608 13609 13610 13611 13612 13613 13614 13615 13616 13617 13618 13619 13620 13621 13622 13623 13624 13625 13626 13627 13628 13629 13630 13631 13632 13633 13634 13635 13636 13637 13638 13639 13640 13641 13642 13643 13644 13645 13646 13647 13648 13649 13650 13651 13652 13653 13654 13655 13656 13657 13658 13659 13660 13661 13662 13663 13664 13665 13666 13667 13668 13669 13670 13671 13672 13673 13674 13675 13676 13677 13678 13679 13680 13681 13682 13683 13684 13685 13686 13687 13688 13689 13690 13691 13692 13693 13694 13695 13696 13697 13698 13699 13700 13701 13702 13703 13704 13705 13706 13707 13708 13709 13710 13711 13712 13713 13714 13715 13716 13717 13718 13719 13720 13721 13722 13723 13724 13725 13726 13727 13728 13729 13730 13731 13732 13733 13734 13735 13736 13737 13738 13739 13740 13741 13742 13743 13744 13745 13746 13747 13748 13749 13750 13751 13752 13753 13754 13755 13756 13757 13758 13759 13760 13761 13762 13763 13764 13765 13766 13767 13768 13769 13770 13771 13772 13773 13774 13775 13776 13777 13778 13779 13780 13781 13782 13783 13784 13785 13786 13787 13788 13789 13790 13791 13792 13793 13794 13795 13796 13797 13798 13799 13800 13801 13802 13803 13804 13805 13806 13807 13808 13809 13810 13811 13812 13813 13814 13815 13816 13817 13818 13819 13820 13821 13822 13823 13824 13825 13826 13827 13828 13829 13830 13831 13832 13833 13834 13835 13836 13837 13838 13839 13840 13841 13842 13843 13844 13845 13846 13847 13848 13849 13850 13851 13852 13853 13854 13855 13856 13857 13858 13859 13860 13861 13862 13863 13864 13865 13866 13867 13868 13869 13870 13871 13872 13873 13874 13875 13876 13877 13878 | FreeExprInternalRep, DupExprInternalRep, NULL, JIM_TYPE_REFERENCES, }; struct ExprTree { struct JimExprNode *expr; struct JimExprNode *nodes; int len; int inUse; }; static void ExprTreeFreeNodes(Jim_Interp *interp, struct JimExprNode *nodes, int num) { int i; for (i = 0; i < num; i++) { if (nodes[i].objPtr) { Jim_DecrRefCount(interp, nodes[i].objPtr); } } Jim_Free(nodes); } static void ExprTreeFree(Jim_Interp *interp, struct ExprTree *expr) { ExprTreeFreeNodes(interp, expr->nodes, expr->len); Jim_Free(expr); } static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) { struct ExprTree *expr = (void *)objPtr->internalRep.ptr; if (expr) { if (--expr->inUse != 0) { return; } ExprTreeFree(interp, expr); } } static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { JIM_NOTUSED(interp); JIM_NOTUSED(srcPtr); dupPtr->typePtr = NULL; } struct ExprBuilder { int parencount; int level; ParseToken *token; ParseToken *first_token; Jim_Stack stack; Jim_Obj *exprObjPtr; Jim_Obj *fileNameObj; struct JimExprNode *nodes; struct JimExprNode *next; }; #ifdef DEBUG_SHOW_EXPR static void JimShowExprNode(struct JimExprNode *node, int level) { int i; for (i = 0; i < level; i++) { printf(" "); } if (TOKEN_IS_EXPR_OP(node->type)) { printf("%s\n", jim_tt_name(node->type)); if (node->left) { JimShowExprNode(node->left, level + 1); } if (node->right) { JimShowExprNode(node->right, level + 1); } if (node->ternary) { JimShowExprNode(node->ternary, level + 1); } } else { printf("[%s] %s\n", jim_tt_name(node->type), Jim_String(node->objPtr)); } } #endif #define EXPR_UNTIL_CLOSE 0x0001 #define EXPR_FUNC_ARGS 0x0002 #define EXPR_TERNARY 0x0004 static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms) { int rc; struct JimExprNode *node; int exp_stacklen = builder->stack.len + exp_numterms; if (builder->level++ > 200) { Jim_SetResultString(interp, "Expression too complex", -1); return JIM_ERR; } while (builder->token->type != JIM_TT_EOL) { ParseToken *t = builder->token++; int prevtt; if (t == builder->first_token) { prevtt = JIM_TT_NONE; } else { prevtt = t[-1].type; } if (t->type == JIM_TT_SUBEXPR_START) { if (builder->stack.len == exp_stacklen) { Jim_SetResultFormatted(interp, "unexpected open parenthesis in expression: \"%#s\"", builder->exprObjPtr); return JIM_ERR; } builder->parencount++; rc = ExprTreeBuildTree(interp, builder, 0, EXPR_UNTIL_CLOSE, 1); if (rc != JIM_OK) { return rc; } } else if (t->type == JIM_TT_SUBEXPR_END) { if (!(flags & EXPR_UNTIL_CLOSE)) { if (builder->stack.len == exp_stacklen && builder->level > 1) { builder->token--; builder->level--; return JIM_OK; } Jim_SetResultFormatted(interp, "unexpected closing parenthesis in expression: \"%#s\"", builder->exprObjPtr); return JIM_ERR; } builder->parencount--; if (builder->stack.len == exp_stacklen) { break; } } else if (t->type == JIM_TT_SUBEXPR_COMMA) { if (!(flags & EXPR_FUNC_ARGS)) { if (builder->stack.len == exp_stacklen) { builder->token--; builder->level--; return JIM_OK; } Jim_SetResultFormatted(interp, "unexpected comma in expression: \"%#s\"", builder->exprObjPtr); return JIM_ERR; } else { if (builder->stack.len > exp_stacklen) { Jim_SetResultFormatted(interp, "too many arguments to math function"); return JIM_ERR; } } } else if (t->type == JIM_EXPROP_COLON) { if (!(flags & EXPR_TERNARY)) { if (builder->level != 1) { builder->token--; builder->level--; return JIM_OK; } Jim_SetResultFormatted(interp, ": without ? in expression: \"%#s\"", builder->exprObjPtr); return JIM_ERR; } if (builder->stack.len == exp_stacklen) { builder->token--; builder->level--; return JIM_OK; } } else if (TOKEN_IS_EXPR_OP(t->type)) { const struct Jim_ExprOperator *op; if (TOKEN_IS_EXPR_OP(prevtt) || TOKEN_IS_EXPR_START(prevtt)) { if (t->type == JIM_EXPROP_SUB) { t->type = JIM_EXPROP_UNARYMINUS; } else if (t->type == JIM_EXPROP_ADD) { t->type = JIM_EXPROP_UNARYPLUS; } } op = JimExprOperatorInfoByOpcode(t->type); if (op->precedence < precedence || (!(op->attr & OP_RIGHT_ASSOC) && op->precedence == precedence)) { builder->token--; break; } if (op->attr & OP_FUNC) { if (builder->token->type != JIM_TT_SUBEXPR_START) { Jim_SetResultString(interp, "missing arguments for math function", -1); return JIM_ERR; } builder->token++; if (op->arity == 0) { if (builder->token->type != JIM_TT_SUBEXPR_END) { Jim_SetResultString(interp, "too many arguments for math function", -1); return JIM_ERR; } builder->token++; goto noargs; } builder->parencount++; rc = ExprTreeBuildTree(interp, builder, 0, EXPR_FUNC_ARGS | EXPR_UNTIL_CLOSE, op->arity); } else if (t->type == JIM_EXPROP_TERNARY) { rc = ExprTreeBuildTree(interp, builder, op->precedence, EXPR_TERNARY, 2); } else { rc = ExprTreeBuildTree(interp, builder, op->precedence, 0, 1); } if (rc != JIM_OK) { return rc; } noargs: node = builder->next++; node->type = t->type; if (op->arity >= 3) { node->ternary = Jim_StackPop(&builder->stack); if (node->ternary == NULL) { goto missingoperand; } } if (op->arity >= 2) { node->right = Jim_StackPop(&builder->stack); if (node->right == NULL) { goto missingoperand; } } if (op->arity >= 1) { node->left = Jim_StackPop(&builder->stack); if (node->left == NULL) { missingoperand: Jim_SetResultFormatted(interp, "missing operand to %s in expression: \"%#s\"", op->name, builder->exprObjPtr); builder->next--; return JIM_ERR; } } Jim_StackPush(&builder->stack, node); } else { Jim_Obj *objPtr = NULL; if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) { Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", builder->exprObjPtr); return JIM_ERR; } if (t->type == JIM_TT_EXPR_INT || t->type == JIM_TT_EXPR_DOUBLE) { char *endptr; if (t->type == JIM_TT_EXPR_INT) { objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr)); } else { objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr)); } if (endptr != t->token + t->len) { Jim_FreeNewObj(interp, objPtr); objPtr = NULL; } } if (!objPtr) { objPtr = Jim_NewStringObj(interp, t->token, t->len); if (t->type == JIM_TT_CMD) { JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line); } } node = builder->next++; node->objPtr = objPtr; Jim_IncrRefCount(node->objPtr); node->type = t->type; Jim_StackPush(&builder->stack, node); } } if (builder->stack.len == exp_stacklen) { builder->level--; return JIM_OK; } if ((flags & EXPR_FUNC_ARGS)) { Jim_SetResultFormatted(interp, "too %s arguments for math function", (builder->stack.len < exp_stacklen) ? "few" : "many"); } else { if (builder->stack.len < exp_stacklen) { if (builder->level == 0) { Jim_SetResultFormatted(interp, "empty expression"); } else { Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": premature end of expression", builder->exprObjPtr); } } else { Jim_SetResultFormatted(interp, "extra terms after expression"); } } return JIM_ERR; } static struct ExprTree *ExprTreeCreateTree(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj) { struct ExprTree *expr; struct ExprBuilder builder; int rc; struct JimExprNode *top = NULL; builder.parencount = 0; builder.level = 0; builder.token = builder.first_token = tokenlist->list; builder.exprObjPtr = exprObjPtr; builder.fileNameObj = fileNameObj; builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1)); memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1)); builder.next = builder.nodes; Jim_InitStack(&builder.stack); rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1); if (rc == JIM_OK) { top = Jim_StackPop(&builder.stack); if (builder.parencount) { Jim_SetResultString(interp, "missing close parenthesis", -1); rc = JIM_ERR; } } Jim_FreeStack(&builder.stack); if (rc != JIM_OK) { ExprTreeFreeNodes(interp, builder.nodes, builder.next - builder.nodes); return NULL; } expr = Jim_Alloc(sizeof(*expr)); expr->inUse = 1; expr->expr = top; expr->nodes = builder.nodes; expr->len = builder.next - builder.nodes; assert(expr->len <= tokenlist->count - 1); return expr; } static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) { int exprTextLen; const char *exprText; struct JimParserCtx parser; struct ExprTree *expr; ParseTokenList tokenlist; int line; Jim_Obj *fileNameObj; int rc = JIM_ERR; if (objPtr->typePtr == &sourceObjType) { |
︙ | ︙ | |||
13995 13996 13997 13998 13999 14000 14001 | if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) { ScriptTokenListFree(&tokenlist); Jim_DecrRefCount(interp, fileNameObj); return JIM_ERR; } | | < < < | < < | < < < < < < < < < < < | | | | | | | | | | > | > > > > > > | | > > > > > > > | > > > > > > > | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | | < | | | < | | | | 13917 13918 13919 13920 13921 13922 13923 13924 13925 13926 13927 13928 13929 13930 13931 13932 13933 13934 13935 13936 13937 13938 13939 13940 13941 13942 13943 13944 13945 13946 13947 13948 13949 13950 13951 13952 13953 13954 13955 13956 13957 13958 13959 13960 13961 13962 13963 13964 13965 13966 13967 13968 13969 13970 13971 13972 13973 13974 13975 13976 13977 13978 13979 13980 13981 13982 13983 13984 13985 13986 13987 13988 13989 13990 13991 13992 13993 13994 13995 13996 13997 13998 13999 14000 14001 14002 14003 14004 14005 14006 14007 14008 14009 14010 14011 14012 14013 14014 14015 14016 14017 14018 14019 14020 14021 14022 14023 14024 14025 14026 14027 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 14043 14044 14045 14046 14047 14048 14049 14050 14051 14052 14053 14054 14055 14056 14057 14058 14059 14060 14061 14062 14063 14064 14065 14066 14067 14068 14069 14070 14071 14072 14073 14074 14075 14076 14077 14078 14079 14080 14081 14082 14083 14084 14085 14086 14087 14088 14089 14090 14091 14092 14093 | if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) { ScriptTokenListFree(&tokenlist); Jim_DecrRefCount(interp, fileNameObj); return JIM_ERR; } expr = ExprTreeCreateTree(interp, &tokenlist, objPtr, fileNameObj); ScriptTokenListFree(&tokenlist); if (!expr) { goto err; } #ifdef DEBUG_SHOW_EXPR printf("==== Expr ====\n"); JimShowExprNode(expr->expr, 0); #endif rc = JIM_OK; err: Jim_DecrRefCount(interp, fileNameObj); Jim_FreeIntRep(interp, objPtr); Jim_SetIntRepPtr(objPtr, expr); objPtr->typePtr = &exprObjType; return rc; } static struct ExprTree *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) { if (objPtr->typePtr != &exprObjType) { if (SetExprFromAny(interp, objPtr) != JIM_OK) { return NULL; } } return (struct ExprTree *) Jim_GetIntRepPtr(objPtr); } #ifdef JIM_OPTIMIZATION static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, struct JimExprNode *node) { if (node->type == JIM_TT_EXPR_INT) return node->objPtr; else if (node->type == JIM_TT_VAR) return Jim_GetVariable(interp, node->objPtr, JIM_NONE); else if (node->type == JIM_TT_DICTSUGAR) return JimExpandDictSugar(interp, node->objPtr); else return NULL; } #endif static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node) { if (TOKEN_IS_EXPR_OP(node->type)) { const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(node->type); return op->funcop(interp, node); } else { Jim_Obj *objPtr; switch (node->type) { case JIM_TT_EXPR_INT: case JIM_TT_EXPR_DOUBLE: case JIM_TT_EXPR_BOOLEAN: case JIM_TT_STR: Jim_SetResult(interp, node->objPtr); return JIM_OK; case JIM_TT_VAR: objPtr = Jim_GetVariable(interp, node->objPtr, JIM_ERRMSG); if (objPtr) { Jim_SetResult(interp, objPtr); return JIM_OK; } return JIM_ERR; case JIM_TT_DICTSUGAR: objPtr = JimExpandDictSugar(interp, node->objPtr); if (objPtr) { Jim_SetResult(interp, objPtr); return JIM_OK; } return JIM_ERR; case JIM_TT_ESC: if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) { Jim_SetResult(interp, objPtr); return JIM_OK; } return JIM_ERR; case JIM_TT_CMD: return Jim_EvalObj(interp, node->objPtr); default: return JIM_ERR; } } } static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr) { int rc = JimExprEvalTermNode(interp, node); if (rc == JIM_OK) { *objPtrPtr = Jim_GetResult(interp); Jim_IncrRefCount(*objPtrPtr); } return rc; } static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node) { if (JimExprEvalTermNode(interp, node) == JIM_OK) { return ExprBool(interp, Jim_GetResult(interp)); } return -1; } int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr) { struct ExprTree *expr; int retcode = JIM_OK; expr = JimGetExpression(interp, exprObjPtr); if (!expr) { return JIM_ERR; } #ifdef JIM_OPTIMIZATION { Jim_Obj *objPtr; switch (expr->len) { case 1: objPtr = JimExprIntValOrVar(interp, expr->expr); if (objPtr) { Jim_SetResult(interp, objPtr); return JIM_OK; } break; case 2: if (expr->expr->type == JIM_EXPROP_NOT) { objPtr = JimExprIntValOrVar(interp, expr->expr->left); if (objPtr && JimIsWide(objPtr)) { Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj); return JIM_OK; } } break; case 3: objPtr = JimExprIntValOrVar(interp, expr->expr->left); if (objPtr && JimIsWide(objPtr)) { Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, expr->expr->right); if (objPtr2 && JimIsWide(objPtr2)) { jim_wide wideValueA = JimWideValue(objPtr); jim_wide wideValueB = JimWideValue(objPtr2); int cmpRes; switch (expr->expr->type) { case JIM_EXPROP_LT: cmpRes = wideValueA < wideValueB; break; case JIM_EXPROP_LTE: cmpRes = wideValueA <= wideValueB; break; case JIM_EXPROP_GT: |
︙ | ︙ | |||
14132 14133 14134 14135 14136 14137 14138 | break; case JIM_EXPROP_NUMNE: cmpRes = wideValueA != wideValueB; break; default: goto noopt; } | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < | < < < < < | < | | | < | < | | | > > > | < | < | | | | 14101 14102 14103 14104 14105 14106 14107 14108 14109 14110 14111 14112 14113 14114 14115 14116 14117 14118 14119 14120 14121 14122 14123 14124 14125 14126 14127 14128 14129 14130 14131 14132 14133 14134 14135 14136 14137 14138 14139 14140 14141 14142 14143 14144 14145 14146 14147 14148 14149 14150 14151 14152 14153 14154 14155 14156 14157 14158 14159 14160 14161 14162 14163 | break; case JIM_EXPROP_NUMNE: cmpRes = wideValueA != wideValueB; break; default: goto noopt; } Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj); return JIM_OK; } } break; } } noopt: #endif expr->inUse++; retcode = JimExprEvalTermNode(interp, expr->expr); expr->inUse--; return retcode; } int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) { int retcode = Jim_EvalExpression(interp, exprObjPtr); if (retcode == JIM_OK) { switch (ExprBool(interp, Jim_GetResult(interp))) { case 0: *boolPtr = 0; break; case 1: *boolPtr = 1; break; case -1: retcode = JIM_ERR; break; } } return retcode; } typedef struct ScanFmtPartDescr { const char *arg; const char *prefix; size_t width; int pos; char type; char modifier; } ScanFmtPartDescr; |
︙ | ︙ | |||
14332 14333 14334 14335 14336 14337 14338 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { ScanFmtStringObj *fmtObj; char *buffer; int maxCount, i, approxSize, lastPos = -1; | | | | 14211 14212 14213 14214 14215 14216 14217 14218 14219 14220 14221 14222 14223 14224 14225 14226 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) { ScanFmtStringObj *fmtObj; char *buffer; int maxCount, i, approxSize, lastPos = -1; const char *fmt = Jim_String(objPtr); int maxFmtLen = Jim_Length(objPtr); const char *fmtEnd = fmt + maxFmtLen; int curr; Jim_FreeIntRep(interp, objPtr); for (i = 0, maxCount = 0; i < maxFmtLen; ++i) if (fmt[i] == '%') |
︙ | ︙ | |||
14418 14419 14420 14421 14422 14423 14424 14425 14426 14427 14428 14429 14430 14431 | continue; if (fmtObj->descr[prev].pos == descr->pos) { fmtObj->error = "variable is assigned by multiple \"%n$\" conversion specifiers"; return JIM_ERR; } } if (sscanf(fmt, "%d%n", &width, &skip) == 1) { descr->width = width; fmt += skip; } if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) fmtObj->maxPos = descr->pos; | > > > > > | 14297 14298 14299 14300 14301 14302 14303 14304 14305 14306 14307 14308 14309 14310 14311 14312 14313 14314 14315 | continue; if (fmtObj->descr[prev].pos == descr->pos) { fmtObj->error = "variable is assigned by multiple \"%n$\" conversion specifiers"; return JIM_ERR; } } if (descr->pos < 0) { fmtObj->error = "\"%n$\" conversion specifier is negative"; return JIM_ERR; } if (sscanf(fmt, "%d%n", &width, &skip) == 1) { descr->width = width; fmt += skip; } if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) fmtObj->maxPos = descr->pos; |
︙ | ︙ | |||
14469 14470 14471 14472 14473 14474 14475 | swapped = 1; } } } } else { | | > > > > > | 14353 14354 14355 14356 14357 14358 14359 14360 14361 14362 14363 14364 14365 14366 14367 14368 14369 14370 14371 14372 14373 | swapped = 1; } } } } else { if (fmt < fmtEnd && strchr("hlL", *fmt)) descr->modifier = tolower((int)*fmt++); if (fmt >= fmtEnd) { fmtObj->error = "missing scan conversion character"; return JIM_ERR; } descr->type = *fmt; if (strchr("efgcsndoxui", *fmt) == 0) { fmtObj->error = "bad scan conversion character"; return JIM_ERR; } else if (*fmt == 'c' && descr->width != 0) { |
︙ | ︙ | |||
14878 14879 14880 14881 14882 14883 14884 14885 14886 14887 14888 14889 14890 14891 | return retcode; } static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) { int retcode; Jim_Cmd *cmdPtr; #if 0 printf("invoke"); int j; for (j = 0; j < objc; j++) { printf(" '%s'", Jim_String(objv[j])); } | > | 14767 14768 14769 14770 14771 14772 14773 14774 14775 14776 14777 14778 14779 14780 14781 | return retcode; } static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) { int retcode; Jim_Cmd *cmdPtr; void *prevPrivData; #if 0 printf("invoke"); int j; for (j = 0; j < objc; j++) { printf(" '%s'", Jim_String(objv[j])); } |
︙ | ︙ | |||
14907 14908 14909 14910 14911 14912 14913 14914 14915 14916 14917 14918 14919 14920 14921 14922 14923 14924 14925 14926 14927 14928 14929 14930 | if (interp->evalDepth == interp->maxEvalDepth) { Jim_SetResultString(interp, "Infinite eval recursion", -1); retcode = JIM_ERR; goto out; } interp->evalDepth++; Jim_SetEmptyResult(interp); if (cmdPtr->isproc) { retcode = JimCallProcedure(interp, cmdPtr, objc, objv); } else { interp->cmdPrivData = cmdPtr->u.native.privData; retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); } interp->evalDepth--; out: JimDecrCmdRefCount(interp, cmdPtr); return retcode; } | > > | 14797 14798 14799 14800 14801 14802 14803 14804 14805 14806 14807 14808 14809 14810 14811 14812 14813 14814 14815 14816 14817 14818 14819 14820 14821 14822 | if (interp->evalDepth == interp->maxEvalDepth) { Jim_SetResultString(interp, "Infinite eval recursion", -1); retcode = JIM_ERR; goto out; } interp->evalDepth++; prevPrivData = interp->cmdPrivData; Jim_SetEmptyResult(interp); if (cmdPtr->isproc) { retcode = JimCallProcedure(interp, cmdPtr, objc, objv); } else { interp->cmdPrivData = cmdPtr->u.native.privData; retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); } interp->cmdPrivData = prevPrivData; interp->evalDepth--; out: JimDecrCmdRefCount(interp, cmdPtr); return retcode; } |
︙ | ︙ | |||
15081 15082 15083 15084 15085 15086 15087 | Jim_IncrRefCount(intv[i]); Jim_String(intv[i]); totlen += intv[i]->length; } if (tokens == 1 && intv[0] && intv == sintv) { | | > | 14973 14974 14975 14976 14977 14978 14979 14980 14981 14982 14983 14984 14985 14986 14987 14988 | Jim_IncrRefCount(intv[i]); Jim_String(intv[i]); totlen += intv[i]->length; } if (tokens == 1 && intv[0] && intv == sintv) { intv[0]->refCount--; return intv[0]; } objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC && token[2].type == JIM_TT_VAR) { |
︙ | ︙ | |||
15536 15537 15538 15539 15540 15541 15542 15543 15544 15545 15546 15547 15548 15549 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); badargset: interp->framePtr = interp->framePtr->parent; JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); if (interp->framePtr->tailcallObj) { do { Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; | > | 15429 15430 15431 15432 15433 15434 15435 15436 15437 15438 15439 15440 15441 15442 15443 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); badargset: retcode = JimInvokeDefer(interp, retcode); interp->framePtr = interp->framePtr->parent; JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); if (interp->framePtr->tailcallObj) { do { Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; |
︙ | ︙ | |||
15824 15825 15826 15827 15828 15829 15830 | Jim_Obj *objPtr; Jim_Obj *listObjPtr; JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0")); listObjPtr = Jim_NewListObj(interp, argv, argc); | | | 15718 15719 15720 15721 15722 15723 15724 15725 15726 15727 15728 15729 15730 15731 15732 | Jim_Obj *objPtr; Jim_Obj *listObjPtr; JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0")); listObjPtr = Jim_NewListObj(interp, argv, argc); if (msg && *msg) { Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1)); } Jim_IncrRefCount(listObjPtr); objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1); Jim_DecrRefCount(interp, listObjPtr); Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr); |
︙ | ︙ | |||
16064 16065 16066 16067 16068 16069 16070 | for (i = 2; i < argc; i++) { if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) { doubleRes = (double)res; goto trydouble; } if (op == JIM_EXPROP_SUB) res -= wideValue; | | > > > > > | 15958 15959 15960 15961 15962 15963 15964 15965 15966 15967 15968 15969 15970 15971 15972 15973 15974 15975 15976 15977 15978 | for (i = 2; i < argc; i++) { if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) { doubleRes = (double)res; goto trydouble; } if (op == JIM_EXPROP_SUB) res -= wideValue; else { if (wideValue == 0) { Jim_SetResultString(interp, "Division by zero", -1); return JIM_ERR; } res /= wideValue; } } Jim_SetResultInt(interp, res); return JIM_OK; trydouble: for (; i < argc; i++) { if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) return JIM_ERR; |
︙ | ︙ | |||
16217 16218 16219 16220 16221 16222 16223 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); #ifdef JIM_OPTIMIZATION if (retval == JIM_OK && boolean) { ScriptObj *incrScript; | | | < < | | > > > > > > > > | | | | | | 16116 16117 16118 16119 16120 16121 16122 16123 16124 16125 16126 16127 16128 16129 16130 16131 16132 16133 16134 16135 16136 16137 16138 16139 16140 16141 16142 16143 16144 16145 16146 16147 16148 16149 16150 16151 16152 16153 16154 16155 16156 16157 16158 16159 16160 16161 16162 16163 16164 16165 16166 16167 16168 16169 16170 16171 16172 16173 16174 16175 16176 16177 16178 16179 16180 16181 16182 16183 16184 16185 16186 16187 16188 16189 16190 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); #ifdef JIM_OPTIMIZATION if (retval == JIM_OK && boolean) { ScriptObj *incrScript; struct ExprTree *expr; jim_wide stop, currentVal; Jim_Obj *objPtr; int cmpOffset; expr = JimGetExpression(interp, argv[2]); incrScript = JimGetScript(interp, argv[3]); if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { goto evalstart; } if (incrScript->token[1].type != JIM_TT_ESC) { goto evalstart; } if (expr->expr->type == JIM_EXPROP_LT) { cmpOffset = 0; } else if (expr->expr->type == JIM_EXPROP_LTE) { cmpOffset = 1; } else { goto evalstart; } if (expr->expr->left->type != JIM_TT_VAR) { goto evalstart; } if (expr->expr->right->type != JIM_TT_VAR && expr->expr->right->type != JIM_TT_EXPR_INT) { goto evalstart; } if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { goto evalstart; } if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->expr->left->objPtr)) { goto evalstart; } if (expr->expr->right->type == JIM_TT_EXPR_INT) { if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) { goto evalstart; } } else { stopVarNamePtr = expr->expr->right->objPtr; Jim_IncrRefCount(stopVarNamePtr); stop = 0; } varNamePtr = expr->expr->left->objPtr; Jim_IncrRefCount(varNamePtr); objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { goto testcond; } |
︙ | ︙ | |||
16478 16479 16480 16481 16482 16483 16484 | JimListIterInit(&iters[i], argv[i + 1]); if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { result = JIM_ERR; } } if (result != JIM_OK) { Jim_SetResultString(interp, "foreach varlist is empty", -1); | | | 16383 16384 16385 16386 16387 16388 16389 16390 16391 16392 16393 16394 16395 16396 16397 | JimListIterInit(&iters[i], argv[i + 1]); if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { result = JIM_ERR; } } if (result != JIM_OK) { Jim_SetResultString(interp, "foreach varlist is empty", -1); goto empty_varlist; } if (doMap) { resultObj = Jim_NewListObj(interp, NULL, 0); } else { resultObj = interp->emptyObj; |
︙ | ︙ | |||
16541 16542 16543 16544 16545 16546 16547 16548 16549 16550 16551 16552 16553 16554 | } } out: result = JIM_OK; Jim_SetResult(interp, resultObj); err: Jim_DecrRefCount(interp, resultObj); if (numargs > 2) { Jim_Free(iters); } return result; } | > | 16446 16447 16448 16449 16450 16451 16452 16453 16454 16455 16456 16457 16458 16459 16460 | } } out: result = JIM_OK; Jim_SetResult(interp, resultObj); err: Jim_DecrRefCount(interp, resultObj); empty_varlist: if (numargs > 2) { Jim_Free(iters); } return result; } |
︙ | ︙ | |||
16667 16668 16669 16670 16671 16672 16673 | if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) { eq = -rc; } return eq; } | < < < > | | | 16573 16574 16575 16576 16577 16578 16579 16580 16581 16582 16583 16584 16585 16586 16587 16588 16589 16590 16591 16592 16593 | if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) { eq = -rc; } return eq; } static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; Jim_Obj *command = NULL, *scriptObj = NULL, *strObj; Jim_Obj **caseList; if (argc < 3) { wrongnumargs: Jim_WrongNumArgs(interp, 1, argv, "?options? string " "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); return JIM_ERR; } |
︙ | ︙ | |||
16716 16717 16718 16719 16720 16721 16722 | } if ((argc - opt) < 2) goto wrongnumargs; } strObj = argv[opt++]; patCount = argc - opt; if (patCount == 1) { | < < | < | | | | < < | < | | | | | | | | 16620 16621 16622 16623 16624 16625 16626 16627 16628 16629 16630 16631 16632 16633 16634 16635 16636 16637 16638 16639 16640 16641 16642 16643 16644 16645 16646 16647 16648 16649 16650 16651 16652 16653 16654 16655 16656 16657 16658 16659 16660 16661 16662 16663 16664 16665 16666 16667 16668 16669 16670 16671 16672 16673 16674 16675 16676 16677 16678 16679 16680 16681 16682 16683 16684 16685 | } if ((argc - opt) < 2) goto wrongnumargs; } strObj = argv[opt++]; patCount = argc - opt; if (patCount == 1) { JimListGetElements(interp, argv[opt], &patCount, &caseList); } else caseList = (Jim_Obj **)&argv[opt]; if (patCount == 0 || patCount % 2 != 0) goto wrongnumargs; for (i = 0; scriptObj == NULL && i < patCount; i += 2) { Jim_Obj *patObj = caseList[i]; if (!Jim_CompareStringImmediate(interp, patObj, "default") || i < (patCount - 2)) { switch (matchOpt) { case SWITCH_EXACT: if (Jim_StringEqObj(strObj, patObj)) scriptObj = caseList[i + 1]; break; case SWITCH_GLOB: if (Jim_StringMatchObj(interp, patObj, strObj, 0)) scriptObj = caseList[i + 1]; break; case SWITCH_RE: command = Jim_NewStringObj(interp, "regexp", -1); case SWITCH_CMD:{ int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); if (argc - opt == 1) { JimListGetElements(interp, argv[opt], &patCount, &caseList); } if (rc < 0) { return -rc; } if (rc) scriptObj = caseList[i + 1]; break; } } } else { scriptObj = caseList[i + 1]; } } for (; i < patCount && Jim_CompareStringImmediate(interp, scriptObj, "-"); i += 2) scriptObj = caseList[i + 1]; if (scriptObj && Jim_CompareStringImmediate(interp, scriptObj, "-")) { Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); return JIM_ERR; } Jim_SetEmptyResult(interp); if (scriptObj) { return Jim_EvalObj(interp, scriptObj); } return JIM_OK; } static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { |
︙ | ︙ | |||
17072 17073 17074 17075 17076 17077 17078 | len = Jim_ListLength(interp, listObj); first = JimRelToAbsIndex(len, first); last = JimRelToAbsIndex(len, last); JimRelToAbsRange(len, &first, &last, &rangeLen); | < | < < < < | < < < < < | 16970 16971 16972 16973 16974 16975 16976 16977 16978 16979 16980 16981 16982 16983 16984 16985 | len = Jim_ListLength(interp, listObj); first = JimRelToAbsIndex(len, first); last = JimRelToAbsIndex(len, last); JimRelToAbsRange(len, &first, &last, &rangeLen); if (first > len) { first = len; } newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first); ListInsertElements(newListObj, -1, argc - 4, argv + 4); |
︙ | ︙ | |||
17127 17128 17129 17130 17131 17132 17133 17134 17135 17136 17137 17138 17139 17140 | "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL }; enum { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; Jim_Obj *resObj; int i; int retCode; struct lsort_info info; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "?options? list"); return JIM_ERR; } | > | 17015 17016 17017 17018 17019 17020 17021 17022 17023 17024 17025 17026 17027 17028 17029 | "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL }; enum { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; Jim_Obj *resObj; int i; int retCode; int shared; struct lsort_info info; if (argc < 2) { Jim_WrongNumArgs(interp, 1, argv, "?options? list"); return JIM_ERR; } |
︙ | ︙ | |||
17192 17193 17194 17195 17196 17197 17198 | return JIM_ERR; } info.indexed = 1; i++; break; } } | > > | | | 17081 17082 17083 17084 17085 17086 17087 17088 17089 17090 17091 17092 17093 17094 17095 17096 17097 17098 17099 17100 17101 17102 | return JIM_ERR; } info.indexed = 1; i++; break; } } resObj = argv[argc - 1]; if ((shared = Jim_IsShared(resObj))) resObj = Jim_DuplicateObj(interp, resObj); retCode = ListSortElements(interp, resObj, &info); if (retCode == JIM_OK) { Jim_SetResult(interp, resObj); } else if (shared) { Jim_FreeNewObj(interp, resObj); } return retCode; } static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
︙ | ︙ | |||
17243 17244 17245 17246 17247 17248 17249 17250 17251 17252 17253 17254 17255 17256 | } return JIM_ERR; } } Jim_SetResult(interp, stringObjPtr); return JIM_OK; } static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { #if !defined(JIM_DEBUG_COMMAND) Jim_SetResultString(interp, "unsupported", -1); return JIM_ERR; | > | 17134 17135 17136 17137 17138 17139 17140 17141 17142 17143 17144 17145 17146 17147 17148 | } return JIM_ERR; } } Jim_SetResult(interp, stringObjPtr); return JIM_OK; } static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { #if !defined(JIM_DEBUG_COMMAND) Jim_SetResultString(interp, "unsupported", -1); return JIM_ERR; |
︙ | ︙ | |||
17325 17326 17327 17328 17329 17330 17331 | return JIM_ERR; } } static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { | < | | < < | 17217 17218 17219 17220 17221 17222 17223 17224 17225 17226 17227 17228 17229 17230 17231 17232 17233 17234 17235 17236 17237 17238 17239 17240 17241 17242 17243 17244 17245 17246 17247 17248 17249 | return JIM_ERR; } } static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int retcode; if (argc == 2) { retcode = Jim_EvalExpression(interp, argv[1]); } else if (argc > 2) { Jim_Obj *objPtr; objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); Jim_IncrRefCount(objPtr); retcode = Jim_EvalExpression(interp, objPtr); Jim_DecrRefCount(interp, objPtr); } else { Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); return JIM_ERR; } if (retcode != JIM_OK) return retcode; return JIM_OK; } static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { |
︙ | ︙ | |||
19650 19651 19652 19653 19654 19655 19656 19657 19658 19659 19660 19661 19662 19663 19664 19665 | Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1)); } Jim_Free(tablePtrSorted); return JIM_OK; } return JIM_ERR; } int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr, int *indexPtr, const char *name, int flags) { const char *bad = "bad "; const char *const *entryPtr = NULL; int i; int match = -1; int arglen; | > > > > > > > > > > > > > > > > > | | | > > > > > > > > | 19539 19540 19541 19542 19543 19544 19545 19546 19547 19548 19549 19550 19551 19552 19553 19554 19555 19556 19557 19558 19559 19560 19561 19562 19563 19564 19565 19566 19567 19568 19569 19570 19571 19572 19573 19574 19575 19576 19577 19578 19579 19580 19581 19582 19583 19584 19585 19586 19587 19588 19589 19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 19601 19602 19603 19604 19605 19606 19607 19608 19609 19610 19611 19612 | Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1)); } Jim_Free(tablePtrSorted); return JIM_OK; } return JIM_ERR; } static const Jim_ObjType getEnumObjType = { "get-enum", NULL, NULL, NULL, JIM_TYPE_REFERENCES }; int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr, int *indexPtr, const char *name, int flags) { const char *bad = "bad "; const char *const *entryPtr = NULL; int i; int match = -1; int arglen; const char *arg; if (objPtr->typePtr == &getEnumObjType) { if (objPtr->internalRep.ptrIntValue.ptr == tablePtr && objPtr->internalRep.ptrIntValue.int1 == flags) { *indexPtr = objPtr->internalRep.ptrIntValue.int2; return JIM_OK; } } arg = Jim_GetString(objPtr, &arglen); *indexPtr = -1; for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { match = i; goto found; } if (flags & JIM_ENUM_ABBREV) { if (strncmp(arg, *entryPtr, arglen) == 0) { if (*arg == '-' && arglen == 1) { break; } if (match >= 0) { bad = "ambiguous "; goto ambiguous; } match = i; } } } if (match >= 0) { found: Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &getEnumObjType; objPtr->internalRep.ptrIntValue.ptr = (void *)tablePtr; objPtr->internalRep.ptrIntValue.int1 = flags; objPtr->internalRep.ptrIntValue.int2 = match; *indexPtr = match; return JIM_OK; } ambiguous: if (flags & JIM_ERRMSG) { JimSetFailedEnumResult(interp, arg, bad, "", tablePtr, name); |
︙ | ︙ | |||
19816 19817 19818 19819 19820 19821 19822 | } } } static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, Jim_Obj *cmd, Jim_Obj *subcmd) { | < < | < < | > > > > > > > > < < < < | < | > > > > > > > > | 19730 19731 19732 19733 19734 19735 19736 19737 19738 19739 19740 19741 19742 19743 19744 19745 19746 19747 19748 19749 19750 19751 19752 19753 19754 19755 19756 19757 19758 19759 19760 19761 19762 19763 19764 19765 19766 19767 19768 19769 19770 19771 19772 19773 19774 19775 19776 19777 19778 19779 19780 19781 19782 19783 19784 19785 19786 19787 19788 19789 19790 19791 19792 19793 19794 19795 19796 19797 19798 19799 19800 19801 19802 19803 19804 19805 19806 | } } } static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, Jim_Obj *cmd, Jim_Obj *subcmd) { Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd); add_commands(interp, command_table, ", "); } static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, Jim_Obj *const *argv) { Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]); add_commands(interp, command_table, ", "); } static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) { if (cmd) { Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), " ", NULL); } Jim_AppendStrings(interp, Jim_GetResult(interp), ct->cmd, NULL); if (ct->args && *ct->args) { Jim_AppendStrings(interp, Jim_GetResult(interp), " ", ct->args, NULL); } } static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd) { Jim_SetResultString(interp, "wrong # args: should be \"", -1); add_cmd_usage(interp, command_table, subcmd); Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); } static const Jim_ObjType subcmdLookupObjType = { "subcmd-lookup", NULL, NULL, NULL, JIM_TYPE_REFERENCES }; const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, Jim_Obj *const *argv) { const jim_subcmd_type *ct; const jim_subcmd_type *partial = 0; int cmdlen; Jim_Obj *cmd; const char *cmdstr; int help = 0; if (argc < 2) { Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n" "Use \"%#s -help ?command?\" for help", argv[0], argv[0]); return 0; } cmd = argv[1]; if (cmd->typePtr == &subcmdLookupObjType) { if (cmd->internalRep.ptrIntValue.ptr == command_table) { ct = command_table + cmd->internalRep.ptrIntValue.int1; goto found; } } if (Jim_CompareStringImmediate(interp, cmd, "-help")) { if (argc == 2) { show_cmd_usage(interp, command_table, argc, argv); return &dummy_subcmd; } |
︙ | ︙ | |||
19939 19940 19941 19942 19943 19944 19945 19946 19947 19948 19949 19950 19951 19952 | if (help) { Jim_SetResultString(interp, "Usage: ", -1); add_cmd_usage(interp, ct, argv[0]); return &dummy_subcmd; } if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { Jim_SetResultString(interp, "wrong # args: should be \"", -1); add_cmd_usage(interp, ct, argv[0]); Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); | > > > > > > > | 19860 19861 19862 19863 19864 19865 19866 19867 19868 19869 19870 19871 19872 19873 19874 19875 19876 19877 19878 19879 19880 | if (help) { Jim_SetResultString(interp, "Usage: ", -1); add_cmd_usage(interp, ct, argv[0]); return &dummy_subcmd; } Jim_FreeIntRep(interp, cmd); cmd->typePtr = &subcmdLookupObjType; cmd->internalRep.ptrIntValue.ptr = (void *)command_table; cmd->internalRep.ptrIntValue.int1 = ct - command_table; found: if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { Jim_SetResultString(interp, "wrong # args: should be \"", -1); add_cmd_usage(interp, ct, argv[0]); Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
︙ | ︙ | |||
20131 20132 20133 20134 20135 20136 20137 | default: sawFlag = 0; continue; } *p++ = ch; format += step; step = utf8_tounicode(format, &ch); | > | | 20059 20060 20061 20062 20063 20064 20065 20066 20067 20068 20069 20070 20071 20072 20073 20074 | default: sawFlag = 0; continue; } *p++ = ch; format += step; step = utf8_tounicode(format, &ch); } while (sawFlag && (p - spec <= 5)); width = 0; if (isdigit(ch)) { width = strtoul(format, &end, 10); format = end; step = utf8_tounicode(format, &ch); |
︙ | ︙ | |||
20328 20329 20330 20331 20332 20333 20334 20335 20336 20337 20338 20339 20340 20341 | *p++ = 'l'; } #endif } *p++ = (char) ch; *p = '\0'; if (width > length) { length = width; } if (gotPrecision) { length += precision; | > > > > > > > | 20257 20258 20259 20260 20261 20262 20263 20264 20265 20266 20267 20268 20269 20270 20271 20272 20273 20274 20275 20276 20277 | *p++ = 'l'; } #endif } *p++ = (char) ch; *p = '\0'; if (width > 10000 || length > 10000 || precision > 10000) { Jim_SetResultString(interp, "format too long", -1); goto error; } if (width > length) { length = width; } if (gotPrecision) { length += precision; |
︙ | ︙ | |||
20702 20703 20704 20705 20706 20707 20708 20709 20710 20711 20712 20713 20714 20715 | if (end == preg->regparse + 1) { preg->err = REG_ERR_BAD_COUNT; return 0; } if (*end == '}') { max = min; } else { preg->regparse = end; max = strtoul(preg->regparse + 1, &end, 10); if (*end != '}') { preg->err = REG_ERR_UNMATCHED_BRACES; return 0; } | > > > > | 20638 20639 20640 20641 20642 20643 20644 20645 20646 20647 20648 20649 20650 20651 20652 20653 20654 20655 | if (end == preg->regparse + 1) { preg->err = REG_ERR_BAD_COUNT; return 0; } if (*end == '}') { max = min; } else if (*end == '\0') { preg->err = REG_ERR_UNMATCHED_BRACES; return 0; } else { preg->regparse = end; max = strtoul(preg->regparse + 1, &end, 10); if (*end != '}') { preg->err = REG_ERR_UNMATCHED_BRACES; return 0; } |
︙ | ︙ | |||
20906 20907 20908 20909 20910 20911 20912 20913 20914 20915 20916 20917 20918 20919 20920 20921 | } while (*pattern && *pattern != ']') { int start; int end; pattern += reg_utf8_tounicode_case(pattern, &start, nocase); if (start == '\\') { pattern += reg_decode_escape(pattern, &start); if (start == 0) { preg->err = REG_ERR_NULL_CHAR; return 0; } } if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') { | > > > > > > > > > > > > > > > > > > > > > > > | 20846 20847 20848 20849 20850 20851 20852 20853 20854 20855 20856 20857 20858 20859 20860 20861 20862 20863 20864 20865 20866 20867 20868 20869 20870 20871 20872 20873 20874 20875 20876 20877 20878 20879 20880 20881 20882 20883 20884 | } while (*pattern && *pattern != ']') { int start; int end; enum { CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER, CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT, CC_NUM }; int cc; pattern += reg_utf8_tounicode_case(pattern, &start, nocase); if (start == '\\') { switch (*pattern) { case 's': pattern++; cc = CC_SPACE; goto cc_switch; case 'd': pattern++; cc = CC_DIGIT; goto cc_switch; case 'w': pattern++; reg_addrange(preg, '_', '_'); cc = CC_ALNUM; goto cc_switch; } pattern += reg_decode_escape(pattern, &start); if (start == 0) { preg->err = REG_ERR_NULL_CHAR; return 0; } } if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') { |
︙ | ︙ | |||
20934 20935 20936 20937 20938 20939 20940 | continue; } if (start == '[' && pattern[0] == ':') { static const char *character_class[] = { ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:", ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:", }; | < < < < < < | | | | > | | 20897 20898 20899 20900 20901 20902 20903 20904 20905 20906 20907 20908 20909 20910 20911 20912 20913 20914 20915 20916 20917 20918 20919 20920 20921 20922 | continue; } if (start == '[' && pattern[0] == ':') { static const char *character_class[] = { ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:", ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:", }; for (cc = 0; cc < CC_NUM; cc++) { n = strlen(character_class[cc]); if (strncmp(pattern, character_class[cc], n) == 0) { pattern += n + 1; break; } } if (cc != CC_NUM) { cc_switch: switch (cc) { case CC_ALNUM: reg_addrange(preg, '0', '9'); case CC_ALPHA: if ((preg->cflags & REG_ICASE) == 0) { reg_addrange(preg, 'a', 'z'); } |
︙ | ︙ | |||
21805 21806 21807 21808 21809 21810 21811 21812 21813 21814 21815 21816 21817 21818 | void regfree(regex_t *preg) { free(preg->program); } #endif #if defined(_WIN32) || defined(WIN32) #ifndef STRICT #define STRICT #endif #define WIN32_LEAN_AND_MEAN #include <windows.h> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 21763 21764 21765 21766 21767 21768 21769 21770 21771 21772 21773 21774 21775 21776 21777 21778 21779 21780 21781 21782 21783 21784 21785 21786 21787 21788 21789 21790 21791 21792 21793 21794 21795 21796 21797 21798 21799 21800 21801 21802 21803 21804 21805 21806 21807 21808 21809 21810 21811 21812 21813 21814 21815 21816 21817 21818 21819 21820 21821 21822 21823 21824 21825 21826 21827 21828 21829 21830 21831 21832 21833 21834 21835 21836 21837 21838 21839 21840 21841 21842 21843 21844 21845 21846 21847 21848 21849 21850 21851 21852 21853 21854 21855 21856 21857 21858 21859 21860 21861 21862 21863 21864 21865 21866 21867 21868 21869 21870 21871 21872 21873 21874 21875 21876 21877 21878 21879 21880 21881 21882 21883 21884 21885 21886 21887 21888 21889 21890 21891 21892 21893 21894 21895 21896 21897 21898 21899 21900 21901 21902 21903 21904 21905 21906 21907 21908 21909 21910 21911 21912 21913 21914 21915 21916 21917 21918 21919 21920 21921 21922 21923 21924 21925 21926 21927 21928 21929 21930 21931 21932 21933 21934 21935 21936 21937 21938 21939 21940 21941 21942 21943 21944 21945 21946 21947 21948 21949 21950 21951 21952 21953 21954 21955 21956 21957 21958 21959 21960 21961 21962 21963 21964 21965 21966 21967 21968 21969 21970 21971 21972 21973 21974 21975 21976 21977 21978 21979 21980 21981 21982 21983 21984 21985 21986 21987 21988 21989 | void regfree(regex_t *preg) { free(preg->program); } #endif #include <string.h> void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) { Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno())); } #if defined(__MINGW32__) #include <sys/stat.h> int Jim_Errno(void) { switch (GetLastError()) { case ERROR_FILE_NOT_FOUND: return ENOENT; case ERROR_PATH_NOT_FOUND: return ENOENT; case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; case ERROR_ACCESS_DENIED: return EACCES; case ERROR_INVALID_HANDLE: return EBADF; case ERROR_BAD_ENVIRONMENT: return E2BIG; case ERROR_BAD_FORMAT: return ENOEXEC; case ERROR_INVALID_ACCESS: return EACCES; case ERROR_INVALID_DRIVE: return ENOENT; case ERROR_CURRENT_DIRECTORY: return EACCES; case ERROR_NOT_SAME_DEVICE: return EXDEV; case ERROR_NO_MORE_FILES: return ENOENT; case ERROR_WRITE_PROTECT: return EROFS; case ERROR_BAD_UNIT: return ENXIO; case ERROR_NOT_READY: return EBUSY; case ERROR_BAD_COMMAND: return EIO; case ERROR_CRC: return EIO; case ERROR_BAD_LENGTH: return EIO; case ERROR_SEEK: return EIO; case ERROR_WRITE_FAULT: return EIO; case ERROR_READ_FAULT: return EIO; case ERROR_GEN_FAILURE: return EIO; case ERROR_SHARING_VIOLATION: return EACCES; case ERROR_LOCK_VIOLATION: return EACCES; case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; case ERROR_HANDLE_DISK_FULL: return ENOSPC; case ERROR_NOT_SUPPORTED: return ENODEV; case ERROR_REM_NOT_LIST: return EBUSY; case ERROR_DUP_NAME: return EEXIST; case ERROR_BAD_NETPATH: return ENOENT; case ERROR_NETWORK_BUSY: return EBUSY; case ERROR_DEV_NOT_EXIST: return ENODEV; case ERROR_TOO_MANY_CMDS: return EAGAIN; case ERROR_ADAP_HDW_ERR: return EIO; case ERROR_BAD_NET_RESP: return EIO; case ERROR_UNEXP_NET_ERR: return EIO; case ERROR_NETNAME_DELETED: return ENOENT; case ERROR_NETWORK_ACCESS_DENIED: return EACCES; case ERROR_BAD_DEV_TYPE: return ENODEV; case ERROR_BAD_NET_NAME: return ENOENT; case ERROR_TOO_MANY_NAMES: return ENFILE; case ERROR_TOO_MANY_SESS: return EIO; case ERROR_SHARING_PAUSED: return EAGAIN; case ERROR_REDIR_PAUSED: return EAGAIN; case ERROR_FILE_EXISTS: return EEXIST; case ERROR_CANNOT_MAKE: return ENOSPC; case ERROR_OUT_OF_STRUCTURES: return ENFILE; case ERROR_ALREADY_ASSIGNED: return EEXIST; case ERROR_INVALID_PASSWORD: return EPERM; case ERROR_NET_WRITE_FAULT: return EIO; case ERROR_NO_PROC_SLOTS: return EAGAIN; case ERROR_DISK_CHANGE: return EXDEV; case ERROR_BROKEN_PIPE: return EPIPE; case ERROR_OPEN_FAILED: return ENOENT; case ERROR_DISK_FULL: return ENOSPC; case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; case ERROR_INVALID_TARGET_HANDLE: return EBADF; case ERROR_INVALID_NAME: return ENOENT; case ERROR_PROC_NOT_FOUND: return ESRCH; case ERROR_WAIT_NO_CHILDREN: return ECHILD; case ERROR_CHILD_NOT_COMPLETE: return ECHILD; case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; case ERROR_SEEK_ON_DEVICE: return ESPIPE; case ERROR_BUSY_DRIVE: return EAGAIN; case ERROR_DIR_NOT_EMPTY: return EEXIST; case ERROR_NOT_LOCKED: return EACCES; case ERROR_BAD_PATHNAME: return ENOENT; case ERROR_LOCK_FAILED: return EACCES; case ERROR_ALREADY_EXISTS: return EEXIST; case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; case ERROR_BAD_PIPE: return EPIPE; case ERROR_PIPE_BUSY: return EAGAIN; case ERROR_PIPE_NOT_CONNECTED: return EPIPE; case ERROR_DIRECTORY: return ENOTDIR; } return EINVAL; } pidtype waitpid(pidtype pid, int *status, int nohang) { DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { return JIM_BAD_PID; } GetExitCodeProcess(pid, &ret); *status = ret; CloseHandle(pid); return pid; } int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file) { char name[MAX_PATH]; HANDLE handle; if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, filename_template ? filename_template : "JIM", 0, name)) { return -1; } handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | (unlink_file ? FILE_FLAG_DELETE_ON_CLOSE : 0), NULL); if (handle == INVALID_HANDLE_VALUE) { goto error; } Jim_SetResultString(interp, name, -1); return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT); error: Jim_SetResultErrno(interp, name); DeleteFile(name); return -1; } int Jim_OpenForWrite(const char *filename, int append) { if (strcmp(filename, "/dev/null") == 0) { filename = "nul:"; } int fd = _open(filename, _O_WRONLY | _O_CREAT | _O_TEXT | (append ? _O_APPEND : _O_TRUNC), _S_IREAD | _S_IWRITE); if (fd >= 0 && append) { _lseek(fd, 0L, SEEK_END); } return fd; } int Jim_OpenForRead(const char *filename) { if (strcmp(filename, "/dev/null") == 0) { filename = "nul:"; } return _open(filename, _O_RDONLY | _O_TEXT, 0); } #elif defined(HAVE_UNISTD_H) int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file) { int fd; mode_t mask; Jim_Obj *filenameObj; if (filename_template == NULL) { const char *tmpdir = getenv("TMPDIR"); if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { tmpdir = "/tmp/"; } filenameObj = Jim_NewStringObj(interp, tmpdir, -1); if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { Jim_AppendString(interp, filenameObj, "/", 1); } Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); } else { filenameObj = Jim_NewStringObj(interp, filename_template, -1); } mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); #ifdef HAVE_MKSTEMP fd = mkstemp(filenameObj->bytes); #else if (mktemp(filenameObj->bytes) == NULL) { fd = -1; } else { fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC); } #endif umask(mask); if (fd < 0) { Jim_SetResultErrno(interp, Jim_String(filenameObj)); Jim_FreeNewObj(interp, filenameObj); return -1; } if (unlink_file) { remove(Jim_String(filenameObj)); } Jim_SetResult(interp, filenameObj); return fd; } int Jim_OpenForWrite(const char *filename, int append) { return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); } int Jim_OpenForRead(const char *filename) { return open(filename, O_RDONLY, 0); } #endif #if defined(_WIN32) || defined(WIN32) #ifndef STRICT #define STRICT #endif #define WIN32_LEAN_AND_MEAN #include <windows.h> |
︙ | ︙ | |||
21923 21924 21925 21926 21927 21928 21929 21930 21931 21932 21933 21934 21935 21936 21937 21938 21939 21940 21941 21942 21943 21944 21945 21946 | else { errno = EBADF; } return result; } #endif #endif #ifndef JIM_BOOTSTRAP_LIB_ONLY #include <errno.h> #include <string.h> #ifdef USE_LINENOISE #ifdef HAVE_UNISTD_H #include <unistd.h> #endif #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif #include "linenoise.h" #else #define MAX_LINE_LEN 512 #endif | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > | > > > | 22094 22095 22096 22097 22098 22099 22100 22101 22102 22103 22104 22105 22106 22107 22108 22109 22110 22111 22112 22113 22114 22115 22116 22117 22118 22119 22120 22121 22122 22123 22124 22125 22126 22127 22128 22129 22130 22131 22132 22133 22134 22135 22136 22137 22138 22139 22140 22141 22142 22143 22144 22145 22146 22147 22148 22149 22150 22151 22152 22153 22154 22155 22156 22157 22158 22159 22160 22161 22162 22163 22164 22165 22166 22167 22168 22169 22170 22171 22172 22173 22174 | else { errno = EBADF; } return result; } #endif #endif #include <stdio.h> #include <signal.h> #ifndef SIGPIPE #define SIGPIPE 13 #endif #ifndef SIGINT #define SIGINT 2 #endif const char *Jim_SignalId(int sig) { static char buf[10]; switch (sig) { case SIGINT: return "SIGINT"; case SIGPIPE: return "SIGPIPE"; } snprintf(buf, sizeof(buf), "%d", sig); return buf; } #ifndef JIM_BOOTSTRAP_LIB_ONLY #include <errno.h> #include <string.h> #ifdef USE_LINENOISE #ifdef HAVE_UNISTD_H #include <unistd.h> #endif #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif #include "linenoise.h" #else #define MAX_LINE_LEN 512 #endif #ifdef USE_LINENOISE static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata); static const char completion_callback_assoc_key[] = "interactive-completion"; #endif char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt) { #ifdef USE_LINENOISE struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key); char *result; Jim_Obj *objPtr; long mlmode = 0; if (compinfo) { linenoiseSetCompletionCallback(JimCompletionCallback, compinfo); } objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE); if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) { linenoiseSetMultiLine(mlmode); } result = linenoise(prompt); linenoiseSetCompletionCallback(NULL, NULL); return result; #else int len; char *line = malloc(MAX_LINE_LEN); fputs(prompt, stdout); fflush(stdout); |
︙ | ︙ | |||
21987 21988 21989 21990 21991 21992 21993 | #ifdef HAVE_UMASK mode_t mask; mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); #endif linenoiseHistorySave(filename); #ifdef HAVE_UMASK | | | 22204 22205 22206 22207 22208 22209 22210 22211 22212 22213 22214 22215 22216 22217 22218 | #ifdef HAVE_UMASK mode_t mask; mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); #endif linenoiseHistorySave(filename); #ifdef HAVE_UMASK umask(mask); #endif #endif } void Jim_HistoryShow(void) { #ifdef USE_LINENOISE |
︙ | ︙ | |||
22011 22012 22013 22014 22015 22016 22017 | #ifdef USE_LINENOISE struct JimCompletionInfo { Jim_Interp *interp; Jim_Obj *command; }; | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | < < < < | 22228 22229 22230 22231 22232 22233 22234 22235 22236 22237 22238 22239 22240 22241 22242 22243 22244 22245 22246 22247 22248 22249 22250 22251 22252 22253 22254 22255 22256 22257 22258 22259 22260 22261 22262 22263 22264 22265 22266 22267 22268 22269 22270 22271 22272 22273 22274 22275 22276 22277 22278 22279 22280 22281 22282 22283 22284 22285 22286 22287 22288 22289 22290 22291 22292 22293 22294 22295 22296 22297 22298 22299 22300 22301 22302 22303 22304 22305 22306 22307 22308 22309 | #ifdef USE_LINENOISE struct JimCompletionInfo { Jim_Interp *interp; Jim_Obj *command; }; static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata) { struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata; Jim_Obj *objv[2]; int ret; objv[0] = info->command; objv[1] = Jim_NewStringObj(info->interp, prefix, -1); ret = Jim_EvalObjVector(info->interp, 2, objv); if (ret == JIM_OK) { int i; Jim_Obj *listObj = Jim_GetResult(info->interp); int len = Jim_ListLength(info->interp, listObj); for (i = 0; i < len; i++) { linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i))); } } } static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data) { struct JimCompletionInfo *compinfo = data; Jim_DecrRefCount(interp, compinfo->command); Jim_Free(compinfo); } #endif void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj) { #ifdef USE_LINENOISE if (commandObj) { Jim_IncrRefCount(commandObj); } Jim_DeleteAssocData(interp, completion_callback_assoc_key); if (commandObj) { struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo)); compinfo->interp = interp; compinfo->command = commandObj; Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo); } #endif } int Jim_InteractivePrompt(Jim_Interp *interp) { int retcode = JIM_OK; char *history_file = NULL; #ifdef USE_LINENOISE const char *home; home = getenv("HOME"); if (home && isatty(STDIN_FILENO)) { int history_len = strlen(home) + sizeof("/.jim_history"); history_file = Jim_Alloc(history_len); snprintf(history_file, history_len, "%s/.jim_history", home); Jim_HistoryLoad(history_file); } Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1)); #endif printf("Welcome to Jim version %d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100); Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); while (1) { |
︙ | ︙ | |||
22088 22089 22090 22091 22092 22093 22094 | scriptObjPtr = Jim_NewStringObj(interp, "", 0); Jim_IncrRefCount(scriptObjPtr); while (1) { char state; char *line; | | | 22328 22329 22330 22331 22332 22333 22334 22335 22336 22337 22338 22339 22340 22341 22342 | scriptObjPtr = Jim_NewStringObj(interp, "", 0); Jim_IncrRefCount(scriptObjPtr); while (1) { char state; char *line; line = Jim_HistoryGetline(interp, prompt); if (line == NULL) { if (errno == EINTR) { continue; } Jim_DecrRefCount(interp, scriptObjPtr); retcode = JIM_OK; goto out; |
︙ | ︙ | |||
22138 22139 22140 22141 22142 22143 22144 | if (reslen) { printf("%s\n", result); } } out: Jim_Free(history_file); | < < < < < | 22378 22379 22380 22381 22382 22383 22384 22385 22386 22387 22388 22389 22390 22391 | if (reslen) { printf("%s\n", result); } } out: Jim_Free(history_file); return retcode; } #include <stdio.h> #include <stdlib.h> #include <string.h> |
︙ | ︙ |
Changes to autosetup/system.tcl.
︙ | ︙ | |||
141 142 143 144 145 146 147 | # is the fully-expanded template. # # The mapping parameter is how we expand @varname@ within the template. # We do that inline within this step only for @include directives which # can have variables in the filename arg. A separate substitution pass # happens when this recursive function returns, expanding the rest of # the variables. | | | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | # is the fully-expanded template. # # The mapping parameter is how we expand @varname@ within the template. # We do that inline within this step only for @include directives which # can have variables in the filename arg. A separate substitution pass # happens when this recursive function returns, expanding the rest of # the variables. # proc include-file {infile mapping} { # A stack of true/false conditions, one for each nested conditional # starting with "true" set condstack {1} set result {} set linenum 0 foreach line [split [readfile $infile] \n] { |
︙ | ︙ | |||
179 180 181 182 183 184 185 | autosetup-error "$infile:$linenum: Invalid expression: $line" } dputs "@$condtype: $condexpr => $condval" } if {$condtype ne "if"} { if {[llength $condstack] <= 1} { autosetup-error "$infile:$linenum: Error: @$condtype missing @if" | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | autosetup-error "$infile:$linenum: Invalid expression: $line" } dputs "@$condtype: $condexpr => $condval" } if {$condtype ne "if"} { if {[llength $condstack] <= 1} { autosetup-error "$infile:$linenum: Error: @$condtype missing @if" } elseif {[string length $condargs] && [string index $condargs 0] ne "#"} { autosetup-error "$infile:$linenum: Error: Extra arguments after @$condtype" } } switch -exact $condtype { if { # push condval lappend condstack $condval |
︙ | ︙ |
hardware/pdp8i/customlibraries/pdp8_library.dcm became a regular file.
hardware/pdp8i/customlibraries/pdp8_library.lib became a regular file.
︙ | ︙ |
hardware/pdp8i/customlibraries/pdp8footprintlib2.mod became a regular file.
︙ | ︙ |
src/cc8/os8/n8.c became a regular file.
︙ | ︙ |
src/os8/v3f/BATCH.PA became a regular file.
︙ | ︙ |
src/os8/v3f/BLOAD.PA became a regular file.
︙ | ︙ |
src/os8/v3f/BOOT.PA became a regular file.
︙ | ︙ |
src/os8/v3f/BPAT.PA became a regular file.
︙ | ︙ |
src/os8/v3f/BUILD.PA became a regular file.
︙ | ︙ |
src/os8/v3f/CCL.BI became a regular file.
︙ | ︙ |
src/os8/v3f/CCL.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLAT.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLCD.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLCDX.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLCOR.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLDAT.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLDRV.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLMSG.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLPS.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLREM.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLRUN.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLSB2.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLSEM.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLSIZ.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLSUB.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLTAB.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CCLTBL.MA became a regular file.
︙ | ︙ |
src/os8/v3f/CD.PA became a regular file.
︙ | ︙ |
src/os8/v3f/FPAT.PA became a regular file.
︙ | ︙ |
src/os8/v3f/FUTIL.PA became a regular file.
︙ | ︙ |
src/os8/v3f/KL8E.PA became a regular file.
︙ | ︙ |
src/os8/v3f/OS78.BI became a regular file.
︙ | ︙ |
src/os8/v3f/OS8.PA became a regular file.
︙ | ︙ |
src/os8/v3f/PAL8.PA became a regular file.
︙ | ︙ |
src/os8/v3f/PIP.PA became a regular file.
︙ | ︙ |
src/os8/v3f/README.V3F became a regular file.
︙ | ︙ |
src/os8/v3f/RESORC.BI became a regular file.
︙ | ︙ |
src/os8/v3f/RESORC.MA became a regular file.
︙ | ︙ |
src/os8/v3f/RESOV0.MA became a regular file.
︙ | ︙ |
src/os8/v3f/RESOV1.MA became a regular file.
︙ | ︙ |
src/os8/v3f/RESOV2.MA became a regular file.
︙ | ︙ |
src/os8/v3f/RESOVD.MA became a regular file.
︙ | ︙ |
src/os8/v3f/RL0.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RL1.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RL2.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RL3.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RLC.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RLFRMT.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RLSY.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RTL.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RTS.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RX78C.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RXCOPY.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RXNS.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RXSY1.PA became a regular file.
︙ | ︙ |
src/os8/v3f/RXSY2.PA became a regular file.
︙ | ︙ |
src/os8/v3f/SAVECB.PA became a regular file.
︙ | ︙ |
src/os8/v3f/TECO.PA became a regular file.
︙ | ︙ |
src/os8/v3f/VXNS.PA became a regular file.
︙ | ︙ |
src/os8/v3f/VXSY.PA became a regular file.
︙ | ︙ |
Changes to src/pidp8i/gpio-common.c.in.
︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 | * All of this module's other external interfaces are only called * by the other gpio-* modules, from the GPIO thread. */ #include "pidp8i.h" #include <config.h> #include <pthread.h> #include <sys/file.h> #include <sys/time.h> #include <ctype.h> #include <errno.h> | > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | * All of this module's other external interfaces are only called * by the other gpio-* modules, from the GPIO thread. */ #include "pidp8i.h" #include <config.h> #if defined(HAVE_BCM_HOST_H) # include <bcm_host.h> #endif #include <pthread.h> #include <sys/file.h> #include <sys/time.h> #include <ctype.h> #include <errno.h> |
︙ | ︙ | |||
231 232 233 234 235 236 237 | } pidp8i_gpio_present = 0; } } //// bcm_host_get_peripheral_address /////////////////////////////////// | < < < < < < | < | < < < < < < < < < < < < | | < < | < < < | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | } pidp8i_gpio_present = 0; } } //// bcm_host_get_peripheral_address /////////////////////////////////// // Provide fallback for non-Pi case to avoid a link error. #if !defined(HAVE_BCM_HOST_H) static unsigned bcm_host_get_peripheral_address(void) { return 0; } #endif //// DOUBLE BUFFERED DISPLAY MANIPULATION FUNCTIONS //////////////////// //// swap_displays //////////////////////////////////////////////////// // Clear the current "paint-from" display, then exchange the double- // buffered display pointers atomically, saving the current update-to |
︙ | ︙ |
Changes to tools/bosi.
1 2 3 | #!/bin/bash # bosi - The Binary OS Image creation/update script # | | | 1 2 3 4 5 6 7 8 9 10 11 | #!/bin/bash # bosi - The Binary OS Image creation/update script # # Copyright © 2016-2019 by Warren Young # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to |
︙ | ︙ | |||
85 86 87 88 89 90 91 | exit 1 fi set -x apt-get update && apt-get -y upgrade || true | | < < < < < < < < < | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | exit 1 fi set -x apt-get update && apt-get -y upgrade || true apt-get -y install fossil python-pip || true pip install pexpect test -f /usr/include/curses.h || apt-get -y install libncurses-dev if [ ! -e "$nh" ] then # First pass on a clean SD card: rename 'pi' user and group to # 'pidp8i' and rename its home directory to match. pkill -u pi usermod -l $nu -d $nh -m pi groupmod -n $nu pi |
︙ | ︙ |