LINUX.ORG.RU

[GCC] Как генерировать код на C из bash'а перед компиляцией

 


0

2

Нужно встроить bash-скрипт в программу на C, так чтобы перед компиляцией этот скрипт выполнялся, и вывод скрипта замещался его самого. Те примерно так:

void example()
{
bash( export num=1; 
for varname in a b c ; do 
echo "$varname = $num"; 
num=$(($num+1)); done 
)
}

Соответственно перед компиляцией это должно раскрыться в

void example()
{
a = 1
b = 2
c = 3
}
Пример тупой конечно, но главное он иллюстрирует что надо сделать. Как этого добиться в gcc ?



Последнее исправление: lexa_ (всего исправлений: 2)

используй препроцессор, например:

void example()
{
    GENERATED_CODE
}
CODE="`num=1; for varname in a b c; do echo $varname=$num; num=$((num+1)); done`"
gcc -DGENERATED_CODE="$CODE" example.c ...
arsi ★★★★★
()

Вам придётся написать генератор .c-файлов.

Sorcerer ★★★★★
()

может лучше так?

#include <"config.h">
export num=1; 
for varname in a b c ; do 
echo "$varname = $num" >> config.h;
num=$(($num+1)); done 
lazyklimm ★★★★★
()

>Пример тупой конечно, но главное он иллюстрирует что надо сделать.

Синтаксическую ошибку, что ли? Это можно и без баша:

#define return retun

gentoo_root ★★★★★
()
Ответ на: комментарий от Sorcerer

> Человек хочет, чтобы код на баше был в теле исходника, а не в Makefile или скрипте bash.

ты это понял до того, как предложил свой вариант, или после? ;)

arsi ★★★★★
()
Ответ на: комментарий от arsi

Хорошее решние, и не gcc специфичное, но в этом случае код получается в мэйкфайле, а не в теле программы, что не очень удобно.

lexa_
() автор топика

Мы (правда в питоне) брали шаблон С-файла, типа

void exmaple(){ %(example_code)s }

потом читали по строкам и каждую форматировали по словарю с кодом {'example_code':'...' }. Наверное то же самое можно сделать и другими средствами, без питона.

Но вариант arsi конечно куда изящней, правда могут возникнуть проблемы со скобочками-кавычками.

AIv ★★★★★
()
Ответ на: комментарий от lexa_

код баша можно загнать в тело программы в закомментированном виде типа

void example(){
//=EXMAPLE_CODE for ...
EXAMPLE_CODE
}
а в make выдернуть код grep-ом или еще чем.

AIv ★★★★★
()

Встрой PHP, серьёзно.

[code] void main() { <?php .... ?> } [/code]

anonymous
()

Ведь обычно строки в C не начинаются с решетки?

Ведь можно в исходни вставить что-то типа: #beginbash bash-скрипт #endbash

Это ужь точно ничему не помешает…

А кроме какого-нибудь m4 разве нет нормальных препроцессоров, которые было бы принято использовать вместе с C?

anarquista ★★★★★
()

сделай свой препроцессор :)

и это не шутка. Не особо сложная программа. Используя flex(чтобы корректно отработать комментарии и строки) - может пару часов, чтобы было время отладить.

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Этот препроцессор можно будето потом подключить к gcc ? чтобы gcc при виде

#pragma bash 

Понимал что это bash код. Или мне придётся запускать свой препроцессор перед компиляцией чтобы он подставил результат скрипта в сишный код?

Второй вариант мне не нравится тем, что появляются временные файлы.

lexa_
() автор топика
Ответ на: комментарий от lexa_

> Второй вариант мне не нравится тем, что появляются временные файлы.

my_pp file.c | gcc -x c -с -o file.o -

и никаких временных файлов :) правда, зависит от компилятора.

arsi ★★★★★
()

Примерно так:


#include <stdio.h>

#sh
nm=`uname`
#endsh

int main(int argc, char *argv[])
{
        const char *world = "World";
#sh
        echo "printf(\"$nm: Hello, %s!\\n\", world);"
#endsh
        return '\000';
}

На AWK:


BEGIN {
        state = 0;
        bash_found = 0;
        print "#!/bin/sh"
}

/^[:space:]*\#[:space:]*sh/ {
        state = 1;
        bash_found = 1;
        next;
}

/^[:space:]*#[:space:]*endsh/ {
        # TODO: check state
        state = 0;
        next;
}

function escape_bash(s)
{
        return gensub("'", "'\"'\"'", "g", s);
}

{
        if (state == 0) {
                printf "echo '%s'\n", escape_bash($0);
        } else {
                print;
        }
}

и тест:

#!/bin/sh

awk -f bashc.awk test.c.in > test.c.sh
bash test.c.sh > test.c

Результат:


#include <stdio.h>


int main(int argc, char *argv[])
{
        const char *world = "World";
printf("Linux: Hello, %s!\n", world);
        return '\000';
}

rymis ★★
()

в смысле так что ли?

cat >> /tmp/prog.c << EOF
// here is your C code
EOF

gcc /tmp/prog.c -o /tmp/prog

/tmp/prog
true_admin ★★★★★
()
Ответ на: комментарий от lazyklimm

а смысл? просто обернуть cpp скриптом

просто то, что ТС хочет называется препроцессор :) А то что вы подразумеваете - генератор. Те-же яйца, вид сбоку

И то и другое всё равно на чём писать, надо только чтобы выбранное средство немного разбиралось в С - то есть как минимум различало коментарии, строки и инструкции С-шного препроцессора. Если будет разбираться чуть более - то получится макропроцессор.

вообще-то свой (макро)препроцессор - полезная вещь, если грамотно используется. В Qt очень даже не лишняя. Разные SQL подстановки и интерфейсы (было когда-то такое, не знаю как сейчас). doxygen и иже с ним.

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

>А то что вы подразумеваете - генератор

я подразумеваю враппер для стандартного препроцессора, чтобы не велосипедить функционал cpp по второму кругу

lazyklimm ★★★★★
()
Ответ на: комментарий от lexa_

>Второй вариант мне не нравится тем, что появляются временные файлы.

А мне нравятся временные файлы. Там можно подсмотреть что нагенерировалось, поотлаживать. В конце-концов файлы *.o тебя же не смущают?

legolegs ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.