File size: 3,379 Bytes
1e75d97
2e8c18d
1e75d97
5b3f6a4
2e8c18d
 
 
1e75d97
 
2e8c18d
 
1e75d97
2e8c18d
 
1e75d97
 
2e8c18d
1e75d97
 
 
2e8c18d
1e75d97
 
2e8c18d
 
 
1e75d97
 
2e8c18d
1e75d97
 
2e8c18d
1e75d97
2e8c18d
 
 
1e75d97
 
 
 
 
 
 
2e8c18d
1e75d97
 
 
2e8c18d
1e75d97
 
2e8c18d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1e75d97
2e8c18d
 
 
 
1e75d97
 
2e8c18d
 
5b3f6a4
2e8c18d
 
 
 
 
5b3f6a4
2e8c18d
 
 
 
 
 
 
5b3f6a4
1e75d97
 
 
 
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import gradio as gr
import subprocess, tempfile, os, resource, shutil


# ------------------------------------------------------------------
# 1️⃣  Función que compila y ejecuta el código C
# ------------------------------------------------------------------
def compile_and_run(code: str, stdin: str = "") -> str:
    """
    Compila el código C recibido, lo ejecuta con límites de
    recursos y devuelve stdout, stderr y exit-code.
    """
    tmpdir   = tempfile.mkdtemp(prefix="c_exec_")
    c_path   = os.path.join(tmpdir, "main.c")
    bin_path = os.path.join(tmpdir, "main")

    # Guardar el código fuente
    with open(c_path, "w") as f:
        f.write(code)

    # Compilar
    compile_proc = subprocess.run(
        ["gcc", c_path, "-O2", "-std=c11", "-pipe", "-o", bin_path],
        capture_output=True,
        text=True,
        timeout=10
    )
    if compile_proc.returncode != 0:
        shutil.rmtree(tmpdir, ignore_errors=True)
        return f"❌ Error de compilación:\n{compile_proc.stderr}"

    # Límites (CPU 2 s, RAM 128 MB)
    def limit_resources():
        resource.setrlimit(resource.RLIMIT_CPU, (2, 2))
        resource.setrlimit(resource.RLIMIT_AS, (128 * 1024 * 1024,
                                               128 * 1024 * 1024))

    try:
        run_proc = subprocess.run(
            [bin_path],
            input=stdin,
            text=True,
            capture_output=True,
            timeout=2,
            preexec_fn=limit_resources
        )
    except subprocess.TimeoutExpired:
        shutil.rmtree(tmpdir, ignore_errors=True)
        return "⏰ Tiempo de ejecución excedido (2 s)."

    stdout, stderr = run_proc.stdout, run_proc.stderr
    exit_code = run_proc.returncode

    shutil.rmtree(tmpdir, ignore_errors=True)

    result = f"⏹ Código de salida: {exit_code}\n"
    if stdout:
        result += f"\n📤 STDOUT\n{stdout}"
    if stderr:
        result += f"\n⚠️ STDERR\n{stderr}"
    return result.strip()


# ------------------------------------------------------------------
# 2️⃣  Detección automática del lenguaje para gr.Code
#      ('c' en Gradio ≥4, 'cpp' en Gradio 3)
# ------------------------------------------------------------------
def detect_c_language() -> str:
    langs = getattr(gr.Code, "languages", [])
    return "c" if "c" in langs else "cpp"

code_lang = detect_c_language()


# ------------------------------------------------------------------
# 3️⃣  Construcción de la interfaz
# ------------------------------------------------------------------
title       = "Compilador C online (42 Edition)"
description = (
    "Ejecuta fragmentos de **lenguaje C** con límite de recursos.\n"
    "Disponible también como endpoint REST (`/run/predict`)."
)

demo = gr.Interface(
    fn=compile_and_run,
    inputs=[
        gr.Code(language=code_lang, label="Código C"),
        gr.Textbox(
            lines=3,
            placeholder="Entrada estándar (stdin)",
            label="Stdin (opcional)"
        ),
    ],
    outputs=gr.Textbox(label="Resultado"),
    title=title,
    description=description,
    examples=[
        ["#include <stdio.h>\nint main(){puts(\"Hola 42!\");}", ""],
        ["#include <stdio.h>\nint main(){int a,b;scanf(\"%d %d\",&a,&b);"
         "printf(\"%d\\n\",a+b);}", "3 4"],
    ],
)

if __name__ == "__main__":
    demo.launch()