• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# CMake implementation of AutoGen
2# Copyright (C) 2017 Anonymous Maarten <anonymous.maarten@gmail.com>
3
4set(WS " \t\r\n")
5
6function(cutoff_first_occurrence TEXT OCCURRENCE RESULT)
7    string(FIND "${TEXT}" "${OCCURRENCE}" OCCURRENCE_INDEX)
8    if (OCCURRENCE_INDEX EQUAL -1)
9        set(${TEXT} "" PARENT_SCOPE)
10        return()
11    endif()
12
13    string(LENGTH "${OCCURRENCE}" OCCURRENCE_LENGTH)
14    math(EXPR CUTOFF_INDEX "${OCCURRENCE_INDEX}+${OCCURRENCE_LENGTH}")
15    string(SUBSTRING "${TEXT}" ${CUTOFF_INDEX} -1 TEXT_REMAINDER)
16    set(${RESULT} "${TEXT_REMAINDER}" PARENT_SCOPE)
17
18    endfunction()
19
20function(read_definition DEFINITION_FILENAME TEMPLATE_FILENAME DATA)
21    file(READ "${DEFINITION_FILENAME}" DEFINITION_CONTENTS)
22
23    string(REGEX MATCH "autogen definitions ([a-zA-Z\\._-]+);[${WS}]*" TEMPLATE_MATCH "${DEFINITION_CONTENTS}")
24    if (NOT TEMPLATE_MATCH)
25        message(FATAL_ERROR "${DEFINITION_FILENAME} doest not contain an AutoGen definition.")
26    endif()
27
28    get_filename_component(DEFINITION_DIR "${DEFINITION_FILENAME}" PATH)
29    set(${TEMPLATE_FILENAME} "${DEFINITION_DIR}/${CMAKE_MATCH_1}" PARENT_SCOPE)
30    if (DEBUG)
31        message("found: TEMPLATE_FILENAME=${CMAKE_MATCH_1}")
32    endif()
33
34    cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${TEMPLATE_MATCH}" DEFINITION_CONTENTS)
35
36    set(DEFINITION "")
37
38    while (1)
39        string(REGEX MATCH "([a-zA-Z_][a-zA-Z0-9_]*)[${WS}]*=[${WS}]*{[${WS}]*" GROUPSTART_MATCH "${DEFINITION_CONTENTS}")
40        if (NOT GROUPSTART_MATCH)
41            break()
42        endif()
43        set(GROUPNAME "${CMAKE_MATCH_1}")
44        cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${GROUPSTART_MATCH}" DEFINITION_CONTENTS)
45        if (DEBUG)
46            message("found: GROUPNAME=${GROUPNAME}")
47        endif()
48        set(NBKEYS 0)
49        set(GROUP_KEY_VALUES "")
50        while (1)
51            string(REGEX MATCH "^([a-zA-Z_][a-zA-Z0-9_]*)[${WS}]*=[${WS}]*(([\"']([${WS}a-zA-Z0-9_%\\\"<>\(\)\\.*+/?:,\\-]+)[\"'])|([a-zA-Z0-9_%\\]+))[${WS}]*;[${WS}]*" KEY_VALUE_MATCH "${DEFINITION_CONTENTS}")
52            if (NOT KEY_VALUE_MATCH)
53                break()
54            endif()
55            set(KEY "${CMAKE_MATCH_1}")
56            if ("${CMAKE_MATCH_4}" STREQUAL "")
57                set(VALUE "${CMAKE_MATCH_5}")
58            else()
59                string(REPLACE "\\\"" "\"" VALUE "${CMAKE_MATCH_4}")
60                #set(VALUE "${CMAKE_MATCH_4}")
61            endif()
62
63            if (DEBUG)
64                message("found: KEY=${KEY}, VALUE=${VALUE}")
65            endif()
66            math(EXPR NBKEYS "${NBKEYS}+1")
67            list(APPEND GROUP_KEY_VALUES "${KEY}" "${VALUE}")
68            cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${KEY_VALUE_MATCH}" DEFINITION_CONTENTS)
69        endwhile()
70        string(REGEX MATCH "^[${WS}]*}[${WS}]*;[${WS}]*" GROUPEND_MATCH "${DEFINITION_CONTENTS}")
71        if (NOT GROUPEND_MATCH)
72            message(FATAL_ERROR "Group ${GROUPNAME} did not finish.")
73        endif()
74        cutoff_first_occurrence("${DEFINITION_CONTENTS}" "${GROUPEND_MATCH}" DEFINITION_CONTENTS)
75        list(APPEND DEFINITION "${GROUPNAME}" ${NBKEYS} ${GROUP_KEY_VALUES})
76    endwhile()
77    set(${DATA} "${DEFINITION}" PARENT_SCOPE)
78endfunction()
79
80function(match_autogen_group TEXT START POS0 POS1 MATCH FOUND)
81    string(SUBSTRING "${TEXT}" "${START}" -1 TEXT)
82    string(REGEX MATCH "\\[\\+[${WS}]*([ a-zA-Z0-9=_$%\\(\\)\"\\+\\-]+)[${WS}]*\\+\\]" MATCH_GROUP "${TEXT}")
83    if ("${MATCH_GROUP}" STREQUAL "")
84        set(${FOUND} 0 PARENT_SCOPE)
85        return()
86    endif()
87    string(FIND "${TEXT}" "${MATCH_GROUP}" START_TEXT)
88    math(EXPR POS0_var "${START}+${START_TEXT}")
89    string(LENGTH "${MATCH_GROUP}" MATCH_LENGTH)
90    math(EXPR POS1_var "${POS0_var}+${MATCH_LENGTH}")
91    set(${POS0} "${POS0_var}" PARENT_SCOPE)
92    set(${POS1} "${POS1_var}" PARENT_SCOPE)
93    set(${FOUND} 1 PARENT_SCOPE)
94    string(STRIP "${CMAKE_MATCH_1}" CONTENT)
95    set("${MATCH}" "${CONTENT}" PARENT_SCOPE)
96endfunction()
97
98function(append_output SUFFICES_FILENAMES TEXT POS0 POS1 FILTER)
99    math(EXPR POS_LENGTH "${POS1}-${POS0}")
100    string(LENGTH "${TEXT}" TEXT_LENGTH)
101    string(SUBSTRING "${TEXT}" "${POS0}" "${POS_LENGTH}" TEXT_APPEND)
102    if (DEBUG)
103        message("appending ${POS0}:${POS1}, length=${POS_LENGTH}")
104    endif()
105    append_output_text("${SUFFICES_FILENAMES}" "${TEXT_APPEND}" "${FILTER}")
106endfunction()
107
108function(append_output_text SUFFICES_FILENAMES TEXT_APPEND FILTER)
109    string(LENGTH "${TEXT_APPEND}" TEXT_LENGTH)
110    list(LENGTH SUFFICES_FILENAMES NB)
111    math(EXPR NB_END "${NB}-1")
112    foreach(INDEX RANGE 0 ${NB_END} 3)
113        math(EXPR INDEX_1 "${INDEX}+1")
114        math(EXPR INDEX_2 "${INDEX}+2")
115        list(GET SUFFICES_FILENAMES ${INDEX} SUFFIX)
116        list(GET SUFFICES_FILENAMES ${INDEX_1} FILENAME)
117        list(GET SUFFICES_FILENAMES ${INDEX_2} TEMPFILENAME)
118        set(WRITE_OK 1)
119        if (FILTER)
120            if (NOT "${SUFFIX}" STREQUAL "${FILTER}")
121                set(WRITE_OK 0)
122            endif()
123        endif()
124        if (WRITE_OK)
125            if (DEBUG)
126                message("Write: ${TEXT_LENGTH} characters to ${FILENAME}")
127            endif()
128            file(APPEND "${TEMPFILENAME}" "${TEXT_APPEND}")
129        endif()
130    endforeach()
131endfunction()
132
133function(output_finish SUFFICES_FILENAMES)
134    list(LENGTH SUFFICES_FILENAMES NB)
135    math(EXPR NB_END "${NB}-1")
136    foreach(INDEX RANGE 0 ${NB_END} 3)
137        math(EXPR INDEX_1 "${INDEX}+1")
138        math(EXPR INDEX_2 "${INDEX}+2")
139        list(GET SUFFICES_FILENAMES ${INDEX_1} FILENAME)
140        list(GET SUFFICES_FILENAMES ${INDEX_2} TEMPFILENAME)
141        file(RENAME "${TEMPFILENAME}" "${FILENAME}")
142    endforeach()
143endfunction()
144
145function(stack_push STACK_ARG)
146    set(STACK_LIST "${${STACK_ARG}}")
147    string(REPLACE ";" " " NEWITEM "${ARGN}")
148    if (DEBUG)
149        list(LENGTH STACK_LIST STACK_LENGTH)
150        message("Pushing \"${NEWITEM}\" onto stack (length=${STACK_LENGTH})")
151    endif()
152    list(APPEND STACK_LIST "${NEWITEM}")
153    set(${STACK_ARG} "${STACK_LIST}" PARENT_SCOPE)
154endfunction()
155
156function(stack_pop STACK_ARG ITEM)
157    set(STACK_LIST "${${STACK_ARG}}")
158    list(LENGTH STACK_LIST STACK_LENGTH)
159    if (STACK_LENGTH EQUAL 0)
160        message(FATAL_ERROR "ENDFOR: stack is empty")
161    endif()
162    math(EXPR LAST_ITEM_INDEX "${STACK_LENGTH}-1")
163    list(GET STACK_LIST "${LAST_ITEM_INDEX}" LAST_ITEM)
164    list(REMOVE_AT STACK_LIST "${LAST_ITEM_INDEX}")
165    string(REPLACE " " ";" LAST_ITEM_LIST "${LAST_ITEM}")
166    if (DEBUG)
167        message("Popping \"${LAST_ITEM}\" from stack (length=${STACK_LENGTH})")
168    endif()
169    set(${ITEM} "${LAST_ITEM_LIST}" PARENT_SCOPE)
170    set(${STACK_ARG} "${STACK_LIST}" PARENT_SCOPE)
171endfunction()
172
173function(stack_top STACK_ARG ITEM)
174    set(STACK_LIST "${${STACK_ARG}}")
175    list(LENGTH STACK_LIST STACK_LENGTH)
176    if (STACK_LENGTH EQUAL 0)
177        message(FATAL_ERROR "ENDFOR: stack is empty")
178    endif()
179    math(EXPR LAST_ITEM_INDEX "${STACK_LENGTH}-1")
180    list(GET STACK_LIST "${LAST_ITEM_INDEX}" LAST_ITEM)
181    string(REPLACE " " ";" LAST_ITEM_LIST "${LAST_ITEM}")
182    if (DEBUG)
183        message("Top of stack: \"${LAST_ITEM}\" from stack (length=${STACK_LENGTH})")
184    endif()
185    set(${ITEM} "${LAST_ITEM_LIST}" PARENT_SCOPE)
186endfunction()
187
188function(stack_find_key STACK_LIST TEMPLATE_PARAMETERS KEY VALUE)
189    list(REVERSE STACK_LIST)
190    foreach(STACK_ITEM ${STACK_LIST})
191        string(REPLACE " " ";" STACK_ITEM_LIST "${STACK_ITEM}")
192        list(GET STACK_ITEM_LIST 3 TP_INDEX)
193        math(EXPR TP_SIZE_INDEX "${TP_INDEX}+1")
194        list(GET TEMPLATE_PARAMETERS ${TP_SIZE_INDEX} TP_SIZE)
195        math(EXPR TP_KV_INDEX_START "${TP_INDEX}+2")
196        math(EXPR TP_KV_INDEX_END "${TP_KV_INDEX_START}+2*${TP_SIZE}-1")
197        foreach(TP_KV_INDEX RANGE ${TP_KV_INDEX_START} ${TP_KV_INDEX_END} 2)
198            list(GET TEMPLATE_PARAMETERS ${TP_KV_INDEX} TP_KEY)
199            if("${TP_KEY}" STREQUAL "${KEY}")
200                math(EXPR TP_VALUE_INDEX "${TP_KV_INDEX}+1")
201                list(GET TEMPLATE_PARAMETERS ${TP_VALUE_INDEX} TP_VALUE)
202                set(${VALUE} "${TP_VALUE}" PARENT_SCOPE)
203                return()
204            endif()
205        endforeach()
206    endforeach()
207    message(FATAL_ERROR "Unknown KEY=${KEY}")
208endfunction()
209
210function(template_parameters_find_next_groupname_index TEMPLATE_PARAMETERS GROUPNAME INDEX_LAST INDEX_NEXT)
211    if (${INDEX_LAST} LESS 0)
212        set(INDEX 0)
213    else ()
214        math(EXPR INDEX_1 "1+(${INDEX_LAST})")
215        list(GET TEMPLATE_PARAMETERS ${INDEX_1} GROUPNAME_INDEX_SIZE)
216        math(EXPR INDEX "${INDEX_LAST}+1+2*${GROUPNAME_INDEX_SIZE}+1")
217    endif()
218    list(LENGTH TEMPLATE_PARAMETERS PARAMETERS_LENGTH)
219    while (${INDEX} LESS ${PARAMETERS_LENGTH})
220        list(GET TEMPLATE_PARAMETERS ${INDEX} GROUPNAME_AT_INDEX)
221        if ("${GROUPNAME}" STREQUAL "${GROUPNAME_AT_INDEX}")
222            set("${INDEX_NEXT}" ${INDEX} PARENT_SCOPE)
223            return()
224        endif()
225        math(EXPR INDEX_1 "${INDEX}+1")
226        list(GET TEMPLATE_PARAMETERS ${INDEX_1} GROUPNAME_INDEX_SIZE)
227        math(EXPR INDEX "${INDEX}+1+2*${GROUPNAME_INDEX_SIZE}+1")
228    endwhile()
229    set("${INDEX_NEXT}" -1 PARENT_SCOPE)
230endfunction()
231
232function(calculate_line_number TEXT POSITION LINENUMBER_ARG)
233    #math(EXPR INDEX_MAX "${POSITION}-1")
234    string(SUBSTRING "${TEXT}" 0 ${POSITION} SUBTEXT)
235    string(REGEX MATCHALL "\n" MATCH_NEWLINES "${SUBTEXT}")
236    list(LENGTH MATCH_NEWLINES NBLINES)
237    math(EXPR NBLINES "${NBLINES}+1")
238    set(${LINENUMBER_ARG} ${NBLINES} PARENT_SCOPE)
239endfunction()
240
241function(parse_template TEMPLATE_FILENAME OUTPUT_DIR TEMPLATE_PARAMETERS)
242    file(READ ${TEMPLATE_FILENAME} TEMPLATE_CONTENTS)
243    set(POSITION 0)
244    match_autogen_group("${TEMPLATE_CONTENTS}" "${POSITION}" POS0 POS1 AUTOGEN FOUND)
245    if (NOT FOUND)
246        message(FATAL_ERROR "Header of template not found")
247    endif()
248    string(REGEX MATCH "AutoGen5 template ([ a-zA-Z0-9]*)" SUFFICES_MATCH "${AUTOGEN}")
249    if (NOT SUFFICES_MATCH)
250        message(FATAL_ERROR "No output suffices found")
251    endif()
252    string(STRIP "${CMAKE_MATCH_1}" SUFFICES)
253    string(REPLACE " " ";" SUFFICES "${SUFFICES}")
254    set(SUFFICES_FILENAMES "")
255    get_filename_component(TEMPLATE_NAME_WE "${TEMPLATE_FILENAME}" NAME_WE)
256    foreach(SUFFIX ${SUFFICES})
257        if ("${OUTPUT_DIR}" STREQUAL "")
258            set(DIR_PREFIX "")
259        else()
260            set(DIR_PREFIX "${OUTPUT_DIR}/")
261        endif()
262        string(RANDOM LENGTH 64 RANDOMSTRING)
263        set(FILENAME "${DIR_PREFIX}${TEMPLATE_NAME_WE}.${SUFFIX}")
264        set(TEMPFILENAME "${DIR_PREFIX}${TEMPLATE_NAME_WE}${RANDOMSTRING}.${SUFFIX}")
265        list(APPEND SUFFICES_FILENAMES "${SUFFIX}" "${FILENAME}" "${TEMPFILENAME}")
266        file(WRITE "${FILENAME}" "")
267    endforeach()
268    if (DEBUG)
269        message("Output files: ${SUFFICES_FILENAMES}")
270    endif()
271    set(WRITE_FILTER "")
272    append_output("${SUFFICES_FILENAMES}" "${TEMPLATE_CONTENTS}" 0 "${POS0}" "${WRITE_FILTER}")
273    math(EXPR POS1 "${POS1}+1")
274    set(POSITION "${POS1}")
275    if (DEBUG)
276        message("Output: ${SUFFICES_FILENAMES}")
277    endif()
278
279    set(STACK "")
280    while (1)
281        match_autogen_group("${TEMPLATE_CONTENTS}" "${POSITION}" POS0 POS1 GROUP_MATCH FOUND)
282        if (NOT FOUND)
283            if (DEBUG)
284                message("No group found. Dumping rest of file.")
285            endif()
286            if (NOT "${STACK}" STREQUAL "")
287                message(FATAL_ERROR "Stack not empty at end of file")
288            endif()
289            string(LENGTH "${TEMPLATE_CONTENTS}" TEXT_LENGTH)
290            append_output("${SUFFICES_FILENAMES}" "${TEMPLATE_CONTENTS}" ${POSITION} ${TEXT_LENGTH} "${WRITE_FILTER}")
291            break()
292        endif()
293        append_output("${SUFFICES_FILENAMES}" "${TEMPLATE_CONTENTS}" ${POSITION} ${POS0} "${WRITE_FILTER}")
294        set(POSITION "${POS1}")
295
296        if (GROUP_MATCH MATCHES "^FOR")
297            string(REPLACE " " ";" GROUP_MATCH_LIST "${GROUP_MATCH}")
298            list(GET GROUP_MATCH_LIST 1 FOR_KEY)
299            template_parameters_find_next_groupname_index("${TEMPLATE_PARAMETERS}" "${FOR_KEY}" -1 FOR_INDEX)
300            if (DEBUG)
301                message("FOR_KEY: ${FOR_KEY}")
302                message("FOR_INDEX: ${FOR_INDEX}")
303            endif()
304            if (${FOR_KEY} LESS 0)
305                message(FATAL_ERROR "FOR has key with empty list. Not implemented yet..")
306            endif()
307            stack_push(STACK FOR ${POSITION} ${FOR_KEY} ${FOR_INDEX})
308        elseif (GROUP_MATCH MATCHES "^ENDFOR")
309            string(REPLACE " " ";" GROUP_MATCH_LIST "${GROUP_MATCH}")
310            list(GET GROUP_MATCH_LIST 1 ENDFOR_KEY)
311            stack_pop(STACK FOR_ITEM)
312            list(GET FOR_ITEM 0 FOR_FOR)
313            if (NOT "${FOR_FOR}" STREQUAL "FOR")
314                message(FATAL_ERROR "ENDFOR does not match last item: ${FOR_FOR}")
315            endif()
316            list(GET FOR_ITEM 1 FOR_POSITION)
317            list(GET FOR_ITEM 2 FOR_KEY)
318            if (NOT "${FOR_KEY}" STREQUAL "${ENDFOR_KEY}")
319                calculate_line_number("${TEMPLATE_CONTENTS}" "${POSITION}" LINENUMBER)
320                message("FOR and ENDFOR do not match. (line number ${LINENUMBER}) (FOR:${FOR_KEY}, ENDFOR:${ENDFOR_KEY})")
321            endif()
322            list(GET FOR_ITEM 3 FOR_INDEX_PREV)
323            template_parameters_find_next_groupname_index("${TEMPLATE_PARAMETERS}" "${FOR_KEY}" ${FOR_INDEX_PREV} FOR_INDEX)
324            if (DEBUG)
325                message("FOR_INDEX was ${FOR_INDEX_PREV}, is now ${FOR_INDEX}")
326            endif()
327            if (${FOR_INDEX} LESS 0)
328                if (DEBUG)
329                    message("ENDFOR: FOR_INDEX < 0 (no more key) ==> Continue")
330                endif()
331            else()
332                set(POSITION ${FOR_POSITION})
333                stack_push(STACK FOR ${FOR_POSITION} ${FOR_KEY} ${FOR_INDEX})
334                if (DEBUG)
335                    message("ENDFOR: FOR_INDEX >= 0 (more keys available) ==> Back to position=${FOR_POSITION}")
336                endif()
337            endif()
338        elseif (GROUP_MATCH MATCHES "^CASE")
339            string(REGEX MATCH "^CASE[${WS}]+\\(([a-zA-Z]+)\\)" CASE_MATCH "${GROUP_MATCH}")
340            if ("${CASE_MATCH}" STREQUAL "")
341                message(FATAL_ERROR "Wrong CASE syntax")
342            endif()
343            set(CASE_KEY "${CMAKE_MATCH_1}")
344            if (DEBUG)
345                message("CASE: KEY=${CASE_KEY}")
346            endif()
347            stack_push(STACK CASE "${CASE_KEY}" ${POSITION})
348        elseif (GROUP_MATCH MATCHES "^==")
349            math(EXPR POSITION "${POSITION}+1")
350            string(REGEX MATCH "^==[${WS}]+([a-zA-Z_][a-zA-Z0-9_]*)" CASE_MATCH "${GROUP_MATCH}")
351            if ("${CASE_MATCH}" STREQUAL "")
352                message(FATAL_ERROR "Wrong == syntax")
353            endif()
354            stack_top(STACK CASE_ITEM)
355            list(GET CASE_ITEM 0 CASE_CASE)
356            if(NOT "${CASE_CASE}" STREQUAL "CASE")
357                message(FATAL_ERROR "== block must be in CASE. Top of stack=${CASE_CASE}")
358            endif()
359            set(CASE_VALUE "${CMAKE_MATCH_1}")
360            if (DEBUG)
361                message("case: == VALUE=${CASE_VALUE}")
362            endif()
363            list(GET CASE_ITEM 1 CASE_KEY)
364            if ("${CASE_KEY}" STREQUAL "suffix")
365                if (DEBUG)
366                    message("Setting write filter to ${CASE_VALUE}")
367                endif()
368                set(WRITE_FILTER "${CASE_VALUE}")
369            else()
370                message(FATAL_ERROR "CASE: unsupported argument ${CASE_KEY}")
371            endif()
372        elseif (GROUP_MATCH MATCHES "^ESAC")
373            stack_pop(STACK CASE_ITEM)
374            if (DEBUG)
375                message("ESAC")
376            endif()
377            list(GET CASE_ITEM 0 CASE_CASE)
378            if (NOT "${CASE_CASE}" STREQUAL "CASE")
379                message(FATAL_ERROR "ESAC does not match last item: ${CASE_CASE}")
380            endif()
381            if ("${CASE_KEY}" STREQUAL "suffix")
382                if (DEBUG)
383                    message("Removing write filter")
384                endif()
385                set(WRITE_FILTER "")
386            else()
387                message(FATAL_ERROR "CASE: unsupported argument ${CASE_KEY}")
388            endif()
389        else()
390            string(REGEX MATCH "\\(([a-zA-Z0-9_$%\"${WS}\\+\\-]+)\\)" PARENTHESE_MATCH "${GROUP_MATCH}")
391            if (NOT "${PARENTHESE_MATCH}" STREQUAL "")
392                set(PARENTHESE_CONTENT "${CMAKE_MATCH_1}")
393                string(REPLACE " " ";" PARENTHESE_LIST "${PARENTHESE_CONTENT}")
394                list(GET PARENTHESE_LIST 0 PARENTHESE_COMMAND)
395                if ("${PARENTHESE_COMMAND}" STREQUAL "get")
396                    list(GET PARENTHESE_LIST 1 KEY_QUOTED)
397                    string(REGEX MATCH "\\\"([a-zA-Z_${WS}]+)\\\"" KEY_MATCH "${KEY_QUOTED}")
398                    if ("${KEY_MATCH}" STREQUAL "")
399                        message(FATAL_ERROR "get: empty key")
400                    endif()
401                    set(KEY "${CMAKE_MATCH_1}")
402                    if (DEBUG)
403                        message("Get: key=${KEY}")
404                    endif()
405                    stack_find_key("${STACK}" "${TEMPLATE_PARAMETERS}" "${KEY}" VALUE)
406                    if (DEBUG)
407                        message("Get key=${KEY} ==> value=${VALUE}")
408                    endif()
409                    append_output_text("${SUFFICES_FILENAMES}" "${VALUE}" "${WRITE_FILTER}")
410                elseif("${PARENTHESE_COMMAND}" STREQUAL "tpl-file-line")
411                    list(GET PARENTHESE_LIST 1 FORMAT_LINE)
412                    calculate_line_number("${TEMPLATE_CONTENTS}" "${POSITION}" LINENUMBER)
413                    append_output_text("${SUFFICES_FILENAMES}" "${LINENUMBER}" "${WRITE_FILTER}")
414                else()
415                    message(FATAL_ERROR "Unknown parenthese command: ${PARENTHESE_COMMAND}")
416                endif()
417            else()
418                message(FATAL_ERROR "Unknown command: ${GROUP_MATCH}")
419            endif()
420        endif()
421
422    endwhile()
423    if (NOT "${STACK}" STREQUAL "")
424        message(FATAL_ERROR "STACK was not empty at EOF")
425    endif()
426    output_finish("${SUFFICES_FILENAMES}")
427endfunction()
428
429if ("${DEFINITION}" STREQUAL "")
430    message(FATAL_ERROR "Need definition file")
431endif()
432if (NOT EXISTS "${DEFINITION}")
433    message(FATAL_ERROR "Definition file does not exist (${DEFINITION})")
434endif()
435
436read_definition("${DEFINITION}" TEMPLATE_FILENAME DATA)
437if (DEBUG)
438    message("${TEMPLATE_FILENAME}")
439    message("${DATA}")
440endif()
441
442parse_template("${TEMPLATE_FILENAME}" "${OUTPUTDIR}" "${DATA}")
443