From be2211a6fb78375cec9a5d2615dafaf043e5e848 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 11 Apr 2026 03:20:45 +0900 Subject: add files --- .envrc | 5 +++ .gitignore | 20 +++++++++ build.sh | 6 +++ config.m4 | 8 ++++ flake.lock | 64 ++++++++++++++++++++++++++++ flake.nix | 27 ++++++++++++ mini-xdebug | 3 ++ mini_xdebug.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test.php | 4 ++ 9 files changed, 269 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 build.sh create mode 100644 config.m4 create mode 100644 flake.lock create mode 100644 flake.nix create mode 100755 mini-xdebug create mode 100644 mini_xdebug.c create mode 100644 test.php diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..09672f8 --- /dev/null +++ b/.envrc @@ -0,0 +1,5 @@ +# shellcheck shell=bash +if ! has nix_direnv_version || ! nix_direnv_version 3.1.1; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.1.1/direnvrc" "sha256-p+fzQdrms/hDa7g+soShAybJNo4bN4SIAeSfqNKgD5I=" +fi +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a7f06e1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Files generated by phpize and make +.libs/ +Makefile +Makefile.fragments +Makefile.objects +autom4te.cache/ +build/ +config.h +config.h.in +config.log +config.nice +config.status +configure +configure.ac +libtool +mini_xdebug.dep +mini_xdebug.la +mini_xdebug.lo +modules/ +run-tests.php diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..e1f9d50 --- /dev/null +++ b/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh +PHP_PREFIX="${PHP_PREFIX:-/usr/local}" +cd "$(dirname "$0")" && \ + "$PHP_PREFIX/bin/phpize" && \ + ./configure --with-php-config="$PHP_PREFIX/bin/php-config" --enable-mini-xdebug && \ + make diff --git a/config.m4 b/config.m4 new file mode 100644 index 0000000..8527939 --- /dev/null +++ b/config.m4 @@ -0,0 +1,8 @@ +PHP_ARG_ENABLE([mini_xdebug], + [whether to enable mini-xdebug], + [AS_HELP_STRING([--enable-mini-xdebug], [Enable mini-xdebug])], + [no]) + +if test "$PHP_MINI_XDEBUG" != "no"; then + PHP_NEW_EXTENSION([mini_xdebug], [mini_xdebug.c], [$ext_shared]) +fi diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..7758994 --- /dev/null +++ b/flake.lock @@ -0,0 +1,64 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1775793324, + "narHash": "sha256-omax7atcZbol+6HJ2RLpP+ZCFcPa5bZ65Hn71RufeWQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9d29d5f667d7467f98efc31881e824fa586c927e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "systems": "systems" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..a149d7b --- /dev/null +++ b/flake.nix @@ -0,0 +1,27 @@ +{ + description = "A basic flake with a shell"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + inputs.systems.url = "github:nix-systems/default"; + inputs.flake-utils = { + url = "github:numtide/flake-utils"; + inputs.systems.follows = "systems"; + }; + + outputs = + { nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + devShells.default = pkgs.mkShell { packages = [ + pkgs.autoconf + pkgs.bashInteractive + pkgs.bison + pkgs.pkg-config + pkgs.re2c + ]; }; + } + ); +} diff --git a/mini-xdebug b/mini-xdebug new file mode 100755 index 0000000..9b59f2a --- /dev/null +++ b/mini-xdebug @@ -0,0 +1,3 @@ +#!/bin/sh +DIR=$(cd "$(dirname "$0")" && pwd) +php -d "zend_extension=$DIR/modules/mini_xdebug.so" "$@" diff --git a/mini_xdebug.c b/mini_xdebug.c new file mode 100644 index 0000000..b9263ba --- /dev/null +++ b/mini_xdebug.c @@ -0,0 +1,132 @@ +#include +#include + +#include "php.h" +#include "zend_extensions.h" + +#define MINI_XDEBUG_CMD_END -1 +#define MINI_XDEBUG_CMD_INVALID 0 +#define MINI_XDEBUG_CMD_NEXT 1 + +static int g_is_first_statement; +static int g_do_next_cmd; +static int g_next_call_depth; + +static void mini_xdebug_activate(void) { + CG(compiler_options) |= ZEND_COMPILE_EXTENDED_STMT; + g_is_first_statement = 1; + g_do_next_cmd = 0; + g_next_call_depth = 0; +} + +static int get_call_depth(void) { + int depth = 0; + zend_execute_data* ex = EG(current_execute_data); + while (ex) { + depth++; + ex = ex->prev_execute_data; + } + return depth; +} + +static void show_context(const char* filename, int lineno) { + FILE* fp = fopen(filename, "r"); + if (!fp) { + return; + } + + char buf[1024]; + int n = 0; + while (fgets(buf, sizeof(buf), fp)) { + n++; + if (lineno - 1 <= n && n <= lineno + 1) { + fprintf(stdout, "%s %3d | %s", n == lineno ? ">" : " ", n, buf); + } + if (n > lineno + 1) { + break; + } + } + fclose(fp); +} + +static void show_prompt(void) { + fprintf(stdout, "(mini-xdebug) "); + fflush(stdout); +} + +static int query_command(char* buf) { + if (!fgets(buf, sizeof(buf), stdin)) { + return MINI_XDEBUG_CMD_END; + } + buf[strcspn(buf, "\n")] = '\0'; + + return (!strcmp(buf, "next") || !strcmp(buf, "n")) + ? MINI_XDEBUG_CMD_NEXT + : MINI_XDEBUG_CMD_INVALID; +} + +static void mini_xdebug_statement_handler(zend_execute_data* frame) { + if (!g_is_first_statement && !g_do_next_cmd) { + return; + } + + uint32_t lineno = EG(current_execute_data)->opline->lineno; + const char* filename = ZSTR_VAL(frame->func->op_array.filename); + int depth = get_call_depth(); + + if (g_is_first_statement) { + g_is_first_statement = 0; + } else if (g_do_next_cmd) { + if (depth > g_next_call_depth) { + return; + } + g_do_next_cmd = 0; + } + + fprintf(stdout, "\n%s:%d\n", filename, lineno); + show_context(filename, lineno); + + char command_buf[256]; + for (;;) { + show_prompt(); + int cmd = query_command(command_buf); + if (cmd == MINI_XDEBUG_CMD_NEXT) { + g_do_next_cmd = 1; + g_next_call_depth = depth; + break; + } else if (cmd == MINI_XDEBUG_CMD_END) { + break; + } else { + fprintf(stdout, "Available commands: next (n)\n"); + } + } +} + +#ifndef ZEND_EXT_API +#define ZEND_EXT_API ZEND_DLEXPORT +#endif + +ZEND_EXT_API zend_extension_version_info extension_version_info = { + ZEND_EXTENSION_API_NO, + (char*)ZEND_EXTENSION_BUILD_ID, +}; + +ZEND_DLEXPORT zend_extension zend_extension_entry = { + "mini-xdebug", /* name */ + "0.1.0", /* version */ + "nsfisis", /* author */ + "", /* URL */ + "", /* copyright */ + NULL, /* startup */ + NULL, /* shutdown */ + mini_xdebug_activate, /* activate */ + NULL, /* deactivate */ + NULL, /* message_handler */ + NULL, /* op_array_handler */ + mini_xdebug_statement_handler, /* statement_handler */ + NULL, /* fcall_begin_handler */ + NULL, /* fcall_end_handler */ + NULL, /* op_array_ctor */ + NULL, /* op_array_dtor */ + STANDARD_ZEND_EXTENSION_PROPERTIES, +}; diff --git a/test.php b/test.php new file mode 100644 index 0000000..8c4a7d9 --- /dev/null +++ b/test.php @@ -0,0 +1,4 @@ +