Filter:   InfoImg
download _MKNameTable.m
Language: ObjectiveC
Copyright: (c) 1988-1992, NeXT Computer, Inc. (c) 1999-2000 The MusicKit Project. (c) 1994 NeXT Computer, Inc. and reproduced under license from NeXT (c) 1994 Stanford University
LOC: 404
Project Info
The MusicKit(musickit)
Server: SourceForge
Type: cvs
...sicKit\Frameworks\MusicKit\
   _ArielQP.h
   _DSPMK.h
   _error.h
   _midi.h
   _MKAppProxy.h
   _MKAppProxy.m
   _MKNameTable.h
   _MKNameTable.m
   _MKParameter.h
   _MTCHelper.h
   _MTCHelper.m
   _musickit.h
   _noteRecorder.h
   _OrchloopbeginUG.h
   _OrchloopbeginUG.m
   _ParName.h
   _ParName.m
   _scorefile.h
   _ScorefileVar.h
   _ScorefileVar.m
   _SharedSynthInfo.h
   _SharedSynthInfo.m
   _synthElementMethods.m
   _time.h
   ArielQP.h
   ArielQP.m
   classFuncs.h
   ConductorPrivate.h
   dsp_types.h
   DSPSerialPortDevice.h
   dspwrap.h
   EnvelopePrivate.h
   equalTempered.m
   errors.h
   fastFFT.c
   fastFFT.h
   GNUmakefile.postamble
   GNUmakefile.preamble.in
   InstrumentPrivate.h
   keynums.h
   libMusicKit.def
   Localized.strings
   make.sh
   Makefile.postamble
   Makefile.preamble
   midi_spec.h
   midifile.h
   midifile.m
   MidiPrivate.h
   midiTranslation.h
   MKConductor.h
   MKConductor.m
   MKConductorDelegate.h
   MKDeviceStatus.h
   MKEnvelope.h
   MKEnvelope.m
   MKFilePerformer.h
   MKFilePerformer.m
   MKFileWriter.h
   MKFileWriter.m
   MKInstrument.h
   MKInstrument.m
   MKMidi.h
   MKMidi.m
   MKMixerInstrument.h
   MKMixerInstrument.m
   MKMTCPerformer.h
   MKMTCPerformer.m
   MKNote.h
   MKNoteFilter.h
   MKNoteFilter.m
   MKNoteReceiver.h
   MKNoteReceiver.m
   MKNoteSender.h
   MKNoteSender.m
   MKOrchestra.h
   MKPart.m
   MKPartials.h
   MKPartials.m
   ...tialsWaveshapingTable.m
   MKPartPerformer.h
   MKPartPerformer.m
   MKPartRecorder.h
   MKPartRecorder.m
   MKPatch.h
   MKPatch.m
   MKPatchConnection.h
   MKPatchConnection.m
   MKPatchEntry.h
   MKPatchEntry.m
   MKPatchTemplate.h
   MKPatchTemplate.m
   MKPerformer.h
   MKPerformer.m
   MKPerformerDelegate.h
   MKPlugin.h
   MKSamplerInstrument.h
   MKSamplerInstrument.m
   MKSamples.h
   MKScore.h
   MKScore.m
   MKScorefileObject.h
   MKScorefilePerformer.h
   MKScorefilePerformer.m
   MKScorefileWriter.m
   MKScorePerformer.h
   MKScorePerformer.m
   MKScoreRecorder.h
   MKScoreRecorder.m
   MKSynthData.h
   MKSynthData.m
   MKSynthInstrument.h
   MKSynthPatch.h
   MKTimbre.h
   MKTimbre.m
   MKTuningSystem.h
   MKTuningSystem.m
   MKUnitGenerator.h
   MKUnitGenerator.m
   MKWaveTable.h
   MKWaveTable.m
   mtcMidi.m
   mtcMidiPrivate.m
   MusicKit-Info.plist
   MusicKit.h
   MusicKitConfig.h.in
   names.h
   noDVal.h
   noteDispatcherMethods.m
   NotePrivate.h
   noteRecorderCFuncs.m
   noteRecorderMethods.m
   orch.h
   OrchestraPrivate.h
   OrchloopbeginUG.h
   OrchloopbeginUG.m
   orchloopbeginUGInclude.m
   params.h
   parNames.m
   partialsDBInclude.m
   PartialsPrivate.h
   PartPerformerPrivate.h
   PartPrivate.h
   PartRecorderPrivate.h
   PatchTemplatePrivate.h
   PB.project
   PerformerPrivate.h
   pitches.h
   platform.make
   ...efilePerformerPrivate.h
   ScorePerformerPrivate.h
   ScorePrivate.h
   ScoreRecorderPrivate.h
   SynthDataPrivate.h
   synthElementCFuncs.m
   synthElementMethods.m
   SynthInstrumentPrivate.h
   SynthPatchList.h
   SynthPatchList.m
   SynthPatchPrivate.h
   timetagInclude.m
   timeunits.h
   tokenNames.m
   tokens.h
   trigonometry.c
   trigonometry.h
   TuningSystemPrivate.h
   UnitGeneratorPrivate.h
   win32-def.top
   writeBinary.m
   writeMidi.m
   writeScore.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
