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