home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / gnu / utlsrc33.lzh / UTLSRC33 / STRIP.C < prev    next >
C/C++ Source or Header  |  1993-07-30  |  17KB  |  748 lines

  1. /*
  2.  *    strip TOS executable format files of symbol table info
  3.  *    usage: strip {-g | -k | -l names} [-t] files ...
  4.  *
  5.  *    Original version by ++jrb    bammi@dsrgsun.ces.cwru.edu
  6.  *    (i.e. Jwahar Bammi)
  7.  *    Modified to add extra options -g -k and -l by
  8.  *    Michal Jaegermann        ntomczak@ualtavm.bitnet
  9.  *    November 1st, 1990
  10.  *
  11.  *    -g    keep all global symbols
  12.  *    -k    keep _stksize symbol, so stack size can be adjusted
  13.  *        even for nearly-stripped gcc produced executables
  14.  *    -l nms    keep all symbols listed in a file 'nms'
  15.  *    -t    remove additional data from end of file
  16.  *
  17.  *    Modified sources compile both with gcc and Sozobon C
  18.  *
  19.  *      Added code to deal correctly with extended symbols produced
  20.  *      by -G option of gcc
  21.  *      Both -k and -l options convert extended symbols into
  22.  *      regular ones.
  23.  *
  24.  *    ++jrb 4/25/91: 
  25.  *    Macroized the code to take care of WORD_ALIGNED cross environments.
  26.  *    Minor fixes for a !atari !gcc compiler.   
  27.  *
  28.  *    AL 08/02/92:        (alexlehm@iti.informatik.th-darmstadt.de)
  29.  *    Added -t option to strip TurboC / PureC style executables
  30.  *    Support for little endian (BYTE_SWAPed) machines
  31.  */
  32.  
  33. #include <stdio.h>
  34. #ifdef atarist
  35. #ifdef __GNUC__
  36. #  include <stddef.h>
  37. #  include <memory.h>
  38. #  include <unixlib.h>
  39. #else
  40. #include <malloc.h>
  41. extern long lread();
  42. extern long lwrite();
  43. extern long lseek();
  44. #endif
  45. #endif
  46.  
  47. #ifdef unix
  48. #  include <strings.h>
  49. #  define lwrite write
  50. #  define lread  read
  51.    extern char *malloc(), *realloc();
  52. #else
  53. #  include <string.h>
  54. #endif
  55.  
  56. #include <fcntl.h>
  57.  
  58. #define NEWBUFSIZ    16384L
  59.  
  60. char            mybuf[NEWBUFSIZ];
  61. char            tmpname[128];
  62.  
  63. #define SYMLEN 8
  64. #define GST_SYMLEN 22
  65.  
  66. typedef char    symstr_t[GST_SYMLEN];
  67. symstr_t        stklist[] = {"__stksize", "__initial_stack"};
  68.  
  69. #ifdef atarist
  70. long            _stksize = 1L;
  71. #endif
  72.  
  73. #ifndef __PROTO
  74. #  if __STDC__ || __cplusplus
  75. #   define __PROTO(s) s
  76. #  else
  77. #   define __PROTO(s) ()
  78. #  endif
  79. #endif
  80.  
  81. /* function pointer type for the select functions */
  82. typedef long (*select_fp) __PROTO((int, int, long, symstr_t *));
  83.  
  84. void usage __PROTO((char *s ));
  85. int main __PROTO((int argc , char **argv ));
  86. int strip __PROTO((char *name,symstr_t *nmlist,select_fp select,int cuttrail));
  87. long copy __PROTO((int from , int to , long bytes ));
  88. long copy_relo __PROTO((char *name,int from,int to));
  89. void report __PROTO((char *s ));
  90. symstr_t *mklist __PROTO((char *fname ));
  91. long sel_globs __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
  92. long sel_listed __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
  93. extern char    *getenv __PROTO((const char *));
  94.  
  95. int 
  96. main (argc, argv)
  97.     int             argc;
  98.     char          **argv;
  99. {
  100.     int             status = 0;
  101.     int             flag = -1;
  102.     int             cuttrail = 0;
  103.     symstr_t       *nmlist = (symstr_t *) 0;
  104.     select_fp       select=(select_fp)NULL;
  105. #ifdef atarist
  106.     char           *tmpdir;
  107.     register int    l;
  108. #endif
  109.  
  110.     /* process arguments */
  111.     while (argv++, --argc) {
  112.     if ('-' != **argv)
  113.         break;
  114.     (*argv)++;
  115.     if( **argv=='t' ) {
  116.         cuttrail = 1;
  117.     } else {
  118.         if ((-1) != flag)
  119.         usage ("only one option at a time is accepted\n");
  120.         flag = **argv;
  121.         switch (flag) {
  122.         case 'g':
  123.             select = sel_globs;
  124.         break;
  125.         case 'k':
  126.             nmlist = stklist;
  127.         select = sel_listed;
  128.         break;
  129.         case 'l':
  130.         (*argv)++;
  131.         if ('\0' == **argv) {
  132.             --argc;
  133.             argv++;
  134.             if( argc==0 )
  135.                 usage("missing names file\n");
  136.         }
  137.         if ((symstr_t *) NULL == (nmlist = mklist (*argv)))
  138.             usage ("cannot create a list of reserved names\n");
  139.         select = sel_listed;
  140.         break;
  141.         default:
  142.         usage ("");
  143.         break;
  144.         }
  145.     }
  146.     }
  147.  
  148.     if (argc < 1) {
  149.     usage ("");
  150.     }
  151.  
  152. #ifdef __GNUC__
  153. #ifdef atarist
  154.     tmpname[0] = '\0';
  155.     if ((tmpdir = getenv ("TEMP")) != NULL) {
  156.     strcpy (tmpname, tmpdir);
  157.     l = (int) strlen (tmpname) - 1;
  158.     if (tmpname[l] == '\\')
  159.         tmpname[l] = '\0';
  160.     }
  161.     strcat (tmpname, "\\STXXXXXX");
  162. #else
  163.     strcpy (tmpname, "/tmp/STXXXXXX");
  164. #endif
  165.  
  166.     mktemp (tmpname);
  167. #else /* not __GNUC__ */
  168. #  ifdef atarist
  169.     if ((tmpdir = getenv ("TEMP")) != NULL) {
  170.     strcpy (tmpname, tmpdir);
  171.     l = (int) strlen (tmpname) - 1;
  172.     if (tmpname[l] != '\\') {
  173.         l++;
  174.         tmpname[l] = '\\';
  175.     }
  176.     l++;
  177.     }
  178.     else {
  179.     l = 0;
  180.     }
  181.     tmpnam (&tmpname[l]);
  182. #  else
  183.     strcpy (tmpname, "/tmp/STXXXXXX");
  184.     mktemp(tmpname);
  185. #  endif    
  186. #endif /* __GNUC__ */
  187.     do {
  188.     status |= strip (*argv++, nmlist, select, cuttrail);
  189.     } while (--argc > 0);
  190.  
  191.     unlink (tmpname);
  192.     return status;
  193. }
  194.  
  195. void
  196. usage (s)
  197.     char           *s;
  198. {
  199.     report (s);
  200.     report ("Usage: strip {-k | -l names | -g} [-t] files ...\n");
  201.     exit (1);
  202. }
  203.  
  204. /* define macro for big and function for little endian machines */
  205. #ifdef BYTE_SWAP
  206. short swap_short __PROTO((short s));
  207. long swap_long __PROTO((long l));
  208. #else
  209. #define swap_short(s) (s)
  210. #define swap_long(l) (l)
  211. #endif
  212.  
  213. #if (defined(__GNUC__)) && (!defined(unix))
  214. #include <st-out.h>
  215. #else
  216. /* include relevant fragments of <st-out.h> file directly */
  217.  
  218. struct aexec {
  219.      short    a_magic;    /* magic number */
  220. unsigned long    a_text;        /* size of text segment */
  221. unsigned long    a_data;        /* size of initialized data */
  222. unsigned long    a_bss;        /* size of uninitialized data */
  223. unsigned long    a_syms;        /* size of symbol table */
  224. unsigned long    a_AZero1;    /* always zero */
  225. unsigned long    a_AZero2;    /* always zero */
  226. unsigned short    a_isreloc;    /* is reloc info present */
  227. };
  228. #define    CMAGIC    0x601A        /* contiguous text */
  229.  
  230. /*
  231.  * Format of a symbol table entry
  232.  */
  233. struct    asym 
  234.     {
  235.     char        a_name[SYMLEN];    /* symbol name */
  236.     unsigned short    a_type;        /* type flag   */
  237.     unsigned long    a_value;    /* value of this symbol
  238.                        (or sdb offset) */
  239.     };
  240.  
  241. #define A_GLOBL    0x2000        /* global */
  242. #define A_LNAM  0x0048        /* extended name */
  243.  
  244. #endif /* __GNUC__ */
  245.  
  246. #if !__STDC__ && !__cplusplus
  247. #  ifndef offsetof
  248. #    define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0L)->MEMBER)
  249. #  endif
  250. #  ifndef CROSSHPUX
  251.      typedef unsigned long size_t;
  252. #  endif
  253. #endif
  254.  
  255. #ifdef WORD_ALIGNED
  256. # define SIZEOF_AEXEC ((2*sizeof(short)) + (6*sizeof(long)))
  257. # define SIZEOF_ASYM  ((SYMLEN*sizeof(char)) + sizeof(short) + sizeof(long))
  258. # define SYM_OFFSET   (sizeof(short) + (3*sizeof(long)))
  259.   int read_head __PROTO((int fd, struct aexec *a));
  260. #else
  261. # define SIZEOF_AEXEC (sizeof(struct aexec))
  262. # define SIZEOF_ASYM  (sizeof(struct asym))
  263. # define SYM_OFFSET   (offsetof (struct aexec, a_syms))
  264. #endif
  265.  
  266. int 
  267. strip (name, nmlist, select, cuttrail)
  268. char *name;
  269. symstr_t * nmlist;
  270. select_fp select;
  271. int cuttrail;
  272. {
  273.     register int    fd;
  274.     register int    tfd;
  275.     register long   count, rbytes, sbytes;
  276.     long            lbytes, swap_lbytes;
  277.     struct aexec    ahead;
  278.  
  279.     if ((fd = open (name, O_RDONLY, 0666)) < 0) {
  280.     perror (name);
  281.     return 2;
  282.     }
  283.     if ((tfd = open (tmpname, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
  284.     perror (tmpname);
  285.     close (fd);
  286.     return 4;
  287.     }
  288. #ifndef WORD_ALIGNED
  289.     if ((count = lread (fd, &ahead, (long) sizeof (ahead))) 
  290.                     != (long) sizeof (ahead)) {
  291. #else
  292.     if (read_head (fd, &ahead)) {
  293. #endif
  294.     perror (name);
  295.     close (tfd);
  296.     close (fd);
  297.     return 8;
  298.     }
  299.     if (swap_short(ahead.a_magic)!=CMAGIC) {
  300.     report (name);
  301.     report (": Bad Magic number\n");
  302.     close (tfd);
  303.     close (fd);
  304.     return 0x10;
  305.     }
  306.     sbytes = swap_long(ahead.a_syms);
  307.     if (0L == sbytes && !cuttrail) {
  308.     report (name);
  309.     report (": Already Stripped\n");
  310.     close (tfd);
  311.     close (fd);
  312.     return 0x20;
  313.     }
  314.     if (lseek (fd, 0L, 0) < 0) {
  315.     report (name);
  316.     report (": seek error\n");
  317.     close (tfd);
  318.     close (fd);
  319.     return 0x40;
  320.     }
  321.     count = SIZEOF_AEXEC + swap_long(ahead.a_text) + swap_long(ahead.a_data);
  322.     if (copy (fd, tfd, count) != count) {
  323.     close (tfd);
  324.     close (fd);
  325.     return 0x80;
  326.     }
  327.     if (NULL == select) {     /* remove whole symbol table */
  328.     lbytes = 0L;
  329.     if (lseek (fd, sbytes, 1) < 0) {
  330.         report (name);
  331.         report (": seek error\n");
  332.         close (tfd);
  333.         close (fd);
  334.         return 0x100;
  335.     }
  336.     }
  337.     else {
  338.     lbytes = ( *select )(fd, tfd, sbytes, nmlist);
  339.     }
  340.     if( cuttrail ) {
  341.     if((rbytes = copy_relo(name,fd,tfd))<0) {
  342.          close(tfd);
  343.          close(fd);
  344.          return 0x8000;
  345.     }
  346.  
  347.     if( lread( fd, &cuttrail, 1 )!=1 ) {
  348.         report (name);
  349.         report (": Already Stripped\n");
  350.         close (tfd);
  351.         close (fd);
  352.         return 0x20;
  353.     }
  354.     } else {
  355.     if ((rbytes = copy (fd, tfd, 0x7fffffffL)) < 0) {
  356.         close (tfd);
  357.         close (fd);
  358.         return 0x200;
  359.     }
  360.     }
  361.     if (lseek (tfd, (long)(SYM_OFFSET), 0) < 0) {
  362.     close (tfd);
  363.     close (fd);
  364.     return 0x400;
  365.     }
  366.     swap_lbytes=swap_long(lbytes);
  367.     if (lwrite (tfd, &swap_lbytes, (long)sizeof (lbytes)) != 
  368.                             (long) sizeof (lbytes)) {
  369.     close (tfd);
  370.     close (fd);
  371.     return 0x800;
  372.     }
  373.     close (tfd);
  374.     close (fd);
  375.     if (rename(tmpname, name) == 0) return 0; /* try to rename it */
  376.     if ((fd = open (name, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
  377.     perror (name);
  378.     return 0x1000;
  379.     }
  380.     if ((tfd = open (tmpname, O_RDONLY, 0666)) < 0) {
  381.     perror (tmpname);
  382.     close (fd);
  383.     return 0x2000;
  384.     }
  385.  
  386.     count = SIZEOF_AEXEC + swap_long(ahead.a_text) + swap_long(ahead.a_data) + rbytes + lbytes;
  387.     if (copy (tfd, fd, count) != count) {
  388.     close (tfd);
  389.     close (fd);
  390.     return 0x4000;
  391.     }
  392.     close (tfd);
  393.     close (fd);
  394.     return 0;
  395. }
  396.  
  397. /*
  398.  * copy from, to in NEWBUFSIZ chunks upto bytes or EOF whichever occurs first
  399.  * returns # of bytes copied
  400.  */
  401. long 
  402. copy (from, to, bytes)
  403. int from, to;
  404. long bytes;
  405. {
  406.     register long   todo, done = 0L, remaining = bytes, actual;
  407.  
  408.     while (done != bytes) {
  409.     todo = (remaining > NEWBUFSIZ) ? NEWBUFSIZ : remaining;
  410.     if ((actual = lread (from, mybuf, todo)) != todo) {
  411.         if (actual < 0) {
  412.         report ("Error Reading\n");
  413.         return -done;
  414.         }
  415.     }
  416.     if (lwrite (to, mybuf, actual) != actual) {
  417.         report ("Error Writing\n");
  418.         return -done;
  419.     }
  420.     done += actual;
  421.     if (actual != todo)    /* eof reached */
  422.         return done;
  423.     remaining -= actual;
  424.     }
  425.     return done;
  426. }
  427.  
  428. /* copy TOS relocation table from `from` to `to`. Copy bytes until NUL byte or
  429.    first 4 bytes if == 0l.
  430.    returns length of relocation table or -1 in case of an error */
  431.  
  432. long 
  433. copy_relo(name,from,to)
  434. char *name;
  435. int from,to;
  436. {
  437.   long res=0;
  438.   long bytes;
  439.   char *end;
  440.   int finished=0;
  441.  
  442.   res=lread( from, mybuf, sizeof(long) );
  443.   if( res!=0 && res!=sizeof(long) ) {
  444.     report( "Error reading\n" );
  445.     return -1;
  446.   }
  447.  
  448.   if( res==0 ) {
  449.     report("Warning: ");  /* I think empty relocation tables are allowed,
  450.     report(name);            but could cause trouble with certain programs */
  451.     report( ": No relocation table\n" );
  452.     return 0; 
  453.   }
  454.   if( lwrite(to,mybuf,res)!=res ) {
  455.     report(name);
  456.     report( ": Error writing\n" );
  457.     return -1;
  458.   }
  459.  
  460.   res=sizeof(long);
  461.   if( *(long*)mybuf == 0 ) return res; /* This is a clean version of an empty
  462.                         relocation table                   */
  463.   while(!finished) {
  464.     if( (bytes=lread(from,mybuf,NEWBUFSIZ))<0 ) {
  465.       report(name);
  466.       report( ": Error reading\n" );
  467.       return -1;
  468.     }
  469.     if( bytes==0 ) {
  470.       report( "Warning: " );
  471.       report(name);
  472.       report( ": Unterminated relocation table\n" );
  473.       return res;
  474.     }
  475. /* dont know if sozobon has memchr */
  476.     end=memchr(mybuf,0,bytes);
  477.     if(end) {
  478.       bytes=end-mybuf+1;
  479.       finished=1;
  480.     }
  481.     if( lwrite(to,mybuf,bytes)!=bytes ) {
  482.       report(name);
  483.       report(": Error writing\n");
  484.       return -1;
  485.     }
  486.   }
  487. }
  488.  
  489. void 
  490. report (s)
  491. char * s;
  492. {
  493.     lwrite (2, s, (long) strlen (s));
  494. }
  495.  
  496. /*
  497.  * Given a name of a file with reserved symbols create an array of
  498.  * reserved symbol names.  To terminate create an entry which starts
  499.  * with a null character.
  500.  */
  501.  
  502. #define LBUFSIZE 128
  503. #define NMSTEP 10
  504.  
  505. symstr_t       *
  506. mklist (fname)
  507. char * fname;
  508. {
  509.     FILE           *fp;
  510.     symstr_t       *list = (symstr_t *) NULL;
  511.     int             left = 0;
  512.     int             pos = 0;
  513.     int             i;
  514.     size_t          max_size = 1;
  515.     char            lbuf[LBUFSIZE];
  516.     char           *in, *out;
  517.  
  518. #ifdef atarist
  519.     if (NULL == (fp = fopen (fname, "rt"))) {
  520. #else
  521.     if (NULL == (fp = fopen (fname, "r"))) {
  522. #endif
  523.     report (fname);
  524.     report (" -- ");
  525.     usage ("cannot open this file\n");
  526.     }
  527.  
  528.     while (NULL != fgets (lbuf, LBUFSIZE, fp)) {
  529.     if (0 == left) {
  530.         max_size += NMSTEP;
  531.         if ((symstr_t *) NULL == list) {
  532.         list = (symstr_t *) malloc ( max_size * sizeof (symstr_t));
  533.         }
  534.         else {
  535.         list = (symstr_t *) realloc ((void *) list,
  536.                          max_size * sizeof (symstr_t));
  537.  
  538.         }
  539.         if ((symstr_t *) NULL == list) {
  540.         report ("out of memory making symbol list\n");
  541.         exit (-3);
  542.         }
  543.         left = NMSTEP;
  544.     }
  545.     /* strip all leading white space */
  546.     in = lbuf;
  547.     while (' ' == *in || '\t' == *in)
  548.         in++;
  549.     if ('\n' == *in)
  550.         continue;        /* empty line - skip it */
  551.     out = &list[pos][0];
  552.     for (i = GST_SYMLEN; i > 0; --i) {
  553.         if ('\n' == *in || ' ' == *in || '\t' == *in) {
  554.         while (i-- > 0) *out++ = '\0';
  555.         break;
  556.         }
  557.         *out++ = *in++;
  558.     }
  559.     pos++;
  560.     --left;
  561.     }                /* while */
  562.     if ((symstr_t *) NULL != list) {
  563.     list[pos][0] = '\0';    /* terminate created list */
  564.     }
  565.     return (list);
  566. }
  567.  
  568. /*
  569.  * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
  570.  * of a symbol table selecting only those symbols which have A_GLOBL
  571.  * flag set. Table nmlist is not really used, but is here for a uniform
  572.  * interface.  Returns a number of bytes copied.
  573.  */
  574. long
  575. sel_globs (fd, tfd, sbytes, nmlist)
  576. int fd, tfd;
  577. long sbytes;
  578. symstr_t * nmlist;
  579. {
  580.     long            lbytes = 0;
  581.     struct asym     cur_sym;
  582.     int            cont = 0;
  583.  
  584.     while (sbytes) {
  585.     if ((long)SIZEOF_ASYM != lread (fd, &cur_sym, 
  586.                         (long)SIZEOF_ASYM)) {
  587.         report ("error on reading symbol table\n");
  588.         break;
  589.     }
  590.     if (0 == cont) { /* if we are not dealing with the second part */
  591.         cont = (0 != (swap_short(cur_sym.a_type) & A_LNAM));
  592.         if (swap_short(cur_sym.a_type) & A_GLOBL) {
  593.         cont = -cont;
  594.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  595.                             (long)SIZEOF_ASYM)) {
  596.             report ("error on writing symbol table\n");
  597.             break;
  598.         }
  599.         lbytes += SIZEOF_ASYM;
  600.         }
  601.     }
  602.     else { /* this was an extended symbol */
  603.         if (cont < 0) {  /* if global then write */
  604.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  605.                             (long)SIZEOF_ASYM)) {
  606.             report ("error on writing symbol table\n");
  607.             break;
  608.         }
  609.         lbytes += SIZEOF_ASYM;
  610.         }
  611.         cont = 0;
  612.     }
  613.     sbytes -= SIZEOF_ASYM;
  614.     }
  615.     return (lbytes);
  616. }
  617.  
  618. /*
  619.  * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
  620.  * of a symbol table selecting only those symbols which are on nmlist.
  621.  * Free nmlist if different from a default global one.
  622.  * Returns a number of bytes copied.
  623.  */
  624. long
  625. sel_listed (fd, tfd, sbytes, nmlist)
  626. int fd, tfd;
  627. long sbytes;
  628. symstr_t * nmlist;
  629. {
  630.     long            lbytes = 0;
  631.     symstr_t       *kname;
  632.     struct asym     cur_sym, spare;
  633.  
  634.     if ((symstr_t *) NULL == nmlist)
  635.     return (0L);
  636.  
  637.     while (sbytes) {
  638.     if ((long)SIZEOF_ASYM != lread (fd, &cur_sym,
  639.                         (long) SIZEOF_ASYM)) {
  640.         report ("error on reading symbol table\n");
  641.         break;
  642.     }
  643.     for (kname = nmlist; '\0' != **kname; kname++) {
  644.         if (0 == strncmp (&(*kname)[0], &cur_sym.a_name[0], SYMLEN)) {
  645.         if ((A_LNAM & swap_short(cur_sym.a_type)) == A_LNAM) { /* if extended */
  646.             if ((long)SIZEOF_ASYM != lread (fd, &spare,
  647.                         (long)SIZEOF_ASYM)) {
  648.             report ("error on reading symbol table\n");
  649.             goto leave;  /* skip two loop levels */
  650.             }
  651.             sbytes -= SIZEOF_ASYM;
  652.             if (strncmp (&(*kname)[SYMLEN], (char *)&spare,
  653.                  GST_SYMLEN-SYMLEN))
  654.               continue;
  655.         }
  656.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  657.                         (long)SIZEOF_ASYM)) {
  658.             report ("error on writing symbol table\n");
  659.             goto leave;
  660.         }
  661.         if ((swap_short(cur_sym.a_type) & A_LNAM) == A_LNAM)
  662.           {
  663.             if (lwrite (tfd, &spare, (long)SIZEOF_ASYM) != SIZEOF_ASYM)
  664.               {
  665.             report ("error on writing symbol table\n");
  666.             goto leave;
  667.               }
  668.             lbytes += SIZEOF_ASYM;
  669.           }
  670.         lbytes += SIZEOF_ASYM;
  671.         break;
  672.         }
  673.     }  /* for */
  674.     sbytes -= SIZEOF_ASYM;
  675.     }  /* while */
  676. leave:
  677.     if (nmlist != stklist) {
  678.     free (nmlist);
  679.     nmlist = (symstr_t *) NULL;
  680.     }
  681.     return (lbytes);
  682. }
  683.  
  684. #ifdef WORD_ALIGNED
  685. /*
  686.  * read header -- return !0 on err
  687.  */
  688. #define ck_read(fd, addr, siz) \
  689.   if((long)siz != lread(fd, addr, (long)siz)) return !0;
  690.  
  691. int read_head (fd, a)
  692. int fd;
  693. struct aexec *a;
  694. {
  695.     ck_read(fd, &a->a_magic,   sizeof(a->a_magic));
  696.     ck_read(fd, &a->a_text,    sizeof(a->a_text));
  697.     ck_read(fd, &a->a_data,    sizeof(a->a_data));
  698.     ck_read(fd, &a->a_bss,     sizeof(a->a_bss));
  699.     ck_read(fd, &a->a_syms,    sizeof(a->a_syms));
  700.     ck_read(fd, &a->a_AZero1,  sizeof(a->a_AZero1));
  701.     ck_read(fd, &a->a_AZero2,  sizeof(a->a_AZero2));
  702.     ck_read(fd, &a->a_isreloc, sizeof(a->a_isreloc));
  703.  
  704.     return 0;
  705. }
  706. #endif
  707.  
  708.  
  709. #ifdef CROSSHPUX
  710. char *xmalloc(n)
  711. unsigned n;
  712. {
  713.     extern char *malloc();
  714.     char *ret = malloc(n);
  715.     
  716.     if(!ret)
  717.     {
  718.         fprintf(stderr,"Out of memory!\n");
  719.         exit(1);
  720.     }
  721.     return ret;
  722. }
  723. #endif
  724.  
  725. #ifdef BYTE_SWAP
  726.  
  727. /* these routines work for big endian machines as well, but are not needed */
  728.  
  729. long swap_long(l)
  730. long l;
  731. {
  732.   long l1=l;
  733.   unsigned char *p=(unsigned char *)&l1;
  734.  
  735.   return (long)p[3]|((long)p[2]<<8)|((long)p[1]<<16)|((long)p[0]<<24);
  736. }
  737.  
  738. short swap_short(s)
  739. short s;
  740. {
  741.   short s1=s;
  742.   unsigned char *p=(unsigned char *)&s1;
  743.  
  744.   return (short)p[1]|((short)p[0]<<8);
  745. }
  746.  
  747. #endif
  748.