[IRC-Dev CVS] [CVS] Module ircd-ircdev: Change committed
Brought to you by:
zolty
From: Toni G. <zo...@us...> - 2005-01-05 16:33:01
|
CVSROOT : /cvsroot/irc-dev Module : ircd-ircdev Commit time: 2005-01-05 16:32:53 UTC Added files: doc/en/api/events.txt doc/en/api/features.txt doc/en/api/gline.txt doc/en/api/ircd_snprintf.txt doc/en/api/joinbuf.txt doc/en/api/jupe.txt doc/en/api/modebuf.txt doc/en/api/motd.txt doc/en/api/msgq.txt doc/en/api/privileges.txt doc/en/api/send.txt Log message: Documentacion API en ingles. ---------------------- diff included ---------------------- Index: ircd-ircdev/doc/en/api/events.txt diff -u /dev/null ircd-ircdev/doc/en/api/events.txt:1.1 --- /dev/null Wed Jan 5 08:32:54 2005 +++ ircd-ircdev/doc/en/api/events.txt Wed Jan 5 08:32:43 2005 @@ -0,0 +1,816 @@ +The IRC server is built around an event loop. Until the u2.10.11 +release, this event loop has been rather ad-hoc; timed events are +hard-coded in, signals are handled inside the signal handler, etc. +All of this has changed with u2.10.11. A new subsystem, the events +subsystem, has been introduced; the new subsystem contains a +generalization of the concept of an event. An event is a signal, the +expiration of a timer, or some form of activity on a network socket. +This new subsystem has the potential to vastly simplify the code that +is arguably the core of any network program, and makes it much simpler +to support more exotic forms of network activity monitoring than the +conventional select() and poll() calls. + +The primary concepts that the events subsystem works with are the +"event," represented by a struct Event, and the "generator." There +are three types of generators: sockets, represented by struct Socket; +signals, represented by struct Signal; and timers, represented by +struct Timer. Each of these generators will be described in turn. + +Signals + +The signal is perhaps the simplest generator in the entire events +subsystem. Basically, instead of setting a signal handler, the +function signal_add() is called, specifying a function to be called +when a given signal is detected. Most importantly, that call-back +function is called _outside_ the context of a signal handler, +permitting the call-back to use more exotic functions that are +anathema within a signal handler, such as MyMalloc(). Once a +call-back for a signal has been established, it cannot be deleted; +this design decision was driven by the fact that ircd never changes +its signal handlers. + +Whenever a signal is received, an event of type ET_SIGNAL is +generated, and that event is passed to the event call-back function +specified in the signal_add() call. + +Timers + +Execution of the call-back functions for a timer occur when that timer +_expires_; when a timer expires depends on the type of timer and the +expiration time that was used for that timer. A TT_ABSOLUTE timer, +for instance, expires at exactly the time given as the expiration +time. This time is a standard UNIX time_t value, measuring seconds +since the UNIX epoch. The TT_ABSOLUTE timer type is complemented by +the TT_RELATIVE timer; the time passed as its expiration time is +relative to the current time. If a TT_RELATIVE timer is given an +expiration time of 5, for instance, it will expire 5 seconds after the +present time. Internally, TT_RELATIVE timers are converted into +TT_ABSOLUTE timers, with the expiration time adjusted by addition of +the current time. + +Those two types of timers, TT_ABSOLUTE and TT_RELATIVE, are +single-shot timers. Once they expire, they are removed from the timer +list unless re-added by the event call-back or through some other +mechanism. There is another type of timer, however, the TT_PERIODIC +timer, that is not removed from the timer list. TT_PERIODIC timers +are similar to TT_RELATIVE timers, in that one passes in the expire +time as a relative number of seconds, but when they expire, they are +re-added to the timer list with the same relative expire time. This +means that a TT_PERIODIC timer with an expire time of 5 seconds that +is set at 11:50:00 will have its call-back called at 11:50:05, +11:50:10, 11:50:15, and so on. + +Timers have to be run by the event engines explicitly by calling +timer_run() on the generator list passed to the engine event loop. +In addition, engines may determine the next (absolute) time that a +timer needs to be run by calling the timer_next() macro; this may be +used to set a timeout on the engine's network activity monitoring +function. Engines are described in detail below. + +When a timer expires, an event of ET_EXPIRE is generated, and the +call-back function is called. When a timer is destroyed, either as +the result of an expiration or as a result of an explicit timer_del() +call, an event of ET_DESTROY is generated, notifying the call-back +that the struct Timer can be deallocated. + +Sockets + +Perhaps the most complicated event generator in all of the event +system is the socket, as described by struct Socket. This single +classification covers datagram sockets and stream sockets. To +differentiate the different kinds of sockets, there is a socket state +associated with each socket. The available states are SS_CONNECTING, +which indicates that a particular socket is in the process of +completing a non-blocking connect(); SS_LISTENING, which indicates +that a particular socket is a listening socket; SS_CONNECTED, which is +the state of every other stream socket; SS_DATAGRAM, which is an +ordinary datagram socket, and SS_CONNECTDG, which describes a +connected datagram socket. (The SS_NOTSOCK state is for the internal +use of the events system and will not be described here.) + +In addition to the socket states, there's also an event mask for each +socket; this set of flags is used to tell the events subsystem what +events the application is interested in for the socket. For +SS_CONNECTING and SS_LISTENING sockets, this events mask has no +meaning, but on the other socket states, the event mask is used to +determine if the application is interested in readable +(SOCK_EVENT_READABLE) or writable (SOCK_EVENT_WRITABLE) indications. + +Most of the defined event types have to do with socket generators. +When a socket turns up readable, for instance, an event of type +ET_READ is generated. Similarly, ET_WRITE is generated when a socket +can be written to. The ET_ACCEPT event is generated when a listening +socket indicates that there is a connection to be accepted; ET_CONNECT +is generated when a non-blocking connect is completed. Finally, if an +end-of-file indication is detected, ET_EOF is generated, whereas if an +error has occurred on the socket, ET_ERROR is generated. Of course, +when a socket has been deleted by the socket_del() function, an event +of ET_DESTROY is generated when it is safe for the memory used by the +struct Socket to be reclaimed. + +Events + +An event, represented by a struct Event, describes in detail all of +the particulars of an event. Each event has a type, and an optional +integer piece of data may be passed with some events--in particular, +ET_SIGNAL events pass the signal number, and ET_ERROR events pass the +errno value. The struct Event also contains a pointer to the +structure describing the generated event--although it should be noted +that the only way to disambiguate which type of generator is contained +within the struct Event is by which call-back function has been +called. + +All generators have a void pointer which can be used to pass important +information to the call-back, such as a pointer to a struct Client. +Additionally, generators have a reference count, and a union of a void +pointer and an integer that should only be utilized by the event +engine. Finally, there is also a field for flags, although the only +flag of concern to the application (or the engine) is the active flag, +which may be tested using the test macros described below. + +Whatever the generator, the call-back function is a function returning +nothing (void) and taking as its sole argument a pointer to struct +Event. This call-back function may be implemented as a single switch +statement that calls out to appropriate external functions as needed. + +Engines + +Engines implement the actual socket event loop, and may also have some +means of receiving signal events. Each engine has a name, which +should describe what its core function is; for instance, the engine +based on the standard select() function is named, simply, "select()." +Each engine must implement several call-backs which are used to +initialize the engine, notify the engine of sockets the application is +interested in, etc. All of this data is described by a single struct +Engine, which should be the only non-static variable or function in +the engine's source file. + +The engine's event loop, pointed to by the eng_loop field of the +struct Engine, must consist of a single while loop predicated on the +global variable _running_. Additionally, this loop's final statement +must be a call to timer_run(), to execute all timers that have become +due. Ideally, this construction should be pulled out of each engine's +eng_loop and put in the event_loop() function of the events +subsystem. + +Reference Counts + +As mentioned previously, all generators keep a reference count. +Should timer_del() or socket_del() be called on a generator with a +non-zero reference count, for whatever reason, the actual destruction +of the generator will be delayed until the reference count again +reaches zero. This is used by the event loop to keep sockets that it +is currently referencing from being deallocated before it is done +checking all pending events on them. To increment the reference count +by one, call gen_ref_inc() on the generator; the corresponding macro +gen_ref_dec() decrements the reference counts, and will automatically +destroy the generator if the appropriate conditions are met. + +Debugging Functions + +It can be difficult to debug an engines if, say, a socket state can +only be expressed as a meaningless number. Therefore, when DEBUGMODE +is #define'd, five number-to-name functions are also defined to make +the debugging data more meaningful. These functions must only be +called when DEBUGMODE is #define'd. Calling them from within Debug() +macro calls is safe; calling them from log_write() calls is not. + +<typedef> +typedef void (*EventCallBack)(struct Event*); + +The _EventCallBack_ type is used to simplify declaration of event +call-back functions. It is used in timer_add(), signal_add(), and +socket_add(). The event call-back should process the event, taking +whatever actions are necessary. The function should be declared as +returning void. +</typedef> + +<typedef> +typedef int (*EngineInit)(int); + +The _EngineInit_ function takes an integer specifying the maximum +number of sockets the event system is expecting to handle. This +number may be used by the engine initialization function for memory +allocation computations. If initialization succeeds, this function +must return 1. If initialization fails, the function should clean up +after itself and return 0. The events subsystem has the ability to +fall back upon another engine, should an engine initialization fail. +Needless to say, the engines based upon poll() and select() should +never fail in this way. +</typedef> + +<typedef> +typedef void (*EngineSignal)(struct Signal*); + +If an engine has the capability to directly detect signals, it should +set the eng_signal field of struct Engine non-zero. When the +application indicates interest in a particular signal, the +_EngineSignal_ function will be called with the filled-in struct +Signal, in order to register interest in that signal with the engine. +</typedef> + +<typedef> +typedef int (*EngineAdd)(struct Socket*); + +All engines must define an _EngineAdd_ function, which is used to +inform the engine of the application's interest in the socket. If the +new socket cannot be accommodated by the engine for whatever reason, +this function must return 0. Otherwise, the function must return 1, +informing the events subsystem that the interest has been noted. +</typedef> + +<typedef> +typedef void (*EngineState)(struct Socket*, enum SocketState new_state); + +Sockets can change state. SS_CONNECTING sockets, for instance, can +become SS_CONNECTED. Whenever a socket state changes, the engine is +informed, since some states require different notification procedures +than others. This is accomplished by calling the _EngineState_ +function with the new state. The struct Socket passed to the engine +will still have the old state, if the engine must reference that. +</typedef> + +<typedef> +typedef void (*EngineEvents)(struct Socket*, unsigned int new_events); + +Applications may only be interested in given events on a socket for a +limited time. When the application's interest shifts, a new events +mask is set for the socket. The engine is informed of this change by +a call to its _EngineEvents_ function. +</typedef> + +<typedef> +typedef void (*EngineDelete)(struct Socket*); + +Eventually, an application will close all the sockets it has opened. +When a socket is closed, and the corresponding struct Socket deleted +with a call to socket_del(), the _EngineDelete_ function will be +called to notify the engine of the change. +</typedef> + +<typedef> +typedef void (*EngineLoop)(struct Generators*); + +The workhorse of the entire events subsystem is the event loop, +implemented by each engine as the _EngineLoop_ function. This +function is called with a single argument that may be passed to +timer_next() to calculate the next time a timer will expire. +</typedef> + +<enum> +enum SocketState { + SS_CONNECTING, /* Connection in progress on socket */ + SS_LISTENING, /* Socket is a listening socket */ + SS_CONNECTED, /* Socket is a connected socket */ + SS_DATAGRAM, /* Socket is a datagram socket */ + SS_CONNECTDG, /* Socket is a connected datagram socket */ + SS_NOTSOCK /* Socket isn't a socket at all */ +}; + +This enumeration contains a list of all possible states a socket can +be in. Applications should not use SS_NOTSOCK; engines should treat +it as a special socket state for non-sockets. The only event that +should be watched for on a struct Socket in the SS_NOTSOCK state is +readability. This socket state is used to implement the fall-back +signal event generation. +</enum> + +<enum> +enum TimerType { + TT_ABSOLUTE, /* timer that runs at a specific time */ + TT_RELATIVE, /* timer that runs so many seconds in the future */ + TT_PERIODIC /* timer that runs periodically */ +}; + +The three possible timer types are defined by the TimerType +enumeration. More details can be found in the "Timers" sub-section. +</enum> + +<enum> +enum EventType { + ET_READ, /* Readable event detected */ + ET_WRITE, /* Writable event detected */ + ET_ACCEPT, /* Connection can be accepted */ + ET_CONNECT, /* Connection completed */ + ET_EOF, /* End-of-file on connection */ + ET_ERROR, /* Error condition detected */ + ET_SIGNAL, /* A signal was received */ + ET_EXPIRE, /* A timer expired */ + ET_DESTROY /* The generator is being destroyed */ +}; + +This enumeration contains all the types of events that can be +generated by the events subsystem. The first 6 are generated by +socket generators, the next by signal generators, and the next by +timer generators. ET_DESTROY is generated by both socket and timer +generators when the events subsystem is finished with the memory +allocated by both. +</enum> + +<struct> +struct Socket; + +This structure describes everything the events subsystem knows about a +given socket. All of its fields may be accessed through the s_* +macros described below. +</struct> + +<struct> +struct Timer; + +The struct Timer structure describes everything the events subsystem +knows about a given timer. Again, all of its fields may be accessed +through the t_* macros described below. +</struct> + +<struct> +struct Signal; + +Signal generators are described by a struct Signal. All of the fields +of a struct Signal may be accessed by the sig_* macros described +below. +</struct> + +<struct> +struct Event; + +Each event is described by a struct Event. Its fields may be examined +using the ev_* macros described below. +</struct> + +<struct> +struct Generators; + +Each engine is passed a list of all generators when the engine's +_EngineLoop_ function is called. The only valid way to access this +structure is via the timer_next() function described below. +</struct> + +<struct> +struct Engine { + const char* eng_name; /* a name for the engine */ + EngineInit eng_init; /* initialize engine */ + EngineSignal eng_signal; /* express interest in a signal */ + EngineAdd eng_add; /* express interest in a socket */ + EngineState eng_state; /* mention a change in state to engine */ + EngineEvents eng_events; /* express interest in socket events */ + EngineDelete eng_closing; /* socket is being closed */ + EngineLoop eng_loop; /* actual event loop */ +}; + +Each engine is described by the struct Engine structure. Each engine +must define all of the functions described above except for the +_EngineSignal_ function, which is optional. +</struct> + +<macro> +#define SOCK_EVENT_READABLE 0x0001 /* interested in readable */ + +The SOCK_EVENT_READABLE flag indicates to the engine that the +application is interested in readability on this particular socket. +</macro> + +<macro> +#define SOCK_EVENT_WRITABLE 0x0002 /* interested in writable */ + +The SOCK_EVENT_WRITABLE flag indicates to the engine that the +application is interested in this socket being writable. +</macro> + +<macro> +#define SOCK_EVENT_MASK (SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE) + +SOCK_EVENT_MASK may be used to extract only the event interest flags +from an event interest set. +</macro> + +<macro> +#define SOCK_ACTION_SET 0x0000 /* set interest set as follows */ + +When socket_events() is called with a set of event interest flags and +SOCK_ACTION_SET, the socket's event interest flags are set to those +passed into socket_events(). +</macro> + +<macro> +#define SOCK_ACTION_ADD 0x1000 /* add to interest set */ + +When SOCK_ACTION_ADD is used in a call to socket_events(), the event +interest flags passed in are added to the existing event interest +flags for the socket. +</macro> + +<macro> +#define SOCK_ACTION_DEL 0x2000 /* remove from interest set */ + +When SOCK_ACTION_DEL is used in a call to socket_events(), the event +interest flags passed in are removed from the existing event interest +flags for the socket. +</macro> + +<macro> +#define SOCK_ACTION_MASK 0x3000 /* mask out the actions */ + +SOCK_ACTION_MASK is used to isolate the socket action desired. +</macro> + +<function> +enum SocketState s_state(struct Socket* sock); + +This macro returns the state of the given socket. +</function> + +<function> +unsigned int s_events(struct Socket* sock); + +This macro returns the current event interest mask for a given +socket. Note that if the socket is in the SS_CONNECTING or +SS_LISTENING states, this mask has no meaning. +</function> + +<function> +int s_fd(struct Socket* sock); + +This macro simply returns the file descriptor for the given socket. +</function> + +<function> +void* s_data(struct Socket* sock); + +When a struct Socket is initialized, data that the call-back function +may find useful, such as a pointer to a struct Connection, is stored +in the struct Socket. This macro returns that pointer. +</function> + +<function> +int s_ed_int(struct Socket* sock); + +Engines may find it convenient to associate an integer with a struct +Socket. This macro may be used to retrieve that integer or, when used +as an lvalue, to assign a value to it. Engine data must be either an +int or a void*; use of both is prohibited. +</function> + +<function> +void* s_ed_ptr(struct Socket* sock); + +Engines may find it convenient to associate a void* pointer with a +struct Socket. This macro may be used to retrieve that pointer or, +when used as an lvalue, to assign a value to it. Engine data must be +either an int or a void*; use of both is prohibited. +</function> + +<function> +int s_active(struct Socket* sock); + +A socket's active flag is set when initialized by socket_add(), and is +cleared immediately prior to generating an event of type ET_DESTROY. +This may be used by the application to determine whether or not the +socket is still in use by the events subsystem. If it is, s_active() +returns a non-zero value; otherwise, its value is 0. +</function> + +<function> +int socket_add(struct Socket* sock, EventCallBack call, void* data, + enum SocketState state, unsigned int events, int fd); + +This function is called to add a socket to the list of sockets to be +monitored. The _sock_ parameter is a pointer to a struct Socket that +is allocated by the application. The _call_ parameter is a pointer to +a function to process any events on the socket. The _data_ parameter +is for use of the socket call-back and may be zero. The _state_ +parameter must be one of the valid socket states. The _events_ +parameter must be a valid events interest mask--0, or the binary OR of +SOCK_EVENT_READABLE or SOCK_EVENT_WRITABLE. Finally, the _fd_ +parameter specifies the socket's file descriptor. This function +returns 1 if successful or 0 otherwise. +</function> + +<function> +void socket_del(struct Socket* sock); + +When the application is no longer interested in a particular socket, +it should call the socket_del() function. This function must be +called no later than when the socket has been closed, to avoid +attempting to call select() or similar functions on closed sockets. +</function> + +<function> +void socket_state(struct Socket* sock, enum SocketState state); + +Occasionally, a socket's state will change. This function is used to +inform the events subsystem of that change. Only certain state +transitions are valid--a socket in the SS_LISTENING or SS_CONNECTED +states cannot change states, nor can an SS_CONNECTING socket change to +some state other than SS_CONNECTED. Of course, SS_DATAGRAM sockets +may change state only to SS_CONNECTDG, and SS_CONNECTDG sockets may +only change states to SS_DATAGRAM. +</function> + +<function> +void socket_events(struct Socket* sock, unsigned int events); + +When the application changes the events it is interested in, it uses +socket_events() to notify the events subsystem of that change. The +_events_ parameter is the binary OR of one of SOCK_ACTION_SET, +SOCK_ACTION_ADD, or SOCK_ACTION_DEL with an events mask. See the +documentation for the SOCK_* macros for more information. +</function> + +<function> +const char* state_to_name(enum SocketState state); + +This function is defined only when DEBUGMODE is #define'd. It takes +the given _state_ and returns a string giving that state's name. This +function may safely be called from Debug() macros. +</function> + +<function> +const char* sock_flags(unsigned int flags); + +This function is defined only when DEBUGMODE is #define'd. It takes +the given event interest flags and returns a string naming each of +those flags. This function may safely be called from Debug() macros, +but may only be called once, since it uses function static storage to +store the flag strings. +</function> + +<function> +int sig_signal(struct Signal* sig); + +This macro returns the signal number for the given struct Signal. +</function> + +<function> +void* sig_data(struct Signal* sig); + +When a struct Signal is initialized, data that the call-back function +may find useful is stored in the struct Signal. This macro returns +that pointer. +</function> + +<function> +int sig_ed_int(struct Signal* sig); + +Engines may find it convenient to associate an integer with a struct +Signal. This macro may be used to retrieve that integer or, when used +as an lvalue, to assign a value to it. Engine data must be either an +int or a void*; use of both is prohibited. +</function> + +<function> +void* sig_ed_ptr(struct Signal* sig); + +Engines may find it convenient to associate a void* pointer with a +struct Signal. This macro may be used to retrieve that pointer or, +when used as an lvalue, to assign a value to it. Engine data must be +either an int or a void*; use of both is prohibited. +</function> + +<function> +int sig_active(struct Signal* sig); + +A signal's active flag is set when initialized by signal_add(). This +may be used by the application to determine whether or not the signal +has been initialized yet. If it is, sig_active() returns a non-zero +value; otherwise, its value is 0. +</function> + +<function> +void signal_add(struct Signal* signal, EventCallBack call, void* data, + int sig); + +This function is called to add a signal to the list of signals to be +monitored. The _signal_ parameter is a pointer is a pointer to a +struct Signal that is allocated by the application. The _call_ +parameter is a pointer to a function to process any signal events. +The _data_ parameter is for use of the signal call-back and may be +zero. The _sig_ parameter is the integer value of the signal to be +monitored. +</function> + +<function> +enum TimerType t_type(struct Timer* tim); + +This macro returns the type of the given timer. +</function> + +<function> +time_t t_value(struct Timer* tim); + +This macro returns the value that was used when the given timer was +initialized by the events subsystem. It will contain an absolute time +if the timer type is TT_ABSOLUTE, and a relative time otherwise. +</function> + +<function> +time_t t_expire(struct Timer* tim); + +This macro returns the absolute time at which the timer will next +expire. +</function> + +<function> +void* t_data(struct Timer* tim); + +When a struct Timer is initialized, data that the call-back function +may find useful is stored in the struct Socket. This macro returns +that pointer. +</function> + +<function> +int t_ed_int(struct Timer *tim); + +Engines may find it convenient to associate an integer with a struct +Timer. This macro may be used to retrieve that integer or, when used +as an lvalue, to assign a value to it. Engine data must be either an +int or a void*; use of both is prohibited. +</function> + +<function> +void* t_ed_ptr(struct Timer *tim); + +Engines may find it convenient to associate a void* pointer with a +struct Timer. This macro may be used to retrieve that pointer or, +when used as an lvalue, to assign a value to it. Engine data must be +either an int or a void*; use of both is prohibited. +</function> + +<function> +int t_active(struct Timer *tim); + +A timer's active flag is set when initialized by timer_add(), and is +cleared immediately prior to generating an event of type ET_DESTROY. +This may be used by the application to determine whether or not the +timer is still in use by the events subsystem. If it is, s_active() +returns a non-zero value; otherwise, its value is 0. +</function> + +<function> +void timer_add(struct Timer* timer, EventCallBack call, void* data, + enum TimerType type, time_t value); + +This function is called to initialize and queue a timer. The _timer_ +parameter is a pointer to a struct Timer that is allocated by the +application. The _call_ parameter is a pointer to a function to +process the timer's expiration. The _data_ parameter is for use of +the timer call-back and may be zero. The _type_ parameter must be one +of the valid timer types--TT_ABSOLUTE, TT_RELATIVE, or TT_PERIODIC. +Finally, _value_ is the value for the timer's expiration. +</function> + +<function> +void timer_del(struct Timer* timer); + +When the application no longer needs a TT_PERIODIC timer, or when it +wishes to stop a TT_ABSOLUTE or TT_RELATIVE timer before its +expiration, it should call the timer_del() function. +</function> + +<function> +void timer_chg(struct Timer* timer, enum TimerType type, time_t value); + +Occasionally, an application may wish to delay an existing TT_ABSOLUTE +or TT_RELATIVE timer; this may be done with the timer_chg() function. +The _type_ parameter must be one of TT_ABSOLUTE or +TT_RELATIVE--changing the values of TT_PERIODIC timers is not +supported. The _value_ parameter is the same as would be given to +timer_add() for that particular type of timer. +</function> + +<function> +void timer_run(void); + +When an engine has finished processing the results of its socket and +signal checks--just before it loops around to test for more events--it +should call the timer_run() function to expire any waiting timers. +</function> + +<function> +time_t timer_next(struct Generators* gen); + +Most engines will use a blocking call with a timeout to check for +socket activity. To determine when the next timer needs to be run, +and thus to calculate how long the call should block, the engine +should call timer_next() with the _gen_ parameter passed to the +_EngineLoop_ function. The timer_next() function returns an absolute +time, which may have to be massaged into a relative time before the +engine may use it. +</function> + +<function> +const char* timer_to_name(enum TimerType type); + +This function is defined only when DEBUGMODE is #define'd. It takes +the given _type_ and returns a string giving that type's name. This +function may safely be called from Debug() macros. +</function> + +<function> +enum EventType ev_type(struct Event* ev); + +This macro simply returns the type of the event _ev_. +</function> + +<function> +int ev_data(struct Event* ev); + +When an event is generated, a single integer can be passed along as a +piece of extra information. This can be used, for instance, to carry +an errno value when an ET_ERROR is generated. This macro simply +returns that integer. +</function> + +<function> +struct Socket* ev_socket(struct Event* ev); + +If the event was generated by a socket, this macro returns a pointer +to the struct Socket that generated the event. The results are +undefined if the event was not generated by a socket. +</function> + +<function> +struct Signal* ev_signal(struct Event* ev); + +If the event was generated by a signal, this macro returns a pointer +to the struct Signal that generated the event. The results are +undefined if the event was not generated by a signal. +</function> + +<function> +struct Timer* ev_timer(struct Event* ev); + +If the event was generated by a timer, this macro returns a pointer to +the struct Timer that generated the event. The results are undefined +if the event was not generated by a timer. +</function> + +<function> +void event_init(int max_sockets); + +Before any of the functions or macros described here can be called, +the events subsystem must be initialized by calling event_init(). The +_max_sockets_ parameter specifies to the events subsystem how many +sockets it must be able to support; this figure may be used for memory +allocation by the engines. +</function> + +<function> +void event_loop(void); + +Once the initial sockets are open, signals added, and timers queued, +the application must call the event_loop() function in order to +actually begin monitoring those sockets, signals, and timers. +</function> + +<function> +void event_generate(enum EventType type, void* arg, int data); + +This is the function called by the events subsystem to generate +particular events. The _type_ parameter specifies the type of event +to generate, and the _arg_ parameter must be a pointer to the event's +generator. The _data_ parameter may be used for passing such things +as signal numbers or errno values. +</function> + +<function> +const char* event_to_name(enum EventType type); + +This function is defined only when DEBUGMODE is #define'd. It takes +the given _type_ and returns a string giving that event type's name. +This function may safely be called from Debug() macros. +</function> + +<function> +const char* engine_name(void); + +This function is used to retrieve the name of the engine presently +being used by the events subsystem. +</function> + +<function> +void gen_ref_inc(void* gen); + +This macro increments the reference count of the generator _gen_, +preventing it from simply disappearing without warning. +</function> + +<function> +void gen_ref_dec(void* gen); + +This macro decrements the reference count of the generator _gen_, and +releases the memory associated with it by generating at ET_DESTROY +event if the reference count falls to zero and the generator is marked +for destruction. No references should be made to the generator after +calling this macro. +</function> + +<authors> +Kev <kl...@mi...> +</authors> + +<changelog> +[2001-6-14 Kev] Finished initial description of the events subsystem. + +[2001-6-13 Kev] Initial description of the events subsystem. +</changelog> Index: ircd-ircdev/doc/en/api/features.txt diff -u /dev/null ircd-ircdev/doc/en/api/features.txt:1.1 --- /dev/null Wed Jan 5 08:32:54 2005 +++ ircd-ircdev/doc/en/api/features.txt Wed Jan 5 08:32:43 2005 @@ -0,0 +1,230 @@ +As of u2.10.11, most of the compile-time configuration options present +in previous versions of ircu have been provided via the configuration +file as "features." This document is intended not only to give an +explanation of how to use the features subsystem in new code, but also +how to define new features. + +In the ircd_features.h header file is an enum Feature that lists all +the features known to the features subsystem. The order of entries in +this list must match precisely the order of features as listed in the +features[] table in ircd_features.c. There are four kinds of +features, seven different flags that can be set for features, and +seven different call-backs for more complex features. + +Types of Features + +There are at present four different types of features: NONE, INT, +BOOL, and STR. Features of type "NONE" are complex features, such as +the logging subsystem, that have complicated behavior that's managed +through the use of call-backs. The call-backs available are set, +which is called to set the value of the feature; reset, which is +called to reset the value of the feature back to its default; get, +which is called to send the user a RPL_FEATURE to describe the feature +setting; unmark, which is called prior to reading the configuration +file; mark, which is called after reading the configuration file; and +report, which is used to send a user a list of RPL_STATSFLINE +replies. + +In comparison to type "NONE," the other types are very simple. Type +"INT" is used for features that take an integer value; "BOOL" is for +those features that are boolean types; and "STR" is for those features +that take simple string values. The values for these feature types +are handled directly by the features subsystem, and can be examined +from code with the feature_int(), feature_bool(), and feature_str() +functions, described below. These features have a notify callback, +which is used to warn subsystems that use the values of particular +features that the value has changed. + +Feature Flags + +There are seven feature flags, one of which is used internally by the +feature subsystem. Three of these flags, FEAT_OPER, FEAT_MYOPER, and +FEAT_NODISP, are used to select who can see the settings of those +features; FEAT_OPER permits any operator anywhere on the network to +examine the settings of a particular feature, whereas FEAT_MYOPER only +permits operators local to a server to examine feature values, and +FEAT_NODISP prohibits display of the feature value altogether. If +none of these three flags are specified, then any user may examine +that feature's value. + +Two other flags only have any meaning for string values; they are +FEAT_NULL, which is used to specify that a feature of type "STR" may +have a NULL value, and FEAT_CASE, which specifies that the feature is +case sensitive--this may be used on file names, for example. Note +that if you give "0" as the default value for a feature, you must also +set the FEAT_NULL flag. + +The remaining non-internal flag is FEAT_READ, which simply sets the +feature to be read-only; a feature so marked may only be changed +through the configuration file. + +Marking Features + +When the configuration file is read, there must be some way to +determine if a particular F-line has been removed since the last time +the configuration file was read. The way this is done in the features +subsystem is to have a "mark" for each feature. Prior to reading the +configuration file, all marks are cleared for all features (and all +"unmark" call-backs are called). As each F-line is encountered and +processed, that feature's mark is set. Finally, when the +configuration file has been fully read, all remaining unmarked +features are reset to their default values (and all "mark" call-backs +are called). + +Adding New Features + +To add a new feature, first determine the feature's name (which must +begin with the string "FEAT_") and its type ("NONE," "INT," "BOOL," or +"STR"). Then add the feature to the enum Feature in an appropriate +place (i.e., it's good to group all features affecting operators +separate from those features affecting networking code), and a +corresponding entry in the features[] table in ircd_features.c. It +will be best to use one of the F_?() macros, which are documented +below. Then, whenever you need to refer to the value of a specific +feature, call the appropriate feature_<type>() function, as documented +below. + +<enum> +enum Feature; + +The "Feature" enum lists all of the features known to the feature +subsystem. Each feature name *must* begin with "FEAT_"; the portion +of the name following "FEAT_" will be what you use to set the feature +from the configuration file or with the "set" or "reset" commands. +</enum> + +<function> +int feature_set(struct Client* from, const char* const* fields, int count); + +The feature_set() function takes an array of strings and a count of +the number of strings in the array. The first string is a feature +name, and, for most features, the second string will be that feature's +value. The _from_ parameter is the struct Client describing the user +that issued the "set" command. This parameter may be NULL if +feature_set() is being called from the configuration file subsystem. +</function> + +<function> +int feature_reset(struct Client* from, const char* const* fields, int count); + +The feature_reset() function is very similar in arguments to the +feature_set() function, except that it may not be called from the +configuration file subsystem. It resets the named feature to its +default value. +</function> + +<function> +int feature_get(struct Client* from, const char* const* fields, int count); + +Again, feature_get() is very similar in arguments to the feature_set() +function, except that again it may not be called from the +configuration file subsystem. It reports the value of the named +feature to the user that issued the "get" command. +</function> + +<function> +void feature_unmark(void); + +This function is used to unmark all feature values, as described in +the subsection "Marking Features." It takes no arguments and returns +nothing. +</function> + +<function> +void feature_mark(void); + +The complement to feature_unmark(), feature_mark() resets all +unchanged feature settings to their defaults. See the subsection on +"Marking Features." +</function> + +<function> +void feature_init(void); + +This function initializes the feature interface by setting the default +values for all features correctly. +</function> + +<function> +void feature_report(struct Client* to); + +Reports all F-lines to a user using RPL_STATSFLINE, except those which +the user is not permitted to see due to flag settings. +</function> + +<function> +int feature_int(enum Feature feat); + +To retrieve the values of integer features, call this function. +Calling this function on a different type of feature, such as a "BOOL" +feature, will result in an assertion failure. +</function> + +<function> +int feature_bool(enum Feature feat); + +This function is the complement of feature_int() for features of type +"BOOL." +</function> + +<function> +const char *feature_str(enum Feature feat); + +Use this function to retrieve strings values for features of type +"STR"; you may not modify nor free the string value. +</function> + +<macro> +#define F_N(type, flags, set, reset, get, notify, unmark, mark, report) + +This macro is used in the features[] table to simplify defining a +feature of type "NONE." The _type_ parameter is the name of the +feature excluding the "FEAT_" prefix, and MUST NOT be in +double-quotes. The _flags_ parameter may be 0, FEAT_OPER, or +FEAT_MYOPER--the bitwise OR of these two flags is permissible but +would not make sense. The rest of the arguments are pointers to +functions implementing the named call-back. +</macro> + +<macro> +#define F_I(type, flags, v_int, notify) + +To define integer features, use the F_I() macro. The _type_ and +_flags_ parameters are as for F_N(), and the _v_int_ parameter +specifies the default value of the feature. The _notify_ parameter, +if non-zero, will be called whenever the value of the feature changes. +</macro> + +<macro> +#define F_B(type, flags, v_int, notify) + +This macro is used for defining features of type "BOOL"; it is very +similar to F_I(), but _v_int_ should either 0 (for a "FALSE" value) or +1 (for a "TRUE" value). The _notify_ parameter, if non-zero, will be +called whenever the value of the feature changes. +</macro> + +<macro> +#define F_S(type, flags, v_str, notify) + +Also similar to F_I(), F_S() defines features of type "STR." The +_flags_ argument may be the bitwise OR of one of FEAT_OPER or +FEAT_MYOPER with the special string flags FEAT_NULL and FEAT_CASE, +which are described above in the section "Feature Flags." The +_notify_ parameter, if non-zero, will be called whenever the value of +the feature changes. Note that FEAT_NULL *must* be set if the default +string _v_str_ is set to NULL. +</macro> + +<authors> +Kev <kl...@mi...> +</authors> + +<changelog> +[2001-06-13 Kev] Mention notify with the other callbacks + +[2001-01-02 Kev] Add documentation for new flags and for the notify +mechanism + +[2000-12-18 Kev] Document the features API +</changelog> Index: ircd-ircdev/doc/en/api/gline.txt diff -u /dev/null ircd-ircdev/doc/en/api/gline.txt:1.1 --- /dev/null Wed Jan 5 08:32:54 2005 +++ ircd-ircdev/doc/en/api/gline.txt Wed Jan 5 08:32:43 2005 @@ -0,0 +1,283 @@ +Some users can be very annoying, as any IRC operator can attest. Some +can in fact be downright abusive. Sometimes the best way of dealing +with these users is to ban them from the entire network. The G-line +system permits this. + +G-lines are fairly complicated. A G-line can be active or inactive, +either locally or globally. It can be a purely local G-line, or +global. It could be based on IP address or on host name. In short, +there are many variations on the basic G-line. Worse, there is also +the concept of a "bad channel," or BADCHAN, that has been tacked onto +the G-line subsystem, when it should have been a separate command in +the first place. + +Different types of G-lines are differentiated from each other through +the use of various flags. Some of these flags are maintained solely +by the G-line subsystem, where as others are passed to various +functions in the API. + +<macro> +#define GLINE_MAX_EXPIRE 604800 /* max expire: 7 days */ + +This macro lists the maximum expire time a G-line is permitted to +have. This value is limited to 7 days to prevent abuse of the system. +</macro> + +<macro> +#define GLINE_ACTIVE 0x0001 + +This flag is used to indicate that a given G-line is globally active. +</macro> + +<macro> +#define GLINE_IPMASK 0x0002 + +This flag is used to indicate that a given G-line is an IP mask. This +flag is maintained internally by the G-line subsystem. +</macro> + +<macro> +#define GLINE_BADCHAN 0x0004 + +This flag is used to indicate that a given G-line specifies a BADCHAN, +a channel that users are not permitted to join. This flag is +maintained internally, but is also used in gline_find() to search for +a BADCHAN for a particular channel. +</macro> + +<macro> +#define GLINE_LOCAL 0x0008 + +This flag is used to indicate that a given G-line is a local G-line. +Local G-lines do not affect users on other servers. +</macro> + +<macro> +#define GLINE_ANY 0x0010 + +This flag is passed to gline_find() to signal that function to return +any G-line or BADCHAN that matches the passed mask string. It is +never set on a real G-line. +</macro> + +<macro> +#define GLINE_FORCE 0x0020 + +This flag is passed to gline_add() to force the server to accept an +expire time that might be out of bounds. It is never set on a real +G-line. +</macro> + +<macro> +#define GLINE_EXACT 0x0040 + +This flag is passed to gline_find() to signal that function to return +only G-lines that exactly match the passed mask string. That is, the +ircd_strcmp() function is called to compare the G-line to the mask, +rather than the match() function. This flag is never set on a real +G-line. +</macro> + +<macro> +#define GLINE_LDEACT 0x0080 /* locally deactivated */ + +This flag is set on global G-lines that have been locally +deactivated. This flag is maintained internally by the G-line +subsystem. +</macro> + +<macro> +#define GLINE_GLOBAL 0x0100 /* find only global glines */ + +This flag is passed to gline_find() or gline_lookup() to specify that +the caller is only interested in global G-lines. This flag is never +set on a real G-line. +</macro> + +<macro> +#define GLINE_LASTMOD 0x0200 /* find only glines with non-zero lastmod */ + +This flag is passed to gline_find() or gline_lookup() to specify that +the caller is only interested in G-lines with a non-zero lastmod time, +that is, G-lines that were not set by a U-lined service. This flag is +never set on a real G-line. +</macro> + +<struct> +struct Gline; + +The struct Gline describes everything about a given G-line. None of +its fields may be directly accessed by the application; use the +functions and macros described below instead. +</struct> + +<function> +int GlineIsActive(struct Gline* g); + +This macro returns a non-zero value if the G-line is active, or 0 +otherwise. If a G-line is locally deactivated, this macro will always +return 0. +</function> + +<function> +int GlineIsRemActive(struct Gline* g); + +This macro returns a non-zero value if the G-line is active, ignoring +whether or not it is locally deactivated. +</function> + +<function> +int GlineIsIpMask(struct Gline* g); + +This macro returns a non-zero value if the G-line is an IP mask. +</function> + +<function> +int GlineIsBadChan(struct Gline* g); + +This macro returns a non-zero value if a G-line actually represents a +BADCHAN. +</function> + +<function> +int GlineIsLocal(struct Gline* g); + +This macro returns a non-zero value if a G-line is local only. +</function> + +<function> +char* GlineUser(struct Gline* g); + +This macro returns the user name associated with the G-line. If the +G-line represents a BADCHAN, this will contain the channel name. +</function> + +<function> +char* GlineHost(struct Gline* g); + +This macro returns the host name associated with the G-line. If the +G-line represents a BADCHAN, this will be a NULL pointer. +</function> + +<function> +char* GlineReason(struct Gline* g); + +This macro returns the reason that was given when the G-line was set. +</function> + +<function> +time_t GlineLastMod(struct Gline* g); + +G-lines that were not set by a U-lined service have a modification +time that must be monotonically increasing. This macro simply returns +that modification time. +</function> + +<function> +int gline_propagate(struct Client *cptr, struct Client *sptr, + struct Gline *gline); + +When a global G-line is set or modified, all other servers must be +notified of the new G-line. This function takes care of propagating +the G-line specified by _gline_, originated by the client _sptr_, to +all servers except _cptr_ (which may be a NULL pointer). +</function> + +<function> +int gline_add(struct Client *cptr, struct Client *sptr, char *userhost, + char *reason, time_t expire, time_t lastmod, unsigned int flags); + +This function simply adds a G-line, set by _sptr_ and with a +_userhost_, _reason_, _expire_, and _lastmod_ as specified. The +_flags_ parameter is a bit mask consisting of the binary OR of +GLINE_FORCE, GLINE_LOCAL, or GLINE_ACTIVE, as appropriate. The +gline_add() function also calls gline_propagate() to propagate the +G-line, and kills off any local users matching the G-line if it is +active. +</function> + +<function> +int gline_activate(struct Client *cptr, struct Client *sptr, + struct Gline *gline, time_t lastmod, unsigned int flags); + +This function activates the G-line specified by _gline_, setting its +_lastmod_ time as specified. If _flags_ is GLINE_LOCAL and if the +G-line is locally deactivated, this function will turn off the local +deactivation flag, but will not modify _lastmod_. If the G-line is +globally deactivated, passing this function the GLINE_LOCAL flag will +have no effect. +</function> + +<function> +int gline_deactivate(struct Client *cptr, struct Client *sptr, + struct Gline *gline, time_t lastmod, unsigned int flags); + +This function is similar to gline_activate() except that it +deactivates the G-line. If the given G-line is local, or if it was +set by a U-lined service (and GLINE_LOCAL was not passed via _flags_), +then the G-line is deleted from memory. In all other cases, the +G-line is simply deactivated, either locally (if GLINE_LOCAL was +passed via _flags_) or globally. Global deactivation will update the +_lastmod_ time. +</function> + +<function> +struct Gline *gline_find(char *userhost, unsigned int flags); + +This function looks up a G-line matching the given _userhost_ value, +under control of the _flags_ parameter. Valid _flags_ that may be +passed are: GLINE_BADCHAN, GLINE_ANY, GLINE_GLOBAL, GLINE_LASTMOD, or +GLINE_EXACT, each described above. +</function> + +<function> +struct Gline *gline_lookup(struct Client *cptr, unsigned int flags); + +This function looks up a G-line matching the given client, specified +by _cptr_, under the control of the _flags_. Valid values for _flags_ +are GLINE_GLOBAL and GLINE_LASTMOD, as described above. +</function> + +<function> +void gline_free(struct Gline *gline); + +This function releases all storage associated with a given G-line. +</function> + +<function> +void gline_burst(struct Client *cptr); + +This function generates a burst of all existing global G-lines and +BADCHANs and sends them to the server specified by _cptr_. +</function> + +<function> +int gline_resend(struct Client *cptr, struct Gline *gline); + +This function resends the _gline_ to a server specified by _cptr_. +This may be used if, for instance, it is discovered that a server is +not synchronized with respect to a particular G-line. +</function> + +<function> +int gline_list(struct Client *sptr, char *userhost); + +This function sends the information about a G-line matching _userhost_ +to the client specified by _sptr_. If _userhost_ is a NULL pointer, a +list of all G-lines is sent. +</function> + +<function> +void gline_stats(struct Client *sptr); + +This function generates a list of all G-lines, sending them to the +user _sptr_ by a /STATS G response. +</function> + +<authors> +Kev <kl...@mi...> +</authors> + +<changelog> +[2001-6-15 Kev] Initial documentation for the G-line API. +</changelog> Index: ircd-ircdev/doc/en/api/ircd_snprintf.txt diff -u /dev/null ircd-ircdev/doc/en/api/ircd_snprintf.txt:1.1 --- /dev/null Wed Jan 5 08:32:54 2005 +++ ircd-ircdev/doc/en/api/ircd_snprintf.txt Wed Jan 5 08:32:43 2005 @@ -0,0 +1,268 @@ +These functions are intended to be a complete replacement for sprintf +and sprintf_irc. They are a (nearly) complete reimplementation, and +of course they're snprintf clones, making it more difficult for +accidental buffer overflows to crop up. + +First off, what's missing? These functions support all ANSI C +conversion specifiers and selected ones from ISO 9x, with the +exception of all floating-point conversions. The floating-point +conversions are tricky, and will likely be dependent on the +representation of a floating-point number on a particular +architecture. While that representation is likely to conform to some +standard, it is not currently used in ircu, so seemed like a good +thing to omit, given the difficulty of implementing it. + +There are two more things missing from this implementation that would +be required by ANSI; the first is support for multibyte character +strings, and the second is support for locales, neither of which have +any relevance for ircu, so again omission seemed to be a good policy. +Additionally, %#x always causes '0x' (or '0X') to be printed, even if +the number is zero. + +These functions also have some extensions not seen in a +standards-compliant implementation; technically, the ISO 9x extensions +fall into this category, for instance. The ISO 9x extensions +supported are type extensions--%ju, %tu, and %zu, for instance; %qu +and %hhu are also supported. The extensions added for use in ircu are +%Tu, which takes a time_t, and the new %C conversion, which inserts +either a numeric or a nick, dependent on the <dest> parameter. The +GNU %m extension, which inserts the strerror() string corresponding to +the current value of errno, is also supported, as is a special %v +extension, which essentially does a recursive call to ircd_snprintf. + +The following description is descended from the Linux man page for the +printf family of functions. + +The format string is composed of zero or more directives: ordinary +characters (not %), which are copied unchanged to the output stream; +and conversion specifications, each of which results in fetching zero +or more subsequent arguments. Each conversion specification is +introduced by the character %. The arguments must correspond properly +(after type promotion) with the conversion specifier. After the %, +the following appear in sequence: + +* Zero or more of the following flags: + + # specifying that the value should be converted to an "alternate + form." For c, d, i, n, p, s, and u conversions, this option + has no effect. For o conversions, the precision of the number + is increased to force the first character of the output string + to a zero (except if a zero value is printed with an explicit + precision of zero). For x and X conversions, the string '0x' + (or '0X' for X conversions) is prepended to it. For e, E, f, + g, and G conversions, the result will always contain a decimal + point, even if no digits follow it (normally, a decimal point + appears in the results of those conversions only if a digit + follows). For g and G conversions, trailing zeros are not + removed from the result as they would otherwise be. For C + conversions, if the destination is local and the origin is a + user, the nick!user@host form is used. + + 0 specifying zero padding. For all conversions except n, the + converted value is padded on the left with zeros rather than + blanks. If a precision is given with a numeric conversion (d, + i, o, u, i, x, and X), the 0 flag is ignored. + + - (a negative field width flag) indicates the converted value is + to be left adjusted on the field boundary. Except for n + conversions, the converted value is padded on the right with + blanks, rather than on the left with blanks or zeros. A - + overrides a 0 if both are given. + + ' ' (a space) specifying that a blank should be left before a + positive number produced by a signed conversion (d, e, E, f, + g, G, or i). + + + specifying that a sign always be placed before a number + produced by a signed conversion. A + overrides a space if + both are used. + + : specifying that a struct Client name should be preceded by a + ':' character if the destination is a user + +* An optional decimal digit string specifying a minimum field width. + If the converted value has fewer characters than the field width, it + will be padded with spaces on the left (or right, if the + left-adjustment flag has been given) to fill out the field width. + +* An optional precision, in the form of a period (`.') followed by an + optional digit string. If the digit string is omitted, the + precision is taken as zero. This gives the minimum number of digits + to appear for d, i, o, u, x, and X conversions, the number of digits + to appear after the decimal-point for e, E, and f conversions, the + maximum number of significant digits for g and G conversions, or the + maximum number of characters to be printed from a string for s + conversions. + +* The optional character h, specifying that a following d, i, o, u, x, + or X conversion corresponds to a short int or unsigned short int + argument, or that a following n conversion corresponds to a pointer + to a short int argument. If the h character is given again, char is + used instead of short int. + +* The optional character l (ell) specifying that a following d, i, o, + u, x, or X conversion applies to a pointer to a long int or unsigned + long int argument, or that a following n conversion corresponds to a + pointer to a long int argument. + +* The character L specifying that a following e, E, f, g, or G + conversion corresponds to a long double argument, or a following d, + i, o, u, x, or X conversion corresponds to a long long argument. + Note that long long is not specified in ANSI C and therefore not + portable to all architectures. + +* The optional character q. This is equivalent to L. + +* A j character specifying that the following integer (d, i, o, u, x, + or X) conversion corresponds to an intmax_t argument. + +* A t character specifying that the following integer (d, i, o, u, x, + or X) conversion corresponds to a ptrdiff_t argument. + +* A z character specifying that the following integer (d, i, o, u, x, + or X) conversion corresponds to a size_t argument. + +* A T character specifying that the following integer (d, i, o, u, x, + or X) conversion corresponds to a time_t argument. + +* A character that specifies the type of conversion to be applied. + +A field width or precision, or both, may be indicated by an asterisk +`*' instead of a digit string. In this case, an int argument supplies +the field width or precision. A negative field width is treated as a +left adjustment flag followed by a positive field width; a negative +precision is treated as though it were missing. + +The conversion specifiers and their meanings are: + + diouxX The int (or appropriate variant) argument is converted + to signed decimal (d and i), unsigned octal (o), + unsigned decimal (u), or unsigned hexadecimal (x and + X) notation. The letters abcdef are used for x + conversions; the letters ABCDEF are used for X + conversions. The precision, if any, gives the minimum + number of digits that must appear; if the converted + value requires fewer digits, it is padded on the left + with zeros. + + eE [NOT IMPLEMENTED] The double argument is rounded and + converted in the style [-]d.dddedd where there is one + digit before the decimal-point character and the + number of digits after it is equal to the precision; + if the precision is missing, it is taken as 6; if the + precision is zero, no decimal-point character + appears. An E conversion uses the letter E (rather + than e) to introduce the exponent. The exponent + always contains at least two digits; if the value is + zero, the exponent is 00. + + f [NOT IMPLEMENTED] The double argument is rounded and + converted to decimal notation in the style + [-]ddd.ddd, where the number of digits after the + decimal-point character is equal to the precision + specification. If the precision is missing, it is + taken as 6; if the precision is explicitly zero, no + decimal-point character appears. If a decimal point + appears, at least one digit appears before it. + + g [NOT IMPLEMENTED] The double argument is converted in + style f or e (or E for G conversions). The precision + specifies the number of significant digits. If the + precision is missing, 6 digits are given; if the + precision is zero, it is treated as 1. Style e is + used if the exponent from its conversion is less than + -4 or greater than or equal to the precision. + Trailing zeros are removed from the fractional part of + the result; a decimal point appears only if it is + followed by at le... [truncated message content] |