/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
#import <stdio.h>
#import <ctype.h>
#import	<libc.h>
#import <ansi/string.h>

#import	"genassym.h"

#define	NAME_LEN	30

char *progname;

unsigned bit_num(char *reg_type, char *field, unsigned bits)
{
	unsigned bit;
	unsigned mask;
	
	for (bit = 0, mask = 0x1;
	  (mask & bits) == 0 && mask;
	  mask <<= 1, bit += 1)
		continue;
	if (mask)
		return bit;
	fprintf(stderr, "%s: Bad BIT_POS for %s.%s\n", progname,
	  reg_type, field);
	exit(1);
}

unsigned field_width(char *reg_type, char *field, unsigned bits)
{
	unsigned width;

	while (bits && (bits & 0x1) == 0)
		bits >>= 1;
	for (width = 0; (bits & 0x1) == 1; bits >>= 1, width += 1)
		continue;
	if (bits == 0 && width)
		return width;
	fprintf(stderr, "%s: Bad BIT_FIELD for %s.%s\n", progname,
	  reg_type, field);
	exit(1);
}

unsigned log2(unsigned val, char *type)
{
	unsigned l2 = 0;

	if (val == 0) {
		fprintf(stderr, "log2: sizeof(%s) is zero!\n", type);
		exit(1);
	}
	while ((val & 0x1) == 0) {
		l2 += 1;
		val >>= 1;
	}
	if (val != 0x1) {
		fprintf(stderr, "log2: sizeof(%s) is not power of two!\n",
		  type);
		exit(1);
	}
	return l2;
}

const char *skip_white(const char *cp)
{
	while (*cp && isspace(*cp))
		cp += 1;
	return cp;
}

const char *strip_prefix(const char *cp, const char *prefix)
{
	int len;

	cp = skip_white(cp);
	len = strlen(prefix);
	if (strncmp(cp, prefix, len) == 0 && isspace(*(cp+len)))
		cp += len;
	return cp;
}

void
print_define(const char *prefix, const char *type_name, const char *field)
{
    const char *cp;
    int col = 0;
    
    printf("#define\t");
    if (prefix != NULL && *prefix != '\0') {
	printf("%s", prefix);
	col += strlen(prefix);
    }
    if (type_name != NULL && *type_name != '\0') {
	cp = strip_prefix(type_name, "struct");
	cp = strip_prefix(cp, "enum");
	cp = skip_white(cp);
	if (*cp != '\0' && col != 0) {
	    putchar('_');
	    col += 1;
	}
	for (; *cp != '\0'; cp++) {
	    if (isspace(*cp))
		break;
	    if (*cp == '*')
		break;
	    if (strncmp(cp, "_t", 2) == 0 && !isalnum(cp[2]))
		break;
	    putchar(isalpha(*cp) ? toupper(*cp) : *cp);
	    col += 1;
	    
	}
    }
    if (field != NULL && *field != '\0') {
	if (col != 0) {
	    putchar('_');
	    col++;
	}
	for (cp = field; *cp != 0; cp++) {
	    if (*cp == '.')
		putchar('_');
	    else if (*cp == '[')
		putchar('_');
	    else if (*cp == ']')
		continue;
	    else if (!isspace(*cp))
		putchar(isalpha(*cp) ? toupper(*cp) : *cp);
	    col++;
	}
    }
    if (col == 0) {
	fprintf(stderr, "%s: Bad call to print_define\n", progname);
	exit(1);
    }
    do {
	putchar(' ');
	col += 1;
    } while (col < NAME_LEN);
}

void print_dec(int val)
{
	printf("%d\n", val);
}

void print_hex(unsigned val)
{
	printf("%#010x\n", val);
}

void print_str(const char *str)
{
	printf("%s\n", str);
}

void comment(cmt_level_t level, const char *cmt)
{
	switch (level) {
	case MAJOR:
		printf("\n\n");
		printf("/*\n");
		printf(" * %s\n", cmt);
		printf(" */\n");
		break;
	case MINOR:
		printf("\n");
		printf("/* %s */\n", cmt);
		printf("\n");
		break;
	default:
		fprintf(stderr, "%s: Bad comment level\n", progname);
		exit(1);
	}
}

void main(int argc, char **argv)
{
	progname = argv[0];
	
	printf("/* assym.h -- generated by genassym */\n");
	printf("/* DON'T EDIT THIS -- change assymdefs.c */\n");
	
	assymdefs();
	
	exit(0);
}
