/branches/tracing/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); |
} |
/branches/tracing/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 $@ |
/branches/tracing/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<OSTOP) */ |
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); |
} |
/branches/tracing/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; |
} |
/branches/tracing/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 */ |
} |