Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2717 → Rev 2782

/tags/0.3.0/uspace/app/ash/tools/mksyntax.c
0,0 → 1,428
/* $NetBSD: mksyntax.c,v 1.23 2000/07/18 19:13:21 cgd Exp $ */
 
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
*
* 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 University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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.
*/
 
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
 
#ifndef lint
#if 0
static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
#else
static const char rcsid[] =
"$NetBSD: mksyntax.c,v 1.23 2000/07/18 19:13:21 cgd Exp $";
#endif
#endif /* not lint */
 
/*
* This program creates syntax.h and syntax.c.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "../parser.h"
 
 
struct synclass {
char *name;
char *comment;
};
 
/* Syntax classes */
struct synclass synclass[] = {
{ "CWORD", "character is nothing special" },
{ "CNL", "newline character" },
{ "CBACK", "a backslash character" },
{ "CSQUOTE", "single quote" },
{ "CDQUOTE", "double quote" },
{ "CENDQUOTE", "a terminating quote" },
{ "CBQUOTE", "backwards single quote" },
{ "CVAR", "a dollar sign" },
{ "CENDVAR", "a '}' character" },
{ "CLP", "a left paren in arithmetic" },
{ "CRP", "a right paren in arithmetic" },
{ "CEOF", "end of file" },
{ "CCTL", "like CWORD, except it must be escaped" },
{ "CSPCL", "these terminate a word" },
{ NULL, NULL }
};
 
 
/*
* Syntax classes for is_ functions. Warning: if you add new classes
* you may have to change the definition of the is_in_name macro.
*/
struct synclass is_entry[] = {
{ "ISDIGIT", "a digit" },
{ "ISUPPER", "an upper case letter" },
{ "ISLOWER", "a lower case letter" },
{ "ISUNDER", "an underscore" },
{ "ISSPECL", "the name of a special parameter" },
{ NULL, NULL }
};
 
static char writer[] = "\
/*\n\
* This file was generated by the mksyntax program.\n\
*/\n\
\n";
 
 
static FILE *cfile;
static FILE *hfile;
static char *syntax[513];
static int base;
static int size; /* number of values which a char variable can have */
static int nbits; /* number of bits in a character */
static int digit_contig;/* true if digits are contiguous */
 
static void filltable(char *);
static void init(void);
static void add(char *, char *);
static void print(char *);
static void output_type_macros(void);
static void digit_convert(void);
int main(int, char **);
 
int
main(argc, argv)
int argc;
char **argv;
{
#ifdef TARGET_CHAR
TARGET_CHAR c;
TARGET_CHAR d;
#else
char c;
char d;
#endif
int sign;
int i;
char buf[80];
int pos;
static char digit[] = "0123456789";
 
/* Create output files */
if ((cfile = fopen("syntax.c", "w")) == NULL) {
perror("syntax.c");
exit(2);
}
if ((hfile = fopen("syntax.h", "w")) == NULL) {
perror("syntax.h");
exit(2);
}
fputs(writer, hfile);
fputs(writer, cfile);
 
/* Determine the characteristics of chars. */
c = -1;
if (c <= 0)
sign = 1;
else
sign = 0;
for (nbits = 1 ; ; nbits++) {
d = (1 << nbits) - 1;
if (d == c)
break;
}
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
if (nbits > 9) {
fputs("Characters can't have more than 9 bits\n", stderr);
exit(2);
}
size = (1 << nbits) + 1;
base = 1;
if (sign)
base += 1 << (nbits - 1);
digit_contig = 1;
for (i = 0 ; i < 10 ; i++) {
if (digit[i] != '0' + i)
digit_contig = 0;
}
 
fputs("#include <sys/cdefs.h>\n", hfile);
fputs("#include <ctype.h>\n", hfile);
 
/* Generate the #define statements in the header file */
fputs("/* Syntax classes */\n", hfile);
for (i = 0 ; synclass[i].name ; i++) {
sprintf(buf, "#define %s %d", synclass[i].name, i);
fputs(buf, hfile);
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
putc('\t', hfile);
fprintf(hfile, "/* %s */\n", synclass[i].comment);
}
putc('\n', hfile);
fputs("/* Syntax classes for is_ functions */\n", hfile);
for (i = 0 ; is_entry[i].name ; i++) {
sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
fputs(buf, hfile);
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
putc('\t', hfile);
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
}
putc('\n', hfile);
fprintf(hfile, "#define SYNBASE %d\n", base);
fprintf(hfile, "#define PEOF %d\n\n", -base);
if (sign)
fprintf(hfile, "#define UPEOF %d\n\n", -base);
else
fprintf(hfile, "#define UPEOF ((unsigned char) %d)\n\n", -base);
putc('\n', hfile);
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
putc('\n', hfile);
output_type_macros(); /* is_digit, etc. */
putc('\n', hfile);
 
/* Generate the syntax tables. */
fputs("#include \"shell.h\"\n", cfile);
fputs("#include \"syntax.h\"\n\n", cfile);
init();
fputs("/* syntax table used when not in quotes */\n", cfile);
add("\n", "CNL");
add("\\", "CBACK");
add("'", "CSQUOTE");
add("\"", "CDQUOTE");
add("`", "CBQUOTE");
add("$", "CVAR");
add("}", "CENDVAR");
add("<>();&| \t", "CSPCL");
print("basesyntax");
init();
fputs("\n/* syntax table used when in double quotes */\n", cfile);
add("\n", "CNL");
add("\\", "CBACK");
add("\"", "CENDQUOTE");
add("`", "CBQUOTE");
add("$", "CVAR");
add("}", "CENDVAR");
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
add("!*?[=~:/-]", "CCTL");
print("dqsyntax");
init();
fputs("\n/* syntax table used when in single quotes */\n", cfile);
add("\n", "CNL");
add("'", "CENDQUOTE");
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
add("!*?[=~:/-]\\", "CCTL");
print("sqsyntax");
init();
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
add("\n", "CNL");
add("\\", "CBACK");
add("`", "CBQUOTE");
add("'", "CSQUOTE");
add("\"", "CDQUOTE");
add("$", "CVAR");
add("}", "CENDVAR");
add("(", "CLP");
add(")", "CRP");
print("arisyntax");
filltable("0");
fputs("\n/* character classification table */\n", cfile);
add("0123456789", "ISDIGIT");
add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
add("_", "ISUNDER");
add("#?$!-*@", "ISSPECL");
print("is_type");
if (! digit_contig)
digit_convert();
exit(0);
/* NOTREACHED */
}
 
 
 