/*
 $Id: _MKNameTable.m,v 1.16 2006/02/05 17:57:10 leighsmith Exp $
 Defined In: The MusicKit

 Description:

 Note:
 * back-hashing is optionally supported.
 * the name is owned by the name table (it is copied and freed)
 * a type is associated with the name.

 Note that if back-hashing is not specified (via the _MK_BACKHASH bit),
 the object name is NOT accessible from the object. We use backhashing
 except for things such as pitch names and keywords, where backhashing
 is never done.

 We should convert it to an NSDictionary, however:
 1. NSDictionary always copies but memory's cheap so big deal.
 2. using the object as reference (back-hashing) needs somewhere to save the type,
 otherwise an enclosing object needs to be defined holding the object and the type
 parameters as the value. This means a search won't work.
 We could do this by making the type be an instance var of the object, or just having two dictionaries.

 Also, should NOT copy strings. Or, at least, have a no-copy bit
 that can be set for the strings that exist elsewhere (e.g. the
                                                       ones for the keywords and such) in the program.

 Original Author: David Jaffe

 Copyright (c) 1988-1992, NeXT Computer, Inc.
 Portions Copyright (c) 1994 NeXT Computer, Inc. and reproduced under license from NeXT
 Portions Copyright (c) 1994 Stanford University
 Portions Copyright (c) 1999-2000 The MusicKit Project.
 */
/*
Modification history:

 $Log: _MKNameTable.m,v $
 Revision 1.16  2006/02/05 17:57:10  leighsmith
 Cleaned up prototypes for Xcode 2.2 as it is much more strict about mixing id with a defined type

 Revision 1.15  2004/11/16 18:17:26  leighsmith
 Removed _MKTuningSystemInit() so it is now unnecessary to initialise the tuning system until it is needed

 Revision 1.14  2003/08/16 22:29:11  leighsmith
 replaced some i386 #if conditions with a tighter check to verify it is only in the case of Intel NeXTStep platforms, several chunks of code were being compiled on Intel machines running GnuStep

 Revision 1.13  2003/08/04 21:14:33  leighsmith
 Changed typing of several variables and parameters to avoid warnings of mixing comparisons between signed and unsigned values.

 Revision 1.12  2002/04/16 15:07:06  sbrandon
 - now use proper capacity for new nametbles instead of default 10
 - included new debug tool "_MKPrintGlobalNameTables()" to view
   what's in there

 Revision 1.11  2002/04/15 14:28:15  sbrandon
 - changed symbols and types NSDictionaries to NSMapTables, because NSMapTables
   do not have to retain their objects (and I have set them up not to do so).
   This had been causing dealloc loops for objects held in the main dict
   and trying to remove themselves in their -dealloc methods.

 Revision 1.10  2002/04/03 03:59:41  skotmcdonald
 Bulk = NULL after free type paranoia, lots of ensuring pointers are not nil before freeing, lots of self = [super init] style init action

 Revision 1.9  2002/01/23 15:33:02  sbrandon
 The start of a major cleanup of memory management within the MK. This set of
 changes revolves around MKNote allocation/retain/release/autorelease.

 Revision 1.8  2001/09/06 21:27:48  leighsmith
 Merged RTF Reference documentation into headerdoc comments and prepended MK to any older class names

 Revision 1.7  2000/10/01 06:42:47  leigh
 Doco cleanup.

 Revision 1.6  2000/07/22 00:34:05  leigh
 Minor doco and typing cleanups.

 Revision 1.5  2000/05/13 17:19:10  leigh
 stricter typing

 Revision 1.4  2000/04/22 20:10:24  leigh
 user defaults standardised to MK prefix

 Revision 1.3  2000/04/07 22:45:03  leigh
 Cleaned up defaults usage, removed redundant DSP output assignments (which are better covered using the IOKit).

 Revision 1.2  1999/07/29 01:25:59  leigh
 Added Win32 compatibility, CVS logs, SBs changes

 09/22/89/daj - Made back-hash optional in the interest of saving space.
 Flushed _MKNameTableAddGlobalNameNoCopy() in light of the
 decision to make name table bits (e.g. _MK_NOFREESTRINGBIT)
 globally defined.
 Flushed _MKNameTableAddNameNoCopy() and added a copyIt
 parameter to _MKNameTableAddName().
 10/06/89/daj - Changed to use hashtable.h version of table.
 12/03/89/daj - Added seed and ranSeed to initTokens list.
 03/05/90/daj - Added check for null name and nil object in public functions.
 Added conversion of name in MKNameObject to legal scorefile
 name and added private global function _MKSymbolize().
 03/06/90/daj - Added _MK_repeat to keyword list.
 04/21/90/daj - Removed unused auto var.
 10/02/94/daj - Added MKTrace defaults var
 ??/??/98/sb  - OpenStep conversion
 04/21/99/lms - overhaul for NSDictionary operation for portability and clarity
 */

