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