/*
* Clear the syntax table.
*/
 
static void
filltable(dftval)
char *dftval;
{
int i;
 
for (i = 0 ; i < size ; i++)
syntax[i] = dftval;
}
 
 
/*
* Initialize the syntax table with default values.
*/
 
static void
init()
{
filltable("CWORD");
syntax[0] = "CEOF";
#ifdef TARGET_CHAR
syntax[base + (TARGET_CHAR)CTLESC] = "CCTL";
syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL";
syntax[base + (TARGET_CHAR)CTLENDVAR] = "CCTL";
syntax[base + (TARGET_CHAR)CTLBACKQ] = "CCTL";
syntax[base + (TARGET_CHAR)CTLBACKQ + (TARGET_CHAR)CTLQUOTE] = "CCTL";
syntax[base + (TARGET_CHAR)CTLARI] = "CCTL";
syntax[base + (TARGET_CHAR)CTLENDARI] = "CCTL";
syntax[base + (TARGET_CHAR)CTLQUOTEMARK] = "CCTL";
#else
syntax[base + CTLESC] = "CCTL";
syntax[base + CTLVAR] = "CCTL";
syntax[base + CTLENDVAR] = "CCTL";
syntax[base + CTLBACKQ] = "CCTL";
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
syntax[base + CTLARI] = "CCTL";
syntax[base + CTLENDARI] = "CCTL";
syntax[base + CTLQUOTEMARK] = "CCTL";
#endif /* TARGET_CHAR */
}
 
 
/*
* Add entries to the syntax table.
*/
 
static void
add(p, type)
char *p, *type;
{
while (*p)
syntax[*p++ + base] = type;
}
 
 
 
/*
* Output the syntax table.
*/
 
static void
print(name)
char *name;
{
int i;
int col;
 
fprintf(hfile, "extern const char %s[];\n", name);
fprintf(cfile, "const char %s[%d] = {\n", name, size);
col = 0;
for (i = 0 ; i < size ; i++) {
if (i == 0) {
fputs(" ", cfile);
} else if ((i & 03) == 0) {
fputs(",\n ", cfile);
col = 0;
} else {
putc(',', cfile);
while (++col < 9 * (i & 03))
putc(' ', cfile);
}
fputs(syntax[i], cfile);
col += strlen(syntax[i]);
}
fputs("\n};\n", cfile);
}
 
 
 
/*
* Output character classification macros (e.g. is_digit). If digits are
* contiguous, we can test for them quickly.
*/
 
static char *macro[] = {
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
"#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
"#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
"#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
NULL
};
 
static void
output_type_macros()
{
char **pp;
 
if (digit_contig)
macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
for (pp = macro ; *pp ; pp++)
fprintf(hfile, "%s\n", *pp);
if (digit_contig)
fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
else
fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
}
 
 
 
/*
* Output digit conversion table (if digits are not contiguous).
*/
 
static void
digit_convert()
{
int maxdigit;
static char digit[] = "0123456789";
char *p;
int i;
 
maxdigit = 0;
for (p = digit ; *p ; p++)
if (*p > maxdigit)
maxdigit = *p;
fputs("extern const char digit_value[];\n", hfile);
fputs("\n\nconst char digit_value[] = {\n", cfile);
for (i = 0 ; i <= maxdigit ; i++) {
for (p = digit ; *p && *p != i ; p++);
if (*p == '\0')
p = digit;
fprintf(cfile, " %ld,\n", (long)(p - digit));
}
fputs("};\n", cfile);
}
/tags/0.3.0/uspace/app/ash/tools/Makefile
0,0 → 1,56
#
# Copyright (c) 2005 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - 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.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
#
 
SOURCES = \
mkinit.c \
mknodes.c \
mksyntax.c \
mksignames.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
OUTPUT := $(addprefix ../,$(basename $(SOURCES)))
 
.PHONY: all clean move-output
 
all: $(OUTPUT)
 
$(OUTPUT): $(OBJECTS)
$(CC) $< $(LFLAGS) -o $@
 
clean:
-rm -f $(OUTPUT) $(OBJECTS)
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
 
/tags/0.3.0/uspace/app/ash/tools/mksignames.c
0,0 → 1,400
/* signames.c -- Create and write `signames.c', which contains an array of
signal names. */
 