#import <Foundation/NSString.h>
#import <Foundation/NSUserDefaults.h>
#import "_musickit.h"
#import "_MKNameTable.h"
#import "TuningSystemPrivate.h"
#import "MKTuningSystem.h"
#import "MKNote.h"
#import "_ParName.h"
#import "_ScorefileVar.h"

#define MASKBITS (_MK_NOFREESTRINGBIT | _MK_AUTOIMPORTBIT | _MK_BACKHASHBIT)
#define TYPEMASK(_x) (_x & (0xffff & ~(MASKBITS)))
// Dear WinNT doesn't know about PI, stolen from MacOSX-Servers math.h definition
#ifndef M_PI
#define M_PI            3.14159265358979323846  /* pi */
#endif

@implementation _MKNameTable

- (id) initWithCapacity: (unsigned) capacity;
{
  self = [super init];
  if (self != nil) {
  // NSObjectMapKeyCallBacks are objects which will be retained/released (all our keys
  // are NSStrings, so I'm happy with that)
  // NSNonRetainedObjectMapValueCallBacks are objects, but will never be retained or
  // released. This means that if the objects in question are ever dealloced, they MUST
  // call MKRemoveObjectName() in their dealloc method, so the map tables don't hold
  // dangling references.
    symbols    = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks,capacity); 
    types      = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks,capacity);
  }
  return self;
}

- (void) dealloc
{
  if (symbols != NULL) {
    NSFreeMapTable(symbols);
    symbols = NULL;
  }
  if (types != NULL) {
    NSFreeMapTable(types);
    types = NULL;
  }
  [super dealloc];
}

static void importAutoGlobals(_MKNameTable *globalTable,_MKNameTable *localTable)
/* Adds all the 'auto-import' symbols from globalTable to localTable. The
strings aren't copied. The type is set to be global.

'auto-import' symbols are all those that are not of type
MK_envelope, MK_waveTable or MK_object. (Actually, it's anything
                                         without the AUTOIMPORT bit on.) */
{
//  NSEnumerator *enumerator = [globalTable->symbols keyEnumerator];
  NSMapEnumerator enumerator = NSEnumerateMapTable(globalTable->symbols);
  id name;
  id obj;
  unsigned short type;

//  while ((name = [enumerator nextObject])) {
  while (NSNextMapEnumeratorPair(&enumerator, (void**)&name, (void**)&obj)) {
//    obj = [globalTable->symbols objectForKey: name];
    type = [(id)NSMapGet(globalTable->types, name) unsignedShortValue];
    if (type & _MK_AUTOIMPORTBIT)
      _MKNameTableAddName(localTable, name, nil, obj, type | _MK_NOFREESTRINGBIT, NO);
  }
  NSEndMapTableEnumeration(&enumerator);
}

