Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

sial.c

/*
 * $Id: sial.c,v 1.1 2004/12/21 23:26:17 tjm Exp $
 *
 * This file is part of lcrash, an analysis tool for Linux memory dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, and others
 *
 * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *
 * This program 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 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sial_api.h>
#include <lcrash.h>

/*
      for the moment I hardcode some variables here 
      This needs to be changed when we have a way to grab this
      from the image. I have'nt done it yet. 
      - get the size of type caddr_t
      - get the cpuinfo cpu model to set the ABI.
*/
dbg_sym_t *dbg_find_sym(char *, int, uint64_t);

char * kl_getproducer(void) { return ""; }

/*
      This is the glue between the sial interpreter and icrash.
*/

static int
apigetmem(ull iaddr, void *p, int nbytes)
{
      if(kl_get_block(iaddr, nbytes, p, 0)) return 0;
      return 1;
}

static uint8_t apigetuint8(void* ptr)
{
      return KL_GET_UINT8(ptr);
}

static uint16_t apigetuint16(void* ptr)
{
      return KL_GET_UINT16(ptr);
}

static uint32_t apigetuint32(void* ptr)
{
      return KL_GET_UINT32(ptr);
}

static uint64_t apigetuint64(void* ptr)
{
      return KL_GET_UINT64(ptr);
}

static int
apiputmem(ull iaddr, void *p, int nbytes)
{
      return 1;
}

/* extract a complex type (struct, union and enum) */
static int
apigetctype(int ctype, char *name, TYPE_S *tout)
{
int kltype, stype;
dbg_sym_t *st;

      if(sial_is_struct(ctype)) { stype=DBG_TYPE; kltype=KLT_STRUCT; }
      else if(sial_is_union(ctype))  { stype=DBG_TYPE; kltype=KLT_UNION; }
      else if(sial_is_enum(ctype))   { stype=DBG_TYPE; kltype=KLT_ENUMERATION; }
      else if(sial_is_typedef(ctype)){ stype=DBG_TYPEDEF; kltype=KLT_TYPEDEF; }
      else sial_error("Oops getctype");

      if((st = dbg_find_sym(name, stype, 0))) {

            dbg_type_t *sp=(dbg_type_t *)st->sym_kltype;

            if(sp->st_type == kltype) {

                  /* populate */
                  sial_type_settype(tout, ctype);
                  sial_type_setsize(tout, sp->st_size);
                  sial_type_setidx(tout, st->sym_typenum);
                  sial_pushref(tout, 0);
                  return 1;
            }
      }
      return 0;
}

