/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
#include <dirent.h>
#include <libgen.h>
#include <errno.h>
#include "parser.h"
#include "errlog.h"
static int dofiles(const Translator_info *);
static int read_spec(const Translator_info *, char *);
static int Curlineno;
/*
* frontend entry point
* returns the number of errors encountered
*/
int
{
if (keywordlist == NULL) {
return (1);
}
++i;
};
}
switch (retval) {
case XLATOR_SKIP:
retval = 0;
break;
case XLATOR_NONFATAL:
++errors;
retval = 0;
break;
case XLATOR_SUCCESS:
++errors;
retval = 0;
break;
default:
"Error: Invalid return code from xlator_startlib()\n");
exit(1);
}
++errors;
return (errors);
}
/*
* dofiles(const Translator_info *T_info);
* iterate through files specified in the command line and process
* them one by one
* requires spec files to have a ".spec" suffix
* returns the number of errors;
*/
static int
{
if ((flen <= 5) ||
"Error: File specified does not have the "
++errors;
continue;
};
}
return (errors);
}
/*
* read_spec -
* Given a filename, this function will reads the spec file to
* recognize keywords which it passes along with the corresponding
* value to the back-end translator to process. The following
* back-end interfaces are called:
* xlator_startfile
* xlator_start_if
* xlator_take_kvpair
* xlator_end_if
* xlator_endfile
*/
static int
{
int extends_err = 0;
switch (retval) {
case XLATOR_SKIP:
return (errors);
case XLATOR_NONFATAL:
++errors;
return (errors);
case XLATOR_SUCCESS:
break;
default:
"Error: Invalid return code from xlator_startfile()\n");
++errors;
return (errors);
};
/* file processing */
++errors;
return (errors);
}
meta_info.mi_line_number = 0;
continue;
}
if (p == NULL) {
"Error: Unable to allocate memory for "
"value: %d\n", errno);
}
value = p;
switch (ki) {
case XLATOR_KW_FUNC: /* Function keyword */
case XLATOR_KW_DATA: /* Data keyword */
meta_info.mi_extended = 0;
switch (retval) {
case XLATOR_FATAL: /* FATAL ERROR */
"Error in xlator_start_if: ");
}
++errors;
return (errors);
case XLATOR_NONFATAL: /* NON-FATAL ERROR */
"Error in xlator_start_if\n");
++errors;
start_if_fail = 1;
break;
case XLATOR_SUCCESS: /* OK */
start_if_fail = 0;
switch (extends_err) {
case -1: /* Error */
"Error occurred while "
"checking for extends clause\n",
++errors;
/*FALLTHRU*/
case 0: /* No Extends */
break;
case 1: /* Extends */
if (extends_err) {
errors += extends_err;
}
break;
default: /* Programmer Error */
"Error: invalid return from "
"check4extends %d\n", extends_err);
}
break;
case XLATOR_SKIP: /* SKIP */
"interface %s\n", value);
skip_if = 1;
start_if_fail = 0;
break;
default:
/* Invalid Return */
"Error: Invalid return code "
"from xlator_start_if (): %d\n", retval);
}
break;
case XLATOR_KW_END: /* END keyword */
if (start_if_fail == 0 && skip_if == 0) {
if (retval)
++errors;
}
skip_if = 0;
break;
case XLATOR_KW_NOTFOUND:
key);
break;
default:
if (skip_if == 0 && start_if_fail == 0) {
if (retval) {
"xlator_take_kvpair\n");
++errors;
}
}
}
}
++errors;
}
free(p);
return (errors);
}
/*
* interesting_keyword(char **keywordlist, const char *key) {
* returns the token associated with key if key is found in keywordlist
* returns XLATOR_KW_NOTFOUND if key is NOT found in keywordlist
* "Function" and "End" are always interesting, return XLATOR_KW_FUNC
* and XLATOR_KW_DATA respectively;
* "End" is always interesting, return XLATOR_KW_END;
*
*/
int
{
int i = 0;
return (XLATOR_KW_DATA);
}
return (XLATOR_KW_FUNC);
}
return (XLATOR_KW_END);
return (keywordlist[i].token);
++i;
}
return (XLATOR_KW_NOTFOUND);
}
/*
* line_to_buf(char *dest, const char *src) {
* appends src to dest, dynamically increasing the size of dest.
* replaces the trailing '\' continuation character with a space.
*
* if src is continuation of dest, dest != NULL, and
* the last character in dest before the newline must be a `\'
* if src is not continuation of dest, then dest must be NULL
*/
char *
{
int dlen;
/* We're being called for the first time */
"Error: Unable to allocate memory for dest\n");
}
return (dest);
}
"Error: Unable to allocate memory for dest\n");
}
if (dlen > 1) {
/*
* remove continuation character
* we replace the '\' from the previous line with a space
*/
}
}
/* join the two strings */
return (dest);
}
/*
* non_empty(const char *str)
* assumes str is non null
* checks if str is a non empty string
* returns 1 if string contains non whitespace
* returns 0 if string contains only whitespace
*/
int
{
while (*str != '\0') {
return (1);
++str;
};
return (0);
}
/*
* split(const char *line, char *key, char *value);
* splits the line into keyword (key) and value pair
*/
void
{
char *p;
p = (char *)line;
/* skip leading whitespace */
while (isspace(*p)&& *p != '\0')
++p;
/* copy keyword from line into key */
while (!isspace(*p) && *p != '\0')
*key++ = *p++;
*key = '\0';
/* skip whitespace */
while (isspace(*p) && *p != '\0')
p++;
}
/*
* check4extends(char *filename, char *value, int arch, FILE *fp)
* if no arch keyword is found or there is a MATCHING arch keyword
* returns 1 if value is of the form "data|function name extends"
* -1 for error
* 0 no other keyword after the function name
* else
* return 0
*
* filename is used only for error reporting
*/
int
{
int n;
return (1);
} else {
if (*extends != '\0') {
"Trailing garbage after function name\n",
return (-1);
}
}
}
return (0);
}
/*
* remcomment (char *buf)
* replace comments with single whitespace
*/
/* XXX: There is currently no way to escape a comment character */
void
{
char *p;
if (p) {
*p = ' ';
*(p+1) = '\0';
}
}
/*
* arch_strtoi()
*
* input: string
* return: XLATOR_I386 if string == ARCH_I386
* XLATOR_SPARC if string == ARCH_SPARC
* XLATOR_SPARCV9 if string == ARCH_SPARCV9
* XLATOR_IA64 if string == ARCH_IA64
* XLATOR_AMD64 if string == ARCH_AMD64
* XLATOR_ALLARCH if string == ARCH_ALL
* 0 if outside the known set {i386, sparc, sparcv9, ia64, amd64}.
*/
int
{
return (XLATOR_I386);
return (XLATOR_SPARC);
return (XLATOR_SPARCV9);
return (XLATOR_IA64);
return (XLATOR_AMD64);
return (XLATOR_ALLARCH);
} else {
"arch keyword with no value");
}
return (0);
}
int
{
int nlines = 0;
int len;
nlines++;
/* replace comments with single whitespace */
/* get complete line */
if (len > 1) {
/* handle continuation lines */
break;
}
nlines++;
}
} /* end of 'get complete line' */
}
return (nlines);
}