type.str
util.str
util.c
+stab.c
!File: regcount.h
#undef REGCOUNT 1 /* count occurrences for register messages */
+!File: dbsymtab.h
+#define DBSYMTAB 1 /* ability to produce symbol table for debugger
+*/
+
#undef REGCOUNT 1 /* count occurrences for register messages */
+!File: dbsymtab.h
+#undef DBSYMTAB 1 /* ability to produce symbol table for debugger
+*/
+
+
insert \fIdirname\fR in the list of include directories.
.IP \fB\-M\fP\fIn\fP
set maximum identifier length to \fIn\fP.
+.IP \fB\-g\fP
+produce a DBX-style symbol table.
.IP \fB\-n\fR
do not generate EM register messages.
The user-declared variables are not stored into registers on the target
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
-/* C O D E - G E N E R A T I N G R O U T I N E S */
+/* C O D E - G E N E R A T I N G R O U T I N E S */
#include "lint.h"
+#include "dbsymtab.h"
#ifndef LINT
#include <em.h>
#else
#include "atw.h"
#include "assert.h"
#include "noRoption.h"
-#include "file_info.h"
+#include "LLlex.h"
+#ifdef DBSYMTAB
+#include <stb.h>
+#endif /* DBSYMTAB */
label lab_count = 1;
label datlab_count = 1;
fatal("cannot write to %s\n", dst_file);
C_magic();
C_ms_emx(word_size, pointer_size);
+#ifdef DBSYMTAB
+ if (options['g']) {
+ extern char *source;
+
+ C_ms_std(source, N_SO, 0);
+ stb_typedef(int_type, "int");
+ stb_typedef(char_type, "char");
+ stb_typedef(long_type, "long");
+ stb_typedef(short_type, "short");
+ stb_typedef(uchar_type, "unsigned char");
+ stb_typedef(ushort_type, "unsigned short");
+ stb_typedef(ulong_type, "unsigned long");
+ stb_typedef(uint_type, "unsigned int");
+ stb_typedef(float_type, "float");
+ stb_typedef(double_type, "double");
+ stb_typedef(void_type, "void");
+ }
+#endif /* DBSYMTAB */
#ifdef USE_TMP
#ifdef PREPEND_SCOPES
C_insertpart(tmp_id = C_getid());
while (se != 0) {
register struct idf *id = se->se_idf;
register struct def *df = id->id_def;
-
+
if (df && (df->df_initialized || df->df_used || df->df_alloc))
code_scope(id->id_text, df);
se = se->next;
as given by def, if meaningful.
*/
int fund = def->df_type->tp_fund;
-
+
switch (def->df_sc) {
case EXTERN:
case GLOBAL:
C_fil_dlb(file_name_label, (arith)0);
C_lin((arith)LineNumber);
}
+#ifdef DBSYMTAB
+ if (options['g']) {
+ stb_string(def, FUNCTION, name);
+ if (! strcmp(name, "main")) {
+ C_ms_stb_cst(name, N_MAIN, 0, (arith) 0);
+ }
+ }
+#endif
}
end_proc(fbytes)
probably smarter than generating a direct return.
Return sequences may be expensive.
*/
+#ifdef DBSYMTAB
+ if (options['g']) db_line(dot.tk_file, dot.tk_line);
+#endif /* DBSYMTAB */
C_bra(return2_label);
}
Since the expression may be modified in the process,
code_declaration() frees it after use, as the caller can
no longer do so.
-
+
If there is a storage class indication (EXTERN/STATIC),
code_declaration() will generate an exa or ina.
The sc is the actual storage class, as given in the
register struct def *def = idf->id_def;
register arith size = def->df_type->tp_size;
int def_sc = def->df_sc;
-
- if (def_sc == TYPEDEF) /* no code for typedefs */
+
+ if (def_sc == TYPEDEF) { /* no code for typedefs */
+#ifdef DBSYMTAB
+ if (options['g']) {
+ stb_typedef(def->df_type, idf->id_text);
+ }
+#endif /* DBSYMTAB */
return;
+ }
if (sc == EXTERN && expr && !is_anon_idf(idf))
error("%s is extern; cannot initialize", idf->id_text);
if (lvl == L_GLOBAL) { /* global variable */
/* they are handled on the spot and get an
integer label in EM.
*/
+#ifdef DBSYMTAB
+ if (options['g'] && ! expr) {
+ stb_string(def, sc, idf->id_text);
+ }
+#endif /* DBSYMTAB */
C_df_dlb((label)def->df_address);
if (expr) { /* there is an initialisation */
}
break;
case AUTO:
case REGISTER:
+#ifdef DBSYMTAB
+ if (options['g']) {
+ stb_string(def, sc, idf->id_text);
+ }
+#endif /* DBSYMTAB */
if (expr)
loc_init(expr, idf);
break;
*/
register struct expr *e = expr;
register struct type *tp = id->id_def->df_type;
-
+
ASSERT(id->id_def->df_sc != STATIC);
switch (tp->tp_fund) {
case ARRAY:
/* bss() allocates bss space for the global idf.
*/
arith size = idf->id_def->df_type->tp_size;
-
+
#ifndef PREPEND_SCOPES
code_scope(idf->id_text, idf->id_def);
#endif PREPEND_SCOPES
+#ifdef DBSYMTAB
+ if (options['g']) {
+ stb_string(idf->id_def, idf->id_def->df_sc, idf->id_text);
+ }
+#endif /* DBSYMTAB */
/* Since bss() is only called if df_alloc is non-zero, and
since df_alloc is only non-zero if size >= 0, we have:
*/
/* but we already gave a warning at the declaration of the
array. Besides, the message given here does not apply to
voids
-
+
if (options['R'] && size == 0)
warning("actual array of size 0");
*/
#ifndef LINT
if (! options['L']) /* profiling */
C_lin((arith)(expr->ex_line));
+#ifdef DBSYMTAB
+ if (options['g']) db_line(expr->ex_file, (unsigned int)expr->ex_line);
+#endif
EVAL(expr, val, code, tlbl, flbl);
#else LINT
lint_expr(expr, code ? USED : IGNORED);
{
register struct stmt_block *stmt_block = stmt_stack;
+#ifdef DBSYMTAB
+ if (options['g']) db_line(dot.tk_file, dot.tk_line);
+#endif /* DBSYMTAB */
if (stmt_block)
C_bra(stmt_block->st_break);
else
while (stmt_block) {
if (stmt_block->st_continue) {
+#ifdef DBSYMTAB
+ if (options['g']) db_line(dot.tk_file, dot.tk_line);
+#endif /* DBSYMTAB */
C_bra(stmt_block->st_continue);
return;
}
C_asp(pointer_size);
}
}
+
+#ifdef DBSYMTAB
+db_line(file, line)
+ char *file;
+ unsigned int line;
+{
+ static unsigned oldline;
+ static char *oldfile;
+
+ if (file != oldfile || line != oldline) {
+ C_ms_std((char *) 0, N_SLINE, (int) line);
+ oldline = line;
+ oldfile = file;
+ }
+}
+#endif /* DBSYMTAB */
{
#include "lint.h"
+#include "dbsymtab.h"
#include <alloc.h>
#include "nobitfield.h"
#include "debug.h"
This means that something like:
unsigned extern int short xx;
is perfectly good C.
-
+
On top of that, multiple occurrences of storage_class_specifiers,
unsigned_specifiers and size_specifiers are errors, but a second
type_specifier should end the decl_specifiers and be treated as
occurrence of the type_specifier in the grammar (we have no choice),
collecting all data in a `struct decspecs' and turning that data
structure into what we want.
-
+
The existence of declarations like
short typedef yepp;
makes all hope of writing a specific grammar for typedefs illusory.
#ifdef LINT
change_state(idf, SET);
#endif LINT
+#ifdef DBSYMTAB
+ if (options['g'] && level >= L_LOCAL && expr) {
+ db_line(expr->ex_file, (unsigned) expr->ex_line)
+;
+ }
+#endif /* DBSYMTAB */
code_declaration(idf, expr, level, sc);
}
+#ifdef DBSYMTAB
+ if (options['g'] && globalflag) {
+ stb_string(idf->id_def, sc, idf->id_text);
+ }
+#endif /* DBSYMTAB */
init_idf(idf);
}
;
identifier(&idf)
{
register struct formal *new = new_formal();
-
+
new->fm_idf = idf;
new->next = *fmp;
*fmp = new;
[
{declare_struct(ENUM, idf, tpp);}
enumerator_pack(*tpp, &l)
+ {
+#ifdef DBSYMTAB
+ if (options['g']) {
+ stb_tag(idf->id_enum, idf->id_text);
+ }
+#endif /*DBSYMTAB */
+ }
|
{apply_struct(ENUM, idf, tpp);}
empty
struct_declaration_pack(*tpp)
{
(idf->id_struct->tg_busy)--;
+#ifdef DBSYMTAB
+ if (options['g']) {
+ stb_tag(idf->id_struct, idf->id_text);
+ }
+#endif /*DBSYMTAB */
}
|
{apply_struct(fund, idf, tpp);}
#include "nopp.h"
#ifndef NOPP
-#include "ifdepth.h"
-#include "botch_free.h"
-#include "nparams.h"
-#include "parbufsize.h"
-#include "textsize.h"
-#include "idfsize.h"
+#include "ifdepth.h"
+#include "botch_free.h"
+#include "nparams.h"
+#include "parbufsize.h"
+#include "textsize.h"
+#include "idfsize.h"
#include "assert.h"
#include <alloc.h>
#include "class.h"
#include "macro.h"
+#include "dbsymtab.h"
+#ifdef DBSYMTAB
+#include <stb.h>
+int IncludeLevel = 0;
+extern char options[];
+#endif
IMPORT char **inctable; /* list of include directories */
IMPORT char *getwdir();
FileName = result;
LineNumber = 0;
nestlow = nestlevel;
+#ifdef DBSYMTAB
+ IncludeLevel++;
+ if (options['g']) {
+ C_ms_std(FileName, N_BINCL, 0);
+ }
+#endif /* DBSYMTAB */
}
}
}
return;
}
/* there is a formal parameter list if the identifier is
- followed immediately by a '('.
+ followed immediately by a '('.
*/
LoadChar(ch);
if (ch == '(') {
else
id->id_macro = newdef = new_macro();
newdef->mc_text = text; /* replacement text */
- newdef->mc_nps = nformals; /* nr of formals */
+ newdef->mc_nps = nformals; /* nr of formals */
newdef->mc_length = length; /* length of repl. text */
newdef->mc_flag = flags; /* special flags */
newdef->mc_count = 0;
macroeq(s, t)
register char *s, *t;
{
-
+
/* skip leading spaces */
while (BLANK(*s)) s++;
while (BLANK(*t)) t++;
{
if (options['h']) {
register int i;
-
+
print("Hash table tally:\n");
for (i = 0; i < HASHSIZE; i++) {
register struct idf *notch = idf_hashtable[i];
int cnt = 0;
-
+
while (notch) {
cnt++;
notch = notch->next;
print("%d %d\n", i, cnt);
}
print("End hash table tally\n");
- }
+ }
}
#endif DEBUG
char tg[];
{
/* str2idf() returns an entry in the symbol table for the
- identifier tg. If necessary, an entry is created.
+ identifier tg. If necessary, an entry is created.
It is used where the text of the identifier is available
but its hash value is not; otherwise idf_hashed() is to
be used.
register struct type *type;
struct stack_level *stl = stack_level_of(lvl);
char formal_array = 0;
-
+
/* determine the present type */
if (ds->ds_type == 0) {
/* at the L_FORMAL1 level there is no type specified yet
check_hiding(idf, lvl, sc); /* of some idf by this idf */
#endif LINT
- if (def &&
+ if (def &&
( def->df_level == lvl ||
( lvl != L_GLOBAL && def->df_level > lvl )
)
/* An actual_declaration needs space, right here and now.
*/
register int fund = tp->tp_fund;
-
+
if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */
return 0;
if (fund == FUNCTION || fund == ARRAY)
/* Declares the formal parameters if they exist.
*/
register struct formal *fm = dc->dc_formal;
-
+
while (fm) {
declare_parameter(fm->fm_idf);
fm = fm->next;
/* The topmost definition of idf is set to initialized.
*/
register struct def *def = idf->id_def; /* the topmost */
-
+
if (def->df_initialized)
error("multiple initialization of %s", idf->id_text);
if (def->df_sc == TYPEDEF) {
#endif DEBUG
while (se) {
register struct def *def = se->se_idf->id_def;
-
+
def->df_address = f_offset;
/* the alignment convention for parameters is: align on
word boundaries, i.e. take care that the following
*/
f_offset = align(f_offset + def->df_type->tp_size, (int) word_size);
formal_cvt(def); /* cvt int to char or short, if necessary */
- se = se->next;
def->df_level = L_FORMAL2; /* CJ */
RegisterAccount(def->df_address, def->df_type->tp_size,
regtype(def->df_type),
def->df_sc);
+#ifdef DBSYMTAB
+ if (options['g']) {
+ stb_string(def, FORMAL, se->se_idf->id_text);
+ }
+#endif /* DBSYMTAB */
+ se = se->next;
}
*fp = f_offset;
}
described in Knuth, vol 2.
*/
register int h, rnd = HASH_X;
-
+
for (h = 0; h < IDFSIZE; h++) {
hmask[h] = rnd;
rnd = (HASH_A * rnd + HASH_C) & HASHMASK;
#include "nopp.h"
#include <inp_pkg.body>
+#include "dbsymtab.h"
#ifndef NOPP
+#ifdef DBSYMTAB
+#include <stb.h>
+extern int IncludeLevel;
+extern char options[];
+#endif
char *
getwdir(fn)
register char *fn;
if (NoUnstack) lexerror("unexpected EOF");
#ifndef NOPP
nestlevel = nestlow;
+#ifdef DBSYMTAB
+ if (options['g'] && IncludeLevel > 0) {
+ C_ms_std(FileName, N_EINCL, 0);
+ }
+ IncludeLevel--;
+#endif
#endif
return 0;
}
init();
LineNumber = 0;
nestlow = -1;
+#ifndef LINT
+ init_code(destination && strcmp(destination, "-") != 0 ?
+ destination : 0);
+#endif
#ifndef NOPP
WorkingDir = getwdir(source);
#endif NOPP
#endif DEBUG
{
#ifndef LINT
- init_code(destination && strcmp(destination, "-") != 0 ?
- destination : 0);
/* compile the source text */
C_program();
#ifdef PREPEND_SCOPES
d perform a small dataflow analysis
D see identifier following as a macro
E run preprocessor only
+g produce symbol table for debugger
i suppress /usr/include include files in dependency list
I expand include table with directory name following
+L don't generate linenumbers and filename indications
m generate file.o: file1.h format dependency lines
M set identifier length
n don't generate register messages
-L don't generate linenumbers and filename indications
p trace
P in running the preprocessor do not output '# line' lines
R restricted C
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
-/* U S E R O P T I O N - H A N D L I N G */
+/* U S E R O P T I O N - H A N D L I N G */
#include "lint.h"
#include "botch_free.h"
#include "use_tmp.h"
#include "dataflow.h"
#include "noRoption.h"
+#include "dbsymtab.h"
#ifndef NOPP
extern char **inctable;
#ifndef LINT
#ifndef NOPP
- case 'A' : /* Amake dependency generation */
+ case 'A' : /* Amake dependency generation */
do_dependencies = 1;
if (*text) {
dep_file = text;
break;
#endif NOPP
#endif LINT
-
+#ifdef DBSYMTAB
+ case 'g': /* symbol table for debugger */
+ options['g'] = 1;
+ options['n'] = 1;
+ break;
+#endif /* DBSYMTAB */
+
case 'R': /* strict version */
#ifndef NOROPTION
options[opt] = 1;
if (*text) {
int i;
register char *new = text;
-
+
if (++inc_total > inc_max) {
inctable = (char **)
Realloc(inctable,(inc_max+=10)*sizeof(char *));
}
-
+
for (i = inc_pos++; i < inc_total; i++) {
char *tmp = inctable[i];
-
+
inctable[i] = new;
new = tmp;
}
#endif USE_TMP
break;
}
-
+
case 'U' : { /* -Uname : undefine predefined */
#ifndef NOPP
register struct idf *idef;
*tp; the resulting value is yielded.
*/
register int val = 0, ch;
-
+
while (ch = **tp, ch >= '0' && ch <= '9') {
val = val * 10 + ch - '0';
(*tp)++;
$(SRC_DIR)/switch.c \
$(SRC_DIR)/tokenname.c \
$(SRC_DIR)/type.c \
- $(SRC_DIR)/util.c
+ $(SRC_DIR)/util.c \
+ $(SRC_DIR)/stab.c
+
GEN_C = tokenfile.c program.c declar.c expression.c statement.c ival.c \
symbol2str.c char.c Lpars.c next.c
CFILES= $(SRC_C) $(GEN_C)
regcount.h \
code.h declar.h decspecs.h def.h expr.h field.h estack.h util.h \
idf.h macro.h stmt.h struct.h switch.h type.h l_brace.h l_state.h \
- l_outdef.h stack.h lapbuf.h noRoption.h nofloat.h
+ l_outdef.h stack.h lapbuf.h noRoption.h nofloat.h dbsymtab.h
HFILES= $(GEN_H) $(SRC_H)
#include "debug.h"
#include "botch_free.h"
+#include "dbsymtab.h"
#include "arith.h"
#include "LLlex.h"
#include "code.h"
#include "stack.h"
#include "def.h"
+#ifdef DBSYMTAB
+#include <stb.h>
+#endif /* DBSYMTAB */
extern int level;
+extern char options[];
}
/* Each statement construction is stacked in order to trace a ???
}
;
-compound_statement:
+compound_statement
+ {
+#ifdef DBSYMTAB
+ static int brc_level = 1;
+ int decl_seen = brc_level == 1;
+#endif /* DBSYMTAB */
+ }
+:
'{'
{
stack_level();
(DOT == IDENTIFIER && AHEAD == IDENTIFIER))
/* >>> conflict on TYPE_IDENTIFIER, IDENTIFIER */
declaration
+ {
+#ifdef DBSYMTAB
+ decl_seen++;
+#endif /* DBSYMTAB */
+ }
]*
+ {
+#ifdef DBSYMTAB
+ ++brc_level;
+ if (options['g'] && decl_seen) {
+ C_ms_std((char *) 0, N_LBRAC, brc_level);
+ }
+#endif /* DBSYMTAB */
+ }
[%persistent
statement
]*
'}'
{
unstack_level();
+#ifdef DBSYMTAB
+ if (options['g'] && decl_seen) {
+ C_ms_std((char *) 0, N_RBRAC, brc_level);
+ }
+ brc_level--;
+#endif /* DBSYMTAB */
}
;
#include "nofloat.h"
#include "nobitfield.h"
+#include "dbsymtab.h"
struct type {
struct type *next; /* used only with ARRAY */
struct type *tp_pointer;/* to POINTER */
struct type *tp_array; /* to ARRAY */
struct type *tp_function;/* to FUNCTION */
+#ifdef DBSYMTAB
+ int tp_dbindex;
+#endif
};
extern struct type