/* set idx value to actual array indexes from specified size */
static void
sial_setupidx(TYPE_S*t, int ref, int nidx, int *idxlst)
{
        /* put the idxlst in index size format */
        if(nidx) {

                int i;

                for(i=0;i<nidx-1;i++) idxlst[i]=idxlst[i]/idxlst[i+1];

                /* divide by element size for last element bound */
                if(ref) idxlst[i] /= sial_defbsize();
                else idxlst[i] /= sial_type_getsize(t);
                sial_type_setidxlst(t, idxlst);
        }
}
/*
      This function needs to drill down a typedef and
      return the corresponding type.
      If the typedef is from a basetype sial_parsetype() will be
      called back to build the type 
*/
static char *
drilldowntype(kltype_t *kltp, TYPE_S *t)
{
char *tstr=0;
int fctflg=0, ref=0;
int *idxlst=0;
int nidx=0;

      while(kltp)
      {

            switch(kltp->kl_type) {

            case KLT_MEMBER:

                  kltp=kltp->kl_realtype;
            break;

            /* typedef inserts a level of reference to the actual type */
            case KLT_POINTER:
      
                  ref++;
                  /* this could be a void*, in which case the drill down stops here */
                  if(!kltp->kl_realtype) {

                        /* make it a char* */
                        sial_parsetype("char", t, ref);
                        return 0;

                  }
                  kltp=kltp->kl_realtype;
            break;

            /* handle pointer to functions */
            case KLT_FUNCTION:

                  fctflg=1;
                  kltp=kltp->kl_realtype;
            break;

            /* Is this an array ? if so then just skip this type info and
               we only need information on the elements themselves */
            case KLT_ARRAY:

                        if(!idxlst) idxlst=sial_calloc(sizeof(int)*(MAXIDX+1));
                        if(nidx >= MAXIDX) sial_error("Too many indexes! max=%d\n", MAXIDX);
                        idxlst[nidx++]=kltp->kl_high_bounds;
                  kltp=kltp->kl_elementtype;
            break;

            /* typedef points to a typedef itself */
            case KLT_TYPEDEF:

                  kltp=kltp->kl_realtype;
            break;

            case KLT_BASE:

                  sial_parsetype(kltp->kl_name, t, 0);
                  tstr=kltp->kl_typestr;
                  kltp=0;
            break;

            case KLT_UNION: 
                  sial_type_mkunion(t);
                  goto label;

            case KLT_ENUMERATION:
                  sial_type_mkenum(t);
                  goto label;

            case KLT_STRUCT:
            {
            dbg_type_t *sp=(dbg_type_t *)kltp;

                  sial_type_mkstruct(t);

label:
                  if(kltp->kl_typestr /*XXX*/ && strcmp(kltp->kl_typestr,"struct") != 0){ 
                        sial_parsetype(kltp->kl_typestr, t, 0);
                        if(kltp->kl_name)
                              tstr=kltp->kl_name;
                  }
                        
                  else {
                        sial_type_setsize(t, kl_type_size(kltp));
                        sial_type_setidx(t, sp->st_type_num);
                        tstr=0; // XXX kltp->kl_typestr;
                  }
                  kltp=0;
            }
            break;

            /* we don;t have all the info about it */
            case KLT_INCOMPLETE:
            case KLT_UNKNOWN:
            case 100:
                  sial_parsetype("int", t, 0);
                  kltp=0;
            break;


            default: 
                  sial_error("Oops drilldowntype");
            break;
            }


      }
      sial_setupidx(t, ref, nidx, idxlst);
      if(fctflg) sial_type_setfct(t, 1);
      sial_pushref(t, ref+(nidx?1:0));
      if(tstr) return sial_strdup(tstr);
      return sial_strdup("");
}

static char *
apigetrtype(ull idx, TYPE_S *t)
{
dbg_type_t *stp;
kltype_t *kltp;

      if(!(stp = (dbg_type_t *)kl_find_typenum(idx))) return 0;
      // kltp=stp->st_realtype;
      // kltp=kltp->kl_realtype;
      kltp=stp->st_klt.kl_realtype;
      return drilldowntype(kltp, t);
}


/* 
      Get the type, size and position information for a member of a structure.
*/
static char*
apimember(char *mname,  ull tnum, TYPE_S *tm, MEMBER_S *m, ull *lnum)
{
dbg_type_t *sp, *mp;
#define LASTNUM (*lnum)

      /* if we're being asked the next member in a getfirst/getnext sequence */
      if(mname && !mname[0] && LASTNUM) {

            sp = (dbg_type_t *)(unsigned long)LASTNUM;

      } else {

            sp = (dbg_type_t *)kl_find_typenum(tnum);
            if (sp->st_type == KLT_TYPEDEF) {
                  if (!(sp = (dbg_type_t *)sp->st_realtype)) {
                        return 0;
                  }
            }
            if ((sp->st_type != KLT_STRUCT) && (sp->st_type != KLT_UNION)) {
                  return 0;
            }
      }
      if (!sp) return 0;
      mp = (dbg_type_t *)sp->st_member;
      while(mp) {

            if (!mname || !mname[0] || !strcmp(mp->st_name, mname)) {

                  sial_member_soffset(m, mp->st_offset);
                  sial_member_ssize(m, mp->st_size);

                  if(mp->st_size*8 == mp->st_bit_size) 

                        sial_member_snbits(m, 0);
                  else
                        sial_member_snbits(m, mp->st_bit_size);

                  sial_member_sfbit(m, mp->st_klt.kl_bit_offset);
                  sial_member_sname(m, mp->st_klt.kl_name?mp->st_klt.kl_name:"");
if(!strcmp(mp->st_klt.kl_name?mp->st_klt.kl_name:"", "comm")) {

      LASTNUM=LASTNUM;
}
                  LASTNUM=(unsigned long)mp;
                  return drilldowntype(&mp->st_klt, tm);
            }
            mp = (dbg_type_t *)mp->st_member;
      }
      return 0;
}

