1m4_divert(-1)
2
3dnl This m4 file includes macro definitions for:
4dnl - application independent helper macros used here and by other m4 files.
5dnl - defining the main code generation macro m4_all_code.
6
7dnl Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
8dnl Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
9dnl
10dnl This file is part of the Parma Polyhedra Library (PPL).
11dnl
12dnl The PPL is free software; you can redistribute it and/or modify it
13dnl under the terms of the GNU General Public License as published by the
14dnl Free Software Foundation; either version 3 of the License, or (at your
15dnl option) any later version.
16dnl
17dnl The PPL is distributed in the hope that it will be useful, but WITHOUT
18dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19dnl FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20dnl for more details.
21dnl
22dnl You should have received a copy of the GNU General Public License
23dnl along with this program; if not, write to the Free Software Foundation,
24dnl Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
25dnl
26dnl For the most up-to-date information see the Parma Polyhedra Library
27dnl site: http://bugseng.com/products/ppl/ .
28
29dnl ---------------------------------------------------------------------
30dnl           --- MACRO GROUPS and DEPENDENCIES ---
31dnl
32dnl For ease of keeping track of these macros and their dependencies,
33dnl the macro definitions are separated by the "===" comments into groups.
34dnl
35dnl Where a macro is only used within the group, it is labelled as "LOCAL".
36dnl Where it is used in this file but by another macro group, it is
37dnl labelled as "PRIVATE" and an indication of which group uses it.
38dnl Where it may be used in the generator files, it is labelled
39dnl as "PUBLIC".
40dnl
41dnl Some simple macros may be redefined by generator files and we
42dnl indicate that here is the default definition by the label
43dnl "DEFAULT DEF".
44dnl
45dnl The macro groups and the dependencies are:
46dnl
47dnl HELPERS (m4_forloop, m4_upcase, m4_downcase, m4_capfirstletter,
48dnl          m4_capfirstletters, m4_changecase, m4_add_one_after_underscore,
49dnl          m4_ifndef, m4_nargs, m4_arg, m4_arg_counter, m4_echo_unquoted,
50dnl          m4_echo_quoted, m4_seq_intersection, m4_seq_difference
51dnl          are all public.)
52dnl          WARNING: some may not be used and may not be fully tested.
53dnl
54dnl ALL_CLASSES (m4_all_code is public)
55dnl |-- m4_interface_generator_common_dat.m4 (m4_init_class_definitions)
56dnl `-- ONE_CLASS (m4_one_class_code)
57dnl     |-- FILTER_PROCEDURES (m4_filter_all_procedures)
58dnl     |   `-- m4_interface_generator_common_dat.m4 (m4_group_names)
59dnl     |-- PATTERNS_TO_REPLACEMENTS (m4_replace_all_patterns_in_string)
60dnl     |-- PATTERNS (m4_pattern_annotation0, ...)
61dnl     |-- REPLACEMENT_TEXT (m4_annotated_pattern_replacement,
62dnl     |   |                 m4_def_replacements_for_extended_patterns,
63dnl     |   |                 m4_def_extended_replacements)
64dnl     |   |-- PATTERNS (m4_pattern_extension0, ...)
65dnl     |   `-- m4_interface_generator_common_dat.m4
66dnl     |         (m4_class_pattern_replacements)
67dnl     |-- m4_interface_generator_<interface>_procedure_generator.m4
68dnl     |    (m4_procedure_list)
69dnl     `-- EXPAND_PROCEDURES (m4_get_schematic_code)
70dnl
71dnl Note that the macro names indicate that they are used by the parent
72dnl macro group.
73dnl ---------------------------------------------------------------------
74
75dnl =====================================================================
76dnl           *** HELPERS ****
77dnl  The following are application independent helper macros
78dnl =====================================================================
79
80dnl All these helper macros are intended to be "PUBLIC"
81dnl except for auxiliary macros, labelled as "LOCAL".
82
83dnl m4_forloop(Iteration_Var, From_Value, To_Value, Loop_Body)
84dnl
85dnl Code copied from m4 documentation.
86m4_define(`m4_forloop',
87  `m4_pushdef(`$1', `$2')_m4_forloop(`$1', `$2', `$3', `$4')m4_popdef(`$1')')
88m4_define(`_m4_forloop',
89  `$4`'m4_ifelse($1, `$3', ,
90    `m4_define(`$1', m4_incr($1))_m4_forloop(`$1', `$2', `$3', `$4')')')
91
92
93dnl m4_upcase(String), m4_downcase(String)
94dnl
95dnl Code copied from m4 documentation.
96dnl Examples: m4_upcase(`abCd')   ==> ABCD
97dnl           m4_downcase(`abCd') ==> abcd
98m4_define(`m4_upcase', `m4_translit(`$*', `a-z', `A-Z')')
99m4_define(`m4_downcase', `m4_translit(`$*', `A-Z', `a-z')')
100
101dnl m4_capfirstletter(String)
102dnl
103dnl Capitalises first letter of words that can have letters and underscores.
104dnl Example: m4_capfirstletter(`xyz_abc') ==> Xyz_abc
105m4_define(`m4_capfirstletter',
106  `m4_regexp(`$1', `^\(\w\)\([\w_]*\)',
107     m4_upcase(`\1')`\2')')
108
109dnl m4_capfirstletters(String)
110dnl
111dnl Capitalises first letter of subwords that can have letters only.
112dnl Example: m4_capfirstletter(`xyz_abc') ==> Xyz_Abc
113m4_define(`m4_capfirstletters',
114  `m4_ifelse(m4_index(`$1', `_'), -1,
115     `m4_regexp(`$1', `^\(\w\)\(\w*\)',
116       `m4_upcase(`\1')`\2'')',
117         m4_regexp(`$1', `^\(\w\)\(\w*_\)\(\w\)\(\w*\)',
118           `m4_upcase(`\1')`\2'm4_upcase(`\3')`\4''))')
119
120m4_define(`m4_changecase',
121  `m4_ifelse(m4_regexp(`$1', `[A-Z]'), -1,
122    m4_capfirstletters($1),
123    m4_downcase($1))`'dnl
124')
125
126
127dnl m4_add_one_after_underscore(String)
128dnl
129dnl Adds a 1 after any underscore (needed for Java interface code)..
130dnl Example: m4_capfirstletter(`xyz_abc') ==> xyz_1abc
131m4_define(`m4_add_one_after_underscore', `m4_patsubst(`$1', `_', `_1')')
132
133dnl m4_ifndef(Macro, Default Definition)
134dnl
135dnl If Macro is defined, use that definition;
136dnl otherwise use the Default Definition.
137m4_define(`m4_ifndef', `m4_ifdef(`$1', $1, $2)')
138
139dnl m4_nargs expands to the number of arguments.
140dnl
141dnl Code copied from m4 documentation.
142m4_define(`m4_nargs', `$#')
143
144dnl m4_arg(Ind, Arg1, Arg2, ...)
145dnl
146dnl m4_arg expands to Arg`'Ind
147m4_define(`m4_arg',
148`m4_ifelse($1, 0, , $1, 1, $2, `m4_arg(m4_decr($1), m4_shift(m4_shift($@)))')')
149
150dnl m4_arg_counter(String, Arg1, Arg2, ...)
151dnl
152dnl If String = Arg`'Counter, m4_arg_counter expands to Counter
153dnl where Counter is the least index for which this holds.
154dnl Otherwise it expands to the empty string.
155m4_define(`m4_arg_counter', `m4_arg_counter_aux(1, $@)')
156
157dnl LOCAL
158m4_define(`m4_arg_counter_aux', `dnl
159m4_ifelse($#, 0, ,$#, 1, , $#, 2, ,
160  $2, $3, $1,
161  $#, 3, ,
162  `m4_arg_counter_aux(m4_incr($1), $2, m4_shift(m4_shift(m4_shift($@))))')`'dnl
163')
164
165dnl m4_echo_unquoted(Args)
166dnl
167dnl Code copied from m4 documentation where it is called echo1.
168m4_define(`m4_echo_unquoted', `$*')
169dnl m4_echo_quoted(Args)
170dnl
171dnl Code copied from m4 documentation where it is called echo2.
172m4_define(`m4_echo_quoted', `$@')
173
174dnl ----------------------------------------------------------------------
175dnl m4_two_seq_intersection,
176dnl m4_three_seq_intersection and helper macros
177dnl
178dnl These find the intersection of two and three sequences, respectively.
179dnl ----------------------------------------------------------------------
180dnl
181dnl m4_seq_intersection
182dnl
183dnl This macro with its helper macros below,
184dnl intersects two or three sequences that must be previously defined
185dnl as `m4_1st_sequence', `m4_2nd_sequence' and, if there is a third,
186dnl `m4_3rd_sequence'. The number of sequences (2 or 3) must also be defined
187dnl by the macro `m4_number_of_sequences'. The order of the
188dnl intersected sequence is that of m4_1st_sequence.
189dnl
190dnl For example, if m4_1st_sequence is defined to be `a, b, c, d' and
191dnl m4_2nd_sequence is defined to be `b, d, e, a, f',
192dnl this macro is defined to be `a, b, d'.
193m4_define(`m4_seq_intersection', `dnl
194m4_define(`m4_add_one_first', 1)`'dnl
195m4_patsubst(m4_seq_intersection_aux(m4_1st_sequence),
196            |COMMA|, `, ')`'dnl
197')
198
199dnl LOCAL
200dnl m4_seq_intersection_aux(...)
201dnl
202dnl The arguments are the first sequence to be intersected.
203dnl It calls either the helper macro for 3 sequences or the helper
204dnl macro for 2 sequences (depending on the number of sequences).
205dnl It calls itself recursively with the tail of the sequence.
206m4_define(`m4_seq_intersection_aux', `dnl
207m4_ifelse($#, 0, , $#, 1,
208  m4_`'m4_num_of_sequences`'_seq_intersection_aux($1, m4_2nd_sequence),
209  m4_`'m4_num_of_sequences`'_seq_intersection_aux($1, m4_2nd_sequence)`'dnl
210`m4_seq_intersection_aux(m4_shift($@))')`'dnl
211')
212
213dnl LOCAL
214dnl m4_3_seq_intersection_aux(String, ...)
215dnl
216dnl This is defined to be `String' if `String' also occurs
217dnl in the 2nd or in a later argument position
218dnl as well as in m4_3rd_sequence.
219dnl It calls itself recursively with the tail of the sequence.
220m4_define(`m4_3_seq_intersection_aux', `dnl
221m4_ifelse($#, 0, , $#, 1, , $#, 2,
222  `m4_ifelse($1, $2, `m4_2_seq_intersection_aux($1, m4_3rd_sequence)')',
223  `m4_ifelse($1, $2, `m4_2_seq_intersection_aux($1, m4_3rd_sequence)',
224`m4_3_seq_intersection_aux($1, m4_shift(m4_shift($@)))')')`'dnl
225')
226
227dnl LOCAL
228dnl m4_2_seq_intersection_aux(String, ...)
229dnl
230dnl This is defined to be `String' if `String' also occurs
231dnl in the 2nd or in a later argument position.
232dnl It calls itself recursively with the tail of the sequence.
233m4_define(`m4_2_seq_intersection_aux', `dnl
234m4_ifelse($#, 0, , $#, 1, , $#, 2,
235  `m4_ifelse($1, $2, `m4_add_one($1)')',
236  `m4_ifelse($1, $2, `m4_add_one($1)',
237`m4_2_seq_intersection_aux($1, m4_shift(m4_shift($@)))')')`'dnl
238')
239
240dnl LOCAL
241dnl m4_add_one(String)
242dnl
243dnl This separates the new sequence temporarily with |COMMA| to avoid
244dnl the `,' being mis-interpreted by m4.
245m4_define(`m4_add_one', `dnl
246m4_ifelse(m4_add_one_first, 1,
247  $1`'m4_undefine(`m4_add_one_first'), |COMMA|$1)`'dnl
248')
249
250dnl ----------------------------------------------------------------------
251dnl m4_seq_difference and helper macros
252dnl
253dnl This finds the difference of two sequences.
254dnl ----------------------------------------------------------------------
255dnl
256dnl m4_seq_difference
257dnl
258dnl CHECKME: Currently this macro is not used.
259dnl This macro with its helper macros below,
260dnl finds the difference of two sequences that must be previously defined
261dnl as `m4_1st_sequence', `m4_2nd_sequence'. The order of the
262dnl difference sequence is that of m4_1st_sequence.
263dnl
264dnl For example, if m4_1st_sequence is defined to be `a, b, c, d' and
265dnl m4_2nd_sequence is defined to be `d, e, a, f',
266dnl this macro is defined to be `b, c'.
267m4_define(`m4_seq_difference', `dnl
268m4_patsubst(m4_seq_difference_aux(m4_1st_sequence),
269            `^|COMMA|', `')`'dnl
270')
271m4_define(`m4_seq_differencexx', `dnl
272m4_patsubst(m4_patsubst(m4_seq_difference_aux(m4_1st_sequence),
273            `^|COMMA|', `'),
274            |COMMA|, `, ')`'dnl
275')
276
277dnl LOCAL
278dnl m4_seq_difference_aux(...)
279dnl
280dnl The arguments are the first sequence to be intersected.
281dnl It calls either the helper macro for 3 sequences or the helper
282dnl macro for 2 sequences (depending on the number of sequences).
283dnl It calls itself recursively with the tail of the sequence.
284m4_define(`m4_seq_difference_aux', `dnl
285m4_ifelse($#, 0, , $#, 1,
286  m4_2_seq_difference_aux($1, m4_2nd_sequence),
287  `m4_2_seq_difference_aux($1, m4_2nd_sequence)`'dnl
288m4_seq_difference_aux(m4_shift($@))')`'dnl
289')
290
291dnl LOCAL
292dnl m4_2_seq_difference_aux(String, ...)
293dnl
294dnl This is defined to be `String' if `String' does not occur
295dnl in the 2nd or in a later argument position.
296dnl It calls itself recursively with the tail of the sequence.
297m4_define(`m4_2_seq_difference_aux', `dnl
298m4_ifelse($#, 0, , $#, 1, `m4_add_one($1)', $#, 2,
299  `m4_ifelse($1, $2, , `m4_add_one($1)')',
300  `m4_ifelse($1, $2, ,
301`m4_2_seq_difference_aux($1, m4_shift(m4_shift($@)))')')`'dnl
302')
303
304dnl =====================================================================
305dnl              *** PATTERNS ***
306dnl Some processing that just involves the patterns themselves.
307dnl =====================================================================
308
309dnl ----------- General Info on Patterns --------------------------------
310dnl Each pattern can be plain, have an extension (eg "A_") and/or
311dnl be annotated by "!", and, for Java "1" where the
312dnl latter can be combined with a "!".
313dnl In the text being replaced, all patterns, extensions, and annotations
314dnl are in upper case and the complete pattern is bracketed by the pattern
315dnl delimiter.
316dnl ---------------------------------------------------------------------
317
318dnl PRIVATE
319dnl Used in macro-group "REPLACEMENT_TEXT"
320dnl
321dnl DEFAULT_DEF
322dnl m4_pattern_extension`'EIndex
323dnl
324dnl is defined for each allowed extension.
325dnl These options can be added to as needed by any of the generator files.
326dnl
327m4_define(`m4_pattern_extension0', `')
328m4_define(`m4_pattern_extension1', `A_')
329m4_define(`m4_pattern_extension2', `B_')
330
331dnl PRIVATE
332dnl Used in macro-group "PATTERNS_TO_REPLACEMENTS"
333dnl
334dnl m4_pattern_annotation`'AIndex
335dnl
336dnl is defined here for AIndex values 0 and 1.
337dnl - 0, which has the empty annotation,
338dnl   means that the actual replacement must be unchanged:
339dnl - 1, which has annotation !,
340dnl   means that the actual replacement must be:
341dnl   - lowercase, if the original has the first character uppercase, and
342dnl   - the first letter of each word ("_" separated) uppercase, otherwise.
343m4_define(`m4_pattern_annotation0', `')
344m4_define(`m4_pattern_annotation1', `!')
345
346dnl PUBLIC
347dnl m4_java_prefix_one_annotation
348dnl Only used by Java/jni/ppl_interface_generator_java_classes_cc_files.m4
349dnl as the extra annotations are only needed there.
350dnl PRIVATE
351dnl m4_pattern_annotation`'AIndex
352dnl Used in macro-group "PATTERNS_TO_REPLACEMENTS"
353dnl
354dnl m4_pattern_annotation`'AIndex is defined here for AIndex values 2 and 3:
355dnl - 2, which has annotation 1,
356dnl   means that the actual replacement must have a 1 after
357dnl   the underscore;
358dnl - 3, which has annotation 1!,
359dnl   means that the actual replacement must have a 1 after
360dnl   the underscore with the same change of case as for the annotation "!".
361m4_define(`m4_java_prefix_one_annotation',
362`m4_define(`m4_pattern_annotation2', `1')
363m4_define(`m4_pattern_annotation3', `1!')')
364
365dnl =====================================================================
366dnl              *** REPLACEMENT_TEXT ***
367dnl The precise replacing text is defined in
368dnl m4_interfaces_generator_common_dat.m4
369dnl We first retrieve this text by constructing the correct macro
370dnl for the extended pattern. We then define the additional text
371dnl processing needed based on the annotation of the pattern.
372dnl =====================================================================
373
374dnl LOCAL
375dnl DEFAULT_DEF
376dnl m4_replacement_extension`'EIndex
377dnl
378dnl is defined for each allowed extension EIndex.
379dnl This should correspond in lowercase to m4_pattern_extension.
380dnl
381m4_define(`m4_replacement_extension0', `')
382m4_define(`m4_replacement_extension1', `a_')
383m4_define(`m4_replacement_extension2', `b_')
384
385dnl PRIVATE
386dnl Used in macro-group "PATTERNS_TO_REPLACEMENTS".
387dnl
388dnl m4_def_replacements_for_extended_patterns(RIndex, EIndex)
389dnl m4_replace`'EIndex
390dnl
391dnl RIndex         - is the index of the replacement;
392dnl EIndex         - is the index of the extension.
393dnl For each possible EIndex value, m4_replace`'EIndex
394dnl is defined for the RIndex replacement.
395dnl
396m4_define(`m4_def_replacements_for_extended_patterns', `dnl
397m4_ifdef(`m4_pattern_extension$2',
398  `m4_define(`m4_replace$2',
399    `m4_arg($1, m4_replacements$2)')`'dnl
400m4_def_replacements_for_extended_patterns($1, m4_incr($2))`'dnl
401')`'dnl
402')
403
404dnl PRIVATE
405dnl Used in macro-group "PATTERNS_TO_REPLACEMENTS".
406dnl
407dnl m4_annotated_pattern_replacement`'AIndex(EIndex)
408dnl
409dnl where AIndex in {0..3}
410dnl Note that annotations 2 and 3 are only used by the Java interface.
411dnl
412dnl EIndex         - is the index of the extension.
413dnl
414dnl For each annotation and, for the single replacement
415dnl m4_replace`'EIndex (already defined for the current pattern),
416dnl this macro defines an exact replacement string to be used to
417dnl replace the annotated and extended pattern.
418dnl
419m4_define(`m4_annotated_pattern_replacement0',
420  `m4_replace$1')
421m4_define(`m4_annotated_pattern_replacement1',
422  `m4_changecase(m4_replace$1)')
423m4_define(`m4_annotated_pattern_replacement2',
424  `m4_add_one_after_underscore(m4_replace$1)')
425m4_define(`m4_annotated_pattern_replacement3',
426  `m4_add_one_after_underscore(m4_changecase(m4_replace$1))')
427
428dnl PRIVATE
429dnl Used in macro-group "PATTERNS_TO_REPLACEMENTS".
430dnl
431dnl m4_def_extended_replacements(Class_Counter, Pattern, EIndex)
432dnl m4_replacements`'EIndex
433dnl
434dnl Class_Counter    - The current class counter;
435dnl Pattern          - The current pattern;
436dnl EIndex           - is the index of the replacement macro name extension.
437dnl
438dnl m4_replacements`'EIndex is defined to be the list
439dnl of the replacements for Pattern with the EIndex extension
440dnl and for the class indicated by Class_Counter.
441dnl This uses m4_class_pattern_replacements/3 that is defined in
442dnl ppl_interface_generator_common_dat.m4 and uses the data for
443dnl the replacements defined in the same file.
444dnl
445m4_define(`m4_def_extended_replacements', `dnl
446m4_ifdef(m4_replacement_extension`'$3, `dnl
447m4_define(`m4_replacements$3',
448  `m4_class_pattern_replacements($1, $2, m4_replacement_extension$3)`'dnl
449m4_def_extended_replacements($1, $2, m4_incr($3))')')`'dnl
450')
451
452dnl =====================================================================
453dnl              *** EXPAND_PROCEDURES ***
454dnl  The next macros deal with expanding the schematic procedures.
455dnl =====================================================================
456
457dnl LOCAL
458dnl m4_get_arity(Procedure_Flags)
459dnl
460dnl Procedure_Flags - The schematic code flags.
461dnl
462dnl If the substring "/Arity" is found in the Procedure_Flags,
463dnl this macro expands to Arity.
464m4_define(`m4_get_arity', `m4_regexp(`$1', `/\([0-9]*\)', \1)')
465
466dnl LOCAL
467dnl m4_get_attribute(Procedure_Flags)
468dnl
469dnl Procedure_Flags - The schematic code flags.
470dnl
471dnl If the substring "*nofail" is found in the Procedure_Flags,
472dnl this macro expands to "nofail"
473dnl This is only needed for the Ciao system code.
474m4_define(`m4_get_attribute', `m4_regexp(`$1', `\*\(nofail\)', \1)')
475
476dnl We next define the default values for two extra macros
477dnl giving us more dynamic control by the individual code generators.
478
479dnl LOCAL
480dnl DEFAULT DEF
481dnl m4_procedure_schema_extension
482dnl
483dnl Normally, the procedure schema is defined using the extension `code'
484dnl but in the (Prolog) documentation this is varied according to the type of
485dnl the procedure.
486m4_define(`m4_procedure_schema_extension', `code')
487
488dnl LOCAL
489dnl DEFAULT DEF
490dnl m4_procedure_schema_debug
491dnl
492dnl the default is to do nothing;
493dnl However, by locally defining this to be
494dnl m4_dumpdef($1, m4_procedure_schema_extension, we can check
495dnl that all the procedure schemas are defined with the given extension.
496m4_define(`m4_procedure_schema_debug', `')
497
498dnl LOCAL
499dnl DEFAULT DEF
500dnl m4_expanded_procedure_schema(Procedure_Name,
501dnl                              [Arity, Attribute],
502dnl                              Start_Flag)
503dnl
504dnl Procedure_Name - The schematic name;
505dnl Arity          - The arity of the procedure;
506dnl Attribute      - The attribute `nofail' or `';
507dnl Start_Flag     - 0 suppresses any separator
508dnl                  (needed for expanding a comma separated list).
509dnl
510dnl The default definition.
511dnl Appends "_code" to Procedure_Name so that it can match the name
512dnl of one of the macros defined (if ever) in file *_code.m4 and get
513dnl therefore expanded to the corresponding code schema.
514dnl
515dnl Here arguments Arity and Attribute are ignored.
516dnl This macro is redefined when a different extension is needed.
517dnl (e.g., in the Prolog system files).
518dnl
519dnl Note: the macro `$1_code' has to be called using builtin `indir'
520dnl because it is not a legal m4 identifier (it contains `@').
521dnl
522dnl Some test generators and the Prolog system file generators redefine this
523dnl macro to construct the code directly from the schema name, arity
524dnl and its attributes.
525m4_define(`m4_expanded_procedure_schema',
526  `m4_ifdef($1_`'m4_procedure_schema_extension,
527            `m4_indir($1_`'m4_procedure_schema_extension)',
528            `m4_procedure_schema_debug($1)')`'dnl
529')
530
531dnl PRIVATE
532dnl Used in macro-group "ONE_CLASS".
533dnl
534dnl m4_get_schematic_code(Procedure_Spec, Start_Flag, Class_Kind)
535dnl
536dnl Procedure_Spec - The schematic procedure name, complete with any flags;
537dnl Start_Flag     - 0 suppresses any separator
538dnl                  (needed for expanding a comma separated list);
539dnl Class_Kind     - The current class kind.
540dnl
541dnl Procedure_Spec has the flags removed and expanded to the extended code.
542m4_define(`m4_get_schematic_code', `dnl
543m4_patsubst(`$1',
544         `[ ]*\(ppl_[^ /]+\)\(.*\)',
545         `m4_expanded_procedure_schema(\1, m4_get_arity(\2),
546                                       m4_get_attribute(\2), $2, $3)')`'dnl
547')
548
549dnl =====================================================================
550dnl              *** FILTER_PROCEDURES ***
551dnl ====== The next set of macros filter the procedure specifications   =
552dnl ====== according to the +/-group names in the extra flags in the    =
553dnl ====== procedure specification.                                     =
554dnl =====================================================================
555
556dnl LOCAL
557dnl m4_keep_or_throw_for_one_group(
558dnl     Class_Counter, Procedure_Spec, +_or_-, Group)
559dnl
560dnl Class_Counter   - The current class counter;
561dnl Procedure_Spec  - A schematic procedure name with flags still attached;
562dnl +_or_-          - + or -;
563dnl Group           - A group name.
564dnl
565dnl This checks if Class_Kind is in the list of class kinds defined
566dnl by Group (in ppl_interface_generator_common_dat.m4);
567dnl if it is, it checks if +Group or -Group
568dnl (depending if +_or_- is + or -) is included in the Procedure_Spec;
569dnl if it is, then it expands to 1, otherwise, expands to 0.
570m4_define(`m4_keep_or_throw_for_one_group', `dnl
571m4_ifelse(m4_arg_counter($1, m4_$4_group), `', 0,
572  `m4_ifelse(m4_index($2, $3$4), -1, 0, 1)')`'dnl
573')
574
575dnl LOCAL
576dnl m4_keep_or_throw(
577dnl     Class_Counter, Procedure_Spec, +_or_-, Group1, Group2, ...)
578dnl
579dnl Class_Counter   - The current class counter;
580dnl Procedure_Spec  - A schematic procedure name with flags still attached;
581dnl +_or_-          - + or -;
582dnl Group1          - A group name;
583dnl ....
584dnl Groupk          - A group name.
585m4_define(`m4_keep_or_throw', `dnl
586m4_ifelse($#, 0, 0, $#, 1, 0, $#, 2, 0, $#, 3, 0,
587  $#, 4, `m4_keep_or_throw_for_one_group($1, $2, $3, $4)',
588    `m4_ifelse(m4_keep_or_throw_for_one_group($1, $2, $3, $4), 1, 1,
589      `m4_keep_or_throw($1, $2, $3,
590                       m4_shift(m4_shift(m4_shift(m4_shift($@)))))')')`'dnl
591')
592
593dnl LOCAL
594dnl m4_filter_one_procedure(Class_Counter, Procedure_Spec)
595dnl
596dnl Class_Counter   - The current class counter;
597dnl Procedure_Spec  - A schematic procedure name with flags still attached.
598dnl
599dnl Keeps just those procedures that are wanted for the given class kind.
600dnl It first checks if there is a group in Procedure_Spec, whose
601dnl definition includes the Class_Kind, preceded by a "-",
602dnl if so, it expands to the empty string;
603dnl otherwise, it checks if there is a group in Procedure_Spec, whose
604dnl definition includes the Class_Kind, preceded by a "+",
605dnl if so, it expands to Procedure_Spec.
606m4_define(`m4_filter_one_procedure', `dnl
607m4_define(`m4_proc_info_string',
608       `m4_patsubst(`$2', `[ ]*ppl_[^ ]+ \(.*\)', \1)')`'dnl
609m4_ifelse(m4_keep_or_throw(m4_class_kind$1,
610                           m4_proc_info_string, -,
611                           m4_group_names),
612  1, 0,
613  m4_keep_or_throw(m4_class_body_kind$1,
614                             m4_proc_info_string, \,
615                             m4_group_names),
616  1, 0,
617  m4_keep_or_throw(m4_class_body_2nd_kind$1,
618                             m4_proc_info_string, ?,
619                             m4_group_names),
620  1, 0,
621  `m4_keep_or_throw(m4_class_kind$1,
622                   m4_proc_info_string, +,
623                   m4_group_names)')`'dnl
624m4_undefine(m4_proc_info_string)`'dnl
625')
626
627dnl PRIVATE
628dnl Used in macro-group "ONE_CLASS".
629dnl
630dnl m4_filter_all_procedures(Class_Counter, keep_or_throw_flag,
631dnl                         Procedure_Spec1, ProcedureSpec2, ...)
632dnl
633dnl Class_Counter   - The current class kind;
634dnl keep_or_throw_flag
635dnl                 - has value 1 or 0;
636dnl Procedure_Spec1 - A schematic procedure name with flags still attached;
637dnl ...
638dnl Procedure_Speck - A schematic procedure name with flags still attached;
639dnl Keeps just those procedure names that are needed for the given class kind.
640dnl The classes to be kept or filtered away are determined by extra info
641dnl included with each Procedure_Name
642dnl The keep_or_throw_flag determines if the filtered procedures
643dnl are the wanted (value 1) procedures or the unwanted ones (value 0);
644dnl Here we only use the wanted procedures list.
645dnl The unwanted list is used when generating the Prolog tests.
646m4_define(`m4_filter_all_procedures', `dnl
647m4_ifelse($#, 0, , $#, 1, , $#, 2, ,
648  $#, 3,
649    `m4_ifelse(m4_filter_one_procedure($1, $3), $2,
650       `$3')',
651    `m4_ifelse(m4_filter_one_procedure($1, $3), $2,
652       `$3,
653')`'dnl
654m4_filter_all_procedures($1, $2, m4_shift(m4_shift(m4_shift($@))))`'dnl
655')`'dnl
656')
657
658dnl =====================================================================
659dnl              *** PATTERNS_TO_REPLACEMENTS ***
660dnl The string has all its patterns replaced by the corresponding
661dnl replacements. If there are several alternative replacements
662dnl then several versions of the pattern-replaced string are generated.
663dnl =====================================================================
664
665dnl LOCAL
666dnl m4_annotated_extended_pattern_replacement(String, EIndex, AIndex)
667dnl
668dnl String        - is the string that has the patterns for replacing;
669dnl EIndex        - is the index of the extension;
670dnl AIndex        - is the index of the annotation.
671dnl
672dnl One pattern with an optional extension and annotation is replaced
673dnl by the corresponding replacement.
674dnl This is the key inner step for each string
675dnl (usually this string is the expanded procedure schema).
676dnl
677m4_define(`m4_annotated_extended_pattern_replacement', `dnl
678m4_ifdef(`m4_pattern_annotation$3',
679  `m4_define(`m4_annotated_extended_pattern',
680        m4_pattern_annotation$3`'m4_extended_pattern)`'dnl
681m4_annotated_extended_pattern_replacement(m4_patsubst($1,
682  @`'m4_annotated_extended_pattern`'@,
683  m4_annotated_pattern_replacement$3($2)), $2, m4_incr($3))',
684  `$1')`'dnl
685')
686
687dnl LOCAL
688dnl m4_expand_pattern_by_one_replacement(String, RIndex)
689dnl
690dnl String        - is the string;
691dnl RIndex        - is the index of the replacement.
692dnl
693dnl The patterns in the string are replaced by the replacement
694dnl indexed by RIndex.
695dnl
696dnl It first defines the m4_replace`'EIndex macros for each EIndex
697dnl extension using the macro m4_def_replacements_for_extended_patterns/2.
698dnl If m4_replace0 is defined to be different from "NONE",
699dnl the macro m4_expand_pattern_by_one_replacement_aux/2 is called
700dnl to do the replacements, iterating through the extensions.
701dnl When m4_replace0 is NONE, then the code is replaced by the
702dnl the empty string.
703dnl
704m4_define(`m4_expand_pattern_by_one_replacement', `dnl
705m4_def_replacements_for_extended_patterns($2, 0)`'dnl
706m4_ifelse(m4_replace0, NONE, `',
707  m4_expand_pattern_by_one_replacement_aux($1, 0)`'dnl
708)`'dnl
709')
710
711dnl LOCAL
712dnl m4_expand_pattern_by_one_replacement_aux(String, EIndex)
713dnl m4_extended_pattern(EIndex)
714dnl
715dnl String        - is the string;
716dnl EIndex        - is the index of the pattern extension.
717dnl
718dnl Iterates through EIndex values, defining m4_extended_pattern(EIndex)
719dnl and calling an auxiliary macro to replace the (delimited, possibly
720dnl extended and annotated) m4_PATTERN in String.
721dnl
722dnl If there are no replacements for EIndex, stop the replacements.
723dnl
724m4_define(`m4_expand_pattern_by_one_replacement_aux', `dnl
725m4_ifelse(`m4_replacements$2', `', `$1',
726   `m4_ifdef(`m4_pattern_extension$2',
727   `m4_define(`m4_extended_pattern', m4_pattern_extension$2`'m4_PATTERN)`'dnl
728m4_expand_pattern_by_one_replacement_aux(
729    m4_annotated_extended_pattern_replacement($1, $2, 0),
730       m4_incr($2))',
731   `$1')`'dnl
732')`'dnl
733')
734
735dnl LOCAL
736dnl m4_expand_pattern_by_all_replacements(String, RIndex)
737dnl
738dnl String        - is the string;
739dnl RIndex        - is the index of the replacement.
740dnl
741dnl This iteratively calls m4_expand_pattern_by_one_replacement/2 to replace
742dnl (a delimited form of possibly extended and annotated) m4_PATTERN by the
743dnl arguments of m4_replacements`'RIndex.
744m4_define(`m4_expand_pattern_by_all_replacements', `dnl
745m4_ifelse($2, m4_nargs(m4_replacements0),
746  m4_expand_pattern_by_one_replacement($1, $2),
747  `m4_expand_pattern_by_one_replacement($1, $2)`'dnl
748m4_expand_pattern_by_all_replacements($1, m4_incr($2))')`'dnl
749')
750
751dnl LOCAL
752dnl m4_replace_one_pattern_in_string(Class_Number, String, Pattern)
753dnl
754dnl Class_Number  - is the index to Class in Class_List;
755dnl String        - is the code to be changed;
756dnl Pattern       - is the pattern to be replaced.
757dnl
758dnl Replaces all occurrences of the capitalised form of Pattern
759dnl in String by the required replacement
760dnl (determined both by the class kind of Class and Pattern).
761m4_define(`m4_replace_one_pattern_in_string', `dnl
762dnl the m4_PATTERN (in uppercase) is the string to be replaced.
763m4_define(`m4_PATTERN', m4_upcase($3))`'dnl
764m4_def_extended_replacements($1, $3, 0)`'dnl
765m4_expand_pattern_by_all_replacements($2, 1)`'dnl
766dnl Cleanup temporary definitions.
767m4_undefine(`m4_PATTERN')`'dnl
768')
769
770dnl PUBLIC
771dnl Used in macro-group "ONE_CLASS" and by other m4 generator files.
772dnl
773dnl m4_replace_all_patterns(Class_Number, String)
774dnl
775dnl A (recursive) macro to replace, inside the second argument String,
776dnl all of the patterns.
777dnl
778dnl This is public because it is used by some code generators to replace
779dnl patterns used in some additional text provided locally.
780m4_define(`m4_replace_all_patterns', `dnl
781m4_define(`m4_ann_ext_pattern_in_string',
782  `m4_regexp($2, `[.]*@[^@_A-Z]*\([_A-Z]+\)@.*', `\1')')`'dnl
783m4_ifelse(m4_ann_ext_pattern_in_string, `', $2,
784  `m4_replace_all_patterns($1,
785    m4_replace_one_pattern_in_string($1, $2,
786      m4_downcase(m4_patsubst(m4_ann_ext_pattern_in_string, ^[A-E]_, `'))))')
787')
788
789dnl =====================================================================
790dnl              *** ONE_CLASS ***
791dnl   The next set of macros process a single class.
792dnl =====================================================================
793
794dnl LOCAL
795dnl m4_replace_procedure_spec_by_code(Class_Number, Procedure_Spec)
796dnl
797dnl Class_Number   - The current class counter;
798dnl Procedure_Spec - The schematic procedure name, complete with any flags.
799dnl
800dnl The procedure specification is replaced with the code and then
801dnl the patterns in the code are replaced by the required replacements.
802dnl
803dnl Note: one schematic specification will replaced by a single
804dnl matching schematic code item; which is then replaced by several
805dnl instances.
806m4_define(`m4_replace_procedure_spec_by_code', `dnl
807m4_patsubst(`$2', `\(.*\)', `dnl
808m4_replace_all_patterns($1,
809  m4_get_schematic_code(\1, 1, $1))')`'dnl
810')
811
812dnl LOCAL
813dnl m4_replace_all_procedure_specs_by_code(Class_Number,
814dnl                            Procedure_Spec1, Procedure_Spec2, ...)
815dnl
816dnl Class_Number    - The current class counter;
817dnl Procedure_Spec1 - A schematic procedure name;
818dnl ...
819dnl Procedure_Speck - A schematic procedure name.
820dnl
821dnl Each name from the second argument onwards is replaced
822dnl with the code and then the schema patterns in the code
823dnl are replaced by the various instances.
824m4_define(`m4_replace_all_procedure_specs_by_code', `dnl
825m4_ifelse($#, 0, , $#, 1, ,
826       $#, 2, `m4_replace_procedure_spec_by_code($1, $2)',
827       `dnl
828m4_replace_procedure_spec_by_code($1, $2)`'dnl
829m4_replace_all_procedure_specs_by_code($1, m4_shift(m4_shift($@)))`'dnl
830')dnl
831')
832
833dnl LOCAL
834dnl DEFAULT DEF
835dnl
836dnl m4_pre_extra_class_code(Class_Counter)
837dnl m4_post_extra_class_code(Class_Counter)
838dnl
839dnl Class_Counter   - The index for the current class.
840dnl
841dnl Default (empty) definitions for pre- and post- code for each class.
842dnl These should be redefined as needed.
843m4_define(`m4_pre_extra_class_code', `')
844m4_define(`m4_post_extra_class_code', `')
845
846dnl PRIVATE
847dnl Used by macro-group "ALL_CLASSES".
848dnl
849dnl DEFAULT DEF
850dnl m4_one_class_code(Class_Counter)
851dnl
852dnl Class_Counter   - The index for the current class.
853dnl
854dnl First, any necessary prefix code for the procedures in
855dnl that class is added.
856dnl Then, the main procedure input list is filtered according to
857dnl the current class kind and the +/- codes included with the procedure.
858dnl Each procedure that is not filtered away is checked to see if
859dnl there is a macro with "_code" extension that defines the code.
860dnl Then a macro sets the class and other schematic components.
861dnl Finally, any necessary postfix code for the procedures in
862dnl that class is added.
863m4_define(`m4_one_class_code', `dnl
864dnl m4_this_class_stuff($1)`'dnl
865m4_pre_extra_class_code($1)`'dnl
866m4_define(`m4_filtered_proc_list',
867       `m4_filter_all_procedures($1, 1, m4_procedure_list)')`'dnl
868m4_replace_all_procedure_specs_by_code($1, m4_filtered_proc_list)`'dnl
869m4_undefine(`m4_filtered_proc_list')`'dnl
870m4_post_extra_class_code($1)`'dnl
871')
872
873dnl =====================================================================
874dnl              *** ALL_CLASSES ***
875dnl  The final set of macros process all the classes, one at a time.
876dnl =====================================================================
877
878dnl LOCAL
879dnl m4_pre_all_classes_code
880dnl
881dnl Default (empty) definitions for code that must be placed before all
882dnl the generated code.
883dnl This is required for code that depends on the instantiated classes
884dnl (so must be generated from a schema) but has to be included before
885dnl all classes (as in ppl_prolog_icc.m4).
886m4_define(`m4_pre_all_classes_code', `')
887
888dnl LOCAL
889dnl m4_all_classes_code(Class_Counter)
890dnl
891dnl Class_Counter   - The index for the current class;
892dnl This iterates through the classes to generate the code.
893dnl The actual code for each class is generated by m4_one_class_code.
894dnl The generated code then has the pattern "|COMMA|" replaced by ",".
895m4_define(`m4_all_classes_code', `dnl
896m4_ifdef(m4_interface_class`'$1,
897  `m4_patsubst(m4_one_class_code($1), `|COMMA|', `,')`'dnl
898m4_all_classes_code(m4_incr($1))')`'dnl
899')
900
901dnl LOCAL
902dnl m4_class_definitions_initialized/0
903dnl
904dnl Avoids initializing the class macro definitions more than once
905dnl when the main macro m4_all_code/0 is called more than once in a
906dnl file generation.
907m4_define(`m4_class_initialized', `false')
908
909m4_define(`m4_initialize_all', `dnl
910m4_init_class_definitions`'dnl
911m4_define(`m4_class_initialized', `true')`'dnl
912')
913
914dnl PUBLIC
915dnl m4_all_code
916dnl
917dnl The macros for names of the classes are first initialized:
918dnl
919dnl The main loop macro m4_all_classes_loop is called to generate
920dnl code for all the required classes.
921m4_define(`m4_all_code', `dnl
922m4_ifelse(m4_class_initialized, `false', `m4_initialize_all')`'dnl
923m4_pre_all_classes_code`'dnl
924m4_all_classes_code(1)`'dnl
925')
926