162306a36Sopenharmony_ci%{
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Sub-parser for macro invocation in the Aic7xxx SCSI
462306a36Sopenharmony_ci * Host adapter sequencer assembler.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (c) 2001 Adaptec Inc.
762306a36Sopenharmony_ci * All rights reserved.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
1062306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
1162306a36Sopenharmony_ci * are met:
1262306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
1362306a36Sopenharmony_ci *    notice, this list of conditions, and the following disclaimer,
1462306a36Sopenharmony_ci *    without modification.
1562306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1662306a36Sopenharmony_ci *    substantially similar to the "NO WARRANTY" disclaimer below
1762306a36Sopenharmony_ci *    ("Disclaimer") and any redistribution must be conditioned upon
1862306a36Sopenharmony_ci *    including a substantially similar Disclaimer requirement for further
1962306a36Sopenharmony_ci *    binary redistribution.
2062306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names
2162306a36Sopenharmony_ci *    of any contributors may be used to endorse or promote products derived
2262306a36Sopenharmony_ci *    from this software without specific prior written permission.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the
2562306a36Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free
2662306a36Sopenharmony_ci * Software Foundation.
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * NO WARRANTY
2962306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3062306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3162306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3262306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3362306a36Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3462306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3562306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3662306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3762306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3862306a36Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3962306a36Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES.
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_gram.y#5 $
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * $FreeBSD$
4462306a36Sopenharmony_ci */
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#include <sys/types.h>
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#include <inttypes.h>
4962306a36Sopenharmony_ci#include <regex.h>
5062306a36Sopenharmony_ci#include <stdio.h>
5162306a36Sopenharmony_ci#include <stdlib.h>
5262306a36Sopenharmony_ci#include <string.h>
5362306a36Sopenharmony_ci#include <sysexits.h>
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#include "../queue.h"
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#include "aicasm.h"
5862306a36Sopenharmony_ci#include "aicasm_symbol.h"
5962306a36Sopenharmony_ci#include "aicasm_insformat.h"
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic symbol_t *macro_symbol;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic void add_macro_arg(const char *argtext, int position);
6462306a36Sopenharmony_civoid mmerror(const char *string);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci%}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci%union {
6962306a36Sopenharmony_ci	int		value;
7062306a36Sopenharmony_ci	char		*str;
7162306a36Sopenharmony_ci	symbol_t	*sym;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci%token <str> T_ARG
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci%token <sym> T_SYMBOL
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci%type <value> macro_arglist
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci%%
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cimacrocall:
8462306a36Sopenharmony_ci	T_SYMBOL '('
8562306a36Sopenharmony_ci	{
8662306a36Sopenharmony_ci		macro_symbol = $1;
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci	macro_arglist ')'
8962306a36Sopenharmony_ci	{
9062306a36Sopenharmony_ci		if (macro_symbol->info.macroinfo->narg != $4) {
9162306a36Sopenharmony_ci			printf("Narg == %d", macro_symbol->info.macroinfo->narg);
9262306a36Sopenharmony_ci			stop("Too few arguments for macro invocation",
9362306a36Sopenharmony_ci			     EX_DATAERR);
9462306a36Sopenharmony_ci			/* NOTREACHED */
9562306a36Sopenharmony_ci		}
9662306a36Sopenharmony_ci		macro_symbol = NULL;
9762306a36Sopenharmony_ci		YYACCEPT;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cimacro_arglist:
10262306a36Sopenharmony_ci	{
10362306a36Sopenharmony_ci		/* Macros can take 0 arguments */
10462306a36Sopenharmony_ci		$$ = 0;
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci|	T_ARG
10762306a36Sopenharmony_ci	{
10862306a36Sopenharmony_ci		$$ = 1;
10962306a36Sopenharmony_ci		add_macro_arg($1, 1);
11062306a36Sopenharmony_ci	}
11162306a36Sopenharmony_ci|	macro_arglist ',' T_ARG
11262306a36Sopenharmony_ci	{
11362306a36Sopenharmony_ci		if ($1 == 0) {
11462306a36Sopenharmony_ci			stop("Comma without preceding argument in arg list",
11562306a36Sopenharmony_ci			     EX_DATAERR);
11662306a36Sopenharmony_ci			/* NOTREACHED */
11762306a36Sopenharmony_ci		}
11862306a36Sopenharmony_ci		$$ = $1 + 1;
11962306a36Sopenharmony_ci		add_macro_arg($3, $$);
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci%%
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic void
12662306a36Sopenharmony_ciadd_macro_arg(const char *argtext, int argnum)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	struct macro_arg *marg;
12962306a36Sopenharmony_ci	int i;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	if (macro_symbol == NULL || macro_symbol->type != MACRO) {
13262306a36Sopenharmony_ci		stop("Invalid current symbol for adding macro arg",
13362306a36Sopenharmony_ci		     EX_SOFTWARE);
13462306a36Sopenharmony_ci		/* NOTREACHED */
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci	/*
13762306a36Sopenharmony_ci	 * Macro Invocation.  Find the appropriate argument and fill
13862306a36Sopenharmony_ci	 * in the replace ment text for this call.
13962306a36Sopenharmony_ci	 */
14062306a36Sopenharmony_ci	i = 0;
14162306a36Sopenharmony_ci	STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
14262306a36Sopenharmony_ci		i++;
14362306a36Sopenharmony_ci		if (i == argnum)
14462306a36Sopenharmony_ci			break;
14562306a36Sopenharmony_ci	}
14662306a36Sopenharmony_ci	if (marg == NULL) {
14762306a36Sopenharmony_ci		stop("Too many arguments for macro invocation", EX_DATAERR);
14862306a36Sopenharmony_ci		/* NOTREACHED */
14962306a36Sopenharmony_ci	}
15062306a36Sopenharmony_ci	marg->replacement_text = strdup(argtext);
15162306a36Sopenharmony_ci	if (marg->replacement_text == NULL) {
15262306a36Sopenharmony_ci		stop("Unable to replicate replacement text", EX_SOFTWARE);
15362306a36Sopenharmony_ci		/* NOTREACHED */
15462306a36Sopenharmony_ci	}
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_civoid
15862306a36Sopenharmony_cimmerror(const char *string)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	stop(string, EX_DATAERR);
16162306a36Sopenharmony_ci}
162