/*
      This function gets the proper allignment value for a type.
*/
static int
apialignment(ull idx)
{
dbg_type_t *sp;
kltype_t *kltp;

      if(!(sp=(dbg_type_t *)kl_find_typenum(idx))) {

            sial_error("apialignment: type not found %lld", idx);
      }

      kltp=&sp->st_klt;

      while(1)
      {
            switch(kltp->kl_type) {

            /* Is this an array ? if so then just skip this type info and
               we only need information on the elements themselves */
            /* typedef points to a typedef itself */
            case KLT_TYPEDEF:
            case KLT_ARRAY:
            case KLT_MEMBER:

                  kltp=kltp->kl_realtype;
            break;

            case KLT_STRUCT:
            case KLT_UNION:
            {
                  int max=0, cur;
                  dbg_type_t *mp;

                  mp = (dbg_type_t *)sp->st_member;
                  while(mp) {
                        cur=apialignment(mp->st_type_num);
                        if(cur > max) max=cur;
                        mp = (dbg_type_t *)mp->st_member;
                  }
                  return max;
            }

            case KLT_POINTER:

                  /* size should have been already set by us */
                  return sial_defbsize();

            case KLT_ENUMERATION:
            case KLT_BASE:

                  return kltp->kl_size;

            default:

                  sial_error("Oops apialignment");
            }
      }
}

/* get the value of a symbol */
static int
apigetval(char *name, ull *val)
{
syment_t *sym;

      sym=kl_lkup_symname(name);
      if(sym) {

            *val=(ull)sym->s_addr;
            return 1;
      }
      return 0;
}

/*
      Get the list of enum symbols.
*/
ENUM_S*
apigetenum(char *name)
{
dbg_sym_t *st;

      if((st=dbg_find_sym(name, DBG_TYPE, 0))) {

            dbg_type_t *sp=(dbg_type_t *)st->sym_kltype;

            if(sp->st_type == KLT_ENUMERATION) {

                  ENUM_S *et=0;

                  while(sp->st_member) {

                        et=sial_add_enum(et, sial_strdup(sp->st_name), sp->st_value);
                        sp = (dbg_type_t *)sp->st_member;
                  }
                  return et;
            }
        }

      return 0;
}

/*
      Return the list of preprocessor defines.
      For Irix we have to get the die for a startup.c file.
      Of dwarf type DW_TAG_compile_unit.
      the DW_AT_producer will contain the compile line.

      We then need to parse that line to get all the -Dname[=value]
*/
DEF_S *
apigetdefs(void)
{
DEF_S *dt=0;
char *prod, *p, rbuf[40];
int i;
struct linuxdefs_s {

      char *name;
      char *value;

} linuxdefs[] = {

      {"linux",         "1"},
      {"__linux",       "1"},
      {"__linux__",           "1"},
      {"unix",          "1"},
      {"__unix",        "1"},
      {"__unix__",            "1"},
      // helper macros
      {"LINUX_2_2_16",  "(LINUX_RELEASE==0x020210)"},
      {"LINUX_2_2_17",  "(LINUX_RELEASE==0x020211)"},
      {"LINUX_2_4_0",         "(LINUX_RELEASE==0x020400)"},
      {"LINUX_2_2_X",         "(((LINUX_RELEASE) & 0xffff00) == 0x020200)"},
      {"LINUX_2_4_X",         "(((LINUX_RELEASE) & 0xffff00) == 0x020400)"},
      {"LINUX_2_6_X",         "(((LINUX_RELEASE) & 0xffff00) == 0x020600)"},
};

struct archdefs_s {

      int arch;
      struct linuxdefs_s def;

} archdefs[] = {

      {KL_ARCH_I386, {"i386",       "1"}},
      {KL_ARCH_I386, {"__i386",     "1"}},
      {KL_ARCH_I386, {"__i386__",   "1"}},

      {KL_ARCH_S390, {"s390",       "1"}},
      {KL_ARCH_S390, {"__s390",     "1"}},
      {KL_ARCH_S390, {"__s390__",   "1"}},

      {KL_ARCH_S390X, {"s390x",     "1"}},
      {KL_ARCH_S390X, {"__s390x",   "1"}},
      {KL_ARCH_S390X, {"__s390x__", "1"}},

      {KL_ARCH_IA64, {"ia64",       "1"}},
      {KL_ARCH_IA64, {"__ia64",     "1"}},
      {KL_ARCH_IA64, {"__ia64__",   "1"}},
      {KL_ARCH_IA64, {"__LP64__",   "1"}},
      {KL_ARCH_IA64, {"_LONGLONG",  "1"}},
      {KL_ARCH_IA64, {"__LONG_MAX__",     "9223372036854775807L"}},
};
      
      prod=sial_strdup(kl_getproducer());
      for(p=prod; *p; p++) {

            if(*p=='-' && *(p+1)=='D') {

                  char *def=p+2;

                  while(*p && *p != '=' && *p != ' ') p++;

                  if(!*p || *p == ' ') {

                        *p='\0';
                        dt=sial_add_def(dt, sial_strdup(def), sial_strdup("1"));

                  } else {

                        char *val=p+1;

                        *p++='\0';
                        while(*p && *p != ' ') p++;
                        *p='\0';

                        dt=sial_add_def(dt, sial_strdup(def), sial_strdup(val));
                  }
            }
      }
      
      /* insert constant defines from list above */
      for(i=0;i<sizeof(linuxdefs)/sizeof(linuxdefs[0]);i++) {

            dt=sial_add_def(dt, sial_strdup(linuxdefs[i].name), 
                  sial_strdup(linuxdefs[i].value));
      }

      sprintf(rbuf, "0x%08x", KL_LINUX_RELEASE);
      dt=sial_add_def(dt, sial_strdup("LINUX_RELEASE"), sial_strdup(rbuf));

      /* push arch specific macros */
      for(i=0;i<(sizeof(archdefs)/sizeof(archdefs[0])); i++) {

            if(archdefs[i].arch==KL_ARCH) {

                  dt=sial_add_def(dt, sial_strdup(archdefs[i].def.name), 
                         sial_strdup(archdefs[i].def.value));
            }
      }

      return dt;
}

