diff --git a/.gitignore b/.gitignore index 94f6f6948572daedb9ec0966318363dabe180aaa..361da59e0a0d154b4fb22596ed4780e24c011f9d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ /autom4te.cache /build*/ /configure +/docs/sefht.info +/docs/stamp-vti +/docs/version.texi Makefile.in *.h.in *.hin diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c99d71fd6a73fc237413456536436d7a6bb9873f..e39bcdc2e8464191697c13ed63f39afefcc48f1e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,7 @@ setup: image: gcc before_script: - - apt update && apt install -y autoconf + - apt update && apt install -y autoconf texinfo script: - autoreconf -vi @@ -31,6 +31,7 @@ setup: build-macro/ configure Makefile.in + docs/Makefile.in src/Makefile.in src/config.h.in src/lib/Makefile.in @@ -46,6 +47,7 @@ setup: - build-macro/ - configure - Makefile.in + - docs/Makefile.in - src/Makefile.in - src/config.h.in - src/lib/Makefile.in @@ -75,6 +77,7 @@ config: build-macro/ configure Makefile.in + docs/Makefile.in src/Makefile.in src/config.h.in src/lib/Makefile.in @@ -91,6 +94,7 @@ config: - build-macro/ - configure - Makefile.in + - docs/Makefile.in - src/Makefile.in - src/config.h.in - src/lib/Makefile.in @@ -104,7 +108,7 @@ compile: image: gcc before_script: - - apt update && apt install -y make + - apt update && apt install -y make texinfo - for file in `find . -type f -not -path "./.git/*"`; do git rev-list -n 1 HEAD $file | xargs git show -s --format=%ai @@ -125,6 +129,10 @@ compile: build-macro/ configure Makefile.in + docs/Makefile.in + docs/stamp-vti + docs/sefht.info + docs/version.texi src/Makefile.in src/config.h.in src/lib/Makefile.in @@ -141,6 +149,10 @@ compile: - build-macro/ - configure - Makefile.in + - docs/Makefile.in + - docs/sefht.info + - docs/stamp-vti + - docs/version.texi - src/Makefile.in - src/config.h.in - src/lib/Makefile.in @@ -174,7 +186,7 @@ dist: image: gcc before_script: - - apt update && apt install -y make check + - apt update && apt install -y make check texinfo texlive - for file in `find . -type f -not -path "./.git/*"`; do git rev-list -n 1 HEAD $file | xargs git show -s --format=%ai diff --git a/Makefile.am b/Makefile.am index 1f8e5e4f60fa5b14881be63d0c16acb0748e2db4..0a287f272a21c45492a785be3414315743c25f47 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,9 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = src tests +SUBDIRS = +SUBDIRS += docs +SUBDIRS += src +SUBDIRS += tests EXTRA_DIST = gitlab-ci/save_timestamps.sh diff --git a/configure.ac b/configure.ac index 1a78250218a1f4f169c6bcf798323e89b27fc4f4..2a534f6de2be32e20373deee2cbba7b5c9583cd1 100644 --- a/configure.ac +++ b/configure.ac @@ -87,6 +87,7 @@ AC_CHECK_FUNCS([strdup]) # Makefiles AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([docs/Makefile]) AC_CONFIG_FILES([src/Makefile]) AC_CONFIG_FILES([src/lib/Makefile]) AC_CONFIG_FILES([tests/Makefile]) diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..10986f3fc7267b33c9e86f7793ffb48229b91dc7 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,19 @@ +## Process this file with automake to produce Makefile.in + +info_TEXINFOS = sefht.texi + +html-local: $(builddir)/$(HTMLS)/manual.css +html-local: $(builddir)/$(HTMLS)/style.css +html-local: $(builddir)/$(HTMLS)/reset.css + +$(builddir)/$(HTMLS)/manual.css: $(srcdir)/css/manual.css + @cp $< $@ + +$(builddir)/$(HTMLS)/style.css: $(srcdir)/css/style.css + @cp $< $@ + +$(builddir)/$(HTMLS)/reset.css: $(srcdir)/css/reset.css + @cp $< $@ + +AM_MAKEINFOHTMLFLAGS = --css-ref=manual.css + diff --git a/docs/commit_messages.txt b/docs/commit_messages.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f109c4b594801bba67dec34103efca14e2adb50 --- /dev/null +++ b/docs/commit_messages.txt @@ -0,0 +1,442 @@ + +Classes: +Attr: + The structure SH_Attr implements an HTML Attribute. + For every function there is also a static method/function, + which can perform the same work, but doesn't rely on really + having a single struct Attr. This is useful for example in an + array to manipulate a single element. + +Fragment: + +@subsubsection NodeFragment - Attributes + + The method SH_NodeFragment_get_attr provides a pointer to an Attr, by + its index. Note, that it directly points to the internal data, instead + of copying the data to a new Attr, which would be unneccessary overhead, + if only reading access is needed. That's why it is also a const pointer. + If the user intends to modify it, a copy should be taken via + SH_Attr_copy. + + Multiple insert methods allow either to add an existing Attr, or to + create a new one implicitly. If the Attr is not already used beforehand, + it is more efficient to call the attr_new methods. Also an old Attr is + freed, after it was inserted, thus it can't be used afterwards. This is + neccessary, as for efficiency reasons an array of Attr is used directly, + instead of the indirect approach of storing a pointer of Attr. This + means, that the contents of the Attr has to be copied to the internal + structure. If the old Attr would be left unfreed, there would be two + Attrs, the original one and the implicit one, referring to the same + data, which would lead to at least data corruption, or undefined + behaviour like a double free, which would be a serious threat for a + library which is to be used on a webserver. ... + For each of the two insert modes, there is a method to prepend, append + or insert at a specific position. An incorrect position is handled + inside of the external method and an E_VALUE is thrown. The internal + method doesn't handle this, so special care must be taken to not make + undefined behaviour. However enforcing this check would be unneccessary + overhead for the prepend and append methods, which are known to have + correct indicies, as well for other internal methods, where the internal + method may be used. + + Two alternatives are provided: remove_attr and pop_attr. While the + former free's the Attr's data, the latter allocates a new Attr, to store + and return the data. Both functionality is provided by a single + (internal) static method. + + @subsubsection Childs + + A Fragment can contain childs. When building the html, the + childs html is generated where appropiate. + The methods + - SH_Fragment_get_child (by index) + - SH_Fragment_is_child (non recursive) and + - SH_Fragment_is_descendant (recursive) + were added. + Fragment can be copied, either recursive (copying also all + childs) or nonrecursive (ignoring the childs, thus the copy + has always no childs). + Adding the same element twice in the tree (graph) isn't + possible, as this would lead to problems e.g. double free or + similar quirks. + + The single method (formerly SH_NodeFragment_append_child) to add a child + at the end of the child list was replaced, by a bunch of methods to + insert a child at the beginning (SH_NodeFragment_prepend_child), at the + end (SH_NodeFragment_append_child), at a specific position + (SH_NodeFragment_insert_child) and directly before + (SH_NodeFragment_insert_child_before) or after another child + (SH_NodeFragment_insert_child_after). All these methods are implemented + by a single internal one (insert_child), as there isn't really much + difference in inserting one or the other way. + But this internal method doesn't check whether this insertion request is + actually doable, to save overhead as not every insertion method requires + this check. This is done by the respective method. However if the check + is not done correctly the internal method will attempt to write at not + allocated space, which will hopefully result in a segfault. + + The child list is implemented as an array. To reduce the overhead to + realloc calls, the array is allocated in chunks of childs. The + calculation how many has to be allocated is done by another static + method and determined by the macro CHILD_CHUNK. This is set to 5, which + is just a guess. It should be somewhere around the average number of + childs per html element, to reduce unused overhead. + + Also some predicates (SH_NodeFragment_is_parent, + SH_NodeFragment_is_ancestor) were added to check whether a relationship + exists between to nodes, thus whether they are linked through one or + multiple levels. These functions could replace the old ones + (SH_NodeFragment_is_child, SH_NodeFragment_is_descendant) semantically. + Furthermore they are more efficient as this is now possible to check + over the parent pointer. The internal insert method also uses these + methods to check whether the child node is actually a parent of the + parent node, which would result in errors later one. + + The old test is now obsolete but remained, as it is not bad to test + more. + + Various remove methods were added, which are all implemented by an + static method, analog to the insert methods. + + + @subsubsection Misc + A Fragment can output it's html. If there is an error the method + aborts and returns NULL. + This method also pays attention to self-closing tags, which is + determined via the validator. + When the wrap mode is used, after each tag a newline is started. + Also the html is indented, which can be configured by the + parameters indent_base, indent_step and indent_char. The + parameter indent_base specifies the width the first tag should + be indented with, while indent_step specifies the increment of + the indent when switching to a child tag. The character, that is + used for indenting is taken from indent_char. (It could also be + a string longer than a single character). + This arguments can't be set by the user, but are hardcoded + (by now). + The to_html method generates also the html for the attributes. + Note, that there is no escaping of the quotes, the values are + wrapped with. But this is also somewhat consistent, as there is + no syntax validation on the tags either. + (i.e. no '<' inside of a tag) + + The TextFragment is used to implement the text between and + outside html tags. Currently, it is still very rudimentary in, + that it doesn't support any operations at all and just has a + function to expose a internal text. + While this function is necessary to manipulate the content of a + TextFragment, the TextFragment should abstract the semantics of + Text. While simple wrapper functions for appending are to be + added, methods purely manipulating the text, i.e. relying on + the text's contents, wont get wrapper functions. Thus this + function is still needed until a more sophisticated approach is + implemented. + Some basic text functionality is already supported via wrapper + functions. + Note that wrapper functions aren't tested in unit tests. + + When a newline is encountered in the text, a <br /> is inserted + and for wrap mode also a newline and an indent is inserted. + Note, that the indent is still missing at the front where it + can't be inserted yet as SH_Text is still lacking basic + functionality. + + + The html generation for both TextFragment and NodeFragment + combined is tested. As the encoding semantics of the + TextFragments are neither defined nor implemented, some tests + are marked as XFAIL. + + + What is still missing is the proper treatment of embed text. + This should be indented and breaked at 72/79/80. Also newlines + and special chars should be replaced on generation, maybe also + giving some way of preventing XSS. Regarding the NodeFragment + there should be some adjustments to further adjust the styling, + which of course should also be reflected by TextFragment. This + should also include the generation of self-closing tags. + Furthermore the html generation should be based on a single + text object, to which is added to. This will later on also + enable to directly send generated parts over the network while + still generating some data. + +Validator: + Validator serves as an syntax checker, i.e. it can be requested + whether a tag is allowed. + On initialization (of data), the Validator's knowledge is filled + with some common tags. This is of course to be replaced later, + by some dynamic handling. + When a tag is made known to the Validator, which it already + knows, the old id is returned and nothing is added. + + The Validator saves the tags as an array. Now also another information + is added, which slots aren't used currently to spare expensive calls to + realloc. This led to a mere reimplementation of the functions. Tags + can't be deleted by now, but the adding function supports reusing empty + slots. Also the reading functions have to determine, whether a slot can + be read or is empty. + The tests were adjusted, but are buggy, so they should be rewritten in + the future. + + A registered tag can be deregistered by calling SH_Validator_deregister. + The data is removed, but the space is not deallocated, if it is not at + the end. This prevents copying data on removal and saves expensive calls + to realloc. Instead the empty space is added to the list of free blocks, + which allows to refill these spaces, if a new tag is being registered. + The space is finally deallocated, if the validator is being deallocated + or the tag written in the last block is removed. In this case, heavy + iteration is performed, as the list of free blocks is not ordered. The + next last tag at that time is determined by iterating over the list of + free blocks until some it is not found. + Note that even if there can be a lot of gaps in between, the Validator + will not allocate more space until all these gaps are refilled when a + new tag is registered, thus new space is only being allocated, if there + is really not enough space left. + Due to the 4 nested loops, there was an issue related to the + 72(80)-column rule. It can't be abided without severely impacting the + readability of the code. + + Originally the ids were intended to be useful for linking different + information together internally, and for providing references + externally. However, they weren't used internally, for this, pointers + seamed to be more useful, as they also allow to directly access the data + and also have a relation defined. + Regarding reference purposes, they aren't really needed, and it is more + convenient to directly use some strings, and they aren't more + performant, as there still have to be internal checks and looking for an + int isn't more performant, then looking for a pointer. + Also, they have to be stored, so they need more memory and also some + code, to be handled. + + While it was very clever, the complex data structure of the tag array + introduced in 'Validator: restructured internal data (a0c9bb2)' comes + with a lot of runtime overhead. It reduces the calls to free and + realloc, when a lot of tags are deleted and inserted subsequently, but + burdens each call with a loop over the linked list of free blocks. + + This is even more important, as validator must be fast in checking, as + this is done every time something is inserted into the DOM-tree, but has + not so tight requirements for registering new tags, as this is merely + done at startup time. + + As the access must be fast, the tags are sorted when inserted, so that + the search can take place in log-time. + + There is a method to add a set of tags to a validator on initialisation. + First this removes a user application from the burden of maintaining the + html spec and also is more performant, as a lot of tags are to be + inserted at once, so there aren't multiple allocation calls. + As the validator needs the tags to be in order, the tags must be sorted + on insertion. Of course it would be easier for the code, if the tags + were already in order, but first there could be easily a mistake and + second sorting the tags by an algorithm allows the tags to be specified + in a logically grouped and those more maintainable order. + For the sorting, insertion sort is used. Of course it has a worse + quadratic time complexity, but in a constructor, I wouldn't introduce + the overhead of memory managment a heap- or mergesort would introduce + and in-place sorting is also out, because the data lies in ro-memory. + Thus I choose an algorithm with constant space complexity. Also the + 'long' running time is not so important, as the initilization only runs + at startup once and the tags are not likely to exceed a few hundred so + even a quadratic time isn't that bad. + + Each tag has a type as defined by the html spec. This must be provided + on registration. Implicitly registering tags, when an attribute is + registered can't be done anymore, as the type information would be + missing. + The added parameterin register_tag, as well as the change of behaviourin + register_attr has broken a lot of tests, that had to be adjusted + therefor. + + Added self-closing predicate. Other predicates may follow. + + The Validator contains already all HTML5 tags. + Tags according to: + https://html.spec.whatwg.org/dev/indices.html#elements-3 + + Types according to: + https://html.spec.whatwg.org/multipage/syntax.html#elements-2 + + Retrieved 04. 10. 2023 + + + A attribute can be deregistered by calling SH_Validator_deregister_attr. + Note that deregistering an attr, that was never registered is considered + an error, but this may change, as technically it is not registered + afterwards and sometimes (i.e. for a blacklist) it might be preferable + to ensure, that a specific attr is not registered, but it is not clear + whether there should be an error or not. + Also the deallocating of the data used for an attr was moved to an extra + method, as this is needed in several locations and it might be subject + to change. + + The Validator can check if a attribute is allowed in a tag. It does so + by associating allowed tags with attributes. This is done in that way, + to support also attributes which are allowed for every tag (global + attributes), but this is not yet supported. So some functions allow for + NULL to be passed and some will still crash. + + The predicate SH_Validator_check_attr returns whether an attribute is + allowed for a specific tag. If tag is NULL, it returns whether an attr + is allowed at all, not whether it is allowed for every tag. For this + another predicate will be provided, when this is to be implemented. + + The method SH_Validator_register_attr registers an tag-attr combination. + Note, that it will automatically call SH_Validator_register_tag, if the + tag doesn't exist. Later it will be possible, to set tag to NULL to + register a global attribute, but for now the method will crash. + + The method SH_Validator_deregister_attr removes a tag-attr combination + registered earlier. Note, that deregistering a non existent combination + will result in an error. This behaviour is arguable and might be subject + to change. When setting only tag to NULL, all tags for this attribute + are deregistered. When setting only attr to NULL, all attrs for this tag + are deregistered. This might suffer from problems, if this involves some + attrs, that are global. Also this will use the internal method + remove_tag_for_all_attrs, which has the problem, that it might fail + partially. Normally when failing all functions revert the program to the + same state, as it was before the call. This function however is + different, as if it fails there might be some combinations, that haven't + been removed, but others are already. Nevertheless, the validator is + still in a valid state, so it is possible to call this function a second + time, but it is not sure, which combinations are already deregistered. + + As the attrs also use the internal strings of the tags, it must be + ensured, when a tag is deregistered, that all remaining references are + removed, otherwise there would be dangling pointers. Note, that for this + also remove_tag_for_all_attrs is used, so the method + SH_Validator_deregister_tag suffers from the same problems listed above. + Also if this internal method fails, the tag won't be removed at all. + + Similar to the tags, the attributes can be initialized. Missing tags are + automatically added. The declaration syntax is currently a bit annoying, + as the tags, that belong to an attribute, either have to be declared + explicitly or a pointer to the tag declaration must be given, but then + only concurrent tags are possible. + Support for global attributes is likewise missing; it must be ensured, + that (tag_n != 0) && (tags != NULL). Otherwise validator will be + inconsistent and there might be a bug. + + Global attributes are represented by empty attributes. A global + attribute is an attribute, that is accepted for any tag. + It is refused to remove a specific tag for a global attribute, as this + would mean to "localize" the tag, thus making it not global anymore. + The method to do that and a predicate for globalness is missing yet. + + Deregistering a global attribute normally is not possible, as basically + every other tag has to be added. This was implemented now. + Originally it was intended to provide the caller with the information, + that a global attribute has to be converted into a local one before + removal. However such internals should not be exposed to the caller. As + it stands there is no real reason to inform a caller, whether an + attribute is local or global. Also, there is a problem that the + predicate is burdened with the possibility, that the attribute doesn't + exists, thus it can't return a boolean directly. Both is why, the + predicate isn't added yet. + Also a bug was detected in the method remove_tag_for_all_attrs. It + removes an attribute while also iterating over it, thus potentially + skipping over some attribute and maybe also invoking undefined behaviour + by deallocating space after the array. + + + Copying a Validator could be useful if multiple html versions are to be + supported. Another use case is a blacklist XSS-Scanner. + +Text: + This is a data type to deal with frequently appending to a string. + + The space a Text has for saving the string is allocated in chunks. + To request additional space SH_Text_enlarge is called. If the + requested size fits inside the already allocated space or is even + smaller than the current size, nothing is done. Otherwise a + multiple of chunk size is allocated being equal or greater than + the requested size. The chunk size can be changed by changing + the macro CHUNK_SIZE in src/text.h. The default is 64. + + The adjustment is done automatically when a string is added. + SH_Text_append_string can be used to append a string to the text, + SH_Text_append_text can be used to append another text to the text. + SH_Text_join is a wrapper for SH_Text_append_text, but also frees + the second text, thus joining the texts to a single one. + + The constructor SH_Text_new_from_string accepts a string, with that the + text is initialized. This can replace the so far needed two calls + SH_Text_new and SH_Text_append_string. + + The (intern) implementation of SH_Text was changed from an array of + char, to a single linked list of arrays of char. This allows an easier + implementation of (further) text manipulation. + + The API hasn't changed much, but SH_Text_join can't yield an error + anymore, so it now doesn't support passing an error and returns nothing. + The method SH_Text_get_char returns a single character by a given index. + If the index is out of range, NULL is returned and error->type is set to + VALUE_ERROR. + + The function SH_Text_get_string returns a substring of text beginning at + index and of length offset. If index is out of bounds, NULL is returned + and an error is set. If offset is out of bounds, the existent part is + returned. Also the length of the returned string can be set (optionally) + to the out parameter length. + + If the original behaviour of SH_Text_get_string is achieved, + SH_Text_get_string (text, length, error) has to be changed to + SH_Text_get_string (text, 0, SIZE_MAX, length, error). The only + difference will be that the function won't fail, when the text is longer + than SIZE_MAX, because it is told to stop there. A text that is longer + than SIZE_MAX is not possible to be returned, but that wasn't possible + at anytime. Also I don't think handling char[] longer than SIZE_MAX is + possible with the standard C library. Those in this case the text can + only be returned in parts (By now only possible till 2*SIZE_MAX-1 with + calling SH_Text_get_string (text, SIZE_MAX, SIZE_MAX, length, error)) + or has to be manipulated using the appropriate SH_Text methods, which are + not implemented yet. + + The function SH_Text_get_range returns a string beginning at start and + ending at end. Note that end specifies the char, that is not returned + any more. Thus the function implements something similar, as the pythonic + slice syntax (text[start:end]). In opposition to the behaviour there, + calling SH_Text_get_range with start > end is undefined behaviour. If + start == end, the empty string is returned. + If start is out of bounds, NULL is returned and an error is set. If end + is out of bounds, the existent part is returned. Also the length of the + returned string can be set (optionally) to the out parameter length. + The function SH_Text_get_length returns the length of the text. As the + text also supports being longer than SIZE_MAX, this method can fail on + runtime. If the text is longer then SIZE_MAX, the Text returns SIZE_MAX + and sets error to DOMAIN_ERROR. Note, that due to the implementation, + this is a non trivial function, so don't use it to exhaustively. + The method SH_Text_print just prints the whole string to stdout. + + The function SH_Text_set_char allows to write a single character to a + position, that already exists in the text. Thus overwriting another + character. If the index is out of range, a value error is set and FALSE + is returned. + + + It was tried to implement the text in terms of multiple text + segments. + + While it would be preferable, it doesn't seam to be possible to + abstract over the internals of text_segment. That's why only + some basic functionality is moved, but whether more is to + follow, is not known yet. + + A text_segment allocates memory in terms of chunks, this is now + also done, when created from a string, but this means that we + can't rely on strdup any more, as it takes care of the + allocation. Calling malloc ourselves shouldn't be such an + overhead as at least glibc's strdup performs the exact same + steps. Actually we should be spare a strlen call now, so it + should be more performant. + + The copy_and_replace function replaces a single character with + a string, while copying. This may be replaced by an elaborate + function as manipulating a text normally means that + manipulating is deferred until needed, which this function + contradicts to. + + + Also there is the concept of a text mark. + A mark will be used to point to a specific location inside of a + text. Currently it can't do anything and isn't even used. diff --git a/docs/css/manual.css b/docs/css/manual.css new file mode 100644 index 0000000000000000000000000000000000000000..6f77190f3bd62a6ff5a91f8141af3772b99b7f9e --- /dev/null +++ b/docs/css/manual.css @@ -0,0 +1,72 @@ +/* Style-sheet to use for manuals (copied from Emacs) */ + +@import url('./style.css'); + +/* makeinfo 6.5 converts @quotation to <blockquote>. Highlight them. */ +blockquote { + font-style: normal; + border-left: solid 10px red; + padding-left: 2.5%; + margin-left: 0px; +} + +/* Increase inter-line spacing to improve readability. */ +p, pre, li, dt, dd, table, code, address { line-height: 1.5em; } + +var { font-style: italic; } + +/* Lay out @lisp just like @example. Copied from what /style.css + does for the 'example' class. */ +div.lisp { padding: .8em 1.2em .4em; } +pre.lisp { padding: .8em 1.2em; } +div.lisp, pre.lisp { + margin: 1em 0 1em 3% ; + -webkit-border-radius: .3em; + -moz-border-radius: .3em; + border-radius: .3em; + border: 1px solid #d4cbb6; + background-color: #f2efe4; +} +div.lisp > pre.lisp { + padding: 0 0 .4em; + margin: 0; + border: none; +} + +/* makeinfo 6.7 uses <div class="header"> for navigation links above node + titles. Make those links less prominent. */ +.header { + line-height: 2em; + font-size: 87.5%; + color: #433; +} + +/* In title and node titles, use Fira Sans if available as it is more + pleasant and more compact than Helvetica. */ +.settitle, .top, .chapter, .section, .subsection, .subsubsection { + font-family: Fira Sans, sans-serif; +} + +/* ----- coreutils specific styling ----- */ + +/* layout.css indents "body p" when it should probably only indent "body > p"? + In any case, disable indenting of p in these sub elements. */ +dd p,li p { + margin-left: 0; + margin-right: 0; +} + +/* underlined links are distracting, especially within outlined tables. */ +a { /*add :link for external links*/ + text-decoration: none; /* don't underline links by default */ + outline-style: none; /* don't put dotted box around clicked links */ +} +a:hover { + text-decoration: underline; +} + +body { + /* Make sure the body doesn't become to wide: long lines are hard to + read. */ + max-width: 45em; +} diff --git a/docs/css/reset.css b/docs/css/reset.css new file mode 100644 index 0000000000000000000000000000000000000000..9a6c3065f81b6cfdedc2f6d3d219adeb74035091 --- /dev/null +++ b/docs/css/reset.css @@ -0,0 +1,114 @@ +/* +Software License Agreement (BSD License) + +Copyright (c) 2006, Yahoo! Inc. +All rights reserved. + +Redistribution and use of this software in source and +binary forms, with or without modification, arepermitted +provided that the following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of Yahoo! Inc. nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of Yahoo! Inc. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +html { + color: #000; + background: #FFF; +} + +body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, +h5, h6, pre, code, form, fieldset, legend, input, +button, textarea, p, blockquote, th, td { + margin: 0; + padding: 0; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +fieldset, img { + border: 0; +} + +address, caption, cite, code, dfn, em, strong, +th, var, optgroup { + font-style: inherit; + font-weight: inherit; +} + +del, ins { + text-decoration: none; +} + +li { + list-style:none; +} + +caption, th { + text-align: left; +} + +h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-weight: normal; +} + +q:before, q:after { + content:''; +} + +abbr, acronym { + border: 0; + font-variant: normal; +} + +sup { + vertical-align: baseline; +} +sub { + vertical-align: baseline; +} + +legend { + color: #000; +} + +input, button, textarea, select, optgroup, option { + font-family: inherit; + font-size: inherit; + font-style: inherit; + font-weight: inherit; +} + +input, button, textarea, select { + *font-size: 100%; +} diff --git a/docs/css/style.css b/docs/css/style.css new file mode 100644 index 0000000000000000000000000000000000000000..1322535f6508becb6cfc37ccf91c78e4d3dbf4c2 --- /dev/null +++ b/docs/css/style.css @@ -0,0 +1,175 @@ +/* This stylesheet is used by manuals and a few older resources. */ + +@import url('./reset.css'); + + +/*** PAGE LAYOUT ***/ + +html, body { + font-size: 1em; + text-align: left; + text-decoration: none; +} +html { background-color: #e7e7e7; } + +body { + max-width: 74.92em; + margin: 0 auto; + padding: .5em 1em 1em 1em; + background-color: white; + border: .1em solid #c0c0c0; +} + +/*** BASIC ELEMENTS ***/ + +/* Size and positioning */ + +p, pre, li, dt, dd, table, code, address { line-height: 1.3em; } + +h1 { font-size: 2em; margin: 1em 0 } +h2 { font-size: 1.50em; margin: 1.0em 0 0.87em 0; } +h3 { font-size: 1.30em; margin: 1.0em 0 0.87em 0; } +h4 { font-size: 1.13em; margin: 1.0em 0 0.88em 0; } +h5 { font-size: 1.00em; margin: 1.0em 0 1.00em 0; } + +p, pre { margin: 1em 0; } +pre { overflow: auto; padding-bottom: .3em; } + +ul, ol, blockquote { margin-left: 1.5%; margin-right: 1.5%; } +hr { margin: 1em 0; } +/* Lists of underlined links are difficult to read. The top margin + gives a little more spacing between entries. */ +ul li { margin: .5em 1em; } +ol li { margin: 1em; } +ol ul li { margin: .5em 1em; } +ul li p, ul ul li { margin-top: .3em; margin-bottom: .3em; } +ul ul, ol ul { margin-top: 0; margin-bottom: 0; } + +/* Separate description lists from preceding text */ +dl { margin: 1em 0 0 0; } +/* separate the "term" from subsequent "description" */ +dt { margin: .5em 0; } +/* separate the "description" from subsequent list item + when the final <dd> child is an anonymous box */ +dd { margin: .5em 3% 1em 3%; } +/* separate anonymous box (used to be the first element in <dd>) + from subsequent <p> */ +dd p { margin: .5em 0; } + +table { + display: block; overflow: auto; + margin-top: 1.5em; margin-bottom: 1.5em; +} +th { padding: .3em .5em; text-align: center; } +td { padding: .2em .5em; } + +address { margin-bottom: 1em; } +caption { margin-bottom: .5em; text-align: center; } +sup { vertical-align: super; } +sub { vertical-align: sub; } + +/* Style */ + +h1, h2, h3, h4, h5, h6, strong, dt, th { font-weight: bold; } + +/* The default color (black) is too dark for large text in + bold font. */ +h1, h2, h3, h4 { color: #333; } +h5, h6, dt { color: #222; } + +a[href] { color: #005090; } +a[href]:visited { color: #100070; } +a[href]:active, a[href]:hover { + color: #100070; + text-decoration: none; +} + +h1 a[href]:visited, h2 a[href]:visited, h3 a[href]:visited, + h4 a[href]:visited { color: #005090; } +h1 a[href]:hover, h2 a[href]:hover, h3 a[href]:hover, + h4 a[href]:hover { color: #100070; } + +ol { list-style: decimal outside;} +ul { list-style: square outside; } +ul ul, ol ul { list-style: circle; } +li { list-style: inherit; } + +hr { background-color: #ede6d5; } +table { border: 0; } + +abbr,acronym { + border-bottom:1px dotted #000; + text-decoration: none; + cursor:help; +} +del { text-decoration: line-through; } +em { font-style: italic; } +small { font-size: .9em; } + +img { max-width: 100%} + + +/*** SIMPLE CLASSES ***/ + +.center, .c { text-align: center; } +.nocenter{ text-align: left; } + +.underline { text-decoration: underline; } +.nounderline { text-decoration: none; } + +.no-bullet { list-style: none; } +.inline-list li { display: inline } + +.netscape4, .no-display { display: none; } + + +/*** MANUAL PAGES ***/ + +/* This makes the very long tables of contents in Gnulib and other + manuals easier to read. */ +.contents ul, .shortcontents ul { font-weight: bold; } +.contents ul ul, .shortcontents ul ul { font-weight: normal; } +.contents ul { list-style: none; } + +/* For colored navigation bars (Emacs manual): make the bar extend + across the whole width of the page and give it a decent height. */ +.header, .node { margin: 0 -1em; padding: 0 1em; } +.header p, .node p { line-height: 2em; } + +/* For navigation links. We can't use inline-block display to avoid wrapping + because this makes the links appear much smaller than normal text on + phones with Chromium (RT #1872370). */ +.node a, .header a { /*display: inline-block;*/ line-height: 2em; } +.node a:hover, .header a:hover { background: #f2efe4; } + +/* Inserts */ +table.cartouche td { padding: 1.5em; } + +div.display, div.lisp, div.smalldisplay, + div.smallexample, div.smalllisp { margin-left: 3%; } + +div.example { padding: .8em 1.2em .4em; } +pre.example { padding: .8em 1.2em; } +div.example, pre.example { + margin: 1em 0 1em 3% ; + -webkit-border-radius: .3em; + -moz-border-radius: .3em; + border-radius: .3em; + border: 1px solid #d4cbb6; + background-color: #f2efe4; +} +div.example > pre.example { + padding: 0 0 .4em; + margin: 0; + border: none; +} + +pre.menu-comment { padding-top: 1.3em; margin: 0; } + + +/*** FOR WIDE SCREENS ***/ + +@media (min-width: 40em) { + body { padding: .5em 3em 1em 3em; } + div.header, div.node { margin: 0 -3em; padding: 0 3em; } +} diff --git a/docs/sefht.texi b/docs/sefht.texi new file mode 100644 index 0000000000000000000000000000000000000000..67295f8f9ec84a1d852929c4ffbc4cbacffd558c --- /dev/null +++ b/docs/sefht.texi @@ -0,0 +1,1388 @@ +\input texinfo +@include version.texi +@settitle SeFHT @value{VERSION} - Developer Manual +@afourpaper + +@deftypefnnewline on + +@defindex file + +@copying +This manual is for SeFHT @value{VERSION} (@value{UPDATED}). + +Copyright @copyright{} 2023 Jonathan Schöbel +@email{jonathan@@xn--schbel-yxa.info} +@end copying + +@titlepage +@title SeFHT Developer Manual +@subtitle for version @value{VERSION}, @value{UPDATED} +@author Jonathan Schöbel +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + +@ifnottex +@node Top +@top SeFHT Developer Manual + +This is the developer manual for SeFHT +(version @value{VERSION}, @value{UPDATED}). + +It aims to document the implementation of SeFHT and targets +(future) developers of that library. It is not intended as +guide for users of SeFHT, for those another manual will be written. +@end ifnottex + +@menu +* Introduction:: +* Overview:: +* Main Classes:: +* Type Index:: +* Function Index:: +* File Index:: +* General Index:: +@end menu + + +@node Introduction +@chapter Introduction + +SeFHT, which is an acronym for Server side Fragment-based Homepage +Toolkit, is a library for creating web applications on a webserver +on runtime. It is written for my personal use, but may be useful for +others. + +In @ref{About} the projects benefits and use-cases are being described, +and a rationale why the project's existence is deemed necessary in +the way it is, can be found in @ref{Rationale}, while +a short remark about the evolving of the project and it's name can be +found in @ref{History}. + +@menu +* About:: +* Rationale:: +* History:: +@end menu + + +@node About +@section About + +The @dfn{Server side Fragment based Homepage Toolkit} (SeFHT) is a +library, with which the frontend of websites can be generated. It can +be used from any C (and C++) program +(and from other languages, if the bindings exist). +It does not provide any network related features, so it might end up +in a CGI program, or for some ambitious project in a module for a +webserver. + +A webpage is generated by calling functions, and in the end the HTML +is produced. Also it is checked to some extend, that the HTML is +consistent. This can't be evaded, as it is actually a side effect of +the implementation. This is because it is necessary for formatting, +that SeFHT has some knowledge about the used tags. This knowledge can +be created manually, or a predefinition of HTML5 can be used. + +SeFHT is still in a early development phase, so a lot of features are +still missing. That's why the provided benefits may not seam to be +useful enough, for using it. However the presented functionality is +already working, but with the drawback, that the API and ABI may change +at any time, as it is not yet stable. Of course, this will be changed, +once the project reaches version 1.0. + + +@node Rationale +@section Rationale + +For some developers the idea of generating static HTML on a webserver +is not straightforward and doing this with some C library would be +considered a crime. However as I have grown up with less powerful +devices, a static website has a huge usability advantage. It is also +more useful for users using a text-based webbrowser. +Sometimes a website using javascript is also better viewed with a +textbrowser, as a lot of bloat and advertisement can't be displayed +and it can be focused on the information. But most modern webpages are +really annoying to view, because there is so much div-bloat and some +don't show anything at all. + +Secondly, I really like semantic markup. I think, that HTML is a way +of marking text in a way, that it is clear (for computers), what type +of information is being displayed. I definitely don't like the idea of +using HTML as a cheap way of describing the GUI of some application. +I also don't like, that work, that really ought to be performed on +a server, is performed on a client. +(This might be actually useful for some offline "web"app, but this is +completely different from an actual website, which is inherently +online.) +This also leads to a website, where URLs can be used by something +different than a user agent. + +Thirdly, I like the idea of webpages being readable without a browser. +This is not the case, for webpages containing div-bloat and +definitely not for webpages, which contain nothing besides a linked +javascript file, which is minified and then creates even more div-bloat. +This idea is, why the library is capable of indenting HTML. +Contralateral, I also know that even carefully handcrafted HTML is not +perfectly readable, because tags containing attributes can be quite +long, but on webpages actually containing text content, this is usually +not a problem. + +Apparently, these issues influence and support each other, +i.e.@: a beautiful website is also readable in a textbrowser. + + +C is often criticized, for reasons not exactly pointless, but +eventually I really like C, e.g. for manually managing memory. +Not using generic data structures (which would be possible in C) +slows down development, but enables also to think about how data +is really managed in the memory. Also C doesn't imposes restrictions +on what a developer can do, which is quite flattering. + +Regarding vulnerabilities, which is obviously an important issue, +for a program running on a webserver, hopefully, there won't be so much, +but I am not so blindly to assume, that there aren't any. +To help with that, of course the library is tested with valgrind and +UBSan from time to time. +However, often undefined behaviour is invoked (besides for nasty bugs) +on code paths, where something would have to be caught independently +from the used programming language. For example, if in python an +unconsidered code path is executed, there might also be an exception +(if you are lucky), which might also yield a website containing data +not intended for the public. Also the trickiest bugs are always in +a way, where type checking doesn't help much, because the logic itself +written down in the programming language is relying on wrong +assumptions. + + +@node History +@section History + +In early 2020, I started to write a website for my family as a +replacement for the older website, which wasn't working thoroughly +any more, due to being dated, so that dependencies had already vanished. + +The new website happened to be written in Python (3) and started merely +as some functions inserting small strings into larger built-in strings, +which contained the HTML. Each webpage corresponded to a python file +and there was an additional file, which contained all the global +functions, needed by each webpage. While it was effective and also not +quite unmaintainable, it wasn't sophisticated enough to gratify me. +Also a lot of common code was inserted in every file, which also wasn't +quite elegant. + +The successor became an approach, which is quite similar as the +library on hand. There was a class called CMSContent (which +resembles the NodeFragment being present here), that represented a +tree of HTML tags. There was a module mechanism implemented via a +base module, which provided the module functionality and some +abstract methods (a concept not existing in python). These abstract +methods were then overridden by the actual modules. The creation of +HTML a module provides was parted in four steps: +collecting of offline data (i.e. from the database), +collecting of online data (i.e. from another website), +creating the CMSContent tree and +generating the HTML, which was done via the created CMSContent tree. +A fifth step automatically creating menu entries was never finished. +There also existed a separate class for managing the database and +the class CMS, which glued everything together. Static HTML was +also created as part of the CMSContent tree and stored normalized +in the database. + +While the whole concept became quite elaborated (indenting the HTML +was done automatically and it also became capable of automatically +generating the CSS, while a automatic generation of the navigation +elements wasn't completed), there were also some issues.@* +Firstly, the whole system was developed further and further without +actually implementing the website in terms of the system. Thus, +the website became quite chaotic, as the code mixed using different +concepts and system versions. Eventually the development become +divergent from the running website, so that the system evolved, but +the website doesn't evolved as well. This became a problem, as more +bugfixes were done and also some functionality was added to the website, +which wasn't exactly compatible with the new system. It also happened, +as it was considered easier to do the switch, when the implementation +would have become more maturate and stable, but this never happened, +because more features became apparent, that would be nice and ease +the rewrite based on the new system.@* +Secondly, while the code was pretty fast, maybe also because in each +generation step basically everything could run in parallel, the website +became very slow, because python needed between one and two seconds on +the webserver and between three and five seconds on my local computer +for parsing and interpreting the code, which is definitely to long +for a website. This was also valid, for the running version, which +used very little of the code, which couldn't be separated from the +rest.@* +Thirdly, I began disliking python for being dynamically typed. I +eventually started every function, with checks, whether the arguments +had the right types and threw an exception, if they were wrong. Of +course I also added type hints. Technically, these aren't really +problems, but it also contributed to the thought of reimplementing it +in another language. + +To overcome this issues, I started writing a new project in C. I +recognised, that the tree-like arranging of HTML nodes, very much +resembled the Document Object Model (DOM). It was therefore called +Server-side DOM API (SeDOMA). As the name indicates, its focus lied on +actually implementing the DOM. It also headed for the goal of eventually +converting dynamic HTML to a static HTML on a server. While it still +considered a goal in the current library, it is a long-term goal and not +particularly envisaged.@* +This project started in C, but switched to C++, because the DOM is also +defined in terms of inheritance and using the STL is convenient. +However, implementing the whole DOM is complete overkill, for just +creating a website. That's why, this project came to a halt until after +everything had been declared (and very little been implemented). + +The next bid, became the Serverside Web Fragment Toolkit (SeWFT), an +approach of performing the same goal, but without implementing the DOM. +It was considered part of SeDOMA, so it might also be called SeDOMA +Web Fragment Toolkit. +This project started in C++, as this was were the last project ended, +but due to some struggles between me and C++, namely the mixing between +declaration, definition and constructor, i.e. the inability to just +call the constructor of an existing object or just declaring space, +without calling a constructor, it switched back to C. +Another reason was me liking to manage memory explicitly. +Both projects were very short-lived with SeDOMA having 39 commits and +SeWFT only 14. At the time of this writing, SeFHT has 215. + +As after switching to C, there was no sensible code left, it was +considered appropriate to deem it a new project. +It was called Server side Fragment-based Homepage Toolkit (SeFHT), +because it will be focused more on creating a useful library for +creating a homepage, then on more elaborate stuff. + +As it is basically still the same project, there might be a rename in +the future, as SeDOMA is more pronounceable, which is why it was called +that way. + + +@node Overview +@chapter Overview +@node Dependencies +@section Dependencies and Build Environment + +@subsection Language, Build Tools, etc. + +SeFHT is a library written in C. Compilation is coordinated by make. +The projects makes uses of the GNU Autotools, namely +Autoconf, Automake and Libtool. Documentation is created using +GNU Texinfo. The used testing framework is check. +For static code analysis splint is used, but not very actively. + +The project implements a library and a small demo program +(@command{sefht_demo}), +which uses some base functionality of the library. + +@cindex @command{configure} +@cindex Build Configuration +@fileindex configure +@fileindex configure.ac +@subsection Configuration + +This package uses the GNU Autotools to provide the @command{configure} +script. Therefore, the standard options are supported. +Besides that it supports the following options: +@table @asis + +@item @option{--enable-tests=}@var{OPTION} +Specify whether tests will be available at compiletime. +@var{OPTION} can be one of: +@table @option + +@item yes +Enable the tests. They are not included by @command{make all}, but must +be separately compiled by @command{make check}. This needs Check to be +installed. Check is a unit test framework for C. If Check is not found, +@command{configure} will throw an error. + +@item no +Disable the tests. This makes calling @command{make check} throwing +an error. + +@item auto +Enable the tests, if Check is available, otherwise disable them; +this is the default. + +@end table + +By default @command{configure} tries to detect whether Check is +installed and enables/disables the tests automatically, this behaviour +is also achieved by using @option{--enable-tests=auto}. + +@fileindex tests/no_test.sh +@fileindex tests/no_test.sh.in +If @command{configure} is invoked with @option{--enable-tests=no}, +@option{--disable-tests} or with @option{--enable-tests=auto} and +Check is not detected, the conditional @env{MISSING_CHECK} is defined. +This will ensure, that @command{make check} will throw an error. +Note, that it was not possible to directly stop the generation of the +testsuite by injecting a rule to a Makefile without relying on the +implementation details of Automake. This was discussed in: +@uref{https://stackoverflow.com/questions/76376806/automake-how-to-portably-throw-an-error-and-aborting-the-target/76382437} + +Thus, if MISSING_CHECK is defined, the Makefile, will not include the +real tests to the testsuite, but a special script +@file{tests/no_test.sh}, which will issue and error message, and makes +@command{make check} fail. + +The script is created by @command{configure} from +@file{tests/no_test.sh.in}, which will not expand any Automake macros, +but instead ensure, that the executable flag is set. + +To allow the script to issue messages to stderr, +@env{AM_TESTS_FD_REDIRECT} is used, because the parallel test harness +redirects output of its tests to logfiles. This isn't used for the +serial test harness, because there is no redirection to logfiles, but +there @env{AM_TESTS_FD_REDIRECT} is also not taken into account. +For details about @env{AM_TESTS_FD_REDIRECT}, +@pxref{Testsuite Environment Overrides,, +@uref{https://www.gnu.org/software/automake/manual/html_node/Testsuite-Environment-Overrides.html,, + 15.2.1.1 Testsuite Environment Overrides}, +automake, The GNU Automake Manual} + +@end table + + +@fileindex src/lib/sefht/sefht.h +@subsection Compilation + +For compiling and linking libtool is used, this way the correct flags +for both static and dynamic linking are added depending on the platform. +This can be configured using @command{configure}. + +When compiling against libsefht, only the central header file +(@file{sefht/sefht.h}) should be included. It takes care of including +other header files in the right order. +To prevent accidental inclusion, there are header inclusion guards. + +To disable these inclusion guards, the macro @env{SEFHT_COMPILATION} is +defined. If another program does this, then it can be depended on the +internals, which is discouraged. +This macro is also defined for compiling the tests, as they also test a +lot of implementation details.@* +@xref{Testing} for more information about the tests. + +@subsection Compilation flags + +As there are some wrapper functions, inlining across compilation units +is desired, so link time optimization is turned on. (@option{-flto}). + + +@page +@node Development Environment +@section Development Environment + +@fileindex sefht.geany +@subsection Editor + +For developing I use the IDE Geany. It stores the project information +in the file @file{sefht.geany}. This file contains a project description +as well as all open files. It is included in the VCS (Git), because it +is practical to have the position, where it was last worked on when +switching branches. However this file also often causes merge conflicts, +which could be avoided, if this file was not tracked by the VCS. + +@cindex Version Control System (VCS) +@cindex Git +@cindex Tracking files changes +@cindex File changes, versioning +@fileindex .gitignore +@subsection Version Control System (VCS) + +For version control Git is used. The policy for generated files is, +that they are never included in the version control system, but of +course they must be always included for distributions. As this is a +per project decision, instead of a personal choice, these files are +mentioned in @file{.gitignore}. This file is sorted alphabetically. + +@cindex Repository +@cindex Online Repository +@cindex Gitlab +@cindex Git, online repository +@subsection Repository + +The online repository is hosted in the Gitlab instance of the +Technical University of Dresden (TU Dresden). It can be found under +@uref{https://gitlab.mn.tu-dresden.de/josc941e/sefht}. + +@cindex Nigthtly Builds +@cindex Automatic Nightly Builds +@cindex Building, Online +@cindex CI (Continuous Integration) +@cindex Pipeline +@fileindex .gitlab-ci.yml +@fileindex gitlab-ci/release.sh.in +@fileindex gitlab-ci/upload.sh.in +@fileindex gitlab-ci/save_timestamps.sh + +Beside the plain repository, there is also a pipeline, with some CI +jobs on Gitlab. This is configured in @file{.gitlab-ci.yml}. +In the pipeline, first, the package needs a setup, because the files, +that aren't included in the VCS, have to be generated via +@command{autoreconf}. +Then the package is compiled and tested. +Furthermore, a release is created and uploaded. These nightly releases +are by no means intended for users of the library, but for testing, +that everything works. +The release is marked by a tag naming this nightly release with the +corresponding commit SHA. Note, that adding a tag triggers the pipeline +again, which would result in an error, as a release with the same name +can't be added twice. This is prevented with an execution rule. These +releases are manually deleted from time to time, as they take up space. +For uploading and creating the release, the tar-name is needed. +That's why for this there are separate shell scripts, stored under +@file{gitlab-ci/}, in which @command{configure} substitutes some +variables. + +Note, that separating the work into different stages, using a makefile, +to determine what should be compiled, using Git and Gitlab's behaviour, +doesn't always works as intended. The library used to be always +recompiled, even if it has already been compiled in the previous stage, +because on @command{git checkout}, which is done at every stage, +the files get the timestamp of the checkout-time, but the already +build files, coming from artifacts, have older times, thus resulting +in a recompilation. +This is fixed with setting the timestamp of every file to the last +change git knows of. However, this only solves the problem for +prerequisites, that are included in the VCS, but not for any generated +in a previous stage. The timestamps of the latter files are changed, +because they are transferred via artifacts from the previous stage. +When artifacts are extracted, the timestamps are set to the extraction +time. This causes make to consider prerequisites, included in the +artifacts, newer then their targets, which results in an unnecessary +invocation of the associated rules. While this is unnecessary, but +unproblematic for the actual compilation, it induces problems for the +generation of scripts, macros et cetera, which depend on the +installation of maintainer software. These are only installed for +stages, where they are really necessary, to reduce the time, the +pipeline is running. Thus, when the generation is reinvoked in the wrong +stage, not only time is wasted, but the pipeline will fail. + +This could be bypassed until adding the documentation, by invoking +@command{configure} with @option{--disable-maintainer-mode}, which +prevents the rebuilding of the build environment at all. However, +this is not suitable any more, as the generation of the documentation +is also prevented by this option, which is not envisaged. + +The shell script @file{save_timestamps.sh}, which is invoked before +collecting the artifacts, retains the timestamps of the artifacts, by +creating a script, which restores them. This is then invoked after the +artifacts are extracted in the next stage. + +At the moment, the artifacts are listed twice in @file{.gitlab-ci.yml}, +once for the script and the second time for the artifacts list. +A solution to evade that has not yet been found. + + +Actually some bugs were already found due to testing the package in +another environment. + + +@fileindex todo.txt +@subsection Todo +Features, that are discovered to be needed, but aren't yet implemented, +are written into @file{todo.txt}. + + +@cindex SPLint +@cindex Static Code Analysis +@cindex Code Analysis (Static) +@cindex Analysis, Static Code Analysis +@subsection Static Code Analysis (SPLint) + +The source has been adapted to splint, which still tells about some +errors, but they are all checked to be false-positives. + + +@cindex Documentation +@cindex Writing Documentation +@fileindex docs/sefht.texi +@fileindex docs/sefht.info +@subsection Documentation + +For Documentation (as you may notice) Texinfo is used. + +Besides the standard indices, also a file index is used. At each point, +where something important regarding a file is mentioned, it should be +added to the file index. The index looks a bit cursed in printable +format, as is sorted by the first letter and especially the dot (.) +looks strange. Also the alphabetic order isn't really satisfying. +However there are some quirks, when trying to the trick the indexing +system in doing something else. When it is tried to remove the grouping +by letter by grouping everything with @code{@@sortas@{ @}}, just one +entry is appearing. If it is tried to use the grouping feature as a way +of resembling the file system with @code{@@subentry}, there is first +a limit of two subentries, and secondly filenames starting with a dot +disappear. + + +@page +@node Naming and Calling Convention +@section Naming and Calling Convention + +@node Raw Function Variants +@cindex Raw Function Variants +@cindex String Ownership +@cindex Functions, accepting Strings +@cindex Functions, returning Strings +@subsection Raw Function Variants + +Functions taking a string generally take a copy of them, so that +ownership (i.e.@tie{}responsibility to @code{free} the memory) remains +by the caller. When returning, the ownership is passed to the caller. +This is indicated by declaring these parameters as @code{const char *}. + +However, this is sometimes unnecessary, because the caller doesn't need +the string any more, which would infer two unnecessary calls to +@code{free} and @code{strdup} respectively. To avoid this, there also +variants provided, which take the ownership of the string given, or +return a pointer to a string, which is still owned by the callee. + +These functions are called @dfn{Raw Functions} and generally contains +@code{_raw} near the end. + +When both types of functions exist in the API/ABI, it must be decided +which one to use depending on the usecase. While the normal functions, +are safer in terms of memory, as the caller doesn't have to remember +that it can't use the string any more, the Raw Functions can be more +efficient, as there is no extra call to @code{strdup}, but the user is +not allowed to change the pointer, free it and also can't use the +pointer, because it can't be known whether it is already freed by the +library. As it should be decidable by the user, the library often +implements both approaches. + +@subsubsection Reading Raw Functions +Functions, which return a string, whose ownership remains in the callee, +are commonly named @code{@var{TYPE}_raw_get_@var{ATTRIBUTE}}. They can +be used, if the caller only needs to read the string shortly, e.g. +compare it in a condition, to save a call to strdup. Otherwise, it has +to take a copy themselves. Using such a function, needs special care, +as it is neither allowed to modify it nor to free it. Contralateral, +the callee, may modify or free it at any time. Disregarding this will +lead to a segfault in the best, and to silent data corruption and +security bugs in the worst case. This is especially an issue, if the +library is used in a threaded context, but the library is currently not +threadsafe. Thus using it is currently only possible when using a global +lock for all calls to the library. + +@subsubsection Writing Raw Functions +Functions, which return a string, whose ownership remains in the callee, +are commonly named @code{@var{TYPE}_raw_set_@var{ATTRIBUTE}}. They can +be used, to pass a string to the callee, that is not needed any more by +the caller. They may be used afterwards, but the same rules apply, as +for strings obtained by a reading raw function. The memory must be +allocated on the heap, i.e. it must be passable to @code{free}. + + +@node Error Handling +@cindex Error handling +@cindex Failure handling +@cindex The @code{status} parameter @sortas{status} +@tindex @code{struct SH_Status} @sortas {Status} +@fileindex src/lib/sefht/status.h +@subsection Error handling + +Error handling is done using the structure @code{SH_Status}, defined in +@file{src/lib/sefht/status.h}. The name was chosen in favour of error, +because it is also set independently whether an error has occurred. +The structure must be allocated by the caller, +because allocation errors may need to be handled, and in such a case, +it is unlikely, that it is possible to allocate memory. Note, that it +is actually the only type, of which the members are exported to the +public. Other types are exported as incomplete types, so that user +programs don't depend on the implementation. +Thus a versioning mechanism will have to be introduced, so that +extending the structure is possible later on in a compatible way. + +Every function, that can fail predictably on runtime, supports passing +a pointer to a @code{struct SH_Status} as the last parameter, named +@code{status}. +Functions that can't fail detectably, doesn't have this parameter. + +The structure contains an error type, the errno, the filename, +the function name, the line number and a message. +There are the following error types: +@table @code + +@item UNDEFINED +This is only needed to test, whether a function properly sets +the @code{status} parameter, it might be removed in the future. + +@item SUCCESS +No error has occurred. + +@item E_ALLOC +Allocation Failure. i.e. malloc/realloc/calloc or strdup and friends + +@item E_DOMAIN +Something is not representable due to a chosen type. For example, +there are more elements in an array, then the index type supports. + +@item E_VALUE +Some parameter had an erroneous value. For example, an index out of +bounds or a non existing reference. + +@item E_STATE +Something is unfulfillable, due to some constraint. This typically +indicates a bug in the user program, as something is requested, that +contradicts something requested earlier. + +@item E_BUG +Some unconsistent state was encountered. This always indicates some +bug in the library, not in the user program, for this @code{E_VALUE} +or @code{E_STATE} are used. However, it might be caused by the user +program manipulating internals. + +@end table + +The filename, function name and line number point to the file, +where the error has occurred in the first place. This might not +be the function, that is called from the outside; filename and +function name are null-terminated strings allocated on compiletime. +The message, might be allocated on compiletime or during runtime. + +The proper way of accessing the status structure is yet to be defined. +Currently the structure is accessed directly, but it has to be +considered an implementation detail. There are also macros to check +for a set status. + +When an error is detected, also the macro @code{ERROR} is called, to +pass an error to the log. As the log is not yet implemented, this +expands to a call to @code{printf}. + +Unfortunately the compiler reports, that inside the macro +@code{set_status}, @code{printf} may be called with @code{NULL} +(wit @code{printf(NULL)}), although, this is explicitly debarred. To +suppress this warning the library is compiled with +@option{-Wno-nonnull}. + +Some may argue, that in case of a fatal error, like if no memory +can be allocated, a program should just give up and crash. +However, this behaviour is not very user-friendly. +There might be some cases, where it does not make sense or it isn't +possible to provide the user with some opportunity to e.g. save a file. +But it is not decidable in a library, whether there is an option to +inform the user, something must be cleaned up or even that recovering +is possible at all.@* +A lot of these recognized errors are a failing malloc or an +over-/underflow. + +Error handling can be ignored by the caller by passing @code{NULL} to +the status parameter. Whether an error had occurred, is also always +possible to be determined, by examining the return value. The only +exception is currently @code{SH_Validator_is_self_closing_tag}, where a +return value of @code{FALSE} can both mean, that the tag is not +self-closing or, that an error has occurred, while trying to determine, +whether it is. This should be fixed. + +If the error occurs in a function returning a pointer, @code{NULL} will +be returned. If it returns a value, a special error value of that type +is returned, i.e. @code{PAGE_ERR} in @code{SH_Data_register_page}. +If the return type would be void otherwise, a boolean is returned, +which tells, whether the method has succeeded. +(@code{FALSE} means, that an error has occurred.) + +The error may have occurred in an internal method and is passed +upwards (the stack). + +When an error is being indicated, it is in the responsibility of the +caller to recover gracefully. It has to be assumed that the requested +operation have neither worked, nor actually took place. +Those the operation can be retried (hopefully).@* +Sadly, the functions @code{SH_Validator_deregister_tag} and +@code{SH_Validator_deregister_attr} are an exception to this rule, as +they may return on failure, leaving the validator in a state, which is +neither the state before the call, nor the state after a successful +call. However it will still be a valid state for a validator. +This should be fixed. + + +@page +@node Coding Style Guide +@section Coding Style Guide + +While coding style is a personal choice, consistency is desirable. In +the following, this section presents the coding style, which has evolved +alongside this project. + + +@cindex Line Formatting, Coding Style Guide +@cindex Coding Style Guide, Line Formatting +@cindex Line length (Coding Style Guide) +@cindex Breaking long lines (Coding Style Guide) +@cindex Column limit (Coding Style Guide) +@subsection Line Formatting + +Lines are up to 72 columns long. This allows to put some prefix +(i.e. a line number) in front of lines while also staying under the +80 character limit. On modern screens, displaying multiple files side +by side can be handy. + +Long lines should be broken on semantic tokens. When there needs to be +a break in the declaration or definition of a function, it is often +preferred to break after every argument, instead of breaking just ones. + +After the line break, words should be aligned at the same semantic +level. + +@example +@verbatim +void +foo (struct some_data * arg1, + struct another_data * arg2_is_very_long); +@end verbatim +@end example + +Conditions are broken at operators, so that the structure remains clear. +The infix operator is put in front so, that the semantics between +subclauses can quickly be determined. +Often there are more braces added then strictly necessary, in particular +to state the precedence of and- and or- clauses. + +@example +@verbatim +if ((limit < (index + offset)) +&& (cond2 + || (!cond3 && cond4)) +&& (cond5)) +@end verbatim +@end example + + +There are line breaks to separate the declaration specifier, +return type and function name. This has the advantage of having the +function name in column 1 and enables nicer line diffs. + +@example +@verbatim +static inline +const struct data * const +foo () +@end verbatim +@end example + + +@cindex Indentation, Coding Style Guide +@cindex Coding Style Guide, Indentation +@subsection Indentation and Whitespace + +Tabs are 8 characters. This is easier to read especially when being +tired and also enforces less nesting in functions. Furthermore I +strongly differentiate between indenting and aligning. Indenting means, +that there is a semantic subordination, while aligning is used, for +example, if a function call is too long and you want to place a symbol +directly under another. Tabs are used for indenting and spaces for +aligning. Note, that this also allows to arbitrary define the +indentation width to say three (Who would do that?@:) and the aligning +would still work. Aligning and indenting can also be used in the same +line, as in the following example. + +@example +@verbatim +foo (...) +{ +------->... +------->set_status (status, ERROR, 5 +-------> "very long error description here..."); +------->return NULL; +} +@end verbatim +@end example + +@page +After a comma there is usually a single space. The same applies to +semicolons in @w{@code{for}-loops}. After keywords (i.e.@: @code{for}, +@code{if}) there is also a single space. +Some people may complain, but there is also a space after the function +name. This differentiates function calls from macros. However, if a +macro behaves like a function, it might as well have as space before +the argument list. + +@example +@verbatim +for (size_t i = 0; i < 0; i++, j++) +{ + do_something (arg1, arg2, arg3); + MAGIC_MACRO(i, arg) + function_like_macro (); +} +@end verbatim +@end example + +Trailing whitespace is unnecessary and can even be removed by the editor +automatically. It should not be introduced in commits. + + +@cindex Braces, Coding Style Guide +@cindex Coding Style Guide, Braces +@subsection Braces + +I put braces so that they are both in the first column of the respective +indentation level. + +@example +@verbatim +while (...) +{ + if (...) + { + ... + } + else if (...) + { + ... + } + else + { + ... + } +} +@end verbatim +@end example + +Some find K&R to induce less noise, however, this way visually matching +braces is easier, even without support from the editor. Also I found +myself placing newlines after a change in indentation level, which is +easier to read when being tired, so the brace might be put there as +well. Also some comments and annotations can be put between the header +and body, as is commonly done for functions. + +The block after a control structure should always be encapsulated with +braces even if it contains only a single statement. This prevents some +nasty bugs. + +@example +@verbatim +if (!ptr) +{ + ptr->member = 42; +} +@end verbatim +@end example + +An exception might be made, if the statement fits in the same line as +the condition, and for empty loops. + +@example +@verbatim +if (!ptr) abort (); +for (; NULL != ptr->next; ptr = ptr->next); +@end verbatim +@end example + + +@page +@cindex Comparisons, Coding Style Guide +@cindex Coding Style Guide, Comparisons +@cindex Writing Comparisons +@subsection Comparisons + +I prefer to put the constant first in a comparison. This makes using a +single @code{=} by accident an error (but a proper compiler should issue +a warning anyway) and also allows to read conditions faster, as it is +apparent earlier, which case is being targeted (like when using +@code{switch}). Accustoming needs some time, but it becomes quite handy. + +@example +@verbatim +ptr = malloc (...); +if (NULL != ptr) +{ + ... +} +@end verbatim +@end example + + +@cindex @code{goto} +@subsection Using Goto + +While the general use of @code{goto} is long considered discouraged, +there are some exceptions to this rule. It may be used to jump to +common code to cleanup in case of an error, that is bundled at the end +of a function. For people complaining about the use of @code{goto}: +this is the exact use case, where it is recommended! + + +@node Demo Program +@cindex Demo Program +@fileindex src/main.c +@section Demo Program + +The demo program @command{sefht_demo} uses some basic functionality of +@file{libsefht.so}. The sourcecode is contained in @file{src/main.c}. + + +@node Testing +@fileindex tests/ +@section Testing +Tests are done using Check a unit testing framework for C, and +integrated with @command{automake}, so that tests are done, when +calling @command{make check}. +@xref{Top,,, check, The Check Manual} for more details. + +Testing doesn't only check the public viewable behaviour, but also for +the internal state. This is done, to distinguish a proper working +function from a function just pretending and doing nothing, or worse, +a function, that results in corrupt data, which might not be detected +by calling other exported methods, which might not fail, or are +themselves buggy. +Testing the later would defy the concept of unit tests. Thus, the +easiest way to test for a proper working function, is to test for the +internal state. + +To test an overflow condition, it is necessary to include the +sourcefile into the test, instead of linking against the objectfile, +in order to override @code{SIZE_MAX} or the like. + +Sometimes it isn't possible to test correct overflow detection by +setting some variable to @code{@var{TYPE}_MAX}, because this would +cause an out of bounds access. This is solved by filling garbage +until @code{@var{TYPE}_MAX} is really reached. Because there is a +timeout for the tests and it would fill RAM with gigabytes of garbage, +@code{@var{TYPE}_MAX} is overridden prior to inclusion of the +sourcefile. + +When testing functions, that depend on functions of another unit, +functionality, that depends on the latter, isn't tested, as this +would interfere with the idea of unit tests. This naturally applies +for purely wrapper functions, where a call is just passed to another +unit. + + +@node Main Classes +@cindex Classes +@cindex Main Classes +@chapter Main Classes + +Speaking of classes in a project of pure C, may seam surprising, but +the reader will notice, that the concept of classes does also apply +here. + +A @dfn{Class} consists of a @var{type}, which is in most cases a +structure, and functions/methods, which uses this @var{type}. These +functions takes a pointer to the @dfn{Object}, an instance of this +@var{type}, as the first parameter. The functions are generally named +@code{@var{Type}_@var{function}}. + +There are some methods, which exists for all Classes, as they are +obviously needed to handle objects. +@table @code + +@item @var{Class} *@* @var{Class}_new (..., struct SH_Status * status) +This is the @dfn{Constructor}. It can always fail at runtime, because +@code{malloc} can fail. + +@item @var{Class} *@* @var{Class}_copy (@var{Class} * @var{object}, struct SH_Status * status) +This is the @dfn{Copy Constructor}. It can always fail at runtime, +because @code{malloc} can fail. + +@item void @* @var{Class}_free (@var{Class} * @var{object}) +This is the @dfn{Destructor}. It can't fail at runtime, because +@code{free} can't fail. + +@end table + +@xref{Error Handling} for information about the @code{status} parameter. + +In this chapter the important classes are being introduced. + + +@page +@node CMS +@cindex CMS +@fileindex src/lib/sefht/cms.c +@fileindex src/lib/sefht/cms.h +@section CMS + +@dfn{CMS} bundles some features and might be the entry point +of the library in the future. At the moment it doesn't do much. + +Definitions are in @file{src/lib/sefht/cms.c}, Declarations in +@file{src/lib/sefht/cms.h}. + +@node Using @code{SH_Cms} +@tindex @code{SH_Cms} @sortas{Cms} +@subsection Using @code{SH_Cms} + +@deftypefun {SH_Cms *} SH_Cms_new (struct SH_Status * status) +create a new CMS object + +The returned pointer must be @code{free}d by passing it to +@code{SH_Cms_free}. On failure @code{NULL} is returned. + +The parameter @code{status} must be a valid pointer to a +@code{struct SH_Status} or @code{NULL}. It might be allocated on the +stack. It is updated independently of the occurrence of an error.@* +@xref{Error Handling} for more information about the @code{status} +parameter. +@end deftypefun + +@deftypefun void SH_Cms_free (SH_Cms * cms) +free @code{cms} + +The parameter @code{cms} must be a valid (non-@code{NULL}) pointer to a +@code{SH_Cms} obtained by a call to @code{SH_Cms_new}. It will be +@code{free}d after the call. +@end deftypefun + + +@node Data +@cindex Data +@cindex Database +@cindex Persistent Cache +@cindex Caches +@tindex @code{SH_Data} @sortas {Data} +@fileindex src/lib/sefht/data.c +@fileindex src/lib/sefht/data.h +@section Data + +@dfn{@code{SH_Data}} manages runtime data, that is needed through the +library. It will manage the database and some caches, but this isn't +implemented yet. Currently it only provides access to the Validator. +This is necessary, because the Validator shouldn't be changed after +Fragments started to depend on it. That's why, Data only provides +reading access to the Validator. On creation a Validator, is created +with definitions for HTML5. This will be configurable in the future. + +@code{SH_Data} is implemented in @file{src/lib/sefht/data.c}, the +declarations are in @file{src/lib/sefht/data.h}. +@node Using @code{SH_Data} +@subsection Using @code{SH_Data} + +@deftypefun {SH_Data *} SH_Data_new (struct SH_Status * status) +create a new Data object + +This implicitly creates a Validator using @code{SH_Validator_new_html5}. + +The returned pointer must be @code{free}d by passing it to +@code{SH_Data_free}. On failure @code{NULL} is returned. + +The parameter @code{status} must be a valid pointer to a +@code{struct SH_Status} or @code{NULL}. It might be allocated on the +stack. It is updated independently of the occurrence of an error.@* +@xref{Error Handling} for more information about the @code{status} +parameter. +@end deftypefun + +@deftypefun void SH_Data_free (SH_Data * data) +free @code{data} + +The parameter @code{data} must be a valid (non-@code{NULL}) pointer to a +@code{SH_Data} obtained by a call to @code{SH_Data_new}. It will be +@code{free}d after the call. +@end deftypefun + +@deftypefun bool SH_Data_check_tag (SH_Data * data, const char * tag) + +checks whether @code{tag} is known to @code{data}'s internal Validator + +@code{TRUE} is returned, if @code{tag} is a valid HTML tag. This +function calls @code{SH_Validator_check_tag}. + +The parameter @code{data} must be a valid (non-@code{NULL}) pointer to a +@code{SH_Data} obtained by a call to @code{SH_Data_new}. It isn't +modified by the call. + +The parameter @code{tag} must be a non-@code{NULL} pointer to a +@code{NULL}-terminated string. It isn't modified by the call. + +@end deftypefun + +@deftypefun bool SH_Data_check_attr (SH_Data * data, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +const char * tag, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +const char * attr) + +checks whether @code{attr} is known in combination with @code{tag} to +@code{data}'s internal Validator + +@code{TRUE} is returned, if @code{attr} can be used as attribute for +the tag @code{tag}. If @code{tag} is @code{NULL}, it is checked, +whether @code{attr} is a valid attribute at all. +This function calls @code{SH_Validator_check_attr}. + +The parameter @code{data} must be a valid (non-@code{NULL}) pointer to +a @code{SH_Data} obtained by a call to @code{SH_Data_new}. It isn't +modified by the call. + +The parameter @code{tag} can be @code{NULL}, otherwise it must be a +valid pointer to a @code{NULL}-terminated string. It isn't modified +by the call. + +The parameter @code{attr} must be a non-@code{NULL} pointer to a +@code{NULL}-terminated string. It isn't modified by the call. + +@end deftypefun + +@deftypefun bool SH_Data_is_self_closing_tag (const SH_Data * data, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +const char * tag, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +struct SH_Status * status) + +checks whether @code{tag} is of type void + +@code{TRUE} is returned, if @code{tag} is a void element. This +function calls @code{SH_Validator_is_self_closing_tag}. + +The parameter @code{data} must be a valid (non-@code{NULL}) pointer to a +@code{SH_Data} obtained by a call to @code{SH_Data_new}. It isn't +modified by the call. + +The parameter @code{tag} must be a non-@code{NULL} pointer to a +@code{NULL}-terminated string. It isn't modified by the call. + +@end deftypefun + + + +@page +@node Logging +@cindex Logging +@section Logging + +Currently, logging is not implemented. It is replaced by macros, which +expand to a @code{printf} call. Historical, log messages contained a +trailing newline, but new introduced log messages shouldn't contain +them, as they will be added for all messages. Because this isn't yet +done, it results in annoying messages thrown together in a single line. + + +@page +@node Fragments +@cindex Fragments +@cindex Types of Fragment +@cindex Kinds of Fragment +@section Fragments + +@dfn{Fragment} is the core of SeFHT, as the name might reveal. +A @dfn{Fragment} represents a subset of a webpage. The @dfn{Fragment}s +are organised as a tree. While this resembles the DOM, this library +intentionally doesn't implement it. The similarity is not by chance, +but is caused by the nature of HTML. + +There are several different types of Fragments, which all inherit +from the abstract base class @code{SH_Fragment}. + +There are currently two types of Fragments: Node and Text. +There is currently no forward compatibility for more types, but this is +to be implemented. Also modules, might be partially implemented by a +different type of Fragment in the future. + +NodeFragment is virtually finished, but TextFragment is still lacking +basic functionality including a complete implementation for generating +the HTML, as it depends on still not implemented functionality of +@code{SH_Text}. + + +@page +@node Fragment (base class) +@cindex Fragment, abstract base class +@cindex Base class Fragment +@cindex Abstract Base class Fragment +@cindex Fragment, virtual method table +@cindex Virtual Method Table (Fragment) +@tindex @code{SH_Fragment} @sortas{Fragment} +@tindex @code{enum SH_FRAGMENT_TYPE} @sortas{FRAGMENT_TYPE} +@tindex @code{struct fragment_methods} @sortas{fragment_methods} +@fileindex src/lib/sefht/fragment.c +@fileindex src/lib/sefht/fragment.h +@fileindex src/lib/sefht/fragment_class.c +@fileindex src/lib/sefht/fragment_data.c +@subsection Fragment (base class) + +@dfn{@code{SH_Fragment}} is the base class for all different kinds of +Fragments. It contains some virtual methods, which are supported by +every kind of Fragment, as well as data, which is needed by every kind +of Fragment. But the main functionality of the base class is, to +implement the inheritance. +For this, it contains the type of Fragment, represented by an +@code{enum@tie{}SH_FRAGMENT_TYPE}, and a pointer to the virtual method +table, represented by a structure of function pointers +(@code{struct@tie{}fragment_methods}). The virtual method table itself +is allocated at compiletime for each subclass. + +The data needed by a Fragment is, a pointer to the @code{SH_Data} +object, which is needed for requesting any kind of information from +another part of SeFHT a Fragment might need, and a pointer to the +parent node, which is useful both for traversing the tree and for +checking for cycles, i.e. to ensure, that each Fragment has exactly +one parent, when a node is added. +This is necessary to prevent data corruption and also to keep +clear who is responsible, for @code{free}ing the Fragment. +Both, traversing and ensuring consistency, wouldn't be possible +otherwise. + +The virtual methods each kind of Fragment has to implement are the +Copy Constructor, the Destructor and a function to output the HTML. +The Constructor is not defined as a virtual function, as there the +type has to be named anyway, but every subclass defines a Constructor, +which returns a base class object, i.e.@: @code{SH_Fragment}. +Also every subclass defines a predicate, which checks, whether a given +Fragment is of that type. + +The public functions of @code{SH_Fragment} are implemented in +@file{src/lib/sefht/fragment.c} and declared in +@file{src/lib/sefht/fragment.h}. The @code{SH_Fragment}, as well as all +associated types are defined in @file{src/lib/sefht/fragment_data.c}, +while the functions, that are needed by the subclasses to access fields +of the parent class are defined in @file{src/lib/sefht/fragment_class.c}. + + +@node Using @code{SH_Fragment} +@subsubsection Using @code{SH_Fragment} + +@deftypefun {SH_Fragment *} SH_Fragment_copy @ +(const SH_Fragment * fragment, struct SH_Status * status) +copy @code{fragment} + +This function will call the copy method of the appropriate subclass. + +The returned pointer must be @code{free}d by passing it to +@code{SH_Fragment_free}. On failure @code{NULL} is returned. + +The parameter @code{fragment} must be a valid (non-@code{NULL}) pointer +to a @code{SH_Fragment} obtained by a call to the constructor of a +subclass of @code{SH_Fragment}. It will not be changed by the call. + +The parameter @code{status} must be a valid pointer to a +@code{struct SH_Status} or @code{NULL}. It might be allocated on the +stack. It is updated independently of the occurrence of an error.@* +@xref{Error Handling} for more information about the @code{status} +parameter. +@end deftypefun + +@deftypefun void SH_Fragment_free (SH_Fragment * fragment) +free @code{fragment} + +This method will call the free method of the appropriate subclass. + +The parameter @code{fragment} must be a valid (non-@code{NULL}) pointer +to a @code{SH_Fragment} obtained by a call to the constructor of a +subclass of @code{SH_Fragment}. It will be @code{free}d after the call. +@end deftypefun + +@deftypefun bool SH_Fragment_is_orphan (const SH_Fragment * fragment) +check, whether @code{fragment} isn't the child of another Fragment + +If @code{TRUE} is returned, @code{fragment} does not have a parent, +thus it is suitable for adding to a @code{SH_NodeFragment}. +If @code{FALSE} is returned, adding it will result in an error. + +The parameter @code{fragment} must be a valid (non-@code{NULL}) pointer +to a @code{SH_Fragment} obtained by a call to the constructor of a +subclass of @code{SH_Fragment}. It will not be changed by the call. +@end deftypefun + +@deftypefun {SH_Text *} SH_Fragment_to_html @ +(const struct SH_Fragment * fragment, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +enum HTML_MODE mode, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +unsigned int indent_base, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +unsigned int indent_step, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +const char * indent_char, @*@ +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +struct SH_Status * status) +generate the HTML for @code{fragment}. + +This method will call the free method of the appropriate subclass. + +The HTML for this @code{fragment} is generated including all associated +attributes and child Fragments. + +The returned pointer to @code{SH_Text} must be @code{free}d by passing +it to @code{SH_Text_free}. On failure @code{NULL} is returned. + +The parameter @code{fragment} must be a valid (non-@code{NULL}) pointer +to a @code{SH_Fragment} obtained by a call to the constructor of a +subclass of @code{SH_Fragment}. It will not be changed by the call. + +The parameter @code{mode} defines the formatting of the HTML. +Passing @code{INLINE}, will result in HTML in a single line, while +@code{WRAP} will result in newlines after each tag and proper indenting. + +The parameter @code{indent_base} defines, at which indentation level +this Fragments HTML starts. + +The parameter @code{indent_step} defines, by what amount the indentation +level is incremented when creating the HTML of the child tags. + +The parameter @code{indent_char} is a @code{NULL}-terminated string, +which defines one indentation level. + +The parameter @code{status} must be a valid pointer to a +@code{struct SH_Status} or @code{NULL}. It might be allocated on the +stack. It is updated independently of the occurrence of an error.@* +@xref{Error Handling} for more information about the @code{status} +parameter. +@end deftypefun + + +@page +@node Node Fragment +@cindex Node Fragment +@cindex Fragment, Node +@cindex Tree Fragment +@cindex Fragment, Tree +@cindex Fragment, representing HTML tags +@cindex Fragment, representing HTML attributes +@tindex @code{SH_NodeFragment} @sortas{NodeFragment} +@fileindex src/lib/sefht/node_fragment.c +@fileindex src/lib/sefht/node_fragment.h +@subsection Node Fragment + +The @dfn{@code{SH_NodeFragment}} represents an HTML tag (like a Node +in the DOM) including all its attributes and all subsequent Nodes. +Thus the @dfn{@code{SH_NodeFragment}} implements the tree semantics of +a Fragment. + +When generating the HTML, the appropriate code for the attributes is +generated and for the children is included at the respective places. + +For proper indenting, finding self-closing tags and more, SeFHT has to +know something about the semantics of HTML, which is handled by the +Validator. That's why all tag names must be valid, i.e. known to the +Validator. Attribute names (and values) will be validated in the future +too, but aren't currently, because for the validation of values, there +are complexer rules, which aren't yet implemented by the Validator. +However, validation of attributes in general is implemented, so this +just has to be added to the Node Fragment. + +The functions and types of @code{SH_NodeFragment} are implemented in +@file{src/lib/sefht/node_fragment.c} and declared in +@file{src/lib/sefht/node_fragment.h}. + + + + +@node Type Index +@unnumbered Type Index + +@printindex tp + +@node Function Index +@unnumbered Function Index + +@printindex fn + +@node File Index +@unnumbered File Index + +@printindex file + +@node General Index +@unnumbered General Index + +@printindex cp + +@bye diff --git a/sefht.geany b/sefht.geany index 584196c339db4ef46a64bd7b1c605c5de019a318..607658bbb390b604661666f84dc79278fcb6154d 100644 --- a/sefht.geany +++ b/sefht.geany @@ -28,67 +28,71 @@ long_line_behaviour=1 long_line_column=72 [files] -current_page=56 +current_page=7 FILE_NAME_0=139;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2FREADME;0;8 -FILE_NAME_1=134;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitignore;0;8 +FILE_NAME_1=161;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitignore;0;8 FILE_NAME_2=1185;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fconfigure.ac;0;8 -FILE_NAME_3=73;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2FMakefile.am;0;8 -FILE_NAME_4=19;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmain.c;0;8 -FILE_NAME_5=1867;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2FMakefile.am;0;8 -FILE_NAME_6=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.c;0;8 -FILE_NAME_7=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.h;0;8 -FILE_NAME_8=6482;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.c;0;8 -FILE_NAME_9=2172;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.h;0;8 -FILE_NAME_10=23;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.c;0;8 -FILE_NAME_11=23;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.h;0;8 -FILE_NAME_12=28;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment_data.c;0;8 -FILE_NAME_13=2476;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment_class.c;0;8 -FILE_NAME_14=41345;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.c;0;8 -FILE_NAME_15=28;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.h;0;8 -FILE_NAME_16=3454;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_fragment.c;0;8 -FILE_NAME_17=1867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_fragment.h;0;8 -FILE_NAME_18=19;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.c;0;8 -FILE_NAME_19=19;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.h;0;8 -FILE_NAME_20=26;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_static.c;0;8 -FILE_NAME_21=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_data.h;0;8 -FILE_NAME_22=2929;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.c;0;8 -FILE_NAME_23=2065;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.h;0;8 -FILE_NAME_24=1036;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_data.h;0;8 -FILE_NAME_25=8479;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment.c;0;8 -FILE_NAME_26=1083;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment.h;0;8 -FILE_NAME_27=900;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment_mark.c;0;8 -FILE_NAME_28=1867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_mark_static.c;0;8 -FILE_NAME_29=3229;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.c;0;8 -FILE_NAME_30=1159;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.h;0;8 -FILE_NAME_31=4857;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_html.h;0;8 -FILE_NAME_32=13132;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.c;0;8 -FILE_NAME_33=1992;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.h;0;8 -FILE_NAME_34=1150;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag_data.h;0;8 -FILE_NAME_35=21193;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.c;0;8 -FILE_NAME_36=1834;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.h;0;8 -FILE_NAME_37=1413;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr_data.h;0;8 -FILE_NAME_38=924;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fstatus.h;0;8 -FILE_NAME_39=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Flog.h;0;4 -FILE_NAME_40=20;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fmacro.h;0;8 -FILE_NAME_41=20;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fsefht.h;0;8 -FILE_NAME_42=3007;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2FMakefile.am;0;8 -FILE_NAME_43=218;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Fno_test.sh.in;0;8 -FILE_NAME_44=23;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8 -FILE_NAME_45=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8 -FILE_NAME_46=1772;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_fragment.c;0;8 -FILE_NAME_47=130867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8 -FILE_NAME_48=5714;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text_fragment.c;0;8 -FILE_NAME_49=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_attr.c;0;8 -FILE_NAME_50=4221;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8 -FILE_NAME_51=994;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text_mark.c;0;8 -FILE_NAME_52=926;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 -FILE_NAME_53=20787;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_tag.c;0;8 -FILE_NAME_54=58751;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_attr.c;0;8 -FILE_NAME_55=272;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 -FILE_NAME_56=4391;YAML;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitlab-ci.yml;0;4 -FILE_NAME_57=71;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Fupload.sh.in;0;8 -FILE_NAME_58=683;Sh;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Frelease.sh.in;0;4 -FILE_NAME_59=244;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Fsave_timestamps.sh;0;8 +FILE_NAME_3=84;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2FMakefile.am;0;8 +FILE_NAME_4=73;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2FMakefile.am;0;8 +FILE_NAME_5=19;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Fmain.c;0;8 +FILE_NAME_6=455;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fdocs%2FMakefile.am;0;8 +FILE_NAME_7=20922;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fdocs%2Fsefht.texi;0;8 +FILE_NAME_8=9;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fdocs%2Fcommit_messages.txt;0;8 +FILE_NAME_9=1867;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2FMakefile.am;0;8 +FILE_NAME_10=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.c;0;8 +FILE_NAME_11=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fcms.h;0;8 +FILE_NAME_12=6482;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.c;0;8 +FILE_NAME_13=2172;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fdata.h;0;8 +FILE_NAME_14=23;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.c;0;8 +FILE_NAME_15=23;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment.h;0;8 +FILE_NAME_16=28;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment_data.c;0;8 +FILE_NAME_17=2476;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ffragment_class.c;0;8 +FILE_NAME_18=41345;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.c;0;8 +FILE_NAME_19=28;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fnode_fragment.h;0;8 +FILE_NAME_20=3454;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_fragment.c;0;8 +FILE_NAME_21=1867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_fragment.h;0;8 +FILE_NAME_22=19;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.c;0;8 +FILE_NAME_23=19;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr.h;0;8 +FILE_NAME_24=26;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_static.c;0;8 +FILE_NAME_25=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fattr_data.h;0;8 +FILE_NAME_26=2929;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.c;0;8 +FILE_NAME_27=2065;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext.h;0;8 +FILE_NAME_28=1036;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_data.h;0;8 +FILE_NAME_29=8479;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment.c;0;8 +FILE_NAME_30=1083;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment.h;0;8 +FILE_NAME_31=900;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment_mark.c;0;8 +FILE_NAME_32=1867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_mark_static.c;0;8 +FILE_NAME_33=3229;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.c;0;8 +FILE_NAME_34=1159;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.h;0;8 +FILE_NAME_35=4857;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_html.h;0;8 +FILE_NAME_36=13132;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.c;0;8 +FILE_NAME_37=1992;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.h;0;8 +FILE_NAME_38=1150;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag_data.h;0;8 +FILE_NAME_39=21193;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.c;0;8 +FILE_NAME_40=1834;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.h;0;8 +FILE_NAME_41=1413;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr_data.h;0;8 +FILE_NAME_42=924;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fstatus.h;0;8 +FILE_NAME_43=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Flog.h;0;4 +FILE_NAME_44=20;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fmacro.h;0;8 +FILE_NAME_45=20;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fsefht.h;0;8 +FILE_NAME_46=3007;Make;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2FMakefile.am;0;8 +FILE_NAME_47=218;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Fno_test.sh.in;0;8 +FILE_NAME_48=23;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_cms.c;0;8 +FILE_NAME_49=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_data.c;0;8 +FILE_NAME_50=1772;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_fragment.c;0;8 +FILE_NAME_51=130867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_node_fragment.c;0;8 +FILE_NAME_52=5714;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text_fragment.c;0;8 +FILE_NAME_53=24;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_attr.c;0;8 +FILE_NAME_54=4221;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text.c;0;8 +FILE_NAME_55=994;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text_mark.c;0;8 +FILE_NAME_56=926;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 +FILE_NAME_57=20787;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_tag.c;0;8 +FILE_NAME_58=58751;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_attr.c;0;8 +FILE_NAME_59=626;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 +FILE_NAME_60=4505;YAML;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitlab-ci.yml;0;4 +FILE_NAME_61=71;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Fupload.sh.in;0;8 +FILE_NAME_62=683;Sh;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Frelease.sh.in;0;4 +FILE_NAME_63=244;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Fsave_timestamps.sh;0;8 [VTE] last_dir=/home/jonathan/Documents/projects/prgm/internet/web/SeFHT/tests diff --git a/todo.txt b/todo.txt index 94dd15a07bfc4bacff9159986e9a02ab01c635f0..091d83ab5fafbc550fea6ca5c9bb2be6616f0099 100644 --- a/todo.txt +++ b/todo.txt @@ -20,3 +20,6 @@ Validator: - check for global attributes - fix cursed behaviour, when removing fails (remove_tag_for_all_attrs) - initialize from file + +Documentation: +- add to dir