objprs.h
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C头文件 代码 · 共 256 行
H
256 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#ifndef PRSOBJ_H
#define PRSOBJ_H 1
#include <stddef.h>
#include "objrec.h"
#include "watcom.h"
#include "pcobj.h"
#include "queue.h"
#include "objio.h"
/*
The object file parser performs a pass over the object file. For
each record a series of steps are taken, and these steps may be
intercepted mid-stream by filters outside of the object file
parser. This works in the following manner:
1) The parser reads a record.
2) If the record is a record which affects the state of the parser
(i.e., LNAMES, EXTDEF, SEGDEF, ...) then the parser updates its
state accordingly.
3) The record is passed to the each filter in the list for this command
in reverse order of their registration. (i.e., last registered
gets the record first). If any of the routines returns -1, then
the record is not passed any further.
4) If the record was MODEND, then quit
5) Go to step 1
EACH FILTER MUST CONFORM TO THESE GUIDELINES!
In particular, if a filter must move the record pointer it should
return it to its proper spot. This may entail a simple ObjRSeek( objr, 0 )
or it might take a combo: offset = ObjRTell( objr ); ...work...;
ObjRSeek( objr, offset ).
A filter MAY ASSUME that the following are true (by command):
COMENT:
objr->d.coment.attr = ObjGet8( objr );
objr->d.coment.class = ObjGet8( objr );
Record pointer is at first character after the attr and class bytes.
CMT_EASY_OMF and CMT_MS_OMF are detected and are not passed on.
MODEND:
objr->d.modend has been initialized
ObjDetachData( objr ) has been performed.
LNAMES:
objr->d.lnames.first_idx = index of first name in record
objr->d.lnames.num_names = number of names in record
record pointer is at end of record
SEGDEF:
objr->d.segdef.idx = index of this segdef
the remainder of objr->d.segdef has been preprocessed
ObjDetachData( objr ) has been performed; thus, no attempt should
be made to access data in the record.
EXTDEF, STATIC_EXTDEF:
objr->d.extdef.first_idx = index of first name in record
objr->d.extdef.num_names = number of names in record
record pointer is at end of record
COMDEF, STATIC_COMDEF:
objr->d.comdef.first_idx = index of first name in record
objr->d.comdef.num_names = number of names in record
record pointer is at end of record
FIXUP:
objr->d.fixup.idx_last_data = seg index from most recent le/lidata
objr->d.fixup.offset_last_data = offset from most recent le/lidata
objr->d.fixup.fixup = linked list of processed fixups
The fixups can be "stolen" if the record is not going to be
passed on. i.e., the WATPRS FIXUP filter steals all the fixups
for the $$TYPES and $$SYMBOLS segments. This eliminates the
need to use FixDup and saves memory.
ObjDetachData( objr ) has been performed; don't read data.
Thread fixups don't exist internally; any fixup record containing
just threads is not passed on from the preprocessor.
LEDATA, LIDATA:
objr->d.ledata.idx = segment index from record
objr->d.ledata.offset = offset from record
record pointer is just after data offset field (first byte of data)
GRPDEF:
objr->d.grpdef.idx = index of this grpdef
record pointer is at beginning of record
LINNUM:
objr->d.linnum.base contains the base descriptor
objr->d.linnum.num_lines contains the number of lines in the record
objr->d.linnum.lines points to an array of num_lines linnum_datas.
ObjDetachData( objr ) has been performed.
PUBDEF:
objr->d.pubdef.base contains the base descriptor
objr->d.pubdef.num_pubs contains the number of pubs in the array
objr->d.pubdef.pubs is an array of num_pubs pubdef_datas
ObjDetachData( objr ) has been performed.
All other record types:
No preprocessing is done. Record pointer is at beginning of record.
This is subject to change as there is need to preprocess more record
types.
It is safe to modify the record before passing it on.
Note that certain records must always be passed on (i.e., SEGDEF, EXTDEF,
GRPDEF, LNAMES and their 32-bit counterparts) in order to maintain the
index ordering of the original object file. If you want to "eliminate"
one of these records, then you should just munge the fields to some non-
obtrusive values. i.e., for SEGDEF you should make it combinable
(COMB_ADDOFF) and set the seg_length to zero. Any filter may assume that
an obj_rec pointer passed for one of these records will not be ObjKillRec'd
until all passes are complete.
During READ_PASS, if all filters return 0, then the record is stored in a
linked list of all records in the file. The records used during WRITE_PASS
come from this linked list of records left over from READ_PASS.
ObjKillRec( objr ) is performed on all records regardless of the return
values from the filters during WRITE_PASS.
The parser assumes during READ_PASS that if a filter returns -1, then it
has "taken over" the obj_rec. i.e., the filter will ensure that the obj_rec
is ObjKillRec'd at an appropriate time.
An LEDATA can't be ObjKillRec'd until all FIXUPs for that LEDATA have been
read. i.e., an LEDATA can't be ObjKillRec'd until the next LE/LIDATA.
Further, those FIXUPs belong to the LEDATA and must be killed if the
LEDATA is killed (sound like fun?). The same applies to LIDATAs.
Filters are allowed to unregister themselves, or any filter that is called
before they are in the chain.
The MS386 32-bit record types (LIDA32, LEDA32, ...) are passed as their
16-bit counterparts, with the is_32 bit set in the obj_rec structure.
During the WRITE_PASS, this is the ordering of the records:
THEADR
( LNAMES | LLNAMES | SEGDEF | GRPDEF | COMENT ) *
( EXTDEF | STATIC_EXTDEF | COMDEF | STATIC_COMDEF | COMENT | CEXTDF ) *
( PUBDEF | STATIC_PUBDEF | COMENT ) *
-- LAST_DEFN is called here
( LEDATA | LIDATA | FIXUP | COMENT | LINNUM |
COMDAT | BAKPAT | LINSYM ) *
MODEND
*/
typedef struct {
uint_8 pass; /* current pass number */
OBJ_WFILE *file_out; /* output file pointer */
} pobj_state;
typedef int (*pobj_filter)( obj_rec *objr, pobj_state *state );
/* for lists of filters... */
typedef struct {
uint_8 command;
uint_8 pass;
pobj_filter func;
} pobj_list;
#define POBJ_ALL_PASSES 0 /* invoke filter on all passes */
#define POBJ_READ_PASS 1 /* invoke filter on the read pass only */
#define POBJ_WRITE_PASS 2 /* invoke filter on the write pass only */
enum extra_commands {
/* our effective minimum command (should be == 0(mod2)) */
CMD_POBJ_MIN_CMD = ( CMD_MIN_CMD - 1 ) & ~1,
/* the number of extra commands goes here ^^^ */
CMD_LAST_DEFN = CMD_POBJ_MIN_CMD
/* each extra command should be == 0 (mod2), so add 2 to previous */
};
#if _WOMP_OPT & _WOMP_EXTRAS
typedef struct {
size_t page_len;
uint_8 is_lib : 1;
} pobj_lib_info;
#endif
extern uint_16 ObjDGROUPIndex;
extern uint_16 ObjFLATIndex;
#if _WOMP_OPT & _WOMP_EXTRAS
extern void PObjInit( void );
extern int PObj( OBJ_RFILE *file_in, OBJ_WFILE *file_out, pobj_lib_info *pli );
#else
extern void PObjInit( OBJ_WFILE *file_out );
#endif
extern void PObjFini( void );
extern void PObjRegister( uint_8 command, uint_8 pass, pobj_filter func );
extern void PObjRegList( const pobj_list *list, size_t len );
extern void PObjUnRegister( uint_8 command, uint_8 pass, pobj_filter func );
extern void PObjUnRegList( const pobj_list *list, size_t len );
/*
PObjEnqueue will add a record between the current one and the next one.
Actually, it maintains a queue that is added when all filters have seen
the current record. This function is only valid during POBJ_WRITE_PASS.
*/
extern void PObjEnqueue( obj_rec *objr );
extern void PObjJoinQueue( qdesc *q );
/*
The following PObjNew functions are used to enqueue new records that are
position dependant in the object file. The call will reserve 1 (or more)
LNAMES, SEGDEFs, etc., PObjEnqueue the record, and return you a pointer.
Thus they are only valid during pass 2. Furthermore, you must ensure that
you call these functions AFTER the last LNAMES, SEGDEF, etc. has been
processed. (It is safe to call if the last LNAME, etc is the current
record.) See CAN2MS0.C for an example.
*/
extern obj_rec *PObjNewLnames( uint_16 num );
extern obj_rec *PObjNewSegdef( void );
extern obj_rec *PObjNewGrpdef( void );
#if _WOMP_OPT & _WOMP_EXTRAS
/*
Used by pubdef.c
*/
extern qdesc *PObjPubdefQueue( void );
#endif
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?