apiops icops= {
      apigetmem, 
      apiputmem, 
      apimember, 
      apigetctype, 
      apigetrtype, 
      apialignment, 
      apigetval, 
      apigetenum, 
      apigetdefs,
      apigetuint8,
      apigetuint16,
      apigetuint32,
      apigetuint64
};

void
sial_version(void)
{
      sial_msg("< Sial interpreter version %d.%d [%s, %s] >\n"
            , S_MAJOR, S_MINOR, __DATE__, __TIME__);
}

static char *
get_ustr(command_t *cmd)
{
char *ustr;
char fname[MAX_SYMNAMELEN+sizeof("_usage")+1];

      snprintf(fname, sizeof(fname), "%s_usage", cmd->command);
      ustr=(char*)(unsigned long)sial_exefunc(fname, 0);
      return ustr;
}

static void
help_callback(command_t *cmd)
{
char fname[MAX_SYMNAMELEN+sizeof("_help")+1];
char *hstr, *ustr=get_ustr(cmd);

      snprintf(fname, sizeof(fname), "%s_help", cmd->command);
      hstr=(char*)(unsigned long)sial_exefunc(fname, 0);
      if(!hstr) sial_msg("NULL help string from function '%s'\n", fname);
      else { CMD_HELP(cmd, ustr, hstr); }
}

static void
usage_callback(command_t *cmd)
{
char *ustr=get_ustr(cmd);

      if(!ustr) sial_msg("NULL usage string for function '%s'\n", cmd->command);
      else CMD_USAGE(cmd, ustr);
}

static int
parse_callback(command_t *cmd)
{
      if (set_cmd_flags(cmd, (C_NO_OPCHECK + C_WRITE), 0)) {
            return(1);
      }
      return 0;
}

static int
run_callback(command_t *cmd)
{
char **myargv=sial_alloc(sizeof(char*)*(cmd->nargs+1));
int i, ret;
void *f;
      
      // we most create a argv[0] and argc most be at least 1
      // argv[0] becomes the command name

      myargv[0]=sial_strdup(cmd->command);
      for(i=0;i< cmd->nargs;i++) myargv[i+1]=cmd->args[i];

      // switch to lcrash output stream
      f=sial_getofile();
      sial_setofile(cmd->ofp);

      ret=sial_cmd(cmd->command, myargv, cmd->nargs+1);

      // go back to previous stream
      sial_setofile(f);

      return ret;
}