_MKNameTable *_MKNameTableAddName(_MKNameTable *table, NSString *theName, id theOwner,
                                  id theObject, unsigned short theType, BOOL copyIt)
/*
 * Adds the object theObject in the table, with name theName and owner
 * theOwner. If there is already an entry for this name and owner does
 * nothing and returns nil. TheName is not copied unless copyIt is true.
 * Nowdays we ignore owner (which was nil anyway) and copyIt.
 * theType uses bits for freeing strings and backhashing which are redundant.
 * It uses the autoimport bit which may need to be used.
 * It should be able to be an instance var in theObject
 */
{
  if (!copyIt)
    theType |= _MK_NOFREESTRINGBIT;
//  [table->types setObject: [NSNumber numberWithUnsignedShort: theType] forKey: theName];
//  [table->symbols setObject: theObject forKey: theName];

  NSMapInsert(table->types, theName, [[NSNumber numberWithUnsignedShort: theType] retain] );
  NSMapInsert(table->symbols, theName, theObject);
  return table;
}

id _MKNameTableGetObjectForName(_MKNameTable *table,NSString *theName,id theOwner,
                                unsigned short *typeP)
/*
 * If there is an object with this name and owner it is returned, otherwise
 * nil is returned.
 */
{
  id foundObject = NSMapGet(table->symbols, theName);
  id foundType;

  if(foundObject != nil) {
    foundType = NSMapGet(table->types, theName);
    *typeP = TYPEMASK([foundType unsignedShortValue]); /* Clear bits */
    return foundObject;
  }
  else {
    *typeP = 0;
    return nil;
  }
}

NSString * _MKNameTableGetObjectName(_MKNameTable *table,id theObject,id *theOwner)
/*
 * If theObject has been entered in the table before, this method returns
 * its name and sets theOwner to its owner (nil). Otherwise nil is returned.
 */
{
  NSMapEnumerator e = NSEnumerateMapTable(table->symbols);
  id obj,key;
  NSString* firstFoundName = nil;
  while (NSNextMapEnumeratorPair(&e, (void **)&key, (void **)&obj)) {
    if (obj == theObject) { // pointer equality, since the maptable does not copy objects
      firstFoundName = key;
      break;
    }
  }
  NSEndMapTableEnumeration(&e);
  
  if (firstFoundName) {
    *theOwner = nil; // never used anyway
    return [[firstFoundName retain] autorelease];
  }
  else
    return nil;
}

#if 0 /* therefore not updated to NSMapTable usage */
static _MKNameTable *_MKNameTableRemoveName(_MKNameTable *table,NSString *theName,id theOwner)
/*
 * Removes the entry associated to (theName x theOwner) if any.
 */
{
  nameRecord symbol;
  nameRecord *symbolRec1,*symbolRec2;
  symbol.name = theName;
  symbol.owner = theOwner;
  symbolRec1 = NSHashRemove(table->hTab, &symbol);
  if (symbolRec1)
    symbolRec2 = NSHashRemove(table->bTab, symbolRec1);
  else return NULL;
  giveSymbol(symbolRec1);
  return table;
}
#endif

_MKNameTable *_MKNameTableRemoveObject(_MKNameTable *table,id theObject)
/*
 * Removes theObject from the table.
 * Find the key, then remove the symbol and type entries.
 */
{
//  NSArray *allFoundNames = [table->symbols allKeysForObject: theObject];
  NSMapEnumerator e = NSEnumerateMapTable(table->symbols);
  id obj,key;
  NSString* firstFoundName = nil;
  while (NSNextMapEnumeratorPair(&e, (void **)&key, (void **)&obj)) {
    if (obj == theObject) { // pointer equality, since the maptable does not copy objects
      firstFoundName = key;
      break;
    }
  }
  NSEndMapTableEnumeration(&e);

  if (firstFoundName) {
    NSMapRemove(table->symbols,firstFoundName);
    NSMapRemove(table->types,firstFoundName);
    return table;
  }
  else
    return nil;
}


/* Routines to check and convert to C symbols for writing to score files. */