/* Copyright (C) 1992 Free Software Foundation, Inc.
 
This file is part of GNU Bash, the Bourne Again SHell.
 
Bash 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 2, or (at your option) any later
version.
 
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
 
#if !defined (NSIG)
# define NSIG 64
#endif
 
char *signal_names[2 * NSIG];
 
char *progname;
 
#if defined (SIGRTMAX) || defined (SIGRTMIN)
# define RTLEN 14
# define RTLIM 256
#endif
 
void
initialize_signames ()
{
register int i;
#if defined (SIGRTMAX) || defined (SIGRTMIN)
int rtmin, rtmax, rtcnt;
#endif
 
for (i = 1; i < sizeof(signal_names)/sizeof(signal_names[0]); i++)
signal_names[i] = (char *)NULL;
 
/* `signal' 0 is what we do on exit. */
signal_names[0] = "EXIT";
 
/* Place signal names which can be aliases for more common signal
names first. This allows (for example) SIGABRT to overwrite SIGLOST. */
 
/* POSIX 1003.1b-1993 real time signals, but take care of incomplete
implementations. Acoording to the standard, both, SIGRTMIN and
SIGRTMAX must be defined, SIGRTMIN must be stricly less than
SIGRTMAX, and the difference must be at least 7, that is, there
must be at least eight distinct real time signals. */
 
/* The generated signal names are SIGRTMIN, SIGRTMIN+1, ...,
SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number
of RT signals is odd, there is an extra SIGRTMIN+(x+1).
These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */
 
#if defined (SIGRTMIN)
rtmin = SIGRTMIN;
signal_names[rtmin] = "SIGRTMIN";
#endif
 
#if defined (SIGRTMAX)
rtmax = SIGRTMAX;
signal_names[rtmax] = "SIGRTMAX";
#endif
 
#if defined (SIGRTMAX) && defined (SIGRTMIN)
if (rtmax > rtmin)
{
rtcnt = (rtmax - rtmin - 1) / 2;
/* croak if there are too many RT signals */
if (rtcnt >= RTLIM/2)
{
rtcnt = RTLIM/2-1;
fprintf(stderr, "%s: error: more than %i real time signals, fix `%s'\n",
progname, RTLIM, progname);
}
 
for (i = 1; i <= rtcnt; i++)
{
signal_names[rtmin+i] = (char *)malloc(RTLEN);
sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i);
signal_names[rtmax-i] = (char *)malloc(RTLEN);
sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i);
}
 
if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
{
/* Need an extra RTMIN signal */
signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1);
}
}
#endif /* SIGRTMIN && SIGRTMAX */
 
/* AIX */
#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */
signal_names[SIGLOST] = "SIGLOST";
#endif
 
#if defined (SIGMSG) /* HFT input data pending */
signal_names[SIGMSG] = "SIGMSG";
#endif
 
#if defined (SIGDANGER) /* system crash imminent */
signal_names[SIGDANGER] = "SIGDANGER";
#endif
 
#if defined (SIGMIGRATE) /* migrate process to another CPU */
signal_names[SIGMIGRATE] = "SIGMIGRATE";
#endif
 
#if defined (SIGPRE) /* programming error */
signal_names[SIGPRE] = "SIGPRE";
#endif
 
#if defined (SIGVIRT) /* AIX virtual time alarm */
signal_names[SIGVIRT] = "SIGVIRT";
#endif
 
#if defined (SIGALRM1) /* m:n condition variables */
signal_names[SIGALRM1] = "SIGALRM1";
#endif
 
#if defined (SIGWAITING) /* m:n scheduling */
signal_names[SIGWAITING] = "SIGWAITING";
#endif
 
#if defined (SIGGRANT) /* HFT monitor mode granted */
signal_names[SIGGRANT] = "SIGGRANT";
#endif
 
#if defined (SIGKAP) /* keep alive poll from native keyboard */
signal_names[SIGKAP] = "SIGKAP";
#endif
 
#if defined (SIGRETRACT) /* HFT monitor mode retracted */
signal_names[SIGRETRACT] = "SIGRETRACT";
#endif
 
#if defined (SIGSOUND) /* HFT sound sequence has completed */
signal_names[SIGSOUND] = "SIGSOUND";
#endif
 
#if defined (SIGSAK) /* Secure Attention Key */
signal_names[SIGSAK] = "SIGSAK";
#endif
 
/* SunOS5 */
#if defined (SIGLWP) /* special signal used by thread library */
signal_names[SIGLWP] = "SIGLWP";
#endif
 
#if defined (SIGFREEZE) /* special signal used by CPR */
signal_names[SIGFREEZE] = "SIGFREEZE";
#endif
 
#if defined (SIGTHAW) /* special signal used by CPR */
signal_names[SIGTHAW] = "SIGTHAW";
#endif
 
#if defined (SIGCANCEL) /* thread cancellation signal used by libthread */
signal_names[SIGCANCEL] = "SIGCANCEL";
#endif
 
/* HP-UX */
#if defined (SIGDIL) /* DIL signal (?) */
signal_names[SIGDIL] = "SIGDIL";
#endif
 
/* System V */
#if defined (SIGCLD) /* Like SIGCHLD. */
signal_names[SIGCLD] = "SIGCLD";
#endif
 
#if defined (SIGPWR) /* power state indication */
signal_names[SIGPWR] = "SIGPWR";
#endif
 
#if defined (SIGPOLL) /* Pollable event (for streams) */
signal_names[SIGPOLL] = "SIGPOLL";
#endif
 
