реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> скрипт + gcc
antiwin
сообщение May 20 2009, 08:51
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Народ, такая проблема. Необходимо при компиляции определить сколько раз вызывается функция (foo), а так же передать переменную из препроцессора(скрипта) в код программы.
1111493779.gif
Go to the top of the page
 
+Quote Post
msalov
сообщение May 20 2009, 09:14
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Код
#!/bin/sh

COUNT=0

for FILE in *.c
do
    CURR=`cpp -E ${FILE} | grep -vv "^#" | grep "foo(" | grep -vv -c "void foo("`
    COUNT=`expr ${COUNT} + ${CURR}`
    echo -e "${FILE}\t:${CURR}\t:${COUNT}"
done

cat > foo_call_count.h << EOF
#ifndef _FOO_CALL_COUNT_H
#define _FOO_CALL_COUNT_H

#define foo_call_count ${COUNT}

#endif /*_FOO_CALL_COUNT_H*/
EOF

Ну а дальше, делаете foo_call_count.h зависимым от всех с-файлов и генерируете его при помощи этого скрипта.

UPD. Улучшенная версия с предварительной обработкой препроцессором (препроцессор убирает комментарии).
Go to the top of the page
 
+Quote Post
antiwin
сообщение May 21 2009, 05:45
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Спасибо за совет, будем посмотреть
Go to the top of the page
 
+Quote Post
antiwin
сообщение May 21 2009, 08:23
Сообщение #4


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Цитата(antiwin @ May 21 2009, 09:45) *
Спасибо за совет, будем посмотреть



Не совсем понятно как формируется выражение
CURR=`cpp -E ${FILE} | grep -vv "^#" | grep "foo(" | grep -vv -c "void foo("`
Как я понял, последние два оператора проверяют синтаксис на наличие foo, но вот что делают первые два? smile3046.gif
Go to the top of the page
 
+Quote Post
antiwin
сообщение May 22 2009, 06:24
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Цитата(antiwin @ May 21 2009, 12:23) *
Не совсем понятно как формируется выражение
CURR=`cpp -E ${FILE} | grep -vv "^#" | grep "foo(" | grep -vv -c "void foo("`
Как я понял, последние два оператора проверяют синтаксис на наличие foo, но не понятно что значит grep -vv , такое сочетание параметров я не нашел нигде. smile3046.gif
Go to the top of the page
 
+Quote Post
msalov
сообщение May 22 2009, 11:26
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Первый обрабатывает препроцессором файл, второй отбрасывает служебную инфу препроцессора (может не надо), 3 - выделяет все упоминания функции, 4 - исключает прототипы функции и подсчитывает оставшиеся.
Строчку "echo -e "${FILE}\t:${CURR}\t:${COUNT}"" можно удалить (исключительно для отладочных целей), ещё желательно натравливать препроцессор на файл с полным комплектом ключей компиляции.
Go to the top of the page
 
+Quote Post
antiwin
сообщение May 25 2009, 06:02
Сообщение #7


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Спасибо, прояснилось. Как я понимаю этот скрипт надо вписать в makefile?. И еще, давно хотел спросить, запись типа #define _FOO_CALL_COUNT_H определяет файл FOO_CALL_COUNT.H, но как препроцессор знает что перед H надо ставить точку. Почему просто не написать #include <FOO_CALL_COUNT.H>

yeah.gif
Go to the top of the page
 
+Quote Post
antiwin
сообщение May 25 2009, 07:39
Сообщение #8


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



p.s отвечаю не сразу. т.к дома нет инета.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 25 2009, 07:43
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(antiwin @ May 25 2009, 09:02) *
запись типа #define _FOO_CALL_COUNT_H определяет файл FOO_CALL_COUNT.H, но как препроцессор знает что перед H надо ставить точку.
Препроцессор ничего не знает и не ставит. Определяется символ _FOO_CALL_COUNT_H и дальше идет проверка именно этого символа. Это программист сам для себя решает, что _FOO_CALL_COUNT_H относится к файлу foo_call_count.h. Кстати, имена, начинающиеся с подчеркивания зарезервированы за компилятором и стандартной библиотекой, во избежание неприятностей свои имена с подчеркивания лучше не начинать.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
msalov
сообщение May 25 2009, 07:47
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Цитата(antiwin @ May 25 2009, 09:02) *
Спасибо, прояснилось. Как я понимаю этот скрипт надо вписать в makefile?. И еще, давно хотел спросить, запись типа #define _FOO_CALL_COUNT_H определяет файл FOO_CALL_COUNT.H, но как препроцессор знает что перед H надо ставить точку. Почему просто не написать #include <FOO_CALL_COUNT.H>

yeah.gif

Скрипт лучше поместить в отдельный sh-файл и запускать при необходимости (из мейкфайла) (не уверен но может и из makefile-а работать).
Разберем конструкцию по строчкам:
1. #ifndef _FOO_CALL_COUNT_H
проверяем не объявлен ли _FOO_CALL_COUNT_H, если не объявлен - п.2. Если обьявлен - значит этот заголовочный файл включен не в первый раз и значит его содержимое можно не обрабатывать.
2. #define _FOO_CALL_COUNT_H
Это является стандартным обрамлением для заголовочных файлов.
Цитата(Сергей Борщ @ May 25 2009, 10:43) *
Кстати, имена, начинающиеся с подчеркивания зарезервированы за компилятором и стандартной библиотекой, во избежание неприятностей свои имена с подчеркивания лучше не начинать.
Спасибо за замечание, учту.
Go to the top of the page
 
+Quote Post
antiwin
сообщение May 25 2009, 11:11
Сообщение #11


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Цитата(Сергей Борщ @ May 25 2009, 11:43) *
Определяется символ _FOO_CALL_COUNT_H и дальше идет проверка именно этого символа. Это программист сам для себя решает, что _FOO_CALL_COUNT_H относится к файлу foo_call_count.h.


