1 /* Output from p2c 1.21alpha-07.Dec.93, the Pascal-to-C translator */
2 /* From input file "mtx.pas" */
3 
4 
5 #include "p2c.h"
6 
7 
8 #define MTX_G
9 #include "mtx.h"
10 
11 
12 #ifndef CONTROL_H
13 #include "control.h"
14 #endif
15 
16 #ifndef MTXLINE_H
17 #include "mtxline.h"
18 #endif
19 
20 #ifndef STRINGS_H
21 #include "strings.h"
22 #endif
23 
24 #ifndef STATUS_H
25 #include "status.h"
26 #endif
27 
28 #ifndef NOTES_H
29 #include "notes.h"
30 #endif
31 
32 
33 #define flagged         "8136"
34 
35 
36 typedef boolean sticky['z' + 1 - 'a'];
37 
38 
39 Static sticky note_attrib[maxvoices], rest_attrib[maxvoices];
40 
41 
logTwo(denom)42 Static short logTwo(denom)
43 short denom;
44 {
45   short l = 0;
46 
47   while (denom > 1) {
48     l++;
49     denom /= 2;
50   }
51   return l;
52 }
53 
54 
dotted(n)55 Local boolean dotted(n)
56 short n;
57 {
58   boolean Result;
59 
60 /* p2c: mtx.pas: Note: Eliminated unused assignment statement [338] */
61   if (n == 0)
62     return false;
63   if (n != n / 3 * 3)
64     return false;
65   n /= 3;
66   while ((n & 1) == 0)
67     n /= 2;
68   return (n == 1);
69 }
70 
71 
72 /* RESTS should have a third parameter OFFSET.  At present we in effect
73    assume OFFSET+LENGTH to be a multiple of METERDENOM. */
rests(Result,len,meterdenom,blind)74 Char *rests(Result, len, meterdenom, blind)
75 Char *Result;
76 short len, meterdenom;
77 boolean blind;
78 {
79   Char r[256], bl[256];
80   Char STR1[256];
81 
82   if (blind)
83     strcpy(bl, "b");
84   else
85     *bl = '\0';
86   if (len == 0)
87     return strcpy(Result, "");
88   else {
89     if (len == meterdenom * 128) {
90       sprintf(Result, "r9%s ", bl);
91       return Result;
92     } else {
93       if (dotted(len)) {
94 	rests(r, len - len / 3, meterdenom, false);
95 	r[2] = 'd';
96 	sprintf(Result, "%s%s ", r, bl);
97 	return Result;
98       } else if (len >= 64 / meterdenom) {
99 	sprintf(Result, "%sr%c%s ",
100 		rests(STR1, len - 64 / meterdenom, meterdenom, blind),
101 		durations[whole + logTwo(meterdenom) - 1], bl);
102 	return Result;
103       } else
104 	return (rests(Result, len, meterdenom * 2, blind));
105     }
106   }
107 }
108 
109 
attribs(Result,note)110 Local Char *attribs(Result, note)
111 Char *Result;
112 Char *note;
113 {
114   Char a[256];
115   short i = 2;
116   short l;
117   Char n;
118 
119   *a = '\0';
120   l = strlen(note);
121   while (i <= l) {
122     n = note[i-1];
123     if (n == 'x')
124       i = l;
125     else if (islower(n))
126       sprintf(a + strlen(a), "%c", n);
127     i++;
128   }
129   return strcpy(Result, a);
130 }
131 
132 
checkSticky(note,attrib)133 Static Void checkSticky(note, attrib)
134 Char *note;
135 boolean *attrib;
136 {
137   short i = 2;
138   short l;
139   Char c;
140   Char a[256];
141 
142   if (*note == '\0')
143     return;
144   l = strlen(note);
145   while (i <= l) {
146     c = note[i-1];
147     if (islower(c)) {
148       if (i < l && note[i] == ':') {
149 	delete1(note, i + 1);
150 	l--;
151 	attrib[c - 'a'] = !attrib[c - 'a'];
152       } else
153 	attrib[c - 'a'] = false;
154     }
155     i++;
156   }
157   attribs(a, note);
158   for (c = 'z'; c >= 'a'; c--) {
159     if (attrib[c - 'a'] && pos1(c, a) == 0)
160       insertChar(c, note, 3);
161   }
162 }
163 
164 
165 /* Routine was patched by Hiroaki Morimoto, revised 2003/08/15.
166    Rewritten by DPL 2004/05/16 to be more understandable.
167    octaveCode returns octave adjustments in the order
168    [absolute or =],[relative] */
checkOctave(voice,note)169 Void checkOctave(voice, note)
170 voice_index voice;
171 Char *note;
172 {
173   Char code;
174 
175   code = octaveCode(note);
176   if (code == '=') {
177     setOctave(voice);
178     removeOctaveCode(code, note);
179   }
180   if (octave(voice) == blank)
181     return;
182   code = octaveCode(note);
183   if (isdigit(code)) {
184     resetOctave(voice);
185     return;
186   }
187   while (code == '+' || code == '-') {
188     newOctave(voice, code);
189     removeOctaveCode(code, note);
190     code = octaveCode(note);
191   }
192   if (code != ' ')
193     error3(voice, "You may have only one absolute octave assignment");
194   insertOctaveCode(octave(voice), note);
195   resetOctave(voice);
196 }
197 
198 
markDebeamed(voice,note)199 Void markDebeamed(voice, note)
200 voice_index voice;
201 Char *note;
202 {
203   if (isVocal(voice) && afterSlur(voice) == 0 && unbeamVocal() &&
204       pos1(duration(voice), flagged) > 0)
205     insertChar('a', note, 2);
206 }
207 
208 
barLength(meter)209 Static short barLength(meter)
210 Char *meter;
211 {
212   short n1, n2, pn1, pn2;
213 
214   getMeter(meter, &n1, &n2, &pn1, &pn2);
215   return (n1 * (64 / n2));
216 }
217 
218 
isMultiBarRest(rest_)219 Static boolean isMultiBarRest(rest_)
220 Char *rest_;
221 {
222   boolean Result;
223 
224 /* p2c: mtx.pas: Note: Eliminated unused assignment statement [338] */
225   if (strlen(rest_) < 3)
226     return false;
227   if (rest_[1] != 'm')
228     return false;
229   if (multi_bar_rest)
230     error("Only one multibar rest allowed per line", print);
231   multi_bar_rest = true;
232   return true;
233 }
234 
235 
236 /* Double-length in xtuplet detected by a brute search for D anywhere.
237    Could be more elegant. */
238 
239 Static short macro_length[20];
240 
241 Static Char macro_ID[20][3] = {
242   "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14",
243   "15", "16", "17", "18", "19", "20"
244 };
245 
246 
247 /* Local variables for scanMusic: */
248 struct LOC_scanMusic {
249   voice_index voice;
250   Char note[256];
251   boolean doublex, store_macro;
252   short bar, old_length, bar_length, count, l, mlen, ngrace, nmulti, macroID,
253 	playID;
254   Char macro_type;
255 } ;
256 
decmulti(LINK)257 Local Void decmulti(LINK)
258 struct LOC_scanMusic *LINK;
259 {
260   if (LINK->doublex)
261     LINK->nmulti -= 2;
262   else
263     LINK->nmulti--;
264 }
265 
266 /* Local variables for countIt: */
267 struct LOC_countIt {
268   struct LOC_scanMusic *LINK;
269 } ;
270 
incbar(nl,LINK)271 Local Void incbar(nl, LINK)
272 short nl;
273 struct LOC_countIt *LINK;
274 {
275   LINK->LINK->bar_length += nl;
276   if (LINK->LINK->bar_length > LINK->LINK->bar && meternum > 0)
277     error3(LINK->LINK->voice, "Bar end occurs in mid-note");
278 }
279 
countIt(LINK)280 Local Void countIt(LINK)
281 struct LOC_scanMusic *LINK;
282 {
283   struct LOC_countIt V;
284 
285   V.LINK = LINK;
286   if (LINK->ngrace > 0) {
287     LINK->ngrace--;
288     return;
289   }
290   if (LINK->nmulti > 0) {
291     decmulti(LINK);
292     return;
293   }
294   if (LINK->count % 3 != 0 &&
295       (LINK->note[0] != rest && note_attrib[LINK->voice-1]['d' - 'a'] ||
296        LINK->note[0] == rest && rest_attrib[LINK->voice-1]['d' - 'a']))
297     LINK->count += LINK->count / 2;
298 /* p2c: mtx.pas, line 148:
299  * Note: Using % for possibly-negative arguments [317] */
300   incbar(LINK->count, &V);
301   LINK->l = pos1(multi_group, LINK->note);
302   if (LINK->l <= 0)
303     return;
304   predelete(LINK->note, LINK->l);
305   getNum(LINK->note, &LINK->nmulti);
306   decmulti(LINK);
307 }
308 
maybeGroup(LINK)309 Local Void maybeGroup(LINK)
310 struct LOC_scanMusic *LINK;
311 {
312   if (LINK->note[0] != grace_group)
313     return;
314   if (strlen(LINK->note) == 1)
315     LINK->ngrace = 1;
316   else
317     LINK->ngrace = pos1(LINK->note[1], digits);
318   /* bug if ngrace>9 */
319   if (LINK->ngrace > 0)
320     LINK->ngrace--;
321 }
322 
identifyMacro(s_,LINK)323 Local short identifyMacro(s_, LINK)
324 Char *s_;
325 struct LOC_scanMusic *LINK;
326 {
327   Char s[256];
328   short k;
329 
330   strcpy(s, s_);
331   predelete(s, 2);
332   for (k = 1; k <= 20; k++) {
333     if (!strcmp(s, macro_ID[k-1]))
334       return k;
335   }
336   return 0;
337 }
338 
examineMacro(LINK)339 Local Void examineMacro(LINK)
340 struct LOC_scanMusic *LINK;
341 {
342   if (!countMacro())
343     return;
344   if (debugMode())
345     printf("%s: ", LINK->note);
346   if (strlen(LINK->note) == 1) {
347     LINK->mlen = LINK->bar_length - LINK->old_length;
348     if (LINK->macroID < 1 || LINK->macroID > 20)
349       error3(LINK->voice, "Invalid macro ID");
350     macro_length[LINK->macroID-1] = LINK->mlen;
351     if (debugMode())
352       printf("Ending macro %d of type %c, length=%d\n",
353 	     LINK->macroID, LINK->macro_type, LINK->mlen);
354     if (LINK->macro_type == 'S')
355       LINK->bar_length = LINK->old_length;
356     LINK->store_macro = false;
357     return;
358   }
359   LINK->playID = identifyMacro(LINK->note, LINK);
360   if (LINK->playID < 1 || LINK->playID > 20)
361     error3(LINK->voice, "Invalid macro ID");
362   if (LINK->note[1] == 'P') {
363     if (debugMode())
364       printf("Playing macro %d of length %d\n",
365 	     LINK->playID, macro_length[LINK->playID-1]);
366     LINK->bar_length += macro_length[LINK->playID-1];
367     return;
368   }
369   if (pos1(LINK->note[1], "SR") <= 0)
370     return;
371   LINK->old_length = LINK->bar_length;
372   LINK->macro_type = LINK->note[1];
373   LINK->macroID = LINK->playID;
374   LINK->store_macro = true;
375   if (debugMode())
376     printf("Defining macro %d of type %c\n", LINK->macroID, LINK->note[1]);
377 }
378 
379 
scanMusic(voice_,left_over)380 Void scanMusic(voice_, left_over)
381 voice_index voice_;
382 short *left_over;
383 {
384   struct LOC_scanMusic V;
385   Char buf[256], enote[256], xnote[256];
386   boolean has_next = false, done = false;
387   Char dur1, lastdur;
388   music_word nscan;
389   Char STR1[256];
390 
391   V.voice = voice_;
392   strcpy(terminators, "d.x");
393   resetInfo(V.voice, buf);
394   *left_over = 0;
395   V.store_macro = false;
396   V.bar = full_bar;
397   V.bar_length = 0;
398   V.ngrace = 0;
399   V.nmulti = 0;
400   if (meternum == 0)
401     V.bar = 32000;
402   dur1 = duration(V.voice);
403   lastdur = dur1;
404   do {
405     getNextMusWord(buf, V.note, &nscan);
406     if (*V.note == '\0')
407       break;
408     V.count = 0;
409     /*    if isNoteOrRest(note) and not (isPause(note) or isMultibarRest(note))
410           then note:=toStandard(note); */
411     V.doublex = (pos1('D', V.note) > 0);
412     if (nscan == mword) {
413       if (*V.note == '\0')
414 	error3(V.voice, "You may not end a line with a meter change");
415       if (V.bar_length > 0)
416 	error3(V.voice, "Meter change only allowed at start of bar");
417       else
418 	V.bar = barLength(V.note);
419     } else if (nscan == rword) {
420       if (!(isPause(V.note) || isMultiBarRest(V.note))) {
421 	processNote(V.note, xnote, dur1, &lastdur, &V.count);
422 	checkSticky(V.note, rest_attrib[V.voice-1]);
423       }
424     }
425     if (*V.note != '\0')
426       appendNote(V.voice, nscan);
427     strcpy(enote, V.note);
428     if (nscan == macro || nscan == endmacro)
429       examineMacro(&V);
430     if (nscan == abcdefg) {
431       if (!multi_bar_rest && V.ngrace + V.nmulti == 0) {
432 	processNote(enote, xnote, dur1, &lastdur, &V.count);
433 	if (*xnote != '\0') {
434 	  checkSticky(enote, note_attrib[V.voice-1]);
435 	  appendToLine(V.voice, enote);
436 	  appendNote(V.voice, nscan);
437 	  strcpy(enote, xnote);
438 	}
439 	checkSticky(enote, note_attrib[V.voice-1]);
440       }
441     }
442     appendToLine(V.voice, enote);
443     if (*V.note == '\0')   /* !!! else word_bound[here]:=length(line); */
444       done = true;
445     sprintf(STR1, "%c", barsym);
446     if (!strcmp(V.note, STR1)) {
447       if (meternum == 0)
448 	error3(V.voice, "You may not use bar lines in barless music");
449       else if (V.bar_length == 0)
450 	markBar(V.voice);
451       else if (numberOfBars(V.voice) == 0 && V.bar_length < V.bar) {
452 	if (has_next)
453 	  has_next = false;   /*Should check whether pickups are equal*/
454 	else if (*left_over > 0)
455 	  error3(V.voice, "Bar is too short");
456 	*left_over = V.bar_length;
457 	V.bar_length = 0;
458       }
459     }
460     if (nscan == nextvoice) {
461       if (V.bar_length > 0)
462 	error3(V.voice, "Next voice before bar is full");
463       else
464 	barForward(V.voice, -1);
465       has_next = true;
466     } else if (isPause(V.note))
467       V.bar_length += V.bar;
468     else if (!multi_bar_rest) {   /*do nothing*/
469       if (!done && isNoteOrRest(V.note))
470 	countIt(&V);
471       else
472 	maybeGroup(&V);
473     }
474     dur1 = lastdur;
475     if (V.bar_length >= V.bar && V.ngrace + V.nmulti == 0 && !V.store_macro) {
476       if (debugMode())
477 	printf("%d %d\n", V.voice, V.bar_length);
478       barForward(V.voice, V.bar_length / V.bar);
479       V.bar_length %= V.bar;
480 /* p2c: mtx.pas, line 266:
481  * Note: Using % for possibly-negative arguments [317] */
482     }
483   } while (!done);
484   setExtraLength(V.voice, V.bar_length);
485   resetDuration(V.voice, dur1);
486   regroup(V.voice);
487 }
488 
489 
initMTX()490 Void initMTX()
491 {
492   voice_index i;
493   Char j;
494 
495   for (i = 0; i <= maxvoices - 1; i++) {
496     for (j = 'a'; j <= 'z'; j++)
497       note_attrib[i][j - 'a'] = false;
498   }
499   memcpy(rest_attrib, note_attrib, maxvoices * sizeof(sticky));
500 }
501 
502 
503 
504 
505 /* End. */
506