/* Unknown */
#if defined (SIGWINDOW)
signal_names[SIGWINDOW] = "SIGWINDOW";
#endif
 
/* Common */
#if defined (SIGHUP) /* hangup */
signal_names[SIGHUP] = "SIGHUP";
#endif
 
#if defined (SIGINT) /* interrupt */
signal_names[SIGINT] = "SIGINT";
#endif
 
#if defined (SIGQUIT) /* quit */
signal_names[SIGQUIT] = "SIGQUIT";
#endif
 
#if defined (SIGILL) /* illegal instruction (not reset when caught) */
signal_names[SIGILL] = "SIGILL";
#endif
 
#if defined (SIGTRAP) /* trace trap (not reset when caught) */
signal_names[SIGTRAP] = "SIGTRAP";
#endif
 
#if defined (SIGIOT) /* IOT instruction */
signal_names[SIGIOT] = "SIGIOT";
#endif
 
#if defined (SIGABRT) /* Cause current process to dump core. */
signal_names[SIGABRT] = "SIGABRT";
#endif
 
#if defined (SIGEMT) /* EMT instruction */
signal_names[SIGEMT] = "SIGEMT";
#endif
 
#if defined (SIGFPE) /* floating point exception */
signal_names[SIGFPE] = "SIGFPE";
#endif
 
#if defined (SIGKILL) /* kill (cannot be caught or ignored) */
signal_names[SIGKILL] = "SIGKILL";
#endif
 
#if defined (SIGBUS) /* bus error */
signal_names[SIGBUS] = "SIGBUS";
#endif
 
#if defined (SIGSEGV) /* segmentation violation */
signal_names[SIGSEGV] = "SIGSEGV";
#endif
 
#if defined (SIGSYS) /* bad argument to system call */
signal_names[SIGSYS] = "SIGSYS";
#endif
 
#if defined (SIGPIPE) /* write on a pipe with no one to read it */
signal_names[SIGPIPE] = "SIGPIPE";
#endif
 
#if defined (SIGALRM) /* alarm clock */
signal_names[SIGALRM] = "SIGALRM";
#endif
 
#if defined (SIGTERM) /* software termination signal from kill */
signal_names[SIGTERM] = "SIGTERM";
#endif
 
#if defined (SIGURG) /* urgent condition on IO channel */
signal_names[SIGURG] = "SIGURG";
#endif
 
#if defined (SIGSTOP) /* sendable stop signal not from tty */
signal_names[SIGSTOP] = "SIGSTOP";
#endif
 
#if defined (SIGTSTP) /* stop signal from tty */
signal_names[SIGTSTP] = "SIGTSTP";
#endif
 
#if defined (SIGCONT) /* continue a stopped process */
signal_names[SIGCONT] = "SIGCONT";
#endif
 
#if defined (SIGCHLD) /* to parent on child stop or exit */
signal_names[SIGCHLD] = "SIGCHLD";
#endif
 
#if defined (SIGTTIN) /* to readers pgrp upon background tty read */
signal_names[SIGTTIN] = "SIGTTIN";
#endif
 
#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local&LTOSTOP) */
signal_names[SIGTTOU] = "SIGTTOU";
#endif
 
#if defined (SIGIO) /* input/output possible signal */
signal_names[SIGIO] = "SIGIO";
#endif
 
#if defined (SIGXCPU) /* exceeded CPU time limit */
signal_names[SIGXCPU] = "SIGXCPU";
#endif
 
#if defined (SIGXFSZ) /* exceeded file size limit */
signal_names[SIGXFSZ] = "SIGXFSZ";
#endif
 
#if defined (SIGVTALRM) /* virtual time alarm */
signal_names[SIGVTALRM] = "SIGVTALRM";
#endif
 
#if defined (SIGPROF) /* profiling time alarm */
signal_names[SIGPROF] = "SIGPROF";
#endif
 
#if defined (SIGWINCH) /* window changed */
signal_names[SIGWINCH] = "SIGWINCH";
#endif
 
/* 4.4 BSD */
#if defined (SIGINFO) && !defined (_SEQUENT_) /* information request */
signal_names[SIGINFO] = "SIGINFO";
#endif
 
#if defined (SIGUSR1) /* user defined signal 1 */
signal_names[SIGUSR1] = "SIGUSR1";
#endif
 
#if defined (SIGUSR2) /* user defined signal 2 */
signal_names[SIGUSR2] = "SIGUSR2";
#endif
 
#if defined (SIGKILLTHR) /* BeOS: Kill Thread */
signal_names[SIGKILLTHR] = "SIGKILLTHR";
#endif
 
for (i = 0; i < NSIG; i++)
if (signal_names[i] == (char *)NULL)
{
signal_names[i] = (char *)malloc (18);
sprintf (signal_names[i], "SIGJUNK(%d)", i);
}
 
signal_names[NSIG] = "DEBUG";
}
 
void
write_signames (stream)
FILE *stream;
{
register int i;
 
fprintf (stream, "/* This file was automatically created by %s.\n",
progname);
fprintf (stream, " Do not edit. Edit support/mksignames.c instead. */\n\n");
fprintf (stream, "#include <signal.h>\n\n");
fprintf (stream,
"/* A translation list so we can be polite to our users. */\n");
fprintf (stream, "char *signal_names[NSIG + 2] = {\n");
 
for (i = 0; i <= NSIG; i++)
fprintf (stream, " \"%s\",\n", signal_names[i]);
 
fprintf (stream, " (char *)0x0,\n");
fprintf (stream, "};\n");
}
 
