root/usr/src/cmd/sgs/elfedit/common/_elfedit.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef __ELFEDIT_H
#define __ELFEDIT_H

#include        <setjmp.h>
#include        <libtecla.h>
#include        <elfedit.h>

/*
 * Local include file for elfedit.
 */
#ifdef  __cplusplus
extern "C" {
#endif


/*
 * Maximum command line, and history
 */
#define ELFEDIT_MAXCMD  1024
#define ELFEDIT_MAXHIST 1024

/* Maximum number of command completion arguments */
#define ELFEDIT_MAXCPLARGS      128

/* Maximum length of a module name */
#define ELFEDIT_MAXMODNAM       64


/*
 * In elfedit.h, you will find elfedit32_cmd_t and elfedit64_cmd_t
 * typedefs. These types are identical, except for the definition
 * of the cmd_func and cmd_cplfunc function pointers. These function
 * pointers have different argument definitions that reflect the
 * different object state definition blocks for the 32 and 64-bit cases.
 * Yet, From a strictly machine based view, these two types are identical
 * in size and layout:
 *
 *      - At the machine level, all function pointers are simply
 *              machine sized words containing an address.
 *
 *      - Other than the function pointers, the remaining fields
 *              are exactly the same in both cases.
 *
 * The vast majority of elfedit's internals that examine elfedit_cmd_t
 * are looking at the non-function pointer fields. It simplfiies
 * a great deal of code if we can treat elfedit32_cmd_t and elfedit64_cmd_t
 * as equivalent types for this purpose. In C++, we would do this with
 * a superclass. In C, we do it by defining another variant named
 * elfeditGC_cmd_t (GC stands for "Generic Class"). The function pointers
 * are replaced with (void *) pointers. This variant has the same size
 * and layout as the others. We use it internally to represent either type.
 * In the cases where we need to use the function pointers, we first cast
 * them to the proper type for the ELFCLASS being processed.
 *
 * The existance of elfeditGC_cmd_t implies the need for elfeditGC_module_t,
 * for the same reasons.
 *
 * It is extremely important that these definitions exactly mirror the
 * definitions in elfedit.h.
 */
typedef struct {
        void                    *cmd_func;
        void                    *cmd_cplfunc;
        const char              **cmd_name;
        elfedit_i18nhdl_t       cmd_desc;
        elfedit_i18nhdl_t       cmd_help;
        elfedit_cmd_optarg_t    *cmd_opt;
        elfedit_cmd_optarg_t    *cmd_args;
} elfeditGC_cmd_t;


typedef struct {
        elfedit_module_version_t mod_version;
        const char              *mod_name;
        elfedit_i18nhdl_t       mod_desc;
        elfeditGC_cmd_t         *mod_cmds;
        elfedit_mod_i18nhdl_to_str_func_t mod_i18nhdl_to_str;
} elfeditGC_module_t;


/*
 * The result of parsing a user command is one of these blocks entered
 * at the end of state.user_cmd. They encapsulate the arguments and
 * the command function to call. In combination with an elfedit_obj_state_t,
 * they contain everything needed to execute a specified operation. A single
 * call to free() suffices to release the ELFEDIT_USER_CMD and any memory
 * it references.
 */
typedef struct user_cmd_t {
        struct user_cmd_t *ucmd_next;   /* Commands are kept in linked list */
        int             ucmd_argc;      /* # of arguments to command */
        const char      **ucmd_argv;    /* Argument strings */
        char            *ucmd_orig_str; /* Command string as entered by user */
        elfeditGC_module_t *ucmd_mod;   /* Module defining command */
        elfeditGC_cmd_t *ucmd_cmd;      /* Command to call */
        int             ucmd_ostyle_set;        /* True if there is a per-cmd */
                                                /*      output style active */
        elfedit_outstyle_t ucmd_ostyle; /* Per-cmd output style, if active */
} USER_CMD_T;

/*
 * MODLIST_T is used to manage module definitions. Note that a simple linked
 * list is used to maintain the set of active modules. This can be easily
 * changed if the number of modules grows to a point where the lookup
 * time is noticible.
 */
typedef struct moddef_t {
        struct moddef_t         *ml_next;       /* Used for list of open mods */
        elfeditGC_module_t      *ml_mod;        /* The module definition */
        void                    *ml_dl_hdl;     /* dlopen() handle for lib */
        const char              *ml_path;       /* Path used to open lib */
} MODLIST_T;


/*
 * Type of the global variable used to maintain elfedit state.
 */
typedef struct {
        MODLIST_T *modlist;             /* List of loaded commands */
        elfedit_flag_t  flags;          /* ELFEDIT_F_ command line options */
        elfedit_outstyle_t outstyle;    /* Output style */
        struct {
                int present;            /* True if there is a source file. */
                                        /*       False otherwise */
                /*
                 * The remaining file fields are not to be accessed
                 * unless present is True.
                 */
                const char *infile;     /* Name of source file */
                const char *outfile;    /* Name of file being edited */
                int unlink_on_exit;     /* TRUE to unlink outfile on exit  */
                int dirty;              /* TRUE if outfile needs to be saved */
        } file;
        struct {                /* Jump buffer used for ELFEDIT_MSG_ERR */
                int active;     /*      True if MSG_ERR jumps to outer loop */
                sigjmp_buf env; /*      jump environment buffer */
        } msg_jbuf;
        struct {                        /* Search path used to find modules */
                size_t n;               /*      # of path segments */
                const char **seg;       /*      path segments */
        } modpath;
        struct {                /* Linked list of user commands to execute */
                size_t n;               /* # of commands */
                USER_CMD_T *list;       /* head of list */
                USER_CMD_T *tail;       /* points at last element of list */
        } ucmd;
        struct {                        /* Pager related state */
                FILE *fptr;             /* Output file */
        } pager;
        struct {
                int     is_tty;         /* True in stdin is a tty */
                int     full_tty;       /* True if stdin and stdout are tty */
                int     in_tecla;       /* gl_get_line() is active */
                GetLine *gl;            /* getline object */
        } input;
        struct {                /* ELF file state */
                int elfclass;           /* ELFCLASS of file being edited */
                int elfconst_ehdr_change;       /* ELF header has changed. */
                                                /*      Recheck elfconst strs */
                /*
                 * Information for the ELF object being edited.
                 * The value of elfclass determines which of these
                 * fields is valid in the current session. This is
                 * only usable if file.present is True. Otherwise, there
                 * is no object state, and these pointers will be NULL.
                 */
                union {
                        elfedit32_obj_state_t *s32;     /* ELFCLASS32 */
                        elfedit64_obj_state_t *s64;     /* ELFCLASS64 */
                } obj_state;
        } elf;
        USER_CMD_T *cur_cmd;     /* NULL, or currently executing command */
} STATE_T;



/*
 * Type of item argument to elfedit_next_optarg(), used to pull together
 * the information for a single command option or argument, handling
 * the ELFEDIT_CMDOA_F_VALUE and ELFEDIT_CMDOA_F_INHERIT cases.
 */
typedef struct {
        const char              *oai_name;      /* Name of option */
        const char              *oai_vname;     /* Name of value field if */
                                                /* ELFEDIT_CMDOA_F_VALUE */
        elfedit_i18nhdl_t       oai_help;       /* Help text for option */
        elfedit_cmd_oa_flag_t   oai_flags;      /* Additional attributes */
        elfedit_cmd_oa_mask_t   oai_idmask;     /* Returned by elfedit_getopt */
        elfedit_cmd_oa_mask_t   oai_excmask;    /* mutual exclusion mask */
} elfedit_optarg_item_t;



/* Global state is accessible between elfedit files */
extern STATE_T state;

/* Exported by sys.c, used in elfedit.c to initialize builtin sys module */
extern MODLIST_T *elfedit_sys_init(elfedit_module_version_t version);

/* Exported by util.c, used by elfedit.c and sys.c to process output style */
extern int elfedit_atooutstyle(const char *str, elfedit_outstyle_t *outstyle);

/*
 * getopt related routines that are not public
 */
extern void elfedit_set_cmd_outstyle(const char *str);

/* elfedit internal functions used by sys module */
extern void elfedit_exit(int status);
extern elfeditGC_cmd_t *elfedit_find_command(const char *name, int must_exist,
    elfeditGC_module_t **mod_ret);
extern const char *elfedit_format_command_usage(elfeditGC_module_t *mod,
    elfeditGC_cmd_t *cmd, const char *wrap_str, size_t cur_col);
extern elfeditGC_module_t *elfedit_load_module(const char *name, int must_exist,
    int allow_abs_path);
extern void elfedit_load_moddir(const char *dirpath, int must_exist,
    int abs_path);
extern void elfedit_load_modpath(void);
extern void elfedit_unload_module(const char *name);
extern void elfedit_next_optarg(elfedit_cmd_optarg_t **optarg,
    elfedit_optarg_item_t *item);
extern const char *elfedit_optarg_helpstr(elfeditGC_module_t *mod,
    elfedit_optarg_item_t *item);


/* Used by elfedit_getopt_init() to access options array for command */
elfeditGC_cmd_t *elfedit_curcmd(void);

/* elfedit_machelf functions used by elfedit */
extern  void elfedit32_init_obj_state(const char *file, int fd, Elf *elf);
extern  void elfedit64_init_obj_state(const char *file, int fd, Elf *elf);

#ifdef  __cplusplus
}
#endif

#endif  /* __ELFEDIT_H */