文件
Paze-C-CPP-Compiler/tools/pcc-get.c
T
Paze AI 105c1f6f6a feat: bounds-checking/pcc-asm/pcc-impdef/pcc-get/交叉编译 五项功能
1. -b bounds-checking 内存安全
   - 编译 bcheck.o/bt-exe.o/bt-log.o 运行时
   - 数组越界/野指针检测,精确定位文件和行号
   - 测试: strcpy 溢出和数组越界均被捕获

2. pcc-asm 汇编查看工具 (bin/pcc-asm.exe)
   - 反汇编 pcc 生成的二进制 (调用 llvm-objdump)
   - 查看 x86-64 机器码与汇编指令

3. pcc-impdef DLL导入工具 (bin/pcc-impdef.exe)
   - 解析 PE 导出表生成 .def 文件
   - 测试: kernel32.dll 1693 个导出全部正确解析

4. pcc-get 包管理器 (bin/pcc-get.exe)
   - install/remove/list/root 命令
   - 支持本地包目录和 URL 下载安装
   - 安装头文件到 include/、库到 lib/
   - 测试: mymath 包安装→编译→链接→运行 全流程

5. 交叉编译演示
   - 构建 ARM64 交叉编译器 (pcc-arm64.exe)
   - 构建 RISC-V 交叉编译器 (pcc-riscv64.exe)
   - 生成 elf64-littleaarch64 / elf64-littleriscv 对象
   - 反汇编验证: 真正的 ARM64/RISC-V 机器码
2026-08-16 15:16:35 +08:00

351 行
11 KiB
C