int
main (argc, argv)
int argc;
char **argv;
{
char *stream_name;
FILE *stream;
 
progname = argv[0];
 
if (argc == 1)
{
stream_name = "signames.c";
}
else if (argc == 2)
{
stream_name = argv[1];
}
else
{
fprintf (stderr, "Usage: %s [output-file]\n", progname);
exit (1);
}
 
stream = fopen (stream_name, "w");
if (!stream)
{
fprintf (stderr, "%s: %s: cannot open for writing\n",
progname, stream_name);
exit (2);
}
 
initialize_signames ();
write_signames (stream);
exit (0);
}
/tags/0.3.0/uspace/app/ash/tools/mknodes.c
0,0 → 1,492
/* $NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $ */
 
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
*
* 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 University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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.
*/
 
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
 
#ifndef lint
#if 0
static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
#else
static const char rcsid[] =
"$NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $";
#endif
#endif /* not lint */
 
/*
* This program reads the nodetypes file and nodes.c.pat file. It generates
* the files nodes.h and nodes.c.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
 
 
#define MAXTYPES 50 /* max number of node types */
#define MAXFIELDS 20 /* max fields in a structure */
#define BUFLEN 100 /* size of character buffers */
 
/* field types */
#define T_NODE 1 /* union node *field */
#define T_NODELIST 2 /* struct nodelist *field */
#define T_STRING 3
#define T_INT 4 /* int field */
#define T_OTHER 5 /* other */
#define T_TEMP 6 /* don't copy this field */
 
 
struct field { /* a structure field */
char *name; /* name of field */
int type; /* type of field */
char *decl; /* declaration of field */
};
 
 
struct str { /* struct representing a node structure */
char *tag; /* structure tag */
int nfields; /* number of fields in the structure */
struct field field[MAXFIELDS]; /* the fields of the structure */
int done; /* set if fully parsed */
};
 
 
static int ntypes; /* number of node types */
static char *nodename[MAXTYPES]; /* names of the nodes */
static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
static int nstr; /* number of structures */
static struct str str[MAXTYPES]; /* the structures */
static struct str *curstr; /* current structure */
static FILE *infp;
static char line[1024];
static int linno;
static char *linep;
 
static void parsenode(void);
static void parsefield(void);
static void output(char *);
static void outsizes(FILE *);
static void outfunc(FILE *, int);
static void indent(int, FILE *);
static int nextfield(char *);
static void skipbl(void);
static int readline(void);
static void error(const char *, ...);
static char *savestr(const char *);
int main(int, char **);
 
 
int
main(argc, argv)
int argc;
char **argv;
{
 
/*
* some versions of linux complain: initializer element is not
* constant if this is done at compile time.
*/
infp = stdin;
 
if (argc != 3)
error("usage: mknodes file");
if ((infp = fopen(argv[1], "r")) == NULL)
error("Can't open %s", argv[1]);
while (readline()) {
if (line[0] == ' ' || line[0] == '\t')
parsefield();
else if (line[0] != '\0')
parsenode();
}
output(argv[2]);
exit(0);
/* NOTREACHED */
}
 
 
 
static void
parsenode()
{
char name[BUFLEN];
char tag[BUFLEN];
struct str *sp;
 
if (curstr && curstr->nfields > 0)
curstr->done = 1;
nextfield(name);
if (! nextfield(tag))
error("Tag expected");
if (*linep != '\0')
error("Garbage at end of line");
nodename[ntypes] = savestr(name);
for (sp = str ; sp < str + nstr ; sp++) {
if (strcmp(sp->tag, tag) == 0)
break;
}
if (sp >= str + nstr) {
sp->tag = savestr(tag);
sp->nfields = 0;
curstr = sp;
nstr++;
}
nodestr[ntypes] = sp;
ntypes++;
}
 
 
static void
parsefield()
{
char name[BUFLEN];
char type[BUFLEN];
char decl[2 * BUFLEN];
struct field *fp;
 
if (curstr == NULL || curstr->done)
error("No current structure to add field to");
if (! nextfield(name))
error("No field name");
if (! nextfield(type))
error("No field type");
fp = &curstr->field[curstr->nfields];
fp->name = savestr(name);
if (strcmp(type, "nodeptr") == 0) {
fp->type = T_NODE;
sprintf(decl, "union node *%s", name);
} else if (strcmp(type, "nodelist") == 0) {
fp->type = T_NODELIST;
sprintf(decl, "struct nodelist *%s", name);
} else if (strcmp(type, "string") == 0) {
fp->type = T_STRING;
sprintf(decl, "char *%s", name);
} else if (strcmp(type, "int") == 0) {
fp->type = T_INT;
sprintf(decl, "int %s", name);
} else if (strcmp(type, "other") == 0) {
fp->type = T_OTHER;
} else if (strcmp(type, "temp") == 0) {
fp->type = T_TEMP;
} else {
error("Unknown type %s", type);
}
if (fp->type == T_OTHER || fp->type == T_TEMP) {
skipbl();
fp->decl = savestr(linep);
} else {
if (*linep)
error("Garbage at end of line");
fp->decl = savestr(decl);
}
curstr->nfields++;
}
 
 
char writer[] = "\
/*\n\
* This file was generated by the mknodes program.\n\
*/\n\
\n";
 
