diff --git a/.gitignore b/.gitignore index 6870b8d..d36511a 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,7 @@ tests/vla_test tests/hello tests/tests2/fred.txt libtcc.dylib + +# Release packages +release/ +*.zip diff --git a/build-release.ps1 b/build-release.ps1 new file mode 100644 index 0000000..9833b33 --- /dev/null +++ b/build-release.ps1 @@ -0,0 +1,99 @@ +# build-release.ps1 - one-click packaging of PCC Windows toolchain +$ErrorActionPreference = "Stop" +$root = "F:\Paze C Compiler" +$win32 = Join-Path $root "win32" +$version = "0.9.28" +$outDir = Join-Path $root "release" +$pkgName = "pcc-$version-win32" +$pkgDir = Join-Path $outDir $pkgName + +Write-Host "=== PCC Windows toolchain packaging ===" +Write-Host "Version: $version" +Write-Host "" + +if (Test-Path $pkgDir) { Remove-Item $pkgDir -Recurse -Force } +New-Item -ItemType Directory -Path $pkgDir -Force | Out-Null + +Write-Host "[1/6] Copy core programs..." +Copy-Item (Join-Path $win32 "pcc.exe") $pkgDir +if (Test-Path (Join-Path $win32 "libpcc.dll")) { + Copy-Item (Join-Path $win32 "libpcc.dll") $pkgDir +} + +Write-Host "[2/6] Copy standard headers..." +$destInc = Join-Path $pkgDir "include" +New-Item -ItemType Directory -Path $destInc -Force | Out-Null +Get-ChildItem (Join-Path $root "include") -File | Copy-Item -Destination $destInc + +Write-Host "[3/6] Copy Windows headers..." +$destWinInc = Join-Path $pkgDir "win32\include" +New-Item -ItemType Directory -Path $destWinInc -Force | Out-Null +Get-ChildItem (Join-Path $win32 "include") -Recurse -File | ForEach-Object { + $rel = $_.FullName.Substring((Join-Path $win32 "include").Length + 1) + $target = Join-Path $destWinInc $rel + New-Item -ItemType Directory -Path (Split-Path $target) -Force | Out-Null + Copy-Item $_.FullName $target +} + +Write-Host "[4/6] Copy runtime libs..." +$destLib = Join-Path $pkgDir "lib" +New-Item -ItemType Directory -Path $destLib -Force | Out-Null +Get-ChildItem (Join-Path $win32 "lib") -File | Where-Object { $_.Extension -in ".a",".def" } | Copy-Item -Destination $destLib -ErrorAction SilentlyContinue +# also place libs where -B can find them (tcc layout: /lib/) +$winDestLib = Join-Path $pkgDir "win32\lib" +New-Item -ItemType Directory -Path $winDestLib -Force | Out-Null +Get-ChildItem (Join-Path $win32 "lib") -File | Where-Object { $_.Extension -in ".a",".def" } | Copy-Item -Destination $winDestLib -ErrorAction SilentlyContinue + +Write-Host "[5/6] Copy examples and docs..." +$destEx = Join-Path $pkgDir "examples" +New-Item -ItemType Directory -Path $destEx -Force | Out-Null +Get-ChildItem (Join-Path $win32 "examples") -File | Copy-Item -Destination $destEx -ErrorAction SilentlyContinue +Copy-Item (Join-Path $win32 "pcc-win32.txt") $pkgDir -ErrorAction SilentlyContinue + +Write-Host "[6/6] Create README and wrapper..." +$readme = @" +PCC - Paze C Compiler $version (Windows) +======================================== + +Usage: + pcc.bat hello.c -o hello.exe compile C program (auto paths) + pcc.bat -run hello.c compile and run directly + pcc.exe --version show version + +Structure: + pcc.exe compiler main program + pcc.bat launcher with auto include/lib paths + libpcc.dll embeddable compiler library (optional) + include\ standard C headers + win32\include\ Windows API headers + lib\ runtime and import libs + examples\ example programs + +Notes: + - Add this directory to PATH to use pcc globally + - pcc is fully self-contained, no GCC/MinGW needed + +License: MIT +"@ +$readme | Out-File (Join-Path $pkgDir "README.txt") -Encoding ascii + +# pcc.bat launcher: automatically sets -B, -I and -L relative to itself +$bat = @" +@echo off +setlocal +set "PCCDIR=%~dp0" +"%PCCDIR%pcc.exe" -B "%PCCDIR%win32" -I "%PCCDIR%include" -L "%PCCDIR%lib" %* +exit /b %errorlevel% +"@ +$bat | Out-File (Join-Path $pkgDir "pcc.bat") -Encoding ascii + +Write-Host "" +Write-Host "Zipping..." +$zipFile = Join-Path $outDir "$pkgName.zip" +if (Test-Path $zipFile) { Remove-Item $zipFile -Force } +Compress-Archive -Path $pkgDir -DestinationPath $zipFile -CompressionLevel Optimal + +$size = [math]::Round((Get-Item $zipFile).Length / 1KB, 1) +Write-Host "" +Write-Host "OK: $zipFile ($size KB)" +Write-Host "Extract and use directly, no install needed." \ No newline at end of file diff --git a/vscode-extension/.vscode/settings.json b/vscode-extension/.vscode/settings.json new file mode 100644 index 0000000..06d4659 --- /dev/null +++ b/vscode-extension/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": {}, + "files.associations": { + "*.c": "c", + "*.h": "c" + } +} diff --git a/vscode-extension/.vscode/tasks.json b/vscode-extension/.vscode/tasks.json new file mode 100644 index 0000000..d0b3370 --- /dev/null +++ b/vscode-extension/.vscode/tasks.json @@ -0,0 +1,51 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "PCC: Build", + "type": "pcc", + "task": "build", + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": { + "owner": "c", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*):(\\d+):\\s+(error|warning):\\s+(.*)$", + "file": 1, + "line": 2, + "severity": 3, + "message": 4 + } + } + }, + { + "label": "PCC: Run", + "type": "pcc", + "task": "run", + "group": { + "kind": "test", + "isDefault": true + }, + "problemMatcher": { + "owner": "c", + "fileLocation": [ + "relative", + "${workspaceFolder}" + ], + "pattern": { + "regexp": "^(.*):(\\d+):\\s+(error|warning):\\s+(.*)$", + "file": 1, + "line": 2, + "severity": 3, + "message": 4 + } + } + } + ] +} diff --git a/vscode-extension/.vscodeignore b/vscode-extension/.vscodeignore new file mode 100644 index 0000000..860322a --- /dev/null +++ b/vscode-extension/.vscodeignore @@ -0,0 +1,7 @@ +.vscode/** +src/** +node_modules/** +.gitignore +**/*.map +**/*.zip +*.vsix diff --git a/vscode-extension/README.md b/vscode-extension/README.md new file mode 100644 index 0000000..0b0552d --- /dev/null +++ b/vscode-extension/README.md @@ -0,0 +1,47 @@ +# PCC C Language Support + +C language support with **Paze C Compiler (PCC)** integration for Visual Studio Code. + +## Features + +- ✅ **Syntax highlighting** for C files (.c, .h) +- ✅ **Build** current C file with PCC (Ctrl+Shift+B) +- ✅ **Build & Run** current C file (Ctrl+F5) +- ✅ Configurable pcc path, include/lib paths + +## Installation + +### From VSIX +1. Run `npx @vscode/vsce package` in this directory to create the VSIX +2. In VS Code: Extensions → `...` → Install from VSIX → select the .vsix file + +### From source (development) +1. Copy this directory to `~/.vscode/extensions/pcc-language-support` +2. Reload VS Code + +## Usage + +Open a `.c` file, then: + +| Command | Shortcut | Description | +|---------|----------|-------------| +| PCC: Build | `Ctrl+Shift+B` | Compile to `.exe` next to source | +| PCC: Build & Run | `Ctrl+F5` | Compile and run in terminal | + +## Settings + +| Setting | Description | +|---------|-------------| +| `pcc.executable` | Path to pcc.exe (empty = search PATH) | +| `pcc.includePath` | Extra `-I` include directories | +| `pcc.libPath` | Extra `-L` library directories | +| `pcc.args` | Extra arguments passed to pcc | +| `pcc.outputDir` | Output directory for exe (empty = source dir) | + +## Requirements + +- **PCC** - install from https://git.parlz.com/Paze/Paze-C-CPP-Compiler or add to PATH + +## License + +MIT diff --git a/vscode-extension/extension.js b/vscode-extension/extension.js new file mode 100644 index 0000000..fece0bc --- /dev/null +++ b/vscode-extension/extension.js @@ -0,0 +1,164 @@ +// PCC - Paze C Compiler VS Code extension +// Provides build and run commands for C files using pcc + +const vscode = require('vscode'); +const path = require('path'); +const { execSync } = require('child_process'); + +/** + * Find the pcc executable. + * Search order: + * 1. Setting "pcc.executable" + * 2. "pcc" / "pcc.exe" in PATH + * 3. Common install locations + */ +function findPcc() { + // 1. User setting + const configured = vscode.workspace.getConfiguration('pcc').get('executable'); + if (configured && configured.trim()) { + return configured.trim(); + } + + // 2. PATH lookup + try { + execSync('pcc --version', { stdio: 'ignore' }); + return 'pcc'; + } catch (e) { + // not in PATH + } + + // 3. Common locations + const candidates = [ + 'C:\\pcc\\pcc.exe', + 'C:\\Program Files\\pcc\\pcc.exe', + 'C:\\Program Files (x86)\\pcc\\pcc.exe', + 'F:\\Paze C Compiler\\win32\\pcc.exe' + ]; + for (const c of candidates) { + try { + if (require('fs').existsSync(c)) { + return c; + } + } catch (e) { } + } + return 'pcc'; +} + +function getPccArgs(extraArgs) { + const cfg = vscode.workspace.getConfiguration('pcc'); + const includePath = cfg.get('includePath', []); + const libPath = cfg.get('libPath', []); + const extra = cfg.get('args', []); + const args = []; + + // Add include paths + for (const inc of includePath) { + args.push('-I', inc); + } + // Add lib paths + for (const lib of libPath) { + args.push('-L', lib); + } + // User extra args + args.push(...extra); + // Extra args passed from command + args.push(...extraArgs); + return args; +} + +function getOutputPath(sourceFile) { + const cfg = vscode.workspace.getConfiguration('pcc'); + const outputDir = cfg.get('outputDir', ''); + const baseName = path.basename(sourceFile, path.extname(sourceFile)); + if (outputDir) { + return path.join(outputDir, baseName + '.exe'); + } + return path.join(path.dirname(sourceFile), baseName + '.exe'); +} + +function runPcc(args) { + const pcc = findPcc(); + const cmd = `"${pcc}" ${args.join(' ')}`; + return new Promise((resolve, reject) => { + const cp = require('child_process').exec(cmd, { + cwd: vscode.workspace.rootPath || path.dirname(vscode.window.activeTextEditor.document.fileName), + env: process.env + }, (error, stdout, stderr) => { + resolve({ stdout, stderr, error }); + }); + }); +} + +async function getActiveCFile() { + const editor = vscode.window.activeTextEditor; + if (!editor) { + vscode.window.showWarningMessage('No active editor.'); + return null; + } + const doc = editor.document; + if (doc.languageId !== 'c' && !doc.fileName.endsWith('.c')) { + vscode.window.showWarningMessage('Active file is not a C file.'); + return null; + } + await doc.save(); + return doc.fileName; +} + +async function build(file) { + const output = getOutputPath(file); + const args = getPccArgs([file, '-o', output]); + const result = await runPcc(args); + return { output, result }; +} + +async function cmdBuild() { + const file = await getActiveCFile(); + if (!file) return; + + const status = vscode.window.setStatusBarMessage('$(sync~spin) PCC: compiling...'); + const { output, result } = await build(file); + status.dispose(); + + if (result.error) { + vscode.window.showErrorMessage('PCC: Build failed'); + vscode.window.showInformationMessage('See output for details.'); + const outputChannel = vscode.window.createOutputChannel('PCC'); + outputChannel.appendLine(result.stderr || result.stdout); + outputChannel.show(true); + } else { + vscode.window.showInformationMessage(`PCC: Build OK -> ${output}`); + } +} + +async function cmdRun() { + const file = await getActiveCFile(); + if (!file) return; + + const status = vscode.window.setStatusBarMessage('$(sync~spin) PCC: compiling...'); + const { output, result } = await build(file); + status.dispose(); + + if (result.error) { + vscode.window.showErrorMessage('PCC: Build failed'); + const outputChannel = vscode.window.createOutputChannel('PCC'); + outputChannel.appendLine(result.stderr || result.stdout); + outputChannel.show(true); + return; + } + + const terminal = vscode.window.createTerminal('PCC Run'); + terminal.show(); + terminal.sendText(`"${output}"`); +} + +function activate(context) { + context.subscriptions.push( + vscode.commands.registerCommand('pcc.build', cmdBuild), + vscode.commands.registerCommand('pcc.run', cmdRun) + ); + console.log('PCC extension activated'); +} + +function deactivate() { } + +module.exports = { activate, deactivate }; diff --git a/vscode-extension/language-configuration.json b/vscode-extension/language-configuration.json new file mode 100644 index 0000000..5ff5594 --- /dev/null +++ b/vscode-extension/language-configuration.json @@ -0,0 +1,28 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": [ + "/*", + "*/" + ] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "\"", "close": "\"", "notIn": ["string"] }, + { "open": "'", "close": "'", "notIn": ["string", "comment"] } + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ] +} diff --git a/vscode-extension/package.json b/vscode-extension/package.json new file mode 100644 index 0000000..8604c97 --- /dev/null +++ b/vscode-extension/package.json @@ -0,0 +1,115 @@ +{ + "name": "PCC C Language Support", + "displayName": "PCC C Language Support", + "description": "C language support with Paze C Compiler (PCC) integration", + "version": "0.1.0", + "publisher": "PazeAI", + "engines": { + "vscode": "^1.60.0" + }, + "categories": [ + "Programming Languages" + ], + "contributes": { + "languages": [ + { + "id": "c", + "aliases": [ + "C", + "c" + ], + "extensions": [ + ".c", + ".h" + ] + } + ], + "grammars": [ + { + "language": "c", + "scopeName": "source.c", + "path": "./syntaxes/c.json" + } + ], + "configuration": { + "title": "PCC", + "properties": { + "pcc.executable": { + "type": "string", + "default": "", + "description": "Path to pcc executable. If empty, searches PATH." + }, + "pcc.includePath": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Additional include paths (-I)." + }, + "pcc.libPath": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Additional library paths (-L)." + }, + "pcc.args": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Extra arguments passed to pcc." + }, + "pcc.outputDir": { + "type": "string", + "default": "", + "description": "Output directory for compiled exe. Empty = same dir as source." + } + } + } + }, + "main": "./extension.js", + "activationEvents": [ + "onCommand:pcc.build", + "onCommand:pcc.run" + ], + "commands": [ + { + "command": "pcc.build", + "title": "PCC: Build" + }, + { + "command": "pcc.run", + "title": "PCC: Build & Run" + } + ], + "keybindings": [ + { + "command": "pcc.build", + "key": "ctrl+shift+b", + "when": "editorLangId == c" + }, + { + "command": "pcc.run", + "key": "ctrl+f5", + "when": "editorLangId == c" + } + ], + "menus": { + "editor/title": [ + { + "command": "pcc.build", + "when": "editorLangId == c", + "group": "navigation" + }, + { + "command": "pcc.run", + "when": "editorLangId == c", + "group": "navigation" + } + ] + } +} diff --git a/vscode-extension/syntaxes/c.json b/vscode-extension/syntaxes/c.json new file mode 100644 index 0000000..9a1ce02 --- /dev/null +++ b/vscode-extension/syntaxes/c.json @@ -0,0 +1,155 @@ +{ + "name": "C", + "scopeName": "source.c", + "fileTypes": ["c", "h"], + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#strings" + }, + { + "include": "#numbers" + }, + { + "include": "#keywords" + }, + { + "include": "#types" + }, + { + "include": "#preprocessor" + }, + { + "include": "#functions" + } + ], + "repository": { + "comments": { + "patterns": [ + { + "name": "comment.line.double-slash.c", + "match": "//.*$" + }, + { + "name": "comment.block.c", + "begin": "/\\*", + "end": "\\*/" + } + ] + }, + "strings": { + "patterns": [ + { + "name": "string.quoted.double.c", + "begin": "\"", + "end": "\"", + "patterns": [ + { + "name": "constant.character.escape.c", + "match": "\\\\(x[0-9a-fA-F]+|[0-7]{1,3}|[abfnrtv\\\\'\"?])" + } + ] + }, + { + "name": "string.quoted.single.c", + "begin": "'", + "end": "'", + "patterns": [ + { + "name": "constant.character.escape.c", + "match": "\\\\(x[0-9a-fA-F]+|[0-7]{1,3}|[abfnrtv\\\\'\"?])" + } + ] + } + ] + }, + "numbers": { + "patterns": [ + { + "name": "constant.numeric.c", + "match": "\\b(0[xX][0-9a-fA-F]+|0[bB][01]+|[0-9]+)([uUlL]{1,3})?\\b" + }, + { + "name": "constant.numeric.float.c", + "match": "\\b[0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?[fFlL]?\\b" + }, + { + "name": "constant.numeric.float.c", + "match": "\\b[0-9]+[eE][+-]?[0-9]+[fFlL]?\\b" + } + ] + }, + "keywords": { + "patterns": [ + { + "name": "keyword.control.c", + "match": "\\b(if|else|for|while|do|switch|case|default|break|continue|return|goto)\\b" + }, + { + "name": "keyword.other.c", + "match": "\\b(sizeof|typedef|extern|static|const|volatile|inline|register|auto|restrict|_Atomic|_Generic|_Alignas|_Alignof|_Static_assert|_Thread_local)\\b" + }, + { + "name": "keyword.operator.c", + "match": "\\b(sizeof|typeof)\\b" + } + ] + }, + "types": { + "patterns": [ + { + "name": "storage.type.c", + "match": "\\b(void|char|short|int|long|float|double|signed|unsigned|_Bool|_Complex|struct|union|enum)\\b" + }, + { + "name": "storage.type.builtin.c", + "match": "\\b(size_t|ssize_t|ptrdiff_t|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|intptr_t|uintptr_t|FILE|va_list|wchar_t)\\b" + } + ] + }, + "preprocessor": { + "patterns": [ + { + "name": "meta.preprocessor.c", + "begin": "^\\s*#\\s*(include|import)\\b", + "end": "$", + "patterns": [ + { + "name": "string.quoted.double.include.c", + "match": "\"[^\"]*\"" + }, + { + "name": "string.quoted.other.lt-gt.include.c", + "match": "<[^>]*>" + } + ] + }, + { + "name": "meta.preprocessor.macro.c", + "begin": "^\\s*#\\s*(define|undef)\\b", + "end": "$", + "patterns": [ + { + "name": "entity.name.function.preprocessor.c", + "match": "\\w+" + } + ] + }, + { + "name": "meta.preprocessor.conditional.c", + "match": "^\\s*#\\s*(if|ifdef|ifndef|elif|else|endif|pragma|error|warning)\\b" + } + ] + }, + "functions": { + "patterns": [ + { + "name": "meta.function.c", + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=\\()" + } + ] + } + } +}