Rev 5 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
Crown Copyright (c) 1997
This TenDRA(r) Computer Program is subject to Copyright
owned by the United Kingdom Secretary of State for Defence
acting through the Defence Evaluation and Research Agency
(DERA). It is made available to Recipients with a
royalty-free licence for its use, reproduction, transfer
to other parties and amendment for any purpose not excluding
product development provided that any such use et cetera
shall be deemed to be acceptance of the following conditions:-
(1) Its Recipients shall ensure that this Notice is
reproduced upon any copies or amended versions of it;
(2) Any amended version of it shall be clearly marked to
show both the nature of and the organisation responsible
for the relevant amendment or amendments;
(3) Its onward transfer from a recipient to another
party shall be deemed to be that party's acceptance of
these conditions;
(4) DERA gives no warranty or assurance as to its
quality or suitability for any purpose and DERA accepts
no liability whatsoever in relation to any use to which
it may be put.
*/
#include "config.h"
#include "tdf.h"
#include "cmd_ops.h"
#include "cons_ops.h"
#include "info_ops.h"
#include "link_ops.h"
#include "par_ops.h"
#include "sort_ops.h"
#include "spec_ops.h"
#include "error.h"
#include "input.h"
#include "lex.h"
#include "output.h"
/*
DO THE INITIAL SEGMENTS OF TWO STRINGS MATCH
This macro gives a convenient method for testing whether the first
C characters of the strings A and B are equal.
*/
#define strneq( A, B, C )\
( strncmp ( ( A ), ( B ), ( size_t ) ( C ) ) == 0 )
/*
CURRENT OUTPUT FILE
These variables describe the current output file.
*/
static FILE *output_file ;
static char output_buff [512] ;
static int output_posn = 0 ;
static unsigned crt_column = 0 ;
/*
CURRENT LOOP VARIABLES
These variables keep track of the current state of the various
output loops.
*/
static unsigned crt_major = 0 ;
static unsigned crt_minor = 0 ;
static int crt_unique = 0 ;
static SORT crt_sort = NULL_sort ;
static SORT_INFO crt_info = NULL_info ;
static CONSTRUCT crt_cons = NULL_cons ;
static PARAMETER crt_param = NULL_par ;
static int crt_param_no = 0 ;
static int last_param_no = 0 ;
/*
PRINT A CHARACTER TO THE OUTPUT FILE
This routine prints the character c to the output file updating the
current column number.
*/
static void output_char
PROTO_N ( ( c ) )
PROTO_T ( int c )
{
int i = output_posn ;
output_buff [i] = ( char ) c ;
if ( ++i >= 500 || c == '\n' ) {
output_buff [i] = 0 ;
IGNORE fputs ( output_buff, output_file ) ;
i = 0 ;
}
if ( c == '\n' ) {
crt_column = 0 ;
} else if ( c == '\t' ) {
crt_column = 8 * ( crt_column / 8 + 1 ) ;
} else {
crt_column++ ;
}
output_posn = i ;
return ;
}
/*
PRINT A STRING TO THE OUTPUT FILE
This routine prints the string s to the output file.
*/
static void output_string
PROTO_N ( ( s ) )
PROTO_T ( char *s )
{
char c ;
while ( c = *( s++ ), c != 0 ) {
output_char ( ( int ) c ) ;
}
return ;
}
/*
OUTPUT AN ENCODING STRING FOR A CONSTRUCT
This routine writes the encoding strings for the parameter sorts of
the construct cons to the output file.
*/
static void output_cons
PROTO_N ( ( cons, intro ) )
PROTO_T ( CONSTRUCT cons X int intro )
{
int c ;
int brks = 0 ;
unsigned kind = DEREF_unsigned ( cons_kind ( cons ) ) ;
LIST ( PARAMETER ) p = DEREF_list ( cons_pars ( cons ) ) ;
while ( !IS_NULL_list ( p ) ) {
PARAMETER par = DEREF_par ( HEAD_list ( p ) ) ;
SORT sort = DEREF_sort ( par_type ( par ) ) ;
int align = DEREF_int ( par_align ( par ) ) ;
int brk = DEREF_int ( par_brk ( par ) ) ;
int intro2 = DEREF_int ( par_intro ( par ) ) ;
if ( align ) output_char ( '|' ) ;
if ( brk ) output_char ( '{' ) ;
if ( intro2 ) intro = 1 ;
c = output_sort ( sort, intro ) ;
if ( c == '@' && kind == KIND_cond ) {
/* Conditional construct */
output_char ( '[' ) ;
sort = DEREF_sort ( cons_res ( cons ) ) ;
IGNORE output_sort ( sort, intro ) ;
output_char ( ']' ) ;
}
brks += brk ;
p = TAIL_list ( p ) ;
}
while ( brks-- ) output_char ( '}' ) ;
return ;
}
/*
OUTPUT AN ENCODING STRING FOR A SORT
Every basic and built-in type has an associated code letter. This,
together with various control characters for lists and optional sorts,
allows every sort to be expressed as a sequence of characters. This
routine prints this encoding string for the sort sort to the output
file
*/
int output_sort
PROTO_N ( ( sort, intro ) )
PROTO_T ( SORT sort X int intro )
{
int c = DEREF_int ( sort_code ( sort ) ) ;
SORT_INFO info = DEREF_info ( sort_info ( sort ) ) ;
if ( !IS_NULL_info ( info ) ) {
switch ( TAG_info ( info ) ) {
case info_builtin_tag :
case info_basic_tag : {
if ( c < 32 ) {
char buff [10] ;
sprintf_v ( buff, "\\%03o", ( unsigned ) c ) ;
output_string ( buff ) ;
} else {
output_char ( c ) ;
}
if ( intro ) {
int edge = DEREF_int ( sort_edge ( sort ) ) ;
if ( edge ) output_char ( '&' ) ;
}
break ;
}
case info_dummy_tag : {
CONSTRUCT cons = DEREF_cons ( info_dummy_cons ( info ) ) ;
output_cons ( cons, intro ) ;
break ;
}
case info_clist_tag :
case info_slist_tag :
case info_option_tag : {
sort = DEREF_sort ( info_clist_etc_arg ( info ) ) ;
output_char ( c ) ;
output_char ( '[' ) ;
IGNORE output_sort ( sort, intro ) ;
output_char ( ']' ) ;
break ;
}
}
}
return ( c ) ;
}
/*
OUTPUT A FORMAT STRING
This routine writes the format string s to the output file.
*/
static void output
PROTO_N ( ( s ) )
PROTO_T ( string s )
{
char c ;
while ( c = *( s++ ), c != 0 ) {
if ( c == '%' ) {
char *s0 = s ;
int prec = 100 ;
char buff [120] ;
int have_prec = 0 ;
SORT cs = crt_sort ;
SORT_INFO ci = crt_info ;
CONSTRUCT cc = crt_cons ;
PARAMETER cp = crt_param ;
c = *( s++ ) ;
if ( c >= '0' && c <= '9' ) {
/* Read precision */
prec = ( int ) ( c - '0' ) ;
while ( c = *( s++ ), ( c >= '0' && c <= '9' ) ) {
prec = 10 * prec + ( int ) ( c - '0' ) ;
}
have_prec = 1 ;
}
switch ( c ) {
case 'C' :
cons_format : {
/* Construct information */
if ( IS_NULL_cons ( cc ) ) goto misplaced_arg ;
c = *( s++ ) ;
switch ( c ) {
case 'N' : {
/* '%CN' -> construct name */
string nm = DEREF_string ( cons_name ( cc ) ) ;
sprintf_v ( buff, "%.*s", prec, nm ) ;
output_string ( buff ) ;
break ;
}
case 'E' : {
/* '%CE' -> construct encoding */
unsigned e ;
e = DEREF_unsigned ( cons_encode ( cc ) ) ;
sprintf_v ( buff, "%u", e ) ;
output_string ( buff ) ;
break ;
}
case 'S' : {
/* '%CS' -> construct result sort */
goto sort_format ;
}
case 'X' : {
/* '%CX' -> construct encoding string */
output_cons ( cc, 0 ) ;
break ;
}
default : {
goto bad_format ;
}
}
break ;
}
case 'P' : {
/* Parameter information */
if ( IS_NULL_par ( cp ) ) goto misplaced_arg ;
c = *( s++ ) ;
if ( c == 'N' ) {
/* '%PN' -> parameter name */
string nm = DEREF_string ( par_name ( cp ) ) ;
sprintf_v ( buff, "%.*s", prec, nm ) ;
output_string ( buff ) ;
} else if ( c == 'S' ) {
/* '%PS' -> parameter sort */
cs = DEREF_sort ( par_type ( cp ) ) ;
ci = DEREF_info ( sort_info ( cs ) ) ;
goto sort_format ;
} else if ( c == 'E' ) {
/* '%PE' -> parameter number */
sprintf_v ( buff, "%d", crt_param_no ) ;
output_string ( buff ) ;
} else {
goto bad_format ;
}
break ;
}
case 'S' :
sort_format : {
/* Sort information */
if ( IS_NULL_info ( ci ) ) goto misplaced_arg ;
c = *( s++ ) ;
switch ( c ) {
case 'N' : {
/* '%SN' -> sort name */
string nm = DEREF_string ( sort_name ( cs ) ) ;
sprintf_v ( buff, "%.*s", prec, nm ) ;
output_string ( buff ) ;
break ;
}
case 'T' : {
/* '%ST' -> sort name in capitals */
string nm = DEREF_string ( sort_caps ( cs ) ) ;
sprintf_v ( buff, "%.*s", prec, nm ) ;
output_string ( buff ) ;
break ;
}
case 'L' : {
/* '%SL' -> sort unit name */
string nm = DEREF_string ( sort_link ( cs ) ) ;
if ( nm ) {
sprintf_v ( buff, "%.*s", prec, nm ) ;
output_string ( buff ) ;
}
break ;
}
case 'U' : {
/* '%SU' -> sort unit name */
string nm = DEREF_string ( sort_unit ( cs ) ) ;
if ( nm ) {
sprintf_v ( buff, "%.*s", prec, nm ) ;
output_string ( buff ) ;
}
break ;
}
case 'B' : {
/* '%SB' -> bits in encoding */
unsigned b = 0 ;
if ( IS_info_basic ( ci ) ) {
b = DEREF_unsigned ( info_basic_bits ( ci ) ) ;
}
sprintf_v ( buff, "%u", b ) ;
output_string ( buff ) ;
break ;
}
case 'E' : {
/* '%SE' -> extended encoding */
unsigned e = 0 ;
if ( IS_info_basic ( ci ) ) {
e = DEREF_unsigned ( info_basic_extend ( ci ) ) ;
}
sprintf_v ( buff, "%u", e ) ;
output_string ( buff ) ;
break ;
}
case 'M' : {
/* '%SM' -> maximum encoding */
unsigned m = 0 ;
if ( IS_info_basic ( ci ) ) {
m = DEREF_unsigned ( info_basic_max ( ci ) ) ;
}
if ( have_prec ) m += ( unsigned ) prec ;
sprintf_v ( buff, "%u", m ) ;
output_string ( buff ) ;
break ;
}
case 'C' : {
/* '%SC' -> sortname information */
cc = NULL_cons ;
if ( IS_info_basic ( ci ) ) {
cc = DEREF_cons ( info_basic_sortname ( ci ) ) ;
}
goto cons_format ;
}
case 'S' : {
/* '%SS' -> subsort information */
if ( IS_info_clist_etc ( ci ) ) {
cs = DEREF_sort ( info_clist_etc_arg ( ci ) ) ;
ci = DEREF_info ( sort_info ( cs ) ) ;
}
goto sort_format ;
}
case 'X' : {
/* '%SX' -> construct encoding string */
IGNORE output_sort ( cs, 0 ) ;
break ;
}
default : {
goto bad_format ;
}
}
break ;
}
case 'V' : {
c = *( s++ ) ;
if ( c == 'A' ) {
/* '%VA' -> major version number */
sprintf_v ( buff, "%u", crt_major ) ;
output_string ( buff ) ;
} else if ( c == 'B' ) {
/* '%VB' -> minor version number */
sprintf_v ( buff, "%u", crt_minor ) ;
output_string ( buff ) ;
} else {
goto bad_format ;
}
break ;
}
case 'Z' : {
c = *( s++ ) ;
if ( c == 'V' ) {
/* %ZV -> program version */
sprintf_v ( buff, "%.*s", prec, progvers ) ;
output_string ( buff ) ;
} else if ( c == 'X' ) {
/* %ZX -> program name */
sprintf_v ( buff, "%.*s", prec, progname ) ;
output_string ( buff ) ;
} else {
goto bad_format ;
}
break ;
}
case 'b' : {
/* '%b' -> backspaces */
if ( !have_prec ) prec = 1 ;
output_posn -= prec ;
if ( output_posn < 0 ) output_posn = 0 ;
break ;
}
case 't' : {
/* '%t' -> tabs */
if ( have_prec ) {
while ( crt_column < ( unsigned ) prec ) {
output_char ( '\t' ) ;
}
}
break ;
}
case 'u' : {
/* '%u' -> unique value */
if ( have_prec ) {
crt_unique = prec ;
} else {
prec = crt_unique++ ;
sprintf_v ( buff, "%d", prec ) ;
output_string ( buff ) ;
}
break ;
}
case '%' : {
/* '%%' -> '%' */
output_char ( '%' ) ;
break ;
}
case '@' : {
/* '%@' -> '@' */
output_char ( '@' ) ;
break ;
}
case '\n' : {
/* Escaped newline */
break ;
}
case '_' : {
/* Dummy end marker */
break ;
}
misplaced_arg : {
error ( ERROR_SERIOUS, "Misplaced format, '%%%.2s'", s0 ) ;
output_string ( "<error>" ) ;
break ;
}
default :
bad_format : {
error ( ERROR_SERIOUS, "Unknown format, '%%%.2s'", s0 ) ;
output_string ( "<error>" ) ;
break ;
}
}
} else {
output_char ( ( int ) c ) ;
}
}
return ;
}
/*
EVALUATE A CONDITION
This routine evaluates the condition given by the string s.
*/
static int eval_cond
PROTO_N ( ( s ) )
PROTO_T ( string s )
{
string s0 = s ;
SORT cs = crt_sort ;
SORT_INFO ci = crt_info ;
CONSTRUCT cc = crt_cons ;
PARAMETER cp = crt_param ;
if ( s [0] == '!' ) {
/* Negate condition */
return ( !eval_cond ( s + 1 ) ) ;
}
if ( strneq ( s, "sort.", 5 ) ) {
/* Sort conditions */
s += 5 ;
sort_label : {
unsigned tag = 100 ;
if ( !IS_NULL_info ( ci ) ) tag = TAG_info ( ci ) ;
if ( streq ( s, "builtin" ) ) return ( tag == info_builtin_tag ) ;
if ( streq ( s, "basic" ) ) return ( tag == info_basic_tag ) ;
if ( streq ( s, "dummy" ) ) return ( tag == info_dummy_tag ) ;
if ( streq ( s, "list" ) ) return ( tag == info_clist_tag ) ;
if ( streq ( s, "slist" ) ) return ( tag == info_slist_tag ) ;
if ( streq ( s, "option" ) ) return ( tag == info_option_tag ) ;
if ( streq ( s, "simple" ) ) {
return ( tag == info_basic_tag || tag == info_dummy_tag ) ;
}
if ( streq ( s, "compound" ) ) {
if ( tag == info_option_tag ) return ( 1 ) ;
return ( tag == info_clist_tag || tag == info_slist_tag ) ;
}
if ( streq ( s, "extends" ) ) {
if ( tag == info_basic_tag ) {
unsigned a = DEREF_unsigned ( info_basic_extend ( ci ) ) ;
if ( a ) return ( 1 ) ;
}
return ( 0 ) ;
}
if ( streq ( s, "special" ) ) {
int a = 0 ;
if ( !IS_NULL_sort ( cs ) ) {
a = DEREF_int ( sort_special ( cs ) ) ;
}
return ( a ) ;
}
if ( streq ( s, "edge" ) ) {
int a = 0 ;
if ( !IS_NULL_sort ( cs ) ) {
a = DEREF_int ( sort_edge ( cs ) ) ;
}
return ( a ) ;
}
if ( streq ( s, "link" ) ) {
if ( !IS_NULL_sort ( cs ) ) {
string nm = DEREF_string ( sort_link ( cs ) ) ;
if ( nm ) return ( 1 ) ;
}
return ( 0 ) ;
}
if ( streq ( s, "unit" ) ) {
if ( !IS_NULL_sort ( cs ) ) {
string nm = DEREF_string ( sort_unit ( cs ) ) ;
if ( nm ) return ( 1 ) ;
}
return ( 0 ) ;
}
if ( strneq ( s, "name.", 5 ) ) {
if ( tag == info_basic_tag ) {
cc = DEREF_cons ( info_basic_sortname ( ci ) ) ;
} else {
cc = NULL_cons ;
}
goto cons_label ;
}
if ( strneq ( s, "sub.", 4 ) ) {
s += 4 ;
if ( tag == info_clist_tag || tag == info_slist_tag ||
tag == info_option_tag ) {
cs = DEREF_sort ( info_clist_etc_arg ( ci ) ) ;
ci = DEREF_info ( sort_info ( cs ) ) ;
}
goto sort_label ;
}
if ( strneq ( s, "eq.", 3 ) ) {
s += 3 ;
if ( !IS_NULL_sort ( cs ) ) {
string nm = DEREF_string ( sort_name ( cs ) ) ;
if ( streq ( nm, s ) ) return ( 1 ) ;
}
return ( 0 ) ;
}
}
} else if ( strneq ( s, "cons.", 5 ) ) {
/* Construct conditions */
cons_label : {
unsigned kind = KIND_dummy ;
s += 5 ;
if ( strneq ( s, "sort.", 5 ) ) {
s += 5 ;
if ( IS_NULL_cons ( cc ) ) {
cs = NULL_sort ;
ci = NULL_info ;
}
goto sort_label ;
}
if ( !IS_NULL_cons ( cc ) ) {
kind = DEREF_unsigned ( cons_kind ( cc ) ) ;
}
if ( streq ( s, "simple" ) ) return ( kind == KIND_simple ) ;
if ( streq ( s, "token" ) ) return ( kind == KIND_token ) ;
if ( streq ( s, "cond" ) ) return ( kind == KIND_cond ) ;
if ( streq ( s, "edge" ) ) return ( kind == KIND_edge ) ;
if ( streq ( s, "foreign" ) ) return ( kind == KIND_foreign ) ;
if ( streq ( s, "special" ) ) return ( kind == KIND_special ) ;
if ( streq ( s, "params" ) ) {
if ( !IS_NULL_cons ( cc ) ) {
LIST ( PARAMETER ) p = DEREF_list ( cons_pars ( cc ) ) ;
if ( !IS_NULL_list ( p ) ) return ( 1 ) ;
}
return ( 0 ) ;
}
if ( streq ( s, "extends" ) ) {
if ( !IS_NULL_cons ( cc ) ) {
if ( !IS_NULL_info ( ci ) && IS_info_basic ( ci ) ) {
unsigned b, e ;
b = DEREF_unsigned ( info_basic_bits ( ci ) ) ;
e = DEREF_unsigned ( cons_encode ( cc ) ) ;
if ( e >= ( ( unsigned ) 1 << b ) ) return ( 1 ) ;
}
}
return ( 0 ) ;
}
if ( strneq ( s, "eq.", 3 ) ) {
s += 3 ;
if ( !IS_NULL_cons ( cc ) ) {
string nm = DEREF_string ( cons_name ( cc ) ) ;
if ( streq ( nm, s ) ) return ( 1 ) ;
}
return ( 0 ) ;
}
}
} else if ( strneq ( s, "param.", 6 ) ) {
/* Parameter conditions */
s += 6 ;
if ( strneq ( s, "sort.", 5 ) ) {
s += 5 ;
if ( !IS_NULL_par ( cp ) ) {
cs = DEREF_sort ( par_type ( cp ) ) ;
ci = DEREF_info ( sort_info ( cs ) ) ;
} else {
cs = NULL_sort ;
ci = NULL_info ;
}
goto sort_label ;
}
if ( streq ( s, "align" ) ) {
int a = 0 ;
if ( !IS_NULL_par ( cp ) ) a = DEREF_int ( par_align ( cp ) ) ;
return ( a ) ;
}
if ( streq ( s, "break" ) ) {
int a = 0 ;
if ( !IS_NULL_par ( cp ) ) a = DEREF_int ( par_brk ( cp ) ) ;
return ( a ) ;
}
if ( streq ( s, "intro" ) ) {
int a = 0 ;
if ( !IS_NULL_par ( cp ) ) a = DEREF_int ( par_intro ( cp ) ) ;
return ( a ) ;
}
if ( streq ( s, "first" ) ) {
return ( crt_param_no == 0 ) ;
}
if ( streq ( s, "last" ) ) {
return ( crt_param_no == last_param_no ) ;
}
if ( strneq ( s, "eq.", 3 ) ) {
s += 3 ;
if ( !IS_NULL_par ( cp ) ) {
string nm = DEREF_string ( par_name ( cp ) ) ;
if ( streq ( nm, s ) ) return ( 1 ) ;
}
return ( 0 ) ;
}
} else {
/* Other conditions */
if ( streq ( s, "uniq" ) ) return ( crt_unique ) ;
if ( streq ( s, "true" ) ) return ( 1 ) ;
if ( streq ( s, "false" ) ) return ( 0 ) ;
}
error ( ERROR_SERIOUS, "Unknown condition, '%s'", s0 ) ;
return ( 0 ) ;
}
/*
WRITE A TEMPLATE FILE
This routine writes the template file given by the commands cmd for
the specification spec to the output file.
*/
static void output_template
PROTO_N ( ( spec, cmd ) )
PROTO_T ( SPECIFICATION spec X COMMAND cmd )
{
if ( !IS_NULL_cmd ( cmd ) ) {
crt_line_no = DEREF_int ( cmd_line ( cmd ) ) ;
switch ( TAG_cmd ( cmd ) ) {
case cmd_simple_tag : {
string s = DEREF_string ( cmd_simple_text ( cmd ) ) ;
output ( s ) ;
break ;
}
case cmd_compound_tag : {
LIST ( COMMAND ) p ;
p = DEREF_list ( cmd_compound_seq ( cmd ) ) ;
while ( !IS_NULL_list ( p ) ) {
COMMAND a = DEREF_cmd ( HEAD_list ( p ) ) ;
output_template ( spec, a ) ;
p = TAIL_list ( p ) ;
}
break ;
}
case cmd_loop_tag : {
string s = DEREF_string ( cmd_loop_control ( cmd ) ) ;
COMMAND a = DEREF_cmd ( cmd_loop_body ( cmd ) ) ;
if ( streq ( s, "sort" ) ) {
/* Loop over all sorts */
SORT ls = crt_sort ;
SORT_INFO li = crt_info ;
LIST ( SORT ) ps = DEREF_list ( spec_sorts ( spec ) ) ;
while ( !IS_NULL_list ( ps ) ) {
SORT cs = DEREF_sort ( HEAD_list ( ps ) ) ;
int mark = DEREF_int ( sort_mark ( cs ) ) ;
if ( mark ) {
SORT_INFO ci = DEREF_info ( sort_info ( cs ) ) ;
if ( !IS_NULL_info ( ci ) ) {
crt_sort = cs ;
crt_info = ci ;
output_template ( spec, a ) ;
}
}
ps = TAIL_list ( ps ) ;
}
crt_sort = ls ;
crt_info = li ;
} else if ( streq ( s, "sort.cons" ) ) {
/* Loop over all constructs */
CONSTRUCT lc = crt_cons ;
SORT_INFO ci = crt_info ;
if ( !IS_NULL_info ( ci ) ) {
if ( IS_info_basic ( ci ) ) {
LIST ( CONSTRUCT ) pc ;
pc = DEREF_list ( info_basic_cons ( ci ) ) ;
while ( !IS_NULL_list ( pc ) ) {
crt_cons = DEREF_cons ( HEAD_list ( pc ) ) ;
output_template ( spec, a ) ;
pc = TAIL_list ( pc ) ;
}
} else if ( IS_info_dummy ( ci ) ) {
crt_cons = DEREF_cons ( info_dummy_cons ( ci ) ) ;
output_template ( spec, a ) ;
}
}
crt_cons = lc ;
} else if ( streq ( s, "cons.param" ) ) {
/* Loop over all parameters */
int np = crt_param_no ;
int mp = last_param_no ;
PARAMETER lp = crt_param ;
CONSTRUCT cc = crt_cons ;
if ( !IS_NULL_cons ( cc ) ) {
LIST ( PARAMETER ) pp ;
pp = DEREF_list ( cons_pars ( cc ) ) ;
crt_param_no = 0 ;
last_param_no = ( int ) LENGTH_list ( pp ) - 1 ;
while ( !IS_NULL_list ( pp ) ) {
crt_param = DEREF_par ( HEAD_list ( pp ) ) ;
output_template ( spec, a ) ;
crt_param_no++ ;
pp = TAIL_list ( pp ) ;
}
}
last_param_no = mp ;
crt_param_no = np ;
crt_param = lp ;
} else if ( streq ( s, "param.prev" ) ) {
/* Loop over all previous parameters */
int np = crt_param_no ;
int mp = last_param_no ;
PARAMETER lp = crt_param ;
CONSTRUCT cc = crt_cons ;
if ( !IS_NULL_cons ( cc ) ) {
LIST ( PARAMETER ) pp ;
pp = DEREF_list ( cons_pars ( cc ) ) ;
crt_param_no = 0 ;
last_param_no = np - 1 ;
while ( !IS_NULL_list ( pp ) && crt_param_no < np ) {
crt_param = DEREF_par ( HEAD_list ( pp ) ) ;
output_template ( spec, a ) ;
crt_param_no++ ;
pp = TAIL_list ( pp ) ;
}
}
last_param_no = mp ;
crt_param_no = np ;
crt_param = lp ;
} else {
error ( ERROR_SERIOUS, "Unknown control, '%s'", s ) ;
}
break ;
}
case cmd_cond_tag : {
string s = DEREF_string ( cmd_cond_control ( cmd ) ) ;
COMMAND a = DEREF_cmd ( cmd_cond_true_code ( cmd ) ) ;
COMMAND b = DEREF_cmd ( cmd_cond_false_code ( cmd ) ) ;
if ( eval_cond ( s ) ) {
output_template ( spec, a ) ;
} else {
output_template ( spec, b ) ;
}
break ;
}
case cmd_use_tag : {
int m = 1 ;
string c = DEREF_string ( cmd_use_cons ( cmd ) ) ;
string s = DEREF_string ( cmd_use_sort ( cmd ) ) ;
while ( s [0] == '!' ) {
m = !m ;
s++ ;
}
if ( c == NULL && streq ( s, "all" ) ) {
mark_all_sorts ( m ) ;
} else {
SORT sn = find_sort ( s, 0 ) ;
if ( c ) {
CONSTRUCT cn = find_construct ( sn, c ) ;
mark_construct ( cn, m ) ;
} else {
mark_sort ( sn, m ) ;
}
}
break ;
}
case cmd_special_tag : {
SORT sn ;
int m = 1 ;
string c = DEREF_string ( cmd_special_cons ( cmd ) ) ;
string s = DEREF_string ( cmd_special_sort ( cmd ) ) ;
while ( s [0] == '!' ) {
m = !m ;
s++ ;
}
sn = find_sort ( s, 0 ) ;
if ( c ) {
if ( m ) {
set_special ( sn, c, KIND_special ) ;
} else {
set_special ( sn, c, KIND_simple ) ;
}
} else {
COPY_int ( sort_special ( sn ), m ) ;
}
mark_sort ( sn, 1 ) ;
break ;
}
}
}
return ;
}
/*
MAIN OUTPUT ROUTINE
This routine outputs all the information concerning the TDF specification
spec to the output file nm using the template cmd.
*/
void output_spec
PROTO_N ( ( nm, spec, cmd ) )
PROTO_T ( char *nm X SPECIFICATION spec X COMMAND cmd )
{
CONST char *tnm = crt_file_name ;
crt_line_no = 1 ;
if ( nm == NULL || streq ( nm, "-" ) ) {
crt_file_name = "<stdout>" ;
output_file = stdout ;
nm = NULL ;
} else {
crt_file_name = nm ;
output_file = fopen ( nm, "w" ) ;
if ( output_file == NULL ) {
error ( ERROR_SERIOUS, "Can't open output file, '%s'", nm ) ;
return ;
}
}
output_posn = 0 ;
crt_column = 0 ;
crt_file_name = tnm ;
crt_major = DEREF_unsigned ( spec_major ( spec ) ) ;
crt_minor = DEREF_unsigned ( spec_minor ( spec ) ) ;
output_template ( spec, cmd ) ;
if ( output_posn ) output_char ( '\n' ) ;
if ( nm ) fclose_v ( output_file ) ;
return ;
}