home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / s / sd-27.zip / mkcalls.c < prev    next >
C/C++ Source or Header  |  1992-11-15  |  44KB  |  1,505 lines

  1. /* SD -- square dance caller's helper.
  2.  
  3.     Copyright (C) 1990, 1991, 1992  William B. Ackerman.
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 1, or (at your option)
  8.     any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     This is for version 27. */
  20.  
  21. /* mkcalls.c */
  22.  
  23. #include <stdio.h>
  24.  
  25. #ifdef _POSIX_SOURCE
  26. #include <unistd.h>
  27. #endif
  28.  
  29. /* We take pity on those poor souls who are compelled to use
  30.     troglodyte development environments. */
  31.  
  32. #ifdef __STDC__
  33. #include <stdlib.h>
  34. #else
  35. extern void exit(int code);
  36. #endif
  37.  
  38. #ifndef SEEK_SET        /* stdlib.h may not define it */
  39. #define SEEK_SET 0
  40. #endif
  41.  
  42. #include <string.h>
  43. #include <errno.h>
  44.  
  45. #include "database.h"
  46. #include "paths.h"
  47.  
  48. /* This is the number of "base" (tagged) calls that our internal tables
  49.    can handle.  Making this number enormous only uses up space in this program,
  50.    in the array "tagtab".  Space is not wasted in the sd program itself,
  51.    because we encode into the database the number of tagged calls that
  52.    we actually used. */
  53. #define DATABASE_MAX_BASE_CALLS 1000
  54.  
  55. typedef enum {
  56.    tok_string, tok_symbol, tok_lbkt, tok_rbkt, tok_number} toktype;
  57.  
  58.  
  59. /* Several of the top-level flags have different meanings for calls
  60. defined by array or defined by (concentric or sequential) definition.
  61.  
  62.     flag                   meaning by array                      meaning by (concentric or
  63.                                                                    sequential) definition
  64.  
  65. left_means_mirror        The "left" modifier is legal          The "left" modifier is legal
  66.                          and causes the call to be             and will be passed on to those
  67.                          done mirror.                          subcalls that have the
  68.                                                                "inherit_left" property set in
  69.                                                                the subcall invocation.  Its
  70.                                                                meaning in that subcall is
  71.                                                                determined according to the way
  72.                                                                that subcall is defined, by
  73.                                                                applying this rule recursively.
  74.                                                                Presumably at least one subcall
  75.                                                                has that property set.
  76.  
  77. reverse_means_mirror     The "reverse" modifier is legal       The "reverse" modifier is legal
  78.                          and causes the call to be             and will be passed on to those
  79.                          done mirror.                          subcalls that have the
  80.                          You may also use the                  "inherit_left" property set in
  81.                          "reverse_coming_next"                 the subcall invocation.  Its
  82.                          flag in the array list to             meaning in that subcall is
  83.                          get a completely different            determined according to the way
  84.                          meaning.  You should of               that subcall is defined, by
  85.                          course not use both.                  applying this rule recursively.
  86.                                                                Presumably at least one subcall
  87.                                                                has that property set.
  88.  
  89. diamond_is_inherited     The "diamond" modifier is legal,      The "diamond" modifier is legal
  90.                          and its meaning is determined by an   and will be passed on to those
  91.                          item in the array list that has the   subcalls that have the
  92.                          "alternate_definition [diamond]"      "inherit_diamond" property set in
  93.                          flag.                                 the subcall invocation.  Its
  94.                                                                meaning in that subcall is
  95.                                                                determined according to the way
  96.                                                                that subcall is defined, by
  97.                                                                applying this rule recursively.
  98.                                                                Presumably at least one subcall
  99.                                                                has that property set.
  100.  
  101. magic_is_inherited       Has no meaning.  If the "magic"       The "magic" modifier is legal
  102.                          modifier is given, its legality       and will be passed on to those
  103.                          and meaning are determined by an      subcalls that have the
  104.                          item in the array list that has the   "inherit_magic" property set in
  105.                          "alternate_definition [magic]"        the subcall invocation.  Its
  106.                          flag.                                 meaning in that subcall is
  107.                                                                determined according to the way
  108.                                                                that subcall is defined, by
  109.                                                                applying this rule recursively.
  110.                                                                Presumably at least one subcall
  111.                                                                has that property set.
  112.  
  113. intlk_is_inherited       Has no meaning.  If the "interlocked" The "interlocked" modifier is legal
  114.                          modifier is given, its legality       and will be passed on to those
  115.                          and meaning are determined by an      subcalls that have the
  116.                          item in the array list that has the   "inherit_intlk" property set in
  117.                          "alternate_definition [interlocked]"  the subcall invocation.  Its
  118.                          flag.                                 meaning in that subcall is
  119.                                                                determined according to the way
  120.                                                                that subcall is defined, by
  121.                                                                applying this rule recursively.
  122.                                                                Presumably at least one subcall
  123.                                                                has that property set.
  124.  
  125. 12_matrix_is_inherited   Has no meaning.  If the "12 matrix"   The "12 matrix" modifier is legal
  126.                          modifier is given, its legality       and will be passed on to those
  127.                          and meaning are determined by an      subcalls that have the
  128.                          item in the array list that has the   "inherit_12_matrix" property set in
  129.                          "alternate_definition [12matrix]"     the subcall invocation.  Its
  130.                          flag.                                 meaning in that subcall is
  131.                                                                determined according to the way
  132.                                                                that subcall is defined, by
  133.                                                                applying this rule recursively.
  134.                                                                Presumably at least one subcall
  135.                                                                has that property set.
  136.  
  137. funny_is_inherited       Has no meaning.  Use the              The "funny" modifier is legal
  138.                          "simple_funny" flag at the            and will be passed on to those
  139.                          head of each array list.              subcalls that have the
  140.                          This will make "funny" legal          "inherit_funny" property set in
  141.                          for that call from that setup.        the subcall invocation.  Its
  142.                                                                meaning in that subcall is
  143.                                                                determined according to the way
  144.                                                                that subcall is defined, by
  145.                                                                applying this rule recursively.
  146.                                                                Presumably at least one subcall
  147.                                                                has that property set.
  148.  
  149. Properties applied to a call are only legal (whether they arose from being clicked on at
  150. the top level or being inherited from a higher level call) if they can be interpreted according
  151. to one of the mechanisms described above.  For example, if we have:
  152.  
  153. call "scoot and plenty" c1
  154.             left_means_mirror
  155.             intlk_is_inherited
  156.    seq scootback [inherit_intlk]
  157.    seq plenty [inherit_left inherit_intlk]
  158.  
  159. then "left scoot and plenty" is only legal if "left plenty" is legal.
  160. (The legality of "left scoot back" is irrelevant, since the "inherit_left"
  161. property is not present on that invocation.)
  162.  
  163. Now if we have:
  164.  
  165. call "plenty" c1 tag plenty
  166.             left_means_mirror
  167.             intlk_is_inherited
  168.    seq startplenty [inherit_left inherit_intlk]
  169.    seq turnstar2 [or_anycall]
  170.    seq finishplenty []
  171.  
  172. then "left scoot and plenty" is only legal if "left _start plenty" is legal.
  173.  
  174. Now if we have:
  175.  
  176. call "_start plenty" dontshow tag startplenty
  177.             fudge_to_q_tag left_means_mirror
  178.    setup qtag 2x4
  179.       array [3S 4S 2S 2N 0 0 1S 1N]
  180.                intlk_coming_next
  181.    setup qtag 2x4
  182.       array [3S 4S 1S 2N 0 0 2S 1N]
  183.  
  184. then "left scoot and plenty" is legal.  The "_start plenty" will be
  185. done mirror, but the scoot back, star turn, and finish will not.
  186. */
  187.  
  188. /* A few notes about "definition modifiers":
  189.  
  190. These appear within the brackets after each call in a concdefine or seqdefine or whatever.
  191. They are only meaningful as indicated in the table in database.h.  For example, repeat_n
  192. is meaningful only in a "seq" definition, not in a "conc" definition.
  193.  
  194. Full documentation of these doesn't exist (and, when it does, it will belong elsewhere),
  195. but the following notes need to be written down.
  196.  
  197. When "repeat_n_alternate" is used on a part of a "seq" definition, there MUST be
  198. another part following.  No flags in that part are meaningful -- it gets its flags
  199. from the first part.
  200.  
  201. When "roll_transparent" is used on a part of a "seq" definition, that call must
  202. have the property that anyone who is marked roll-neutral (that is, with an "M" roll
  203. letter), must not have moved at all, and must consider this part not to have applied
  204. to him, so that the call "roll" will direct him to use the roll direction arising
  205. from what he did previously.  The call "centers hinge" obeys this property, and so
  206. the "roll_transparent" flag is appropriate.  The purpose of this flag is to make
  207. the centers hinge part of peel/trail to a diamond work correctly, so that the
  208. new points can roll.
  209. */
  210.  
  211.  
  212.  
  213. typedef struct {
  214.    int def;
  215.    char s[80];
  216.    } tagtabitem;
  217.  
  218.  
  219. /* This table is keyed to "level". */
  220. char *leveltab[] = {
  221.    "mainstream", "plus", "a1", "a2", "c1", "c2", "c3a", "c3", "c3x", "c4a", "c4", "dontshow", ""};
  222.  
  223. /* This table is keyed to "begin_kind". */
  224. char *sstab[] = {
  225.    "??",
  226.    "1x1",
  227.    "1x2",
  228.    "2x1",
  229.    "1x3",
  230.    "3x1",
  231.    "2x2",
  232.    "dmd",
  233.    "pmd",
  234.    "star",
  235.    "trngl",
  236.    "ptrngl",
  237.    "bone6",
  238.    "pbone6",
  239.    "short6",
  240.    "pshort6",
  241.    "qtag",
  242.    "pqtag",
  243.    "bone",
  244.    "pbone",
  245.    "rigger",
  246.    "prigger",
  247.    "spindle",
  248.    "pspindle",
  249.    "hrglass",
  250.    "phrglass",
  251.    "crosswave",
  252.    "pcrosswave",
  253.    "1x4",
  254.    "4x1",
  255.    "1x8",
  256.    "8x1",
  257.    "2x4",
  258.    "4x2",
  259.    "2x3",
  260.    "3x2",
  261.    "1x6",
  262.    "6x1",
  263.    "3x4",
  264.    "4x3",
  265.    "2x6",
  266.    "6x2",
  267.    "2x8",
  268.    "8x2",
  269.    "4x4",
  270.    "1x10",
  271.    "10x1",
  272.    "1x12",
  273.    "12x1",
  274.    "1x14",
  275.    "14x1",
  276.    "1x16",
  277.    "16x1",
  278.    "c1phan",
  279.    "galaxy",
  280.    "4x6",
  281.    "6x4",
  282.    "thar",
  283.    "ptpd",
  284.    "pptpd",
  285.    "3x1dmd",
  286.    "p3x1dmd",
  287.    "3dmd",
  288.    "p3dmd",
  289.    "4dmd",
  290.    "p4dmd",
  291.    ""};
  292.  
  293. /* This table is keyed to "setup_kind". */
  294. char *estab[] = {
  295.    "nothing",
  296.    "1x1",
  297.    "1x2",
  298.    "1x3",
  299.    "2x2",
  300.    "dmd",
  301.    "star",
  302.    "trngl",
  303.    "bone6",
  304.    "short6",
  305.    "qtag",
  306.    "bone",
  307.    "rigger",
  308.    "spindle",
  309.    "hrglass",
  310.    "hyperglass",
  311.    "crosswave",
  312.    "1x4",
  313.    "1x8",
  314.    "2x4",
  315.    "2x3",
  316.    "1x6",
  317.    "3x4",
  318.    "2x6",
  319.    "2x8",
  320.    "4x4",
  321.    "1x10",
  322.    "1x12",
  323.    "1x14",
  324.    "1x16",
  325.    "c1phan",
  326.    "bigblob",
  327.    "ptpd",
  328.    "3x1dmd",
  329.    "3dmd",
  330.    "4dmd",
  331.    "wingedstar",
  332.    "wingedstar12",
  333.    "wingedstar16",
  334.    "galaxy",
  335.    "4x6",
  336.    "thar",
  337.    "normal_concentric",
  338.    ""};
  339.  
  340. /* This table is keyed to "calldef_schema". */
  341. char *schematab[] = {
  342.    "conc",
  343.    "crossconc",
  344.    "singleconc",
  345.    "singlecrossconc",
  346.    "maybesingleconc",
  347.    "conc_diamond_line",
  348.    "conc6_2",
  349.    "conc2_6",
  350.    "conc_star",
  351.    "conc_star12",
  352.    "conc_star16",
  353.    "maybematrix_conc_star",
  354.    "checkpoint",
  355.    "reverse_checkpoint",
  356.    "ckpt_star",
  357.    "???",
  358.    "???",
  359.    "seq",
  360.    "splitseq",
  361.    "setup",
  362.    "nulldefine",
  363.    "matrix",
  364.    "partnermatrix",
  365.    "rolldefine",
  366.    ""};
  367.  
  368. /* This table is keyed to "search_qualifier". */
  369. char *qualtab[] = {
  370.    "none",
  371.    "wave_only",
  372.    "2fl_only",
  373.    "miniwaves",
  374.    "right_wave",
  375.    "left_wave",
  376.    "3_4_tag",
  377.    "dmd_same_point",
  378.    "dmd_facing",
  379.    "true_Z",
  380.    "ctrwv_end2fl",
  381.    "ctr2fl_endwv",
  382.    ""};
  383.  
  384. /* This table is keyed to "call_restriction". */
  385. char *crtab[] = {
  386.    "???",
  387.    "alwaysfail",
  388.    "wave_only",
  389.    "wave_unless_say_2faced",
  390.    "all_facing_same",
  391.    "1fl_only",
  392.    "2fl_only",
  393.    "3x3_2fl_only",
  394.    "4x4_2fl_only",
  395.    "couples_only",
  396.    "3x3couples_only",
  397.    "4x4couples_only",
  398.    "awkward_centers",
  399.    "nice_diamonds",
  400.    "magic_only",
  401.    "peelable_box",
  402.    "ends_are_peelable",
  403.    "not_tboned",
  404.    "quarterbox_or_col",
  405.    "quarterbox_or_magic_col",
  406.    ""};
  407.  
  408. /* This table is keyed to the constants "dfm_???". */
  409. char *defmodtab[] = {
  410.    "conc_demand_lines",
  411.    "conc_demand_columns",
  412.    "conc_force_lines",
  413.    "conc_force_columns",
  414.    "conc_force_otherway",
  415.    "conc_force_spots",
  416.    "conc_concentric_rules",
  417.    "suppress_elongation_warnings",
  418.    "or_anycall",
  419.    "mandatory_anycall",
  420.    "repeat_n",
  421.    "repeat_nm1",
  422.    "repeat_n_alternate",
  423.    "endscando",
  424.    "allow_forced_mod",
  425.    "roll_transparent",
  426.    "must_be_tag_call",
  427.    "must_be_scoot_call",
  428.    "cpls_unless_single",
  429.    "??",
  430.    "??",
  431.    "??",
  432.    "inherit_diamond",
  433.    "inherit_reverse",
  434.    "inherit_left",
  435.    "inherit_funny",
  436.    "inherit_intlk",
  437.    "inherit_magic",
  438.    "inherit_grand",
  439.    "inherit_12_matrix",
  440.    "inherit_cross",
  441.    "inherit_single",
  442.    ""};
  443.  
  444. /* This table is keyed to the constants "cflag__???". */
  445. char *flagtab[] = {
  446.    "step_to_wave",
  447.    "rear_back_from_r_wave",
  448.    "rear_back_from_qtag",
  449.    "dont_use_in_resolve",
  450.    "needselector",         /* This actually never appears in the text -- it is automatically added. */
  451.    "neednumber",
  452.    "sequence_starter",
  453.    "split_like_square_thru",
  454.    "split_like_dixie_style",
  455.    "parallel_conc_end",
  456.    "take_right_hands",
  457.    "is_tag_call",
  458.    "is_scoot_call",
  459.    "is_star_call",
  460.    "split_large_setups",
  461.    "fudge_to_q_tag",
  462.    "visible_fractions",
  463.    "first_part_visible",
  464.    "12_16_matrix_means_split",
  465.    "??",
  466.    "??",
  467.    "??",
  468.    "diamond_is_legal",
  469.    "reverse_means_mirror",
  470.    "left_means_mirror",
  471.    "funny_is_inherited",
  472.    "intlk_is_inherited",
  473.    "magic_is_inherited",
  474.    "grand_is_inherited",
  475.    "12_matrix_is_inherited",
  476.    "cross_is_inherited",
  477.    "single_is_inherited",
  478.    ""};
  479.  
  480. /* This table is keyed to the constants "cflag__???".
  481.    Notice that it looks like the end of flagtab, with an offset defined here. */
  482.  
  483. #define NEXTTAB_OFFSET 22
  484.  
  485. char *nexttab[] = {
  486.    "diamond",
  487.    "reverse",
  488.    "left",
  489.    "???",
  490.    "interlocked",
  491.    "magic",
  492.    "grand",
  493.    "12matrix",
  494.    "cross",
  495.    "single",
  496.    ""};
  497.  
  498. /* This table is keyed to the constants "MTX_???". */
  499. char *matrixcallflagtab[] = {
  500.    "use_selector",
  501.    "stop_and_warn_on_tbone",
  502.    "tbone_is_ok",
  503.    "ignore_nonselectees",
  504.    "must_face_same_way",
  505.    ""};
  506.  
  507. /* BEWARE!!  This list must track the array "pred_table" in sdpreds.c . */
  508.  
  509. /* The first 6 of these (the constant to use is SELECTOR_PREDS) take a predicate.
  510.    Any call that uses one of these predicates in its definition will cause a
  511.    popup to appear asking "who?". */
  512.  
  513. char *predtab[] = {
  514.    "select",
  515.    "unselect",
  516.    "select_near_select",
  517.    "select_near_unselect",
  518.    "unselect_near_select",
  519.    "unselect_near_unselect",
  520.    "always",
  521.    "x22_miniwave",
  522.    "x22_couple",
  523.    "x22_facing_someone",           /* does anyone use this? */
  524.    "x14_once_rem_miniwave",
  525.    "x14_once_rem_couple",
  526.    "lines_miniwave",
  527.    "lines_couple",
  528.    "lines_magic_miniwave",
  529.    "lines_magic_couple",
  530.    "lines_once_rem_miniwave",
  531.    "lines_once_rem_couple",
  532.    "lines_tandem",
  533.    "lines_antitandem",
  534.    "columns_tandem",
  535.    "columns_antitandem",
  536.    "columns_magic_tandem",
  537.    "columns_magic_antitandem",
  538.    "columns_once_rem_tandem",
  539.    "columns_once_rem_antitandem",
  540.    "columns_couple",
  541.    "columns_miniwave",
  542.    "1x2_beau_or_miniwave",
  543.    "1x4_wheel_and_deal",
  544.    "1x6_wheel_and_deal",
  545.    "1x8_wheel_and_deal",
  546.    "vert1",
  547.    "vert2",
  548.    "inner_active_lines",
  549.    "outer_active_lines",
  550.    "judge_is_right",
  551.    "judge_is_left",
  552.    "socker_is_right",
  553.    "socker_is_left",
  554.    "inroller_is_cw",
  555.    "magic_inroller_is_cw",
  556.    "outroller_is_cw",
  557.    "outposter_is_cw",
  558.    "outposter_is_ccw",
  559.    "nexttrnglspot_is_tboned",
  560.    "next62spot_is_tboned",
  561.    "next_magic62spot_is_tboned",
  562.    "next_galaxyspot_is_tboned",
  563.    "column_double_down",
  564.    "boyp",
  565.    "girlp",
  566.    "roll_is_cw",
  567.    "roll_is_ccw",
  568.    "x12_boy_facing_girl",
  569.    "x12_girl_facing_boy",
  570.    "x22_boy_facing_girl",
  571.    "x22_girl_facing_boy",
  572.    "dmd_ctrs_rh",
  573.    "trngl_pt_rh",
  574.    "q_tag_front",
  575.    "q_tag_back",
  576.    "q_line_front",
  577.    "q_line_back",
  578.    ""};
  579.  
  580. int tagtabsize = 2;
  581.  
  582. tagtabitem tagtab[DATABASE_MAX_BASE_CALLS] = {
  583.       {1, "+++"},         /* Must be unused -- call #0 signals end of list in sequential encoding. */
  584.       {0, "nullcall"}};   /* Must be next -- the database initializer uses call #1 for any mandatory
  585.                                     modifier, e.g. "clover and [anything]" is executed as
  586.                                     "clover and [call #1]". */
  587.  
  588. int eof;
  589. int chars_left;
  590. char *lineptr;
  591. int linelen;
  592. int lineno;
  593. int tok_value;
  594. int letcount;
  595. toktype tok_kind;
  596. char tok_str[80];
  597. int char_ct;
  598.  
  599. FILE *infile;
  600. FILE *outfile;
  601. char line[200];
  602. char ch;
  603. char *return_ptr;
  604. int callcount;
  605. int filecount;
  606. int dumbflag;
  607. int call_flags;
  608. int call_tag;
  609. char call_name[80];
  610. int call_namelen;
  611. int call_level;
  612. int call_startsetup;
  613. int call_qualifier;
  614. int call_endsetup;
  615. int call_endsetup_in;
  616. int call_endsetup_out;
  617. int bmatrix, gmatrix;
  618. int restrstate;
  619. int callarray_flags1;
  620. int callarray_flags2;
  621.  
  622. /* BEWARE!!  This list is keyed to the definition of "begin_kind" in SD.H. */
  623. /*   It must also match the similar table in the sdtables.c. */
  624. int begin_sizes[] = {
  625.    0,          /* b_nothing */
  626.    1,          /* b_1x1 */
  627.    2,          /* b_1x2 */
  628.    2,          /* b_2x1 */
  629.    3,          /* b_1x3 */
  630.    3,          /* b_3x1 */
  631.    4,          /* b_2x2 */
  632.    4,          /* b_dmd */
  633.    4,          /* b_pmd */
  634.    4,          /* b_star */
  635.    6,          /* b_trngl */
  636.    6,          /* b_ptrngl */
  637.    6,          /* b_bone6 */
  638.    6,          /* b_pbone6 */
  639.    6,          /* b_short6 */
  640.    6,          /* b_pshort6 */
  641.    8,          /* b_qtag */
  642.    8,          /* b_pqtag */
  643.    8,          /* b_bone */
  644.    8,          /* b_pbone */
  645.    8,          /* b_rigger */
  646.    8,          /* b_prigger */
  647.    8,          /* b_spindle */
  648.    8,          /* b_pspindle */
  649.    8,          /* b_hrglass */
  650.    8,          /* b_phrglass */
  651.    8,          /* b_crosswave */
  652.    8,          /* b_pcrosswave */
  653.    4,          /* b_1x4 */
  654.    4,          /* b_4x1 */
  655.    8,          /* b_1x8 */
  656.    8,          /* b_8x1 */
  657.    8,          /* b_2x4 */
  658.    8,          /* b_4x2 */
  659.    6,          /* b_2x3 */
  660.    6,          /* b_3x2 */
  661.    6,          /* b_1x6 */
  662.    6,          /* b_6x1 */
  663.    12,         /* b_3x4 */
  664.    12,         /* b_4x3 */
  665.    12,         /* b_2x6 */
  666.    12,         /* b_6x2 */
  667.    16,         /* b_2x8 */
  668.    16,         /* b_8x2 */
  669.    16,         /* b_4x4 */
  670.    10,         /* b_1x10 */
  671.    10,         /* b_10x1 */
  672.    12,         /* b_1x12 */
  673.    12,         /* b_12x1 */
  674.    14,         /* b_1x14 */
  675.    14,         /* b_14x1 */
  676.    16,         /* b_1x16 */
  677.    16,         /* b_16x1 */
  678.    16,         /* b_c1phan */
  679.    8,          /* b_galaxy */
  680.    24,         /* b_4x6 */
  681.    24,         /* b_6x4 */
  682.    8,          /* b_thar */
  683.    8,          /* b_ptpd */
  684.    8,          /* b_pptpd */
  685.    8,          /* b_3x1dmd */
  686.    8,          /* b_p3x1dmd */
  687.    12,         /* b_3dmd */
  688.    12,         /* b_p3dmd */
  689.    16,         /* b_4dmd */
  690.    16};        /* b_p4dmd */
  691.  
  692. static void errexit(char s[])
  693. {
  694.    char my_line[80];
  695.    int i;
  696.  
  697.    if (!call_namelen) {
  698.       if (eof) {
  699.          printf("Error at line %d:\n%s.\n", lineno, s);
  700.       }
  701.       else {
  702.          strncpy(my_line, lineptr, linelen-1);
  703.          my_line[linelen-1] = '\0';
  704.          printf("Error at line %d:\n%s.\n%s\n", lineno, s, my_line);
  705.          for (i = 1; i <= linelen-chars_left-1; i++) printf(" ");
  706.          printf("|\n");
  707.       }
  708.    }
  709.    else {
  710.       if (eof) {
  711.          printf("Error at line %d:\n%s.  Last call was: %s\n", lineno, s, call_name);
  712.       }
  713.       else {
  714.          strncpy(my_line, lineptr, linelen-1);
  715.          my_line[linelen-1] = '\0';
  716.          printf("Error at line %d:\n%s.  Last call was: %s\n%s\n", lineno, s, call_name, my_line);
  717.          for (i = 1; i <= linelen-chars_left-1; i++) printf(" ");
  718.          printf("|\n");
  719.       }
  720.    }
  721.  
  722.    exit(1);
  723. }
  724.  
  725.  
  726. static int get_char(void)
  727. {
  728.    if (!chars_left) {
  729.       lineno++;
  730.       return_ptr = fgets(line, 199, infile);
  731.       lineptr = return_ptr;
  732.       linelen = strlen(line);
  733.       if (!return_ptr)
  734.          {
  735.          if (feof(infile)) {
  736.             eof = 1;
  737.             return(1);
  738.          }
  739.          else {
  740.             perror("Can't read input file");
  741.             exit(1);
  742.          }
  743.       }
  744.       chars_left = linelen;
  745.       }
  746.    ch = *return_ptr++;
  747.    chars_left--;
  748.    return(0);
  749. }
  750.  
  751. static int symchar(void)
  752. {
  753.    if (ch == '[' || ch == ']' || ch == ',' || ch == ':' || (int)ch <= 32) return(0);
  754.    else return(1);
  755. }
  756.  
  757. static void get_tok_or_eof(void)
  758. {
  759.    int digit;
  760.  
  761.    char_ct = 0;
  762.    tok_value = 0;
  763.    letcount = 0;
  764.    while ((ch == ' ') || (ch == '/') || (ch == '\n')) {
  765.       if (ch == '/') {
  766.          if (get_char()) errexit("End of file in comment starter");
  767.          if (ch != '*') errexit("Incorrect comment starter");
  768.          while (1) {
  769.             if (get_char()) errexit("End of file inside comment");
  770.             if (ch == '*') {
  771.                while (1) {
  772.                   if (get_char()) errexit("End of file inside comment");
  773.                   if (ch != '*') break;
  774.                }
  775.                if (ch == '/') break;
  776.             }
  777.          }
  778.       }
  779.       if (get_char()) return;
  780.    }
  781.    /* Now have a real character. */
  782.    switch (ch) {
  783.       case '[': tok_kind = tok_lbkt; ch = ' '; break;
  784.       case ']': tok_kind = tok_rbkt; ch = ' '; break;
  785.       case '"':
  786.          while (1) {
  787.             if (get_char()) {
  788.                printf("end of file inside string\n");
  789.                exit(1);
  790.             }
  791.             if (ch == '"') break;
  792.             else if (ch == '\\') {
  793.                if (get_char()) {
  794.                   printf("end of file inside string\n");
  795.                   exit(1);
  796.                }
  797.             }
  798.             if (char_ct > 80) {
  799.                printf("String too long\n");
  800.                exit(1);
  801.             }
  802.             tok_str[char_ct++] = ch;
  803.          }
  804.  
  805.          ch = ' ';
  806.          tok_kind = tok_string;
  807.  
  808.          /* Pack a null. */
  809.  
  810.          if (char_ct > 80) {
  811.             printf("String too long\n");
  812.             exit(1);
  813.          }
  814.          tok_str[char_ct] = '\0';
  815.          break;
  816.       default:
  817.          while (1) {
  818.             if (char_ct > 80) {
  819.                printf("Symbol too long\n");
  820.                exit(1);
  821.             }
  822.             tok_str[char_ct++] = ch;
  823.  
  824.             digit = ch - '0';
  825.             if (digit < 0 || digit > 9) letcount++;
  826.             else tok_value = tok_value*10 + digit;
  827.  
  828.             if (get_char()) {
  829.                printf("End of file inside symbol\n");
  830.                exit(1);
  831.             }
  832.  
  833.             if (!symchar()) break;
  834.          }
  835.  
  836.          /* Pack a null. */
  837.  
  838.          if (char_ct > 80) {
  839.             printf("Symbol too long\n");
  840.             exit(1);
  841.          }
  842.          tok_str[char_ct] = '\0';
  843.  
  844.          if (letcount)
  845.             tok_kind = tok_symbol;
  846.          else
  847.             tok_kind = tok_number;
  848.          break;
  849.    }
  850. }
  851.  
  852.  
  853. /* This returns -1 if the item is not found. */
  854.  
  855. static int search(char *table[])
  856. {
  857.    int i;
  858.  
  859.    i = -1;
  860.    while (*table[++i]) {
  861.       if (strcmp(tok_str, table[i]) == 0)
  862.          return(i);
  863.    }
  864.    return(-1);
  865. }
  866.  
  867.  
  868. static int tagsearch(int def)
  869. {
  870.    int i;
  871.  
  872.    for (i = 0; i < tagtabsize; i++) {
  873.       if (!strcmp(tok_str, tagtab[i].s)) goto done;
  874.    }
  875.    i = tagtabsize++;
  876.    if (i >= DATABASE_MAX_BASE_CALLS)
  877.       errexit("Too many call tags -- must recompile with larger value of DATABASE_MAX_BASE_CALLS");
  878.    strcpy(tagtab[i].s, tok_str);
  879.    tagtab[i].def = 0;
  880.  
  881.    done:
  882.    if (def) {
  883.       if (tagtab[i].def) errexit("Multiple definition of a call tag");
  884.       tagtab[i].def = 1;
  885.    }
  886.    return(i);
  887. }
  888.  
  889.  
  890. static void get_tok(void)
  891. {
  892.    get_tok_or_eof();
  893.    if (eof) errexit("Unexpected end of file");
  894. }
  895.  
  896.  
  897. static int get_num(char s[])
  898. {
  899.    get_tok();
  900.    if ((tok_kind != tok_number)) errexit(s);
  901.    return(tok_value);
  902. }
  903.  
  904.  
  905. static int dfmsearch(void)
  906. {
  907.    int i;
  908.    int rrr = 0;
  909.  
  910.    get_tok();
  911.    if (tok_kind != tok_lbkt)
  912.       errexit("Missing left bracket in defmod list");
  913.  
  914.    get_tok();
  915.    if (tok_kind != tok_rbkt) {
  916.       while (1) {
  917.          if ((tok_kind != tok_symbol))
  918.             errexit("Improper defmod key");
  919.  
  920.          if ((i = search(defmodtab)) < 0) errexit("Unknown defmod key");
  921.          rrr |= (1 << i);
  922.  
  923.          get_tok();
  924.          if (tok_kind == tok_rbkt) break;
  925.       }
  926.    }
  927.  
  928.    return(rrr);
  929. }
  930.  
  931.  
  932.  
  933.  
  934. static void write_halfword(int n)
  935. {
  936.    fputc((n>>8) & 0xFF, outfile);
  937.    fputc((n) & 0xFF, outfile);
  938.    filecount += 2;
  939. }
  940.  
  941.  
  942.  
  943. static void write_fullword(int n)
  944. {
  945.    fputc((n>>24) & 0xFF, outfile);
  946.    fputc((n>>16) & 0xFF, outfile);
  947.    fputc((n>>8) & 0xFF, outfile);
  948.    fputc((n) & 0xFF, outfile);
  949.    filecount += 4;
  950. }
  951.  
  952.  
  953.  
  954. static void write_callarray(int num, int doing_matrix)
  955. {
  956.    int count;
  957.  
  958.    if (tok_kind != tok_lbkt)
  959.       errexit("Missing left bracket in callarray list");
  960.  
  961.    for (count=0; ; count++) {
  962.       int dat = 0;
  963.       int p = 0;
  964.       stability stab = stb_none;
  965.  
  966.       get_tok();
  967.       if (tok_kind == tok_rbkt) break;
  968.       else if (tok_kind == tok_number && tok_value == 0)
  969.          write_halfword(0);
  970.       else if (tok_kind == tok_symbol) {
  971.          if (letcount > 1) {
  972.             if      (tok_str[0] == 'Z' || tok_str[0] == 'z') { stab = stb_z; p++; }
  973.             else if (tok_str[0] == 'A' || tok_str[0] == 'a') { stab = stb_a; p++; }
  974.             else if (tok_str[0] == 'C' || tok_str[0] == 'c') { stab = stb_c; p++; }
  975.          }
  976.  
  977.          if (letcount-p == 2) {
  978.             if (tok_str[p] == 'L' || tok_str[p] == 'l') dat = 4;
  979.             else if (tok_str[p] == 'M' || tok_str[p] == 'm') dat = 2;
  980.             else if (tok_str[p] == 'R' || tok_str[p] == 'r') dat = 1;
  981.             else errexit("Improper callarray specifier");
  982.          }
  983.          else if (letcount-p != 1)
  984.             errexit("Improper callarray specifier");
  985.  
  986.          if (doing_matrix) {
  987.             dat = (dat << 12) | (tok_value << 7);
  988.          }
  989.          else {
  990.             dat = (dat * DBROLL_BIT) | (tok_value << 4) | (((unsigned int) stab) * DBSTAB_BIT);
  991.          }
  992.  
  993.          /* We now have roll indicator and position, need to get direction. */
  994.          switch (tok_str[char_ct-1]) {
  995.             case 'N': case 'n': dat |= 010; break;
  996.             case 'E': case 'e': dat |= 001; break;
  997.             case 'S': case 's': dat |= 012; break;
  998.             case 'W': case 'w': dat |= 003; break;
  999.             default:
  1000.                errexit("Improper callarray direction specifier");
  1001.          }
  1002.  
  1003.          if (doing_matrix) {
  1004.             dat &= ~0x7C;
  1005.             dat |= (get_num("Improper y coordinate") & 0x1F) << 2;
  1006.          }
  1007.  
  1008.          write_halfword(dat);
  1009.       }
  1010.       else
  1011.          errexit("Improper callarray element");
  1012.    }
  1013.  
  1014.    if (count < num) errexit("Callarray list is too short for this call");
  1015.    else if (count > num) errexit("Callarray list is too long for this call");
  1016. }
  1017.  
  1018.  
  1019. static void write_call_header(calldef_schema schema)
  1020. {
  1021.    int i, j;
  1022.  
  1023.    i = call_namelen;
  1024.    write_halfword(0x2000 | call_tag);
  1025.    write_halfword(call_level);
  1026.    write_fullword(call_flags);
  1027.    write_halfword((i << 8) | (int)schema);
  1028.    for (j = 1; j <= (i >> 1); j++)
  1029.       write_halfword((((int)(call_name[2*j-2])) << 8) | (int)(call_name[2*j-1]));
  1030.    if (i&1)
  1031.       write_halfword(((int)(call_name[i-1])) << 8);
  1032.  
  1033.    callcount++;
  1034. }
  1035.  
  1036.  
  1037. static void write_conc_stuff(calldef_schema schema)
  1038. {
  1039.    int defin, minn, defout, mout;
  1040.  
  1041.    write_call_header(schema);
  1042.  
  1043.    /* Write two level 2 concdefine groups. */
  1044.  
  1045.    get_tok();
  1046.    if ((tok_kind != tok_symbol)) errexit("Improper conc symbol");
  1047.    defin = tagsearch(0);
  1048.  
  1049.    minn = dfmsearch();
  1050.  
  1051.    get_tok();
  1052.    if ((tok_kind != tok_symbol)) errexit("Improper conc symbol");
  1053.    defout = tagsearch(0);
  1054.  
  1055.    mout = dfmsearch();
  1056.  
  1057.    write_halfword(0x4000 | defin);
  1058.    write_fullword(minn);
  1059.    write_halfword(0x4000 | defout);
  1060.    write_fullword(mout);
  1061. }
  1062.  
  1063.  
  1064. static void write_seq_stuff(void)
  1065. {
  1066.    int deff, mods;
  1067.  
  1068.    get_tok();
  1069.    if ((tok_kind != tok_symbol)) errexit("Improper seq symbol");
  1070.    deff = tagsearch(0);
  1071.  
  1072.    mods = dfmsearch();
  1073.  
  1074.    write_halfword(0x4000 | deff);
  1075.    write_fullword(mods);
  1076. }
  1077.  
  1078.  
  1079. static void write_level_3_group(int predbit)
  1080. {
  1081.    write_halfword(0x6000 | predbit | callarray_flags1 | callarray_flags2);
  1082.    write_halfword(call_startsetup | (call_qualifier << 8));
  1083.    if (callarray_flags1 & CAF__CONCEND) {
  1084.       write_halfword(call_endsetup_in | (restrstate << 8));
  1085.       write_halfword(call_endsetup_out);
  1086.    }
  1087.    else {
  1088.       write_halfword(call_endsetup | (restrstate << 8));
  1089.    }
  1090. }
  1091.  
  1092.  
  1093. static void write_array_def(void)
  1094. {
  1095.    int i, iii, jjj;
  1096.  
  1097.    write_call_header(schema_by_array);
  1098.  
  1099.    /* Write a level 2 array define group. */
  1100.    write_halfword(0x4000);
  1101. def2:
  1102.    restrstate = 0;
  1103.    callarray_flags2 = 0;
  1104.    call_qualifier = 0;
  1105.  
  1106.    get_tok();
  1107.    if ((tok_kind != tok_symbol)) errexit("Improper starting setup");
  1108.    if ((call_startsetup = search(sstab)) < 0) errexit("Unknown start setup");
  1109.  
  1110.    get_tok();
  1111.    if ((tok_kind != tok_symbol)) errexit("Improper ending setup");
  1112.    if ((call_endsetup = search(estab)) < 0) errexit("Unknown ending setup");
  1113.  
  1114.    /* Should actually look for anomalous concentric and do it specially */
  1115.  
  1116.    while (1) {
  1117.       get_tok();
  1118.       if ((tok_kind != tok_symbol)) errexit("Missing indicator");
  1119.  
  1120.       if (!strcmp(tok_str, "array")) {
  1121.          write_level_3_group(0);             /* Pred flag off. */
  1122.          get_tok();
  1123.          write_callarray(begin_sizes[call_startsetup], 0);
  1124.          get_tok_or_eof();
  1125.          break;
  1126.       }
  1127.       else if (!strcmp(tok_str, "preds")) {
  1128.          write_level_3_group(CAF__PREDS);        /* Pred flag on. */
  1129.          get_tok();
  1130.          if (tok_kind != tok_string) errexit("Missing string");
  1131.          iii = char_ct;
  1132.          write_halfword(iii);
  1133.          for (jjj = 1; jjj <= (iii >> 1); jjj++)
  1134.             write_halfword((((int)(tok_str[2*jjj-2])) << 8) | ((int)(tok_str[2*jjj-1])));
  1135.          if (iii&1)
  1136.             write_halfword(((int)(tok_str[iii-1])) << 8);
  1137.  
  1138.          while (1) {
  1139.             get_tok_or_eof();
  1140.             if (eof) break;
  1141.  
  1142.             if ((tok_kind != tok_symbol)) break;    /* Will give an error. */
  1143.  
  1144.             if (!strcmp(tok_str, "if")) {
  1145.                get_tok();
  1146.                if ((tok_kind != tok_symbol)) errexit("Improper predicate");
  1147.                if ((iii = search(predtab)) < 0) errexit("Unknown predicate");
  1148.  
  1149.                /* Write a level 4 group. */
  1150.                write_halfword(0x8000);
  1151.                write_halfword(iii);
  1152.                get_tok();
  1153.                write_callarray(begin_sizes[call_startsetup], 0);
  1154.             }
  1155.             else
  1156.                break;
  1157.          }
  1158.  
  1159.          break;
  1160.       }
  1161.       else if (!strcmp(tok_str, "qualifier")) {
  1162.          get_tok();
  1163.          if ((tok_kind != tok_symbol)) errexit("Improper qualifier");
  1164.          if ((call_qualifier = search(qualtab)) < 0) errexit("Unknown qualifier");
  1165.       }
  1166.       else if (!strcmp(tok_str, "restriction")) {
  1167.          get_tok();
  1168.          if ((tok_kind != tok_symbol)) errexit("Improper restriction specifier");
  1169.  
  1170.          if (!strcmp(tok_str, "unusual")) {
  1171.             callarray_flags2 |= CAF__RESTR_UNUSUAL;
  1172.             get_tok();
  1173.             if ((tok_kind != tok_symbol)) errexit("Improper restriction specifier");
  1174.          }
  1175.          else if (!strcmp(tok_str, "forbidden")) {
  1176.             callarray_flags2 |= CAF__RESTR_FORBID;
  1177.             get_tok();
  1178.             if ((tok_kind != tok_symbol)) errexit("Improper restriction specifier");
  1179.          }
  1180.  
  1181.          if ((restrstate = search(crtab)) < 0) errexit("Unknown restriction specifier");
  1182.       }
  1183.       else if (!strcmp(tok_str, "rotate")) {
  1184.          callarray_flags1 |= CAF__ROT;
  1185.       }
  1186.       else if ((!(callarray_flags1 & CAF__CONCEND)) && (!strcmp(tok_str, "concendsetup"))) {
  1187.          if (call_endsetup != (int)s_normal_concentric)
  1188.             errexit("concendsetup with wrong end_setup");
  1189.          get_tok();
  1190.          if ((tok_kind != tok_symbol)) errexit("Improper setup specifier");
  1191.          if ((call_endsetup_in = search(estab)) < 0) errexit("Unknown setup specifier");
  1192.  
  1193.          get_tok();
  1194.          if ((tok_kind != tok_symbol)) errexit("Improper setup specifier");
  1195.          if ((call_endsetup_out = search(estab)) < 0) errexit("Unknown setup specifier");
  1196.  
  1197.          jjj = get_num("Improper second rotation");
  1198.          if (jjj != (jjj & 1))
  1199.             errexit("Improper second rotation");
  1200.          if (jjj) callarray_flags1 |= CAF__ROT_OUT;
  1201.  
  1202.          callarray_flags1 |= CAF__CONCEND;
  1203.       }
  1204.       else
  1205.          errexit("Item in illegal context while parsing setups/preds/arrays");
  1206.    }
  1207.  
  1208.    if (eof) return;
  1209.    if ((tok_kind != tok_symbol)) errexit("Missing indicator");
  1210.  
  1211.    /* If see "setup", just do another basic array. */
  1212.  
  1213.    if (!strcmp(tok_str, "setup")) {
  1214.       callarray_flags1 = 0;
  1215.       goto def2;
  1216.    }
  1217.  
  1218.    /* Otherwise, it's either an alternate definition to start another group
  1219.       of arrays, or it's the end of the whole call.
  1220.       We make use of the fact that the constants "cflag__reverse_means_mirror"
  1221.       etc. all lie in the left half of the word.  Sdinit.c checks that. */
  1222.  
  1223.    if (!strcmp(tok_str, "alternate_definition")) {
  1224.       int rrr;
  1225.       int alt_level;
  1226.       rrr = 0;
  1227.  
  1228.       get_tok();
  1229.       if (tok_kind != tok_lbkt)
  1230.          errexit("Missing left bracket in alternate_definition list");
  1231.  
  1232.       get_tok();
  1233.       if (tok_kind != tok_rbkt) {
  1234.          while (1) {
  1235.             if ((tok_kind != tok_symbol))
  1236.                errexit("Improper alternate_definition key");
  1237.  
  1238.             if ((i = search(nexttab)) < 0) errexit("Unknown alternate_definition key");
  1239.             rrr |= (1 << i);
  1240.  
  1241.             get_tok();
  1242.             if (tok_kind == tok_rbkt) break;
  1243.          }
  1244.       }
  1245.  
  1246.       get_tok();
  1247.       if ((tok_kind != tok_symbol)) errexit("Improper alternate_definition level");
  1248.       if ((alt_level = search(leveltab)) < 0) errexit("Unknown alternate_definition level");
  1249.  
  1250.       write_halfword(0x4000 | alt_level);
  1251.       write_halfword(rrr << (NEXTTAB_OFFSET-16));
  1252.    }
  1253.    else
  1254.       return;       /* Must have seen next 'call' indicator. */
  1255.  
  1256.    /* Saw "alternate_definition", ready to do another group of arrays. */
  1257.  
  1258.    get_tok();
  1259.    if ((tok_kind != tok_symbol)) errexit("Missing indicator");
  1260.  
  1261.    callarray_flags1 = 0;
  1262.    if (!strcmp(tok_str, "simple_funny")) {
  1263.       callarray_flags1 = CAF__FACING_FUNNY;
  1264.       get_tok();
  1265.       if ((tok_kind != tok_symbol)) errexit("Missing indicator");
  1266.    }
  1267.  
  1268.    if (!strcmp(tok_str, "setup")) {
  1269.       callarray_flags1 = 0;
  1270.       goto def2;
  1271.    }
  1272.    else
  1273.       errexit("Need \"setup\" indicator");
  1274. }
  1275.  
  1276.  
  1277.  
  1278. void main(void)
  1279. {
  1280.    int i, iii;
  1281.  
  1282.    infile = fopen(CALLS_FILENAME, "r");
  1283.    if (!infile) {
  1284.       printf("Can't open input file\n");
  1285.       perror(CALLS_FILENAME);
  1286.       exit(1);
  1287.    }
  1288.  
  1289.    eof = 0;
  1290.    lineno = 0;
  1291.    chars_left = 0;
  1292.    ch = ' ';
  1293.    call_namelen = 0;   /* So won't print error first time around. */
  1294.  
  1295.    if (remove(DATABASE_FILENAME)) {
  1296.       if (errno != ENOENT) {
  1297.          printf("Error deleting old output file\n");
  1298.          perror(DATABASE_FILENAME);
  1299.       }
  1300.    }
  1301.  
  1302.    outfile = fopen(DATABASE_FILENAME, "w");
  1303.    if (!outfile) {
  1304.       printf("Can't open output file\n");
  1305.       perror(DATABASE_FILENAME);
  1306.       exit(1);
  1307.    }
  1308.  
  1309.    filecount = 0;
  1310.  
  1311.    write_halfword(DATABASE_MAGIC_NUM);
  1312.    write_halfword(DATABASE_FORMAT_VERSION);
  1313.    write_halfword(0);      /* These will get fixed later, when we know what to write. */
  1314.    write_halfword(0);
  1315.  
  1316.    get_tok();
  1317.    if (strcmp(tok_str, "version")) errexit("Missing version specification");
  1318.    get_tok();
  1319.    if (tok_kind != tok_number) errexit("Improper major version specification");
  1320.    write_halfword(tok_value);
  1321.    get_tok();
  1322.    if (tok_kind != tok_number) errexit("Improper minor version specification");
  1323.    write_halfword(tok_value);
  1324.  
  1325.    callcount = 0;
  1326.    while (1) {
  1327.  
  1328.       get_tok_or_eof();
  1329.    startagain:
  1330.       if (eof) break;
  1331.  
  1332.       if ((tok_kind != tok_symbol)) errexit("Missing indicator");
  1333.  
  1334.       if (!strcmp(tok_str, "call")) {
  1335.          int count;
  1336.          int matrixflags;
  1337.          int bit;
  1338.          calldef_schema ccc;
  1339.  
  1340.          get_tok();
  1341.          if (tok_kind != tok_string) errexit("Improper call name");
  1342.  
  1343.          strcpy(call_name, tok_str);
  1344.          call_namelen = char_ct;
  1345.          call_flags = 0;
  1346.          call_tag = 0;
  1347.  
  1348.          get_tok();
  1349.          if ((tok_kind != tok_symbol)) errexit("Improper level");
  1350.          if ((call_level = search(leveltab)) < 0) errexit("Unknown level");
  1351.  
  1352.          /* Get toplevel options. */
  1353.  
  1354.          while (1) {
  1355.             get_tok();
  1356.             if ((tok_kind != tok_symbol)) errexit("Missing indicator");
  1357.             if (!strcmp(tok_str, "tag")) {
  1358.                get_tok();
  1359.                if ((tok_kind != tok_symbol)) errexit("Improper tag");
  1360.                call_tag = tagsearch(1);
  1361.             }
  1362.             else {
  1363.                iii = search(flagtab);
  1364.                if (iii < 0) break;
  1365.                call_flags |= (1 << iii);
  1366.             }
  1367.          }
  1368.  
  1369.          /* Process the actual definition.  First, check for the "simple_funny" indicator. */
  1370.  
  1371.          callarray_flags1 = 0;
  1372.  
  1373.          if (!strcmp(tok_str, "simple_funny")) {
  1374.             callarray_flags1 = CAF__FACING_FUNNY;
  1375.             get_tok();
  1376.             if ((tok_kind != tok_symbol)) errexit("Missing indicator");
  1377.          }
  1378.  
  1379.          /* Find out what kind of call it is. */
  1380.          iii = search(schematab);
  1381.  
  1382.          if (iii < 0) errexit("Can't determine call definition type");
  1383.  
  1384.          ccc = (calldef_schema) iii;
  1385.  
  1386.          if (callarray_flags1 != 0 && ccc != schema_by_array)
  1387.             errexit("Simple_funny out of place");
  1388.  
  1389.  
  1390.          switch(ccc) {
  1391.             case schema_concentric:
  1392.             case schema_cross_concentric:
  1393.             case schema_single_concentric:
  1394.             case schema_single_cross_concentric:
  1395.             case schema_maybe_single_concentric:
  1396.             case schema_concentric_diamond_line:
  1397.             case schema_concentric_6_2:
  1398.             case schema_concentric_2_6:
  1399.             case schema_conc_star:
  1400.             case schema_conc_star12:
  1401.             case schema_conc_star16:
  1402.             case schema_maybe_matrix_conc_star:
  1403.             case schema_checkpoint:
  1404.             case schema_rev_checkpoint:
  1405.             case schema_ckpt_star:
  1406.                write_conc_stuff(ccc);
  1407.                break;
  1408.             case schema_sequential:
  1409.             case schema_split_sequential:
  1410.                count = 0;
  1411.    
  1412.                write_call_header(ccc);
  1413.                /* Write a level 2 seqdefine group. */
  1414.    
  1415.                write_seq_stuff();
  1416.                while (1) {
  1417.                   get_tok_or_eof();
  1418.                   if (eof) break;
  1419.                   if ((tok_kind == tok_symbol) && (!strcmp(tok_str, "seq"))) {
  1420.                      /* Write a level 2 seqdefine group. */
  1421.                      if (++count == SEQDEF_MAX) errexit("Too many parts in sequential definition");
  1422.                      write_seq_stuff();
  1423.                   }
  1424.                   else
  1425.                      break;       /* Must have seen next 'call' indicator. */
  1426.                }
  1427.                goto startagain;
  1428.             case schema_by_array:
  1429.                write_array_def();
  1430.                goto startagain;
  1431.             case schema_nothing:
  1432.                write_call_header(ccc);
  1433.                break;
  1434.             case schema_matrix:
  1435.                matrixflags = 0;
  1436.    
  1437.                write_call_header(ccc);
  1438.                write_halfword(matrixflags >> 8);
  1439.                write_halfword(matrixflags);
  1440.                get_tok();
  1441.                write_callarray(2, 2);
  1442.                break;
  1443.             case schema_partner_matrix:
  1444.                matrixflags = 0;
  1445.    
  1446.                /* Get partner matrix call options. */
  1447.    
  1448.                while (1) {
  1449.                   get_tok();
  1450.                   if ((tok_kind != tok_symbol)) break;
  1451.                   if ((bit = search(matrixcallflagtab)) < 0) errexit("Unknown matrix call flag");
  1452.                   matrixflags |= (1 << bit);
  1453.                }
  1454.    
  1455.                if (matrixflags & MTX_USE_SELECTOR) call_flags |= cflag__requires_selector;
  1456.                write_call_header(ccc);
  1457.                write_halfword(matrixflags >> 8);
  1458.                write_halfword(matrixflags);
  1459.                write_callarray(8, 1);
  1460.                break;
  1461.             case schema_roll:
  1462.                write_call_header(ccc);
  1463.                break;
  1464.             default:
  1465.                errexit("Can't determine call definition type");
  1466.          }
  1467.       }
  1468.       else
  1469.          errexit("Item in illegal context");
  1470.    }
  1471.  
  1472.    write_halfword(0);         /* final end mark */
  1473.  
  1474.    dumbflag = 0;
  1475.  
  1476.    for (i = 0; i < tagtabsize; i++) {
  1477.       if (!tagtab[i].def) {
  1478.          if (!dumbflag++) printf("Tags not defined:\n");
  1479.          printf("   %s\n", tagtab[i].s);
  1480.       }
  1481.    }
  1482.  
  1483.    if (fclose(infile)) {
  1484.       perror("Can't close input file");
  1485.       exit(1);
  1486.    }
  1487.  
  1488.    printf("%d bytes written, %d calls\n", filecount, callcount);
  1489.  
  1490.    if (fseek(outfile, 4, SEEK_SET)) {
  1491.       perror("Can't seek output file back to beginning");
  1492.       exit(1);
  1493.    }
  1494.  
  1495.    write_halfword(callcount);
  1496.    write_halfword(tagtabsize);
  1497.  
  1498.    if (fclose(outfile)) {
  1499.       perror("Can't close output file");
  1500.       exit(1);
  1501.    }
  1502.  
  1503.    exit(0);
  1504. }
  1505.