То есть, компилятор у себя в "уме" держит некую таблицу в которой, допустим, строке _FOO_CALL_COUNT_H соответствует include <FOO_CALL_COUNT.H>?

Цитата(Сергей Борщ @ May 25 2009, 11:43) *
Скрипт лучше поместить в отдельный sh-файл и запускать при необходимости (из мейкфайла).
Разберем конструкцию по строчкам:
1. #ifndef _FOO_CALL_COUNT_H
проверяем не объявлен ли _FOO_CALL_COUNT_H.

Т.е запуск скрипта с помощью команды sh (скрипт)?
Хотел бы уточнить выражение (объявлен ли _FOO_CALL_COUNT_H), если следовать синтаксису С, то это запись (_FOO_CALL_COUNT_H FOO_CALL_COUNT.H ) или нет? Мне хотелось бы понять сам механизм.

smile.gif

Сообщение отредактировал antiwin - May 25 2009, 11:28
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 25 2009, 14:33
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(antiwin @ May 25 2009, 14:11) *
То есть, компилятор у себя в "уме" держит некую таблицу в которой, допустим, строке _FOO_CALL_COUNT_H соответствует include <FOO_CALL_COUNT.H>?
Нет никакой таблицы. Нет никакого соответствия. вот смотрите:
Код
foo.h:
#ifndef  FOO_H_INCLUDED__
#define FOO_H_INCLUDED__
.....
#endif  //FOO_H_INCLUDED__

abc.c:
#include "foo.h"
....
#include "foo.h"
Что происходит при компиляции abc.c?
1)удаляются все комментарии.
2)весь текст foo.h вставляется в те места, где был #include "foo.h". Все, #include исчезли, на их месте появился текст.
3) Теперь препроцессор проходит весь файл от начала до конца. В месте, где файл foo.h вставлен первый раз, он встречает строку #ifndef FOO_H_INCLUDED__.
4)Он ищет в своих списках символ FOO_H_INCLUDED__ и не находит его. Символ не определен. Условие выполнилось, препроцессор просматривает текст внутри условия.
5) тут он встречает строку #define FOO_H_INCLUDED__. Он вносит такой символ в свои списки - все, символ определен.
6) он просматривает файл дальше и доходит до места, где был второй #include "foo.h". Тут он снова встречает строку #ifndef FOO_H_INCLUDED__.
7) Он снова смотрит в своих списках и теперь уже находит там символ FOO_H_INCLUDED__. Условие не выполнилось, препроцессор выкидывает весь текст до #endif .

Все, содержимое foo.h попало компилятору только один раз. Как мы обозвали этот символ - FOO_H_INCLUDED__ или FOO_H_ или SKIP_THIS_FILE или TIPA_TEST - препроцессору все равно. Это наша забота, чтобы в каждом заголовочном файле был определен уникальный символ. И проще всего это сделать, связав имя символа с именем файла.

Чтобы понять смысл выражения "определен символ" - лучше всего прочитать документацию на препроцессор (не компилятор, а именно препроцессор - до компилятора эти символы не доходят).


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
antiwin
сообщение May 26 2009, 06:27
Сообщение #13


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Цитата(Сергей Борщ @ May 25 2009, 18:33) *
Это наша забота, чтобы в каждом заголовочном файле был определен уникальный символ...

Я правильно понал, об'явление уникального символа предохраняет от повторной компиляции?
А вроде бы у препроцессора есть функции на этот счет?

Цитата(Сергей Борщ @ May 25 2009, 18:33) *
Он ищет в своих списках символ FOO_H_INCLUDED__ ...

Значит, что то вроде таблицы все та ки есть...
За ссылку спасибо, как почитаю отпишусь
немного отвлеченный вопрос.
AT (ADDR (.text) + SIZEOF (.text))
SIZEOF вроде понятно-это размер секции, тогда ADDR-это начало? и что это за оператор AT?.
И еще, в WinAvr есть папка с man, как вот эти man прочесть? Я думаю, что масса вопросов сразу бы отпала.

Сообщение отредактировал antiwin - May 26 2009, 06:47
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 26 2009, 08:13
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(antiwin @ May 26 2009, 09:27) *
Я правильно понал, об'явление уникального символа предохраняет от повторной компиляции?
А вроде бы у препроцессора есть функции на этот счет?
Есть, но они не стандартизованы (насколько я помню) и обладают рядом недостатков. Вот на этом форуме второй ответ описывает их. А обертка из #ifndef #define #endif работает везде. Вот неплохое описание
Цитата(antiwin @ May 26 2009, 09:27) *
Значит, что то вроде таблицы все та ки есть...
Как это устроено внутри - не знаю, да это и не принципиально. Важно, что никаких таблиц соответствия имени символа и имени файла нет.
Цитата(antiwin @ May 26 2009, 09:27) *
немного отвлеченный вопрос.
AT (ADDR (.text) + SIZEOF (.text))
Дежа-вю


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
antiwin
сообщение Jun 29 2009, 07:49
Сообщение #15


Участник
*

Группа: Новичок
Сообщений: 22
Регистрация: 20-05-09
Пользователь №: 49 303



Привет всем, такой вот проблем: как можно узнать адрес в ОЗУ выше которого стек не "перерастет"? Это нужно сделать на этапе компиляции.
И еще, можно ли в теле функции узнать тип возвращаемого значения т.е допустим определена функция void *foo(...), далее где то вызывается int *ptr=foo(...), как в теле foo узнать что это указатель на int?

Сообщение отредактировал antiwin - Jun 29 2009, 08:01
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 20:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.01487 секунд с 7
ELECTRONIX ©2004-2016