Похоже, вывод дизассемблера следует сделать несколько иначе, чем планировалось. Т.к. каждый хочет выводить результаты на свой лад, необходимо сделать вывод более гибким. Archer предложил сделать вывод с помощью форматирующей строки, но это не очень гибко, т.к. если кому-то приспичит выводить непосредственные операнды, например, в четверичной системе счисления, то мне придется дописывать распознавание спецификатора четверичной системы. Другой вариант -- принимать от пользователя массив обработчиков, в котором каждый обработчик отвечает за вывод элемента инструкции. Обработчики вызываются из Mediana. Это позволит пользователю перегружать ф-ии вывода а ля С++. Подход представляется мне так:
int dump_handler(struct STREAM * const stream, struct INSTRUCTION *instr, int operand, int param1, int param2);
int (*handlers)[HANDLERS_NUM](struct STREAM * const, struct INSTRUCTION *, int, int, int);
handlers[0] = dump_prefix;
handlers[1] = dump_mnemonic;
handlers[2] = dump_mnem_op_space;
...
medi_dump(..., handlers, ...);
Возможные обработчики:
prefix //префикс инструкции.
mnem //мнемоника.
mnem_op_space //разделитель мнемоники и операндов.
op_op_space //разделитель операндов.
reg //операнд-регистр.
imm //непосредственное значение.
dir //операнд-дальний адрес.
addr_size //квалификатор размера адреса.
addr_open_brace //открывающая скобка операнда-адреса.
addr_seg_reg //сегментный регистр адреса.
addr_base //базовый регистр адреса.
addr_idx //индексный регистр адреса.
addr_multiplier //множитель индексного регистра адреса.
addr_disp //смещение.
addr_base_idx_space //разделитель базового и индексных регистров.
addr_idx_multiplier_space //разделитель индексного регистра и множителя.
addr_multiplier_disp_space //разделитель множителя и смещения.
addr_close_brace //закрывающая скобка.
Если в массиве передано значение NULL, то Mediana вызовет обработчик по умолчанию. Кроме того, думаю, стоит добавить возможность вызова обработчика по умолчанию и передачу результатов его работы в пользовательский обработчик. Не уверен, что необходимы обработчики разделителей, разделители можно выводить в обработчиках предшествующего элемента.
Плюс такого подхода: не требуются никакие опции для вывода, достигается максимальная гибкость. Однако есть и минусы:
- Придется открыть большое число внутренних ф-ий и структур. Например, служебная структура STREAM должна передавться в пользовательский обработчик, но следует строго запретить модификацию этой структуры пользователем. Кроме того придется открыть большое число массивов указателей на строки для удобства написания пользовательских ф-ий вывода.
- Для вывода результата необходимо использовать только ф-ии вывода значений, определенные в Mediana. (Вероятно, это получится немного упростить, но надо обдумать.) Это связано с тем, что Mediana всегда ведет подсчет выведенных символов и возвращает их пользователю в качестве результата работы ф-ии medi_dump. Это позволяет перезапросить буфер, отведенный под строку вывода, если он слишком мал.
- Возрастает общая сложность использования дизассемблера, а значит повышается вероятность ошибок.
Буду рад комментариям и предложениям.