-2
\$\begingroup\$

Some built-in functions in PHP return mixed types, like file_get_contents that returns both string or false. Union structs in C can be used to simulate this, but is there a way to make it polyglot, that is, can be run in both PHP and C without (major) modification? Macros is often one way.

$result === false

can be replaced with

CHECK_RESULT($result, false)

where

#define CHECK_RESULT(res, b) res.success == b

and in PHP

function CHECK_RESULT($res, $b) { return $res === $b; }

Maybe C11 generics can help in a macro too? To switch on second argument.

Thankful for any suggestions regarding this. :)

\$\endgroup\$
4
  • \$\begingroup\$ what's the scoring criterion? \$\endgroup\$ Sep 28 at 4:58
  • 1
    \$\begingroup\$ I didn't understand what your question is. Won't false simply equals to NULL in C, while char* could be NULL as trivial. \$\endgroup\$
    – tsh
    Sep 28 at 5:50
  • \$\begingroup\$ @UndoneStudios I guess smaller size and less changes needed before compile is better. :) The more polyglot the better, that is. \$\endgroup\$ Sep 28 at 10:02
  • \$\begingroup\$ @tsh In PHP === null is not the same as === false. \$\endgroup\$ Sep 28 at 10:03

1 Answer 1

0
\$\begingroup\$

This behaves the same in C and PHP (assuming there's a file named moo.txt with content "hej" in it).

//<?php echo "\x08\x08"; ob_start(); ?>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

enum type
{
    STRING = 0,
    BOOL   = 1
};

struct Result
{
    enum type t;
    union {
        char* str;
        bool  b;
    };
};

struct Result file_get_contents(char* filename)
{
    //struct Result r = {.t = BOOL, .b = false};
    char* s = malloc(4);
    strcpy(s, "hej\n");
    struct Result r = {.t = STRING, .str = s};
    return r;
}

bool compare_string(struct Result r, char* val)
{
    printf("compare_string\n");
    return false;
}

#define DO_OP(a, op) a op a
#define COMPARE_MIXED(res, val, op) _Generic(val, int: (res.t == BOOL && res.b op val),\
    char*: (res.t == STRING && strcmp(res.str, val) == 0)\
    )

#define OP_EQUALS ==
#define OP_PLUS +

#if __PHP__//<?php
define("OP_EQUALS", "==");
define("OP_PLUS", "+");
function COMPARE_MIXED($res, $val, $op)
{
    switch ($op) {
        case OP_EQUALS:
            return $res == $val;
            break;
        default:
            assert(false, 'Unkown operation');
    }
}
#endif
//<?php
/**
 * Compile with
 *   cat mixed.c | sed -e "s/#__C__//g" | gcc -g -I. -Wno-incompatible-pointer-types -xc - -lgc
 */
#define function int
function main()
#undef function
{
    #__C__ struct Result
    $r = file_get_contents("moo.txt");
    if (COMPARE_MIXED($r, false, OP_EQUALS)) {
        printf("Is false\n");
    } else if (COMPARE_MIXED($r, "hej\n", OP_EQUALS)) {
        printf("Is hej\n");
    }
    return 0;
}
//?>
//<?php ob_end_clean(); main();
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.