#define isIllegalFirstCChar(_c) (!isalpha(*sym) && (*sym != '_'))
#define isIllegalCChar(_c) (!isalnum(*sym) && (*sym != '_'))

static BOOL isCSym(const register char *sym)
{
  if (isIllegalFirstCChar(*sym))
    return NO;
  while (*++sym)
    if (isIllegalCChar(*sym))
      return NO;
  return YES;
}

static void convertToCSym(const register char *sym,register char *newSym)
/* newSym is assumed to be allocated to be at least the length of sym.
Returns newSym. */
{
  *newSym++ = (isIllegalFirstCChar(*sym)) ? '_' : *sym;
  while (*++sym)
    *newSym++ = (isIllegalCChar(*sym)) ? '_' : *sym;
  *newSym = '\0';
}

NSString *_MKSymbolize(NSString *sym,BOOL *wasChanged)
/* Converts sym to new symbol, returns the new symbol (malloced),and
sets *wasChanged to YES. If sym is already a legal symbol, does not malloc,
returns sym, and sets *wasChagned to NO. */
{
  char     *newSym = NULL;
  NSString *result = nil;
  if (sym == nil) { *wasChanged = NO; return sym; }

  if (isCSym([sym cString])) { /* DAJ. Jan 27, 1996. Added null check */
    *wasChanged = NO;
    return sym;
  }
  _MK_MALLOC(newSym,char,[sym cStringLength] + 1);
  convertToCSym([sym cString],newSym);
  //    *wasChanged = NO;
  *wasChanged = YES; /* DAJ -- Jan 27, 96. Plugged leak */
  result = [[NSString alloc] initWithCString: newSym];
  free(newSym);
  newSym = NULL;
  return result;
}


/* Higher level interface and specific Music Kit use of name tables.  */

/* We keep two name tables, one for parsing (private, flat)
and one for writing (public, hierarchical). There are also private flat
local tables used for parsing. */

static _MKNameTable *globalParseNameTable;
static _MKNameTable *mkNameTable = nil;

void _MKPrintGlobalNameTables()
{
  NSLog(@"globalParseNameTable symbols:");
  NSLog(NSStringFromMapTable(globalParseNameTable->symbols));
  NSLog(@"globalParseNameTable types:");
  NSLog(NSStringFromMapTable(globalParseNameTable->types));
  NSLog(@"mkNameTable symbols:");
  NSLog(NSStringFromMapTable(mkNameTable->symbols));
  NSLog(@"mkNameTable types:");
  NSLog(NSStringFromMapTable(mkNameTable->types));
}

id MKRemoveObjectName(id object)
/*
 * Removes theObject from the table. Returns nil.
 */
{
  if (!mkNameTable)
    _MKCheckInit();
  _MKNameTableRemoveObject(mkNameTable,object);
  return nil;
}

BOOL MKNameObject(NSString * nameStr,id object)
/*
 * Adds the object theObject in the table, with name theName.
 * If the object is already named, does
 * nothing and returns NO. Otherwise returns YES. Note that the name is copied.
 */
{
  /* Always sets BACKHASH bit. */
  BOOL wasChanged;
  BOOL rtnVal;
  NSString * name;
  if (!mkNameTable)
    _MKCheckInit();
  if (nameStr == nil) return NO;
  if (![nameStr length]) /* Added check for !*name - DAJ 1/28/96 */
    return NO;

  name = _MKSymbolize(nameStr ,&wasChanged); /* Convert to valid sf name */
  rtnVal = (_MKNameTableAddName(mkNameTable,name,object,object,_MK_BACKHASHBIT,YES) != NULL);
  if (wasChanged)
    [name autorelease];
  return rtnVal;
}

NSString *MKGetObjectName(id object)
/*
 * Returns object name if any. If object is not found, returns nil. The name
 * is not copied and should not be freed or altered by caller.
 */
{
  id owner;
  if (!mkNameTable || !object)
    return nil;
  return _MKNameTableGetObjectName(mkNameTable,object,&owner);
}

#if 0
static id MKGetNamedObject(NSString *name)
/* Returns the first object found in the name table, with the given name.
Note that the name is not necessarily unique in the table; there may
be more than one object with the same name.
*/
{
  if (!mkNameTable || !name)
    return nil;
  return _MKNameTableGetFirstObjectForName(mkNameTable,name);
}
#endif