static void
output(file)
char *file;
{
FILE *hfile;
FILE *cfile;
FILE *patfile;
int i;
struct str *sp;
struct field *fp;
char *p;
 
if ((patfile = fopen(file, "r")) == NULL)
error("Can't open %s", file);
if ((hfile = fopen("nodes.h", "w")) == NULL)
error("Can't create nodes.h");
if ((cfile = fopen("nodes.c", "w")) == NULL)
error("Can't create nodes.c");
fputs(writer, hfile);
for (i = 0 ; i < ntypes ; i++)
fprintf(hfile, "#define %s %d\n", nodename[i], i);
fputs("\n\n\n", hfile);
for (sp = str ; sp < &str[nstr] ; sp++) {
fprintf(hfile, "struct %s {\n", sp->tag);
for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
fprintf(hfile, " %s;\n", fp->decl);
}
fputs("};\n\n\n", hfile);
}
fputs("union node {\n", hfile);
fprintf(hfile, " int type;\n");
for (sp = str ; sp < &str[nstr] ; sp++) {
fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag);
}
fputs("};\n\n\n", hfile);
fputs("struct nodelist {\n", hfile);
fputs("\tstruct nodelist *next;\n", hfile);
fputs("\tunion node *n;\n", hfile);
fputs("};\n\n\n", hfile);
fputs("#ifdef __STDC__\n", hfile);
fputs("union node *copyfunc(union node *);\n", hfile);
fputs("void freefunc(union node *);\n", hfile);
fputs("#else\n", hfile);
fputs("union node *copyfunc();\n", hfile);
fputs("void freefunc();\n", hfile);
fputs("#endif\n", hfile);
 
fputs(writer, cfile);
while (fgets(line, sizeof line, patfile) != NULL) {
for (p = line ; *p == ' ' || *p == '\t' ; p++);
if (strcmp(p, "%SIZES\n") == 0)
outsizes(cfile);
else if (strcmp(p, "%CALCSIZE\n") == 0)
outfunc(cfile, 1);
else if (strcmp(p, "%COPY\n") == 0)
outfunc(cfile, 0);
else
fputs(line, cfile);
}
}
 
 
 
static void
outsizes(cfile)
FILE *cfile;
{
int i;
 
fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
for (i = 0 ; i < ntypes ; i++) {
fprintf(cfile, " ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
}
fprintf(cfile, "};\n");
}
 
 
static void
outfunc(cfile, calcsize)
FILE *cfile;
int calcsize;
{
struct str *sp;
struct field *fp;
int i;
 
fputs(" if (n == NULL)\n", cfile);
if (calcsize)
fputs(" return;\n", cfile);
else
fputs(" return NULL;\n", cfile);
if (calcsize)
fputs(" funcblocksize += nodesize[n->type];\n", cfile);
else {
fputs(" new = funcblock;\n", cfile);
fputs(" funcblock = (char *) funcblock + nodesize[n->type];\n", cfile);
}
fputs(" switch (n->type) {\n", cfile);
for (sp = str ; sp < &str[nstr] ; sp++) {
for (i = 0 ; i < ntypes ; i++) {
if (nodestr[i] == sp)
fprintf(cfile, " case %s:\n", nodename[i]);
}
for (i = sp->nfields ; --i >= 1 ; ) {
fp = &sp->field[i];
switch (fp->type) {
case T_NODE:
if (calcsize) {
indent(12, cfile);
fprintf(cfile, "calcsize(n->%s.%s);\n",
sp->tag, fp->name);
} else {
indent(12, cfile);
fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
sp->tag, fp->name, sp->tag, fp->name);
}
break;
case T_NODELIST:
if (calcsize) {
indent(12, cfile);
fprintf(cfile, "sizenodelist(n->%s.%s);\n",
sp->tag, fp->name);
} else {
indent(12, cfile);
fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
sp->tag, fp->name, sp->tag, fp->name);
}
break;
case T_STRING:
if (calcsize) {
indent(12, cfile);
fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
sp->tag, fp->name);
} else {
indent(12, cfile);
fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
sp->tag, fp->name, sp->tag, fp->name);
}
break;
case T_INT:
case T_OTHER:
if (! calcsize) {
indent(12, cfile);
fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
sp->tag, fp->name, sp->tag, fp->name);
}
break;
}
}
indent(12, cfile);
fputs("break;\n", cfile);
}
fputs(" };\n", cfile);
if (! calcsize)
fputs(" new->type = n->type;\n", cfile);
}
 
 
static void
indent(amount, fp)
int amount;
FILE *fp;
{
while (amount >= 8) {
putc('\t', fp);
amount -= 8;
}
while (--amount >= 0) {
putc(' ', fp);
}
}
 
 
static int
nextfield(buf)
char *buf;
{
char *p, *q;
 
p = linep;
while (*p == ' ' || *p == '\t')
p++;
q = buf;
while (*p != ' ' && *p != '\t' && *p != '\0')
*q++ = *p++;
*q = '\0';
linep = p;
return (q > buf);
}
 
 
static void
skipbl()
{
while (*linep == ' ' || *linep == '\t')
linep++;
}
 
 
static int
readline()
{
char *p;
 
if (fgets(line, 1024, infp) == NULL)
return 0;
for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
p--;
*p = '\0';
linep = line;
linno++;
if (p - line > BUFLEN)
error("Line too long");
return 1;
}
 
 
 
