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