[prev in list] [next in list] [prev in thread] [next in thread] 

List:       netbsd-tech-userlevel
Subject:    [RFC] String Auxiliary Processor: a... SAP!
From:       tlaronde () polynum ! com
Date:       2023-06-27 17:52:51
Message-ID: ZJsh89xeLKAaojvW () polynum ! com
[Download RAW message or body]

When re-organizing the parsing code of inetd(8), I wanted to achieve
several goals:

1 - Keep the buffer with the statement as is in order to provide the
context in case of syntax error (and improve efficiency by not shifting
in the same buffer strings around);

2 - Make almost no memory allocation at least while in the parsing phase
for a service;

3 - Be able to reconstruct and to publish a v2 version of a successfully
parsed configuration file.

3) happened to be problematic because the successfully parsed config
has to be sent to syslog and translating the servtab to a correct config
definition would have implied whether to add a line for every field
or to construct a line in a buffer, dealing constantly with sizes and so
on.

In fact, a solution solved all the problems at once: the SAP...

It is a very basic "machine" with a stack of strings---not a stack of
pointers: the strings are written in a buffer of fixed size.

The machine provides unary and binary operations. The unary operations
deal with the top of the stack (the last string "pushed"). Binary
operations deal with the top and its predecessor.

A string is "pushed" on the stack and can be manipulated: taken as is;
unquoted; quoted; escape sequences interpreted. All the lexical details
are handled by the SAP.

A string can be pushed creating a new entry or it can be appended to the
string on the stack.

Unary operations:

sap_pop()
sap_dup()
sap_split(char)	: split string on top like strrchr(3)---I needed this
	one; other options can be added.

sap_store(flag, ...)	: stores the string, whether as a string (allocated),
		as a string to a FILE* or a as an interpreted binary
		value handling type, size, sign and bound. This pop's
		out the string.

Binary operations:

sap_swap()	exchange inplace the two last strings
sap_join(char)	assemble the two last strings with the char as
	separator;
sap_merge()	put last string directly at the end of previous one

It shall be noted that you can join with '\0'. This means that one
creates a single string with chunks separated by '\0'.

This solved my memory allocation problem: I only allocate once a
whole record with sap_store(), having "joined" the fields, and having
pop'ped out the binary values, so that the members of the servtab
structure all point inside a single allocated memory chunk.

This is small and consist of the two files sap.h and sap.c in the
inetd(8) sources here:

http://downloads.kergis.com/misc/inetd.tar.gz
-- 
        Thierry Laronde <tlaronde +AT+ polynum +dot+ com>
                     http://www.kergis.com/
                    http://kertex.kergis.com/
Key fingerprint = 0FF7 E906 FBAF FE95 FD89  250D 52B1 AE95 6006 F40C
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic