This file is indexed.

/usr/bin/sdngen is in sdf 2.001+1-5.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#!/usr/bin/perl
# $Id$
$VERSION{'PUBLIC'} = '2.000';
$VERSION{''.__FILE__} = '$Revision$';
#
# >>Title::     SDF Tuning File Generator
#
# >>Copyright::
# Copyright (c) 1992-1997, Ian Clatworthy (ianc@mincom.com).
# You may distribute under the terms specified in the LICENSE file.
#
# >>History::
# -----------------------------------------------------------------------
# Date      Who     Change
# 18-Jan-97 ianc    SDF 2.000
# -----------------------------------------------------------------------
#
# >>Purpose::
# {{CMD:sdngen}} extracts SDF template information from a [[FrameMaker]]
# template.
#
# >>Description::
# !SDF_OPT_STD
#
# The -p option can be used to specify the root paragraph format from
# which others are derived. The default paragraph root is {{Body}}.
#
# The -f option can be used to specify the root font (i.e. phrase) format
# from which others are derived. The default font root is {{Emphasis}}.
#
# The -t option can be used to specify the root table format from
# which others are derived. The default table root is {{Format A}}.
#
# As formats often appear in families (e.g. Heading1, Heading2,
# etc.), {{sdngen}} will use the (alphabetically) previous format as
# the parent if it makes a better parent (i.e. there are less differences)
# than the default one.
#
# If a template already exists, it can be specified using the -e option.
# In this case, {{sdngen}} will get as much information as it can from
# that file including:
#
# * the root format for each type
# * the order of formats within a type
# * the parent for each format.
#
# Within each type, formats which are unknown in the existing template
# are output after those that are known.
#
# >>Examples::
# To generate an SDF tuning file file:
#
# V:     sdngen -osdn mytemplate.mif
#
# This will create a template file called {{FILE:mytemplate.sdn}}.
#
# >>Limitations::
#

require "sdf/app.pl";
require "sdf/parse.pl";
require "sdf/tomif.pl";

########## Initialisation ##########

# define configuration
%app_config = (
    'libdir',   'sdf/home',
);

# define options
push(@app_option, (
    #'Name|Spec|Help',
    'para_root|STR;Body|default parent for a paragraph format',
    'font_root|STR;Emphasis|default parent for a font format',
    'tbl_root|STR;Format A|default parent for a table format',
    'existing_template|STR|existing template file',
));

# handle options
&AppInit('file ...', 'generate an SDF template from a Frame one', 'SDF') ||
  &AppExit();

# initialise the lookup tables loaded when a template already exists
%objects = ();
%parents = ();