NSString *_MKGetGlobalName(id object)
/*
 * Returns object name if any. If object is not found, returns NULL. The name
 * is not copied and should not be freed or altered by caller.
 */
{
  id owner;
  if (!globalParseNameTable)
    return nil;
  return _MKNameTableGetObjectName(globalParseNameTable,object,&owner);
}

void _MKNameGlobal(NSString * name,id dataObj,unsigned short type,BOOL autoImport, BOOL copyIt)
/* Copies name */
{
  if (!globalParseNameTable)
    _MKCheckInit();
  if (autoImport)
    type |= _MK_AUTOIMPORTBIT;
  _MKNameTableAddName(globalParseNameTable,name,nil,dataObj,type,copyIt);
}

id _MKGetNamedGlobal(NSString * name,unsigned short *typeP)
{
  if (!globalParseNameTable)
    return nil;
  return _MKNameTableGetObjectForName(globalParseNameTable,name,nil,typeP);
}

#if 0

BOOL MKAddGlobalScorefileObject(id object,NSString *name)
/*
 * Adds the object theObject in the table, referenced in the scorefile
 * with the name specified. The name is copied.
 * If there is already a global scorefile object
 * with that name, does nothing and returns NO. Otherwise returns YES.
 * The object does not become visible to scorefiles unless they explicitly
 * do a call of getGlobal.
 * The type of the object in the scorefile is determined as follows:
 * * If object isKindOf:[MKWaveTable class], then the type is MK_waveTable.
 * * If object isKindOf:[MKEnvelope class], then the type is MK_envelope.
 * * Otherwise, the type is MK_object.
 */
{
  unsigned short type;
  if (!object || !name)
    return NO;
  if (![name length]) return NO;
  type = ([object isKindOfClass:[MKEnvelope class]]) ? MK_envelope :
    ([object isKindOfClass:[MKWaveTable class]]) ? MK_waveTable : MK_object;
  if (!globalParseNameTable)
    _MKCheckInit();
  _MKNameTableAddName(globalParseNameTable,name,nil,object, type | _MK_BACKHASHBIT,YES);
  return YES;
}

id MKGetGlobalScorefileObject(NSString *name)
/* Returns the global scorefile object with the given name. The object may
be either one that was added with MKAddGlobalScorefileObject or it
may be one that was added by the scorefile itself using "putGlobal".
Objects accessable to the application are those of type
MK_envelope, MK_waveTable and MK_object. An attempt to return some other
object will return nil.
Note that the name is not necessarily registered with the Music Kit
name table.
*/
{
  unsigned short typeP;
  id obj;
  if (!name)
    return nil;
  obj = _MKGetNamedGlobal(name,&typeP);
  switch (typeP) {
    case MK_envelope:
    case MK_waveTable:
    case MK_object:
      return obj;
    default:
      return nil;
  }
}

#endif
/* The following is a list of the key words recognized by the scorefile
parser. */

static const int keyWordsArr[] = {
  /* note types */
  MK_noteDur,MK_mute,MK_noteOn,MK_noteOff,MK_noteUpdate,
  /* MKMidi pars */
  MK_resetControllers,MK_localControlModeOn,MK_localControlModeOff,
  MK_allNotesOff,MK_omniModeOff,MK_omniModeOn,MK_monoMode,MK_polyMode,
  MK_sysClock,MK_sysStart,MK_sysContinue,MK_sysStop,MK_sysActiveSensing,
  MK_sysReset,
  /* Other keywords */
  _MK_part,_MK_doubleVarDecl,_MK_stringVarDecl,_MK_tune,
  _MK_intVarDecl,_MK_to,_MK_begin,_MK_end,_MK_include,_MK_comment,
  _MK_endComment,_MK_print,_MK_time,_MK_dB,_MK_ran,
  _MK_envelopeDecl,_MK_waveTableDecl,_MK_objectDecl,_MK_noteTagRange,
  _MK_envVarDecl,_MK_waveVarDecl,_MK_varDecl,_MK_objVarDecl,_MK_info,
  _MK_putGlobal,_MK_getGlobal,_MK_seed,_MK_ranSeed,_MK_repeat,
  _MK_if,_MK_else,_MK_while,_MK_do
};

/* The following define some assumed defaults used as a guess at Set sizes.
All such Sets are expandable, however. */

