chiark / gitweb /
Debianize new mup version
[mup] / mup / mup / map.c
1
2 /* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2006 by Arkkra Enterprises */
3 /* All rights reserved */
4
5 /* This file contains functions for mapping input to individual voices.
6  * The user can give a single line of input
7  * that gets expanded into several voices.
8  * There are two flavors of this:
9  * voice-at-a-time input and chord-at-a-time input.
10  * For the former, the GRPSYL list just gets cloned and altered as needed.
11  * For the latter, brand new GRPSYL lists are created
12  * by distributing individual notes from the user's input.
13  * For any given staff/voice, only one type of input can be used per measure.
14  * For chord-at-a-time, a given staff/voice can appear more than once
15  * within a single input line, but not on multiple input lines per measure.
16  */
17
18 #include "defines.h"
19 #include "structs.h"
20 #include "globals.h"
21
22 /* mark whether we mapped user data, only mapped implicit spaces, or nothing */
23 #define MAPPED_NOTHING  (0)
24 #define MAPPED_IMPLICIT (1)
25 #define MAPPED_EXPLICIT (2)
26
27 /* This struct tells how to map one note for chord-at-a-time input,
28  * i.e., which staff/voice combinations it should be mapped to.
29  * Each map item in input (semicolon-separated)
30  * gets saved in one of these. */
31 struct NOTEMAP {
32         struct SVRANGELIST *svlist_p;   /* staffs/voices to map this note to */
33         struct NOTEMAP *next;           /* linked list */
34 };
35
36 /* This struct gives the mapping for a particular number of notes.
37  * The set of things inside a pair of brackets gets saved in one of these. */
38 struct MAP {
39         int num_entries;                /* how many item in list */
40         struct NOTEMAP *notemap_p;      /* one entry for each note in chord */
41         struct MAP *next;               /* linked list */
42 };
43
44 /* This points to the list of maps, or to 0 if doing voice-at-a-time input */
45 static struct MAP *Map_p;
46 /* This points to where to add to the map list */
47 static struct MAP **End_map_p_p = &Map_p;
48
49 /* This is where to insert the next NOTEMAP */
50 static struct NOTEMAP **Note_p_p;
51
52 /* It is handy to be able to treat both input styles identically
53  * as much as possible. So for when input is voice-at-a-time, it can be handy
54  * to have a MAP that just points to Svrangelist_p. These two structs are
55  * used for that purpose. Since the value of Svrangelist_p changes
56  * at runtime, we have to set Sv_notemap->svlist_p each time
57  * before these are used. */
58 static struct NOTEMAP Sv_notemap = {
59         (struct SVRANGELIST *) 0, (struct NOTEMAP *) 0
60 };
61 static struct MAP Voice_at_a_time_map = {
62         1, &Sv_notemap, (struct MAP *) 0
63 };
64
65 /* Keep track of which input style was used */
66 static short Input_style[MAXSTAFFS][MAXVOICES];
67
68 static int map_groups P((void));
69 static void clean_map_data P((void));
70 static void free_maps P((struct MAP *map_p));
71 static void free_notemaps P((struct NOTEMAP *notemap_p));
72 static struct NOTEMAP *find_notemap P((int num_notes));
73 static void map1note P((struct GRPSYL *from_gs_p, int n, int staff, int voice,
74         short allocated[MAXSTAFFS][MAXVOICES]));
75 static void do_link_groups P((void));
76 static void link_a_grouplist P((int staffno, int vno, int copies));
77 static void convert_rest_space P((struct GRPSYL *grpsyl_p, int staffno, int vno));
78 static void conv_grpsyl P((struct GRPSYL *grpsyl_p, int staffno, int vno));
79 static void mult_def P((int staff, int voice));
80 \f
81
82 /* Initialize Input_style to default of IS_VOICE_INPUT */
83
84 void
85 reset_input_style()
86
87 {
88         int staff;
89         int voice;
90
91         for (staff = 0; staff < MAXSTAFFS; staff++) {
92                 for (voice = 0; voice < MAXVOICES; voice++) {
93                         Input_style[staff][voice] = IS_VOICE_INPUT;
94                 }
95         }
96 }
97 \f
98
99 /* Return the current input style for a given staff/voice */
100
101 int
102 input_style(staff, voice)
103
104 int staff;
105 int voice;
106
107 {
108         return(Input_style[staff-1][voice-1]);
109 }
110 \f
111
112 /* This is called when a '[' is encountered in input, starting a new map */
113
114 void
115 begin_map()
116
117 {
118         struct MAP *new_p;
119
120
121         /* allocate space for a new map */
122         CALLOC(MAP, new_p, 1);
123
124         /* Keep track of where to link on the first NOTEMAP */
125         Note_p_p = &(new_p->notemap_p);
126
127         /* Add to MAP list */
128         *End_map_p_p = new_p;
129
130         begin_sv_list();
131 }
132 \f
133
134 /* Save one item of a map. Items are the semicolon-separated specifications. */
135
136 void
137 map_item()
138 {
139         CALLOC(NOTEMAP, *Note_p_p, 1);
140
141         /* Save the current range */
142         (*Note_p_p)->svlist_p = Svrangelist_p;
143         ((*End_map_p_p)->num_entries)++;
144
145         /* prepare for another, if any */
146         Note_p_p = &( (*Note_p_p)->next);
147
148         begin_sv_list();
149         begin_range(PL_UNKNOWN);
150 }
151 \f
152
153 /* At the end of a map specification, this function is called to save the
154  * info about the map for later use, and prepare for another map, if any.
155  */
156
157 void
158 end_map()
159
160 {
161         /* prepare for another map, if any */
162         End_map_p_p = &( (*End_map_p_p)->next);
163
164         begin_range(Place);
165 }
166 \f
167
168 /* Map chord-at-a-time input so it looks just like voice-at-a-time input.
169  * Return YES if current measure is chord-at-a-time, and thus
170  * mapping was done, NO if current measure is voice-at-a-time.
171  */
172
173 static int
174 map_groups()
175
176 {
177         struct MAP *map_p;
178         /* Multiple notes in a chord might get mapped to a single staff/voice.
179          * In that case, after the first note for that staff/voice,
180          * we need to just add a note to the existing GRPSYL rather than
181          * allocating a new one. This keeps track of whether we have already
182          * allocated a GRPSYL for the current chord of a given staff/voice. */
183         short allocated[MAXSTAFFS][MAXVOICES];
184         /* This array tells us which staffs/voices we are mapping things to */
185         short used[MAXSTAFFS][MAXVOICES];
186         /* This array will have MAPPED_EXPLICIT
187          * in entries where we mapped actual user data.
188          * If we only mapped implicit spaces (MAPPED_IMPLICIT),
189          * we can treat things as if user didn't use the voice
190          * on this input line. */
191         short mapped_something[MAXSTAFFS][MAXVOICES];
192         /* This says if we've printed an error yet for multiply defined voice,
193          * to make sure we only print it once. */
194         short printed_mult_err[MAXSTAFFS][MAXVOICES];
195         /* This tells which numbers of notes we have maps for. */
196         short have_map[MAXHAND];
197         int s;                  /* staff number */
198         int v;                  /* voice number */
199         int n;                  /* note index */
200         struct NOTEMAP *notemap_p;      /* how to map notes to voices */
201         struct SVRANGELIST *svr_p;
202         struct RANGELIST *sr_p; /* range of staffs being defined */
203         struct RANGELIST *vr_p; /* range of vno's being defined */
204         struct GRPSYL *gs_p;
205         struct GRPSYL *g_p;
206         int errors;
207
208
209         if (Map_p == (struct MAP *) 0) {
210                 /* not chord-at-a-time mapping, so nothing to do here */
211                 return(NO);
212         }
213
214         /* remember current error count */
215         errors = Errorcount;
216
217         /* Initialize arrays. These will later tell us
218          * which GRPSYL lists we are mapping to, and whether we mapped
219          * any actual user input, or just implicit spaces. */
220         for (s = 0; s < Score.staffs; s++) {
221                 for (v = 0; v < MAXVOICES; v++) {
222                         used[s][v] = NO;
223                         mapped_something[s][v] = MAPPED_NOTHING;
224                         printed_mult_err[s][v] = NO;
225                 }
226         }
227         /* This tells for which numbers of notes we have maps */
228         for (n = 0; n < MAXHAND; n++) {
229                 have_map[n] = NO;
230         }
231
232         /* Do some error checking on the MAP list */
233         for (map_p = Map_p; map_p != (struct MAP *) 0; map_p = map_p->next) {
234
235                 if (have_map[map_p->num_entries] == YES) {
236                         l_yyerror(Curr_filename, yylineno,
237                                 "more than one map for chords with %d notes",
238                                 map_p->num_entries);
239                         continue;
240                 }
241                 else {
242                         have_map[map_p->num_entries] = YES;
243                 }
244
245                 for (notemap_p = map_p->notemap_p;
246                                 notemap_p != (struct NOTEMAP *) 0;
247                                 notemap_p = notemap_p->next) {
248                         for (svr_p = notemap_p->svlist_p;
249                                         svr_p != (struct SVRANGELIST *) 0;
250                                         svr_p = svr_p->next) {
251                             for (sr_p = svr_p->stafflist_p; sr_p != 0;
252                                                         sr_p = sr_p->next) {
253                                 for (s = sr_p->begin; s <= sr_p->end; s++) {
254
255                                         if (s > Score.staffs) {
256                                                 l_yyerror(Curr_filename,
257                                                         yylineno,
258                                                         "staff %d does not exist",
259                                                         s);
260                                                 continue;
261                                         }
262
263                                         for (vr_p = svr_p->vnolist_p; vr_p != 0;
264                                                         vr_p = vr_p->next) {
265                                             for (v = vr_p->begin;
266                                                         v <= vr_p->end; v++) {
267
268                                                 /* make sure voice exists */
269                                                 if (v > 1 && svpath(s, VSCHEME)
270                                                         ->vscheme == V_1) {
271                                                    l_yyerror(Curr_filename,
272                                                         yylineno,
273                                                         "there is no voice %d on staff %d",
274                                                         v, s);
275                                                 }
276                                                 used[s-1][v-1] = YES;
277                                                 Input_style[s-1][v-1]
278                                                         = IS_CHORD_INPUT;
279                                             }
280                                         }
281                                 }
282                             }
283                         }
284                 }
285         }
286
287         if (Errorcount > errors) {
288                 clean_map_data();
289                 return(YES);
290         }
291
292         /* process each chord in the GRPSYL list */
293         for (gs_p = Curr_gs_list_p; gs_p != (struct GRPSYL *) 0;
294                                                         gs_p = gs_p->next) {
295                 /* initialize the allocation array for current chord */
296                 for (s = 0; s < Score.staffs; s++) {
297                         for (v = 0; v < MAXVOICES; v++) {
298                                 allocated[s][v] = NO;
299                         }
300                 }
301
302                 /* With voice-at-a-time input, we allow the first group
303                  * to have no pitch specified iff it is on a 1-line staff.
304                  * For chord-at-a-time, to allow that
305                  * we would have to allow a mapping of zero notes,
306                  * which doesn't make sense, or map an implicit note,
307                  * which seems questionable at best.
308                  * If there is a mixture of 1-line and not-1-line
309                  * staffs being mapped, things get even more confusing.
310                  * So we disallow implicit pitch on chord-at-at-time. */
311                 if (gs_p->nnotes == 1 && gs_p->notelist[0].letter == PP_NO_PITCH) {
312                         l_yyerror(Curr_filename, yylineno, "no notes specified");
313                         notemap_p = (struct NOTEMAP *) 0;
314                 }
315                 else {
316                         /* Find the pattern matching the number of notes.
317                          * If none is found, this will return 0, and the 'for'
318                          * below will get skipped, and we'll add spaces */
319                         notemap_p = find_notemap(gs_p->nnotes);
320                 }
321
322                 /* Go through each note in the chord, and copy it
323                  * to the appropriate staffs/voices */
324                 for (n = 0; notemap_p != (struct NOTEMAP *) 0;
325                                         n++, notemap_p = notemap_p->next) {
326                         for (svr_p = notemap_p->svlist_p;
327                                         svr_p != (struct SVRANGELIST *) 0;
328                                         svr_p = svr_p->next) {
329                             for (sr_p = svr_p->stafflist_p; sr_p != 0;
330                                                         sr_p = sr_p->next) {
331                                 for (s = sr_p->begin; s <= sr_p->end; s++) {
332                                     for (vr_p = svr_p->vnolist_p; vr_p != 0;
333                                                         vr_p = vr_p->next) {
334                                         for (v = vr_p->begin;
335                                                         v <= vr_p->end; v++) {
336                                                 /* If we have not yet mapped
337                                                  * anything from the current
338                                                  * input line, yet there is
339                                                  * something in the grpsyl
340                                                  * list for this staff/voice,
341                                                  * that means user must have
342                                                  * already defined data for
343                                                  * this staff/voice on some
344                                                  * other input line, and thus
345                                                  * is not allowed to map
346                                                  * anything from the current
347                                                  * line. */
348                                                 if (mapped_something[s-1][v-1]
349                                                         == MAPPED_NOTHING
350                                                         && Staffmap_p[s]->u.staff_p->groups_p[v-1] != 0
351                                                         && printed_mult_err[s-1][v-1] == NO) {
352                                                     mult_def(s, v);
353                                                     printed_mult_err[s-1][v-1] = YES;
354                                                     continue;
355                                                 }
356                                                 map1note(gs_p, n, s, v,
357                                                                 allocated);
358                                                 mapped_something[s-1][v-1]
359                                                         = MAPPED_EXPLICIT;
360                                         }
361                                     }
362                                 }
363                             }
364                         }
365                 }
366
367                 /* For any staff/voice that is being mapped to, but which
368                  * didn't get anything mapped for this particular chord,
369                  * add a space group. This could happen either because
370                  * user specified several patterns and some patterns don't
371                  * contain all the staffs/voices, which implies they want
372                  * us to fill in spaces, or because there was an error in
373                  * input. If there was an error, it's still nice to add the
374                  * space, because it prevents extra error messages */
375                 for (s = 1; s <= Score.staffs; s++) {
376                         for (v = 1; v <= MAXVOICES; v++) {
377                                 /* If we haven't mapped anything to this
378                                  * voice, but there is something there,
379                                  * user must have defined it on an earlier
380                                  * input line. In that case we should leave
381                                  * it be, because either (1) user didn't
382                                  * actually use any pattern that uses this
383                                  * voice, or (2) they multiply defined the
384                                  * voice, in which case the error is caught
385                                  * elsewhere. In either case, their
386                                  * earlier input should stand. */
387                                 if (mapped_something[s-1][v-1] == MAPPED_NOTHING
388                                                 && Staffmap_p[s]->u.staff_p->groups_p[v-1] != 0) {
389                                         continue;
390                                 }
391
392                                 if (used[s-1][v-1] == YES &&
393                                                 allocated[s-1][v-1] == NO) {
394                                         map1note(gs_p, -1, s, v, allocated);
395                                         if (mapped_something[s-1][v-1] !=
396                                                         MAPPED_EXPLICIT) {
397                                                 mapped_something[s-1][v-1]
398                                                         = MAPPED_IMPLICIT;
399                                         }
400                                 }
401                         }
402                 }
403         }
404
405         /* If this particular input line didn't actually use some of the
406          * patterns, some voices might not *really* have been used--we
407          * merely filled in implicit spaces for it. So we can undo that
408          * so user can specify the voice via voice-at-a-time if they want to.
409          * If they don't, the regular filling in of missing voices with
410          * implicit spaces will happen later. */
411         for (s = 0; s < Score.staffs; s++) {
412                 for (v = 0; v < MAXVOICES; v++) {
413                         if (used[s][v] == YES &&
414                                         mapped_something[s][v] != MAPPED_EXPLICIT) {
415                                 used[s][v] = NO;
416                                 Input_style[s][v] = IS_VOICE_INPUT;
417
418                                 /* If only implict, we free that up */
419                                 if (mapped_something[s][v] == MAPPED_IMPLICIT) {
420                                         free_grpsyls(Staffmap_p[s+1]->u.staff_p->groups_p[v]);
421                                         Staffmap_p[s+1]->u.staff_p->groups_p[v] = 0;
422                                 }
423                         }
424                 }
425         }
426
427         /* Now we can go through and free up any wasted space */
428         for (s = 0; s < Score.staffs; s++) {
429                 for (v = 0; v < MAXVOICES; v++) {
430                         if (used[s][v] == YES) {
431                                 /* Rests and spaces get moved from
432                                  * NOTE pseudo-pitches to GRPSYL */
433                                 convert_rest_space(Staffmap_p[s+1]->u.
434                                                 staff_p->groups_p[v], s+1, v+1);
435                                 for (g_p = Staffmap_p[s+1]->u.staff_p->groups_p[v];
436                                                 g_p != (struct GRPSYL *) 0;
437                                                 g_p = g_p->next) {
438                                         resize_notelist(g_p);
439                                 }
440                         }
441                 }
442         }
443
444         clean_map_data();
445
446         /* Everything in the original GRPSYL list
447          * has been copied to other lists, so original can be freed */
448         free_grpsyls(gs_p);
449
450         return(YES);
451 }
452 \f
453
454 /* map one note to one staff/voice */
455
456 static void
457 map1note(from_gs_p, n, staff, voice, allocated)
458
459 struct GRPSYL *from_gs_p;       /* copy from here */
460 int n;                          /* copy the nth note in from_gs_p, or if -1,
461                                  * create a space group */
462 int staff;
463 int voice;
464 short allocated[MAXSTAFFS][MAXVOICES];  /* tracks whether to allocate a new
465                                  * GRPSYL; may be updated */
466
467 {
468         struct GRPSYL *to_gs_p;         /* where to map note to */
469         struct GRPSYL **add_p_p;        /* where to add to_gs_p */
470         struct NOTE *from_note_p;
471         struct NOTE *to_note_p;
472         struct GRPSYL *prev;            /* value to set to_gs_p->prev to */
473
474
475         /* If original group is a grace group, we don't need to add a
476          * space group, since grace already take no time */
477         if (n == -1 && from_gs_p->grpvalue == GV_ZERO) {
478                 return;
479         }
480
481         /* If this is the first note allocated to this staff/voice for
482          * current chord, have to allocate a GRPSYL for it. */
483         if (allocated [staff - 1] [voice - 1] == NO) {
484                 to_gs_p = newGRPSYL(GS_GROUP);
485                 copy_attributes(to_gs_p, from_gs_p);
486                 /* by the time we get here, we've already gone past the
487                  * newline, so the input line number is one too much */
488                 to_gs_p->inputlineno--;
489
490                 allocated [staff - 1] [voice - 1] = YES;
491
492                 /* Add to end of list */
493                 prev = (struct GRPSYL *) 0;
494                 for (add_p_p = &(Staffmap_p[staff]->u.staff_p->groups_p[voice-1]);
495                                         *add_p_p != (struct GRPSYL *) 0;
496                                         add_p_p = &((*add_p_p)->next) ) {
497                         prev = *add_p_p;
498                 }
499                 to_gs_p->prev = prev;
500                 *add_p_p = to_gs_p;
501
502                 /* copy the other attributes */
503                 to_gs_p->staffno = staff;
504                 to_gs_p->vno = voice;
505                 to_gs_p->basictime = from_gs_p->basictime;
506                 to_gs_p->fulltime = from_gs_p->fulltime;
507                 to_gs_p->dots = from_gs_p->dots;
508                 to_gs_p->is_meas = from_gs_p->is_meas;
509                 to_gs_p->tuploc = from_gs_p->tuploc;
510                 to_gs_p->tupcont = from_gs_p->tupcont;
511                 to_gs_p->tupside = from_gs_p->tupside;
512                 to_gs_p->beamloc = from_gs_p->beamloc;
513                 to_gs_p->breakbeam = from_gs_p->breakbeam;
514                 to_gs_p->beamto = from_gs_p->beamto;
515                 to_gs_p->printtup = from_gs_p->printtup;
516                 to_gs_p->tie = from_gs_p->tie;
517                 to_gs_p->inhibitprint = from_gs_p->inhibitprint;
518                 to_gs_p->ho_usage = from_gs_p->ho_usage;
519                 to_gs_p->ho_value = from_gs_p->ho_value;
520         }
521         else {
522                 /* find the last group for this staff/voice */
523                 for (to_gs_p = Staffmap_p[staff]->u.staff_p->groups_p[voice-1];
524                                         to_gs_p->next != (struct GRPSYL *) 0;
525                                         to_gs_p = to_gs_p->next) {
526                         ;
527                 }
528         }
529
530         /* Special case: If n == -1, make this a space group */
531         if (n == -1) {
532                 to_gs_p->grpcont = GC_SPACE;
533                 /* some things don't make sense with space,
534                  * so nullify the things that just apply to notes */
535                 to_gs_p->grpvalue = GV_NORMAL;
536                 to_gs_p->headshape = HS_UNKNOWN;
537                 to_gs_p->grpsize = GS_NORMAL;
538                 to_gs_p->stemdir = UNKNOWN;
539                 to_gs_p->stemlen = STEMLEN_UNKNOWN;
540                 to_gs_p->roll = NOITEM;
541                 to_gs_p->beamloc = NOITEM;
542                 to_gs_p->breakbeam = NO;
543                 to_gs_p->beamto = CS_SAME;
544                 to_gs_p->stemto = CS_SAME;
545                 to_gs_p->slash_alt = 0;
546                 return;
547         }
548
549         from_note_p = &(from_gs_p->notelist[n]);
550         if (Doing_tab_staff == YES) {
551                 /* fret, nticks, and bendstring exist in from_note_p
552                  * in an internal format, whereas add_note() needs them
553                  * in something close to user input format,
554                  * so we have to reconstruct
555                  * what the user input must have been. */
556                 add_note(to_gs_p, from_gs_p->notelist[n].letter,
557                         from_note_p->accidental,
558                         TMP_FRET(from_note_p),
559                         TMP_NTICKS(from_note_p),
560                         from_note_p->acc_has_paren,
561                         (HASBEND(from_gs_p->notelist[n])
562                           ? bend_string(from_note_p)
563                           : (char *) 0) );
564         }
565         else {
566                 add_note(to_gs_p, from_gs_p->notelist[n].letter,
567                         from_note_p->accidental,
568                         from_note_p->octave,
569                         0,
570                         from_note_p->acc_has_paren,
571                         (char *) 0);
572         }
573
574         /* copy remaining note attributes: tie, slur, etc */
575         to_note_p = &(to_gs_p->notelist[to_gs_p->nnotes - 1]);
576         to_note_p->tie = from_note_p->tie;
577         to_note_p->tiestyle = from_note_p->tiestyle;
578         to_note_p->tiedir = from_note_p->tiedir;
579         to_note_p->nslurto = from_note_p->nslurto;
580         if (from_note_p->nslurto > 0) {
581                 /* slurto lists cannot be safely shared, so make copy */
582                 MALLOC(SLURTO, to_note_p->slurtolist, 
583                                         from_note_p->nslurto);
584                 (void) memcpy(to_note_p->slurtolist,
585                                         from_note_p->slurtolist,
586                                         sizeof(struct SLURTO) *
587                                         from_note_p->nslurto);
588         }
589         else {
590                 to_note_p->slurtolist = (struct SLURTO *) 0;
591         }
592         to_note_p->notesize = from_note_p->notesize;
593         to_note_p->note_has_paren = from_note_p->note_has_paren;
594         to_note_p->is_bend = from_note_p->is_bend;
595         to_note_p->smallbend = from_note_p->smallbend;
596 }
597 \f
598
599 /* When done with temporary map data, clean everything up, to prepare
600  * for potentially getting another set of data */
601
602 static void
603 clean_map_data()
604
605 {
606         /* free up the lists */
607         free_maps(Map_p);
608
609         /* reset pointers to be ready for more data */
610         Map_p = (struct MAP *) 0;
611         End_map_p_p = &Map_p;
612 }
613 \f
614
615 /* free up the MAP list and everything hanging off of it */
616
617 static void
618 free_maps(map_p)
619
620 struct MAP *map_p;
621
622 {
623         if (map_p == (struct MAP *) 0) {
624                 /* end recursion */
625                 return;
626         }
627
628         /* free the list hanging off of this struct */
629         free_notemaps(map_p->notemap_p);
630
631         /* recurse */
632         free_maps(map_p->next);
633
634         /* free the passed-in struct */
635         FREE(map_p);
636 }
637
638 /* free up a NOTEMAP list and everything hanging off of it */
639
640 static void
641 free_notemaps(notemap_p)
642
643 struct NOTEMAP *notemap_p;
644
645 {
646         if (notemap_p == (struct NOTEMAP *) 0) {
647                 return;
648         }
649
650         free_sv_list(notemap_p->svlist_p);
651         free_notemaps(notemap_p->next);
652         FREE(notemap_p);
653 }
654 \f
655
656 /* Given a number of notes, find the NOTEMAP list for that many and return it.
657  * If not found, return 0. */
658
659 static struct NOTEMAP *
660 find_notemap(num_notes)
661
662 int num_notes;
663
664 {
665         struct MAP *m_p;
666
667         for (m_p = Map_p; m_p != (struct MAP *) 0; m_p = m_p->next) {
668                 if (m_p->num_entries == num_notes) {
669                         return(m_p->notemap_p);
670                 }
671         }
672         
673         l_yyerror(Curr_filename, yylineno,
674                         "there is no bracketed mapping for chords containing %d note%s", num_notes, num_notes == 1 ? "" : "s");
675         return ((struct NOTEMAP *) 0);
676 }
677 \f
678
679 /* Once a measure-worth of data is gathered for one or more staffs/voices,
680  * link copies onto the appropriate STAFF structs */
681
682 void
683 link_groups()
684
685 {
686         /* if haven't yet set up the STAFFs for this measure, do so now */
687         create_staffs();
688
689         /* if we are in this function, user specified some music data */
690         Got_some_data = YES;
691         Got_group = YES;
692
693         /* do error check--can't have notes and multirest in same measure */
694         if (Got_multirest == 1) {
695                 report_mix_error();
696                 return;
697         }
698
699         /* Do either chord-to-voice-mapping or standard voice mapping,
700          * as appropriate. */
701         if (map_groups() == NO) {
702                 do_link_groups();
703         }
704
705         /* re-initialize for next measure */
706         Curr_gs_list_p = (struct GRPSYL *) 0;
707         free_rlists();
708 }
709 \f
710
711 /* Go through Svrangelist, creating copies of the GRPSYL lists and
712  * linking them to the appropriate STAFFs. */
713
714 static void
715 do_link_groups()
716
717 {
718         struct SVRANGELIST *svr_p;      /* list of ranges of staffs and vnos */
719         register int s;         /* staff index */
720         register int v;         /* voice index */
721         struct RANGELIST *sr_p; /* range of staffs being defined */
722         struct RANGELIST *vr_p; /* range of vno's being defined */
723         int copies = 0;         /* how many copies of grpsyl list made so far */
724
725
726         for (svr_p = Svrangelist_p; svr_p != (struct SVRANGELIST *) 0;
727                                                 svr_p = svr_p->next) {
728
729                 for (sr_p = svr_p->stafflist_p; sr_p != (struct RANGELIST *) 0;
730                                                         sr_p = sr_p->next) {
731
732                         for (s = sr_p->begin; s <= sr_p->end; s++) {
733
734                                 for (vr_p = svr_p->vnolist_p;
735                                                 vr_p != (struct RANGELIST *) 0;
736                                                 vr_p = vr_p->next) {
737
738                                         for (v = vr_p->begin;
739                                                         v <= vr_p->end; v++) {
740                                                 link_a_grouplist(s, v, copies++);
741                                         }
742                                 }
743                         }
744                 }
745         }
746 }
747 \f
748
749 /* connect list of GRPSYLs to a staff. If copies == 0, use the current
750  * grpsyl list, otherwise make a copy of it and use the copy */
751
752 static void
753 link_a_grouplist(staffno, vno, copies)
754
755 int staffno;
756 int vno;
757 int copies;     /* if non-zero, need to make a copy */
758
759 {
760         if (rangecheck(staffno, MINSTAFFS, Score.staffs, "staff number")
761                                         == NO) {
762                 return;
763         }
764
765         if (rangecheck(vno, MINVOICES, MAXVOICES, "voice number") == NO) {
766                 return;
767         }
768
769         if (Staffmap_p[staffno] == (struct MAINLL *) 0) {
770                 return;
771         }
772
773         if (Staffmap_p[staffno]->u.staff_p == (struct STAFF *) 0) {
774                 pfatal("null staff pointer while linking group list");
775         }
776
777         if (Staffmap_p[staffno]->u.staff_p->groups_p[vno-1]
778                         != (struct GRPSYL *) 0) {
779                 mult_def(staffno, vno);
780                 return;
781         }
782
783         /* the first time through, we can use the
784          * existing list. After that we need to
785          * make a clone of the list */
786         if (copies == 0) {
787                 (Staffmap_p[staffno])->u.staff_p->groups_p[vno-1]
788                                         = Curr_gs_list_p;
789                 convert_rest_space(Staffmap_p[staffno]->u.
790                                         staff_p->groups_p[vno-1], staffno, vno);
791         }
792         else {
793                 (Staffmap_p[staffno])->u.staff_p->groups_p[vno-1]
794                                         = clone_gs_list(Curr_gs_list_p, YES);
795         }
796 }
797 \f
798
799 /* With chord-at-a-time input style, it is legal to have
800  * a mixture of pitches, spaces, and rests. However, once
801  * everything has been distributed to individual voices, we need to check
802  * that there aren't still any mixtures, and convert the rest and
803  * space pseudo-notes into rest and space groups. Some error checks
804  * also get done that couldn't be done till after this conversion. */
805
806 static void
807 convert_rest_space(grpsyl_p, staffno, vno)
808
809 struct GRPSYL *grpsyl_p;
810 int staffno;
811 int vno;
812
813 {
814         for (   ; grpsyl_p != (struct GRPSYL *) 0; grpsyl_p = grpsyl_p->next) {
815                 conv_grpsyl(grpsyl_p, staffno, vno);
816         }
817 }
818 \f
819
820 /* Given a GRPSYL, convert all the rest and space
821  * pseudo notes to groups and do related error checking */
822
823 static void
824 conv_grpsyl(grpsyl_p, staffno, vno)
825
826 struct GRPSYL *grpsyl_p;
827 int staffno;
828 int vno;
829
830 {
831         int notes, rests, spaces, rpts;/* count how many of each in chord */
832         int n;                          /* index through notes */
833
834         /* Count how many notes, rests, and spaces in the group */
835         rests = spaces = notes = rpts = 0;
836         for (n = 0; n < grpsyl_p->nnotes; n++) {
837                 if (grpsyl_p->notelist[n].letter == PP_REST) {
838                         rests++;
839                 }
840                 else if (grpsyl_p->notelist[n].letter == PP_SPACE) {
841                         spaces++;
842                 }
843                 else if (grpsyl_p->notelist[n].letter == PP_RPT) {
844                         rpts++;
845                 }
846                 else {
847                         notes++;
848                 }
849         }
850
851         /* Group may not mix space, rest, rpt, and notes */
852         if (spaces > 0 && spaces != grpsyl_p->nnotes) {
853                 l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
854                         "staff %d voice %d: mixture of space and non-space",
855                         staffno, vno);
856                 return;
857         }
858         if (rests > 0 && rests != grpsyl_p->nnotes) {
859                 l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
860                         "staff %d voice %d: mixture of rest and non-rest",
861                         staffno, vno);
862                 return;
863         }
864         if (rpts > 0 && rpts != grpsyl_p->nnotes) {
865                 l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
866                         "staff %d voice %d: mixture of rpt and non-rpt",
867                         staffno, vno);
868                 return;
869         }
870
871         /* convert rest, space, and rpt pseudo-notes to groups */
872         if (notes < grpsyl_p->nnotes) {
873                 if (rests > 0) {
874                         /* This is actually a rest group */
875                         grpsyl_p->grpcont = GC_REST;
876                         grpsyl_p->tie = NO;
877                         /* If entire group was marked cue, leave it that way.
878                          * Otherwise, if multiple rests map to this group,
879                          * grpsize should be the biggest of them.
880                          * So initialize to small size,
881                          * and if we find any normal size,
882                          * set to normal and jump out of the loop. */
883                         if (grpsyl_p->grpsize != GS_SMALL) {
884                                 grpsyl_p->grpsize = GS_SMALL;
885                                 for (n = 0; n < grpsyl_p->nnotes; n++) {
886                                         if (grpsyl_p->notelist[n].notesize == GS_NORMAL) {
887         
888                                                 grpsyl_p->grpsize = GS_NORMAL;
889                                                 break;
890                                         }
891                                 }
892                         }
893                 }
894                 else if (spaces > 0) {
895                         /* This is actually a space group */
896                         grpsyl_p->grpcont = GC_SPACE;
897                         grpsyl_p->tie = NO;
898                         /* Uncompressibility was temporarily saved
899                          * in octave, so move it now. If multiple spaces
900                          * mapped to this group, if any of them are
901                          * uncompressible, make the group uncompressible. */
902                         for (n = 0; n < grpsyl_p->nnotes; n++) {
903                                 if (grpsyl_p->notelist[n].octave == YES) {
904                                         grpsyl_p->uncompressible = YES;
905                                         break;
906                                 }
907                         }
908                 }
909                 else if (rpts > 0) {
910                         /* This is actually a rpt. Internally, that is stored
911                          * as a note group with no notes (nnotes gets zeroed
912                          * a few lines down from here). This should 
913                          * already be notes but doesn't hurt to set again. */
914                         grpsyl_p->grpcont = GC_NOTES;
915                 }
916                 if (grpsyl_p->notelist[0].slurtolist != (struct SLURTO *) 0) {
917                         l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
918                                         "can't have slur on rest, space, or rpt");
919                 }
920                 free_notelist(grpsyl_p);
921                 grpsyl_p->notelist = 0;
922                 grpsyl_p->nnotes = 0;
923         }
924
925         if (grpsyl_p->grpcont == GC_NOTES) {
926                 if (grpsyl_p->is_meas == YES && grpsyl_p->nnotes > 0) {
927                         l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
928                                 "'m' can only be used with rest, space, or rpt, not notes");
929                         return;
930                 }
931         }
932
933         /* grace can only apply to notes */
934         if (grpsyl_p->grpvalue == GV_ZERO && (grpsyl_p->grpcont != GC_NOTES ||
935                                         grpsyl_p->nnotes == 0)) {
936                 l_yyerror(grpsyl_p->inputfile, grpsyl_p->inputlineno,
937                                 "grace can only be used with notes");
938         }
939 }
940 \f
941
942 /* If first group of a measure has no time value specified, we have to use
943  * the default. This is complicated by the fact that the user could be 
944  * defining mulitples staffs/voices at once. If they are, we need to make
945  * sure that all of them have the same default. */
946
947 struct SSV *
948 get_dflt_timeunit_ssv()
949
950 {
951         struct MAP *map_p;              /* list of maps */
952         struct NOTEMAP *notemap_p;      /* list of notemaps per map */
953         struct SVRANGELIST *svr_p;      /* list of staff/voice ranges */
954         struct RANGELIST *sr_p;         /* list of staffs being defined */
955         struct RANGELIST *vr_p;         /* list of voices being defined */
956         int s;                          /* staff number */
957         int v;                          /* voice */
958         int got_one = NO;               /* YES if have found a dflt value */
959         RATIONAL this_timeunit;         /* value for current staff/voice */
960         RATIONAL dflt_timeunit;         /* the default time unit to use */
961         struct SSV *tu_ssv_p;           /* SSV containing relevent timeunit */
962         struct SSV *ref_ssv_p;          /* SSV we had checked on prev
963                                          * staff/voice being defined together */
964
965
966         /* If doing voice-at-a-time input, use the special MAP for that case,
967          * otherwise use the Map_p */
968         if (Map_p == (struct MAP *) 0) {
969                 map_p = &Voice_at_a_time_map;
970                 map_p->notemap_p->svlist_p = Svrangelist_p;
971         }
972         else {
973                 map_p = Map_p;
974         }
975
976         /* score value is the ultimate default */
977         dflt_timeunit = Score.timeunit;
978         tu_ssv_p = ref_ssv_p = &Score;
979
980         /* check each map/notemap/svrangelist/svrange/staff/voice combination */
981         for (   ; map_p != (struct MAP *) 0; map_p = map_p->next) {
982             for (notemap_p = map_p->notemap_p;
983                                 notemap_p != (struct NOTEMAP *) 0;
984                                 notemap_p = notemap_p->next) {
985                 for (svr_p = notemap_p->svlist_p;
986                                         svr_p != (struct SVRANGELIST *) 0;
987                                         svr_p = svr_p->next) {
988                     for (sr_p = svr_p->stafflist_p;
989                                                 sr_p != (struct RANGELIST *) 0;
990                                                 sr_p = sr_p->next) {
991                         for (s = sr_p->begin; s <= sr_p->end; s++) {
992                             for (vr_p = svr_p->vnolist_p;
993                                                 vr_p != (struct RANGELIST *) 0;
994                                                 vr_p = vr_p->next) {
995                                 for (v = vr_p->begin; v <= vr_p->end; v++) {
996
997                                     /* find default timeunit for
998                                      * this staff/voice */
999                                     tu_ssv_p = vvpath(s, v, TIMEUNIT);
1000                                     this_timeunit = tu_ssv_p->timeunit;
1001
1002                                     if (got_one == NO) {
1003                                         /* now we have one to
1004                                          * compare against */
1005                                         dflt_timeunit = this_timeunit;
1006                                         ref_ssv_p = tu_ssv_p;
1007                                         got_one = YES;
1008                                     }
1009                                     else if ( NE(this_timeunit, dflt_timeunit)
1010                                                 || timelists_equal(
1011                                                 tu_ssv_p->timelist_p,
1012                                                 ref_ssv_p->timelist_p)
1013                                                 == NO) {
1014                                         yyerror("timeunit value must be the same for all staffs being defined on the same input line");
1015                                     }
1016                                 }
1017                             }
1018                         }
1019                     }
1020                 }
1021             }
1022         }
1023
1024         return(tu_ssv_p);
1025 }
1026 \f
1027
1028 /* Return YES if the given lists are equivalent, NO if they aren't. */
1029
1030 int
1031 timelists_equal(list1_p, list2_p)
1032
1033 struct TIMELIST *list1_p;
1034 struct TIMELIST *list2_p;
1035
1036 {
1037         for (   ; list1_p != 0 && list2_p != 0;
1038                         list1_p = list1_p->next, list2_p = list2_p->next) {
1039                 if ( NE(list1_p->fulltime, list2_p->fulltime) ) {
1040                         return(NO);
1041                 }
1042         }
1043         return((list1_p == 0 && list2_p == 0) ? YES : NO);
1044 }
1045 \f
1046
1047 /* Return YES if the current staff range is for all tablature staffs.
1048  * Return NO if not. If there are a mixture, this is an error, so print
1049  * a message. It still returns NO in this case, so if the user wanted tab,
1050  * they may get a lot of errors.  Oh well. After all, they did make an error.
1051  */ 
1052
1053 int
1054 is_tab_range()
1055
1056 {
1057         struct MAP *map_p;
1058         struct NOTEMAP *notemap_p;
1059         struct SVRANGELIST *svr_p;
1060         struct RANGELIST *sr_p;
1061         int s;                          /* staff number */
1062         int found_tab_staff = NO;
1063         int found_non_tab_staff = NO;
1064
1065         /* If doing voice-at-a-time input, use the special MAP for that case,
1066          * otherwise use the Map_p */
1067         if (Map_p == (struct MAP *) 0) {
1068                 map_p = &Voice_at_a_time_map;
1069                 map_p->notemap_p->svlist_p = Svrangelist_p;
1070         }
1071         else {
1072                 map_p = Map_p;
1073         }
1074
1075         /* check each map/notemap/svrangelist/svrange/staff/voice combination */
1076         for (   ; map_p != (struct MAP *) 0; map_p = map_p->next) {
1077                 for (notemap_p = map_p->notemap_p;
1078                                 notemap_p != (struct NOTEMAP *) 0;
1079                                 notemap_p = notemap_p->next) {
1080                         for (svr_p = notemap_p->svlist_p;
1081                                         svr_p != (struct SVRANGELIST *) 0;
1082                                         svr_p = svr_p->next) {
1083                                 for (sr_p = svr_p->stafflist_p;
1084                                                 sr_p != (struct RANGELIST *) 0;
1085                                                 sr_p = sr_p->next) {
1086                                         for (s = sr_p->begin; s <= sr_p->end; s++) {
1087                                                 if (is_tab_staff(s) == YES) {
1088                                                         found_tab_staff = YES;
1089                                                 }
1090                                                 else {
1091                                                         found_non_tab_staff = YES;
1092                                                 }
1093                                         }
1094                                 }
1095                         }
1096                 }
1097         }
1098
1099         if (found_tab_staff == YES && found_non_tab_staff == YES) {
1100                 yyerror("mixture of tab and non-tab staffs not allowed");
1101         }
1102
1103         return(found_tab_staff);
1104 }
1105 \f
1106
1107 /* When two notes in a chord are duplicates from chord-at-a-time input,
1108  * we want to merge the notes, and get rid of the extra. This function will
1109  * change the value of gs_p->nnotes and the size of the notelist array. */
1110
1111 void
1112 merge_dup_notes(gs_p, n)
1113
1114 struct GRPSYL *gs_p;    /* remove duplicate from here */
1115 int n;                  /* merge note n and n+1 into slot n, then remove
1116                          * the note in slot n+1 by moving any remaining
1117                          * notes down. */
1118
1119 {
1120         int i;
1121         int sn, sn1;            /* slurto index */
1122         struct NOTE *note_p, *extra_p;
1123
1124
1125         /* get shorter names for what we will use a lot */
1126         note_p = &(gs_p->notelist[n]);
1127         extra_p = &(gs_p->notelist[n+1]);
1128         /* Merge the data between the two as best we can.
1129          * In general, if one has a "stronger" version of some attribute,
1130          * go with that one. We check the second; if it is "stronger",
1131          * force the result to that--if it was already set the same, fine--
1132          * probably faster to just assign than check and maybe assign.
1133          * If second wasn't stronger, go with whatever the first was. */
1134
1135         /* If one is normal, one small, override the small */
1136         if (extra_p->notesize == GS_NORMAL) {
1137                 note_p->notesize = GS_NORMAL;
1138         }
1139
1140         /* If either has a tie, do a tie */
1141         if (extra_p->tie == YES) {
1142                 note_p->tie = YES;
1143         }
1144         /* Consider normal tie the strongest, then dashed, then dotted */
1145         if (extra_p->tiestyle == L_NORMAL) {
1146                 note_p->tiestyle = L_NORMAL;
1147         }
1148         else if (extra_p->tiestyle == L_DASHED &&
1149                         note_p->tiestyle != L_NORMAL) {
1150                 note_p->tiestyle = L_DASHED;
1151         }
1152         if ( (extra_p->tiedir == UP && note_p->tiedir == DOWN) ||
1153                         (extra_p->tiedir == DOWN && note_p->tiedir == UP)) {
1154                 /* It would be nice to allow both up and down tie,
1155                  * especially since we can do that for slurs,
1156                  * but we only support one tie per note. */
1157                 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
1158                         "duplicate notes with opposite tie direction not allowed");
1159         }
1160         else if (extra_p->tiedir != UNKNOWN) {
1161                 note_p->tiedir = extra_p->tiedir;
1162         }
1163
1164
1165         /* Parentheses around an accidental means "just in case you forgot..."
1166          * which is weaker than no parentheses, so only use parentheses if
1167          * both have it. */
1168         if (extra_p->acc_has_paren == NO) {
1169                 note_p->acc_has_paren = NO;
1170         }
1171         /* Parentheses around a note generally means the note is optional.
1172          * An optional merged with a non-optional, is non-optional. */
1173         if (extra_p->note_has_paren == NO) {
1174                 note_p->note_has_paren = NO;
1175         }
1176
1177         /* Sorry, we don't deal with incompatible bends */
1178         if (note_p->is_bend != extra_p->is_bend ||
1179                         extra_p->smallbend != note_p->smallbend) {
1180                 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
1181                         "duplicate notes with bend mismatch not allowed");
1182         }
1183
1184         /* Slurs... If duplicate between the two slurto lists, just leave
1185          * the one, but use strongest slurstyle. If there is one in the
1186          * NOTE to be deleted but not in the one to keep, move it. */
1187         for (sn1 = 0; sn1 < extra_p->nslurto; sn1++) {
1188                 for (sn = 0; sn < note_p->nslurto; sn++) {
1189                         if (note_p->slurtolist[sn].letter ==
1190                                         extra_p->slurtolist[sn1].letter &&
1191                                         note_p->slurtolist[sn].slurdir ==
1192                                         extra_p->slurtolist[sn1].slurdir &&
1193                                         note_p->slurtolist[sn].octave ==
1194                                         extra_p->slurtolist[sn1].octave) {
1195                                 /* duplicate; just fix style if necessary */
1196                                 if (extra_p->slurtolist[sn1].slurstyle
1197                                                                 == L_NORMAL) {
1198                                         note_p->slurtolist[sn].slurstyle
1199                                                         = L_NORMAL;
1200                                 }
1201                                 else if (extra_p->slurtolist[sn1].slurstyle
1202                                                 == L_DASHED &&
1203                                                 note_p->slurtolist[sn].slurstyle
1204                                                 != L_NORMAL) {
1205                                         note_p->slurtolist[sn].slurstyle
1206                                                         = L_DASHED;
1207                                 }
1208                                 break;
1209                         }
1210                 }
1211                 if (sn == note_p->nslurto) {
1212                         /* wasn't on the list to keep, so add it */
1213                         add_slurto(gs_p, extra_p->slurtolist[sn1].letter,
1214                                         extra_p->slurtolist[sn1].octave,
1215                                         sn,
1216                                         extra_p->slurtolist[sn1].slurstyle);
1217                 }
1218         }
1219
1220         /* Move things down in the notelist to remove the extra */
1221         for (i = n + 1; i < gs_p->nnotes - 1; i++) {
1222                 gs_p->notelist[i] = gs_p->notelist[i+1];
1223         }
1224         (gs_p->nnotes)--;
1225         REALLOC(NOTE, gs_p->notelist, gs_p->nnotes);
1226 }
1227 \f
1228
1229 /* print error message for multiply defined voice */
1230
1231 static void
1232 mult_def(staff, voice)
1233
1234 int staff;
1235 int voice;
1236
1237 {
1238         l_yyerror(Curr_filename, yylineno,
1239                 "staff %d voice %d multiply defined (first defined on line %d)",
1240                 staff, voice,
1241                 Staffmap_p[staff]->u.staff_p->groups_p[voice-1]->inputlineno);
1242 }