2016-12-02 12 views
2

Я портирование большой с проектом из Windows на Unix и источник содержит много тысяч вызовов для функции logprint, который объявлен как это:Как автоматически добавлять типы приведения к функциям стиля printf в c исходном коде?

VOID logprint(DWORD level, LPCSTR format, ...); 

Теперь вот мои две проблем:

1 .) Используемые спецификаторы типа формата не переносятся

В коде используются %lu для переменных ULONG. В Windows это нормально, потому что ULONG является typedef для unsigned long. Однако при портировании кода я не могу воспроизвести этот typedef, потому что ULONG всегда должен быть ровно 32-битным в соответствии с [MS-DTYP] (NB: с компиляторами Microsoft c unsigned long всегда 32-разрядный). Итак, я создал заголовочный файл типов окон wtypes.h, который определяет базовые типы данных Windows с помощью stdint.h и limits.h. Конечно, теперь это приводит к недопустимым чтениям из-за спецификатора %lu, если системы unsigned long являются 64-битными, а мой ULONG - 32-разрядный. Поэтому я также должен добавить в список (unsigned long) все аргументы logprint ULONG. И ULONG только один пример, конечно ...

2.) Недействительные спецификаторов типа формата, используемых

Кроме того, что код использует много недействительных спецификатор формата. Например. % d для аргументов DWORD.

Конечно, легко решить:

  1. идентифицировать все logprint называет
  2. определить тип каждого аргумента
  3. проверить, что правильный спецификатор формата используется
  4. добавить правильные забросы типа к статьям

Пример:

Заменить:

ULONG ulMin, ulMax; 
... 
logprint(FATAL, "specified interval is invalid %ld..%u out of range", 
       ulMin, ulMax); 

с:

logprint(FATAL, "specified interval is invalid %lu..%lu", 
       (unsigned long) ulMin, (unsigned long) ulMax); 

Но это заняло бы меня по крайней мере две недели, и мой мозг будет искажен после этого.

Так что мой актуальный вопрос:

Существуют ли какие-либо автоматизированные инструменты для изготовления такого рода изменений?

Как минимум требование, чтобы инструмент должен был идентифицировать тип аргументов и префикс их с типом. После появления типов типов я могу легко написать скрипт python, который исправляет спецификаторы формата.

+2

Регулировка форматов предпочтительнее, чем при отливке! И поскольку вы на нем используете макросы форматирования из 'inttypes.h'. Парень, переносящий это на 64-битный через 10 лет или около того, полюбит вас за это. ;-) – alk

+0

И относительно рабочей нагрузки: Составьте карту и уменьшите это с помощью своих товарищей по команде. – alk

+2

Этот 'logprint (FATAL,« указанный интервал недействителен% ld ..% u вне диапазона », ulMin, ulMax);' должен быть 'logprint (FATAL, указанный интервал недействителен%" PRIu32 "..%" PRIu32 «вне диапазона», ulMin, ulMax); '. – alk

ответ

1

Доступен ли источник logprint? Если это так, лучший способ, по-видимому, может изменить его напрямую.Он должен содержать код произнесения типа для va_arg, таких как:

ul = va_arg(argp, ULONG); 

затем просто изменить ULONG, как вам нужно.

Если это не так, просто сделайте свою собственную функцию-обертку, такую ​​как logprint64, выполняя аналогичную задачу, но при необходимости применяя типы аргументов. Замедление logprint64 для logprint займет менее часа, я думаю.

Или вы можете переписать logprint. По вашему сообщению и ответ, то logprint кажется быть в следующем виде:

#include <stdio.h> 
#include <stdarg.h> 

enum ErrCode { FATAL, MILD }; 
typedef unsigned short ULONG; 

#define MAX 100 
char Buf[MAX]; 

void logprint(enum ErrCode code, char *fmt, ...) 
{ 
    va_list aptr; 
    va_start(aptr, fmt); 
    vsprintf(Buf, fmt, aptr); 
    va_end(aptr); 
} 

int main() 
{ 
    ULONG ulMin = 97, ulMax = 99; 

    logprint(FATAL,"interval is invalid %c..%c", ulMin, ulMax); 
    printf("%s\n", Buf); 

    return(0); 
} 

Вы можете заменить его следующее определение моделирования vsprintf:

void logprint(enum ErrCode code, const char *fmt, ...) 
{ // add your types as needed 
    ULONG   h; 
    unsigned long u; 
    long   d; 
    int   i; 

    const char *p; 
    char  *buf; 
    va_list argp; 
    va_start(argp, fmt); 
    for (p = fmt, buf = Buf; *p != '\0'; p++) { 
     if (*p != '%') { 
      buf += sprintf(buf, "%c", *p); continue; 
     } 
     switch (*++p) { // change the type casting as needed 
      case 'l': 
       switch (*++p) { 
        case 'u': 
         u = (unsigned long) va_arg(argp, ULONG); 
         buf += sprintf(buf, "%lu", u); continue; 
        case 'd': 
         d = va_arg(argp, long); 
         buf += sprintf(buf, "%ld", d); continue; 
       } 
      case 'c': 
       u = va_arg(argp, unsigned long); 
       buf += sprintf(buf, "%lu", u); continue; 
      case 'd': 
       i = va_arg(argp, int); 
       buf += sprintf(buf, "%d", i); continue; 
     } 
    } 
    va_end(argp); 
} 

Надеется, что это помогает.

+0

Нет, функция использует 'va_start',' vsprintf', 'va_end' – gollum

+0

@gollum. Я изменил проводку, чтобы включить образец повторной реализации журнала, предполагающий вашу запись. –

 Смежные вопросы

  • Нет связанных вопросов^_^