#define NUMKEYWORDS (sizeof(keyWordsArr)/sizeof(int))
#define NUMOCTAVES (128/12)
#define NUMPITCHVARS (NUMOCTAVES * (9 + 12)) /* 9 enharmnonic equivalents */
#define NUMKEYVARS (NUMPITCHVARS)
#define NUMOTHERMUSICKITVARS 9 /* Other than KEYVARS and PITCHVARS */
#define NUMMUSICKITVARS (NUMKEYVARS + NUMPITCHVARS + NUMOTHERMUSICKITVARS)
#define NAPPVARSGUESS 15 /* Per file. (This includes parts and envelopes)  */
#define NFILESGUESS 2 /* Num scoreFiles being read at once or sequentially. */
#define GLOBALTABLESIZE (NUMMUSICKITVARS)
#define GLOBALTABLEBACKHASHSIZE (BACKHASHSIZE)
#define LOCALTABLESIZE (NAPPVARSGUESS + GLOBALTABLESIZE)
#define LOCALTABLEBACKHASHSIZE (BACKHASHSIZE)

/* Re. _MK_NOFREESTRINGBIT below:
Actually, this is not needed, since we never free the elements of the
global table. But I left it in anyway, to highlight that the string is
in the text segment and that horrible things will happen if it's freed */

static id addReadOnlyVar(NSString * name,int val)
{
  /* Add a read-only variable to the global parse table. */
  _ScorefileVar *rtnVal;
  _MKNameGlobal(name,rtnVal = _MKNewScorefileVar(_MKNewIntPar(val,MK_noPar),name,NO,YES),
                _MK_typedVar | _MK_NOFREESTRINGBIT,YES,NO);
  return rtnVal;
}

static void initKeyWords()
{
    /* Init the symbol table used to store key words for score file parsing. */
    static BOOL initialised = NO;
    unsigned int i;
    int tok;
    
    if (initialised)
	return;
    addReadOnlyVar(@"NO",0);
    addReadOnlyVar(@"YES",1);
    _MKNameGlobal(@"PI", _MKNewScorefileVar(_MKNewDoublePar(M_PI,MK_noPar), @"PI", NO, YES),
		  (unsigned short)_MK_typedVar | _MK_NOFREESTRINGBIT,YES,NO);
    for (i=0; i<NUMKEYWORDS; i++) {
	tok = (int)(keyWordsArr[i]);
	_MKNameGlobal([NSString stringWithCString:_MKTokName(tok)],@"",
	       (unsigned short)tok | _MK_NOFREESTRINGBIT,YES,NO);
    }
    initialised = YES;
}

/* set up defaults which will apply to each app linked to the MK framework. */
void _MKCheckInit(void)
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *MKDefaults;
    
    if (globalParseNameTable)  /* Been here? */
	return;
    MKDefaults = [[NSDictionary dictionaryWithObjectsAndKeys:
	@"", @"MKTrace",
#if 0  // disabled as it is becoming redundant as we move DSP to native CPU
	@"", @"MKDSPSerialPortDevice0",
	@"", @"MKDSPSerialPortDevice1",
	@"", @"MKDSPSerialPortDevice2",
	@"", @"MKDSPSerialPortDevice3",
	@"", @"MKDSPSerialPortDevice4",
	@"", @"MKDSPSerialPortDevice5",
	@"", @"MKDSPSerialPortDevice6",
	@"", @"MKDSPSerialPortDevice7",
	@"", @"MKDSPSerialPortDevice8",
	@"", @"MKDSPSerialPortDevice9",
	@"", @"MKDSPSerialPortDevice10",
	@"", @"MKDSPSerialPortDevice11",
	@"", @"MKDSPSerialPortDevice12",
	@"", @"MKDSPSerialPortDevice13",
	@"", @"MKDSPSerialPortDevice14",
	@"", @"MKDSPSerialPortDevice15",
#endif
#if i386 && defined(__NeXT__)
	@"SSI", @"MKOrchestraSoundOut",   /* One of "Host", "SSI", "IRQA", "IRQB" */
#else
	@"Host", @"MKOrchestraSoundOut",
#endif
	NULL,NULL] retain];
    
    [defaults registerDefaults: MKDefaults]; //stick these in the temporary area that is searched last.
    
    MKSetTrace([defaults integerForKey: @"MKTrace"]);
    
    /*sb: I don't think we need to register anything here. */
    MKSetErrorStream(nil);
    /* We don't try and use the Appkit error mechanism. It's not well-suited to real-time. */
    //  NXRegisterErrorReporter( MK_ERRORBASE, MK_ERRORBASE+1000,_MKWriteError);
    globalParseNameTable = [[_MKNameTable alloc] initWithCapacity: GLOBALTABLESIZE];
    mkNameTable = [[_MKNameTable alloc] initWithCapacity: 0];
    [[[MKNote alloc] init] release]; /* Force initialization. Must be after table creation.*/
}

