static void put_stabs(const char *str, int type, int other, int desc, unsigned long value) В stab_section создается символ. Если передана строка, даже пустая, то в поле символа n_strx, записывается адрес троки созданной с помощью put_elf_str() иначе в него записывате 0. Поля символа n_type, n_other, n_desc, n_value заполняются переданными значениями. Все файлы, имена которых переданны на вход компилятора обрабатываются с помощью tcc_add_file_internal(), если указан флаг TCC_OUTPUT_PREPROCESS. Либо с помощью tcc_add_library(), если имя файла начинается на '-' Если два предыдущих условия не сработали используется tcc_add_file() static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) tcc_fileextension() возвращает указатель на позицию в строке, где начинается разишерение файла, начиная с точки. Позиция сдвигается на один символ, чтобы в последующем начать сверку с буквы. BufferedFile *tcc_open(TCCState *s1, const char *filename) tcc_open() открывает фал на чтение в режиме O_BINARY или предполатет что файл будет считан со стандартного ввода. Результат функции — ссылка на структуру BufferedFile. Для нее выделяется место, в нее записывается идентификатор открытого файла или 0, если файл читается со стандартного ввода. Поле buffer, стразу после выделения экземпляра структуры, это указатель на массив из 8192 байт. Поля-указатели buf_ptr и buf_end в этот момент указывают на начало данного массива. В это же место записывается CH_EOB Заполняется поле filename, для Windows вызывается normalize_slashes(), которя заменет '\\' на '/' Количестово строк (поле line_num) начитанеся с единицы, счетчик макросов ifndef_macro с нуля. Указатель ifdef_stack_ptr на s1->ifdef_stack_ptr. Если установлен флаг AFF_PREPROCESS (опции компилятора, выклюшиши TCC_OUTPUT_PREPROCESS), вызывается tcc_preprocess() иначе tcc_compile() Если компилятор собран с поддрежкой ассемблирования, то вызывается tcc_assemble() для *.s и *.S (preprocessed or not во втором параметре). Далее вызывается pe_load_def_file() для загрузки библиотек *.def Если компилятор собран без поддержки TCC_TARGET_PE или расширение файла не "def", проискходит чтение структуры Elf32_Ehdr с контролем ошибки чтения. Если в заголовке присутствуют сигнатуры ELFMAG0, ELFMAG1, ELFMAG2 и ELFMAG3, то происходит следующая обработка: сбрасывается счетчик количества строк. Если поле типа ELF-файла содержит ET_REL, то вызывается tcc_load_object_file(), если ET_DYN, то в зависимости от типа работы компилятора файл загружается с помощью dlopen(), для TCC_OUTPUT_MEMORY или tcc_load_dll() для остальных. Проверяется заголовок на сигнатуру ARMAG вызывается tcc_load_archive() если она находится. Если это файл ресурсов,проверяется с помощью pe_test_res_file(), происходит загрузка — pe_load_res_file(). Если проверка показала, что это не файл ресурсов, компилятор попытается выполнить tcc_load_ldscript() В конце файл закрывается, ссылка на текущий файл восстанавливается из saved_file. static int tcc_preprocess(TCCState *s1) Вызывается preprocess_init() static void preprocess_init(TCCState *s1) указатели переданного состояния компилятора include_stack_ptr и ifdef_stack_ptr устанавливаются на начало соссоветстующих стеков. Текущий файл (указатель file) тоже имеет поле ifdef_stack_ptr, он устанавливается на тот же стек. Стек vstack, соделжащий структуры SValue имеет вершину vtop, она устанавливается в его конец. Поле pack_stack_ptr состояния компилятора устанавливается на соостветствущий стек. В его начало записывается ноль. Стек define_stack состоящий из структур Sym имеет вершину define_start Выставляются флаги токенов TOK_FLAG_BOL и TOK_FLAG_BOF Выставляются флаги парсинга PARSE_FLAG_ASM_COMMENT, PARSE_FLAG_PREPROCESS и PARSE_FLAG_LINEFEED Устанавливется флаг last_is_space. Вызывается функция next() Начинается бесконечный цикл, который завершается если выставлен TOK_EOF. Если выставлен TOK_LINEFEED, то устанавливается флаг last_is_space. Если ни первый ни второй из упомянутых токенов не выставлен то last_is_space сбрасывается. Если он был выставлен, то перед сбросом вызывается fputc(), чтобы добавить пробел в файл, указанный в поле outfile структуры TCCState, переданной в качестве параметра. Кроме этих проверок, на каждом шаге вызывается fputs(), чтобы добавить в тот же файл строку полученую с помощью get_tok_str() для текущего токена. Так же на каждом шаге вызывается next() По оконьчании цикала вызывается free_defines(). Она поледовательно вызывает tok_str_free() для всех структуру в цепочке define_start, если поле c указывает на данные. Если с символом связан токен (поле v), то проверяется есть ли соответсвие в массиве table_ident. Если есть, поле sym_define данного элемента обнуляется. Освобождается текущий элемент с помощью sym_free(). Ссылка на текущий элемент обновлется предварительно сохраненненной ссылкой на следующий элемент в цепочке. В конце функции указатель на define_stack обновляется ссылкой переданной в качестве параметра. |