docs(api): require documented public headers
This commit is contained in:
parent
624034acb5
commit
fdb1406ba2
@ -44,6 +44,11 @@
|
|||||||
- 不写重复描述简单代码行为的注释。
|
- 不写重复描述简单代码行为的注释。
|
||||||
- 如果代码依赖硬件手册、启动协议、调用顺序或特殊寄存器状态,应写明约束。
|
- 如果代码依赖硬件手册、启动协议、调用顺序或特殊寄存器状态,应写明约束。
|
||||||
- 如果一个实现是临时简化,应写清楚后续替换边界,而不是写成永久接口。
|
- 如果一个实现是临时简化,应写清楚后续替换边界,而不是写成永久接口。
|
||||||
|
- 公共头文件 `include/tianole/*.h` 中的函数声明必须使用 Linux kernel-doc 风格块注释。
|
||||||
|
- 公共函数注释至少说明函数职责、关键参数、返回值或副作用;不要只复述函数名。
|
||||||
|
- 公共函数声明和前一个声明/注释块之间必须留一个空行,避免 API 挤在一起。
|
||||||
|
- 私有 `static` 小函数不要求每个都写函数头注释;只有逻辑、数据流、锁语义或硬件约束不明显时才写。
|
||||||
|
- 多行注释要控制行宽,优先写职责、数据流和调用约束,而不是描述每一行代码。
|
||||||
|
|
||||||
## C 格式
|
## C 格式
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,63 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_early_log_init() - Initialize architecture early log devices.
|
||||||
|
*
|
||||||
|
* Provides the backend setup used by the generic early log front end.
|
||||||
|
*/
|
||||||
void arch_early_log_init(void);
|
void arch_early_log_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_early_log_putc() - Emit one character through arch early log devices.
|
||||||
|
* @ch: Character to write.
|
||||||
|
*
|
||||||
|
* This keeps port I/O and other architecture details out of generic logging.
|
||||||
|
*/
|
||||||
void arch_early_log_putc(char ch);
|
void arch_early_log_putc(char ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_halt_forever() - Stop execution permanently.
|
||||||
|
*
|
||||||
|
* Used by panic and unrecoverable paths after diagnostics have been emitted.
|
||||||
|
*/
|
||||||
void arch_halt_forever(void) __attribute__((noreturn));
|
void arch_halt_forever(void) __attribute__((noreturn));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_irq_save() - Save interrupt state and disable maskable interrupts.
|
||||||
|
*
|
||||||
|
* Return: Architecture flags needed by arch_irq_restore().
|
||||||
|
*/
|
||||||
uint64_t arch_irq_save(void);
|
uint64_t arch_irq_save(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_irq_restore() - Restore a previously saved interrupt state.
|
||||||
|
* @flags: Value returned by arch_irq_save().
|
||||||
|
*
|
||||||
|
* This is the backend for interrupt-safe spinlocks on the current CPU.
|
||||||
|
*/
|
||||||
void arch_irq_restore(uint64_t flags);
|
void arch_irq_restore(uint64_t flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_page_table_uses_page() - Check whether a page backs page tables.
|
||||||
|
* @page: Physical page base address.
|
||||||
|
*
|
||||||
|
* Return: Non-zero if the architecture page-table layer owns the page.
|
||||||
|
*/
|
||||||
int arch_page_table_uses_page(uint64_t page);
|
int arch_page_table_uses_page(uint64_t page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_traps_init() - Initialize architecture trap and IRQ entry tables.
|
||||||
|
*
|
||||||
|
* Sets up descriptor tables and entry points before devices enable IRQs.
|
||||||
|
*/
|
||||||
void arch_traps_init(void);
|
void arch_traps_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_timer_init() - Initialize the architecture timer backend.
|
||||||
|
*
|
||||||
|
* Connects the hardware timer to the generic timer and scheduler path.
|
||||||
|
*/
|
||||||
void arch_timer_init(void);
|
void arch_timer_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,11 +3,53 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_log_init() - Initialize early logging backends.
|
||||||
|
*
|
||||||
|
* Sets up the architecture-provided early output path. This must be usable
|
||||||
|
* before heap, scheduler, VFS or normal drivers exist.
|
||||||
|
*/
|
||||||
void early_log_init(void);
|
void early_log_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_log_putc() - Write one character to every early log backend.
|
||||||
|
* @ch: Character to emit.
|
||||||
|
*
|
||||||
|
* This is the byte-level output path used by the string and number helpers.
|
||||||
|
*/
|
||||||
void early_log_putc(char ch);
|
void early_log_putc(char ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_log_puts() - Write a NUL-terminated string to early logs.
|
||||||
|
* @text: String to emit. A NULL pointer is ignored by callers only if they
|
||||||
|
* explicitly check before calling.
|
||||||
|
*
|
||||||
|
* The function does not allocate memory and is safe for early boot diagnostics.
|
||||||
|
*/
|
||||||
void early_log_puts(const char *text);
|
void early_log_puts(const char *text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_log_u64_hex() - Write a 64-bit value in hexadecimal form.
|
||||||
|
* @value: Value to print.
|
||||||
|
*
|
||||||
|
* Used by trap, memory and boot diagnostics where libc formatting is absent.
|
||||||
|
*/
|
||||||
void early_log_u64_hex(uint64_t value);
|
void early_log_u64_hex(uint64_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_log_u64_decimal() - Write a 64-bit value in decimal form.
|
||||||
|
* @value: Value to print.
|
||||||
|
*
|
||||||
|
* Used for counters and boot statistics without depending on printf support.
|
||||||
|
*/
|
||||||
void early_log_u64_decimal(uint64_t value);
|
void early_log_u64_decimal(uint64_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* panic() - Print a fatal error and stop the machine.
|
||||||
|
* @message: Panic reason to include in the early log.
|
||||||
|
*
|
||||||
|
* This path must work even when normal kernel services are not initialized.
|
||||||
|
*/
|
||||||
void panic(const char *message) __attribute__((noreturn));
|
void panic(const char *message) __attribute__((noreturn));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -5,6 +5,14 @@
|
|||||||
|
|
||||||
typedef void (*irq_handler_t)(uint8_t irq, void *data);
|
typedef void (*irq_handler_t)(uint8_t irq, void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* irq_register() - Register a handler for an external IRQ line.
|
||||||
|
* @irq: IRQ line number in the generic IRQ namespace.
|
||||||
|
* @handler: Function called when the IRQ is dispatched.
|
||||||
|
* @data: Opaque handler data passed back during dispatch.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, negative value on failure.
|
||||||
|
*/
|
||||||
int irq_register(uint8_t irq, irq_handler_t handler, void *data);
|
int irq_register(uint8_t irq, irq_handler_t handler, void *data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
#include <tianole/boot_info.h>
|
#include <tianole/boot_info.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kernel_report_boot_state() - Log the boot handoff state.
|
||||||
|
* @boot_info: Firmware-independent boot data passed to the kernel.
|
||||||
|
*
|
||||||
|
* Prints early diagnostics used to verify the bootloader-to-kernel contract.
|
||||||
|
*/
|
||||||
void kernel_report_boot_state(const boot_info_t *boot_info);
|
void kernel_report_boot_state(const boot_info_t *boot_info);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -15,15 +15,84 @@ typedef uint64_t virt_addr_t;
|
|||||||
#define PAGE_WRITABLE (1ull << 1)
|
#define PAGE_WRITABLE (1ull << 1)
|
||||||
#define PAGE_NO_EXECUTE (1ull << 63)
|
#define PAGE_NO_EXECUTE (1ull << 63)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_init() - Initialize the generic memory manager.
|
||||||
|
* @boot_info: Bootloader-provided memory map and handoff data.
|
||||||
|
*
|
||||||
|
* Converts boot memory information into Tianole-owned page allocator state.
|
||||||
|
*/
|
||||||
void mm_init(const boot_info_t *boot_info);
|
void mm_init(const boot_info_t *boot_info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* alloc_page() - Allocate one physical page.
|
||||||
|
*
|
||||||
|
* Return: Physical page base address, or 0 when no page is available.
|
||||||
|
*/
|
||||||
phys_addr_t alloc_page(void);
|
phys_addr_t alloc_page(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* free_page() - Return one physical page to the allocator.
|
||||||
|
* @page: Physical page base address previously returned by alloc_page().
|
||||||
|
*
|
||||||
|
* The page must not still be mapped or owned by another subsystem.
|
||||||
|
*/
|
||||||
void free_page(phys_addr_t page);
|
void free_page(phys_addr_t page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kmalloc() - Allocate small kernel heap memory.
|
||||||
|
* @size: Number of bytes requested.
|
||||||
|
*
|
||||||
|
* Return: Kernel virtual pointer, or NULL when allocation fails.
|
||||||
|
*/
|
||||||
void *kmalloc(size_t size);
|
void *kmalloc(size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kfree() - Free memory allocated by kmalloc().
|
||||||
|
* @ptr: Pointer returned by kmalloc(), or NULL.
|
||||||
|
*
|
||||||
|
* Releases the allocation back to the kernel heap.
|
||||||
|
*/
|
||||||
void kfree(void *ptr);
|
void kfree(void *ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* map_page() - Map one virtual page to one physical page.
|
||||||
|
* @virt: Virtual page address.
|
||||||
|
* @phys: Physical page address.
|
||||||
|
* @flags: Generic page flags such as PAGE_WRITABLE.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, negative value on failure.
|
||||||
|
*/
|
||||||
int map_page(virt_addr_t virt, phys_addr_t phys, uint64_t flags);
|
int map_page(virt_addr_t virt, phys_addr_t phys, uint64_t flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unmap_page() - Remove one virtual page mapping.
|
||||||
|
* @virt: Virtual page address to unmap.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, negative value on failure.
|
||||||
|
*/
|
||||||
int unmap_page(virt_addr_t virt);
|
int unmap_page(virt_addr_t virt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virt_to_phys() - Resolve a virtual address to a physical address.
|
||||||
|
* @virt: Virtual address to query.
|
||||||
|
* @phys: Output storage for the resolved physical address.
|
||||||
|
*
|
||||||
|
* Return: 0 when a mapping exists, negative value otherwise.
|
||||||
|
*/
|
||||||
int virt_to_phys(virt_addr_t virt, phys_addr_t *phys);
|
int virt_to_phys(virt_addr_t virt, phys_addr_t *phys);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* heap_init() - Initialize the kernel heap.
|
||||||
|
*
|
||||||
|
* Sets up kmalloc()/kfree() after page allocation and page tables are ready.
|
||||||
|
*/
|
||||||
void heap_init(void);
|
void heap_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* page_table_selftest() - Run boot-time page table checks.
|
||||||
|
*
|
||||||
|
* Verifies map, unmap and address translation behavior during early boot.
|
||||||
|
*/
|
||||||
void page_table_selftest(void);
|
void page_table_selftest(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -38,24 +38,127 @@ struct thread {
|
|||||||
char name[32];
|
char name[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sched_init() - Initialize scheduler core state.
|
||||||
|
*
|
||||||
|
* Creates scheduler data structures and runs scheduler selftests before
|
||||||
|
* threads are started.
|
||||||
|
*/
|
||||||
void sched_init(void);
|
void sched_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kernel_thread_create() - Create a kernel thread.
|
||||||
|
* @name: Human-readable thread name used by diagnostics.
|
||||||
|
* @entry: Thread entry point.
|
||||||
|
* @arg: Opaque argument passed to @entry.
|
||||||
|
*
|
||||||
|
* Return: Thread object on success, or NULL when allocation fails.
|
||||||
|
*/
|
||||||
struct thread *kernel_thread_create(
|
struct thread *kernel_thread_create(
|
||||||
const char *name, kernel_thread_entry_t entry, void *arg);
|
const char *name, kernel_thread_entry_t entry, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kernel_thread_exit() - Terminate the current kernel thread.
|
||||||
|
*
|
||||||
|
* Marks the current thread dead and yields forever until the scheduler
|
||||||
|
* switches away and later reclaims it from a safe context.
|
||||||
|
*/
|
||||||
void kernel_thread_exit(void) __attribute__((noreturn));
|
void kernel_thread_exit(void) __attribute__((noreturn));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sched_start() - Start scheduler demo threads and enter scheduling.
|
||||||
|
*
|
||||||
|
* Creates the idle thread and current boot-stage scheduler demonstration.
|
||||||
|
*/
|
||||||
void sched_start(void) __attribute__((noreturn));
|
void sched_start(void) __attribute__((noreturn));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sched_tick() - Notify the scheduler about a timer tick.
|
||||||
|
* @tick: Current generic timer tick.
|
||||||
|
*
|
||||||
|
* Wakes sleeping threads whose deadlines expired and requests rescheduling.
|
||||||
|
*/
|
||||||
void sched_tick(uint64_t tick);
|
void sched_tick(uint64_t tick);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sched_irq_exit() - Consume pending reschedule work after IRQ handling.
|
||||||
|
*
|
||||||
|
* Keeps timer IRQ handling short by moving the actual scheduling decision to
|
||||||
|
* a common interrupt-exit boundary.
|
||||||
|
*/
|
||||||
void sched_irq_exit(void);
|
void sched_irq_exit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sched_yield() - Yield the CPU to another runnable kernel thread.
|
||||||
|
*
|
||||||
|
* Performs cooperative scheduling and context switching when another runnable
|
||||||
|
* thread is available.
|
||||||
|
*/
|
||||||
void sched_yield(void);
|
void sched_yield(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sched_sleep() - Sleep the current thread for a number of ticks.
|
||||||
|
* @ticks: Number of timer ticks to sleep.
|
||||||
|
*
|
||||||
|
* Marks the current thread sleeping and yields until the timer path wakes it.
|
||||||
|
*/
|
||||||
void sched_sleep(uint64_t ticks);
|
void sched_sleep(uint64_t ticks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait_queue_init() - Initialize a wait queue.
|
||||||
|
* @queue: Wait queue storage owned by the caller.
|
||||||
|
*
|
||||||
|
* Resets queue links and the internal interrupt-safe lock.
|
||||||
|
*/
|
||||||
void wait_queue_init(struct wait_queue *queue);
|
void wait_queue_init(struct wait_queue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait_queue_sleep() - Sleep until another thread wakes the queue.
|
||||||
|
* @queue: Queue to sleep on.
|
||||||
|
*
|
||||||
|
* Enqueues the current thread, marks it waiting and yields until wakeup.
|
||||||
|
*/
|
||||||
void wait_queue_sleep(struct wait_queue *queue);
|
void wait_queue_sleep(struct wait_queue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait_queue_wait() - Sleep until a condition becomes true.
|
||||||
|
* @queue: Queue used for wakeups.
|
||||||
|
* @condition: Predicate checked before and after sleeping.
|
||||||
|
* @arg: Opaque predicate argument.
|
||||||
|
*
|
||||||
|
* Return: 0 when the condition is true, negative value on invalid input.
|
||||||
|
*/
|
||||||
int wait_queue_wait(
|
int wait_queue_wait(
|
||||||
struct wait_queue *queue, wait_condition_t condition, void *arg);
|
struct wait_queue *queue, wait_condition_t condition, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait_queue_wait_timeout() - Sleep until a condition or timeout.
|
||||||
|
* @queue: Queue used for wakeups.
|
||||||
|
* @condition: Predicate checked before and after sleeping.
|
||||||
|
* @arg: Opaque predicate argument.
|
||||||
|
* @ticks: Maximum number of timer ticks to wait.
|
||||||
|
*
|
||||||
|
* Return: 0 when the condition is true, negative value on timeout or error.
|
||||||
|
*/
|
||||||
int wait_queue_wait_timeout(struct wait_queue *queue,
|
int wait_queue_wait_timeout(struct wait_queue *queue,
|
||||||
wait_condition_t condition,
|
wait_condition_t condition,
|
||||||
void *arg,
|
void *arg,
|
||||||
uint64_t ticks);
|
uint64_t ticks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait_queue_wake_one() - Wake one thread from a wait queue.
|
||||||
|
* @queue: Queue containing waiting threads.
|
||||||
|
*
|
||||||
|
* Removes the oldest waiter and marks it ready if it is still waitable.
|
||||||
|
*/
|
||||||
void wait_queue_wake_one(struct wait_queue *queue);
|
void wait_queue_wake_one(struct wait_queue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait_queue_wake_all() - Wake every thread from a wait queue.
|
||||||
|
* @queue: Queue containing waiting threads.
|
||||||
|
*
|
||||||
|
* Drains the queue and marks every waitable thread ready.
|
||||||
|
*/
|
||||||
void wait_queue_wake_all(struct wait_queue *queue);
|
void wait_queue_wake_all(struct wait_queue *queue);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -12,7 +12,23 @@ struct spinlock {
|
|||||||
0 \
|
0 \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spin_lock_irqsave() - Acquire a single-CPU interrupt-safe spinlock.
|
||||||
|
* @lock: Lock to acquire.
|
||||||
|
* @flags: Storage for the previous interrupt state.
|
||||||
|
*
|
||||||
|
* Disables interrupts before taking the lock so IRQ and thread context can
|
||||||
|
* share early kernel data structures.
|
||||||
|
*/
|
||||||
void spin_lock_irqsave(struct spinlock *lock, uint64_t *flags);
|
void spin_lock_irqsave(struct spinlock *lock, uint64_t *flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spin_unlock_irqrestore() - Release an interrupt-safe spinlock.
|
||||||
|
* @lock: Lock to release.
|
||||||
|
* @flags: Interrupt state returned by spin_lock_irqsave().
|
||||||
|
*
|
||||||
|
* Restores the caller's original interrupt state after releasing the lock.
|
||||||
|
*/
|
||||||
void spin_unlock_irqrestore(struct spinlock *lock, uint64_t flags);
|
void spin_unlock_irqrestore(struct spinlock *lock, uint64_t flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,7 +3,18 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* timer_tick() - Advance generic timer state by one hardware tick.
|
||||||
|
*
|
||||||
|
* Called by the architecture timer IRQ handler before scheduler tick handling.
|
||||||
|
*/
|
||||||
void timer_tick(void);
|
void timer_tick(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* timer_ticks() - Read the generic monotonic tick counter.
|
||||||
|
*
|
||||||
|
* Return: Number of timer ticks observed since timer initialization.
|
||||||
|
*/
|
||||||
uint64_t timer_ticks(void);
|
uint64_t timer_ticks(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -72,6 +72,16 @@ def source_files(files: set[Path]) -> list[Path]:
|
|||||||
return sorted(path for path in files if path.suffix in (".c", ".h"))
|
return sorted(path for path in files if path.suffix in (".c", ".h"))
|
||||||
|
|
||||||
|
|
||||||
|
def public_headers(files: set[Path]) -> list[Path]:
|
||||||
|
return sorted(
|
||||||
|
path
|
||||||
|
for path in files
|
||||||
|
if path.suffix == ".h"
|
||||||
|
and len(path.parts) == 3
|
||||||
|
and path.parts[:2] == ("include", "tianole")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def c_files(files: set[Path]) -> list[Path]:
|
def c_files(files: set[Path]) -> list[Path]:
|
||||||
return sorted(
|
return sorted(
|
||||||
path
|
path
|
||||||
@ -99,6 +109,108 @@ def check_no_relative_parent_includes(root: Path, files: list[Path]) -> list[str
|
|||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def is_function_declaration_start(line: str) -> bool:
|
||||||
|
stripped = line.strip()
|
||||||
|
|
||||||
|
if stripped == "" or stripped.startswith("#"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if stripped.startswith(("typedef ", "struct ", "enum ", "union ")):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if "(" not in stripped or stripped.startswith("*"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if "(*" in stripped or stripped.endswith("{"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def collect_function_declarations(lines: list[str]) -> list[tuple[int, int, str]]:
|
||||||
|
decls = []
|
||||||
|
index = 0
|
||||||
|
|
||||||
|
while index < len(lines):
|
||||||
|
if not is_function_declaration_start(lines[index]):
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
start = index
|
||||||
|
text = lines[index].strip()
|
||||||
|
while ";" not in lines[index]:
|
||||||
|
index += 1
|
||||||
|
if index >= len(lines):
|
||||||
|
break
|
||||||
|
text += " " + lines[index].strip()
|
||||||
|
|
||||||
|
if index < len(lines):
|
||||||
|
decls.append((start, index, text))
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
return decls
|
||||||
|
|
||||||
|
|
||||||
|
def has_kernel_doc_before(lines: list[str], start: int) -> bool:
|
||||||
|
index = start - 1
|
||||||
|
|
||||||
|
while index >= 0 and lines[index].strip() == "":
|
||||||
|
index -= 1
|
||||||
|
|
||||||
|
if index < 0 or lines[index].strip() != "*/":
|
||||||
|
return False
|
||||||
|
|
||||||
|
while index >= 0:
|
||||||
|
if lines[index].strip().startswith("/**"):
|
||||||
|
return True
|
||||||
|
index -= 1
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def has_blank_line_before_doc(lines: list[str], start: int) -> bool:
|
||||||
|
index = start - 1
|
||||||
|
|
||||||
|
while index >= 0 and lines[index].strip() == "":
|
||||||
|
index -= 1
|
||||||
|
|
||||||
|
if index < 0 or lines[index].strip() != "*/":
|
||||||
|
return True
|
||||||
|
|
||||||
|
while index >= 0 and not lines[index].strip().startswith("/**"):
|
||||||
|
index -= 1
|
||||||
|
|
||||||
|
if index <= 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return lines[index - 1].strip() == ""
|
||||||
|
|
||||||
|
|
||||||
|
def check_public_header_function_docs(root: Path, files: list[Path]) -> list[str]:
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
for path in files:
|
||||||
|
lines = read_text(root, path).splitlines()
|
||||||
|
for start, _end, text in collect_function_declarations(lines):
|
||||||
|
line_no = start + 1
|
||||||
|
name = text.split("(", 1)[0].split()[-1].lstrip("*")
|
||||||
|
if not has_kernel_doc_before(lines, start):
|
||||||
|
errors.append(
|
||||||
|
f"{path}:{line_no}: public function '{name}' needs "
|
||||||
|
"a kernel-doc comment immediately before it"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not has_blank_line_before_doc(lines, start):
|
||||||
|
errors.append(
|
||||||
|
f"{path}:{line_no}: public function '{name}' "
|
||||||
|
"comment block must be separated by a blank line"
|
||||||
|
)
|
||||||
|
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
def check_selftests_are_centralized(files: list[Path]) -> list[str]:
|
def check_selftests_are_centralized(files: list[Path]) -> list[str]:
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
@ -201,6 +313,7 @@ def main() -> int:
|
|||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
errors.extend(check_no_relative_parent_includes(root, source_files(files)))
|
errors.extend(check_no_relative_parent_includes(root, source_files(files)))
|
||||||
|
errors.extend(check_public_header_function_docs(root, public_headers(files)))
|
||||||
errors.extend(check_selftests_are_centralized(c_files(files)))
|
errors.extend(check_selftests_are_centralized(c_files(files)))
|
||||||
errors.extend(check_makefile_source_lists(root, files, all_mode))
|
errors.extend(check_makefile_source_lists(root, files, all_mode))
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user