/*
* pcc-get.c - package manager for PCC
*
* Manages C libraries: install headers/libs, remove, list.
*
* Usage:
* pcc-get install <pkg> [url] install a package
* <pkg> is a name; if a directory of that name exists
* in the current dir or the packages/ dir, its files are
* copied. If [url] is given, it is downloaded first
* (zip/tar not extracted; use a flat file layout).
* pcc-get list list installed packages
* pcc-get remove <pkg> remove a package
* pcc-get root print the install root
*
* A package is a directory containing:
* include/xxx.h -> <root>/include/xxx.h
* lib/libxxx.a -> <root>/lib/libxxx.a
* (files may also be placed directly: foo.h -> include/,
* libfoo.a -> lib/)
*
* License: MIT
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef _WIN32
# include <windows.h>
# include <direct.h>
# define mkdir_p(p) _mkdir(p)
#else
# include <unistd.h>
# include <sys/stat.h>
# define mkdir_p(p) mkdir(p, 0755)
#endif
/* URLDownloadToFile from urlmon.dll (declared manually) */
#ifdef _WIN32
typedef long (__stdcall *URLDownloadToFileA_t)(void*, const char*, const char*, long, void*);
static URLDownloadToFileA_t g_url_dl = NULL;
static int http_download(const char *url, const char *dest)
{
HMODULE h = LoadLibraryA("urlmon.dll");
if (!h) return -1;
g_url_dl = (URLDownloadToFileA_t)GetProcAddress(h, "URLDownloadToFileA");
if (!g_url_dl) return -1;
return g_url_dl(NULL, url, dest, 0, NULL) == 0 ? 0 : -1;
}
#else
static int http_download(const char *url, const char *dest)
{
(void)url; (void)dest;
return -1; /* no download on non-Windows */
}
#endif
static void die(const char *msg)
{
fprintf(stderr, "pcc-get: %s\n", msg);
exit(1);
}
/* find install root: dir of pcc-get.exe, else cwd */
static void get_root(char *root, int size)
{
#ifdef _WIN32
GetModuleFileNameA(NULL, root, size);
{
char *s = strrchr(root, '\\');
if (!s) s = strrchr(root, '/');
if (s) *s = 0;
else strcpy(root, ".");
}
#else
getcwd(root, size);
#endif
}
static int file_exists(const char *f)
{
FILE *p = fopen(f, "rb");
if (p) { fclose(p); return 1; }
return 0;
}
static int dir_exists(const char *d)
{
#ifdef _WIN32
DWORD attr = GetFileAttributesA(d);
return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
#else
struct stat st;
return stat(d, &st) == 0 && S_ISDIR(st.st_mode);
#endif
}
/* copy a file */
static int copy_file(const char *src, const char *dst)
{
FILE *in = fopen(src, "rb");
FILE *out;
char buf[8192];
size_t n;
if (!in) return -1;
out = fopen(dst, "wb");
if (!out) { fclose(in); return -1; }
while ((n = fread(buf, 1, sizeof buf, in)) > 0)
fwrite(buf, 1, n, out);
fclose(in);
fclose(out);
return 0;
}
/* case-insensitive compare of extensions */
static int has_ext(const char *name, const char *ext)
{
const char *dot = strrchr(name, '.');
if (!dot) return 0;
return strcmp(dot + 1, ext) == 0
|| strcmp(dot + 1, ext + 1) == 0 /* ".a" vs "a" */
|| strcmp(dot, ext) == 0;
}
static void ensure_dir(const char *path)
{
mkdir_p(path);
}
/* install a package directory */
static int install_dir(const char *pkgdir, const char *root)
{
char pattern[1024];
char incdir[1024], libdir[1024];
char src[1200], dst[1200];
WIN32_FIND_DATAA fd;
HANDLE h;
int n = 0;
snprintf(incdir, sizeof incdir, "%s\\include", root);
snprintf(libdir, sizeof libdir, "%s\\lib", root);
ensure_dir(incdir);
ensure_dir(libdir);
/* copy *.h to include/ */
snprintf(pattern, sizeof pattern, "%s\\*.h", pkgdir);
h = FindFirstFileA(pattern, &fd);
if (h != INVALID_HANDLE_VALUE) {
do {
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
snprintf(src, sizeof src, "%s\\%s", pkgdir, fd.cFileName);
snprintf(dst, sizeof dst, "%s\\%s", incdir, fd.cFileName);
if (copy_file(src, dst) == 0) {
printf(" install %s -> include/\n", fd.cFileName);
n++;
}
}
} while (FindNextFileA(h, &fd));
FindClose(h);
}
/* copy *.a and *.def to lib/ */
snprintf(pattern, sizeof pattern, "%s\\*.a", pkgdir);
h = FindFirstFileA(pattern, &fd);
if (h != INVALID_HANDLE_VALUE) {
do {
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
snprintf(src, sizeof src, "%s\\%s", pkgdir, fd.cFileName);
snprintf(dst, sizeof dst, "%s\\%s", libdir, fd.cFileName);
if (copy_file(src, dst) == 0) {
printf(" install %s -> lib/\n", fd.cFileName);
n++;
}
}
} while (FindNextFileA(h, &fd));
FindClose(h);
}
snprintf(pattern, sizeof pattern, "%s\\*.def", pkgdir);
h = FindFirstFileA(pattern, &fd);
if (h != INVALID_HANDLE_VALUE) {
do {
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
snprintf(src, sizeof src, "%s\\%s", pkgdir, fd.cFileName);
snprintf(dst, sizeof dst, "%s\\%s", libdir, fd.cFileName);
if (copy_file(src, dst) == 0) {
printf(" install %s -> lib/\n", fd.cFileName);
n++;
}
}
} while (FindNextFileA(h, &fd));
FindClose(h);
}
return n;
}
int main(int argc, char **argv)
{
char root[1024];
char pkgdir[1200];
char listfile[1200];
const char *cmd, *pkg = NULL, *url = NULL;
get_root(root, sizeof root);
if (argc < 2) {
fprintf(stderr,
"pcc-get - PCC package manager\n"
"\n"
"Usage:\n"
" pcc-get install <pkg> [url] install a package\n"
" pcc-get list list installed packages\n"
" pcc-get remove <pkg> remove a package\n"
" pcc-get root print install root\n"
"\n"
"Install root: %s\n", root);
return 1;
}
cmd = argv[1];
if (strcmp(cmd, "root") == 0) {
printf("%s\n", root);
return 0;
}
if (strcmp(cmd, "list") == 0) {
char pattern[1024];
WIN32_FIND_DATAA fd;
HANDLE h;
int n = 0;
snprintf(pattern, sizeof pattern, "%s\\lib\\*.a", root);
h = FindFirstFileA(pattern, &fd);
printf("Installed packages:\n");
if (h != INVALID_HANDLE_VALUE) {
do {
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
char name[512];
strncpy(name, fd.cFileName, sizeof name - 1);
name[sizeof name - 1] = 0;
/* strip lib prefix and .a suffix */
if (strncmp(name, "lib", 3) == 0) {
char *dot = strrchr(name, '.');
if (dot) *dot = 0;
printf(" %s\n", name + 3);
n++;
}
}
} while (FindNextFileA(h, &fd));
FindClose(h);
}
if (n == 0) printf(" (none)\n");
return 0;
}
if (strcmp(cmd, "install") == 0) {
int n;
if (argc < 3) die("usage: pcc-get install <pkg> [url]");
pkg = argv[2];
if (argc > 3) url = argv[3];
/* if url given, download to temp then use as package dir */
if (url) {
char tmp[1200];
snprintf(tmp, sizeof tmp, "%s\\%s.tmp", root, pkg);
printf("pcc-get: downloading %s ...\n", url);
if (http_download(url, tmp) != 0) {
fprintf(stderr, "pcc-get: download failed\n");
return 1;
}
printf("pcc-get: downloaded %s\n", tmp);
/* treat the downloaded file as a single library file:
move to lib/ based on extension */
{
char dst[1200];
char name[512];
const char *base = strrchr(url, '/');
base = base ? base + 1 : pkg;
strncpy(name, base, sizeof name - 1);
name[sizeof name - 1] = 0;
if (has_ext(name, ".a") || has_ext(name, "a")) {
snprintf(dst, sizeof dst, "%s\\lib\\lib%s.a", root, pkg);
ensure_dir(root);
{
char libd[1024];
snprintf(libd, sizeof libd, "%s\\lib", root);
ensure_dir(libd);
}
copy_file(tmp, dst);
printf("pcc-get: installed lib%s.a\n", pkg);
remove(tmp);
return 0;
} else if (has_ext(name, ".h") || has_ext(name, "h")) {
char incd[1024];
snprintf(incd, sizeof incd, "%s\\include", root);
ensure_dir(incd);
snprintf(dst, sizeof dst, "%s\\include\\%s.h", root, pkg);
copy_file(tmp, dst);
printf("pcc-get: installed %s.h\n", pkg);
remove(tmp);
return 0;
} else {
fprintf(stderr, "pcc-get: cannot determine type of %s\n", name);
remove(tmp);
return 1;
}
}
}
/* local package: look for <pkg> dir in cwd, then packages/, then root */
snprintf(pkgdir, sizeof pkgdir, "%s", pkg);
if (!dir_exists(pkgdir)) {
snprintf(pkgdir, sizeof pkgdir, "packages\\%s", pkg);
if (!dir_exists(pkgdir)) {
snprintf(pkgdir, sizeof pkgdir, "%s\\packages\\%s", root, pkg);
if (!dir_exists(pkgdir)) {
fprintf(stderr, "pcc-get: package '%s' not found (looked in ., packages/, %s\\packages)\n",
pkg, root);
return 1;
}
}
}
n = install_dir(pkgdir, root);
printf("pcc-get: installed %s (%d files)\n", pkg, n);
return n > 0 ? 0 : 1;
}
if (strcmp(cmd, "remove") == 0) {
char pattern[1024];
WIN32_FIND_DATAA fd;
HANDLE h;
int n = 0;
if (argc < 3) die("usage: pcc-get remove <pkg>");
pkg = argv[2];
/* remove lib/lib<pkg>.a and include/<pkg>.h */
{
char path[1200];
snprintf(path, sizeof path, "%s\\lib\\lib%s.a", root, pkg);
if (file_exists(path)) { remove(path); printf(" removed %s\n", path); n++; }
snprintf(path, sizeof path, "%s\\include\\%s.h", root, pkg);
if (file_exists(path)) { remove(path); printf(" removed %s\n", path); n++; }
}
if (n == 0)
printf("pcc-get: package '%s' not installed\n", pkg);
return 0;
}
fprintf(stderr, "pcc-get: unknown command '%s'\n", cmd);
return 1;
}