PDP-8-E-Simulator/Utilities/OctalFormatter.m
2018-05-26 15:52:10 +12:00

160 lines
4.6 KiB
Objective-C

/*
* PDP-8/E Simulator
*
* Copyright © 1994-2015 Bernhard Baehr
*
* OctalFormatter.m - Formatter for octal numbers
*
* This file is part of PDP-8/E Simulator.
*
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#import "OctalFormatter.h"
@implementation OctalFormatter
+ (OctalFormatter *) formatterWithBitMask:(unsigned)mask wildcardAllowed:(BOOL)withWildcard
{
return [[[OctalFormatter alloc] initWithBitMask:mask wildcardAllowed:withWildcard] autorelease];
}
- (OctalFormatter *) initWithBitMask:(unsigned)mask wildcardAllowed:(BOOL)withWildcard
{
if ((self = [super init])) {
wildcardAllowed = withWildcard;
bitMask = mask;
int digits = 0;
while (mask) {
digits++;
mask >>= 3;
}
outputFormat = [[NSString alloc] initWithFormat:@"%%%d.%do", digits, digits];
numberOfWords = 1;
}
return self;
}
- (void) setNumberOfWords:(unsigned)n
{
numberOfWords = n;
}
- (NSString *) stringForObjectValue:(id)value
{
unsigned i;
NSMutableString *string = nil;
if ([value isKindOfClass:[NSNumber class]])
string = [NSString stringWithFormat:outputFormat, [value intValue]];
else if ([value isKindOfClass:[NSArray class]]) {
unsigned count = [value count];
if (numberOfWords < count)
count = numberOfWords;
string = [NSMutableString stringWithCapacity:5 * count];
for (i = 0; i < count; i++) {
if (i > 0)
[string appendString:@" "];
[string appendFormat:outputFormat, [[value objectAtIndex:i] intValue]];
}
}
return string;
}
- (BOOL) getObjectValue:(id *)value forString:(NSString *)string errorDescription:(NSString **)error
/* For string without placeholder, value becomes a NSNumber (for numberOfWords == 1) or an
NSArray of NSNumbers (for numberOfWords > 1). For strings with placeholder, values becomes
an asencding sorted NSArray of NSNumbers (for numberOfWords == 1) or an NSArray of such NSArrays
(for numberOfWords > 1). */
{
char buf[128];
char *bp = buf;
NSMutableArray *values = [NSMutableArray arrayWithCapacity:numberOfWords];
if (! [string getCString:buf maxLength:(sizeof(buf) - 1) encoding:NSMacOSRomanStringEncoding]) {
if (error)
*error = [string canBeConvertedToEncoding:NSMacOSRomanStringEncoding] ?
NSLocalizedString(@"Input too long.", @"") :
NSLocalizedString(@"Input contains invalid characters.", @"");
return FALSE;
}
while (*bp == ' ')
bp++;
while (('0' <= *bp && *bp < '8') || (wildcardAllowed && *bp == '#')) {
unsigned val = 0;
unsigned pattern = 0;
while (('0' <= *bp && *bp < '8') || (wildcardAllowed && *bp == '#')) {
pattern <<= 3;
if ('0' <= *bp && *bp < '8')
val = val * 8 + (*bp - '0');
else {
val *= 8;
pattern |= 7;
}
bp++;
}
while (*bp == ' ')
bp++;
if ((val | pattern) & ~bitMask) {
if (error)
*error = [NSString stringWithFormat:NSLocalizedString(
@"The octal number is of range. The largest allowed number is %o.",
@""), bitMask];
return FALSE;
}
if (pattern) {
unsigned long mask = pattern;
NSMutableArray *patternValues = [NSMutableArray arrayWithCapacity:8];
do {
[patternValues insertObject:[NSNumber numberWithInt:val + pattern]
atIndex:0];
pattern = (pattern - 1) & mask;
} while (pattern != mask);
[values addObject:patternValues];
} else
[values addObject:[NSNumber numberWithInt:val]];
}
if (*bp || [values count] != numberOfWords) {
if (error)
*error = (numberOfWords == 1) ?
(wildcardAllowed ?
NSLocalizedString(
@"Invalid input. An octal number is expected. "
@"The wildcard character # is allowed.", @"") :
NSLocalizedString(
@"Invalid input. An octal number is expected.", @"")) :
[NSString stringWithFormat:wildcardAllowed ?
NSLocalizedString(
@"Invalid input. %d octal numbers are expected. "
@"The wildcard character # is allowed.", @"") :
NSLocalizedString(
@"Invalid input. %d octal numbers are expected.", @""),
numberOfWords];
return FALSE;
}
*value = (numberOfWords == 1) ? [values objectAtIndex:0] : values;
return TRUE;
}
@end