static char *
complete_callback(command_t *cmd)
{
      fprintf(cmd->ofp, "\n");
      usage_callback(cmd);
      return(DRAW_NEW_ENTIRE_LINE);
}

/*
      This function is called for every new function
      generated by a load command. This enables us to
      register new commands.

      We check here is the functions:

      fname_help()
      fname_opt()
      and
      fname_usage()

      exist, and if so then we have a new command.
      Then we associated (register) a function with
      the standard sial callbacks.
*/
void
reg_callback(char *name)
{
char fname[MAX_SYMNAMELEN+sizeof("_usage")+1];
_command_t cmds[2];

      snprintf(fname, sizeof(fname), "%s_help", name);
      if(!sial_chkfname(fname, 0)) return;
      snprintf(fname, sizeof(fname), "%s_usage", name);
      if(!sial_chkfname(fname, 0)) return;

      cmds[0].cmd=strdup(name);
      cmds[0].real_cmd=0;
      cmds[0].cmdfunc=run_callback;
      cmds[0].cmdparse=parse_callback;
      cmds[0].cmdusage=usage_callback;
      cmds[0].cmdhelp=help_callback;
      cmds[0].cmdcomplete=complete_callback;
      cmds[1].cmd=0;
      unregister_cmd(cmds[0].cmd);
      (void)register_cmds(cmds);
}

#define _VI_USAGE "function_name | -f sial_file_name"

/*
 * vi_usage() -- vi sial macros
 */
void
vi_usage(command_t *cmd)
{
      CMD_USAGE(cmd, _VI_USAGE);
}

/*
 * vi_cmd()
 */
int
vi_cmd(command_t *cmd)
{
      if(cmd->flags&C_LIST) sial_vilast();
      else {

            if(cmd->args[0]) sial_vi(cmd->args[0], cmd->flags&C_FULL);
            else vi_usage(cmd);
      }
      return(0);
}

/*
 * vi_help() -- Print the help information for the 'vi' command.
 */
void
vi_help(command_t *cmd)
{
      CMD_HELP(cmd, _VI_USAGE,
            "Start a vi session of a sial file or a sial function in particular.");
}

/*
 * vi_complete() -- complete filename for 'vi' command.
 */
char* vi_complete(command_t *cmd)
{
        if ((cmd->nargs > 1) &&
            !strcmp(cmd->args[cmd->nargs - 2],"-f")) {
                return(complete_file_name(cmd->args[cmd->nargs -1], 100));
        } else {
                fprintf(cmd->ofp, "\n");
                vi_usage(cmd);
                return(DRAW_NEW_ENTIRE_LINE);
        }
}

/*
 * vi_parse() -- Parse the command line arguments for 'vi'.
 */
int
vi_parse(command_t *cmd)
{
      if (set_cmd_flags(cmd, (C_FULL|C_LIST), 0)) {
            return(1);
      }
      return 0;
}

#define _LOAD_USAGE "filename|directory"

/*
 * load_usage() -- load sial macros
 */
void
load_usage(command_t *cmd)
{
      CMD_USAGE(cmd, _LOAD_USAGE);
}

/*
 * load_cmd()
 */
int
load_cmd(command_t *cmd)
{
      if(lcrash_debug) {

            sialdebug=1;
            sialppdebug=1;

      } else {

            sialdebug=0;
            sialppdebug=0;
      }
      if(!cmd->args[0]) load_usage(cmd);
      else sial_loadunload(1, cmd->args[0], 0);
      return(0);
}

/*
 * load_help() -- Print the help information for the 'load' command.
 */
void
load_help(command_t *cmd)
{
      CMD_HELP(cmd, _LOAD_USAGE,
            "Load a sial macro from a file or a directory. In the case of a directory, "
            "all files in that directory will be loaded.");
}

/*
 * load_complete() -- complete filenames for 'load' command.
 */
char*
load_complete(command_t *cmd)
{
      if ((cmd->nargs == 1)) {
            return(complete_file_name(cmd->args[cmd->nargs -1],100));
      }
      fprintf(cmd->ofp, "\n");
        load_usage(cmd);
        return(DRAW_NEW_ENTIRE_LINE);
}

/*
 * load_parse() -- Parse the command line arguments for 'load'.
 */
int
load_parse(command_t *cmd)
{
      return(0);
}

#define _UNLOAD_USAGE "filename|directory"