# if a template already exists, get as many details as we can from it
if ($existing_template ne '') {

    # Open the file
    unless(open(EXISTING, $existing_template)) {
        &AppExit("fatal", "unable to open existing template '$existing_template'");
    }

    # Scan the template for useful information
    while (<EXISTING>) {
        next unless /^\s*\!targetobject\s+/;
        ($type, $name, $parent) = split(/\s*\;\s*/, $');
        $type =~ s/^\s*["']//;
        $type =~ s/["']\s*$//;
        $name =~ s/^\s*["']//;
        $name =~ s/["']\s*$//;
        $parent =~ s/^\s*["']//;
        $parent =~ s/["']\s*$//;

        # Save the information
        $parents{$type,$name} = $parent;
        if ($objects{$type} eq '') {
            $objects{$type} = $name;
            $para_root = $name if $type eq 'Para';
            $font_root = $name if $type eq 'Phrase';
            $tbl_root  = $name if $type eq 'Table';
        }
        else {
            $objects{$type} .= "\000$name";
        }
    }
    close(EXISTING);
}


########## Support routines ##########

sub ConvertCatalogToSdf {
    local($type, $root, *catalog, *known_objects, *known_parents, *my_attr_list) = @_;
#   local();
    local(@names, @known_names, %known, @ordered_names);
    local(@attr_list);
    local(%root_attrs);
    local($name, $parent, %attrs, %parent_attrs);
    local($prev, %prev_attrs);
    local(%prev_diff, %root_diff, %this_diff);
    local($prev_diff_cnt, $root_diff_cnt);
    local($obj_cnt, $attr_cnt, $diff_cnt, $diff_avg);

    # Check that the catalog is not empty
    @names = sort keys %catalog;
    $obj_cnt = scalar(@names);
    unless ($obj_cnt) {
        &AppMsg("object", "NO $type formats found");
        return;
    }

    # Check that the root object exists
    if (!defined($catalog{$root})) {
        &AppMsg("warning", "root $type '$root' not found (using '$names[0]' instead)");
        $root = shift(@names);
    }

    # Get the attributes of the root object
    %root_attrs = &_MifAttrSplit($catalog{$root});

    # Output the root
    print "# Define the root '$type' format\n";
    &OutputTargetObject($type, $root, '', *root_attrs);

    # Decide on the attribute list to use
    @attr_list = @my_attr_list ? @my_attr_list : sort keys %root_attrs;

    # If there are known objects, output them first
    @known_names = split(/\000/, $known_objects{$type});
    if (@known_names) {
        %known = ();
        grep($known{$_}++, @known_names);
        @ordered_names = @known_names;
        for $name (@names) {
            push(@ordered_names, $name) unless $known{$name};
        }
    }
    else {
        @ordered_names = @names;
    }

    # Analyse and output the non-root formats
    print "\n# Define the other '$type' formats\n";
    %prev_attrs = ();
    $prev = '';
    $diff_cnt = 0;
    for $name (@ordered_names) {

        # Skip the root
        next if $name eq $root;

        # If the list includes names from an existing template,
        # the object might not exist in the catalog, so skip it
        next if $catalog{$name} eq '';

        # Get the attributes
        %attrs = &_MifAttrSplit($catalog{$name});

        # Get the parent and the attribute differences
        $parent = $known_parents{$type,$name};
        if ($parent ne '') {
            %parent_attrs = &_MifAttrSplit($catalog{$parent});
            %this_diff = &DiffAttrs(*attrs, *parent_attrs, *attr_list);
        }
        else {
            # Decide on the best parent
            %root_diff = &DiffAttrs(*attrs, *root_attrs, *attr_list);
            %prev_diff = &DiffAttrs(*attrs, *prev_attrs, *attr_list);
            $root_diff_cnt = scalar(keys %root_diff);
            $prev_diff_cnt = scalar(keys %prev_diff);
            if ($root_diff_cnt < $prev_diff_cnt) {
                $parent = $root;
                %this_diff = %root_diff;
            }
            else {
                $parent = $prev;
                %this_diff = %prev_diff;
            }
        }
        
        # Output the object
        &OutputTargetObject($type, $name, $parent, *this_diff);

        # Collect some stats
        $diff_cnt += scalar(keys %this_diff);
    }
    continue {
        # Save away the previous attributes and name
        %prev_attrs = %attrs;
        $prev = $name;
    }

    # Output some basic stats
    $attr_cnt = scalar(@attr_list);
    $diff_avg = sprintf("%.1f", $diff_cnt/($obj_cnt - 1));
    &AppMsg("object", "$obj_cnt $type formats, $attr_cnt attrs each," .
      " average difference is $diff_avg");
}

sub OutputTargetObject {
    local($type, $name, $parent, *attrs) = @_;
#   local();
    local($attr, $value);

    # Print the macro header
    $parent = " \"$parent\"" if $parent ne '';
    print "!targetobject \"$type\"; \"$name\";$parent";
    
    # Print the attributes, if any
    for $attr (sort keys %attrs) {
        $value = &FormatValue($attrs{$attr});
        print "; \\\n  $attr=$value";
    }
    print "\n\n";
}

sub FormatValue {
    local($value) = @_;
    local($result);

    # Integers and enumerated values are fine as is
    # Values with " are enclosed in '', otherwise
    # the value is enclosed in "".
    if ($value =~ /^\d+$/ || $value =~ /^[A-Z][a-z]+$/) {
        return $value;
    }
    elsif ($value =~ /["\\]/) {
        return "'$value'";
    }
    else {
        return '"' . $value . '"';
    }
}

sub DiffAttrs {
    local(*nv1, *nv2, *name_list) = @_;
    local(%diff);
    local($name);

    # Check the empty set first
    return %nv1 unless %nv2;

    # Find the differences
    %diff = ();
    for $name (@name_list) {
        $diff{$name} = $nv1{$name} unless $nv1{$name} eq $nv2{$name};
    }

    # Return result
    return %diff;
}

########## Processing ##########

sub argProcess {
    local($ARGV) = @_;
#   local();

    # Fetch the template
    unless (&_MifFetchTemplate($ARGV)) {
        &AppMsg("abort", "unable to fetch MIF template '$ARGV'");
        return;
    }

    # Convert the MIF catalogs into an SDF template
    &ConvertCatalogToSdf('Para',   $para_root, *_mif_tpl_paras, *objects,
      *parents, *MIF_PARA_ATTRS);
    &ConvertCatalogToSdf('Phrase', $font_root, *_mif_tpl_fonts, *objects,
      *parents, *MIF_FONT_ATTRS);
    &ConvertCatalogToSdf('Table',  $tbl_root,  *_mif_tpl_tbls, *objects,
      *parents);
}

&AppProcess('argProcess');
&AppExit();