2 /* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
3 /* All rights reserved */
5 /* Assign values to internal variables in an SSV struct. The functions in
6 * this file are called from the parse phase. */
15 /* there are several cases where we ultimately want arrays, but don't
16 * know in advance how many elements will be in the array. This could be
17 * done by building a linked list first, then malloc-ing the right size and
18 * copying everything. However, what we'll do is allocate CHUNK elements
19 * to start, and realloc if necessary. When we're done, we realloc down
20 * to the actual size */
23 /* minimum allowable height or width of page (in inches)
24 * after subtracting off the margins */
25 #define MIN_USABLE_SPACE 0.5
28 /* Macros to adjust numbers between inches to centimeters . */
30 /* Given a number in inches, use that number if in inches mode.
31 * If in centimeter mode, then use the equivalent distance in centimeters,
32 * rounded to the nearest quarter of a centimeter. */
33 #define ADJUST4UNITS(n) (Score.units == INCHES ? n : NEARESTQUARTER(n * CMPERINCH))
35 /* Given an input number, leave as is if in inches mode. If in centimeter
36 * mode, treat the number as being in centimeters, and convert to the inch
37 * equivalent distance. */
38 #define ADJUST2INCHES(n) { if (Score.units == CM) n /= CMPERINCH; }
40 static struct STAFFSET
*Curr_staffset_p
;/* staffset currently
42 static int Ss_count
; /* num of elements in Curr_staffset_p
43 * currently actually being used */
44 static int Ss_length
; /* num of elements allocated
45 * to Curr_staffset_p */
47 static struct TOP_BOT
*Curr_barstlist_p
;/* bar style list being filled in */
48 static int Barst_count
; /* number of elements in
49 * Curr_barstlist_p that are currently
50 * filled in with valid values */
51 static int Barst_length
; /* number of elements allocated to
55 RATIONAL
*list_p
; /* beam list being filled in */
56 int count
; /* elements filled in list_p */
57 int length
; /* elements allocated to list_p */
59 /* These store info from the beamstyle parameter. */
60 static struct BEAMLIST Curr_beamstyle
;
61 static struct BEAMLIST Curr_subbeamstyle
;
62 static int Subbeam_index
; /* Index into Curr_subbeamstyle where
63 * the most recent '(' was, or -1 if
64 * no pending unmatched parenthesis. */
65 static char *parmformat
= "%s parameter"; /* for error messages */
67 /* functions to do all the various checks. They check the context,
68 * range, power_of2, etc, and
69 * mark the variable as used if everything passes the checks. The first
70 * is for int variables (actually short) in SSV, the second for floats */
71 static int do_assign
P((int var
, int value
, int min
, int max
,
72 int cont
, int empty_value
, char *name
,
73 struct MAINLL
*mainll_item_p
, short *ptr2dest
));
75 static int do_fassign
P((int var
, double value
, double min
,
76 double max
, int cont
, char *name
, struct MAINLL
*mainll_item_p
,
78 static void chg_too_late
P((char *var_name
));
80 /* comparison functions to be passed to qsort */
81 static int comp_staffset
P((const void *item1_p
,
82 const void *item2_p
));
83 static int comp_barst
P((const void *item1_p
, const void *item2_p
));
84 static int is_tablature_staff
P((struct SSV
*ssv_p
));
85 static void init_beamlist
P((struct BEAMLIST
*beamlist_p
));
86 static void add2outerbeam
P((RATIONAL value
));
89 /* assign a value to an SSV variable having a domain of short,
90 * after doing any appropriate checks */
93 assign_int(var
, value
, mainll_item_p
)
95 int var
; /* SSV index of which variable to set */
96 int value
; /* what to set it to */
97 struct MAINLL
*mainll_item_p
; /* where to store SSV info in main list */
100 /* all of these things except font can only go
101 * into score/staff sorts of things,
102 * not head/foot. If we are in a head/foot, the MAINLL will be null */
103 if (Context
== C_MUSIC
|| Context
== C_GRIDS
|| Context
== C_HEADSHAPES
104 || (mainll_item_p
== 0 && var
!= SIZE
)) {
105 yyerror("trying to set parameter value in wrong context");
110 if (mainll_item_p
!= (struct MAINLL
*) 0) {
111 debug(4, "assign_int file=%s line=%d var=%d t value=%d",
112 mainll_item_p
->inputfile
, mainll_item_p
->inputlineno
, var
, value
);
115 /* handle each variable appropriately */
120 if ( Context
& C_BLOCKHEAD
) {
121 (void) rangecheck(value
, MINSIZE
, MAXSIZE
, "size");
123 /* special case -- size can be set in block,
124 * and there we don't put in SSV struct,
125 * just save its value in Curr_size */
129 (void) do_assign(var
, value
, MINSIZE
, MAXSIZE
,
130 C_SCORE
| C_STAFF
, NO
, "size",
131 mainll_item_p
, &(mainll_item_p
->u
.ssv_p
->size
));
132 /* set in Score, in case we get an "all" */
133 if (Context
== C_SCORE
) {
134 Score
.size
= (short) value
;
140 if (do_assign(var
, value
, MINSIZE
, MAXSIZE
, C_SCORE
| C_STAFF
,
141 NO
, "lyricssize", mainll_item_p
,
142 &(mainll_item_p
->u
.ssv_p
->lyricssize
) )
144 /* save values for any lyrics that come later */
145 if (Context
== C_SCORE
) {
146 /* set in case we get some "all" lyrics */
147 Score
.lyricssize
= (short) value
;
149 setlyrsize(mainll_item_p
->u
.ssv_p
->staffno
, value
);
154 (void) do_assign(var
, value
, MINSIZE
, MAXSIZE
, C_SCORE
,
155 NO
, "measnumsize", mainll_item_p
,
156 &(mainll_item_p
->u
.ssv_p
->measnumsize
) );
160 (void) do_assign(var
, value
, MINSYLPOSITION
, MAXSYLPOSITION
,
162 NO
, "sylposition", mainll_item_p
,
163 &(mainll_item_p
->u
.ssv_p
->sylposition
) );
167 (void) do_assign(var
, value
, MINOCTAVE
, MAXOCTAVE
,
168 C_SSV
, NO
, "defoct", mainll_item_p
,
169 &(mainll_item_p
->u
.ssv_p
->defoct
) );
170 if (Context
!= C_SCORE
&&
171 is_tab_staff(mainll_item_p
->u
.ssv_p
->staffno
)
173 yyerror("defoct not allowed on tablature staff");
176 asgnssv(mainll_item_p
->u
.ssv_p
);
181 if (do_assign(var
, value
, MINSTAFFS
, MAXSTAFFS
, C_SCORE
, NO
,
182 "staffs", mainll_item_p
,
183 &(mainll_item_p
->u
.ssv_p
->staffs
) )
186 /* can only change number of staffs if not in the
187 * middle of doing music data. We exclaimed about
188 * the user error in end_prev_context(), so if this
189 * occurs, we just skip over the code in the "if"
191 if (List_of_staffs_p
== (struct MAINLL
*) 0) {
192 /* NUMSTAFFS is a special case,
193 * in that several other
194 * items have to do error checking
195 * based on the number of staffs specified,
196 * so we have to set it immediately rather than
197 * waiting for the whole SSV struct
199 Score
.staffs
= (short) value
;
201 /* if the number of scores changes,
203 * pending "til" clauses on STUFF */
204 chk4dangling_til_clauses(
205 "change in number of staffs");
207 /* any pedal information is no long valid */
214 /* actually yacc already guarantees will be in range */
215 (void) do_assign(var
, value
, 0, 1, C_SCORE
|C_STAFF
|C_VOICE
, NO
,
216 "visible", mainll_item_p
,
217 &(mainll_item_p
->u
.ssv_p
->visible
) );
221 /* actually yacc already guarantees will be in range */
222 (void) do_assign(var
, value
, 0, 1, C_SCORE
, NO
,
223 "measnum", mainll_item_p
,
224 &(mainll_item_p
->u
.ssv_p
->measnum
) );
228 /* actually yacc already guarantees will be in range */
229 (void) do_assign(var
, value
, 0, 1, C_SCORE
| C_STAFF
, NO
,
230 "cancelkey", mainll_item_p
,
231 &(mainll_item_p
->u
.ssv_p
->cancelkey
) );
235 (void) do_assign(var
, value
, MINMINSTSEP
, MAXSEPVAL
,
236 C_SCORE
| C_STAFF
, NO
, "staffsep", mainll_item_p
,
237 &(mainll_item_p
->u
.ssv_p
->minstsep
) );
241 (void) do_assign(var
, value
, MINMINSCSEP
, MAXSEPVAL
,
242 C_SCORE
, NO
, "min scoresep", mainll_item_p
,
243 &(mainll_item_p
->u
.ssv_p
->minscsep
) );
247 (void) do_assign(var
, value
, MINMAXSCSEP
, MAXSEPVAL
,
248 C_SCORE
, NO
, "max scoresep", mainll_item_p
,
249 &(mainll_item_p
->u
.ssv_p
->maxscsep
) );
253 (void) do_assign(var
, value
, MINCHORDDIST
, MAXCHORDDIST
,
254 C_SCORE
| C_STAFF
, NO
, "chorddist",
256 &(mainll_item_p
->u
.ssv_p
->chorddist
) );
260 (void) do_assign(var
, value
, MINDIST
, MAXDIST
,
261 C_SCORE
| C_STAFF
, NO
, "dist", mainll_item_p
,
262 &(mainll_item_p
->u
.ssv_p
->dist
) );
266 (void) do_assign(var
, value
, MINDYNDIST
, MAXDYNDIST
,
267 C_SCORE
| C_STAFF
, NO
, "dyndist",
269 &(mainll_item_p
->u
.ssv_p
->dyndist
) );
273 (void) do_assign(var
,value
, MINSTPAD
, MAXSTPAD
,
274 C_SCORE
| C_STAFF
, NO
,
275 "staffpad", mainll_item_p
,
276 &(mainll_item_p
->u
.ssv_p
->staffpad
) );
280 (void) do_assign(var
, value
, MINMINSCPAD
, MAXPADVAL
,
281 C_SCORE
, NO
, "min scorepad", mainll_item_p
,
282 &(mainll_item_p
->u
.ssv_p
->minscpad
) );
286 (void) do_assign(var
, value
, MINMAXSCPAD
, MAXPADVAL
,
287 C_SCORE
, NO
, "max scorepad", mainll_item_p
,
288 &(mainll_item_p
->u
.ssv_p
->maxscpad
) );
292 chg_too_late("division");
293 (void) do_assign(var
, value
, MINDIVISION
, MAXDIVISION
,
294 C_SCORE
, NO
, "division", mainll_item_p
,
295 &(mainll_item_p
->u
.ssv_p
->division
) );
296 /* division values that aren't divisible by 2 and 3 are
297 * unlikely to be right and are likely to lead to rational
298 * overflow in MIDI code, so give warning */
299 if ((value
% 6) != 0) {
300 l_warning(Curr_filename
, yylineno
,
301 "dubious division value");
307 (void) do_assign(var
, value
, MINRELEASE
, MAXRELEASE
,
308 C_SCORE
| C_STAFF
| C_VOICE
, NO
,
309 "release", mainll_item_p
,
310 &(mainll_item_p
->u
.ssv_p
->release
) );
314 chg_too_late("panelsperpage");
315 (void) do_assign(var
, value
, MINPANELSPERPAGE
, MAXPANELSPERPAGE
,
317 "panelsperpage", mainll_item_p
,
318 &(mainll_item_p
->u
.ssv_p
->panelsperpage
) );
322 (void) do_assign(var
, value
,
323 MINRESTCOMBINE
, MAXRESTCOMBINE
,
324 C_SCORE
, NORESTCOMBINE
,
325 "restcombine", mainll_item_p
,
326 &(mainll_item_p
->u
.ssv_p
->restcombine
) );
330 chg_too_late("firstpage");
331 (void) do_assign(var
, value
, MINFIRSTPAGE
, MAXFIRSTPAGE
,
333 "firstpage", mainll_item_p
,
334 &(mainll_item_p
->u
.ssv_p
->firstpage
) );
338 (void) do_assign(var
, value
, MINGRIDFRET
, MAXGRIDFRET
,
339 C_SCORE
| C_STAFF
, NOGRIDFRET
,
340 "gridfret", mainll_item_p
,
341 &(mainll_item_p
->u
.ssv_p
->gridfret
) );
345 (void) do_assign(var
, value
, 0, 1,
346 C_SCORE
| C_STAFF
, NO
,
347 "gridswhereused", mainll_item_p
,
348 &(mainll_item_p
->u
.ssv_p
->gridswhereused
) );
352 (void) do_assign(var
, value
, 0, 1, C_SCORE
, NO
,
353 "gridsatend", mainll_item_p
,
354 &(mainll_item_p
->u
.ssv_p
->gridsatend
) );
358 /* actually yacc already guarantees will be in range */
359 (void) do_assign(var
, value
, 0, 1,
360 C_SCORE
| C_STAFF
| C_VOICE
, NO
,
361 "tabwhitebox", mainll_item_p
,
362 &(mainll_item_p
->u
.ssv_p
->tabwhitebox
) );
366 /* This only makes sense on 1-line staffs, but we decided
367 * it is best to silently accept it elsewhere. For example,
368 * you might want to set it in score context to apply to all
369 * the 1-line staffs there are. */
370 (void) do_assign(var
, value
, 0, 1,
371 C_SCORE
| C_STAFF
| C_VOICE
, NO
,
372 "ontheline", mainll_item_p
,
373 &(mainll_item_p
->u
.ssv_p
->ontheline
) );
377 (void) do_assign(var
, value
, 0, 1,
378 C_SCORE
, NO
, "warn", mainll_item_p
,
379 &(mainll_item_p
->u
.ssv_p
->warn
) );
383 (void) do_assign(var
, value
, 0, 1,
384 C_SCORE
| C_STAFF
, NO
, "numbermrpt", mainll_item_p
,
385 &(mainll_item_p
->u
.ssv_p
->numbermrpt
) );
389 (void) do_assign(var
, value
, 0, 1,
390 C_SCORE
| C_STAFF
, NO
, "printmultnum", mainll_item_p
,
391 &(mainll_item_p
->u
.ssv_p
->printmultnum
) );
395 (void) do_assign(var
, value
, 0, 1,
396 C_SCORE
| C_STAFF
, NO
, "restsymmult", mainll_item_p
,
397 &(mainll_item_p
->u
.ssv_p
->restsymmult
) );
401 pfatal("bad parameter name\n");
407 /* do all the error checks for an int variable. If it passes all checks,
408 * set the used flag to YES and return YES. If something fails, return NO. */
409 /* Checks are: must be within range, must be in valid context, the MAINLL
410 * struct passed must be non-NULL, and if the pow2 flag is YES, the value
411 * must be a power of two. Also give warning if field already used. Getting
412 * a null pointer is not fatal--it can happen if user tried to do something
413 * in the wrong context. */
416 do_assign(var
, value
, min
, max
, cont
, empty_value
, name
, mainll_item_p
, ptr2dest
)
418 int var
; /* which variable to set */
419 int value
; /* what to set it to */
420 int min
; /* minimum valid value */
421 int max
; /* maximum valid value */
422 int cont
; /* valid context(s) (bitmap) */
423 int empty_value
; /* if NO, value must be strictly within the
424 * given min/max. If != NO, it is an extra
425 * value, outside the min/max range, that
426 * is legal, and indicates
427 * user set the value to empty */
428 char *name
; /* of internal variable, for error messages */
429 struct MAINLL
*mainll_item_p
; /* which structure to set it in */
430 short *ptr2dest
; /* the address of the variable to be set */
433 char fullname
[50]; /* name + " parameter" */
434 if (mainll_item_p
== (struct MAINLL
*) 0) {
435 l_yyerror(Curr_filename
, yylineno
, "wrong context for setting %s",
439 (void) sprintf(fullname
, parmformat
, name
);
440 if (contextcheck(cont
, fullname
) == NO
) {
444 /* exclaim if already set in this SSV */
445 used_check(mainll_item_p
, var
, name
);
448 if (empty_value
!= NO
&& erangecheck(value
, min
, max
, empty_value
, name
) == NO
) {
451 else if (empty_value
== NO
&& rangecheck(value
, min
, max
, name
) == NO
) {
454 /* passed all the checks-- assign and mark it as used */
455 mainll_item_p
->u
.ssv_p
->used
[var
] = YES
;
456 *ptr2dest
= (short) value
;
461 /* do assignment of float type SSV variables */
464 assign_float(var
, value
, mainll_item_p
)
466 int var
; /* which variable to set */
467 double value
; /* what to set it to */
468 struct MAINLL
*mainll_item_p
; /* where to store info */
472 /* all of these things can only go into score/staff sorts of things,
473 * not head/foot. If we are in a head/foot, the MAINLL will be null */
474 if (mainll_item_p
== 0 || Context
== C_MUSIC
) {
475 yyerror("trying to set parameter value in wrong context");
479 debug(4, "assign_float file=%s line=%d var=%d value=%f",
480 mainll_item_p
->inputfile
, mainll_item_p
->inputlineno
, var
, value
);
482 /* some changes are only allowed before music data is entered */
483 if (Got_some_data
== YES
) {
489 chg_too_late( "margin");
492 chg_too_late( "scale");
496 chg_too_late( "page size");
503 /* if pagesize minus the margins get too small (or even worse,
504 * negative), we better complain */
512 chkmargin(Score
.topmargin
, Score
.botmargin
, Score
.leftmargin
,
522 if (do_fassign(var
, (double) value
,
523 (double) ADJUST4UNITS(MINVMARGIN
),
524 (double) ADJUST4UNITS(Score
.pageheight
- MIN_USABLE_SPACE
),
525 C_SCORE
, "topmargin", mainll_item_p
,
526 &(mainll_item_p
->u
.ssv_p
->topmargin
) )
528 ADJUST2INCHES(mainll_item_p
->u
.ssv_p
->topmargin
)
530 /* put in score so we can check for margins exceeding paper size */
531 Score
.topmargin
= mainll_item_p
->u
.ssv_p
->topmargin
;
536 if (do_fassign(var
, (double) value
,
537 (double) ADJUST4UNITS(MINVMARGIN
),
538 (double) ADJUST4UNITS(Score
.pageheight
- MIN_USABLE_SPACE
),
539 C_SCORE
, "bottommargin", mainll_item_p
,
540 &(mainll_item_p
->u
.ssv_p
->botmargin
) )
542 ADJUST2INCHES(mainll_item_p
->u
.ssv_p
->botmargin
)
543 Score
.botmargin
= mainll_item_p
->u
.ssv_p
->botmargin
;
548 if (do_fassign(var
, (double) value
,
549 (double) ADJUST4UNITS(MINHMARGIN
),
550 (double) ADJUST4UNITS(Score
.pagewidth
- MIN_USABLE_SPACE
),
551 C_SCORE
, "leftmargin", mainll_item_p
,
552 &(mainll_item_p
->u
.ssv_p
->leftmargin
) )
554 ADJUST2INCHES(mainll_item_p
->u
.ssv_p
->leftmargin
)
555 Score
.leftmargin
= mainll_item_p
->u
.ssv_p
->leftmargin
;
560 if (do_fassign(var
, (double) value
,
561 (double) ADJUST4UNITS(MINHMARGIN
),
562 (double) ADJUST4UNITS(Score
.pagewidth
- MIN_USABLE_SPACE
),
563 C_SCORE
, "rightmargin", mainll_item_p
,
564 &(mainll_item_p
->u
.ssv_p
->rightmargin
) )
566 ADJUST2INCHES(mainll_item_p
->u
.ssv_p
->rightmargin
)
567 Score
.rightmargin
= mainll_item_p
->u
.ssv_p
->rightmargin
;
572 (void) do_fassign(var
, (double) value
,
573 (double) MINPACKFACT
, (double) MAXPACKFACT
,
574 C_SCORE
, "packfact", mainll_item_p
,
575 &(mainll_item_p
->u
.ssv_p
->packfact
) );
579 (void) do_fassign(var
, (double) value
,
580 (double) MINPACKEXP
, (double) MAXPACKEXP
,
581 C_SCORE
, "packexp", mainll_item_p
,
582 &(mainll_item_p
->u
.ssv_p
->packexp
) );
586 (void) do_fassign(var
, (double) value
,
587 (double) MINSCALE
, (double) MAXSCALE
,
588 C_SCORE
, "scale factor", mainll_item_p
,
589 &(mainll_item_p
->u
.ssv_p
->scale_factor
) );
593 (void) do_fassign(var
, (double) value
,
594 (double) MINSTFSCALE
, (double) MAXSTFSCALE
,
595 C_SCORE
| C_STAFF
, "staffscale", mainll_item_p
,
596 &(mainll_item_p
->u
.ssv_p
->staffscale
) );
600 (void) do_fassign(var
, (double) value
,
601 (double) MINGRIDSCALE
, (double) MAXGRIDSCALE
,
602 C_SCORE
| C_STAFF
, "gridscale", mainll_item_p
,
603 &(mainll_item_p
->u
.ssv_p
->gridscale
) );
607 if (do_fassign(var
, (double) value
,
608 (double) ADJUST4UNITS(MINPAGEHEIGHT
),
609 (double) ADJUST4UNITS(MAXPAGEHEIGHT
),
610 C_SCORE
, "pageheight", mainll_item_p
,
611 &(mainll_item_p
->u
.ssv_p
->pageheight
) )
613 ADJUST2INCHES(mainll_item_p
->u
.ssv_p
->pageheight
)
614 Score
.pageheight
= mainll_item_p
->u
.ssv_p
->pageheight
;
619 if (do_fassign(var
, (double) value
,
620 (double) ADJUST4UNITS(MINPAGEWIDTH
),
621 (double) ADJUST4UNITS(MAXPAGEWIDTH
),
622 C_SCORE
, "pagewidth", mainll_item_p
,
623 &(mainll_item_p
->u
.ssv_p
->pagewidth
) )
625 ADJUST2INCHES(mainll_item_p
->u
.ssv_p
->pagewidth
)
626 Score
.pagewidth
= mainll_item_p
->u
.ssv_p
->pagewidth
;
631 (void) do_fassign(var
, (double) value
,
632 (double) MINLYRICSALIGN
,
633 (double) MAXLYRICSALIGN
,
634 C_SCORE
| C_STAFF
, "lyricsalign", mainll_item_p
,
635 &(mainll_item_p
->u
.ssv_p
->lyricsalign
) );
639 (void) do_fassign(var
, (double) value
,
642 C_SCORE
| C_STAFF
| C_VOICE
, "pad", mainll_item_p
,
643 &(mainll_item_p
->u
.ssv_p
->pad
) );
644 /* What the user calls zero means notes can
645 * just touch, but internally we want zero to mean the
646 * default of 1 point of padding, so adjust. */
647 mainll_item_p
->u
.ssv_p
->pad
-= POINT
;
651 (void) do_fassign(var
, (double) value
,
654 C_SSV
, "stemlen", mainll_item_p
,
655 &(mainll_item_p
->u
.ssv_p
->stemlen
) );
660 (void) do_fassign(var
, (double) value
,
661 (double) MINSTEMSHORTEN
,
662 (double) MAXSTEMSHORTEN
,
663 C_SSV
, "stemshorten", mainll_item_p
,
664 &(mainll_item_p
->u
.ssv_p
->stemshorten
) );
668 pfatal("invalid float parameter");
675 /* Handle parameters that have two float numbers as their value */
678 assign_2floats(var
, value1
, value2
, mainll_item_p
)
680 int var
; /* which variable to set */
681 double value1
, value2
; /* which values to set */
682 struct MAINLL
*mainll_item_p
; /* where to store info */
688 /* First float value is the factor */
689 if (do_fassign(var
, (double) value1
,
690 (double) MINBEAMFACT
,
691 (double) MAXBEAMFACT
,
692 C_SCORE
| C_STAFF
| C_VOICE
, "beamslope factor",
694 &(mainll_item_p
->u
.ssv_p
->beamfact
) ) == YES
) {
696 /* Fool do_fassign into thinking we haven't set the used
697 * flag yet. This is a little kludgy... */
698 mainll_item_p
->u
.ssv_p
->used
[var
] = NO
;
700 /* Second value is the max angle in degrees */
701 (void) do_fassign(var
, value2
,
704 C_SCORE
| C_STAFF
| C_VOICE
,
705 "beamslope maximum slope angle",
707 &(mainll_item_p
->u
.ssv_p
->beammax
) );
712 pfatal("bad var value for assign_2floats %d", var
);
719 /* If user tries to change something that can only be changed before music
720 * data is entered, but music has been entered, print error message. */
723 chg_too_late(var_name
)
728 if (Got_some_data
== YES
) {
729 l_yyerror(Curr_filename
, yylineno
,
730 "Can't change %s after music or block data has been entered",
736 /* Do error checks for a float variable. If it passes all checks,
737 * set the used flag to YES and return YES.
738 * If something fails check, return NO.
739 * Checks are: value within range, valid context, and MAINLL struct pointer
741 * Also give warning if field already used.
745 do_fassign(var
, value
, min
, max
, cont
, name
, mainll_item_p
, ptr2dest
)
747 int var
; /* which variable to set */
748 double value
; /* what to set it to */
749 double min
; /* minimum valid value */
750 double max
; /* maximum valid value */
751 int cont
; /* valid context(s) (bitmap) */
752 char *name
; /* for error messages */
753 struct MAINLL
*mainll_item_p
; /* which structure to set it in */
754 float *ptr2dest
; /* pointer to the float variable
758 char fullname
[50]; /* name + " parameter" */
760 if (mainll_item_p
== (struct MAINLL
*) 0) {
761 l_yyerror(Curr_filename
, yylineno
, "wrong context for setting %s", name
);
764 (void) sprintf(fullname
, parmformat
, name
);
765 if ( contextcheck(cont
, fullname
) == NO
) {
769 /* exclaim if already set in this SSV */
770 used_check(mainll_item_p
, var
, name
);
773 if (frangecheck(value
, min
, max
, name
) == NO
) {
777 /* passed all the checks-- assign and mark it as used */
778 mainll_item_p
->u
.ssv_p
->used
[var
] = YES
;
785 /* assign value to vscheme variable */
788 assign_vscheme(numvoices
, vtype
, mainll_item_p
)
790 int numvoices
; /* 1, 2, or 3 */
791 int vtype
; /* V_1, V_2FREESTEM, or V_2OPSTEM. For 3 voice
792 * case, this is still one of the V_2* values,
793 * and in that case it specifies whether
794 * the stems are free or opposing,
795 * with the numvoices indicating the 3 */
796 struct MAINLL
*mainll_item_p
; /* where to assign it */
799 /* check for proper context */
800 if (contextcheck(C_SCORE
| C_STAFF
, "vscheme parameter") == NO
) {
804 /* exclaim if already set in this SSV */
805 used_check(mainll_item_p
, VSCHEME
, "vscheme");
807 if (rangecheck(numvoices
, MINVOICES
, MAXVOICES
, "vscheme value") == NO
) {
811 /* check for valid combination */
812 if ( (numvoices
== 1) && (vtype
!= V_1
) ) {
813 yyerror("can't have 'o' or 'f' qualifier when vscheme=1");
817 if ( (numvoices
== 2 || numvoices
== 3) && (vtype
== V_1
) ) {
818 yyerror("'o' or 'f' qualifier required when vscheme=2 or vscheme=3");
822 /* The 3 voice things are really just the 2 voice ones, but a third
823 * voice is allowed. They get passed in as V_2*, so fix that */
824 if (numvoices
== 3) {
825 if (vtype
== V_2FREESTEM
) {
828 else if (vtype
== V_2OPSTEM
) {
833 /* set variable to requested value */
834 mainll_item_p
->u
.ssv_p
->vscheme
= (short) vtype
;
835 mainll_item_p
->u
.ssv_p
->used
[VSCHEME
] = YES
;
837 asgnssv(mainll_item_p
->u
.ssv_p
);
841 /* assign value to voicecombine parameter */
844 assign_vcombine(qualifier
, mainll_p
)
847 struct MAINLL
* mainll_p
;
850 short listed
[MAXVOICES
+ 1]; /* If user mentioned the voice */
851 struct RANGELIST
* curr_p
; /* walk through list of voices */
853 int offset
; /* index into vcombine array */
856 if (contextcheck(C_SCORE
| C_STAFF
, "voicecombine parameter") == NO
) {
859 used_check(mainll_p
, VCOMBINE
, "voicecombine");
861 /* Clear list of voices mentioned by user,
862 * and initialize list of voices to combine to none. */
863 for (v
= 1; v
<= MAXVOICES
; v
++) {
865 mainll_p
->u
.ssv_p
->vcombine
[v
-1] = 0;
868 /* We start filling in at beginning of vcombine array */
871 /* Add the specified voices in input order to SSV vcombine array */
872 for (curr_p
= Vnorange_p
; curr_p
!= 0; curr_p
= curr_p
->next
) {
873 /* add voices into voice combine list after error checks */
874 for (v
= curr_p
->begin
; v
<= curr_p
->end
; v
++) {
875 if (listed
[v
] == YES
) {
876 l_yyerror(Curr_filename
, yylineno
,
877 "voice %d specified more than once", v
);
879 if (offset
>= MAXVOICES
) {
880 /* The only way this can happen is if user
881 * specified at least one voice more than once,
882 * and we would have already reported that
883 * above, so no need to print another error.
884 * But we must not attempt to write beyond
885 * end of vcombine array, so jump out of loop.
889 mainll_p
->u
.ssv_p
->vcombine
[offset
++] = v
;
895 mainll_p
->u
.ssv_p
->vcombinequal
= (short) qualifier
;
896 mainll_p
->u
.ssv_p
->used
[VCOMBINE
] = YES
;
897 /* Since voicecombine is relatively rare, we set a flag if it is
898 * ever used. If flag is not set, all the voicecombine placement
899 * code can be skipped entirely. If turning off or only a
900 * single voice is specified, that doesn't really count as being used.
908 /* assign key signature */
911 assign_key(num
, acc
, is_minor
, mainll_item_p
)
913 int num
; /* number of sharps or flats */
914 int acc
; /* # or & for sharp or flat */
915 int is_minor
; /* YES or NO */
916 struct MAINLL
*mainll_item_p
; /* where to assign */
919 if (contextcheck( C_SCORE
| C_STAFF
, "key parameter") == NO
) {
923 /* exclaim if already set in this SSV */
924 used_check(mainll_item_p
, SHARPS
, "key");
926 /* error check. Must be no more than 7 flats or sharps, and can only
927 * be set in score or staff contexts */
928 if (rangecheck(num
, 0, MAXSHARPS
,
929 "number of flats or sharps in key signature") == NO
) {
933 /* looks okay, so make assignment */
934 /* NOTE: num of flats == negative number of sharps */
935 mainll_item_p
->u
.ssv_p
->sharps
= num
* (acc
== '#' ?
1 : -1);
936 mainll_item_p
->u
.ssv_p
->used
[SHARPS
] = YES
;
937 mainll_item_p
->u
.ssv_p
->is_minor
= (short) is_minor
;
939 asgnssv(mainll_item_p
->u
.ssv_p
);
943 /* Assign a string to an SSV variable. It just assigns the pointer for labels,
944 * so temporary strings should be copied before being passed.
945 * For NOTEHEADS, it parses the string and saves the numeric internal numbers.
949 assign_string(var
, string
, mainll_item_p
)
951 int var
; /* LABEL, LABEL2, or NOTEHEADS */
952 char *string
; /* the string to assign */
953 struct MAINLL
*mainll_item_p
; /* where to assign it */
956 int n
; /* note shape index */
957 char namebuff
[100]; /* For note shape names. Builtin names are
958 * fairly short, but user could define longer
959 * ones. We figure 100 should be plenty,
960 * and ufatal if they try to go longer. */
961 int nameleng
; /* strlen of a name shape name */
962 int context
; /* which context to check */
963 char *error_msg
; /* what to print in error message */
965 if (var
== NOTEHEADS
) {
967 error_msg
= "noteheads parameter";
970 context
= C_SCORE
| C_STAFF
;
971 error_msg
= (var
== LABEL ?
"label parameter"
972 : "label2 parameter");
975 if (contextcheck(context
, error_msg
) == YES
) {
977 /* get string into proper internal format */
978 (void) fix_string(string
, string
[0], string
[1],
979 Curr_filename
, yylineno
);
984 used_check(mainll_item_p
, var
, "label");
985 mainll_item_p
->u
.ssv_p
->label
= string
;
989 used_check(mainll_item_p
, var
, "label2");
990 mainll_item_p
->u
.ssv_p
->label2
= string
;
994 if (is_tab_staff(mainll_item_p
->u
.ssv_p
->staffno
) == YES
995 && strcmp(string
+2, "allx") != 0
996 && strcmp(string
+2, "norm") != 0) {
997 warning("noteheads parameter ignored on tablature staffs (unless allx or norm)");
1000 /* skip past font/size */
1002 /* split into tokens */
1003 for (n
= 0; n
< 7; n
++) {
1004 /* skip past white space */
1005 while ( isspace(*string
) ) {
1009 if ( *string
== '\0') {
1013 nameleng
= strcspn(string
, " \t\r\n");
1014 if (nameleng
> sizeof(namebuff
) - 1) {
1015 ufatal("note head name too long");
1017 strncpy(namebuff
, string
, nameleng
);
1018 namebuff
[nameleng
] = '\0';
1019 if ((mainll_item_p
->u
.ssv_p
->noteheads
[n
] =
1020 get_shape_num(namebuff
))
1022 l_yyerror(Curr_filename
, yylineno
,
1023 "'%s' is not a valid headshape name",
1029 /* copy same shape for all 7 */
1030 for ( ; n
< 7; n
++) {
1031 mainll_item_p
->u
.ssv_p
->noteheads
[n
] =
1032 mainll_item_p
->u
.ssv_p
->noteheads
[0];
1036 /* Skip past trailing white space, and make sure we got
1037 * right number of tokens. */
1038 while ( isspace(*string
) ) {
1041 if (n
!= 7 || *string
!= '\0') {
1042 yyerror("wrong number of notehead names: expecting either 1 or 7");
1046 pfatal("invalid string variable type");
1051 mainll_item_p
->u
.ssv_p
->used
[var
] = YES
;
1056 /* make a copy of a string and return pointer to it,
1057 * or return NULL if string was NULL. The incoming string is a regular C-style
1058 * string. The returned string is 2 bytes longer, with the font in the first
1059 * byte, size in the second byte, and the copy of the original string in the
1063 copy_string(string
, font
, size
)
1065 char *string
; /* make a copy of this string */
1066 int font
; /* use this font */
1067 int size
; /* use this point size */
1070 char *copy
; /* pointer to new copy of string */
1073 if (string
== (char *) 0) {
1077 /* need 2 extra bytes at beginning for font and size,
1078 * and 1 at end for '\0' */
1079 MALLOCA(char, copy
, strlen(string
) + 3);
1081 /* fill in font and size in first 2 bytes */
1082 *copy
= (char) font
;
1083 *(copy
+ 1) = (char) size
;
1085 /* copy the string and return pointer to copy */
1086 (void) strcpy(copy
+ 2, string
);
1091 /* Assign time signature in SSV.
1092 * Derives the effective numerator/denominator and the RATIONAL time value
1093 * from the timerep, and fills them in the SSV. If there are alternating
1094 * time signatures, that will be for the first of them, and a pointer
1095 * to the remaining signature(s) will be returned via next_alternation_p.
1096 * If there are additive time signatures, the effective num/den will
1097 * be based on the largest denominator.
1101 assign_timesig(mainll_item_p
, visibility
, next_alternation_p
)
1103 struct MAINLL
*mainll_item_p
; /* SSV to assign time signature in */
1104 int visibility
; /* YES, NO, or EACHMEAS */
1105 char **next_alternation_p
; /* If this time signature includes alternating
1106 * time signatures, as in 3/4 4/4,
1107 * this will be filled in with a pointer to
1108 * where the next alternate time signature
1109 * begins in the timerep. If there are no
1110 * alternating time signatures, it will be
1111 * filled by a null pointer. */
1114 struct SSV
*ssv_p
; /* mainll_item_p->u.ssv_p */
1115 RATIONAL curr_value
; /* There may be compound time
1116 * signatures, and each of those
1117 * may have multiple numerator
1118 * components, so this is used for
1119 * getting value of one fraction */
1120 int biggest_denominator
; /* for calculating effective
1121 * numerator and denominator */
1122 char *t
; /* to walk through timerep */
1125 if (contextcheck(C_SCORE
, "time parameter") == NO
) {
1129 /* exclaim if already set in this SSV */
1130 used_check(mainll_item_p
, TIME
, "time signature");
1132 ssv_p
= mainll_item_p
->u
.ssv_p
;
1134 ssv_p
->timevis
= visibility
;
1138 biggest_denominator
= 0;
1139 *next_alternation_p
= 0;
1141 for (t
= ssv_p
->timerep
; *t
!= TSR_END
; t
++) {
1142 if (*t
== TSR_CUT
) {
1146 else if (*t
== TSR_COMMON
) {
1150 else if (*t
== TSR_SLASH
) {
1151 curr_value
.d
= *++t
;
1153 else if (*t
== TSR_ALTERNATING
) {
1154 *next_alternation_p
= ++t
;
1157 else if (*t
== TSR_ADD
) {
1164 biggest_denominator
= MAX(biggest_denominator
, curr_value
.d
);
1166 ssv_p
->time
= radd(ssv_p
->time
, curr_value
);
1170 /* If there were mixed denominators, use the biggest for the
1171 * purpose of effective numerator and denominator */
1172 if (biggest_denominator
> ssv_p
->time
.d
) {
1173 ssv_p
->timenum
= ssv_p
->time
.n
* (biggest_denominator
/ ssv_p
->time
.d
);
1176 ssv_p
->timenum
= ssv_p
->time
.n
;
1178 ssv_p
->timeden
= biggest_denominator
;
1180 /* mark time as used */
1181 mainll_item_p
->u
.ssv_p
->used
[TIME
] = YES
;
1183 /* We have to set this for real immediately, since beamstyle and
1184 * other things may need to have it set */
1185 asgnssv(mainll_item_p
->u
.ssv_p
);
1187 if (mainll_item_p
->u
.ssv_p
->used
[BEAMSTLIST
] == YES
) {
1188 l_warning(Curr_filename
, yylineno
,
1189 "changing time signature clears beamstyle");
1190 /* have to actually clear it here, because otherwise it
1191 * would still get assigned in ssv.c because beamstyle is
1192 * done after the code for time signature */
1193 mainll_item_p
->u
.ssv_p
->used
[BEAMSTLIST
] = NO
;
1194 mainll_item_p
->u
.ssv_p
->nbeam
= 0;
1195 if (mainll_item_p
->u
.ssv_p
->beamstlist
!= (RATIONAL
*) 0) {
1196 FREE(mainll_item_p
->u
.ssv_p
->beamstlist
);
1202 /* assign a font variable (FONT, LYRICSFONT, FONTFAMILY, LYRICSFAMILY) */
1205 set_font(var
, value
, mainll_item_p
)
1207 int var
; /* which variable to set */
1208 int value
; /* which font to set it too */
1209 struct MAINLL
*mainll_item_p
; /* where to assign it in main list */
1212 char *varname
; /* name of variable, for error messages */
1213 char fullname
[50]; /* varname + " parameter" */
1216 /* determine the name of the variable, for error messages */
1222 varname
= "lyricsfont";
1225 varname
= "measnumfont";
1228 varname
= "fontfamily";
1231 varname
= "lyricsfontfamily";
1234 varname
= "measnumfontfamily";
1237 pfatal("bad font variable");
1241 (void) sprintf(fullname
, parmformat
, varname
);
1243 /* if being called from SSV, exclaim if already set */
1244 if ((Context
& C_SSV
) != 0) {
1245 used_check(mainll_item_p
, var
, varname
);
1253 if (Context
& C_BLOCKHEAD
) {
1254 /* Special case. In block, we just
1255 * keep track of the current font */
1258 else if (contextcheck(C_SCORE
| C_STAFF
, fullname
) == YES
) {
1259 mainll_item_p
->u
.ssv_p
->font
= (short) value
;
1268 Curr_family
= value
;
1270 if (Context
& C_BLOCKHEAD
) {
1271 /* Special case. In block, we just
1272 * keep track of the current font */
1275 else if (contextcheck(C_SCORE
| C_STAFF
, fullname
) == YES
) {
1276 mainll_item_p
->u
.ssv_p
->fontfamily
= (short) value
;
1285 if (contextcheck(C_SCORE
| C_STAFF
, fullname
) == YES
) {
1286 mainll_item_p
->u
.ssv_p
->lyricsfont
= (short) value
;
1288 /* assign immediately in case there is a following
1289 * font family change that needs to read it */
1290 mainll_item_p
->u
.ssv_p
->used
[var
] = YES
;
1291 asgnssv(mainll_item_p
->u
.ssv_p
);
1292 setlyrfont(mainll_item_p
->u
.ssv_p
->staffno
, value
);
1303 if (contextcheck(C_SCORE
| C_STAFF
, fullname
) == YES
) {
1304 mainll_item_p
->u
.ssv_p
->lyricsfamily
= (short) value
;
1305 /* assign immediately, so we can reset all
1306 * lyrics info for this staff */
1307 mainll_item_p
->u
.ssv_p
->used
[var
] = YES
;
1308 asgnssv(mainll_item_p
->u
.ssv_p
);
1310 setlyrfont(mainll_item_p
->u
.ssv_p
->staffno
,
1311 svpath(mainll_item_p
->u
.ssv_p
->staffno
,
1312 LYRICSFONT
)->lyricsfont
);
1323 if (contextcheck(C_SCORE
, fullname
) == YES
) {
1324 mainll_item_p
->u
.ssv_p
->measnumfont
= (short) value
;
1332 if (contextcheck(C_SCORE
, fullname
) == YES
) {
1333 mainll_item_p
->u
.ssv_p
->measnumfamily
= (short) value
;
1341 pfatal("unknown font variable");
1345 mainll_item_p
->u
.ssv_p
->used
[var
] = YES
;
1349 /* set number of stafflines and whether or not to print clef. Number of
1350 * lines must be 1 or 5, unless it's a tablature staff,
1351 * in which case it can be anything from MINTABLINES to MAXTABLINES.
1352 * In any case, it must be set before any music data. */
1355 asgn_stafflines(numlines
, printclef
, mainll_item_p
)
1357 int numlines
; /* 1 or 5 for normal, or MINTABLINES to MAXTABLINES for tablature */
1358 int printclef
; /* SS_* */
1359 struct MAINLL
*mainll_item_p
; /* where to set value */
1362 int is_tab
; /* YES if is tablature staff */
1366 if (mainll_item_p
== (struct MAINLL
*) 0) {
1367 /* must be in here due to some user syntax error */
1371 is_tab
= is_tablature_staff(mainll_item_p
->u
.ssv_p
);
1372 if (is_tab
== YES
) {
1373 if (contextcheck(C_STAFF
, "stafflines=tab") == NO
) {
1378 if (contextcheck(C_SCORE
| C_STAFF
, "stafflines parameter") == NO
) {
1383 /* exclaim if already set in this SSV */
1384 used_check(mainll_item_p
, STAFFLINES
, "stafflines");
1386 if (is_tab
== YES
) {
1387 /* is a tablature staff */
1388 (void) rangecheck(numlines
, MINTABLINES
, MAXTABLINES
,
1389 "number of tab strings specified");
1392 /* not a tablature staff */
1393 if (numlines
!= 5 && numlines
!= 1) {
1394 yyerror("stafflines must be 1 or 5");
1399 mainll_item_p
->u
.ssv_p
->stafflines
= (short) numlines
;
1401 /* single line never has clef except the drum clef,
1402 * so if user didn't explictly set 'n' we do it for them */
1403 if (numlines
== 1 && printclef
== SS_NORMAL
) {
1406 mainll_item_p
->u
.ssv_p
->printclef
= (short) printclef
;
1407 mainll_item_p
->u
.ssv_p
->used
[STAFFLINES
] = YES
;
1409 /* index into Staff array is staffno - 1 */
1410 staff_index
= mainll_item_p
->u
.ssv_p
->staffno
- 1;
1412 /* need to do extra consistency check for tablature staffs */
1413 if (is_tab
== YES
) {
1415 if (staff_index
== 0) {
1416 yyerror("staff 1 can't be a tablature staff");
1419 if (is_tablature_staff( &(Staff
[staff_index
- 1]) ) == YES
1420 || (staff_index
< MAXSTAFFS
- 1 &&
1421 is_tablature_staff( &(Staff
[staff_index
+ 1]) )
1423 yyerror("can't have two consecutive tablature staffs");
1425 if (svpath(mainll_item_p
->u
.ssv_p
->staffno
- 1,
1426 STAFFLINES
)->stafflines
!= 5) {
1427 yyerror("staff before a tablature staff must be a 5-line staff");
1432 /* if trying to establish a non-5-line non-tablature staff,
1433 * and it's not the bottom staff, and the staff below is a
1434 * tablature staff, that's a no-no */
1435 if (numlines
!= 5 && staff_index
< MAXSTAFFS
- 1 &&
1436 is_tablature_staff( &(Staff
[staff_index
+ 1]) )
1438 yyerror("staff before a tablature staff must be a 5-line staff");
1442 /* assign, so we can do error checking on tablature staffs
1443 * for future SSVs that we process */
1444 asgnssv(mainll_item_p
->u
.ssv_p
);
1448 /* When the input contains a rangelist, we need to allocate some space for
1449 * the information. Allocate an array of length CHUNK. Set the Ss_count to start
1450 * filling in element 0, and mark the Ss_length as CHUNK. As we add elements,
1451 * Ss_count will be incremented, and the array size enlarged if it overflows.
1458 CALLOC(STAFFSET
, Curr_staffset_p
, CHUNK
);
1465 /* add information about one staffset, at the current offset in the list,
1466 * re-allocating additional space if necessary */
1469 add_staffset(start
, end
, label1
, label2
)
1471 int start
, end
; /* of the range */
1472 char *label1
, *label2
; /* malloc-ed copies of labels for the range, or NULL */
1475 /* Murphey's Law insurance */
1476 if (Curr_staffset_p
== (struct STAFFSET
*) 0) {
1477 pfatal("NULL staffset");
1480 /* swap if backwards */
1489 /* if we guessed too small, need to make a bigger array */
1490 if (Ss_count
>= Ss_length
) {
1492 REALLOC(STAFFSET
, Curr_staffset_p
, Ss_length
);
1495 /* fill in values */
1496 Curr_staffset_p
[Ss_count
].topstaff
= (short) start
;
1497 Curr_staffset_p
[Ss_count
].botstaff
= (short) end
;
1498 if (label1
!= (char *) 0) {
1499 (void) fix_string(label1
, label1
[0], label1
[1],
1500 Curr_filename
, yylineno
);
1502 Curr_staffset_p
[Ss_count
].label
= label1
;
1503 if (label2
!= (char *) 0) {
1504 (void) fix_string(label2
, label2
[0], label2
[1],
1505 Curr_filename
, yylineno
);
1507 Curr_staffset_p
[Ss_count
].label2
= label2
;
1509 /* one more item in list */
1514 /* When we have collected an entire list of ranges, assign the
1515 * list to the appropriate place in the SSV struct.
1516 * (Using "set" instead of "assign" for function name because some
1517 * people's compilers are too stupid to tell the difference in names
1518 * after 8 characters, which would clash with another function name) */
1521 set_staffset(var
, mainll_item_p
)
1523 int var
; /* which rangelist to set */
1524 struct MAINLL
*mainll_item_p
; /* which struct to assign it in */
1527 register int i
; /* index through ranges */
1528 short okay
= NO
; /* if passed all overlap checks */
1531 /* can only do this in score context */
1532 if (contextcheck(C_SCORE
, "list of staff ranges") == NO
) {
1536 /* first we need to make sure no ranges are out of range */
1537 /* go through the list of ranges */
1538 for (i
= 0; i
< Ss_count
; i
++) {
1540 /* range check. Make sure it is within number of staffs that
1541 * user specified. Since when we assign the user-specified
1542 * number, we make sure that is within MAXSTAFFS, it will
1543 * be within the absolute maximum as well.
1545 if (rangecheck(Curr_staffset_p
[i
].botstaff
, 1, Score
.staffs
,
1546 "brace/bracket staff number") == NO
) {
1551 /* if explicitly empty, can free space */
1552 if (Ss_count
== 0) {
1553 FREE(Curr_staffset_p
);
1556 /* we probably have too much space allocated, shed the rest */
1557 REALLOC(STAFFSET
, Curr_staffset_p
, Ss_count
);
1559 /* sort lowest to highest */
1560 qsort( (char *) Curr_staffset_p
, (unsigned int) Ss_count
,
1561 sizeof(struct STAFFSET
), comp_staffset
);
1564 if (mainll_item_p
== (struct MAINLL
*) 0) {
1565 pfatal("NULL SSV for staffset");
1568 /* now assign to appropriate variable */
1572 mainll_item_p
->u
.ssv_p
->bracelist
= (Ss_count
== 0 ?
1573 (struct STAFFSET
*) 0 : Curr_staffset_p
);
1574 mainll_item_p
->u
.ssv_p
->nbrace
= (short) Ss_count
;
1575 okay
= brac_check(Curr_staffset_p
, Ss_count
,
1576 Score
.bracklist
, Score
.nbrack
);
1577 used_check(mainll_item_p
, var
, "brace");
1581 mainll_item_p
->u
.ssv_p
->bracklist
= (Ss_count
== 0 ?
1582 (struct STAFFSET
*) 0 : Curr_staffset_p
);
1583 mainll_item_p
->u
.ssv_p
->nbrack
= (short) Ss_count
;
1584 okay
= brac_check(Score
.bracelist
, Score
.nbrace
,
1585 Curr_staffset_p
, Ss_count
);
1586 used_check(mainll_item_p
, var
, "bracket");
1590 pfatal("unknown staffset type");
1595 mainll_item_p
->u
.ssv_p
->used
[var
] = YES
;
1597 /* assign now, so we can check for overlap */
1598 asgnssv(mainll_item_p
->u
.ssv_p
);
1601 /* the list has been attached to its permanent place, so
1602 * reset the temporary pointer to an empty list */
1603 Curr_staffset_p
= (struct STAFFSET
*) 0;
1608 /* compare 2 STAFFSETs for sorting using qsort */
1611 comp_staffset(item1_p
, item2_p
)
1614 const void *item1_p
; /* the two items to compare */
1615 const void *item2_p
;
1617 char *item1_p
; /* the two items to compare */
1625 top1
= ((struct STAFFSET
*)item1_p
)->topstaff
;
1626 top2
= ((struct STAFFSET
*)item2_p
)->topstaff
;
1627 bot1
= ((struct STAFFSET
*)item1_p
)->botstaff
;
1628 bot2
= ((struct STAFFSET
*)item2_p
)->botstaff
;
1634 else if (top1
> top2
) {
1638 else if (bot1
< bot2
) {
1642 else if (bot1
> bot2
) {
1652 /* allocate an array of TOP_BOT structs for building up a list of bar style
1653 * information (which staffs to bar together) */
1659 CALLOC(TOP_BOT
, Curr_barstlist_p
, CHUNK
);
1661 /* initialize used and allocated lengths */
1663 Barst_length
= CHUNK
;
1667 /* add a pair of staff numbers to bar style list */
1670 add_barst(start
, end
)
1672 int start
; /* first staff to bar together */
1673 int end
; /* last staff to bar together */
1676 if (Curr_barstlist_p
== (struct TOP_BOT
*) 0) {
1677 pfatal("NULL barstlist");
1680 /* swap if backwards */
1689 /* if we guessed too small, make a bigger array */
1690 if (Barst_count
>= Barst_length
) {
1692 Barst_length
+= CHUNK
;
1694 REALLOC(TOP_BOT
, Curr_barstlist_p
, Barst_length
);
1697 Curr_barstlist_p
[Barst_count
].top
= (short) start
;
1698 Curr_barstlist_p
[Barst_count
].bottom
= (short) end
;
1700 /* one more item on list */
1705 /* When we have collected an entire list of ranges, assign the
1706 * list to the appropriate place in the SSV struct */
1709 set_barstlist(mainll_item_p
)
1711 struct MAINLL
*mainll_item_p
; /* which struct to assign it in */
1714 register int i
, s
; /* index for ranges and staffs */
1715 short mentioned
[MAXSTAFFS
+ 1]; /* mark whether each staff occurs in
1716 * this list somewhere. Element 0 is
1720 if (contextcheck(C_SCORE
, "barstyle parameter") == NO
) {
1724 /* exclaim if alrady set in this SSV */
1725 used_check(mainll_item_p
, BARSTLIST
, "barstyle");
1727 /* first we need to make sure no ranges overlap or are out of range */
1729 /* initialize that we haven't seen anything yet */
1730 for (s
= 1; s
< MAXSTAFFS
+ 1; s
++) {
1734 /* go through the list of ranges */
1735 for (i
= 0; i
< Barst_count
; i
++) {
1738 if (rangecheck(Curr_barstlist_p
[i
].bottom
, 1, Score
.staffs
,
1739 "barstyle staff number") == NO
) {
1743 /* fill in each in the range as having been mentioned.
1744 * If already mentioned, we have a problem */
1745 for (s
= Curr_barstlist_p
[i
].top
;
1746 s
<= Curr_barstlist_p
[i
].bottom
; s
++) {
1748 if (mentioned
[s
] == YES
) {
1749 yyerror("overlapping range in bar list");
1758 /* if explicitly empty, free space */
1759 if (Barst_count
== 0) {
1760 FREE(Curr_barstlist_p
);
1764 /* we probably have too much space allocated, shed the rest */
1765 REALLOC(TOP_BOT
, Curr_barstlist_p
, Barst_count
);
1767 /* sort lowest to highest */
1768 qsort ( (char *) Curr_barstlist_p
, (unsigned int) Barst_count
,
1769 sizeof(struct TOP_BOT
), comp_barst
);
1772 if (mainll_item_p
== (struct MAINLL
*) 0) {
1773 pfatal("NULL SSV for barstlist");
1777 mainll_item_p
->u
.ssv_p
->nbarst
= (short) Barst_count
;
1778 if (Barst_count
> 0) {
1779 mainll_item_p
->u
.ssv_p
->barstlist
= Curr_barstlist_p
;
1782 mainll_item_p
->u
.ssv_p
->used
[BARSTLIST
] = YES
;
1784 /* now that list has been assigned to its proper place,
1785 * re-initialize pointer to null to prepare for another list */
1786 Curr_barstlist_p
= (struct TOP_BOT
*) 0;
1791 /* compare 2 barslist items for sorting using qsort */
1794 comp_barst(item1_p
, item2_p
)
1797 const void *item1_p
; /* the two items to compare */
1798 const void *item2_p
;
1800 char *item1_p
; /* the two items to compare */
1805 if ( ((struct TOP_BOT
*)item1_p
)->top
1806 < ((struct TOP_BOT
*)item2_p
)->top
) {
1810 else if ( ((struct TOP_BOT
*)item1_p
)->top
1811 > ((struct TOP_BOT
*)item2_p
)->top
) {
1816 /* actually this should never occur */
1822 /* Initialize and allocate space for beamstyle information */
1828 init_beamlist(&Curr_beamstyle
);
1829 init_beamlist(&Curr_subbeamstyle
);
1834 /* Initalize a BEAMLIST struct.
1835 * Allocate CHUNK entries, and mark that 0 of them are currently used.
1839 init_beamlist(beamlist_p
)
1841 struct BEAMLIST
*beamlist_p
;
1844 MALLOCA(RATIONAL
, beamlist_p
->list_p
, CHUNK
);
1845 beamlist_p
->count
= 0;
1846 beamlist_p
->length
= CHUNK
;
1850 /* This function is called at the parenthesis to begin a sub-beam grouping.
1851 * It saves the current index into the subbeam list. At the ending parenthesis,
1852 * we add up add the subbeam list time values since that saved index.
1859 if (Subbeam_index
>= 0) {
1860 yyerror("Nested sub-beam groups not allowed");
1863 Subbeam_index
= Curr_subbeamstyle
.count
;
1871 /* Do error checks */
1872 if (Subbeam_index
< 0) {
1873 yyerror("Missing '(' for sub-beam grouping");
1876 if (Subbeam_index
>= Curr_subbeamstyle
.count
- 1) {
1877 warning("sub-beam grouping needs at least two values");
1880 /* Count up all the time values of subbeams that make up the
1881 * single outer beam. */
1882 for (tot_time
= Zero
; Subbeam_index
< Curr_subbeamstyle
.count
;
1884 tot_time
= radd(tot_time
, Curr_subbeamstyle
.list_p
[Subbeam_index
]);
1886 add2outerbeam(tot_time
);
1891 /* Add an entry to the current beam list */
1896 RATIONAL value
; /* what to add to beam list */
1899 /* If we guessed too small, make a bigger array */
1900 if (Curr_subbeamstyle
.count
>= Curr_subbeamstyle
.length
) {
1901 Curr_subbeamstyle
.length
+= CHUNK
;
1902 REALLOCA(RATIONAL
, Curr_subbeamstyle
.list_p
, Curr_subbeamstyle
.length
);
1905 Curr_subbeamstyle
.list_p
[Curr_subbeamstyle
.count
] = value
;
1906 (Curr_subbeamstyle
.count
)++;
1908 /* If not in a subbeam grouping, goes into Curr_beamstyle too */
1909 if (Subbeam_index
< 0) {
1910 add2outerbeam(value
);
1915 /* Add entry to time values for the outermost beam. In the case of subbeaming,
1916 * the value will be the sum of the subbeams values; otherwise it will be
1917 * the same as that in the subbeam list.
1921 add2outerbeam(value
)
1926 /* If we guessed too small, make a bigger array */
1927 if (Curr_beamstyle
.count
>= Curr_beamstyle
.length
) {
1928 Curr_beamstyle
.length
+= CHUNK
;
1929 REALLOCA(RATIONAL
, Curr_beamstyle
.list_p
, Curr_beamstyle
.length
);
1931 Curr_beamstyle
.list_p
[Curr_beamstyle
.count
] = value
;
1932 (Curr_beamstyle
.count
)++;
1936 /* Assign current beam list to SSV structure in main list */
1939 set_beamlist(mainll_item_p
)
1941 struct MAINLL
*mainll_item_p
; /* where to attach list */
1944 if (contextcheck(C_SSV
, "beamstyle parameter") == NO
) {
1948 /* exclaim if already set in this SSV */
1949 used_check(mainll_item_p
, BEAMSTLIST
, "beamstyle");
1951 /* Shed any extra allocated space */
1952 if (Curr_beamstyle
.count
== 0) {
1953 FREE(Curr_beamstyle
.list_p
);
1954 Curr_beamstyle
.list_p
= 0;
1956 else if (Curr_beamstyle
.count
< Curr_beamstyle
.length
) {
1957 REALLOCA(RATIONAL
, Curr_beamstyle
.list_p
, Curr_beamstyle
.count
);
1959 if (Curr_subbeamstyle
.count
== 0) {
1960 FREE(Curr_subbeamstyle
.list_p
);
1961 Curr_subbeamstyle
.list_p
= 0;
1963 else if (Curr_subbeamstyle
.count
< Curr_subbeamstyle
.length
) {
1964 REALLOCA(RATIONAL
, Curr_subbeamstyle
.list_p
, Curr_subbeamstyle
.count
);
1967 if (mainll_item_p
== (struct MAINLL
*) 0) {
1968 pfatal("NULL SSV for beamlist");
1971 if (Context
!= C_SCORE
&& is_tab_staff(mainll_item_p
->u
.ssv_p
->staffno
)
1973 yyerror("beamstyle not allowed on tablature staff");
1977 /* attach to the SSV struct and mark as used */
1978 mainll_item_p
->u
.ssv_p
->beamstlist
= Curr_beamstyle
.list_p
;
1979 mainll_item_p
->u
.ssv_p
->subbeamstlist
= Curr_subbeamstyle
.list_p
;
1980 mainll_item_p
->u
.ssv_p
->nbeam
= (short) Curr_beamstyle
.count
;
1981 mainll_item_p
->u
.ssv_p
->nsubbeam
= (short) Curr_subbeamstyle
.count
;
1982 mainll_item_p
->u
.ssv_p
->used
[BEAMSTLIST
] = YES
;
1984 if (Curr_beamstyle
.count
> 0) {
1985 /* make sure time adds up to exactly a measure */
1986 RATIONAL tot_time
; /* sum of times in beamstyle list */
1991 for (n
= 0; n
< Curr_beamstyle
.count
; n
++) {
1992 tot_time
= radd(tot_time
, Curr_beamstyle
.list_p
[n
]);
1995 if (NE(tot_time
, Score
.time
)) {
1996 yyerror("beam list does not add up to a measure");
2000 /* Mark temporary lists as invalid */
2001 Curr_beamstyle
.list_p
= 0;
2002 Curr_subbeamstyle
.list_p
= 0;
2004 asgnssv(mainll_item_p
->u
.ssv_p
);
2009 assign_unit(unittype
, mainll_p
)
2012 struct MAINLL
*mainll_p
;
2015 if (contextcheck(C_SCORE
, "units parameter") == NO
) {
2019 mainll_p
->u
.ssv_p
->units
= unittype
;
2020 Score
.units
= unittype
;
2024 /* return YES if given SSV refers to a tablature staff, NO if not.
2025 * This function is different than the is_tab_staff() function in that
2026 * this takes an ssv_p and thus can be used on a user's SSV, whereas
2027 * is_tab_staff takes a staff number and only works on the SSVs in
2028 * the Staff array. */
2031 is_tablature_staff(ssv_p
)
2036 return (ssv_p
->strinfo
!= (struct STRINGINFO
*) 0 ? YES
: NO
);
2040 /* add information about a string for a tablature staff. This gets put
2041 * in a malloc-ed strinfo array off the ssv_p struct */
2044 add_tab_string_info(letter
, accidental
, nticks
, octave
, ssv_p
)
2046 int letter
; /* pitch letter 'a' to 'g' */
2047 int accidental
; /* #, &, or \0, others are blocked by parser */
2048 int nticks
; /* how many tick marks, to distinguish multiple
2049 * strings with the same pitch/accidental */
2050 int octave
; /* for MIDI and translating to tabnote staff */
2051 struct SSV
*ssv_p
; /* add the info to this struct */
2054 int index
; /* which strinfo array element we are filling in */
2058 /* increment number of stafflines. This gets done for real later
2059 * by asgn_stafflines(), but we do it here to keep track of how
2060 * many structs we have malloc-ed from previous calls to this function
2061 * for previous strings */
2062 (ssv_p
->stafflines
)++;
2064 /* first get space. If first one to add, malloc, otherwise realloc */
2065 if (ssv_p
->stafflines
== 1) {
2066 MALLOC(STRINGINFO
, ssv_p
->strinfo
, ssv_p
->stafflines
);
2069 REALLOC(STRINGINFO
, ssv_p
->strinfo
, ssv_p
->stafflines
);
2072 /* get the index of the new element we are adding */
2073 index
= ssv_p
->stafflines
- 1;
2075 /* fill in the data */
2076 ssv_p
->strinfo
[index
].letter
= (char) letter
;
2077 ssv_p
->strinfo
[index
].accidental
= (char) accidental
;
2078 ssv_p
->strinfo
[index
].nticks
= (short) nticks
;
2079 ssv_p
->strinfo
[index
].octave
2080 = (short) (octave
== USE_DFLT_OCTAVE ? TABDEFOCT
: octave
);
2082 /* check for duplicate strings */
2083 for (i
= 0; i
< index
; i
++) {
2084 if (ssv_p
->strinfo
[i
].letter
== letter
2085 && ssv_p
->strinfo
[i
].accidental
== accidental
2086 && ssv_p
->strinfo
[i
].nticks
== nticks
) {
2087 l_yyerror(Curr_filename
, yylineno
,
2088 "duplicate %c%c%sstring, use ' marks to distinguish",
2089 letter
, accidental ? accidental
: ' ',
2090 accidental ?
" " : "");
2096 /* Save user-specified measure number in given bar struct,
2097 * after verifying it is valid (that is it > 0).
2101 set_mnum(bar_p
, mnum
)
2107 char *old_reh_string
;
2111 l_yyerror(Curr_filename
, yylineno
, "mnum must be > 0");
2113 else if (bar_p
->mnum
!= 0) {
2114 l_yyerror(Curr_filename
, yylineno
,
2115 "mnum cannot be specified more than once per bar");
2118 Meas_num
= bar_p
->mnum
= mnum
;
2119 /* If user had already specified " reh mnum" on this bar,
2120 * we would already have made a reh_string for it, so we
2121 * have to undo that. It would be nicer to delay the call
2122 * to set_reh_string till after we've set mnum, but by then
2123 * we would have lost the information we needed unless we
2124 * added a bunch more code, so even though this approach
2125 * isn't ideal, it's easiest. This shouldn't happen very
2127 if ( (bar_p
->reh_type
== REH_MNUM
) &&
2128 (bar_p
->reh_string
!= (char *) 0) ) {
2129 old_reh_string
= bar_p
->reh_string
;
2130 (void) sprintf(num_string
, "%d", mnum
);
2131 bar_p
->reh_string
= copy_string(num_string
,
2132 (int) old_reh_string
[0],
2133 (int) old_reh_string
[1]);
2134 FREE(old_reh_string
);
2140 /* Give error if margin is too wide, If any is negative, use from Score */
2143 chkmargin(topmargin
, botmargin
, leftmargin
, rightmargin
)
2151 if (topmargin
< 0.0) {
2152 topmargin
= Score
.topmargin
;
2154 if (botmargin
< 0.0) {
2155 botmargin
= Score
.botmargin
;
2157 if (leftmargin
< 0.0) {
2158 leftmargin
= Score
.leftmargin
;
2160 if (rightmargin
< 0.0) {
2161 rightmargin
= Score
.rightmargin
;
2163 if (((Score
.pageheight
- topmargin
- botmargin
) < MIN_USABLE_SPACE
)
2164 || ((Score
.pagewidth
- leftmargin
- rightmargin
)
2165 < MIN_USABLE_SPACE
)) {
2166 yyerror("page size minus margins is too small");
2171 /* function to let other files get to the ADJUST2INCHES macro */
2174 adjust2inches(value
)
2179 ADJUST2INCHES(value
);