Главная » Статьи » FreePascal |
Для подготовки справочной документации для модулей в состав пакета FreePascal входят две утилиты:
И вот при использовании этих утилит я обнаружил, что две одинаковых директивы IfDef условной компиляции: {$Define def1} обрабатываются этими утилитами по разному: для первой директивы блок кода до директивы EndIf — обрабатывался, для второй — пропускался. Различие между директивами было в том, что во втором случае между идентификатором def1 и закрывающейся скобкой } был расположен пробел. Такое же различие в работе наблюдалось и для директивы IfNDef. При этом компилятор FPC обрабатывал абсолютно одинаково в полном соответствии с описанием, которое допускает наличие комментария между условным идентификатором (именем) и скобкой, например, {$ifdef def1 this is a comment}. Из исходных файлов MAKESKEL и FPDOC было видно, что для парсинга исходного кода эти утилиты используют модули пакета fcl-passrc — Pascal parsing parts of Free Component Libraries (FCL). Конкретно, для лексического анализа исходного кода Pascal применяется класс TPascalScanner, реализованный в файле pscanner.pp. Поиск причины некорректной обработки был облегчен тем фактом, что директива Define корректно отрабатывала и при наличии комментария между условным идентификатором и скобкой }. В классе TPascalScanner парсинг директив Define, IfDef и IfNDef выполняется в следующих методах: HandleDefine, HandleIFDEF и HandleIFNDEF, которым передается в виде параметра весь остаток строки, начиная с условного идентификатора до скобки }. Эти методы имеют следующий код: 2487 procedure TPascalScanner.HandleDefine(Param: String); 2630 procedure TPascalScanner.HandleIFDEF(const AParam: String); 2652 procedure TPascalScanner.HandleIFNDEF(const AParam: String); Отсюда видно, что при добавлении условного имени параметр, в котором передается методу HandleDefine весь остаток строки, начиная с условного идентификатора до скобки }, предварительно обрабатывается функцией GetMacroName. Исходный код этой функции имеет следующий вид: 3527 function TPascalScanner.GetMacroName(const Param: String): String; то есть в ней происходит выделение только условного имени, все оставшиеся символы отбрасываются. В методах же HandleIFDEF и HandleIFNDEF для проверки определено ли условное имя функции IsDefined передается исходный параметр, который может содержать дополнительные символы после имени. После коррекции строк 2637 и 2659 в методах HandleIFDEF и HandleIFNDEF, соответственно, следующим образом: | |
Просмотров: 184 | Комментарии: 1 | |
Всего комментариев: 1 | |
| |