static void
#ifdef __STDC__
error(const char *msg, ...)
#else
error(va_alist)
va_dcl
#endif
{
va_list va;
#ifdef __STDC__
va_start(va, msg);
#else
char *msg;
va_start(va);
msg = va_arg(va, char *);
#endif
 
(void) fprintf(stderr, "line %d: ", linno);
(void) vfprintf(stderr, msg, va);
(void) fputc('\n', stderr);
 
va_end(va);
 
exit(2);
/* NOTREACHED */
}
 
 
 
static char *
savestr(s)
const char *s;
{
char *p;
 
if ((p = malloc(strlen(s) + 1)) == NULL)
error("Out of space");
(void) strcpy(p, s);
return p;
}
/tags/0.3.0/uspace/app/ash/tools/mkinit.c
0,0 → 1,525
/* $NetBSD: mkinit.c,v 1.20 2000/07/18 19:13:20 cgd Exp $ */
 
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
*
* 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 University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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.
*/
 
 
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
 
#ifndef lint
#if 0
static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
#else
static const char rcsid[] =
"$NetBSD: mkinit.c,v 1.20 2000/07/18 19:13:20 cgd Exp $";
#endif
#endif /* not lint */
 
/*
* This program scans all the source files for code to handle various
* special events and combines this code into one file. This (allegedly)
* improves the structure of the program since there is no need for
* anyone outside of a module to know that that module performs special
* operations on particular events.
*
* Usage: mkinit sourcefile...
*/
 
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
 
 
/*
* OUTFILE is the name of the output file. Output is initially written
* to the file OUTTEMP, which is then moved to OUTFILE.
*/
 
#define OUTFILE "init.c"
#define OUTTEMP "init.c.new"
 
 
/*
* A text structure is basicly just a string that grows as more characters
* are added onto the end of it. It is implemented as a linked list of
* blocks of characters. The routines addstr and addchar append a string
* or a single character, respectively, to a text structure. Writetext
* writes the contents of a text structure to a file.
*/
 
#define BLOCKSIZE 512
 
struct text {
char *nextc;
int nleft;
struct block *start;
struct block *last;
};
 
struct block {
struct block *next;
char text[BLOCKSIZE];
};
 
 
/*
* There is one event structure for each event that mkinit handles.
*/
 
struct event {
char *name; /* name of event (e.g. INIT) */
char *routine; /* name of routine called on event */
char *comment; /* comment describing routine */
struct text code; /* code for handling event */
};
 
 
char writer[] = "\
/*\n\
* This file was generated by the mkinit program.\n\
*/\n\
\n";
 
char init[] = "\
/*\n\
* Initialization code.\n\
*/\n";
 
char reset[] = "\
/*\n\
* This routine is called when an error or an interrupt occurs in an\n\
* interactive shell and control is returned to the main command loop.\n\
*/\n";
 
char shellproc[] = "\
/*\n\
* This routine is called to initialize the shell to run a shell procedure.\n\
*/\n";
 
 
struct event event[] = {
{"INIT", "init", init},
{"RESET", "reset", reset},
{"SHELLPROC", "initshellproc", shellproc},
{NULL, NULL}
};
 
 
char *curfile; /* current file */
int linno; /* current line */
char *header_files[200]; /* list of header files */
struct text defines; /* #define statements */
struct text decls; /* declarations */
int amiddecls; /* for formatting */
 
 
void readfile(char *);
int match(char *, char *);
int gooddefine(char *);
void doevent(struct event *, FILE *, char *);
void doinclude(char *);
void dodecl(char *, FILE *);
void output(void);
void addstr(char *, struct text *);
void addchar(int, struct text *);
void writetext(struct text *, FILE *);
FILE *ckfopen(char *, char *);
void *ckmalloc(int);
char *savestr(char *);
void error(char *);
int main(int, char **);
 
#define equal(s1, s2) (strcmp(s1, s2) == 0)
 
int
main(argc, argv)
int argc;
char **argv;
{
char **ap;
 
header_files[0] = "\"shell.h\"";
header_files[1] = "\"mystring.h\"";
header_files[2] = "\"init.h\"";
for (ap = argv + 1 ; *ap ; ap++)
readfile(*ap);
output();
rename(OUTTEMP, OUTFILE);
exit(0);
/* NOTREACHED */
}
 
 
/*
* Parse an input file.
*/
 
