1186681Sed#!/usr/bin/awk -f
2186681Sed
3186681Sed#-
4186681Sed# Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
5186681Sed# All rights reserved.
6223574Sed#
7186681Sed# Redistribution and use in source and binary forms, with or without
8186681Sed# modification, are permitted provided that the following conditions
9186681Sed# are met:
10186681Sed# 1. Redistributions of source code must retain the above copyright
11186681Sed#    notice, this list of conditions and the following disclaimer.
12186681Sed# 2. Redistributions in binary form must reproduce the above copyright
13186681Sed#    notice, this list of conditions and the following disclaimer in the
14186681Sed#    documentation and/or other materials provided with the distribution.
15223574Sed#
16186681Sed# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17186681Sed# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18186681Sed# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19186681Sed# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20186681Sed# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21186681Sed# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22186681Sed# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23186681Sed# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24186681Sed# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25186681Sed# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26186681Sed# SUCH DAMAGE.
27186681Sed#
28186681Sed# $FreeBSD$
29186681Sed
30186681Sedfunction die(msg) {
31186681Sed	print msg;
32186681Sed	exit 1;
33186681Sed}
34186681Sed
35186681Sedfunction cchar(str) {
36186681Sed	if (str == "^[")
37186681Sed		return "\\x1B";
38186681Sed
39186681Sed	return str;
40186681Sed}
41186681Sed
42186681SedBEGIN {
43186681SedFS = "\t+"
44186681Sed
45186681Sedwhile (getline > 0) {
46186681Sed	if (NF == 0 || $1 ~ /^#/)
47186681Sed		continue;
48186681Sed
49186681Sed	if (NF != 3 && NF != 4)
50186681Sed		die("Invalid line layout: " NF " columns");
51186681Sed
52186681Sed	split($3, sequence, " +");
53186681Sed	nsequences = 0;
54186681Sed	for (s in sequence)
55186681Sed		nsequences++;
56186681Sed
57186681Sed	prefix = "";
58186681Sed	l_prefix_name[""] = "teken_state_init";
59186681Sed	for (i = 1; i < nsequences; i++) {
60186681Sed		n = prefix sequence[i];
61186681Sed		l_prefix_parent[n] = prefix;
62186681Sed		l_prefix_suffix[n] = sequence[i];
63186681Sed		if (!l_prefix_name[n])
64186681Sed			l_prefix_name[n] = "teken_state_" ++npr;
65186681Sed		prefix = n;
66186681Sed	}
67186681Sed
68186681Sed	suffix = sequence[nsequences];
69186681Sed	cmd = prefix suffix;
70186681Sed
71186681Sed	# Fill lists
72186681Sed	if (l_cmd_name[cmd] != "")
73186681Sed		die(cmd " already exists");
74186681Sed	l_cmd_prefix[cmd] = prefix;
75186681Sed	l_cmd_suffix[cmd] = suffix;
76186681Sed	l_cmd_args[cmd] = $4;
77186681Sed	l_cmd_abbr[cmd] = $1;
78186681Sed	l_cmd_name[cmd] = $2;
79186681Sed	l_cmd_c_name[cmd] = "teken_subr_" tolower($2);
80186681Sed	gsub(" ", "_", l_cmd_c_name[cmd]);
81186681Sed
82186681Sed	if ($4 != "")
83186681Sed		l_prefix_numbercmds[prefix]++;
84186681Sed}
85186681Sed
86186681Sedprint "/* Generated file. Do not edit. */";
87186681Sedprint "";
88186681Sed
89186681Sedfor (p in l_prefix_name) {
90186681Sed	if (l_prefix_name[p] != "teken_state_init")
91186681Sed		print "static teken_state_t	" l_prefix_name[p] ";";
92186681Sed}
93186681Sed
94186681Sedfor (p in l_prefix_name) {
95186681Sed	print "";
96186681Sed	print "/* '" p "' */";
97186681Sed	print "static void";
98186681Sed	print l_prefix_name[p] "(teken_t *t, teken_char_t c)";
99186681Sed	print "{";
100186681Sed
101186681Sed	if (l_prefix_numbercmds[p] > 0) {
102186681Sed		print "";
103186681Sed		print "\tif (teken_state_numbers(t, c))";
104186681Sed		print "\t\treturn;";
105186681Sed	}
106186681Sed
107186681Sed	print "";
108186681Sed	print "\tswitch (c) {";
109186681Sed	for (c in l_cmd_prefix) {
110186681Sed		if (l_cmd_prefix[c] != p)
111186681Sed			continue;
112186681Sed
113186681Sed		print "\tcase '" cchar(l_cmd_suffix[c]) "': /* " l_cmd_abbr[c] ": " l_cmd_name[c] " */";
114186681Sed
115186681Sed		if (l_cmd_args[c] == "v") {
116186681Sed			print "\t\t" l_cmd_c_name[c] "(t, t->t_curnum, t->t_nums);";
117186681Sed		} else {
118186681Sed			printf "\t\t%s(t", l_cmd_c_name[c];
119186681Sed			split(l_cmd_args[c], args, " ");
120186681Sed			for (a = 1; args[a] != ""; a++) {
121186681Sed				if (args[a] == "n")
122186681Sed					printf ", (t->t_curnum < %d || t->t_nums[%d] == 0) ? 1 : t->t_nums[%d]", a, (a - 1), (a - 1);
123186681Sed				else if (args[a] == "r")
124186681Sed					printf ", t->t_curnum < %d ? 0 : t->t_nums[%d]", a, (a - 1);
125186681Sed				else
126186681Sed					die("Invalid argument type: " args[a]);
127186681Sed			}
128186681Sed			print ");";
129186681Sed		}
130186681Sed		print "\t\tbreak;";
131186681Sed	}
132186681Sed	for (pc in l_prefix_parent) {
133186681Sed		if (l_prefix_parent[pc] != p)
134186681Sed			continue;
135186681Sed		print "\tcase '" cchar(l_prefix_suffix[pc]) "':";
136186681Sed		print "\t\tteken_state_switch(t, " l_prefix_name[pc] ");";
137186681Sed		print "\t\treturn;";
138186681Sed	}
139186681Sed
140186681Sed	print "\tdefault:";
141186681Sed	if (l_prefix_name[p] == "teken_state_init") {
142186681Sed		print "\t\tteken_subr_regular_character(t, c);";
143186681Sed	} else {
144186681Sed		print "\t\tteken_printf(\"Unsupported sequence in " l_prefix_name[p] ": %u\\n\", (unsigned int)c);";
145186681Sed	}
146186681Sed	print "\t\tbreak;";
147186681Sed
148186681Sed	print "\t}";
149186681Sed
150186681Sed	if (l_prefix_name[p] != "teken_state_init") {
151186681Sed		print "";
152186681Sed		print "\tteken_state_switch(t, teken_state_init);";
153186681Sed	}
154186681Sed	print "}";
155186681Sed}
156186681Sed
157186681Sed}
158