#  $NetBSD: platid.awk,v 1.1 2001/01/28 02:52:18 uch Exp $
#
#  Copyright (c) 1999
#          Shin Takemura and PocketBSD Project. All rights reserved.
# 
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#  3. All advertising materials mentioning features or use of this software
#     must display the following acknowledgement:
# 	This product includes software developed by the PocketBSD project
# 	and its contributors.
#  4. Neither the name of the project nor the names of its contributors
#     may be used to endorse or promote products derived from this software
#     without specific prior written permission.
# 
#  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.
# 

#
#  sub routines
#

function gen_header(file) {
  printf("/*\n") >> file
  printf(" *  Do not edit.\n") > file
  printf(" *  This file is automatically generated by platid.awk.\n") > file
  printf(" */\n") > file
}

function error() {
    printf("ERROR!\n") > stderr
    exit
}

function mode_check() {
    if (mode != MACH && mode != CPU) {
        printf("ERROR: invalid mode( = %d)\n", mode) > stderr
        exit
    }
}

function defname() {
    mode_check()

    #
    #  master header
    #
    enumerator[mode] += 1
    printf("#define PLATID_%s_%s%s_NUM\t%d\n",
           mode_name[mode], nm, saved_name, enumerator[mode]) > out_h
    printf("#define PLATID_%s_%s%s\t\\\n",
           mode_name[mode], nm, saved_name) > out_h
    printf("  ((PLATID_%s_%s%s_NUM << %s)",
           mode_name[mode], nm, saved_name, shifts[mode, nest]) > out_h
    if (nest) {
      printf("| \\\n    PLATID_%s", mode_name[mode]) > out_h
      for (i = 0; i < nest; i++) {
        printf("_%s", names[i]) > out_h
      }
    }
    printf(")\n") > out_h

    #
    #  mask header
    #
    printf("extern platid_t platid_mask_%s_%s%s;\n",
	   mode_name[mode], nm, saved_name) > out_mask_h
    printf("#ifdef PLATID_DEFINE_MASK_NICKNAME\n") > out_mask_h
    if (mode == CPU) {
        printf("#  define GENERIC_%s%s ((int)&platid_mask_%s_%s%s)\n",
	       nm, saved_name,
	       mode_name[mode], nm, saved_name) > out_mask_h
    } else {
        printf("#  define %s%s ((int)&platid_mask_%s_%s%s)\n",
	       nm, saved_name,
	       mode_name[mode], nm, saved_name) > out_mask_h
    }
    printf("#endif\n") > out_mask_h

    #
    #  mask holder
    #
    printf("platid_t platid_mask_%s_%s%s = {{\n",
	   mode_name[mode], nm, saved_name) > out_mask_c
    if (mode == CPU) {
        printf("\tPLATID_%s_%s%s,\n",
	       mode_name[mode], nm, saved_name) > out_mask_c
	printf("\tPLATID_WILD\n") > out_mask_c
    }
    if (mode == MACH) {
        if (saved_cpu != "") {
	    printf("\tPLATID_CPU_%s,\n", saved_cpu) > out_mask_c
        } else {
	    printf("\tPLATID_WILD,\n") > out_mask_c
	}
	printf("\tPLATID_%s_%s%s\n",
	       mode_name[mode], nm, saved_name) > out_mask_c

    }
    printf("}};\n") > out_mask_c

}

function flushname() {
    if ( saved_name != "" ) {
        defname()
    }
}

BEGIN {
  CPU = 1
  MACH = 2

  nest = 0
  nm = ""
  saved_name = ""
  mode = NA
  change_cpu = 0
  saved_cpu = ""

  mode_name[CPU] = "CPU"
  mode_name[MACH] = "MACH"

  shifts[CPU, 0] = "PLATID_CPU_ARCH_SHIFT"
  shifts[CPU, 1] = "PLATID_CPU_SERIES_SHIFT"
  shifts[CPU, 2] = "PLATID_CPU_MODEL_SHIFT"
  shifts[CPU, 3] = "PLATID_CPU_SUBMODEL_SHIFT"

  shifts[MACH, 0] = "PLATID_VENDOR_SHIFT"
  shifts[MACH, 1] = "PLATID_SERIES_SHIFT"
  shifts[MACH, 2] = "PLATID_MODEL_SHIFT"
  shifts[MACH, 3] = "PLATID_SUBMODEL_SHIFT"

  enumerator[CPU] = 0
  enumerator[MACH] = 0

  if (stderr == "") {
    stderr = "/dev/stderr"
  }
  if (out_h == "") {
    out_h = "platid_generated.h"
  }
  if (out_mask_h == "") {
    out_mask_h = "platid_mask.h"
  }
  if (out_mask_c == "") {
    out_mask_c = "platid_mask.c"
  }

  printf("files: %s %s %s\n", out_h, out_mask_h, out_mask_c) > stderr

  gen_header(out_h)
  gen_header(out_mask_h)
  gen_header(out_mask_c)
  printf("#include <machine/platid.h>\n") > out_mask_c
}

/^[ \t]*$/ {
  next
}
/\/\*/ {
  commentout = 1
  next
}
/\*\// {
  commentout = 0
  next
}
/:/{
  if (commentout) {
    next
  }
  if (nest != 0) {
    error()
  }
  if (saved_name == "CPU") {
    mode = CPU
  } else
  if (saved_name == "MACHINE") {
    mode = MACH
  } else {
    error()
  }
  saved_name = ""
  next
}
/=/{
  if (commentout) {
    next
  }
  if (saved_name == "CPU") {
    change_cpu = 1
  } else {
    error()
  }
  saved_name = ""
  next
}
/\?/{
  if (commentout) {
    next
  }
  if (change_cpu) {
    saved_cpu = ""
    change_cpu = 0
  } else {
    error()
  }
  next
}
/{/{
  if (commentout) {
    next
  }
  flushname()

  nms[nest] = nm
  enums[nest] = enumerator[mode]
  names[nest] = saved_name
  cpus[nest] = saved_cpu

  if (nest == 2) {
  } else
  if (nest == 0) {
    nm = sprintf("%s_", saved_name)
  } else {
    nm = sprintf("%s%s_", nm, saved_name)
  }
  nest++

  mode_check()
  enumerator[mode] = 0
  saved_name = ""

  next
}
/}/{
  if (commentout) {
    next
  }
  flushname()
  saved_name = ""
  --nest
  nm = nms[nest]
  enumerator[mode] = enums[nest]
  saved_cpu = cpus[nest]
  next
}
/[a-zA-Z0-9]*/{
  if (commentout) {
    next
  }
  if (change_cpu) {
    saved_cpu = $1
    change_cpu = 0
    next
  }

  flushname()
  saved_name = toupper($1)
  next
}
{
   printf("SYNTAX ERROR: %s\n", $0) > stderr
}