void
readfile(fname)
char *fname;
{
FILE *fp;
char line[1024];
struct event *ep;
 
fp = ckfopen(fname, "r");
curfile = fname;
linno = 0;
amiddecls = 0;
while (fgets(line, sizeof line, fp) != NULL) {
linno++;
for (ep = event ; ep->name ; ep++) {
if (line[0] == ep->name[0] && match(ep->name, line)) {
doevent(ep, fp, fname);
break;
}
}
if (line[0] == 'I' && match("INCLUDE", line))
doinclude(line);
if (line[0] == 'M' && match("MKINIT", line))
dodecl(line, fp);
if (line[0] == '#' && gooddefine(line))
addstr(line, &defines);
if (line[0] == '#' && gooddefine(line)) {
char *cp;
char line2[1024];
static const char undef[] = "#undef ";
 
strcpy(line2, line);
memcpy(line2, undef, sizeof(undef) - 1);
cp = line2 + sizeof(undef) - 1;
while(*cp && (*cp == ' ' || *cp == '\t'))
cp++;
while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
cp++;
*cp++ = '\n'; *cp = '\0';
addstr(line2, &defines);
addstr(line, &defines);
}
}
fclose(fp);
}
 
 
int
match(name, line)
char *name;
char *line;
{
char *p, *q;
 
p = name, q = line;
while (*p) {
if (*p++ != *q++)
return 0;
}
if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
return 0;
return 1;
}
 
 
int
gooddefine(line)
char *line;
{
char *p;
 
if (! match("#define", line))
return 0; /* not a define */
p = line + 7;
while (*p == ' ' || *p == '\t')
p++;
while (*p != ' ' && *p != '\t') {
if (*p == '(')
return 0; /* macro definition */
p++;
}
while (*p != '\n' && *p != '\0')
p++;
if (p[-1] == '\\')
return 0; /* multi-line definition */
return 1;
}
 
 
void
doevent(ep, fp, fname)
struct event *ep;
FILE *fp;
char *fname;
{
char line[1024];
int indent;
char *p;
 
sprintf(line, "\n /* from %s: */\n", fname);
addstr(line, &ep->code);
addstr(" {\n", &ep->code);
for (;;) {
linno++;
if (fgets(line, sizeof line, fp) == NULL)
error("Unexpected EOF");
if (equal(line, "}\n"))
break;
indent = 6;
for (p = line ; *p == '\t' ; p++)
indent += 8;
for ( ; *p == ' ' ; p++)
indent++;
if (*p == '\n' || *p == '#')
indent = 0;
while (indent >= 8) {
addchar('\t', &ep->code);
indent -= 8;
}
while (indent > 0) {
addchar(' ', &ep->code);
indent--;
}
addstr(p, &ep->code);
}
addstr(" }\n", &ep->code);
}
 
 
void
doinclude(line)
char *line;
{
char *p;
char *name;
char **pp;
 
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
if (*p == '\0')
error("Expecting '\"' or '<'");
name = p;
while (*p != ' ' && *p != '\t' && *p != '\n')
p++;
if (p[-1] != '"' && p[-1] != '>')
error("Missing terminator");
*p = '\0';
 
/* name now contains the name of the include file */
for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
if (*pp == NULL)
*pp = savestr(name);
}
 
 
void
dodecl(line1, fp)
char *line1;
FILE *fp;
{
char line[1024];
char *p, *q;
 
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
addchar('\n', &decls);
do {
linno++;
if (fgets(line, sizeof line, fp) == NULL)
error("Unterminated structure declaration");
addstr(line, &decls);
} while (line[0] != '}');
amiddecls = 0;
} else {
if (! amiddecls)
addchar('\n', &decls);
q = NULL;
for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
continue;
if (*p == '=') { /* eliminate initialization */
for (q = p ; *q && *q != ';' ; q++);
if (*q == '\0')
q = NULL;
else {
while (p[-1] == ' ')
p--;
*p = '\0';
}
}
addstr("extern", &decls);
addstr(line1 + 6, &decls);
if (q != NULL)
addstr(q, &decls);
amiddecls = 1;
}
}
 
 
 
/*
* Write the output to the file OUTTEMP.
*/
 
void
output() {
FILE *fp;
char **pp;
struct event *ep;
 
fp = ckfopen(OUTTEMP, "w");
fputs(writer, fp);
for (pp = header_files ; *pp ; pp++)
fprintf(fp, "#include %s\n", *pp);
fputs("\n\n\n", fp);
writetext(&defines, fp);
fputs("\n\n", fp);
writetext(&decls, fp);
for (ep = event ; ep->name ; ep++) {
fputs("\n\n\n", fp);
fputs(ep->comment, fp);
fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
writetext(&ep->code, fp);
fprintf(fp, "}\n");
}
fclose(fp);
}
 
 
/*
* A text structure is simply a block of text that is kept in memory.
* Addstr appends a string to the text struct, and addchar appends a single
* character.
*/
 
void
addstr(s, text)
char *s;
struct text *text;
{
while (*s) {
if (--text->nleft < 0)
addchar(*s++, text);
else
*text->nextc++ = *s++;
}
}
 
 
void
addchar(c, text)
int c;
struct text *text;
{
struct block *bp;
 
if (--text->nleft < 0) {
bp = ckmalloc(sizeof *bp);
if (text->start == NULL)
text->start = bp;
else
text->last->next = bp;
text->last = bp;
text->nextc = bp->text;
text->nleft = BLOCKSIZE - 1;
}
*text->nextc++ = c;
}
 
/*
* Write the contents of a text structure to a file.
*/
void
writetext(text, fp)
struct text *text;
FILE *fp;
{
struct block *bp;
 
if (text->start != NULL) {
for (bp = text->start ; bp != text->last ; bp = bp->next)
fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
}
}
 
FILE *
ckfopen(file, mode)
char *file;
char *mode;
{
FILE *fp;
 
if ((fp = fopen(file, mode)) == NULL) {
fprintf(stderr, "Can't open %s\n", file);
exit(2);
}
return fp;
}
 
void *
ckmalloc(nbytes)
int nbytes;
{
char *p;
 
if ((p = malloc(nbytes)) == NULL)
error("Out of space");
return p;
}
 
char *
savestr(s)
char *s;
{
char *p;
 
p = ckmalloc(strlen(s) + 1);
strcpy(p, s);
return p;
}
 
void
error(msg)
char *msg;
{
if (curfile != NULL)
fprintf(stderr, "%s:%d: ", curfile, linno);
fprintf(stderr, "%s\n", msg);
exit(2);
/* NOTREACHED */
}