blob: e793ee8150367cddb029a4a456a7472864d43127 [file] [log] [blame]
# sppp - the Standard Prelude Pre-Processor
#
# Copyright (C) 2025 Jose E. Marchesi
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
function error(msg)
{
print FILENAME ":" msg | "cat 1>&2"
exit (1)
}
BEGIN {
num_alternatives = 0
in_iter = 0
template = ""
}
/^[ \t]*\{ Process this file/ {
print "{ This is auto-generated from " FILENAME ". Do not edit. }"
next
}
/^[ \t]*\{[ \t]*iter[ \t]+/ {
line=$0
if (match (line, /[ \t\*\{[ \t]*iter[ \t]+/) == 0)
error(FNR ": invalid iter")
line = substr (line, RSTART + RLENGTH)
# Iterator name. #
if (match (line, /[a-zA-Z_]+/) == 0)
error(FNR ": expected iterator name")
iter_name = substr (line, RSTART, RLENGTH)
line = substr (line, RSTART + RLENGTH)
# Blanks. #
if (match (line, /[\t ]*/) == 0)
error(FNR ": invalid iter")
line = substr (line, RSTART + RLENGTH)
# Iterator alternatives. #
if (match (line, /\{.*\}/) == 0)
error(FNR ": expected iterator alternatives")
iter_alts = substr (line, RSTART, RLENGTH)
line = substr (line, RSTART + RLENGTH)
# Count and collect alternatives. #
iter_num_alternatives = 0
while (match (iter_alts, /[ \t]*\{([^\}]*)\}/) > 0)
{
iter_num_alternatives++
iter_names[iter_name] = 1
# Skip prefix. #
if (match (iter_alts, /[ \t]*\{/) == 0)
error(FNR ": invalid iterator alternative")
iter_alts = substr (iter_alts, RSTART + RLENGTH)
# Get alternative contents. #
if (match (iter_alts, /[^\}]*/) == 0)
error(FNR ": invalid iterator alternative")
iterators[iter_name,iter_num_alternatives] = substr (iter_alts, RSTART, RLENGTH)
iter_alts = substr (iter_alts, RSTART + RLENGTH)
# Skip trailer. #
if (match (iter_alts, /\}/) == 0)
error(FNR ": invalid iterator alternative")
iter_alts = substr (iter_alts, RSTART + RLENGTH)
}
if (in_iter == 1)
{
if (iter_num_alternatives != num_alternatives)
error(FNR ": invalid number of alternatives in iterator")
}
num_alternatives = iter_num_alternatives
in_iter = 1
next
}
/^[ \t]*\{[ \t]*reti/ {
separator = ""
line = $0
if (match (line, /[ \t]*\{[ \t]*reti[ \t]*\{/) > 0)
{
# Extract separator. #
line = substr (line, RSTART + RLENGTH)
if (match (line, /[^\}]*/) == 0)
error(FNR ": invalid separator in reti")
separator = substr (line, RSTART, RLENGTH)
line = substr (line, RSTART + RLENGTH)
# Skip suffix
if (match (line, /\}/) == 0)
error(FNR ": expected closing } in reti separator")
}
else
{
# No separator. #
if (match (line, /[ \t]*\{[ \t]*reti[ \t]*\}/) == 0)
error(FNR ": invalid reti")
}
for (nalt = 1; nalt <= num_alternatives; nalt++)
{
output = template
for (iter_name in iter_names)
{
while (sub ("\\{" iter_name "\\}", iterators[iter_name,nalt], output)) {}
}
printf "%s%s\n", substr (output, 0, length(output) - 1), nalt < num_alternatives ? separator : ""
}
for (key in iter_names) delete iter_names[key]
for (key in iterators) delete iterators[key]
in_iter = 0;
template = ""
num_alternatives = 0
next
}
in_iter == 1 {
template = template $0 "\n"
next
}
{
print $0
}