📄 pc3.c
字号:
} /* * something is wrong * if it's not resolved, use the header file * otherwise, it's just a regular error */ if ( symbolp -> sym_un.sym_str.rfilep == NIL ) { error( ERROR , "%s, line %d: %s is already defined\n\t(%s, line %d)." , ifilep -> name , nlp -> n_value , nlp -> n_un.n_name , symbolp -> sym_un.sym_str.fromi -> name , symbolp -> sym_un.sym_str.iline ); return; } break; case N_PGFUNC: case N_PGPROC: /* * functions may not be seen more than once. * the loader will complain about * `multiply defined', but we can, too. */ break; case N_PGLABEL: case N_PGCONST: case N_PGTYPE: case N_PGVAR: /* * labels, constants, types, variables * and external declarations * may be seen as many times as they want, * as long as they come from the same include file. * make it look like they come from this .p file. */included: if ( nlp -> n_desc != symbolp -> desc || symbolp -> sym_un.sym_str.fromi != ifilep ) { break; } symbolp -> fromp = pfilep; return; case N_PLDATA: case N_PLTEXT: switch ( nlp -> n_desc ) { default: error( FATAL , "pc3: unknown stab 0x%x" , nlp -> n_desc ); return; case N_PSO: case N_PSOL: case N_PGCONST: case N_PGTYPE: /* these won't conflict with library */ return; case N_PGLABEL: case N_PGVAR: case N_PGFUNC: case N_PGPROC: case N_PEFUNC: case N_PEPROC: case N_PLDATA: case N_PLTEXT: errtype = WARNING; break; } break; } /* * this is the breaks */ error( errtype , "%s, line %d: %s %s is already defined\n\t%s%s (%s, line %d)." , ifilep -> name , nlp -> n_value , classify( nlp -> n_desc ) , nlp -> n_un.n_name , ( symbolp -> desc == nlp -> n_desc ? "" : " as " ) , ( symbolp -> desc == nlp -> n_desc ? "" : article( symbolp -> desc ) ) , symbolp -> sym_un.sym_str.rfilep -> name , symbolp -> sym_un.sym_str.rline ); } } /* * quadratically hashed symbol table. * things are never deleted from the hash symbol table. * as more hash table is needed, * a new one is alloc'ed and chained to the end. * search is by rehashing within each table, * traversing chains to next table if unsuccessful. */struct symbol *entersymbol( name ) char *name; { static struct symboltableinfo symboltable; char *enteredname; long hashindex; register struct symboltableinfo *tablep; register struct symbol **herep; register struct symbol **limitp; register long increment; enteredname = enterstring( name ); hashindex = SHORT_ABS( ( long ) enteredname ) % SYMBOLPRIME; for ( tablep = &symboltable ; /*return*/ ; tablep = tablep -> chain ) { if ( tablep == NIL ) {# ifdef SPACEDEBUG fprintf( stderr , "[entersymbol] calloc'ing table for %d symbols\n" , SYMBOLPRIME );# endif SPACEDEBUG for ( tablep = &symboltable ; tablep->chain != NIL ; tablep = tablep->chain ) { continue; } tablep->chain = ( struct symboltableinfo * ) calloc( 1 , sizeof ( struct symboltableinfo ) ); if ( tablep->chain == NIL ) { error( FATAL , "ran out of memory (entersymbol)" ); } tablep = tablep->chain; } herep = &( tablep -> entry[ hashindex ] ); limitp = &( tablep -> entry[ SYMBOLPRIME ] ); increment = 1; do { if ( *herep == NIL ) { /* empty */ if ( tablep -> used > ( ( SYMBOLPRIME / 4 ) * 3 ) ) { /* too full, break for next table */ break; } tablep -> used++; *herep = symbolalloc(); ( *herep ) -> name = enteredname; ( *herep ) -> lookup = NEW;# ifdef HASHDEBUG fprintf( stderr , "[entersymbol] name %s NEW after %d\n" , enteredname , increment / 2 );# endif HASHDEBUG return *herep; } /* a find? */ if ( ( *herep ) -> name == enteredname ) { ( *herep ) -> lookup = OLD;# ifdef HASHDEBUG fprintf( stderr , "[entersymbol] name %s OLD at %d\n" , enteredname , increment / 2 );# endif HASHDEBUG return *herep; } herep += increment; if ( herep >= limitp ) { herep -= SYMBOLPRIME; } increment += 2; } while ( increment < SYMBOLPRIME );# ifdef HASHDEBUG fprintf( stderr , "[entersymbol] next symboltable\n" );# endif HASHDEBUG } } /* * allocate a symbol from the dynamically allocated symbol table. */struct symbol *symbolalloc() { static struct symbol *nextsymbol = NIL; static long symbolsleft = 0; struct symbol *newsymbol; if ( symbolsleft <= 0 ) {# ifdef SPACEDEBUG fprintf( stderr , "[symbolalloc] malloc space for %d symbols\n" , SYMBOLALLOC / sizeof( struct symbol ) );# endif SPACEDEBUG nextsymbol = ( struct symbol * ) malloc( SYMBOLALLOC ); if ( nextsymbol == 0 ) { error( FATAL , "ran out of memory (symbolalloc)" ); } symbolsleft = SYMBOLALLOC / sizeof( struct symbol ); } newsymbol = nextsymbol; nextsymbol++; symbolsleft--; return newsymbol; } /* * hash a string based on all of its characters. */longhashstring( string ) char *string; { register char *cp; register long value; value = 0; for ( cp = string ; *cp ; cp++ ) { value = ( value * 2 ) + *cp; } return value; } /* * quadratically hashed string table. * things are never deleted from the hash string table. * as more hash table is needed, * a new one is alloc'ed and chained to the end. * search is by rehashing within each table, * traversing chains to next table if unsuccessful. */char *enterstring( string ) char *string; { static struct stringtableinfo stringtable; long hashindex; register struct stringtableinfo *tablep; register char **herep; register char **limitp; register long increment; hashindex = SHORT_ABS( hashstring( string ) ) % STRINGPRIME; for ( tablep = &stringtable ; /*return*/ ; tablep = tablep -> chain ) { if ( tablep == NIL ) {# ifdef SPACEDEBUG fprintf( stderr , "[enterstring] calloc space for %d strings\n" , STRINGPRIME );# endif SPACEDEBUG for ( tablep = &stringtable ; tablep->chain != NIL ; tablep = tablep->chain ) { continue; } tablep->chain = ( struct stringtableinfo * ) calloc( 1 , sizeof ( struct stringtableinfo ) ); if ( tablep->chain == NIL ) { error( FATAL , "ran out of memory (enterstring)" ); } tablep = tablep->chain; } herep = &( tablep -> entry[ hashindex ] ); limitp = &( tablep -> entry[ STRINGPRIME ] ); increment = 1; do { if ( *herep == NIL ) { /* empty */ if ( tablep -> used > ( ( STRINGPRIME / 4 ) * 3 ) ) { /* too full, break for next table */ break; } tablep -> used++; *herep = charalloc( strlen( string ) ); strcpy( *herep , string );# ifdef HASHDEBUG fprintf( stderr , "[enterstring] string %s copied after %d\n" , *herep , increment / 2 );# endif HASHDEBUG return *herep; } /* quick, check the first chars and then the rest */ if ( **herep == *string && strcmp( *herep , string ) == 0 ) {# ifdef HASHDEBUG fprintf( stderr , "[enterstring] string %s found after %d\n" , *herep , increment / 2 );# endif HASHDEBUG return *herep; } herep += increment; if ( herep >= limitp ) { herep -= STRINGPRIME; } increment += 2; } while ( increment < STRINGPRIME );# ifdef HASHDEBUG fprintf( stderr , "[enterstring] next stringtable\n" );# endif HASHDEBUG } } /* * copy a string to the dynamically allocated character table. */char *charalloc( length ) register long length; { static char *nextchar = NIL; static long charsleft = 0; register long lengthplus1 = length + 1; register long askfor; char *newstring; if ( charsleft < lengthplus1 ) { askfor = lengthplus1 > CHARALLOC ? lengthplus1 : CHARALLOC;# ifdef SPACEDEBUG fprintf( stderr , "[charalloc] malloc space for %d chars\n" , askfor );# endif SPACEDEBUG nextchar = ( char * ) malloc( askfor ); if ( nextchar == 0 ) { error( FATAL , "no room for %d characters" , askfor ); } charsleft = askfor; } newstring = nextchar; nextchar += lengthplus1; charsleft -= lengthplus1; return newstring; } /* * read an archive header for the next element * and find the offset of the one after this. */BOOLnextelement( ofilep ) struct fileinfo *ofilep; { register char *cp; register long red; register off_t arsize; struct ar_hdr archdr; fseek( ofilep -> file , ofilep -> nextoffset , 0 ); red = fread( (char *) &archdr , 1 , sizeof archdr , ofilep -> file ); if ( red != sizeof archdr ) { return FALSE; } /* null terminate the blank-padded name */ cp = &archdr.ar_name[ ( sizeof archdr.ar_name ) - 1 ]; *cp = '\0'; while ( *--cp == ' ' ) { *cp = '\0'; } /* set up the address of the beginning of next element */ arsize = atol( archdr.ar_size ); /* archive elements are aligned on 0 mod 2 boundaries */ if ( arsize & 1 ) { arsize += 1; } ofilep -> nextoffset = ftell( ofilep -> file ) + arsize; /* say we had one */ return TRUE; } /* * variable number of arguments to error, like printf. */error( type , message , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7 , arg8 ) int type; char *message; { errors = type > errors ? type : errors; if ( wflag && type == WARNING ) { return; } fprintf( stderr , "%s: " , program ); switch ( type ) { case WARNING: fprintf( stderr , "Warning: " ); break; case ERROR: fprintf( stderr , "Error: " ); break; case FATAL: fprintf( stderr , "Fatal: " ); break; default: fprintf( stderr , "Ooops: " ); break; } fprintf( stderr , message , arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8 ); fprintf( stderr , "\n" ); if ( type == FATAL ) { exit( FATAL ); } }char *classify( type ) unsigned char type; { switch ( type ) { case N_PSO: return "source file"; case N_PSOL: return "include file"; case N_PGLABEL: return "label"; case N_PGCONST: return "constant"; case N_PGTYPE: return "type"; case N_PGVAR: return "variable"; case N_PGFUNC: return "function"; case N_PGPROC: return "procedure"; case N_PEFUNC: return "external function"; case N_PEPROC: return "external procedure"; case N_PLDATA: return "library variable"; case N_PLTEXT: return "library routine"; default: return "unknown symbol"; } }char *article( type ) unsigned char type; { switch ( type ) { case N_PSO: return "a source file"; case N_PSOL: return "an include file"; case N_PGLABEL: return "a label"; case N_PGCONST: return "a constant"; case N_PGTYPE: return "a type"; case N_PGVAR: return "a variable"; case N_PGFUNC: return "a function"; case N_PGPROC: return "a procedure"; case N_PEFUNC: return "an external function"; case N_PEPROC: return "an external procedure"; case N_PLDATA: return "a library variable"; case N_PLTEXT: return "a library routine"; default: return "an unknown symbol"; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -