aboutsummaryrefslogtreecommitdiffstats
path: root/doc/internals/Frontend.rst
blob: 3751f1e39c05c581bd31251d3ff9189a2ae77796 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.. _INT:Frontend:

Front-end
#########

Input files (or source files) are read by `files_map.ad[sb]`. Only regular files can be
read, because they are read entirely before being scanned. This simplifies the scanner,
but this also allows to have a unique index for each character in any file.
Therefore the source location is a simple 32-bit integer whose type is `Location_Type`.
From the location, `files_map` can deduce the source file (type is `Source_File_Entry`)
and then the offset in the source file.  There is a line table for each source file in
order to speed-up the conversion from file offset to line number and column number.

The scanner (file :file:`vhdl-scanner.ad[sb]`) reads the source files and creates token
from them.  The tokens are defined in file :file:`vhdl-tokens.ads`.  Tokens are scanned
one by one, so the scanner doesn't keep in memory the previous token.  Integer or
floating point numbers are special tokens because beside the token itself there is
also a variable for the value of the number.

For identifiers there is a table containing all identifiers.  This is implemented by
file :file:`name_table.ad[sb]`.  Each identifier is associated to a 32-bit number
(they are internalized).  So the number is used to reference an identifier.  About
one thousand identifiers are predefined (by :file:`std_names.ad[sb]`).  Most of
them are reserved identifiers (or keywords).  When the scanner find an identifier, it
checks if it is a keyword.  In that case it changes the token to the keyword token.

The procedure `scan` is called to get the next token.  The location of the token and
the location after the token are available to store it in the parser tree.

The main client of the scanner is the parser.
re>/****************************************************************************** * common/notifier.c * * Routines to manage notifier chains for passing status changes to any * interested routines. * * Original code from Linux kernel 2.6.27 (Alan Cox <Alan.Cox@linux.org>) */ #include <xen/config.h> #include <xen/init.h> #include <xen/notifier.h> /** * notifier_chain_register - Add notifier to a raw notifier chain * @nh: Pointer to head of the raw notifier chain * @n: New entry in notifier chain * * Adds a notifier to a raw notifier chain. * All locking must be provided by the caller. */ void __init notifier_chain_register( struct notifier_head *nh, struct notifier_block *n) { struct list_head *chain = &nh->head.chain; struct notifier_block *nb; while ( chain->next != &nh->head.chain ) { nb = list_entry(chain->next, struct notifier_block, chain); if ( n->priority > nb->priority ) break; chain = chain->next; } list_add(&n->chain, chain); } /** * notifier_chain_unregister - Remove notifier from a raw notifier chain * @nh: Pointer to head of the raw notifier chain * @n: Entry to remove from notifier chain * * Removes a notifier from a raw notifier chain. * All locking must be provided by the caller. */ void __init notifier_chain_unregister( struct notifier_head *nh, struct notifier_block *n) { list_del(&n->chain); } /** * notifier_call_chain - Informs the registered notifiers about an event. * @nh: Pointer to head of the raw notifier chain * @val: Value passed unmodified to notifier function * @v: Pointer passed unmodified to notifier function * @pcursor: If non-NULL, position in chain to start from. Also updated on * return to indicate how far notifications got before stopping. * * Calls each function in a notifier chain in turn. The functions run in an * undefined context. All locking must be provided by the caller. * * If the return value of the notifier can be and'ed with %NOTIFY_STOP_MASK * then notifier_call_chain() will return immediately, with teh return value of * the notifier function which halted execution. Otherwise the return value is * the return value of the last notifier function called. */ int notifier_call_chain( struct notifier_head *nh, unsigned long val, void *v, struct notifier_block **pcursor) { int ret = NOTIFY_DONE; struct list_head *cursor; struct notifier_block *nb; bool_t reverse = !!(val & NOTIFY_REVERSE); cursor = &(pcursor && *pcursor ? *pcursor : &nh->head)->chain; do { cursor = reverse ? cursor->prev : cursor->next; nb = list_entry(cursor, struct notifier_block, chain); if ( cursor == &nh->head.chain ) break; ret = nb->notifier_call(nb, val, v); } while ( !(ret & NOTIFY_STOP_MASK) ); if ( pcursor ) *pcursor = nb; return ret; }