// TODO Needs NSDictionary
_MKNameTable *_MKNewScorefileParseTable(void)
{
    // Initialize a local symbol table for a new score file to be parsed.
    // Global symbols are not included here.
    _MKNameTable *localTable = [[_MKNameTable alloc] initWithCapacity: LOCALTABLESIZE];
    initKeyWords();     /* Add key words to global symbol table. */
    importAutoGlobals(globalParseNameTable,localTable);
    return localTable;
}

void _MKFreeScorefileTable(_MKNameTable *aTable)
{
  [aTable release];
}

NSString *_MKUniqueName(NSString *name,_MKNameTable *table,id anObject,id *hashObj)
/* Name is assumed malloced. anObject may be nil. This routine
makes sure that name is not in the table. If it is in the table,
a new name of the form <oldName><int> is generated. */
/*sb: either the original NSString name is returned, or a new, autoreleased string
* is returned.
*/
{
#   define FIRSTDIGIT 0
  int i;
  NSString *newName;
  //    int nDigits = 1, nextPower = 10;
  //    int newSize = strlen(name) + nDigits;
  unsigned short typeP;
  /*sb: added this to here to do initial check for un-suffixed name */
  *hashObj = _MKNameTableGetObjectForName(table,name,nil,&typeP);
  /* Name unused or we found it? */
  if ((!*hashObj) || (*hashObj == anObject))
    return name;

  //    _MK_REALLOC(name,char,newSize+1);     /* Now expand (1 for NULL) */
  for (i = FIRSTDIGIT;  ; i++) {
    //	if (i >= nextPower) {                 /* Make more room */
    //	    newSize++;
    //	    _MK_REALLOC(name,char,newSize+1); /* 1 for NULL */
    //	    nextPower *= 10;
    //	    nDigits++;
    //	}
    //	sprintf(&(name[newSize - nDigits]),"%d",i);
    newName = [NSString stringWithFormat:@"%@%d",name,i];
    *hashObj = _MKNameTableGetObjectForName(table,newName,nil,&typeP);
    /* Name unused or we found it? */
    if ((!*hashObj) || (*hashObj == anObject))
      return newName;
  }
}

#if 0
char *MKUniqueName(NSString *name,id anObject)
/* name must be a valid malloc'ed string.
* Checks to see if there is an object (other than 'anObject')
* in the Music Kit name table with the specified name.  If so,
* reallocs and returns a name of the form <oldName><int> that
* is not used by any object in the table.
* If name is not in the table, or anObject is already named
* with the given name, returns name.
* anObject may be nil, in which case a name is generated if
* and only if name is already present in the table.
*
* Example of use:
*
* char *s = malloc(10);
* sprintf(s,"hello");
* MKNameObject(MKUniqueName(s),myObject);
* sprintf(s,"hello");
* // Here, myOtherObject will get the name "hello1"
* MKNameObject(MKUniqueName(s),myOtherObject);
* free(s);
*/
{
  unsigned short typeP;
  id hashObj;
  /* First see if it's already there */
  NSString *s;
  if (anObject)
    s = MKGetObjectName(anObject);
  if (s != nil)
    if ([s isEqualToString:name])
      return name;
#if 0
  if (s && !strcmp(s,name))  /* anObject is already named 'name' */
    return name;
#endif
  hashObj = _MKNameTableGetObjectForName(mkNameTable,name,nil,&typeP);
  if (!*hashObj)             /* 'name' isn't in table */
    return name;
  return _MKUniqueName(name,mkNameTable,anObject,&hashObj);
}
#endif

@end