/*
 * unload_usage() -- unload sial macros
 */
void
unload_usage(command_t *cmd)
{
      CMD_USAGE(cmd, _UNLOAD_USAGE);
}

/*
 * unload_cmd()
 */
int
unload_cmd(command_t *cmd)
{
      if(!cmd->args[0]) unload_usage(cmd);
      else sial_loadunload(0, cmd->args[0], 0);
      return(0);
}

/*
 * unload_help() -- Print the help information for the 'unload' command.
 */
void
unload_help(command_t *cmd)
{
      CMD_HELP(cmd, _UNLOAD_USAGE,
            "Unload a file or a directory. In the case of a directory, "
            "all files in that directory will be unloaded.");
}

/*
 * unload_complete() -- complete filenames for 'unload' command.
 */
char*
unload_complete(command_t *cmd)
{
      if ((cmd->nargs == 1)) {
            return(complete_file_name(cmd->args[cmd->nargs -1],100));
      }
      fprintf(cmd->ofp, "\n");
        unload_usage(cmd);
        return(DRAW_NEW_ENTIRE_LINE);
}

/*
 * unload_parse() -- Parse the command line arguments for 'unload'.
 */
int
unload_parse(command_t *cmd)
{
      return 0;
}

static  _command_t  sial_cmds[] = {

      {"vi", 0, vi_cmd, vi_parse, vi_help, vi_usage, vi_complete},
      {"load", 0, load_cmd, load_parse, load_help, load_usage, load_complete},
      {"unload", 0, unload_cmd, unload_parse, unload_help, unload_usage, unload_complete},
      {(char *)0 }
};

// some builtins
VALUE_S*
settask(VALUE_S* vtask, ...)
{
      return sial_makebtype(
            kl_set_deftask((kaddr_t)sial_getval(vtask))
         );
}

void
init_sial(char *M_val, char *I_val)
{
#define LCDIR "/usr/share/sial/lcrash"
#define LCIDIR "include"
#define LCUDIR ".lcrash"


      if(sial_open() >= 0) {

            char *path, *ipath;
            char *homepath=0;
                  char *home=getenv("HOME");

            /* set api, default size, and default sign for types */
            sial_apiset(&icops, KL_ARCH == KL_ARCH_I386 ? ABI_INTEL_X86 : ABI_INTEL_IA, KL_NBPW, 0);

            /* send a message to the user
            sial_msg("\n\n");
            sial_version(); */

            /* set the macro search path */
            if(!(path=M_val) && !(path=getenv("LC_MPATH"))) {

                  if(home) {

                              path=sial_alloc(strlen(home)+sizeof(LCUDIR)+sizeof(LCDIR)+4);
                        homepath=sial_alloc(strlen(home)+sizeof(LCUDIR)+2);

                        /* build a path for call to sial_load() */
                        strcpy(homepath, home);
                        strcat(homepath, "/");
                        strcat(homepath, LCUDIR);

                        /* built the official path */
                              strcpy(path, LCDIR);
                              strcat(path, ":");
                              strcat(path, home);
                              strcat(path, "/");
                        strcat(path, LCUDIR);
                  }
                  else path=LCDIR;
            }
            sial_setmpath(path);

            /* include path */
            if(!(ipath=I_val) && !(ipath=getenv("LC_IPATH"))) {

                  if(home) {

                              ipath=sial_alloc(strlen(home)+sizeof(LCDIR)+sizeof(LCUDIR)+(sizeof(LCIDIR)*2)+(sizeof("/usr/include")+2)+6);

                        /* built the official path */
                              strcpy(ipath, LCDIR);
                              strcat(ipath, "/"LCIDIR":");
                              strcat(ipath, home);
                              strcat(ipath, "/");
                        strcat(ipath, LCUDIR);
                        strcat(ipath, "/"LCIDIR);
                        strcat(ipath, ":/usr/include");
                  }
                  else ipath=LCDIR"/"LCIDIR;
            }
            sial_setipath(ipath);

            /* set the new function callback */
            sial_setcallback(reg_callback);

            /* load the default macros */
            sial_loadall();

            /* our builtins */
            sial_builtin("int settask(struct task_struct*)", settask);

            /* load some sial specific commands */
            register_cmds(sial_cmds);
      }
}


Generated by  Doxygen 1.6.0   Back to index